Files @ 115075d44c60
Branch filter:

Location: gimmecert/functional_tests/test_status.py - annotation

branko
GC-48: Update version string in generated documentation during release.
87692ece8441
87692ece8441
17fc6250168e
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
fc3f4dbefa31
fc3f4dbefa31
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
87692ece8441
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
108dfefd1032
14738fb50670
14738fb50670
fc3f4dbefa31
fc3f4dbefa31
92e93e67b2b6
fc3f4dbefa31
fc3f4dbefa31
14738fb50670
14738fb50670
14738fb50670
14738fb50670
10f853e85ad2
fc3f4dbefa31
14738fb50670
07ff7da6d41f
14738fb50670
10f853e85ad2
10f853e85ad2
10f853e85ad2
92e93e67b2b6
14738fb50670
07ff7da6d41f
14738fb50670
10f853e85ad2
10f853e85ad2
10f853e85ad2
92e93e67b2b6
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
fc3f4dbefa31
14738fb50670
14738fb50670
14738fb50670
14738fb50670
07ff7da6d41f
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
14738fb50670
07ff7da6d41f
07ff7da6d41f
14738fb50670
14738fb50670
10f853e85ad2
92e93e67b2b6
14738fb50670
14738fb50670
14738fb50670
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
14738fb50670
14738fb50670
14738fb50670
fc3f4dbefa31
07ff7da6d41f
07ff7da6d41f
14738fb50670
10f853e85ad2
10f853e85ad2
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
10f853e85ad2
92e93e67b2b6
92e93e67b2b6
92e93e67b2b6
92e93e67b2b6
92e93e67b2b6
14738fb50670
14738fb50670
07ff7da6d41f
07ff7da6d41f
14738fb50670
14738fb50670
10f853e85ad2
92e93e67b2b6
14738fb50670
14738fb50670
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
14738fb50670
14738fb50670
fc3f4dbefa31
07ff7da6d41f
07ff7da6d41f
10f853e85ad2
10f853e85ad2
07ff7da6d41f
07ff7da6d41f
07ff7da6d41f
92e93e67b2b6
92e93e67b2b6
92e93e67b2b6
92e93e67b2b6
92e93e67b2b6
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018, 2020, 2024, 2025 Branko Majic
#
# This file is part of Gimmecert.
#
# Gimmecert is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Gimmecert is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# Gimmecert.  If not, see <http://www.gnu.org/licenses/>.
#


from .base import run_command

import pytest


def test_status_command_available_with_help():
    # John has used Gimmecert for issuing server and client
    # certificates in one of his projects. Since the project has been
    # quite hectic, he has started to loose track of all the different
    # server and client certificates he has issued. He realises that
    # he needs to check what has been issued. Although this should be
    # possible by simply listing the directory content, John hopes
    # that there might be a convenience command for this instead that
    # provides some extra info as well. He starts off by running the
    # command without any paramrters to get a listing of available
    # commands.
    stdout, stderr, exit_code = run_command("gimmecert")

    # Looking at output, John notices the status command.
    assert exit_code == 0
    assert stderr == ""
    assert "status" in stdout

    # He goes ahead and has a look at command invocation to check what
    # kind of parameters he might need to provide.
    stdout, stderr, exit_code = run_command("gimmecert", "status", "-h")

    # John can see that the command does not take any additional
    # arguments.
    assert exit_code == 0
    assert stderr == ""
    assert stdout.split('\n')[0] == "usage: gimmecert status [-h]"


def test_status_on_uninitialised_directory(tmpdir):
    # John wants to see the status of current set of artefacts
    # generated by Gimmecert.

    # He swithces over to his project directory.
    tmpdir.chdir()

    # John runs the status command.
    stdout, stderr, exit_code = run_command('gimmecert', 'status')

    # It turns out that the directory has not been previously
    # initialised. In spite of this, the tool reports success, and
    # informs John that Gimmecert has not been initialised yet.
    assert exit_code == 0
    assert "CA hierarchy has not been initialised in current directory." in stdout


