Merge pull request #2667 from certbot/must-staple

Add --must-staple flag
This commit is contained in:
Peter Eckersley 2016-05-13 13:23:42 -07:00
commit 01a528c3ee
4 changed files with 40 additions and 6 deletions

View file

@ -704,6 +704,9 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
helpful.add(
"security", "--rsa-key-size", type=int, metavar="N",
default=flag_default("rsa_key_size"), help=config_help("rsa_key_size"))
helpful.add(
"security", "--must-staple", action="store_true",
help=config_help("must_staple"), dest="must_staple", default=False)
helpful.add(
"security", "--redirect", action="store_true",
help="Automatically redirect all HTTP traffic to HTTPS for the newly "

View file

@ -75,9 +75,11 @@ def init_save_csr(privkey, names, path, csrname="csr-certbot.pem"):
:rtype: :class:`certbot.le_util.CSR`
"""
csr_pem, csr_der = make_csr(privkey.pem, names)
config = zope.component.getUtility(interfaces.IConfig)
csr_pem, csr_der = make_csr(privkey.pem, names,
must_staple=config.must_staple)
# Save CSR
le_util.make_or_verify_dir(path, 0o755, os.geteuid(),
config.strict_permissions)
@ -92,7 +94,7 @@ def init_save_csr(privkey, names, path, csrname="csr-certbot.pem"):
# Lower level functions
def make_csr(key_str, domains):
def make_csr(key_str, domains, must_staple=False):
"""Generate a CSR.
:param str key_str: PEM-encoded RSA key.
@ -111,13 +113,19 @@ def make_csr(key_str, domains):
req.get_subject().CN = domains[0]
# TODO: what to put into req.get_subject()?
# TODO: put SAN if len(domains) > 1
req.add_extensions([
extensions = [
OpenSSL.crypto.X509Extension(
"subjectAltName",
critical=False,
value=", ".join("DNS:%s" % d for d in domains)
),
])
)
]
if must_staple:
extensions.append(OpenSSL.crypto.X509Extension(
"1.3.6.1.5.5.7.1.24",
critical=False,
value="DER:30:03:02:01:05"))
req.add_extensions(extensions)
req.set_version(2)
req.set_pubkey(pkey)
req.sign(pkey, "sha256")

View file

@ -200,6 +200,10 @@ class IConfig(zope.interface.Interface):
email = zope.interface.Attribute(
"Email used for registration and recovery contact.")
rsa_key_size = zope.interface.Attribute("Size of the RSA key.")
must_staple = zope.interface.Attribute(
"Whether to request the OCSP Must Staple certificate extension. "
"Additional setup may be required after issuance. This does not "
"currently autoconfigure web servers for OCSP stapling. ")
config_dir = zope.interface.Attribute("Configuration directory.")
work_dir = zope.interface.Attribute("Working directory.")

View file

@ -95,6 +95,25 @@ class MakeCSRTest(unittest.TestCase):
['example.com', 'www.example.com'], get_sans_from_csr(
csr_der, OpenSSL.crypto.FILETYPE_ASN1))
def test_must_staple(self):
# TODO: Fails for RSA256_KEY
csr_pem, _ = self._call(
RSA512_KEY, ['example.com', 'www.example.com'], must_staple=True)
csr = OpenSSL.crypto.load_certificate_request(
OpenSSL.crypto.FILETYPE_PEM, csr_pem)
# In pyopenssl 0.13 (used with TOXENV=py26-oldest and py27-oldest), csr
# objects don't have a get_extensions() method, so we skip this test if
# the method isn't available.
if hasattr(csr, 'get_extensions'):
# NOTE: Ideally we would filter by the TLS Feature OID, but
# OpenSSL.crypto.X509Extension doesn't give us the extension's raw OID,
# and the shortname field is just "UNDEF"
must_staple_exts = [e for e in csr.get_extensions()
if e.get_data() == "0\x03\x02\x01\x05"]
self.assertEqual(len(must_staple_exts), 1,
"Expected exactly one Must Staple extension")
class ValidCSRTest(unittest.TestCase):
"""Tests for certbot.crypto_util.valid_csr."""