From 70b0277c55dc0bee736eabe109e0501c4fd20679 2020-06-07 23:09:40 From: Branko Majic Date: 2020-06-07 23:09:40 Subject: [PATCH] GC-37: Added support for requesting custom RSA key size when issuing server certificates: - Added functional test. - Added unit tests. - Added new CLI option to the server command. - Updated the server command to use the passed-in key specification. - Updated existing tests to cope with changes to the server command function signature. --- diff --git a/functional_tests/test_server.py b/functional_tests/test_server.py index d3b7cb40a30cf180d6d5bc49e1907f00a4a2dbb1..4417d81b3e16adbf9274e0eb1d62eb7b976d2204 100644 --- a/functional_tests/test_server.py +++ b/functional_tests/test_server.py @@ -236,3 +236,39 @@ def test_server_command_key_specification(tmpdir): # Likewise with the private key, the certificate is also using the # 1024-bit RSA key. assert "Public-Key: (1024 bit)" in stdout + + # At some point John realises that to cover all bases, he needs to + # have a test with a server that uses 2048-bit RSA keys as + # well. He does not want to regenerate all of the X.509 artefacts, + # and would like to instead issues a single 2048-bit RSA key for a + # specific server instead. + + # He starts off by having a look at the help for the server command. + stdout, stderr, exit_code = run_command("gimmecert", "server", "-h") + + # John notices the option for passing-in a key specification. + assert " --key-specification" in stdout + assert " -k" in stdout + + # John goes ahead and tries to issue a server certificate using + # key specification option. + stdout, stderr, exit_code = run_command("gimmecert", "server", "--key-specification", "rsas:2048", "myserver2") + + # Unfortunately, the command fails due to John's typo. + assert exit_code != 0 + assert "invalid key_specification" in stderr + + # John tries again, fixing his typo. + stdout, stderr, exit_code = run_command("gimmecert", "server", "--key-specification", "rsa:2048", "myserver2") + + # This time around he succeeds. + assert exit_code == 0 + assert stderr == "" + + # He runs a command to see details about the generated private + # key. + stdout, _, _ = run_command('openssl', 'rsa', '-noout', '-text', '-in', '.gimmecert/server/myserver2.key.pem') + + # He nods with his head, observing that the generated private key + # uses the same key size as he has specified. + assert "Private-Key: (2048 bit)" in stdout diff --git a/gimmecert/cli.py b/gimmecert/cli.py index 483d11dced41929312891326902c2727044331ea..b31ca8c3d1c74efcdb9d5c3281f65a92065c9e0c 100644 --- a/gimmecert/cli.py +++ b/gimmecert/cli.py @@ -145,11 +145,14 @@ def setup_server_subcommand_parser(parser, subparsers): subparser.add_argument('dns_name', nargs='*', help='Additional DNS names to include in subject alternative name.') 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.''') + subparser.add_argument('--key-specification', '-k', type=key_specification, + help='''Specification/parameters to use for private key generation. \ + For RSA keys, use format rsa:BIT_LENGTH. Default is to use same algorithm/parameters as used by CA hierarchy.''', default=None) def server_wrapper(args): project_directory = os.getcwd() - return server(sys.stdout, sys.stderr, project_directory, args.entity_name, args.dns_name, args.csr) + return server(sys.stdout, sys.stderr, project_directory, args.entity_name, args.dns_name, args.csr, args.key_specification) subparser.set_defaults(func=server_wrapper) diff --git a/gimmecert/commands.py b/gimmecert/commands.py index 82c406cf50586e78fdaac025df710fc46d6800fe..18a58d706b49329e0a48c8a5f8bc58f418fa434c 100644 --- a/gimmecert/commands.py +++ b/gimmecert/commands.py @@ -111,7 +111,7 @@ def init(stdout, stderr, project_directory, ca_base_name, ca_hierarchy_depth, ke return ExitCode.SUCCESS -def server(stdout, stderr, project_directory, entity_name, extra_dns_names, custom_csr_path): +def server(stdout, stderr, project_directory, entity_name, extra_dns_names, custom_csr_path, key_specification): """ Issues a server certificate using the CA hierarchy initialised within the specified directory. @@ -139,8 +139,13 @@ def server(stdout, stderr, project_directory, entity_name, extra_dns_names, cust :type extra_dns_names: list[str] :param custom_csr_path: Path to custom certificate signing request to use for issuing client certificate. Set to None or "" to generate private key. + Do not use together with key_specification. :type custom_csr_path: str or None + :param key_specification: Key specification to use when generating private keys for the server. Ignored if custom_csr_path is specified. Set to None to + default to issuing CA hiearchy algorithm and parameters. + :type key_specification: tuple(str, int) or None + :returns: Status code, one from gimmecert.commands.ExitCode. :rtype: int """ @@ -175,7 +180,8 @@ def server(stdout, stderr, project_directory, entity_name, extra_dns_names, cust public_key = csr.public_key() private_key = None else: - key_specification = gimmecert.crypto.key_specification_from_public_key(issuer_private_key.public_key()) + if not key_specification: + key_specification = gimmecert.crypto.key_specification_from_public_key(issuer_private_key.public_key()) key_generator = gimmecert.crypto.KeyGenerator(key_specification[0], key_specification[1]) private_key = key_generator() public_key = private_key.public_key() diff --git a/tests/conftest.py b/tests/conftest.py index c8e8f8b431496906d129cf1093a847d37f5fe82d..61d9187d39b928642d4d149bf71b4d0c07550541 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -148,11 +148,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, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None, 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, custom_csr_path) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None, custom_csr_path, None) entity_name = "client-with-privkey-%d" % i gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, entity_name, None) diff --git a/tests/test_cli.py b/tests/test_cli.py index d97903205f9e8dd5e1c6b92c69b0bb148e54d127..3112aeef88c3e3f2c0ec3b21a6949fa5ba1bb70e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -242,6 +242,10 @@ VALID_CLI_INVOCATIONS = [ ("gimmecert.cli.server", ["gimmecert", "server", "--csr", "myserver.csr.pem", "myserver"]), ("gimmecert.cli.server", ["gimmecert", "server", "-c", "myserver.csr.pem", "myserver"]), + # server, key specification long and short option + ("gimmecert.cli.server", ["gimmecert", "server", "--key-specification", "rsa:4096", "myserver"]), + ("gimmecert.cli.server", ["gimmecert", "server", "-k", "rsa:1024", "myserver"]), + # client, no options ("gimmecert.cli.client", ["gimmecert", "client", "myclient"]), @@ -315,6 +319,11 @@ INVALID_CLI_INVOCATIONS = [ ("gimmecert.cli.init", ["gimmecert", "init", "-k", "rsa"]), ("gimmecert.cli.init", ["gimmecert", "init", "-k", "rsa:not_a_number"]), ("gimmecert.cli.init", ["gimmecert", "init", "-k", "unsupported:algorithm"]), + + # server, invalid key specification + ("gimmecert.cli.server", ["gimmecert", "server", "-k", "rsa", "myserver"]), + ("gimmecert.cli.server", ["gimmecert", "server", "-k", "rsa:not_a_number", "myserver"]), + ("gimmecert.cli.server", ["gimmecert", "server", "-k", "unsupported:algorithm", "myserver"]), ] @@ -429,12 +438,12 @@ 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', [], None) + mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', [], None, None) -@mock.patch('sys.argv', ['gimmecert', 'server', 'myserver', 'service.local', 'service.example.com']) +@mock.patch('sys.argv', ['gimmecert', 'server', '-k', 'rsa:1024', 'myserver', 'service.local', 'service.example.com']) @mock.patch('gimmecert.cli.server') -def test_server_command_invoked_with_correct_parameters_with_extra_dns_names(mock_server, tmpdir): +def test_server_command_invoked_with_correct_parameters_with_extra_dns_names_and_key_specification(mock_server, tmpdir): # This should ensure we don't accidentally create artifacts # outside of test directory. tmpdir.chdir() @@ -443,7 +452,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'], None) + mock_server.assert_called_once_with(sys.stdout, sys.stderr, tmpdir.strpath, 'myserver', ['service.local', 'service.example.com'], None, ("rsa", 1024)) @mock.patch('sys.argv', ['gimmecert', 'help']) diff --git a/tests/test_commands.py b/tests/test_commands.py index 11959686230cdb91c5d1073b82af7b6045ba13e4..7417bbc6f4c0b0436a62d32bef97874cbd90cdd1 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -119,7 +119,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, None) + status_code = gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None, None) assert isinstance(status_code, int) @@ -129,7 +129,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, None) + status_code = gimmecert.commands.server(stdout_stream, stderr_stream, tmpdir.strpath, 'myserver', None, None, None) stdout = stdout_stream.getvalue() stderr = stderr_stream.getvalue() @@ -178,7 +178,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, - custom_csr_path) + custom_csr_path, None) stdout = stdout_stream.getvalue() stderr = stderr_stream.getvalue() @@ -197,7 +197,7 @@ def test_server_outputs_private_key_to_file_without_csr(gctmpdir): private_key_file = gctmpdir.join('.gimmecert', 'server', 'myserver.key.pem') csr_file = gctmpdir.join('.gimmecert', 'server', 'myserver.csr.pem') - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) assert private_key_file.check(file=1) assert not csr_file.check() @@ -212,7 +212,7 @@ def test_server_outputs_certificate_to_file(gctmpdir): certificate_file = gctmpdir.join('.gimmecert', 'server', 'myserver.cert.pem') csr_file = gctmpdir.join('.gimmecert', 'client', 'myclient.csr.pem') - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) assert certificate_file.check(file=1) assert not csr_file.check() @@ -228,12 +228,12 @@ def test_server_errors_out_if_certificate_already_issued(gctmpdir): stderr_stream = io.StringIO() # Previous run. - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) existing_private_key = gctmpdir.join('.gimmecert', 'server', 'myserver.key.pem').read() certificate = gctmpdir.join('.gimmecert', 'server', 'myserver.cert.pem').read() # New run. - status_code = gimmecert.commands.server(stdout_stream, stderr_stream, gctmpdir.strpath, 'myserver', None, None) + status_code = gimmecert.commands.server(stdout_stream, stderr_stream, gctmpdir.strpath, 'myserver', None, None, None) stdout = stdout_stream.getvalue() stderr = stderr_stream.getvalue() @@ -487,7 +487,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts(gctmpdir): stdout_stream = io.StringIO() stderr_stream = io.StringIO() - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, gctmpdir.strpath, 'server', 'myserver', False, None, None) @@ -524,7 +524,7 @@ def test_renew_reports_success_and_paths_to_client_artifacts(gctmpdir): def test_renew_keeps_server_private_key(gctmpdir): private_key_file = gctmpdir.join('.gimmecert', 'server', 'myserver.key.pem') - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) private_key_after_issuance = private_key_file.read() gimmecert.commands.renew(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'server', 'myserver', False, None, None) @@ -548,7 +548,7 @@ def test_renew_keeps_client_private_key(gctmpdir): def test_renew_replaces_server_certificate(gctmpdir): certificate_file = gctmpdir.join('.gimmecert', 'server', 'myserver.cert.pem') - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) certificate_after_issuance = certificate_file.read() gimmecert.commands.renew(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'server', 'myserver', False, None, None) @@ -577,7 +577,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_new_key(gctmpd stdout_stream = io.StringIO() stderr_stream = io.StringIO() - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, gctmpdir.strpath, 'server', 'myserver', True, None, None) @@ -594,7 +594,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_new_key(gctmpd def test_renew_generates_new_private_key_if_requested(gctmpdir): private_key_file = gctmpdir.join('.gimmecert', 'server', 'myserver.key.pem') - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) private_key_after_issuance = private_key_file.read() gimmecert.commands.renew(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'server', 'myserver', True, None, None) @@ -680,13 +680,13 @@ def test_status_reports_server_certificate_information(tmpdir): gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, 3, ("rsa", 2048)) with freeze_time('2018-02-01 00:15:00'): - gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, 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'], None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', ['myservice1.example.com', 'myservice2.example.com'], None, None) with freeze_time('2018-04-01 00:15:00'): - gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver3', None, myserver3_csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver3', None, myserver3_csr_file.strpath, None) with freeze_time('2018-06-01 00:15:00'): status_code = gimmecert.commands.status(stdout_stream, stderr_stream, tmpdir.strpath) @@ -825,8 +825,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, 1, ("rsa", 2048)) - gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, None) - gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver1', None, None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver2', None, None, None) status_code = gimmecert.commands.status(stdout_stream, stderr_stream, tmpdir.strpath) @@ -864,7 +864,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", 1, ("rsa", 2048)) - gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None, None) gimmecert.commands.client(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myclient', None) # Move to specific date in future/past for different validity checks. @@ -971,7 +971,7 @@ def test_server_outputs_passed_in_csr_to_file_without_private_key(gctmpdir): gimmecert.storage.write_csr(csr, custom_csr_file.strpath) custom_csr_file_content = custom_csr_file.read() - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath, None) assert csr_file.check(file=1) assert not private_key_file.check() @@ -989,7 +989,7 @@ def test_server_uses_correct_public_key_but_no_naming_with_csr(gctmpdir): csr = gimmecert.crypto.generate_csr('mycustomcsr', private_key) gimmecert.storage.write_csr(csr, custom_csr_file.strpath) - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath, None) certificate = gimmecert.storage.read_certificate(certificate_file.strpath) @@ -1040,12 +1040,12 @@ def test_server_errors_out_if_certificate_already_issued_with_csr(gctmpdir): stderr_stream = io.StringIO() # Previous run. - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath, None) existing_csr = gctmpdir.join('.gimmecert', 'server', 'myserver.csr.pem').read() certificate = gctmpdir.join('.gimmecert', 'server', 'myserver.cert.pem').read() # New run. - status_code = gimmecert.commands.server(stdout_stream, stderr_stream, gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath) + status_code = gimmecert.commands.server(stdout_stream, stderr_stream, gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath, None) stdout = stdout_stream.getvalue() stderr = stderr_stream.getvalue() @@ -1068,7 +1068,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_csr(gctmpdir): csr = gimmecert.crypto.generate_csr("mytest", private_key) gimmecert.storage.write_csr(csr, csr_file.strpath) - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, csr_file.strpath, None) status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, gctmpdir.strpath, 'server', 'myserver', False, None, None) @@ -1118,7 +1118,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_csr_when_repla csr = gimmecert.crypto.generate_csr("mytest", private_key) gimmecert.storage.write_csr(csr, csr_file.strpath) - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, gctmpdir.strpath, 'server', 'myserver', False, csr_file.strpath, None) @@ -1146,7 +1146,7 @@ def test_renew_replaces_server_private_key_with_csr(gctmpdir): gimmecert.storage.write_csr(custom_csr, custom_csr_file.strpath) custom_csr_file_content = custom_csr_file.read() - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, None) assert private_key_file.check(file=1) @@ -1199,7 +1199,7 @@ def test_renew_reports_success_and_paths_to_server_artifacts_with_private_key_wh custom_csr = gimmecert.crypto.generate_csr("mytest", custom_private_key) gimmecert.storage.write_csr(custom_csr, custom_csr_file.strpath) - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath, None) status_code = gimmecert.commands.renew(stdout_stream, stderr_stream, gctmpdir.strpath, 'server', 'myserver', True, None, None) @@ -1241,7 +1241,7 @@ def test_renew_reports_success_and_paths_to_artifacts_when_renewing_server_certi def test_renew_replaces_dns_names(gctmpdir): certificate_file = gctmpdir.join(".gimmecert", "server", "myserver.cert.pem") - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], None, None) old_certificate_pem = certificate_file.read() old_certificate = gimmecert.storage.read_certificate(certificate_file.strpath) @@ -1266,7 +1266,7 @@ def test_renew_replaces_dns_names(gctmpdir): def test_renew_removes_dns_names(gctmpdir): certificate_file = gctmpdir.join(".gimmecert", "server", "myserver.cert.pem") - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', ['myservice1.local', 'myservice2.local'], None, None) old_certificate_pem = certificate_file.read() old_certificate = gimmecert.storage.read_certificate(certificate_file.strpath) @@ -1296,7 +1296,7 @@ def test_renew_replaces_server_csr_with_private_key(gctmpdir): custom_csr = gimmecert.crypto.generate_csr("mycustom", custom_csr_private_key) gimmecert.storage.write_csr(custom_csr, custom_csr_file.strpath) - gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath) + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, custom_csr_file.strpath, None) assert csr_file.check(file=1) @@ -1325,7 +1325,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, '-') + status_code = gimmecert.commands.server(stdout_stream, stderr_stream, sample_project_directory.strpath, entity_name, None, '-', None) assert status_code == 0 # Read stored/generated artefacts. @@ -1378,7 +1378,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, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), sample_project_directory.strpath, entity_name, None, None, None) # Mock our util for reading input from user. mock_read_input.return_value = key_with_csr.csr_pem @@ -1440,7 +1440,18 @@ def test_server_uses_same_private_key_algorithm_and_parameters_as_issuer_when_ge private_key_file = tmpdir.join('.gimmecert', 'server', 'myserver.key.pem') gimmecert.commands.init(io.StringIO(), io.StringIO(), tmpdir.strpath, tmpdir.basename, 1, ("rsa", 1024)) - gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None) + gimmecert.commands.server(io.StringIO(), io.StringIO(), tmpdir.strpath, 'myserver', None, None, None) + + private_key = gimmecert.storage.read_private_key(private_key_file.strpath) + + assert private_key.key_size == 1024 + + +def test_server_uses_passed_in_private_key_algorithm_and_parameters_when_generating_private_key(gctmpdir): + + private_key_file = gctmpdir.join('.gimmecert', 'server', 'myserver.key.pem') + + gimmecert.commands.server(io.StringIO(), io.StringIO(), gctmpdir.strpath, 'myserver', None, None, ("rsa", 1024)) private_key = gimmecert.storage.read_private_key(private_key_file.strpath)