@pytest.mark.parametrize("ca_key_specification, default_key_representation", [
    ("rsa:2048", "2048-bit RSA"),
    ("ecdsa:secp521r1", "secp521r1 ECDSA"),
])
def test_status_on_initialised_directory(tmpdir, ca_key_specification, default_key_representation):
    # John is interested in finding out a bit more about what
    # certificates have been already issued in one of the projects he
    # had initialised before.
    tmpdir.chdir()

    run_command('gimmecert', 'init', '-k', ca_key_specification, '-d', '3', '-b', 'My Project')

    run_command('gimmecert', 'server', 'myserver1', '-k', 'rsa:1024')
    run_command('gimmecert', 'server', 'myserver2', 'myservice.example.com', 'myotherservice.example.com')
    run_command("openssl", "req", "-new", "-newkey", "rsa:2048", "-nodes", "-keyout", "myserver3.key.pem",
                "-subj", "/CN=myserver3", "-out", "myserver3.csr.pem")
    run_command('gimmecert', 'server', '--csr', 'myserver3.csr.pem', 'myserver3')
    run_command('gimmecert', 'server', 'myserver4', '-k', 'ecdsa:secp256r1')

    run_command('gimmecert', 'client', 'myclient1', '-k', 'rsa:1024')
    run_command('gimmecert', 'client', 'myclient2')
    run_command("openssl", "req", "-new", "-newkey", "rsa:2048", "-nodes", "-keyout", "myclient3.key.pem",
                "-subj", "/CN=myclient3", "-out", "myclient3.csr.pem")
    run_command('gimmecert', 'client', '--csr', 'myclient3.csr.pem', 'myclient3')
    run_command('gimmecert', 'client', 'myclient4', '-k', 'ecdsa:secp192r1')

    # John switches to project directory.
    tmpdir.chdir()

    # John runs the status command.
    stdout, stderr, exit_code = run_command('gimmecert', 'status')
    stdout_lines = stdout.split("\n")

    # Command exits with success without any errors being
    # reported.
    assert exit_code == 0
    assert stderr == ""

    # John notices that information is laid-out in three separate
    # sections - one for CA hierachy, one for server certificates, and
    # one for client certificates.
    assert "CA hierarchy" in stdout
    assert "Server certificates" in stdout
    assert "Client certificates" in stdout

    # John first has a look at information about the CA
    # hierarchy. First thing he can see is information about the
    # default key algorithm in use. This is followed by the hierarchy
    # tree presented using indentation. Each CA is listed with its
    # full subject DN, as well as not before and not after dates. In
    # addition, the final CA in chain is marked as end entity issuing
    # CA.
    index_default_key_algorithm = stdout_lines.index("Default key algorithm: %s" % default_key_representation)  # Should not raise
    index_ca_1 = stdout_lines.index("CN=My Project Level 1 CA")  # Should not raise
    index_ca_2 = stdout_lines.index("CN=My Project Level 2 CA")  # Should not raise
    index_ca_3 = stdout_lines.index("CN=My Project Level 3 CA [END ENTITY ISSUING CA]")  # Should not raise

    assert index_default_key_algorithm < index_ca_1
    assert index_ca_1 < index_ca_2
    assert index_ca_2 < index_ca_3

    assert stdout_lines[index_ca_1+1].startswith("    Validity: ")
    assert stdout_lines[index_ca_1+2].startswith("    Certificate: ")

    assert stdout_lines[index_ca_2+1].startswith("    Validity: ")
    assert stdout_lines[index_ca_2+2].startswith("    Certificate: ")

    assert stdout_lines[index_ca_3+1].startswith("    Validity: ")
    assert stdout_lines[index_ca_3+2].startswith("    Certificate: ")

    # In addition to CA information, path to full certificate chain is
    # output as well.
    assert "Full certificate chain:" in stdout

    # John then has a look at server certificates. These are presented
    # in a list, and for each certificate is listed with subject DN,
    # not before, not after, and included DNS names. Information for
    # each server is followed by key algorithm information, and paths
    # to private key and certificate.
    index_myserver1 = stdout_lines.index("CN=myserver1")  # Should not raise
    index_myserver2 = stdout_lines.index("CN=myserver2")  # Should not raise
    index_myserver3 = stdout_lines.index("CN=myserver3")  # Should not raise
    index_myserver4 = stdout_lines.index("CN=myserver4")  # Should not raise

    assert stdout_lines[index_myserver1+1].startswith("    Validity: ")
    assert stdout_lines[index_myserver1+2] == "    DNS: myserver1"
    assert stdout_lines[index_myserver1+3] == "    Key algorithm: 1024-bit RSA"
    assert stdout_lines[index_myserver1+4] == "    Private key: .gimmecert/server/myserver1.key.pem"
    assert stdout_lines[index_myserver1+5] == "    Certificate: .gimmecert/server/myserver1.cert.pem"

    assert stdout_lines[index_myserver2+1].startswith("    Validity: ")
    assert stdout_lines[index_myserver2+2] == "    DNS: myserver2, myservice.example.com, myotherservice.example.com"
    assert stdout_lines[index_myserver2+3] == "    Key algorithm: %s" % default_key_representation
    assert stdout_lines[index_myserver2+4] == "    Private key: .gimmecert/server/myserver2.key.pem"
    assert stdout_lines[index_myserver2+5] == "    Certificate: .gimmecert/server/myserver2.cert.pem"

    assert stdout_lines[index_myserver3+1].startswith("    Validity: ")
    assert stdout_lines[index_myserver3+2] == "    DNS: myserver3"
    assert stdout_lines[index_myserver3+3] == "    Key algorithm: 2048-bit RSA"
    assert stdout_lines[index_myserver3+4] == "    CSR: .gimmecert/server/myserver3.csr.pem"
    assert stdout_lines[index_myserver3+5] == "    Certificate: .gimmecert/server/myserver3.cert.pem"

    assert stdout_lines[index_myserver4+2] == "    DNS: myserver4"
    assert stdout_lines[index_myserver4+3] == "    Key algorithm: secp256r1 ECDSA"
    assert stdout_lines[index_myserver4+4] == "    Private key: .gimmecert/server/myserver4.key.pem"
    assert stdout_lines[index_myserver4+5] == "    Certificate: .gimmecert/server/myserver4.cert.pem"

    # For client certificates, John can see that for each certificate
    # he can see its subject DN and validity. Information for each
    # client is followed by key algorithm and paths to private key and
    # certificate.
    index_myclient1 = stdout_lines.index("CN=myclient1")  # Should not raise
    index_myclient2 = stdout_lines.index("CN=myclient2")  # Should not raise
    index_myclient3 = stdout_lines.index("CN=myclient3")  # Should not raise
    index_myclient4 = stdout_lines.index("CN=myclient4")  # Should not raise

    assert stdout_lines[index_myclient1+1].startswith("    Validity: ")
    assert stdout_lines[index_myclient1+2] == "    Key algorithm: 1024-bit RSA"
    assert stdout_lines[index_myclient1+3] == "    Private key: .gimmecert/client/myclient1.key.pem"
    assert stdout_lines[index_myclient1+4] == "    Certificate: .gimmecert/client/myclient1.cert.pem"

    assert stdout_lines[index_myclient2+1].startswith("    Validity: ")
    assert stdout_lines[index_myclient2+2] == "    Key algorithm: %s" % default_key_representation
    assert stdout_lines[index_myclient2+3] == "    Private key: .gimmecert/client/myclient2.key.pem"
    assert stdout_lines[index_myclient2+4] == "    Certificate: .gimmecert/client/myclient2.cert.pem"

    assert stdout_lines[index_myclient3+1].startswith("    Validity: ")
    assert stdout_lines[index_myclient3+2] == "    Key algorithm: 2048-bit RSA"
    assert stdout_lines[index_myclient3+3] == "    CSR: .gimmecert/client/myclient3.csr.pem"
    assert stdout_lines[index_myclient3+4] == "    Certificate: .gimmecert/client/myclient3.cert.pem"

    assert stdout_lines[index_myclient4+1].startswith("    Validity: ")
    assert stdout_lines[index_myclient4+2] == "    Key algorithm: secp192r1 ECDSA"
    assert stdout_lines[index_myclient4+3] == "    Private key: .gimmecert/client/myclient4.key.pem"
    assert stdout_lines[index_myclient4+4] == "    Certificate: .gimmecert/client/myclient4.cert.pem"