Changeset - 6eaac492b941
[Not reviewed]
0 6 0
Branko Majic (branko) - 6 years ago 2018-05-04 22:33:00
branko@majic.rs
GC-23: Removed option to update DNS names from server command:

- Removed functional test.
- Dropped the option from CLI.
- Dropped the option from command function implementation.
- Updating code for new command function signature.
- Updated existing unit tests.
- Removed unneeded unit tests.
6 files changed with 50 insertions and 321 deletions:
0 comments (0 inline, 0 general)
functional_tests/test_server.py
Show inline comments
 
@@ -202,74 +202,3 @@ def test_server_command_does_not_overwrite_existing_artifacts(tmpdir):
 
    # unchanged.
 
    assert tmpdir.join(".gimmecert", "server", "myserver.key.pem").read() == private_key
 
    assert tmpdir.join(".gimmecert", "server", "myserver.cert.pem").read() == certificate
 

	
 

	
 
def test_server_command_update_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 single 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
 

	
 
    # Not sure what to do, he takes a quick look at help for the
 
    # server command.
 
    stdout, stderr, exit_code = run_command("gimmecert", "server", "-h")
 

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

	
 
    # Based on help description, this seems to be exactly what he
 
    # needs. Private key is still fine, but his certificate needs to
 
    # be reissued. He goes ahead and runs the command for updating the
 
    # DNS subject alternative names.
 
    stdout, stderr, exit_code = run_command("gimmecert", "server", "--update-dns-names", "myserver1", "myservice.example.com")
 

	
 
    # 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 "renewed with new DNS subject alternative names" in stdout
 
    assert "key has remained unchanged" 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
 

	
 
    # John now needs another server certificate. Being a bit lazy, he
 
    # goes up in his shell history, changes the server name, and
 
    # reruns the command.
 
    stdout, stderr, exit_code = run_command("gimmecert", "server", "--update-dns-names", "myserver2", "myservice.example.com")
 

	
 
    # Just as he presses enter, he realizes that he has run the
 
    # command with --update-dns-names option, even though he has not
 
    # issued this particular server certificate before. Despite this,
 
    # no errors are reported, and he gets the familiar message about
 
    # server certificate being issued. Cool!
 
    assert stderr == ""
 
    assert exit_code == 0
 
    assert "Server certificate issued." in stdout
 
    assert ".gimmecert/server/myserver2.key.pem" in stdout
 
    assert ".gimmecert/server/myserver2.cert.pem" in stdout
gimmecert/cli.py
Show inline comments
 
@@ -111,16 +111,13 @@ def setup_server_subcommand_parser(parser, subparsers):
 
    subparser = subparsers.add_parser('server', description='Issues server certificate.')
 
    subparser.add_argument('entity_name', help='Name of the server entity.')
 
    subparser.add_argument('dns_name', nargs='*', help='Additional DNS names to include in subject alternative name.')
 
    subparser.add_argument('--update-dns-names', '-u', action='store_true', help='''Renew certificate for an existing server entity by reusing \
 
    the private key, but replacing the DNS subject alternative names with listed values (if any). \
 
    If entity does not exist, this option has no effect, and a new private key/certificate will be generated as usual.''')
 
    subparser.add_argument('--csr', '-c', type=str, default=None, help='''Do not generate server private key locally, and use the passed-in \
 
    certificate signing request (CSR) instead. Use dash (-) to read from standard input. Only the public key is taken from the CSR.''')
 

	
 
    def server_wrapper(args):
 
        project_directory = os.getcwd()
 

	
 
        return server(sys.stdout, sys.stderr, project_directory, args.entity_name, args.dns_name, args.update_dns_names, args.csr)
 
        return server(sys.stdout, sys.stderr, project_directory, args.entity_name, args.dns_name, args.csr)
 

	
 
    subparser.set_defaults(func=server_wrapper)
 

	
gimmecert/commands.py
Show inline comments
 
@@ -106,7 +106,7 @@ def init(stdout, stderr, project_directory, ca_base_name, ca_hierarchy_depth):
 
    return ExitCode.SUCCESS
 

	
 

	
 
