Kubernetes Dashboard

  • Canonical Kubernetes
Channel Revision Published Runs on
latest/stable 72 16 Dec 2024
Ubuntu 22.04 Ubuntu 20.04
latest/stable 71 16 Dec 2024
Ubuntu 22.04 Ubuntu 20.04
latest/stable 69 16 Dec 2024
Ubuntu 22.04 Ubuntu 20.04
latest/stable 70 16 Dec 2024
Ubuntu 22.04 Ubuntu 20.04
latest/stable 68 16 Dec 2024
Ubuntu 22.04 Ubuntu 20.04
latest/stable 21 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
latest/candidate 72 13 Dec 2024
Ubuntu 22.04
latest/candidate 71 13 Dec 2024
Ubuntu 22.04
latest/candidate 70 13 Dec 2024
Ubuntu 22.04
latest/candidate 69 13 Dec 2024
Ubuntu 22.04
latest/candidate 68 13 Dec 2024
Ubuntu 22.04
latest/beta 67 14 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/beta 66 14 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/beta 64 14 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/beta 65 14 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/beta 63 14 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/beta 21 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 62 05 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 61 05 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 60 05 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 59 05 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 58 05 Aug 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 21 24 Jul 2023
Ubuntu 22.04 Ubuntu 20.04
1.31/stable 72 16 Dec 2024
Ubuntu 22.04
1.31/stable 71 16 Dec 2024
Ubuntu 22.04
1.31/stable 69 16 Dec 2024
Ubuntu 22.04
1.31/stable 70 16 Dec 2024
Ubuntu 22.04
1.31/stable 68 16 Dec 2024
Ubuntu 22.04
1.31/candidate 72 13 Dec 2024
Ubuntu 22.04
1.31/candidate 71 13 Dec 2024
Ubuntu 22.04
1.31/candidate 70 13 Dec 2024
Ubuntu 22.04
1.31/candidate 69 13 Dec 2024
Ubuntu 22.04
1.31/candidate 68 13 Dec 2024
Ubuntu 22.04
1.31/beta 67 13 Aug 2024
Ubuntu 22.04
1.31/beta 66 13 Aug 2024
Ubuntu 22.04
1.31/beta 65 13 Aug 2024
Ubuntu 22.04
1.31/beta 64 13 Aug 2024
Ubuntu 22.04
1.31/beta 63 13 Aug 2024
Ubuntu 22.04
1.31/edge 62 05 Aug 2024
Ubuntu 22.04
1.31/edge 61 05 Aug 2024
Ubuntu 22.04
1.31/edge 60 05 Aug 2024
Ubuntu 22.04
1.31/edge 59 05 Aug 2024
Ubuntu 22.04
1.31/edge 58 05 Aug 2024
Ubuntu 22.04
1.30/stable 47 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/stable 46 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/stable 44 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/stable 45 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/stable 43 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/stable 21 11 Jul 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/beta 47 19 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/beta 46 19 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/beta 44 19 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/beta 45 19 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/beta 43 19 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/beta 21 19 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/edge 47 13 Mar 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/edge 46 13 Mar 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/edge 44 13 Mar 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/edge 45 13 Mar 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/edge 43 13 Mar 2024
Ubuntu 22.04 Ubuntu 20.04
1.30/edge 21 13 Mar 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/stable 57 17 Apr 2024
Ubuntu 22.04
1.29/stable 56 17 Apr 2024
Ubuntu 22.04
1.29/stable 54 17 Apr 2024
Ubuntu 22.04
1.29/stable 55 17 Apr 2024
Ubuntu 22.04
1.29/stable 53 17 Apr 2024
Ubuntu 22.04
1.29/candidate 57 15 Apr 2024
Ubuntu 22.04
1.29/candidate 56 15 Apr 2024
Ubuntu 22.04
1.29/candidate 55 15 Apr 2024
Ubuntu 22.04
1.29/candidate 54 15 Apr 2024
Ubuntu 22.04
1.29/candidate 53 15 Apr 2024
Ubuntu 22.04
1.29/beta 47 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/beta 46 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/beta 44 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/beta 45 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/beta 43 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/beta 21 17 Apr 2024
Ubuntu 22.04 Ubuntu 20.04
1.29/edge 47 21 Aug 2023
Ubuntu 22.04
1.28/stable 34 22 Aug 2023
Ubuntu 22.04
1.28/stable 32 22 Aug 2023
Ubuntu 22.04
1.28/stable 33 22 Aug 2023
Ubuntu 22.04
1.28/stable 31 22 Aug 2023
Ubuntu 22.04
1.28/stable 35 22 Aug 2023
Ubuntu 22.04
1.28/beta 35 07 Aug 2023
Ubuntu 22.04
1.28/beta 34 07 Aug 2023
Ubuntu 22.04
1.28/beta 33 07 Aug 2023
Ubuntu 22.04
1.28/beta 32 07 Aug 2023
Ubuntu 22.04
1.28/beta 31 07 Aug 2023
Ubuntu 22.04
1.28/edge 47 17 Aug 2023
Ubuntu 22.04 Ubuntu 20.04
1.28/edge 46 17 Aug 2023
Ubuntu 22.04 Ubuntu 20.04
1.28/edge 45 17 Aug 2023
Ubuntu 22.04 Ubuntu 20.04
1.28/edge 44 17 Aug 2023
Ubuntu 22.04 Ubuntu 20.04
1.28/edge 43 17 Aug 2023
Ubuntu 22.04 Ubuntu 20.04
1.28/edge 21 24 Jul 2023
Ubuntu 22.04 Ubuntu 20.04
juju deploy kubernetes-dashboard
Show information

