Skip to main content

Source code file content

Revision: 3045

18397632 pt gets updated with linked image states even if there are no linked images
» Project Revision History

» Checkout URL

pkg-gate / src / tests / certgenerator.py

Size: 17288 bytes, 1 line
#!/usr/bin/python2.6
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
#

import os
import subprocess

class CertGenerator(object):
        """A class which creates certificates."""

        def __init__(self, base_dir="."):
                # Allow relative path, but convert it to absolute path first.
                self.base_dir = os.path.abspath(base_dir)

                conf_dict = {"base_dir": self.base_dir}
                self.cnf_file = os.path.join(self.base_dir, "openssl.cnf")
                with open(self.cnf_file, "wb") as fh:
                        fh.write(self.openssl_conf % conf_dict)

                # Set up the needed files.
                fh = open(os.path.join(self.base_dir, "index"), "wb")
                fh.close()

                fh = open(os.path.join(self.base_dir, "serial"), "wb")
                fh.write("01\n")
                fh.close()

                # Set up the names of the needed directories.
                self.keys_loc = "keys"
                self.cs_loc = "code_signing_certs"
                self.chain_certs_loc = "chain_certs"
                self.trust_anchors_loc = "trust_anchors"
                self.crl_loc = "crl"

                # Set up the paths to the certificates that will be needed.
                self.keys_dir = os.path.join(self.base_dir, self.keys_loc)
                self.cs_dir = os.path.join(self.base_dir, self.cs_loc)
                self.chain_certs_dir = os.path.join(self.base_dir,
                    self.chain_certs_loc)
                self.raw_trust_anchor_dir = os.path.join(self.base_dir,
                    self.trust_anchors_loc)
                self.crl_dir = os.path.join(self.base_dir, self.crl_loc)

                os.mkdir(self.keys_dir)
                os.mkdir(self.cs_dir)
                os.mkdir(self.chain_certs_dir)
                os.mkdir(self.raw_trust_anchor_dir)
                os.mkdir(self.crl_dir)

        def convert_pem_to_text(self, tmp_pth, out_pth, kind="x509"):
                """Convert a pem file to a human friendly text file."""

                assert not os.path.exists(out_pth)

                cmd = ["openssl", kind, "-in", tmp_pth,
                    "-text"]

                fh = open(out_pth, "wb")
                p = subprocess.Popen(cmd, stdout=fh)
                assert p.wait() == 0
                fh.close()

        def make_ca_cert(self, new_name, parent_name, parent_loc=None,
            ext="v3_ca", ta_path=None, expired=False, future=False, https=False):
                """Create a new CA cert."""

                if not parent_loc:
                        parent_loc = self.trust_anchors_loc
                if not ta_path:
                        ta_path = self.base_dir
                subj_str_to_use = self.subj_str
                if https:
                        subj_str_to_use = self.https_subj_str
                cmd = ["openssl", "req", "-new", "-nodes",
                    "-keyout", "%s/%s_key.pem" % (self.keys_dir, new_name),
                    "-out", "%s/%s.csr" % (self.chain_certs_dir, new_name),
                    "-sha256", "-subj", subj_str_to_use % (new_name, new_name)]
                p = subprocess.Popen(cmd)
                assert p.wait() == 0

                cmd = ["openssl", "ca", "-policy", "policy_anything",
                    "-extensions", ext,
                    "-out", "%s/%s_cert.pem" % (self.chain_certs_dir,
                        new_name),
                    "-in", "%s/%s.csr" % (self.chain_certs_dir, new_name),
                    "-cert", "%s/%s/%s_cert.pem" % (ta_path, parent_loc,
                        parent_name),
                    "-outdir", "%s" % self.chain_certs_dir,
                    "-keyfile", "%s/%s/%s_key.pem" % (ta_path, self.keys_loc,
                        parent_name),
                    "-config", self.cnf_file,
                    "-batch"]
                if expired:
                        cmd.append("-startdate")
                        cmd.append("090101010101Z")
                        cmd.append("-enddate")
                        cmd.append("090102010101Z")
                elif future:
                        cmd.append("-startdate")
                        cmd.append("350101010101Z")
                        cmd.append("-enddate")
                        cmd.append("350102010101Z")
                else:
                        cmd.append("-days")
                        cmd.append("1000")
                p = subprocess.Popen(cmd)
                assert p.wait() == 0

        def make_cs_cert(self, new_name, parent_name, parent_loc=None,
                ext="v3_req", ca_path=None, expiring=False, expired=False,
                    future=False, https=False, passphrase=None):
                """Create a new code signing cert."""

                if not parent_loc:
                        parent_loc = self.trust_anchors_loc
                if not ca_path:
                        ca_path = self.base_dir
                subj_str_to_use = self.subj_str
                if https:
                        subj_str_to_use = self.https_subj_str
                cmd = ["openssl", "genrsa", "-out", "%s/%s_key.pem" % \
                    (self.keys_dir, new_name), "1024"]
                p = subprocess.Popen(cmd)
                assert p.wait() == 0

                cmd = ["openssl", "req", "-new", "-nodes",
                    "-key", "%s/%s_key.pem" % (self.keys_dir, new_name),
                    "-out", "%s/%s.csr" % (self.cs_dir, new_name),
                    "-sha256", "-subj", subj_str_to_use % (new_name, new_name)]
                p = subprocess.Popen(cmd)
                assert p.wait() == 0

                if passphrase:
                        # Add a passphrase to the key just created using a new filename.
                        cmd = ["openssl", "rsa", "-des3",
                            "-in", "%s/%s_key.pem" % (self.keys_dir, new_name),
                            "-out", "%s/%s_reqpass_key.pem" % (self.keys_dir,
                                new_name),
                            "-passout", "pass:%s" % passphrase]
                        p = subprocess.Popen(cmd)
                        assert p.wait() == 0

                cmd = ["openssl", "ca", "-policy", "policy_anything",
                    "-extensions", ext,
                    "-out", "%s/%s_cert.pem" % (self.cs_dir, new_name),
                    "-in", "%s/%s.csr" % (self.cs_dir, new_name),
                    "-cert", "%s/%s/%s_cert.pem" % (ca_path, parent_loc,
                        parent_name),
                    "-outdir", "%s" % self.cs_dir,
                    "-keyfile", "%s/%s/%s_key.pem" % (ca_path, self.keys_loc,
                        parent_name),
                    "-config", self.cnf_file,
                    "-batch"]
                if expired:
                        cmd.append("-startdate")
                        cmd.append("090101010101Z")
                        cmd.append("-enddate")
                        cmd.append("090102010101Z")
                elif future:
                        cmd.append("-startdate")
                        cmd.append("350101010101Z")
                        cmd.append("-enddate")
                        cmd.append("350102010101Z")
                elif expiring:
                        cmd.append("-days")
                        cmd.append("27")
                else:
                        cmd.append("-days")
                        cmd.append("1000")
                p = subprocess.Popen(cmd)
                assert p.wait() == 0

        def make_trust_anchor(self, name, https=False):
                """Make a new trust anchor."""

                subj_str_to_use = self.subj_str
                if https:
                        subj_str_to_use = self.https_subj_str
                cmd = ["openssl", "req", "-new", "-x509", "-nodes",
                    "-keyout", "%s/%s_key.pem" % (self.keys_dir, name),
                    "-subj", subj_str_to_use % (name, name),
                    "-out", "%s/%s/%s_cert.tmp" % (self.base_dir, name, name),
                    "-days", "1000",
                    "-sha256"]

                os.mkdir("%s/%s" % (self.base_dir, name))

                p = subprocess.Popen(cmd)
                assert p.wait() == 0
                self.convert_pem_to_text("%s/%s/%s_cert.tmp" % (self.base_dir,
                    name, name), "%s/%s/%s_cert.pem" % (self.base_dir, name,
                        name))

                try:
                        os.link("%s/%s/%s_cert.pem" % (self.base_dir, name, name),
                            "%s/%s_cert.pem" % (self.raw_trust_anchor_dir, name))
                except:
                        shutil.copy("%s/%s/%s_cert.pem" % (self.base_dir, name,
                            name), "%s/%s_cert.pem" % (self.raw_trust_anchor_dir,
                                name))

        def revoke_cert(self, ca, revoked_cert, ca_dir=None, cert_dir=None,
                ca_path=None):
                """Revoke a certificate using the CA given."""

                if not ca_dir:
                        ca_dir = ca
                if not cert_dir:
                        cert_dir = self.cs_loc
                if not ca_path:
                        ca_path = self.base_dir
                cmd = ["openssl", "ca", "-keyfile", "%s/%s/%s_key.pem" % \
                    (ca_path, self.keys_loc, ca),
                    "-cert", "%s/%s/%s_cert.pem" % (ca_path, ca_dir, ca),
                    "-config", self.cnf_file,
                    "-revoke", "%s/%s/%s_cert.pem" % (self.base_dir, cert_dir,
                    revoked_cert)]
                p = subprocess.Popen(cmd)
                assert p.wait() == 0

                cmd = ["openssl", "ca", "-gencrl",
                    "-keyfile", "%s/%s/%s_key.pem" % (ca_path, self.keys_loc, ca),
                    "-cert", "%s/%s/%s_cert.pem" % (ca_path, ca_dir, ca),
                    "-config", self.cnf_file,
                    "-out", "%s/%s_crl.tmp" % (self.crl_dir, ca),
                    "-crldays", "1000"]
                p = subprocess.Popen(cmd)
                assert p.wait() == 0
                self.convert_pem_to_text("%s/%s_crl.tmp" % (self.crl_dir, ca),
                    "%s/%s_crl.pem" % (self.crl_dir, ca), kind="crl")

        subj_str = "/C=US/ST=California/L=Santa Clara/O=pkg5/CN=%s/emailAddress=%s"
        https_subj_str = "/C=US/ST=California/L=Santa Clara/O=pkg5/OU=%s/" \
            "CN=localhost/emailAddress=%s"

        openssl_conf = """\
HOME                    = .
RANDFILE                = $ENV::HOME/.rnd

[ ca ]
default_ca      = CA_default

[ CA_default ]
dir             = %(base_dir)s
crl_dir         = $dir/crl
database        = $dir/index
serial          = $dir/serial

x509_extensions = usr_cert
unique_subject  = no

default_md      = sha256
preserve        = no

policy          = policy_match

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

####################################################################
[ req ]
default_bits            = 2048
default_keyfile         = ./private/ca-key.pem
default_md              = sha256

prompt                  = no
distinguished_name      = root_ca_distinguished_name

x509_extensions = v3_ca
string_mask = nombstr

[ root_ca_distinguished_name ]
commonName = ta1
countryName = US
stateOrProvinceName = California
localityName = Santa Clara
0.organizationName = pkg5
emailAddress = ta1@pkg5

[ usr_cert ]

# These extensions are added when 'ca' signs a request.

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always

[ v3_req ]

# Extensions to add to a certificate request.

basicConstraints = critical,CA:FALSE
keyUsage = critical, digitalSignature

[ v3_confused_cs ]

# Have CA be true, but don't have keyUsage allow certificate signing to created
# a confused certificate.

basicConstraints = critical,CA:true
keyUsage = critical, digitalSignature

[ v3_no_keyUsage ]

# The extensions to use for a code signing certificate without a keyUsage
# extension.

basicConstraints = critical,CA:FALSE

[ v3_ca ]

# Extensions for a typical CA.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true
keyUsage = critical, keyCertSign, cRLSign

[ v3_ca_lp4 ]

# Extensions for a typical CA.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true,pathlen:4
keyUsage = critical, keyCertSign, cRLSign

[ v3_ca_lp3 ]

# Extensions for a typical CA

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true,pathlen:3
keyUsage = critical, keyCertSign, cRLSign

[ v3_ca_lp2 ]

# Extensions for a typical CA.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true,pathlen:2
keyUsage = critical, keyCertSign, cRLSign

[ v3_ca_lp1 ]

# Extensions for a typical CA.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true,pathlen:1
keyUsage = critical, keyCertSign, cRLSign

[ v3_ca_lp0 ]

# Extensions for a typical CA.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true,pathlen:0
keyUsage = critical, keyCertSign, cRLSign

[ v3_ca_no_crl ]

# Extensions for a CA which cannot sign a CRL.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true
keyUsage = critical, keyCertSign

[ v3_ca_no_keyUsage ]

# Extensions for a CA without keyUsage information.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true

[ issuer_ext ]

# Used for a code signing cert with an unsupported critical extension.

basicConstraints = critical,CA:FALSE
issuerAltName = critical,issuer:copy

[ issuer_ext_ca ]

# Used for a CA cert with an unsupported critical extension.

basicConstraints = critical,CA:TRUE
issuerAltName = critical,issuer:copy

[ issuer_ext_non_critical ]

# Used to test a recognized non-critical extension with an unrecognized value.

basicConstraints = critical,CA:FALSE
keyUsage = encipherOnly

[ issuer_ext_bad_val ]

# Used to test a recognized critical extension with an unrecognized value.

basicConstraints = critical,CA:FALSE
keyUsage = critical, encipherOnly

[ crl_ext ]

# Used for testing certificate revocation.

basicConstraints = critical,CA:FALSE
crlDistributionPoints = URI:http://localhost:12001/file/0/ch1_ta4_crl.pem

[ ch5_ta1_crl ]

# Used for testing certificate revocation.

basicConstraints = critical,CA:FALSE
crlDistributionPoints = URI:http://localhost:12001/file/0/ch5_ta1_crl.pem

[ ch1.1_ta4_crl ]

# Used for testing certificate revocation.

basicConstraints = critical,CA:FALSE
crlDistributionPoints = URI:http://localhost:12001/file/0/ch1.1_ta4_crl.pem

[ ch1_ta1_crl ]

# Used for testing certificate revocation at the level of a chain certificate.

basicConstraints = critical,CA:FALSE
crlDistributionPoints = URI:http://localhost:12001/file/0/ch1_pubCA1_crl.pem

[ crl_ca ]

# Used for testing CA certificate revocation by a trust anchor.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true
crlDistributionPoints = URI:http://localhost:12001/file/0/ta5_crl.pem
keyUsage = critical, keyCertSign, cRLSign

[ bad_crl ]

# Used for testing a CRL with a bad file format.

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always

basicConstraints = critical,CA:false

crlDistributionPoints = URI:http://localhost:12001/file/0/example_file

[ bad_crl_loc ]

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always

basicConstraints = critical,CA:false

crlDistributionPoints = URI:foo://bar/baz
"""


 
 
Close
loading
Please Confirm
Close