crypto: improve support for non-rsa private keys (discovery)

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-12-22 21:46:22 +01:00
parent c77f804b77
commit c1f0833c09
4 changed files with 13 additions and 8 deletions

View File

@ -72,7 +72,7 @@ class CertificateKeyPairSerializer(ModelSerializer):
return value return value
def validate_key_data(self, value: str) -> str: def validate_key_data(self, value: str) -> str:
"""Verify that input is a valid PEM RSA Key""" """Verify that input is a valid PEM Key"""
# Since this field is optional, data can be empty. # Since this field is optional, data can be empty.
if value != "": if value != "":
try: try:

View File

@ -6,6 +6,11 @@ from uuid import uuid4
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.ec import (
EllipticCurvePrivateKey,
EllipticCurvePublicKey,
)
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey
from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.x509 import Certificate, load_pem_x509_certificate from cryptography.x509 import Certificate, load_pem_x509_certificate
@ -36,8 +41,8 @@ class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
) )
_cert: Optional[Certificate] = None _cert: Optional[Certificate] = None
_private_key: Optional[RSAPrivateKey] = None _private_key: Optional[RSAPrivateKey | EllipticCurvePrivateKey | Ed25519PrivateKey] = None
_public_key: Optional[RSAPublicKey] = None _public_key: Optional[RSAPublicKey | EllipticCurvePublicKey | Ed25519PublicKey] = None
@property @property
def certificate(self) -> Certificate: def certificate(self) -> Certificate:
@ -49,14 +54,14 @@ class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
return self._cert return self._cert
@property @property
def public_key(self) -> Optional[RSAPublicKey]: def public_key(self) -> Optional[RSAPublicKey | EllipticCurvePublicKey]:
"""Get public key of the private key""" """Get public key of the private key"""
if not self._public_key: if not self._public_key:
self._public_key = self.private_key.public_key() self._public_key = self.private_key.public_key()
return self._public_key return self._public_key
@property @property
def private_key(self) -> Optional[RSAPrivateKey]: def private_key(self) -> Optional[RSAPrivateKey | EllipticCurvePrivateKey]:
"""Get python cryptography PrivateKey instance""" """Get python cryptography PrivateKey instance"""
if not self._private_key and self.key_data != "": if not self._private_key and self.key_data != "":
try: try:

View File

@ -24,7 +24,7 @@ MANAGED_DISCOVERED = "goauthentik.io/crypto/discovered/%s"
def ensure_private_key_valid(body: str): def ensure_private_key_valid(body: str):
"""Attempt loading of an RSA Private key without password""" """Attempt loading of a PEM Private key without password"""
load_pem_private_key( load_pem_private_key(
str.encode("\n".join([x.strip() for x in body.split("\n")])), str.encode("\n".join([x.strip() for x in body.split("\n")])),
password=None, password=None,
@ -60,7 +60,7 @@ def certificate_discovery(self: MonitoredTask):
try: try:
with open(path, "r+", encoding="utf-8") as _file: with open(path, "r+", encoding="utf-8") as _file:
body = _file.read() body = _file.read()
if "BEGIN RSA PRIVATE KEY" in body: if "PRIVATE KEY" in body:
private_keys[cert_name] = ensure_private_key_valid(body) private_keys[cert_name] = ensure_private_key_valid(body)
else: else:
certs[cert_name] = ensure_certificate_valid(body) certs[cert_name] = ensure_certificate_valid(body)

View File

@ -34,7 +34,7 @@ You can also bind mount single files into the folder, as long as they fall under
`/foo.pem` Will be imported as the keypair `foo`. Based on its content its either imported as certificate or private key. `/foo.pem` Will be imported as the keypair `foo`. Based on its content its either imported as certificate or private key.
Currently, only RSA Keys are supported, so if the file contains `BEGIN RSA PRIVATE KEY` it will imported as private key. Files containing `PRIVATE KEY` it will imported as private key.
Otherwise it will be imported as certificate. Otherwise it will be imported as certificate.