def server(stdout, stderr, project_directory, entity_name, extra_dns_names, update_dns_names, custom_csr_path):
 
def server(stdout, stderr, project_directory, entity_name, extra_dns_names, custom_csr_path):
 
    """
 
    Issues a server certificate using the CA hierarchy initialised
 
    within the specified directory.
 
@@ -133,9 +133,6 @@ def server(stdout, stderr, project_directory, entity_name, extra_dns_names, upda
 
    :param extra_dns_names: List of additional DNS names to include in the subject alternative name.
 
    :type extra_dns_names: list[str]
 

	
 
    :param update_dns_names: Whether the certificate should be renewed using the existing private key, but with new DNS subject alternative names.
 
    :type update: bool
 

	
 
    :param custom_csr_path: Path to custom certificate signing request to use for issuing client certificate. Set to None or "" to generate private key.
 
    :type custom_csr_path: str or None
 

	
 
@@ -153,41 +150,22 @@ def server(stdout, stderr, project_directory, entity_name, extra_dns_names, upda
 
        print("CA hierarchy must be initialised prior to issuing server certificates. Run the gimmecert init command first.", file=stderr)
 
        return ExitCode.ERROR_NOT_INITIALISED
 

	
 
    # Ensure artefacts do not exist already, unless update of DNS
 
    # names has been requested and custom CSR path has not been
 
    # passed-in.
 
    if (not update_dns_names or custom_csr_path) and (
 
            os.path.exists(private_key_path) or
 
            os.path.exists(certificate_path) or
 
            os.path.exists(csr_path)
 
    ):
 
    # Ensure artefacts do not exist already.
 
    if os.path.exists(private_key_path) or os.path.exists(certificate_path) or os.path.exists(csr_path):
 
        print("Refusing to overwrite existing data. Certificate has already been issued for server %s." % entity_name, file=stderr)
 
        return ExitCode.ERROR_CERTIFICATE_ALREADY_ISSUED
 

	
 
    # Grab the private key or CSR, and extract public key.
 
    if update_dns_names and os.path.exists(private_key_path):
 
        renew_certificate = True
 
        private_key = gimmecert.storage.read_private_key(private_key_path)
 
        public_key = private_key.public_key()
 
        csr = None
 
    elif update_dns_names and os.path.exists(csr_path):
 
        renew_certificate = True
 
        csr = gimmecert.storage.read_csr(csr_path)
 
        public_key = csr.public_key()
 
        private_key = None
 
    elif custom_csr_path == "-":
 
        renew_certificate = False
 
    if custom_csr_path == "-":
 
        csr_pem = gimmecert.utils.read_input(sys.stdin, stderr, "Please enter the CSR")
 
        csr = gimmecert.utils.csr_from_pem(csr_pem)
 
        public_key = csr.public_key()
 
        private_key = None
 
    elif custom_csr_path:
 
        renew_certificate = False
 
        csr = gimmecert.storage.read_csr(custom_csr_path)
 
        public_key = csr.public_key()
 
        private_key = None
 
    else:
 
        renew_certificate = False
 
        private_key = gimmecert.crypto.generate_private_key()
 
        public_key = private_key.public_key()
 
        csr = None
 
@@ -208,15 +186,7 @@ def server(stdout, stderr, project_directory, entity_name, extra_dns_names, upda
 
    gimmecert.storage.write_certificate(certificate, certificate_path)
 

	
 
    # Show user information about generated artefacts.
 
    if renew_certificate:
 
        print("Server certificate renewed with new DNS subject alternative names.", file=stdout)
 

	
 
        if csr:
 
            print("Server CSR has remained unchanged.", file=stdout)
 
        else:
 
            print("Server private key has remained unchanged.", file=stdout)
 
    else:
 
        print("Server certificate issued.", file=stdout)
 
    print("Server certificate issued.", file=stdout)
 

	
 
    if csr:
 
        print("Server CSR: .gimmecert/server/%s.csr.pem" % entity_name, file=stdout)
tests/conftest.py
Show inline comments
 
@@ -147,11 +147,11 @@ def sample_project_directory(tmpdir):
 
    # Issue a bunch of certificates.
 
    for i in range(1, per_type_count + 1):
 
        entity_name = "server-with-privkey-%d" % i
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None, False, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None, None)
 

	
 
        entity_name = "server-with-csr-%d" % i
 
        custom_csr_path = custom_csr_dir.join("server-with-csr-%d.csr.pem" % i).strpath
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None, False, custom_csr_path)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None, custom_csr_path)
 

	
 
        entity_name = "client-with-privkey-%d" % i
 
        gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None)
tests/test_cli.py
Show inline comments
 
@@ -234,10 +234,6 @@ VALID_CLI_INVOCATIONS = [
 
                              "myserver1.example.com", "myserver2.example.com",
 
                              "myserver3.example.com", "myserver4.example.com"]),
 

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

	
 
    # server, CSR long and short option
 
    ("gimmecert.cli.server", ["gimmecert", "server", "--csr", "myserver.csr.pem", "myserver"]),
 
    ("gimmecert.cli.server", ["gimmecert", "server", "-c", "myserver.csr.pem", "myserver"]),
 
@@ -383,7 +379,7 @@ def test_server_command_invoked_with_correct_parameters_without_extra_dns_names(
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', [], False, None)
 
    mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', [], None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'server', 'myserver', 'service.local', 'service.example.com'])
 
@@ -397,7 +393,7 @@ def test_server_command_invoked_with_correct_parameters_with_extra_dns_names(moc
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', ['service.local', 'service.example.com'], False, None)
 
    mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', ['service.local', 'service.example.com'], None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'help'])
 
@@ -504,20 +500,6 @@ def test_client_command_invoked_with_correct_parameters(mock_client, tmpdir):
 
    mock_client.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myclient', None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'server', '--update-dns-names', 'myserver', 'service.local'])
 
@mock.patch('gimmecert.cli.server')
 
def test_server_command_invoked_with_correct_parameters_with_update_option(mock_server, tmpdir):
 
    # This should ensure we don't accidentally create artifacts
 
    # outside of test directory.
 
    tmpdir.chdir()
 

	
 
    mock_server.return_value = gimmecert.commands.ExitCode.SUCCESS
 

	
 
    gimmecert.cli.main()
 

	
 
    mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', ['service.local'], True, None)
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew'])
 
def test_renew_command_fails_without_arguments(tmpdir):
 
    # This should ensure we don't accidentally create artifacts
tests/test_commands.py
Show inline comments
 
@@ -133,7 +133,7 @@ def test_init_does_not_overwrite_artifcats_if_already_initialised(tmpdir):
 

	
 

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

	
 
    assert isinstance(status_code, int)
 

	
 
@@ -143,7 +143,7 @@ def test_server_reports_error_if_directory_is_not_initialised(tmpdir):
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

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

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -153,116 +153,31 @@ def test_server_reports_error_if_directory_is_not_initialised(tmpdir):
 
    assert status_code == gimmecert.commands.ExitCode.ERROR_NOT_INITIALISED
 

	
 

	
 
def test_server_reports_error_with_update_dns_and_csr_options_and_private_key_with_certificate_already_exists(sample_project_directory, key_with_csr):
 
    entity_name = "server-with-privkey-1"
 

	
 
    private_key_file = sample_project_directory.join(".gimmecert", "server", "%s.key.pem" % entity_name)
 
    csr_file = sample_project_directory.join(".gimmecert", "server", "%s.csr.pem" % entity_name)
 
    certificate_file = sample_project_directory.join(".gimmecert", "server", "%s.cert.pem" % entity_name)
 

	
 
    existing_private_key = private_key_file.read()
 
    existing_certificate = certificate_file.read()
 

	
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.server(stdout_stream, stderr_stream, sample_project_directory.strpath, entity_name, None, True, key_with_csr.csr_path)
 

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

	
 
    new_private_key = private_key_file.read()
 
    new_certificate = certificate_file.read()
 

	
 
    assert status_code == gimmecert.commands.ExitCode.ERROR_CERTIFICATE_ALREADY_ISSUED
 
    assert stdout == ""
 
    assert "already been issued" in stderr
 
    assert entity_name in stderr
 
    assert not csr_file.check()
 
    assert new_private_key == existing_private_key
 
    assert new_certificate == existing_certificate
 

	
 

	
 
def test_server_reports_error_with_update_dns_and_csr_options_and_csr_with_certificate_already_exists(sample_project_directory, key_with_csr):
 
    entity_name = "server-with-csr-1"
 

	
 
    private_key_file = sample_project_directory.join(".gimmecert", "server", "%s.key.pem" % entity_name)
 
    csr_file = sample_project_directory.join(".gimmecert", "server", "%s.csr.pem" % entity_name)
 
    certificate_file = sample_project_directory.join(".gimmecert", "server", "%s.cert.pem" % entity_name)
 

	
 
    existing_csr = csr_file.read()
 
    existing_certificate = certificate_file.read()
 

	
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    status_code = gimmecert.commands.server(stdout_stream, stderr_stream, sample_project_directory.strpath, entity_name, None, True, key_with_csr.csr_path)
 

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

	
 
    new_csr = csr_file.read()
 
    new_certificate = certificate_file.read()
 

	
 
    assert status_code == gimmecert.commands.ExitCode.ERROR_CERTIFICATE_ALREADY_ISSUED
 
    assert stdout == ""
 
    assert "already been issued" in stderr
 
    assert entity_name in stderr
 
    assert not private_key_file.check()
 
    assert new_csr == existing_csr
 
    assert new_certificate == existing_certificate
 

	
 

	
 
@pytest.mark.parametrize(
 
    "entity_name, update_dns_names, custom_csr_path, strings_expected_in_output, strings_not_expected_in_output",
 
    "entity_name, custom_csr_path, strings_expected_in_output, strings_not_expected_in_output",
 
    [
 
        # New server certificate, no DNS update, generate private key.
 
        ("myserver", False, None,
 
        # New server certificate, generate private key.
 
        ("myserver", None,
 
         [".gimmecert/server/myserver.key.pem", ".gimmecert/server/myserver.cert.pem"],
 
         [".gimmecert/server/myserver.csr.pem"]),
 

	
 
        # New server certificate, no DNS update, use custom CSR.
 
        ("myserver", False, "custom_csr/mycustom.csr.pem",
 
        # New server certificate, use custom CSR.
 
        ("myserver", "custom_csr/mycustom.csr.pem",
 
         [".gimmecert/server/myserver.cert.pem", ".gimmecert/server/myserver.csr.pem"],
 
         [".gimmecert/server/myserver.key.pem"]),
 

	
 
        # New server certificate, DNS update, generate private key (since no previous key exists).
 
        ("myserver", True, None,
 
         [".gimmecert/server/myserver.key.pem", ".gimmecert/server/myserver.cert.pem"],
 
         ["renewed with new DNS subject alternative names", "key has remained unchanged",
 
          ".gimmecert/server/myserver.csr.pem"]),
 

	
 
        # New server certificate, DNS update, reuse existing private key.
 
        ("server-with-privkey-1", True, None,
 
         ["renewed with new DNS subject alternative names", "key has remained unchanged",
 
          ".gimmecert/server/server-with-privkey-1.key.pem", ".gimmecert/server/server-with-privkey-1.cert.pem"],
 
         [".gimmecert/server/server-with-privkey-1.csr.pem"]),
 

	
 
        # New server certificate, DNS update, reuse existing CSR.
 
        ("server-with-csr-1", True, None,
 
         ["renewed with new DNS subject alternative names", "CSR has remained unchanged",
 
          ".gimmecert/server/server-with-csr-1.cert.pem", ".gimmecert/server/server-with-csr-1.csr.pem"],
 
         [".gimmecert/server/server-with-csr-1.key.pem"]),
 
    ]
 
)
 
def test_server_reports_success_and_outputs_correct_information(sample_project_directory, key_with_csr,
 
                                                                entity_name, update_dns_names, custom_csr_path,
 
                                                                entity_name, custom_csr_path,
 
                                                                strings_expected_in_output, strings_not_expected_in_output):
 
    """
 
    Tests if the server command reports success and outputs correct
 
    information for user.
 

	
 
    Tests is parametrised in order to avoid code
 
    duplication. Unfortunately, the parameters are fairly complex, but
 
    it still beats code duplication.
 

	
 
    Tests has been designed to cater to different permutations of the
 
    following conditions/parameters:
 
    Test is parametrised in order to avoid code duplication.
 

	
 
        - Existence of certificate under the same name (mainly for
 
          testing updates to DNS names).
 
        - Request to update DNS names.
 
        - Request to use a custom CSR for issuing the certificate.
 
    Tests have been designed to cater to different output depending on
 
    whether the CSR was passed-in or not.
 

	
 
    For each variation we have lines we expect in standard output, and
 
    lines which we expect _not_ to be in standard output. E.g. if
 
