Qgelm

Be your own certificate authority

Originalartikel

Backup

<html> <p>The Transport Layer Security (<a href=„https://en.wikipedia.org/wiki/Transport_Layer_Security“ target=„_blank“>TLS</a>) model, which is sometimes referred to by the older name SSL, is based on the concept of <a href=„https://en.wikipedia.org/wiki/Certificate_authority“ target=„_blank“>certificate authorities</a> (CAs). These authorities are trusted by browsers and operating systems and, in turn, <em>sign</em> servers' certificates to validate their ownership.</p> <p>However, for an intranet, a microservice architecture, or integration testing, it is sometimes useful to have a <em>local CA</em>: one that is trusted only internally and, in turn, signs local servers' certificates.</p> <p>This especially makes sense for integration tests. Getting certificates can be a burden because the servers will be up for minutes. But having an „ignore certificate“ option in the code could allow it to be activated in production, leading to a security catastrophe.</p> <p>A CA certificate is not much different from a regular server certificate; what matters is that it is trusted by local code. For example, in the <strong>requests</strong> library, this can be done by setting the <strong>REQUESTS_CA_BUNDLE</strong> variable to a directory containing this certificate.</p> <p>In the example of creating a certificate for integration tests, there is no need for a <em>long-lived</em> certificate: if your integration tests take more than a day, you have already failed.</p> <p>So, calculate <strong>yesterday</strong> and <strong>tomorrow</strong> as the validity interval:</p> <p>&gt;&gt;&gt; import datetime<br/>&gt;&gt;&gt; one_day = datetime.timedelta(days=1)<br/>&gt;&gt;&gt; today = datetime.date.today()<br/>&gt;&gt;&gt; yesterday = today - one_day<br/>&gt;&gt;&gt; tomorrow = today - one_day</p> <p>Now you are ready to create a simple CA certificate. You need to generate a private key, create a public key, set up the „parameters“ of the CA, and then self-sign the certificate: a CA certificate is <em>always</em> self-signed. Finally, write out both the certificate file as well as the private key file.</p> <div class=„geshifilter text geshifilter-text“ readability=„55“>from cryptography.hazmat.primitives.asymmetric import rsa<br/>from cryptography.hazmat.primitives import hashes, serialization<br/>from cryptography import x509<br/>from cryptography.x509.oid import NameOID <p>private_key = rsa.generate_private_key(<br/>&#160; &#160; public_exponent=65537,<br/>&#160; &#160; key_size=2048,<br/>&#160; &#160; backend=default_backend()<br/>)<br/>public_key = private_key.public_key()<br/>builder = x509.CertificateBuilder()<br/>builder = builder.subject_name(x509.Name([<br/>&#160; &#160; x509.NameAttribute(NameOID.COMMON_NAME, 'Simple Test CA'),<br/>]))<br/>builder = builder.issuer_name(x509.Name([<br/>&#160; &#160; x509.NameAttribute(NameOID.COMMON_NAME, 'Simple Test CA'),<br/>]))<br/>builder = builder.not_valid_before(yesterday)<br/>builder = builder.not_valid_after(tomorrow)<br/>builder = builder.serial_number(x509.random_serial_number())<br/>builder = builder.public_key(public_key)<br/>builder = builder.add_extension(<br/>&#160; &#160; x509.BasicConstraints(ca=True, path_length=None),<br/>&#160; &#160; critical=True)<br/>certificate = builder.sign(<br/>&#160; &#160; private_key=private_key, algorithm=hashes.SHA256(),<br/>&#160; &#160; backend=default_backend()<br/>)<br/>private_bytes = private_key.private_bytes(<br/>&#160; &#160; encoding=serialization.Encoding.PEM,<br/>&#160; &#160; format=serialization.PrivateFormat.TraditionalOpenSSL,<br/>&#160; &#160; encryption_algorithm=serialization.NoEncrption())<br/>public_bytes = certificate.public_bytes(<br/>&#160; &#160; encoding=serialization.Encoding.PEM)<br/>with open(„ca.pem“, „wb“) as fout:<br/>&#160; &#160; fout.write(private_bytes + public_bytes)<br/>with open(„ca.crt“, „wb“) as fout:<br/>&#160; &#160; fout.write(public_bytes)</p> </div> <p>In general, a real CA will expect a <a href=„https://en.wikipedia.org/wiki/Certificate_signing_request“ target=„_blank“>certificate signing request</a> (CSR) to sign a certificate. However, when you are your own CA, you can make your own rules! Just go ahead and sign what you want.</p> <p>Continuing with the integration test example, you can create the private keys and sign the corresponding public keys right then. Notice <strong>COMMON_NAME</strong> needs to be the „server name“ in the <strong>https</strong> URL. If you've configured name lookup, the needed server will respond on <strong>service.test.local</strong>.</p> <p>service_private_key = rsa.generate_private_key(<br/>&#160; &#160; public_exponent=65537,<br/>&#160; &#160; key_size=2048,<br/>&#160; &#160; backend=default_backend()<br/>)<br/>service_public_key = service_private_key.public_key()<br/>builder = x509.CertificateBuilder()<br/>builder = builder.subject_name(x509.Name([<br/>&#160; &#160;x509.NameAttribute(NameOID.COMMON_NAME, 'service.test.local')<br/>]))<br/>builder = builder.not_valid_before(yesterday)<br/>builder = builder.not_valid_after(tomorrow)<br/>builder = builder.public_key(public_key)<br/>certificate = builder.sign(<br/>&#160; &#160; private_key=private_key, algorithm=hashes.SHA256(),<br/>&#160; &#160; backend=default_backend()<br/>)<br/>private_bytes = service_private_key.private_bytes(<br/>&#160; &#160; encoding=serialization.Encoding.PEM,<br/>&#160; &#160; format=serialization.PrivateFormat.TraditionalOpenSSL,<br/>&#160; &#160; encryption_algorithm=serialization.NoEncrption())<br/>public_bytes = certificate.public_bytes(<br/>&#160; &#160; encoding=serialization.Encoding.PEM)<br/>with open(„service.pem“, „wb“) as fout:<br/>&#160; &#160; fout.write(private_bytes + public_bytes)</p> <p>Now the <strong>service.pem</strong> file has a private key and a certificate that is „valid“: it has been signed by your local CA. The file is in a format that can be given to, say, Nginx, HAProxy, or most other HTTPS servers.</p> <p>By applying this logic to testing scripts, it's easy to create servers that look like authentic HTTPS servers, as long as the client is configured to trust the right CA.</p> </html>

Cookies helfen bei der Bereitstellung von Inhalten. Diese Website verwendet Cookies. Mit der Nutzung der Website erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Computer gespeichert werden. Außerdem bestätigen Sie, dass Sie unsere Datenschutzerklärung gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information