Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add validity length (in days) for certs #981

Merged
merged 2 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-jans-auth-server/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pinned to py3-grpcio version to avoid failure on native extension build
grpcio==1.41.0
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
4 changes: 2 additions & 2 deletions docker-jans-certmanager/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM bellsoft/liberica-openjre-alpine:11
FROM bellsoft/liberica-openjre-alpine:11.0.13-8

# ===============
# Alpine packages
Expand All @@ -17,7 +17,7 @@ RUN apk update \

# JAR files required to generate OpenID Connect keys
ENV CN_VERSION=1.0.0-SNAPSHOT
ENV CN_BUILD_DATE='2022-01-25 09:43'
ENV CN_BUILD_DATE='2022-03-06 08:13'
ENV CN_SOURCE_URL=https://jenkins.jans.io/maven/io/jans/jans-auth-client/${CN_VERSION}/jans-auth-client-${CN_VERSION}-jar-with-dependencies.jar

RUN wget -q ${CN_SOURCE_URL} -P /app/javalibs/
Expand Down
4 changes: 3 additions & 1 deletion docker-jans-certmanager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Supported services:
Options:

- `source`: `from-files` or empty string
- `valid-to`: Validity length in days (default to `365`)

1. `auth`

Expand Down Expand Up @@ -138,6 +139,7 @@ Supported services:
Options:

- `subj-alt-name`: Subject Alternative Name (SAN) for certificate (default to `localhost`)
- `valid-to`: Validity length in days (default to `365`)

1. `client-api`

Expand All @@ -154,6 +156,7 @@ Supported services:

- `application-cn`: Subject alternative name for application certificate (default to `localhost`)
- `admin-cn`: Subject alternative name for admin certificate (default to `localhost`)
- `valid-to`: Validity length in days (default to `365`)

#### prune

