Skip to content

Instantly share code, notes, and snippets.

@odg0318
Created August 27, 2018 06:30
Show Gist options
  • Select an option

  • Save odg0318/2523356f3ff4e06fe59ec867732921ef to your computer and use it in GitHub Desktop.

Select an option

Save odg0318/2523356f3ff4e06fe59ec867732921ef to your computer and use it in GitHub Desktop.
import datetime
import ipaddress
from cryptography import x509
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
class Base(object):
def _generate_key(self, bits):
return rsa.generate_private_key(
public_exponent=65537,
key_size=bits,
backend=default_backend()
)
def dump_key(self):
return self.key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)
def dump_cert(self):
return self.cert.public_bytes(serialization.Encoding.PEM)
class CA(Base):
def __init__(self, bits=2048):
self.key = self._generate_key(bits)
self.cert = self._generate_cert(self.key)
def _generate_cert(self, key):
name = x509.Name([
x509.NameAttribute(NameOID.ORGANIZATION_NAME, 'MyCompany'),
])
builder = x509.CertificateBuilder()
builder = builder.subject_name(name)
builder = builder.issuer_name(name)
builder = builder.not_valid_before(datetime.datetime.utcnow())
builder = builder.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=3650))
builder = builder.serial_number(x509.random_serial_number())
builder = builder.public_key(key.public_key())
builder = builder.add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=False,
)
builder = builder.add_extension(
x509.SubjectKeyIdentifier.from_public_key(key.public_key()),
critical=False
)
builder = builder.add_extension(
x509.AuthorityKeyIdentifier.from_issuer_public_key(
key.public_key()
), critical=False
)
return builder.sign(
private_key=key, algorithm=hashes.SHA256(),
backend=default_backend()
)
class LeafCertificate(Base):
def __init__(self, ca, cn=None, ip=None, bits=2048):
self.key = self._generate_key(bits)
self.cert = self._generate_cert(self.key, ca, cn, ip)
def _generate_cert(self, key, ca, cn, ip):
name = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, cn),
])
builder = x509.CertificateBuilder()
builder = builder.subject_name(name)
builder = builder.issuer_name(ca.cert.subject)
builder = builder.not_valid_before(datetime.datetime.utcnow())
builder = builder.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=3650))
builder = builder.serial_number(x509.random_serial_number())
builder = builder.public_key(key.public_key())
key_usage = ExtendedKeyUsageOID.CLIENT_AUTH if ip is None else ExtendedKeyUsageOID.SERVER_AUTH
builder = builder.add_extension(
x509.ExtendedKeyUsage(
[key_usage]
),
critical=False,
)
if ip is not None:
builder = builder.add_extension(
x509.SubjectAlternativeName(x509.SubjectAlternativeName(
[
x509.DNSName(ip),
x509.IPAddress(ipaddress.IPv4Address(ip)),
x509.IPAddress(ipaddress.IPv4Address('127.0.0.1')),
]
)),
critical=False
)
# Ok, sign the cert.
return builder.sign(
private_key=ca.key, algorithm=hashes.SHA256(),
backend=default_backend()
)
class ServerCertificate(LeafCertificate):
def __init__(self, ca, ip):
super(ServerCertificate, self).__init__(ca, cn=ip, ip=ip)
class ClientCertificate(LeafCertificate):
def __init__(self, ca, cn):
super(ClientCertificate, self).__init__(ca, cn=cn)
def generate_ca(bits=2048):
return CA(bits)
def generate_server_certificate(ca, ip):
return ServerCertificate(ca, ip)
def generate_client_certificate(ca, cn='portainer'):
return ClientCertificate(ca, cn)
def usage():
ca = generate_ca()
server = generate_server_certificate(ca, '172.16.1.5')
client = generate_client_certificate(ca, 'odg0318')
with open('ca.key', 'wb') as f:
f.write(ca.dump_key())
with open('ca.crt', 'wb') as f:
f.write(ca.dump_cert())
with open('server.key', 'wb') as f:
f.write(server.dump_key())
with open('server.crt', 'wb') as f:
f.write(server.dump_cert())
with open('client.key', 'wb') as f:
f.write(client.dump_key())
with open('client.crt', 'wb') as f:
f.write(client.dump_cert())
if __name__ == '__main__':
usage()
@odg0318
Copy link
Author

odg0318 commented Aug 27, 2018

This python code shows how to generate certificates for protecting docker daemon socket over TLS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment