Changeset - 035fb09894ef
[Not reviewed]
0 5 0
Branko Majic (branko) - 6 years ago 2018-05-03 23:53:26
branko@majic.rs
GC-23: Implemend option for updating DNS names for renew command:

- Added functional test covering the new functionality.
- Implemented ability to accept new DNS names in the renew command.
- Updated existing unit tests for new function signature.
- Added unit tests covering the new functionality.
5 files changed with 212 insertions and 32 deletions:
0 comments (0 inline, 0 general)
functional_tests/test_renew.py
Show inline comments
 
@@ -46,7 +46,7 @@ def test_renew_command_available_with_help():
 
    assert exit_code == 0
 
    assert stderr == ""
 
    assert stdout.startswith("usage: gimmecert renew")
 
    assert stdout.split('\n')[1].endswith("{server,client} entity_name")  # Second line of help (first is options)
 
    assert stdout.split('\n')[2].endswith("{server,client} entity_name")  # Third line of help (first two are options)
 

	
 

	
 
def test_renew_command_requires_initialised_hierarchy(tmpdir):
 
@@ -286,3 +286,57 @@ def test_renew_both_certificate_and_private_key(tmpdir):
 
    # He is happy to see that verification succeeds.
 
    assert verify_server_error_code == 0
 
    assert verify_client_error_code == 0
 

	
 

	
 
def test_renew_update_dns_option(tmpdir):
 
    # John is in a bit of a rush to get his project going. Since he
 
    # needs a server certificate issued, he goes ahead and quickly
 
    # initialises CA and issues a server certificate, with intention
 
    # of accessing the service via URL https://myservice.example.com/.
 
    tmpdir.chdir()
 
    run_command("gimmecert", "init")
 
    run_command("gimmecert", "server", "myserver1", "mysercive.example.com")
 

	
 
    # Once he imports the CA certificate into his browser, and tries
 
    # to access the service page, he very quickly finds out that he
 
    # has misspelled "myservice". Just to be on the safe side, he has
 
    # a look at the certificate using the OpenSSL CLI.
 
    stdout, stderr, exit_code = run_command('openssl', 'x509', '-noout', '-text', '-in', '.gimmecert/server/myserver1.cert.pem')
 

	
 
    # And indeed, in addition to his server name, he can see that the
 
    # extra DNS subject alternative name he provided is wrong.
 
    assert "DNS:myserver1," in stdout
 
    assert "DNS:mysercive.example.com\n" in stdout
 
    assert "DNS:myservice.example.com" not in stdout
 

	
 
    # Since he wants to just replace the certificate, while preserving
 
    # the private key, John figures he needs to renew his certificate
 
    # somehow, and update the DNS names while doing so. He takes a
 
    # quick look at help for the renew command.
 
    stdout, stderr, exit_code = run_command("gimmecert", "renew", "-h")
 

	
 
    # He notices there is an option for updating DNS subject
 
    # alternative names.
 
    assert " --update-dns-names DNS_NAMES" in stdout
 
    assert " -u DNS_NAMES\n" in stdout
 

	
 
    # Based on help description, this seems to be exactly what he
 
    # needs.He goes ahead and runs the renewal command, specifying
 
    # correct DNS subject alternative names.
 
    stdout, stderr, exit_code = run_command("gimmecert", "renew", "server", "--update-dns-names", "myservice.example.com", "myserver1")
 

	
 
    # He notices that no error has been reported by the command, and
 
    # that he is informed that the certificate has been renewed with
 
    # new DNS names, while the private key has been preserved.
 
    assert exit_code == 0
 
    assert "subject alternative names have been updated" in stdout
 

	
 
    # Being paranoid, he decides to double-check the certificate, just
 
    # to be on the safe side. He uses the OpenSSL CLI for this
 
    # purpose.
 
    stdout, stderr, exit_code = run_command('openssl', 'x509', '-noout', '-text', '-in', '.gimmecert/server/myserver1.cert.pem')
 

	
 
    # He notices that certificate includes the intended naming. He can
 
    # finally move ahead with his project.
 
    assert "DNS:myserver1," in stdout
 
    assert "DNS:myservice.example.com\n" in stdout
gimmecert/cli.py
Show inline comments
 
