Changeset - dcac57e9457b
[Not reviewed]
0 5 0
Branko Majic (branko) - 6 years ago 2018-03-22 21:00:29
branko@majic.rs
GC-18: Error-out in case renew is called on uninitialised hierarchy:

- Added functional test for scenario.
- Implemented dummy renew command that for now just verifies the
hierarchy has been initialised.
- Implemented unit tests.
5 files changed with 113 insertions and 3 deletions:
0 comments (0 inline, 0 general)
functional_tests/test_renew.py
Show inline comments
 
@@ -47,3 +47,28 @@ def test_renew_command_available_with_help():
 
    assert stderr == ""
 
    assert stdout.startswith("usage: gimmecert renew")
 
    assert stdout.split('\n')[0].endswith("{server,client} entity_name")  # First line of help
 

	
 

	
 
def test_renew_command_requires_initialised_hierarchy(tmpdir):
 
    # John decides it's time to renew one of the certificates. He
 
    # switches to his project directory.
 
    tmpdir.chdir()
 

	
 
    # John tries to renew a server certificate.
 
    stdout, stderr, exit_code = run_command("gimmecert", "renew", "server", "myserver")
 

	
 
    # John has forgotten to initialise the CA hierarchy from within
 
    # this directory, and is instead presented with an error.
 
    assert exit_code != 0
 
    assert stdout == ""
 
    assert stderr == "No CA hierarchy has been initialised yet. Run the gimmecert init command and issue some certificates first.\n"
 

	
 
    # John gives the screen a weird look, and tries again, this time
 
    # with a client certificate renewal.
 
    stdout, stderr, exit_code = run_command("gimmecert", "renew", "client", "myclient")
 

	
 
    # John gets presented with the same error yet again. Suddenly, he
 
    # realizes he is in a wrong directory... Oh well...
 
    assert exit_code != 0
 
    assert stdout == ""
 
    assert stderr == "No CA hierarchy has been initialised yet. Run the gimmecert init command and issue some certificates first.\n"
gimmecert/cli.py
Show inline comments
 
@@ -24,7 +24,7 @@ import os
 
import sys
 

	
 
from .decorators import subcommand_parser, get_subcommand_parser_setup_functions
 
from .commands import client, help_, init, server, usage, ExitCode
 
from .commands import client, help_, init, renew, server, usage, ExitCode
 

	
 

	
 
ERROR_GENERIC = 10
 
@@ -131,6 +131,13 @@ def setup_renew_subcommand_parser(parser, subparsers):
 
    subparser.add_argument('entity_type', help='Type of entity to renew.', choices=['server', 'client'])
 
    subparser.add_argument('entity_name', help='Name of the entity')
 

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

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

	
 
    subparser.set_defaults(func=renew_wrapper)
 

	
 
    return subparser
 

	
 

	
gimmecert/commands.py
Show inline comments
 
@@ -250,3 +250,13 @@ def client(stdout, stderr, project_directory, entity_name):
 
    Client certificate: .gimmecert/client/%s.cert.pem""" % (entity_name, entity_name), file=stdout)
 

	
 
    return ExitCode.SUCCESS
 

	
 

	
 
def renew(stdout, stderr, project_directory, entity_type, entity_name):
 

	
 
    if not gimmecert.storage.is_initialised(project_directory):
 
        print("No CA hierarchy has been initialised yet. Run the gimmecert init command and issue some certificates first.", file=stderr)
 

	
 
        return ExitCode.ERROR_NOT_INITIALISED
 

	
 
    return ExitCode.SUCCESS
tests/test_cli.py
Show inline comments
 
@@ -613,18 +613,63 @@ def test_renew_command_fails_without_arguments(tmpdir):
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', 'server', 'myserver'])
 
def test_renew_command_accepts_entity_type_server_and_entity_name(tmpdir):
 
@mock.patch('gimmecert.cli.renew')
 
def test_renew_command_accepts_entity_type_server_and_entity_name(mock_renew, tmpdir):
 
    # This should ensure we don't accidentally create artifacts
 
    # outside of test directory.
 
    tmpdir.chdir()
 

	
 
    # We are just testing the parsing here.
 
    mock_renew.return_value = gimmecert.commands.ExitCode.SUCCESS
 

	
 
    gimmecert.cli.main()  # Should not raise
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', 'client', 'myclient'])
 
def test_renew_command_accepts_entity_type_client_and_entity_name(tmpdir):
 
@mock.patch('gimmecert.cli.renew')
 
def test_renew_command_accepts_entity_type_client_and_entity_name(mock_renew, tmpdir):
 
    # This should ensure we don't accidentally create artifacts
 
    # outside of test directory.
 
    tmpdir.chdir()
 

	
 
    # We are just testing the parsing here.
 
    mock_renew.return_value = gimmecert.commands.ExitCode.SUCCESS
 

	
 
    gimmecert.cli.main()  # Should not raise
 

	
 

	
 
def test_setup_renew_subcommand_sets_function_callback():
 
    parser = argparse.ArgumentParser()
 
    subparsers = parser.add_subparsers()
 

	
 
    subparser = gimmecert.cli.setup_renew_subcommand_parser(parser, subparsers)
 

	
 
    assert callable(subparser.get_default('func'))
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', 'server', 'myserver'])
 
@mock.patch('gimmecert.cli.renew')
 
def test_renew_command_invoked_with_correct_parameters_for_server(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')
 

	
 

	
 
@mock.patch('sys.argv', ['gimmecert', 'renew', 'client', 'myclient'])
 
@mock.patch('gimmecert.cli.renew')
 
def test_renew_command_invoked_with_correct_parameters_for_client(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, 'client', 'myclient')
tests/test_commands.py
Show inline comments
 
@@ -462,3 +462,26 @@ def test_server_reports_success_if_certificate_not_already_issued_but_update_was
 
    assert ".gimmecert/server/myserver.key.pem" in stdout
 
    assert ".gimmecert/server/myserver.cert.pem" in stdout
 
    assert stderr == ""
 

	
 

	
 
def test_renew_returns_status_code(tmpdir):
 
    tmpdir.chdir()
 

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

	
 
    assert isinstance(status_code, int)
 

	
 

	
 
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')
 

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

	
 
    assert "No CA hierarchy has been initialised yet" in stderr
 
    assert stdout == ""
 
    assert status_code == gimmecert.commands.ExitCode.ERROR_NOT_INITIALISED
0 comments (0 inline, 0 general)