diff options
| -rw-r--r-- | hosts/vidhar/prometheus/tls.crt | 12 | ||||
| -rw-r--r-- | tools/ca/ca/__main__.py | 48 |
2 files changed, 51 insertions, 9 deletions
diff --git a/hosts/vidhar/prometheus/tls.crt b/hosts/vidhar/prometheus/tls.crt index f5c682fd..1a5bb7bb 100644 --- a/hosts/vidhar/prometheus/tls.crt +++ b/hosts/vidhar/prometheus/tls.crt | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | -----BEGIN CERTIFICATE----- | 1 | -----BEGIN CERTIFICATE----- |
| 2 | MIIBljCCAUigAwIBAgIPQAAAAGNpZawFYkQ2knHlMAUGAytlcDAfMR0wGwYDVQQD | 2 | MIIBljCCAUigAwIBAgIPQAAAAGNpbKICZnRijYnYMAUGAytlcDAfMR0wGwYDVQQD |
| 3 | DBRwcm9tZXRoZXVzLnlnZ2RyYXNpbDAeFw0yMjExMDcyMDAyMzVaFw0zMjExMDcy | 3 | DBRwcm9tZXRoZXVzLnlnZ2RyYXNpbDAeFw0yMjExMDcyMDMyMTdaFw0zMjExMDcy |
| 4 | MDA3MzVaMBsxGTAXBgNVBAMMEHZpZGhhci55Z2dkcmFzaWwwKjAFBgMrZXADIQAT | 4 | MDM3MTdaMBsxGTAXBgNVBAMMEHZpZGhhci55Z2dkcmFzaWwwKjAFBgMrZXADIQAT |
| 5 | hKYBB3pejSuNg+5zHca4mq25PUBR7CzzUn2BkOesiKOBnjCBmzAfBgNVHSMEGDAW | 5 | hKYBB3pejSuNg+5zHca4mq25PUBR7CzzUn2BkOesiKOBnjCBmzAfBgNVHSMEGDAW |
| 6 | gBRoLn1ecDxcc35XFQG3esmYPTIisjAdBgNVHQ4EFgQURKqOzKvJp9Gh0Pp/24ce | 6 | gBRoLn1ecDxcc35XFQG3esmYPTIisjAdBgNVHQ4EFgQURKqOzKvJp9Gh0Pp/24ce |
| 7 | CKpuTVkwDgYDVR0PAQH/BAQDAgXgMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI | 7 | CKpuTVkwDgYDVR0PAQH/BAQDAgXgMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI |
| 8 | KwYBBQUHAwIwJgYDVR0RBB8wHYIbcHJvbWV0aGV1cy52aWRoYXIueWdnZHJhc2ls | 8 | KwYBBQUHAwEwJgYDVR0RBB8wHYIbcHJvbWV0aGV1cy52aWRoYXIueWdnZHJhc2ls |
| 9 | MAUGAytlcANBANhuOaE//pq/5VuYU4j9FU9nJ8KMb5xTruMZfBpribUvGW9Hhhc1 | 9 | MAUGAytlcANBAK3zsSMHBfdnimTyPeekILvkE/JCTADxPJTzsHrsqenrXTG9G1t7 |
| 10 | 4hIMtXflbPQCn7z6qfmobcw5y0zqRkjjSAk= | 10 | AwHrtfuB8xLGo+Jl2ofSy/Q3nGZDLNX+IQY= |
| 11 | -----END CERTIFICATE----- | 11 | -----END CERTIFICATE----- |
diff --git a/tools/ca/ca/__main__.py b/tools/ca/ca/__main__.py index e3e4bbe6..118b3763 100644 --- a/tools/ca/ca/__main__.py +++ b/tools/ca/ca/__main__.py | |||
| @@ -30,6 +30,7 @@ from tempfile import TemporaryFile | |||
| 30 | import subprocess | 30 | import subprocess |
| 31 | import json | 31 | import json |
| 32 | from leapseconddata import LeapSecondData | 32 | from leapseconddata import LeapSecondData |
| 33 | from collections.abc import Iterable | ||
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | class KeyType(Enum): | 36 | class KeyType(Enum): |
| @@ -76,6 +77,28 @@ class KeyType(Enum): | |||
| 76 | except KeyError: | 77 | except KeyError: |
| 77 | raise ValueError() | 78 | raise ValueError() |
| 78 | 79 | ||
| 80 | class SupportedKeyUsage(Enum): | ||
| 81 | SERVER_AUTH = 'server' | ||
| 82 | CLIENT_AUTH = 'client' | ||
| 83 | |||
| 84 | @property | ||
| 85 | def oid(self): | ||
| 86 | match self: | ||
| 87 | case SupportedKeyUsage.SERVER_AUTH: | ||
| 88 | return ExtendedKeyUsageOID.SERVER_AUTH | ||
| 89 | case SupportedKeyUsage.CLIENT_AUTH: | ||
| 90 | return ExtendedKeyUsageOID.CLIENT_AUTH | ||
| 91 | |||
| 92 | def __str__(self): | ||
| 93 | return self.value | ||
| 94 | |||
| 95 | @classmethod | ||
| 96 | def from_string(cls, s): | ||
| 97 | try: | ||
| 98 | return cls(s) | ||
| 99 | except KeyError: | ||
| 100 | raise ValueError() | ||
| 101 | |||
| 79 | class ValidFQDN(FQDN): | 102 | class ValidFQDN(FQDN): |
| 80 | def __init__(self, *args, **kwds): | 103 | def __init__(self, *args, **kwds): |
| 81 | super().__init__(*args, **kwds) | 104 | super().__init__(*args, **kwds) |
| @@ -133,6 +156,19 @@ class BooleanAction(argparse.Action): | |||
| 133 | def __call__(self, parser, namespace, values, option_string=None): | 156 | def __call__(self, parser, namespace, values, option_string=None): |
| 134 | setattr(namespace, self.dest, False if option_string.startswith('--no') else True) | 157 | setattr(namespace, self.dest, False if option_string.startswith('--no') else True) |
| 135 | 158 | ||
| 159 | class ExtendAction(argparse.Action): | ||
| 160 | def __init__(self, *args, **kwargs): | ||
| 161 | super().__init__(*args, **kwargs) | ||
| 162 | self.reset_dest = False | ||
| 163 | def __call__(self, parser, namespace, values, option_string=None): | ||
| 164 | if not self.reset_dest: | ||
| 165 | setattr(namespace, self.dest, []) | ||
| 166 | self.reset_dest = True | ||
| 167 | if isinstance(values, Iterable): | ||
| 168 | getattr(namespace, self.dest).extend(values) | ||
| 169 | else: | ||
| 170 | getattr(namespace, self.dest).append(values) | ||
| 171 | |||
| 136 | 172 | ||
| 137 | def load_key(keyfile, prompt='CA private key password: '): | 173 | def load_key(keyfile, prompt='CA private key password: '): |
| 138 | key = None | 174 | key = None |
| @@ -294,7 +330,10 @@ def initca(ca_cert, ca_key, key_type, subject, clock_skew, validity, sops): | |||
| 294 | logger.debug('Adjusting permissions for ‘%s’...', ca_cert) | 330 | logger.debug('Adjusting permissions for ‘%s’...', ca_cert) |
| 295 | os.chmod(ca_cert, 0o0444) | 331 | os.chmod(ca_cert, 0o0444) |
| 296 | 332 | ||
| 297 | def signcsr(ca_cert, ca_key, clock_skew, validity, subject, alternative_name, ignore_alternative_names, csr, output): | 333 | def signcsr(ca_cert, ca_key, clock_skew, validity, subject, alternative_name, key_usage, ignore_alternative_names, csr, output): |
| 334 | if not key_usage: | ||
| 335 | raise InvalidParamsError('No extended key usages specified') | ||
| 336 | |||
| 298 | csr_bytes = None | 337 | csr_bytes = None |
| 299 | try: | 338 | try: |
| 300 | csr_bytes = csr.read() | 339 | csr_bytes = csr.read() |
| @@ -348,7 +387,7 @@ def signcsr(ca_cert, ca_key, clock_skew, validity, subject, alternative_name, ig | |||
| 348 | x509.BasicConstraints(ca=False, path_length=None), | 387 | x509.BasicConstraints(ca=False, path_length=None), |
| 349 | True | 388 | True |
| 350 | ).add_extension( | 389 | ).add_extension( |
| 351 | x509.ExtendedKeyUsage([ExtendedKeyUsageOID.CLIENT_AUTH]), | 390 | x509.ExtendedKeyUsage(list(map(lambda ku: ku.oid, key_usage))), |
| 352 | False | 391 | False |
| 353 | ) | 392 | ) |
| 354 | 393 | ||
| @@ -374,7 +413,7 @@ def signcsr(ca_cert, ca_key, clock_skew, validity, subject, alternative_name, ig | |||
| 374 | logger.debug('Adjusting permissions for ‘%s’...', output) | 413 | logger.debug('Adjusting permissions for ‘%s’...', output) |
| 375 | os.chmod(output, 0o0444) | 414 | os.chmod(output, 0o0444) |
| 376 | 415 | ||
| 377 | def new_client(ca_cert, ca_key, key_type, clock_skew, validity, subject, alternative_name, sops, output): | 416 | def new_client(ca_cert, ca_key, key_type, clock_skew, validity, subject, alternative_name, key_usage, sops, output): |
| 378 | key_file = output.with_suffix('.key') | 417 | key_file = output.with_suffix('.key') |
| 379 | cert_file = output.with_suffix('.crt') | 418 | cert_file = output.with_suffix('.crt') |
| 380 | 419 | ||
| @@ -417,6 +456,7 @@ def new_client(ca_cert, ca_key, key_type, clock_skew, validity, subject, alterna | |||
| 417 | validity=validity, | 456 | validity=validity, |
| 418 | subject=None, | 457 | subject=None, |
| 419 | alternative_name=[], | 458 | alternative_name=[], |
| 459 | key_usage=key_usage, | ||
| 420 | ignore_alternative_names=False, | 460 | ignore_alternative_names=False, |
| 421 | output=cert_file, | 461 | output=cert_file, |
| 422 | csr=csr.sign( | 462 | csr=csr.sign( |
| @@ -524,6 +564,7 @@ def main(): | |||
| 524 | subparser.add_argument('--validity', metavar='DURATION', type=duration, default=timedelta(days=ceil(365.2425*10))) | 564 | subparser.add_argument('--validity', metavar='DURATION', type=duration, default=timedelta(days=ceil(365.2425*10))) |
| 525 | subparser.add_argument('--subject', metavar='CN', type=str, required=False) | 565 | subparser.add_argument('--subject', metavar='CN', type=str, required=False) |
| 526 | subparser.add_argument('--ignore-alternative-names', '--no-ignore-alternative-names', action=BooleanAction, default=True) | 566 | subparser.add_argument('--ignore-alternative-names', '--no-ignore-alternative-names', action=BooleanAction, default=True) |
| 567 | subparser.add_argument('--key-usage', metavar='KEY_USAGE', type=SupportedKeyUsage, action=ExtendAction, default=[SupportedKeyUsage.CLIENT_AUTH]) | ||
| 527 | subparser.add_argument('--alternative-name', metavar='CN', type=str, action='append') | 568 | subparser.add_argument('--alternative-name', metavar='CN', type=str, action='append') |
| 528 | subparser.add_argument('--output', type=Path, required=True) | 569 | subparser.add_argument('--output', type=Path, required=True) |
| 529 | subparser.add_argument('csr', metavar='FILE', type=argparse.FileType(mode='rb')) | 570 | subparser.add_argument('csr', metavar='FILE', type=argparse.FileType(mode='rb')) |
| @@ -537,6 +578,7 @@ def main(): | |||
| 537 | subparser.add_argument('--validity', metavar='DURATION', type=duration, default=timedelta(days=ceil(365.2425*10))) | 578 | subparser.add_argument('--validity', metavar='DURATION', type=duration, default=timedelta(days=ceil(365.2425*10))) |
| 538 | subparser.add_argument('--sops', '--no-sops', action=BooleanAction, default=True) | 579 | subparser.add_argument('--sops', '--no-sops', action=BooleanAction, default=True) |
| 539 | subparser.add_argument('--subject', metavar='CN', type=str, required=True) | 580 | subparser.add_argument('--subject', metavar='CN', type=str, required=True) |
| 581 | subparser.add_argument('--key-usage', metavar='KEY_USAGE', type=SupportedKeyUsage, action=ExtendAction, default=[SupportedKeyUsage.CLIENT_AUTH]) | ||
| 540 | subparser.add_argument('--alternative-name', metavar='CN', type=str, action='append') | 582 | subparser.add_argument('--alternative-name', metavar='CN', type=str, action='append') |
| 541 | subparser.add_argument('--output', type=Path, required=True) | 583 | subparser.add_argument('--output', type=Path, required=True) |
| 542 | subparser.set_defaults(cmd=new_client) | 584 | subparser.set_defaults(cmd=new_client) |