@@ -149,6 +149,11 @@ def setup_renew_subcommand_parser(parser, subparsers):
 
    subparser = subparsers.add_parser('renew', description='Renews existing certificates.')
 
    subparser.add_argument('entity_type', help='Type of entity to renew.', choices=['server', 'client'])
 
    subparser.add_argument('entity_name', help='Name of the entity')
 
    subparser.add_argument('--update-dns-names', '-u', dest="dns_names", default=None, type=str, help='''Replace the DNS subject alternative names \
 
    with new values. \
 
    Valid only for server certificate renewals. Multiple DNS names can be passed-in as comma-separated list. \
 
    Passing-in an empty string will result in all additional DNS subject alternative names being removed. \
 
    The entity name is kept as DNS subject alternative name in either case.''')
 

	
 
    new_private_key_or_csr_group = subparser.add_mutually_exclusive_group()
 

	
 
@@ -161,7 +166,7 @@ def setup_renew_subcommand_parser(parser, subparsers):
 
    def renew_wrapper(args):
 
        project_directory = os.getcwd()
 

	
 
        return renew(sys.stdout, sys.stderr, project_directory, args.entity_type, args.entity_name, args.new_private_key, args.csr)
 
        return renew(sys.stdout, sys.stderr, project_directory, args.entity_type, args.entity_name, args.new_private_key, args.csr, args.dns_names)
 

	
 
    subparser.set_defaults(func=renew_wrapper)
 

	
gimmecert/commands.py
Show inline comments
 
@@ -359,7 +359,7 @@ def client(stdout, stderr, project_directory, entity_name, custom_csr_path):
 
    return ExitCode.SUCCESS
 

	
 

	
 
def renew(stdout, stderr, project_directory, entity_type, entity_name, generate_new_private_key, custom_csr_path):
 
def renew(stdout, stderr, project_directory, entity_type, entity_name, generate_new_private_key, custom_csr_path, dns_names):
 
    """
 
    Renews existing certificate, while optionally generating a new
 
    private key in the process. Naming and extensions are preserved.
 
@@ -385,6 +385,10 @@ def renew(stdout, stderr, project_directory, entity_type, entity_name, generate_
 
    :param custom_csr_path: Path to custom CSR for issuing client certificate. Cannot be used together with generate_new_private_key.
 
    :type custom_csr_path: str or None
 

	
 
    :param dns_names: Comma-separated list of additional DNS names to use as replacement when renewing a server certificate. To remove additional DNS names,
 
        set the value to empty string (""). To keep the existing DNS names, set the value to None. Valid only for server certificates.
 
    :type dns_names: str or None
 

	
 
    :returns: Status code, one from gimmecert.commands.ExitCode.
 
    :rtype: int
 
    """
 
@@ -393,6 +397,9 @@ def renew(stdout, stderr, project_directory, entity_type, entity_name, generate_
 
    if generate_new_private_key and custom_csr_path:
 
        raise InvalidCommandInvocation("Only one of the following two parameters should be specified: generate_new_private_key, custom_csr_path.")
 

	
 
    if dns_names is not None and entity_type != "server":
 
        raise InvalidCommandInvocation("Updating DNS subject alternative names can be done only for server certificates.")
 

	
 
    # Set-up paths to possible artefacts.
 
    private_key_path = os.path.join(project_directory, '.gimmecert', entity_type, '%s.key.pem' % entity_name)
 
    csr_path = os.path.join(project_directory, '.gimmecert', entity_type, '%s.csr.pem' % entity_name)
 
@@ -437,7 +444,15 @@ def renew(stdout, stderr, project_directory, entity_type, entity_name, generate_
 
        public_key = old_certificate.public_key()
 

	
 
    # Issue and write out the new certificate.
 
    certificate = gimmecert.crypto.renew_certificate(old_certificate, public_key, issuer_private_key, issuer_certificate)
 
    if entity_type == 'server' and dns_names is not None:
 
        if dns_names == "":
 
            extra_dns_names = []
 
        else:
 
            extra_dns_names = dns_names.split(',')
 

	
 
        certificate = gimmecert.crypto.issue_server_certificate(entity_name, public_key, issuer_private_key, issuer_certificate, extra_dns_names)
 
    else:
 
        certificate = gimmecert.crypto.renew_certificate(old_certificate, public_key, issuer_private_key, issuer_certificate)
 
    gimmecert.storage.write_certificate(certificate, certificate_path)
 

	
 
    # Replace private key with CSR.
 
@@ -461,6 +476,9 @@ def renew(stdout, stderr, project_directory, entity_type, entity_name, generate_
 
    else:
 
        print("Renewed certificate for %s %s.\n" % (entity_type, entity_name), file=stdout)
 

	
 
    if dns_names is not None:
 
        print("DNS subject alternative names have been updated.", file=stdout)
 

	
 
    if private_key_replaced_with_csr:
 
        print("Private key used for issuance of previous certificate has been removed, and replaced with the passed-in CSR.", file=stdout)
 

	
tests/test_cli.py
Show inline comments
 
@@ -253,6 +253,12 @@ VALID_CLI_INVOCATIONS = [
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "server", "myserver"]),
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "client", "myclient"]),
 

	
 
    # renew, server, update dns names long and short option
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "--update-dns-names", "myservice.example.com", "server", "myserver"]),
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "--update-dns-names", "", "server", "myserver"]),
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "-u", "myservice.example.com", "server", "myserver"]),
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "-u", "", "server", "myserver"]),
 

	
 
    # renew, generate new private key long and short option
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "--new-private-key", "server", "myserver"]),
 
    ("gimmecert.cli.renew", ["gimmecert", "renew", "--new-private-key", "client", "myclient"]),
 