@@ -277,7 +192,7 @@ def test_server_reports_success_and_outputs_correct_information(sample_project_d
 

	
 
    status_code = gimmecert.commands.server(stdout_stream, stderr_stream,
 
                                            sample_project_directory.strpath, entity_name, None,
 
                                            update_dns_names, custom_csr_path)
 
                                            custom_csr_path)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -299,7 +214,7 @@ def test_server_outputs_private_key_to_file_without_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, None)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 

	
 
    assert private_key_file.check(file=1)
 
    assert not csr_file.check()
 
@@ -317,7 +232,7 @@ def test_server_outputs_certificate_to_file(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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 

	
 
    assert certificate_file.check(file=1)
 
    assert not csr_file.check()
 
@@ -336,12 +251,12 @@ def test_server_errors_out_if_certificate_already_issued(tmpdir):
 

	
 
    # Previous run.
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 
    existing_private_key = tmpdir.join('.gimmecert', 'server', 'myserver.key.pem').read()
 
    certificate = tmpdir.join('.gimmecert', 'server', 'myserver.cert.pem').read()
 

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

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -551,44 +466,6 @@ def test_client_errors_out_if_certificate_already_issued(tmpdir):
 
    assert tmpdir.join('.gimmecert', 'client', 'myclient.cert.pem').read() == certificate
 

	
 

	
 
def test_server_update_dns_does_not_generate_new_private_key(sample_project_directory):
 
    entity_name = "server-with-privkey-1"
 

	
 
    private_key_file = sample_project_directory.join('.gimmecert', 'server', '%s.key.pem' % entity_name)
 
    certificate_file = sample_project_directory.join('.gimmecert', 'server', '%s.cert.pem' % entity_name)
 

	
 
    old_private_key = private_key_file.read()
 
    old_certificate = certificate_file.read()
 

	
 
    status_code = gimmecert.commands.server(io.StringIO(), io.StringIO(), sample_project_directory.strpath, entity_name, None, True, None)
 

	
 
    new_private_key = private_key_file.read()
 
    new_certificate = certificate_file.read()
 

	
 
    assert status_code == gimmecert.commands.ExitCode.SUCCESS
 
    assert new_private_key == old_private_key
 
    assert new_certificate != old_certificate
 

	
 

	
 
def test_server_update_dns_does_not_generate_new_csr(sample_project_directory):
 
    entity_name = "server-with-csr-1"
 

	
 
    csr_file = sample_project_directory.join('.gimmecert', 'server', '%s.csr.pem' % entity_name)
 
    certificate_file = sample_project_directory.join('.gimmecert', 'server', '%s.cert.pem' % entity_name)
 

	
 
    old_csr = csr_file.read()
 
    old_certificate = certificate_file.read()
 

	
 
    status_code = gimmecert.commands.server(io.StringIO(), io.StringIO(), sample_project_directory.strpath, entity_name, None, True, None)
 

	
 
    new_csr = csr_file.read()
 
    new_certificate = certificate_file.read()
 

	
 
    assert status_code == gimmecert.commands.ExitCode.SUCCESS
 
    assert new_csr == old_csr
 
    assert new_certificate != old_certificate
 

	
 

	
 
def test_renew_returns_status_code(tmpdir):
 
    tmpdir.chdir()
 

	
 
@@ -655,7 +532,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts(tmpdir):
 
    stderr_stream = io.StringIO()
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 

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

	
 
@@ -698,7 +575,7 @@ def test_renew_keeps_server_private_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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 
    private_key_after_issuance = private_key_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, None)
 
@@ -728,7 +605,7 @@ def test_renew_replaces_server_certificate(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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 
    certificate_after_issuance = certificate_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', False, None, None)
 
@@ -763,7 +640,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_new_key(tmpdir
 
    stderr_stream = io.StringIO()
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 

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

	
 
@@ -783,7 +660,7 @@ def test_renew_generates_new_private_key_if_requested(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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 
    private_key_after_issuance = private_key_file.read()
 

	
 
    gimmecert.commands.renew(io.StringIO(), io.StringIO(), tmpdir.strpath, 'server', 'myserver', True, None, None)
 
@@ -872,13 +749,13 @@ def test_status_reports_server_certificate_information(tmpdir):
 
        gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 

	
 
    with freeze_time('2018-02-01 00:15:00'):
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, False, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, None)
 

	
 
    with freeze_time('2018-03-01 00:15:00'):
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', ['myservice1.example.com', 'myservice2.example.com'], False, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', ['myservice1.example.com', 'myservice2.example.com'], None)
 

	
 
    with freeze_time('2018-04-01 00:15:00'):
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver3', None, False, myserver3_csr_file.strpath)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver3', None, myserver3_csr_file.strpath)
 

	
 
    status_code = gimmecert.commands.status(stdout_stream, stderr_stream, tmpdir.strpath)
 

	
 
