141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
"""
|
||
.. module: lemur.plugins.lemur_jks.plugin
|
||
:platform: Unix
|
||
:copyright: (c) 2018 by Netflix Inc., see AUTHORS for more
|
||
:license: Apache, see LICENSE for more details.
|
||
|
||
.. moduleauthor:: Marti Raudsepp <marti@juffo.org>
|
||
"""
|
||
|
||
from cryptography.fernet import Fernet
|
||
from cryptography.hazmat.primitives import serialization
|
||
from jks import PrivateKeyEntry, KeyStore, TrustedCertEntry
|
||
|
||
from lemur.common.defaults import common_name
|
||
from lemur.common.utils import parse_certificate, parse_cert_chain, parse_private_key
|
||
from lemur.plugins import lemur_jks as jks
|
||
from lemur.plugins.bases import ExportPlugin
|
||
|
||
|
||
def cert_chain_as_der(cert, chain):
|
||
"""Return a certificate and its chain in a list format, as expected by pyjks."""
|
||
|
||
certs = [parse_certificate(cert)]
|
||
certs.extend(parse_cert_chain(chain))
|
||
# certs (list) – A list of certificates, as byte strings. The first one should be the one belonging to the private
|
||
# key, the others the chain (in correct order).
|
||
return [cert.public_bytes(encoding=serialization.Encoding.DER) for cert in certs]
|
||
|
||
|
||
def create_truststore(cert, chain, alias, passphrase):
|
||
entries = []
|
||
for idx, cert_bytes in enumerate(cert_chain_as_der(cert, chain)):
|
||
# The original cert gets name <ALIAS>_cert, first chain element is <ALIAS>_cert_1, etc.
|
||
cert_alias = alias + "_cert" + ("_{}".format(idx) if idx else "")
|
||
entries.append(TrustedCertEntry.new(cert_alias, cert_bytes))
|
||
|
||
return KeyStore.new("jks", entries).saves(passphrase)
|
||
|
||
|
||
def create_keystore(cert, chain, key, alias, passphrase):
|
||
certs_bytes = cert_chain_as_der(cert, chain)
|
||
key_bytes = parse_private_key(key).private_bytes(
|
||
encoding=serialization.Encoding.DER,
|
||
format=serialization.PrivateFormat.PKCS8,
|
||
encryption_algorithm=serialization.NoEncryption(),
|
||
)
|
||
entry = PrivateKeyEntry.new(alias, certs_bytes, key_bytes)
|
||
|
||
return KeyStore.new("jks", [entry]).saves(passphrase)
|
||
|
||
|
||
class JavaTruststoreExportPlugin(ExportPlugin):
|
||
title = "Java Truststore (JKS)"
|
||
slug = "java-truststore-jks"
|
||
description = "Generates a JKS truststore"
|
||
requires_key = False
|
||
version = jks.VERSION
|
||
|
||
author = "Marti Raudsepp"
|
||
author_url = "https://github.com/intgr"
|
||
|
||
options = [
|
||
{
|
||
"name": "alias",
|
||
"type": "str",
|
||
"required": False,
|
||
"helpMessage": "Enter the alias you wish to use for the truststore.",
|
||
},
|
||
{
|
||
"name": "passphrase",
|
||
"type": "str",
|
||
"required": False,
|
||
"helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this.",
|
||
"validation": "",
|
||
},
|
||
]
|
||
|
||
def export(self, body, chain, key, options, **kwargs):
|
||
"""
|
||
Generates a Java Truststore
|
||
"""
|
||
|
||
if self.get_option("alias", options):
|
||
alias = self.get_option("alias", options)
|
||
else:
|
||
alias = common_name(parse_certificate(body))
|
||
|
||
if self.get_option("passphrase", options):
|
||
passphrase = self.get_option("passphrase", options)
|
||
else:
|
||
passphrase = Fernet.generate_key().decode("utf-8")
|
||
|
||
raw = create_truststore(body, chain, alias, passphrase)
|
||
|
||
return "jks", passphrase, raw
|
||
|
||
|
||
class JavaKeystoreExportPlugin(ExportPlugin):
|
||
title = "Java Keystore (JKS)"
|
||
slug = "java-keystore-jks"
|
||
description = "Generates a JKS keystore"
|
||
version = jks.VERSION
|
||
|
||
author = "Marti Raudsepp"
|
||
author_url = "https://github.com/intgr"
|
||
|
||
options = [
|
||
{
|
||
"name": "passphrase",
|
||
"type": "str",
|
||
"required": False,
|
||
"helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this.",
|
||
"validation": "",
|
||
},
|
||
{
|
||
"name": "alias",
|
||
"type": "str",
|
||
"required": False,
|
||
"helpMessage": "Enter the alias you wish to use for the keystore.",
|
||
},
|
||
]
|
||
|
||
def export(self, body, chain, key, options, **kwargs):
|
||
"""
|
||
Generates a Java Keystore
|
||
"""
|
||
|
||
if self.get_option("passphrase", options):
|
||
passphrase = self.get_option("passphrase", options)
|
||
else:
|
||
passphrase = Fernet.generate_key().decode("utf-8")
|
||
|
||
if self.get_option("alias", options):
|
||
alias = self.get_option("alias", options)
|
||
else:
|
||
alias = common_name(parse_certificate(body))
|
||
|
||
raw = create_keystore(body, chain, key, alias, passphrase)
|
||
|
||
return "jks", passphrase, raw
|