@@ -535,7 +541,7 @@ def test_renew_command_invoked_with_correct_parameters_for_server(mock_renew, tm
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'server', 'myserver', False, None)
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'server', 'myserver', False, None, None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', 'client', 'myclient'])
 
@@ -549,7 +555,7 @@ def test_renew_command_invoked_with_correct_parameters_for_client(mock_renew, tm
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'client', 'myclient', False, None)
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'client', 'myclient', False, None, None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', '--new-private-key', 'server', 'myserver'])
 
@@ -563,7 +569,7 @@ def test_renew_command_invoked_with_correct_parameters_for_server_with_new_priva
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'server', 'myserver', True, None)
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'server', 'myserver', True, None, None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', '--new-private-key', 'client', 'myclient'])
 
@@ -577,7 +583,7 @@ def test_renew_command_invoked_with_correct_parameters_for_client_with_new_priva
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'client', 'myclient', True, None)
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'client', 'myclient', True, None, None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', '--csr', 'mycustom.csr.pem', 'server', 'myserver'])
 
@@ -591,7 +597,7 @@ def test_renew_command_invoked_with_correct_parameters_for_server_with_csr_optio
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'server', 'myserver', False, 'mycustom.csr.pem')
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'server', 'myserver', False, 'mycustom.csr.pem', None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', '--csr', 'mycustom.csr.pem', 'client', 'myclient'])
 
@@ -605,7 +611,23 @@ def test_renew_command_invoked_with_correct_parameters_for_client_with_csr_optio
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'client', 'myclient', False, 'mycustom.csr.pem')
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'client', 'myclient', False, 'mycustom.csr.pem', None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', '--update-dns-names', 'myservice1.example.com,myservice2.example.com', 'server', 'myserver'])
 
@mock.patch('gimmecert.cli.renew')
 
def test_renew_command_invoked_with_correct_parameters_for_client_with_update_dns_option(mock_renew, tmpdir):
 
    # This should ensure we don't accidentally create artifacts
 
    # outside of test directory.
 
    tmpdir.chdir()
 

	
 
    mock_renew.return_value = gimmecert.commands.ExitCode.SUCCESS
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_renew.assert_called_once_with(sys.stdout, sys.stderr,
 
                                       tmpdir.strpath,
 
                                       'server', 'myserver', False, None, 'myservice1.example.com,myservice2.example.com')
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'status'])
tests/test_commands.py
Show inline comments
 
@@ -23,6 +23,8 @@ import io
 
import os
 
import sys
 

	
 
import cryptography.x509
 

	
 
import gimmecert.commands
 

	
 
import pytest
 
@@ -590,7 +592,7 @@ def test_server_update_dns_does_not_generate_new_csr(sample_project_directory):
 
def test_renew_returns_status_code(tmpdir):
 
    tmpdir.chdir()
 

	
 
    status_code = gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None)
 
    status_code = gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, None)
 

	
 
    assert isinstance(status_code, int)
 

	
 