@@ -1021,8 +898,8 @@ def test_status_reports_no_client_certificates_were_issued(tmpdir):
 
    # Just create some sample data, but no client certificates.
 
    with freeze_time('2018-01-01 00:15:00'):
 
        gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, False, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', None, False, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', None, None)
 

	
 
    status_code = gimmecert.commands.status(stdout_stream, stderr_stream, tmpdir.strpath)
 

	
 
@@ -1062,7 +939,7 @@ def test_certificate_marked_as_not_valid_or_expired_as_appropriate(tmpdir, subje
 
    # Perform action on our fixed issuance date.
 
    with freeze_time(issuance_date):
 
        gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, "My Project", depth)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, False, None)
 
        gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 
        gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myclient', None)
 

	
 
    # Move to specific date in future/past for different validity checks.
 
@@ -1188,7 +1065,7 @@ def test_server_outputs_passed_in_csr_to_file_without_private_key(tmpdir):
 
    gimmecert.storage.write_csr(csr, custom_csr_file.strpath)
 
    custom_csr_file_content = custom_csr_file.read()
 

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

	
 
    assert csr_file.check(file=1)
 
    assert not private_key_file.check()
 
@@ -1210,7 +1087,7 @@ def test_server_uses_correct_public_key_but_no_naming_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, custom_csr_file.strpath)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, custom_csr_file.strpath)
 

	
 
    certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 

	
 
@@ -1221,32 +1098,6 @@ def test_server_uses_correct_public_key_but_no_naming_with_csr(tmpdir):
 
    assert csr.subject != certificate.subject
 

	
 

	
 
def test_server_reports_success_if_certificate_not_already_issued_but_update_was_requested_with_csr(tmpdir):
 
    depth = 1
 

	
 
    custom_csr_file = tmpdir.join('customcsr.pem')
 

	
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

	
 
    gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, depth)
 

	
 
    private_key = gimmecert.crypto.generate_private_key()
 
    csr = gimmecert.crypto.generate_csr('mycustomcsr', private_key)
 
    gimmecert.storage.write_csr(csr, custom_csr_file.strpath)
 

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

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

	
 
    assert status_code == gimmecert.commands.ExitCode.SUCCESS
 
    assert ".gimmecert/server/myserver.csr.pem" in stdout
 
    assert ".gimmecert/server/myserver.cert.pem" in stdout
 
    assert ".gimmecert/server/myserver.key.pem" not in stdout
 
    assert stderr == ""
 

	
 

	
 
def test_client_errors_out_if_certificate_already_issued_with_csr(tmpdir):
 
    depth = 1
 

	
 
@@ -1293,12 +1144,12 @@ def test_server_errors_out_if_certificate_already_issued_with_csr(tmpdir):
 

	
 
    # Previous run.
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, custom_csr_file.strpath)
 
    existing_csr = tmpdir.join('.gimmecert', 'server', 'myserver.csr.pem').read()
 
    certificate = tmpdir.join('.gimmecert', 'server', 'myserver.cert.pem').read()
 

	
 
    # New run.
 
    status_code = gimmecert.commands.server(stdout_stream, stderr_stream, tmpdir.strpath, 'myserver', None, False, custom_csr_file.strpath)
 
    status_code = gimmecert.commands.server(stdout_stream, stderr_stream, tmpdir.strpath, 'myserver', None, custom_csr_file.strpath)
 

	
 
    stdout = stdout_stream.getvalue()
 
    stderr = stderr_stream.getvalue()
 