Platform:

charms.kubernetes_dashboard.v0.cert

# Copyright 2021 Canonical Ltd.
# See LICENSE file for licensing details.

"""# Self-Signed Certificate Generator.

This charm library contains a class `SelfSignedCert` which can be used for generating self-signed
RSA certificates for use in TLS connections or otherwise. It does not currently provide much
configurability, apart from the FQDN the certificate should be associated with, a list of IP
addresses to be present in the Subject Alternative Name (SAN) field, validity and key length.

By default, generated certificates are valid for 365 years, and use a 2048-bit key size.

## Getting Started

In order to use this library, you will need to fetch the library from Charmhub as normal, but you
will also need to add a dependency on the `cryptography` package to your charm:

```shell
cd some-charm
charmcraft fetch-lib charms.kubernetes_dashboard.v0.cert
echo <<-EOF >> requirements.txt
cryptography
EOF
```

Once complete, you can import the charm and use it like so (in the most simple form):

```python
# ...
from charms.kubernetes_dashboard.v0.cert import SelfSignedCert
from ipaddress import IPv4Address

# Generate a certificate
self_signed_cert = SelfSigned(names=["test-service.dev"], ips=[IPv4Address("10.28.0.20")])

# Bytes representing the certificate in PEM format
certificate = self_signed_cert.cert

# Bytes representing the private key in PEM/PKCS8 format
key = self_signed_cert.key
```

You can also specify the validity period in days, and the required key size. The algorithm is
always RSA:

```python
# ...
from charms.kubernetes_dashboard.v0.cert import SelfSignedCert
from ipaddress import IPv4Address

# Generate a certificate
self_signed_cert = SelfSigned(
    names=["some_app.my_namespace.svc.cluster.local"],
    ips=[IPv4Address("10.41.150.12"), IPv4Address("192.168.0.20")],
    key_size = 4096,
    validity = 3650
)
```
"""

from datetime import datetime, timedelta
from ipaddress import IPv4Address
from typing import List

from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID

# The unique Charmhub library identifier, never change it
LIBID = "6b649bc0040448399cfc718a6fcba24d"

# Increment this major API version when introducing breaking changes
LIBAPI = 0

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 1


class SelfSignedCert:
    """A class used for generating self-signed RSA TLS certificates."""

    def __init__(
        self,
        *,
        names: List[str],
        ips: List[IPv4Address] = [],
        key_size: int = 2048,
        validity: int = 365,
    ):
        """Initialise a new self-signed certificate.

        Args:
            names: A list of FQDNs that should be placed in the Subject Alternative
                Name field of the certificate. The first name in the list will be
                used as the Common Name, Subject and Issuer field.
            ips: A list of IPv4Address objects that  should be present in the list
                of Subject Alternative Names of the certificate.
            key_size: Size of the RSA Private Key to be generated. Defaults to 2048
            validity: Period in days the certificate is valid for. Default is 365.

        Raises:
            ValueError: is raised if an empty list of names is provided to the
                constructor.
        """
        # Ensure that at least one FQDN was provided
        # TODO: Do some validation on any provided names
        if not names:
            raise ValueError("Must provide at least one name for the certificate")

        # Create a list of x509.DNSName objects from the list of FQDNs provided
        self.names = [x509.DNSName(n) for n in names]
        # Create a list of x509IPAdress objects from the list of IPv4Addresses
        self.ips = [x509.IPAddress(i) for i in ips] if ips else []
        # Initialise some values
        self.key_size = key_size
        self.validity = validity
        self.cert = None
        self.key = None
        # Generate the certificate
        self._generate()

    def _generate(self) -> None:
        """Generate a self-signed certificate."""
        # Generate a new RSA private key
        key = rsa.generate_private_key(public_exponent=65537, key_size=self.key_size)
        # Set the subject/issuer to the first of the given names
        subject = issuer = x509.Name(
            [x509.NameAttribute(NameOID.COMMON_NAME, self.names[0].value)]
        )
        # Build the cert
        cert = (
            x509.CertificateBuilder()
            .subject_name(subject)
            .issuer_name(issuer)
            .public_key(key.public_key())
            .serial_number(x509.random_serial_number())
            .not_valid_before(datetime.utcnow())
            .not_valid_after(datetime.utcnow() + timedelta(days=self.validity))
            .add_extension(
                x509.SubjectAlternativeName(self.names + self.ips),
                critical=False,
            )
            .add_extension(
                x509.KeyUsage(
                    digital_signature=True,
                    key_encipherment=True,
                    key_cert_sign=False,
                    key_agreement=False,
                    content_commitment=False,
                    data_encipherment=False,
                    crl_sign=False,
                    encipher_only=False,
                    decipher_only=False,
                ),
                critical=True,
            )
            .add_extension(
                x509.ExtendedKeyUsage(
                    [
                        x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
                        x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
                    ]
                ),
                critical=False,
            )
            .sign(key, hashes.SHA256())
        )

        self.cert = cert.public_bytes(serialization.Encoding.PEM)
        self.key = key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption(),
        )