@@ -600,7 +602,7 @@ def test_renew_reports_error_if_directory_is_not_initialised(tmpdir):
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -617,7 +619,7 @@ def test_renew_reports_error_if_no_existing_server_certificate_is_present(tmpdir
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -635,7 +637,7 @@ def test_renew_reports_error_if_no_existing_client_certificate_is_present(tmpdir
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'client', 'myclient', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'client', 'myclient', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -655,7 +657,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts(tmpdir):
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -677,7 +679,7 @@ def test_renew_reports_success_and_paths_to_client_artifacts(tmpdir):
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myclient', None)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'client', 'myclient', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'client', 'myclient', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -699,7 +701,7 @@ def test_renew_keeps_server_private_key(tmpdir):
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 
    private_key_after_issuance = private_key_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, None)
 
    private_key_after_renewal = private_key_file.read()
 

	
 
    assert private_key_after_issuance == private_key_after_renewal
 
@@ -714,7 +716,7 @@ def test_renew_keeps_client_private_key(tmpdir):
 
    gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myclient', None)
 
    private_key_after_issuance = private_key_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'client', 'myclient', False, None)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'client', 'myclient', False, None, None)
 
    private_key_after_renewal = private_key_file.read()
 

	
 
    assert private_key_after_issuance == private_key_after_renewal
 
@@ -729,7 +731,7 @@ def test_renew_replaces_server_certificate(tmpdir):
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 
    certificate_after_issuance = certificate_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, None)
 
    certificate_after_renewal = certificate_file.read()
 

	
 
    assert certificate_after_issuance != certificate_after_renewal
 
@@ -746,7 +748,7 @@ def test_renew_replaces_client_certificate(tmpdir):
 
    gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myclient', None)
 
    certificate_after_issuance = certificate_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'client', 'myclient', False, None)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'client', 'myclient', False, None, None)
 
    certificate_after_renewal = certificate_file.read()
 

	
 
    assert certificate_after_issuance != certificate_after_renewal
 
@@ -763,7 +765,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_new_key(tmpdir
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', True, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', True, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -784,7 +786,7 @@ def test_renew_generates_new_private_key_if_requested(tmpdir):
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 
    private_key_after_issuance = private_key_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, None)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, None, None)
 
    private_key_after_renewal = private_key_file.read()
 

	
 
    assert private_key_after_issuance != private_key_after_renewal
 
@@ -1324,7 +1326,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_csr(tmpdir):
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, csr_file.strpath)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -1352,7 +1354,7 @@ def test_renew_reports_success_and_paths_to_client_artifacts_with_csr(tmpdir):
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myclient', csr_file.strpath)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'client', 'myclient', False, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'client', 'myclient', False, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -1380,7 +1382,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_csr_when_repla
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, csr_file.strpath)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', False, csr_file.strpath, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -1413,7 +1415,7 @@ def test_renew_replaces_server_private_key_with_csr(tmpdir):
 

	
 
    assert private_key_file.check(file=1)
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, custom_csr_file.strpath)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, custom_csr_file.strpath, None)
 

	
 
    assert csr_file.check(file=1)
 

	
 
@@ -1441,12 +1443,21 @@ def test_renew_raises_exception_if_both_new_private_key_generation_and_csr_are_p
 
    gimmecert.storage.write_csr(custom_csr, custom_csr_file.strpath)
 

	
 
    with pytest.raises(gimmecert.commands.InvalidCommandInvocation) as e_info:
 
        gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, custom_csr_file.strpath)
 
        gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, custom_csr_file.strpath, None)
 

	
 
    print(e_info.value)
 
    assert str(e_info.value) == "Only one of the following two parameters should be specified: generate_new_private_key, custom_csr_path."
 

	
 

	
 
def test_renew_raises_exception_if_update_dns_names_is_used_for_client_certificate(sample_project_directory):
 

	
 
    with pytest.raises(gimmecert.commands.InvalidCommandInvocation) as e_info:
 
        gimmecert.commands.renew(io.StringIO(), io.StringIO(), sample_project_directory.strpath,
 
                                 'client', 'client-with-privkey-1',
 
                                 False, None, "myservice.example.com")
 

	
 
    assert str(e_info.value) == "Updating DNS subject alternative names can be done only for server certificates."
 

	
 

	
 
def test_renew_reports_success_and_paths_to_server_artifacts_with_private_key_when_replacing_csr(tmpdir):
 
    depth = 1
 

	
 
@@ -1462,7 +1473,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_private_key_wh
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, custom_csr_file.strpath)
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', True, None)
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, tmpdir.strpath, 'server', 'myserver', True, None, None)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -1477,6 +1488,76 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_private_key_wh
 
    assert stderr == ""
 

	
 

	
 