Expand Down Expand Up @@ -240,4 +243,3 @@ spec:
args: ["patch", "auth", "--opts", "interval:48"]
restartPolicy: Never
```

2 changes: 1 addition & 1 deletion docker-jans-certmanager/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
grpcio==1.41.0
click==6.7
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
5 changes: 3 additions & 2 deletions docker-jans-certmanager/scripts/base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
logger = logging.getLogger("certmanager")


class BaseHandler(object):
class BaseHandler:
def __init__(self, manager, dry_run, **opts):
self.manager = manager
self.dry_run = dry_run
Expand All @@ -21,7 +21,7 @@ def _patch_keystore(self, prefix, hostname, passwd):
generate_keystore(prefix, hostname, passwd)
return keystore_fn

def _patch_cert_key(self, prefix, extra_dns=None):
def _patch_cert_key(self, prefix, extra_dns=None, valid_to=365):
cert_fn = f"/etc/certs/{prefix}.crt"
key_fn = f"/etc/certs/{prefix}.key"

Expand All @@ -35,6 +35,7 @@ def _patch_cert_key(self, prefix, extra_dns=None):
self.manager.config.get("state"),
self.manager.config.get("city"),
extra_dns=extra_dns,
valid_to=valid_to,
)
return cert_fn, key_fn

Expand Down
9 changes: 9 additions & 0 deletions docker-jans-certmanager/scripts/client_api_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,18 @@

class ClientApiHandler(BaseHandler):
def generate_x509(self, suffix, cert_cn):
try:
valid_to = int(self.opts.get("valid-to", 365))
except ValueError:
valid_to = 365
finally:
if valid_to < 1:
valid_to = 365

cert_file, key_file = self._patch_cert_key(
suffix,
extra_dns=[cert_cn],
valid_to=valid_to,
)
return cert_file, key_file

Expand Down
10 changes: 9 additions & 1 deletion docker-jans-certmanager/scripts/ldap_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ def generate_x509(self):
alt_name = self.opts.get("subj-alt-name", "localhost")
suffix = "opendj"

self._patch_cert_key(suffix, extra_dns=[alt_name])
try:
valid_to = int(self.opts.get("valid-to", 365))
except ValueError:
valid_to = 365
finally:
if valid_to < 1:
valid_to = 365

self._patch_cert_key(suffix, extra_dns=[alt_name], valid_to=valid_to)

with open("/etc/certs/{}.pem".format(suffix), "w") as fw:
with open("/etc/certs/{}.crt".format(suffix)) as fr:
Expand Down
10 changes: 10 additions & 0 deletions docker-jans-certmanager/scripts/web_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ class WebHandler(BaseHandler):
def patch(self):
source = self.opts.get("source", "")

try:
valid_to = int(self.opts.get("valid-to", 365))
except ValueError:
valid_to = 365
finally:
if valid_to < 1:
valid_to = 365

ssl_cert = "/etc/certs/web_https.crt"
ssl_key = "/etc/certs/web_https.key"
ssl_csr = "/etc/certs/web_https.csr"
Expand Down Expand Up @@ -45,6 +53,7 @@ def patch(self):
country_code,
state,
city,
valid_to=valid_to,
)

logger.info(f"Creating self-generated {ssl_csr}, {ssl_cert}, and {ssl_key}")
Expand All @@ -58,6 +67,7 @@ def patch(self):
country_code,
state,
city,
valid_to=valid_to,
)

if not self.dry_run:
Expand Down
2 changes: 1 addition & 1 deletion docker-jans-client-api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
grpcio==1.41.0
ruamel.yaml==0.16.10
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
2 changes: 1 addition & 1 deletion docker-jans-config-api/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pinned to py3-grpcio version to avoid failure on native extension build
grpcio==1.41.0
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
2 changes: 1 addition & 1 deletion docker-jans-configurator/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ click==6.7
marshmallow==3.10.0
fqdn==1.4.0
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
2 changes: 1 addition & 1 deletion docker-jans-fido2/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pinned to py3-grpcio version to avoid failure on native extension build
grpcio==1.41.0
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
2 changes: 1 addition & 1 deletion docker-jans-persistence-loader/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
grpcio==1.41.0
ldif==4.1.1
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
2 changes: 1 addition & 1 deletion docker-jans-scim/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pinned to py3-grpcio version to avoid failure on native extension build
grpcio==1.41.0
libcst<0.4
git+https://github.com/JanssenProject/jans@5618dd60a340e46377afc20fdc9f9d39248cb1ed#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
git+https://github.com/JanssenProject/jans@2e14ca7dfe600bf1136b4435749a600166328c9f#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
23 changes: 12 additions & 11 deletions jans-pycloudlib/jans/pycloudlib/pki.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,19 @@ def generate_public_key(filename, private_key, is_ca=False, add_san=False, add_k

Keyword arguments:

- ``email``: Email address for subject/issuer.
- ``hostname``: Hostname (common name) for subject/issuer.
- ``org_name``: Organization name for subject/issuer.
- ``country_code``: Country name in ISO format for subject/issuer.
- ``state``: State/province name for subject/issuer.
- ``city``: City/locality name for subject/issuer.
- ``extra_dns``: Additional DNS names (added if ``add_san`` argument is set to ``True``).
- ``extra_ips``: Additional IP addresses (added if ``add_san`` argument is set to ``True``).
- ``email``: Email address for subject/issuer.
- ``hostname``: Hostname (common name) for subject/issuer.
- ``org_name``: Organization name for subject/issuer.
- ``country_code``: Country name in ISO format for subject/issuer.
- ``state``: State/province name for subject/issuer.
- ``city``: City/locality name for subject/issuer.
- ``extra_dns``: Additional DNS names (added if ``add_san`` argument is set to ``True``).
- ``extra_ips``: Additional IP addresses (added if ``add_san`` argument is set to ``True``).
- ``valid_to``: Validity length in days.
"""

valid_from = datetime.utcnow()
valid_to = valid_from + timedelta(days=365)
valid_to = valid_from + timedelta(days=kwargs.get("valid_to", 365))

# issuer equals subject because we use self-signed
subject = issuer = x509.Name([
Expand Down Expand Up @@ -229,7 +230,7 @@ def generate_csr(filename, private_key, add_san=False, add_key_usage=False, **kw
return csr


def sign_csr(filename, csr, ca_private_key, ca_public_key):
def sign_csr(filename, csr, ca_private_key, ca_public_key, **kwargs):
"""Sign a certificate signing request (CSR).

:param filename: Path to signed certificate.
Expand All @@ -239,7 +240,7 @@ def sign_csr(filename, csr, ca_private_key, ca_public_key):
"""

valid_from = datetime.utcnow()
valid_to = valid_from + timedelta(days=365)
valid_to = valid_from + timedelta(days=kwargs.get("valid_to", 365))

builder = (
x509.CertificateBuilder()
Expand Down
98 changes: 89 additions & 9 deletions jans-pycloudlib/jans/pycloudlib/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,35 @@ def decode_text(text: AnyStr, key: AnyStr) -> bytes:
return unpadder.update(padded_data) + unpadder.finalize()


def generate_ssl_certkey(suffix, email, hostname, org_name, country_code,
state, city, base_dir="/etc/certs",
extra_dns=None, extra_ips=None):
def generate_ssl_certkey(
suffix,
email,
hostname,
org_name,
country_code,
state,
city,
base_dir="/etc/certs",
extra_dns=None,
extra_ips=None,
valid_to=365,
):
"""Generate SSL public and private keys.

:param suffix: Suffix as basename (i.e. ``auth-server``)
:param email: Email address for subject/issuer.
:param hostname: Hostname (common name) for subject/issuer.
:param org_name: Organization name for subject/issuer.
:param country_code: Country name in ISO format for subject/issuer.
:param state: State/province name for subject/issuer.
:param city: City/locality name for subject/issuer.
:param base_dir: Directory to store generated public and private keys.
:param extra_dns: Additional DNS names.
:param extra_ips: Additional IP addresses.
:param valid_to: Validity length in days.
:returns: A pair of path to generated public and private keys.
"""

key_fn = f"{base_dir}/{suffix}.key"
priv_key = generate_private_key(key_fn)

Expand All @@ -313,6 +339,7 @@ def generate_ssl_certkey(suffix, email, hostname, org_name, country_code,
org_name=org_name,
extra_dns=extra_dns,
extra_ips=extra_ips,
valid_to=valid_to,
)
return cert_fn, key_fn

Expand Down Expand Up @@ -380,8 +407,30 @@ def generate_keystore(suffix, hostname, keypasswd, jks_fn="", in_key="", in_cert
raise RuntimeError(f"Failed to generate JKS keystore {jks_fn}; reason={err.decode()}")


def generate_ssl_ca_certkey(suffix, email, hostname, org_name, country_code,
state, city, base_dir="/etc/certs"):
def generate_ssl_ca_certkey(
suffix,
email,
hostname,
org_name,
country_code,
state,
city,
base_dir="/etc/certs",
valid_to=365,
):
"""Generate SSL public and private keys for CA.

:param suffix: Suffix as basename (i.e. ``auth-server``)
:param email: Email address for subject/issuer.
:param hostname: Hostname (common name) for subject/issuer.
:param org_name: Organization name for subject/issuer.
:param country_code: Country name in ISO format for subject/issuer.
:param state: State/province name for subject/issuer.
:param city: City/locality name for subject/issuer.
:param base_dir: Directory to store generated public and private keys.
:param valid_to: Validity length in days.
:returns: A pair of path to generated public and private keys.
"""

key_fn = f"{base_dir}/{suffix}.key"
priv_key = generate_private_key(key_fn)
Expand All @@ -397,13 +446,44 @@ def generate_ssl_ca_certkey(suffix, email, hostname, org_name, country_code,
city=city,
email=email,
org_name=org_name,
valid_to=valid_to,
)
return cert_fn, key_fn


def generate_signed_ssl_certkey(suffix, ca_key_fn, ca_cert_fn, email, hostname, org_name,
country_code, state, city, base_dir="/etc/certs",
extra_dns=None, extra_ips=None):
def generate_signed_ssl_certkey(
suffix,
ca_key_fn,
ca_cert_fn,
email,
hostname,
org_name,
country_code,
state,
city,
base_dir="/etc/certs",
extra_dns=None,
extra_ips=None,
valid_to=365,
):
"""Generate SSL public and private keys signed by CA.

:param suffix: Suffix as basename (i.e. ``auth-server``)
:param ca_key_fn: Path to CA private key.
:param ca_cert_fn: Path to CA public key.
:param email: Email address for subject/issuer.
:param hostname: Hostname (common name) for subject/issuer.
:param org_name: Organization name for subject/issuer.
:param country_code: Country name in ISO format for subject/issuer.
:param state: State/province name for subject/issuer.
:param city: City/locality name for subject/issuer.
:param base_dir: Directory to store generated public and private keys.
:param extra_dns: Additional DNS names.
:param extra_ips: Additional IP addresses.
:param valid_to: Validity length in days.
:returns: A pair of path to generated public and private keys.
"""

key_fn = f"{base_dir}/{suffix}.key"
priv_key = generate_private_key(key_fn)

Expand Down Expand Up @@ -435,5 +515,5 @@ def generate_signed_ssl_certkey(suffix, ca_key_fn, ca_cert_fn, email, hostname,
with open(ca_cert_fn, "rb") as f:
ca_cert = x509.load_pem_x509_certificate(f.read())

sign_csr(cert_fn, csr, ca_key, ca_cert)
sign_csr(cert_fn, csr, ca_key, ca_cert, valid_to=valid_to)
return cert_fn, key_fn