@@ -1324,7 +1175,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_csr(tmpdir):
 
    gimmecert.storage.write_csr(csr, csr_file.strpath)
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, csr_file.strpath)
 

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

	
 
@@ -1380,7 +1231,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_csr_when_repla
 
    gimmecert.storage.write_csr(csr, csr_file.strpath)
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 

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

	
 
@@ -1411,7 +1262,7 @@ def test_renew_replaces_server_private_key_with_csr(tmpdir):
 
    custom_csr_file_content = custom_csr_file.read()
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None)
 

	
 
    assert private_key_file.check(file=1)
 

	
 
@@ -1471,7 +1322,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_private_key_wh
 
    gimmecert.storage.write_csr(custom_csr, custom_csr_file.strpath)
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, custom_csr_file.strpath)
 

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

	
 
@@ -1514,7 +1365,7 @@ 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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], None)
 

	
 
    old_certificate_pem = certificate_file.read()
 
    old_certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 
@@ -1540,7 +1391,7 @@ 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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], None)
 

	
 
    old_certificate_pem = certificate_file.read()
 
    old_certificate = gimmecert.storage.read_certificate(certificate_file.strpath)
 
@@ -1573,7 +1424,7 @@ def test_renew_replaces_server_csr_with_private_key(tmpdir):
 
    gimmecert.storage.write_csr(custom_csr, custom_csr_file.strpath)
 

	
 
    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)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, custom_csr_file.strpath)
 

	
 
    assert csr_file.check(file=1)
 

	
 
@@ -1602,7 +1453,7 @@ def test_server_reads_csr_from_stdin(mock_read_input, sample_project_directory,
 
    stdout_stream = io.StringIO()
 
    stderr_stream = io.StringIO()
 

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

	
 
    # Read stored/generated artefacts.
 
@@ -1655,7 +1506,7 @@ def test_renew_server_reads_csr_from_stdin(mock_read_input, sample_project_direc
 
    certificate_file = sample_project_directory.join('.gimmecert', 'server', '%s.cert.pem' % entity_name)
 

	
 
    # Generate server certificate that will be renewed.
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), sample_project_directory.strpath, entity_name, None, False, None)
 
    gimmecert.commands.server(io.StringIO(), io.StringIO(), sample_project_directory.strpath, entity_name, None, None)
 

	
 
    # Mock our util for reading input from user.
 
    mock_read_input.return_value = key_with_csr.csr_pem
0 comments (0 inline, 0 general)