@pytest.mark.parametrize('entity_name,key_or_csr',
 
                         [('server-with-privkey-1', 'key'),
 
                          ('server-with-csr-1', 'csr')])
 
def test_renew_reports_success_and_paths_to_artifacts_when_renewing_server_certificate_with_dns_names(sample_project_directory, entity_name, key_or_csr):
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream,
 
                                           sample_project_directory.strpath,
 
                                           'server', entity_name,
 
                                           False, None, "myservice.example.com")
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 

	
 
    assert status_code == gimmecert.commands.ExitCode.SUCCESS
 
    assert "DNS subject alternative names have been updated." in stdout
 
    assert ".gimmecert/server/%s.%s.pem" % (entity_name, key_or_csr) in stdout
 
    assert ".gimmecert/server/%s.cert.pem" % entity_name in stdout
 
    assert stderr == ""
 

	
 

	
 
def test_renew_replaces_dns_names(tmpdir):
 
    certificate_file = tmpdir.join(".gimmecert", "server", "myserver.cert.pem")
 

	
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, 1)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], False, None)
 

	
 
    old_certificate_pem = certificate_file.read()
 
    old_certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 
    old_subject_alt_name = old_certificate.extensions.get_extension_for_class(cryptography.x509.SubjectAlternativeName).value
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, "myservice1.example.com,myservice2.example.com")
 

	
 
    new_certificate_pem = certificate_file.read()
 
    new_certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 
    new_subject_alt_name = new_certificate.extensions.get_extension_for_class(cryptography.x509.SubjectAlternativeName).value
 

	
 
    expected_subject_alt_name = cryptography.x509.SubjectAlternativeName([
 
        cryptography.x509.DNSName(dns_name) for dns_name in ['myserver', 'myservice1.example.com', 'myservice2.example.com']])
 

	
 
    assert new_certificate_pem != old_certificate_pem
 
    assert old_subject_alt_name != new_subject_alt_name
 
    assert new_subject_alt_name == expected_subject_alt_name
 

	
 

	
 
def test_renew_removes_dns_names(tmpdir):
 
    certificate_file = tmpdir.join(".gimmecert", "server", "myserver.cert.pem")
 

	
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, 1)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], False, None)
 

	
 
    old_certificate_pem = certificate_file.read()
 
    old_certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 
    old_subject_alt_name = old_certificate.extensions.get_extension_for_class(cryptography.x509.SubjectAlternativeName).value
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, "")
 

	
 
    new_certificate_pem = certificate_file.read()
 
    new_certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 
    new_subject_alt_name = new_certificate.extensions.get_extension_for_class(cryptography.x509.SubjectAlternativeName).value
 

	
 
    expected_subject_alt_name = cryptography.x509.SubjectAlternativeName([
 
        cryptography.x509.DNSName(dns_name) for dns_name in ['myserver']])
 

	
 
    assert new_certificate_pem != old_certificate_pem
 
    assert old_subject_alt_name != new_subject_alt_name
 
    assert new_subject_alt_name == expected_subject_alt_name
 

	
 

	
 
def test_renew_replaces_server_csr_with_private_key(tmpdir):
 
    depth = 1
 

	
 
@@ -1494,7 +1575,7 @@ def test_renew_replaces_server_csr_with_private_key(tmpdir):
 

	
 
    assert csr_file.check(file=1)
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, None)
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, None, None)
 

	
 
    assert private_key_file.check(file=1)
 

	
 
@@ -1580,7 +1661,7 @@ def test_renew_server_reads_csr_from_stdin(mock_read_input, sample_project_direc
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, sample_project_directory.strpath, "server", entity_name, False, '-')
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, sample_project_directory.strpath, "server", entity_name, False, '-', None)
 
    assert status_code == 0
 

	
 
    # Read stored/generated artefacts.
 
@@ -1612,7 +1693,7 @@ def test_renew_client_reads_csr_from_stdin(mock_read_input, sample_project_direc
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, sample_project_directory.strpath, "client", entity_name, False, '-')
 
    status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, sample_project_directory.strpath, "client", entity_name, False, '-', None)
 
    assert status_code == 0
 

	
 
    # Read stored/generated artefacts.
0 comments (0 inline, 0 general)