diff --git a/doc/source/usertasks/figures/figure_1_cert_manager.png b/doc/source/usertasks/figures/figure_1_cert_manager.png new file mode 100644 index 000000000..fa4393fa0 Binary files /dev/null and b/doc/source/usertasks/figures/figure_1_cert_manager.png differ diff --git a/doc/source/usertasks/figures/figure_2_cert_manager.png b/doc/source/usertasks/figures/figure_2_cert_manager.png new file mode 100644 index 000000000..4abebc405 Binary files /dev/null and b/doc/source/usertasks/figures/figure_2_cert_manager.png differ diff --git a/doc/source/usertasks/figures/figure_3_issuers_dist_cloud.png b/doc/source/usertasks/figures/figure_3_issuers_dist_cloud.png new file mode 100644 index 000000000..3ec853d74 Binary files /dev/null and b/doc/source/usertasks/figures/figure_3_issuers_dist_cloud.png differ diff --git a/doc/source/usertasks/kubernetes/index.rst b/doc/source/usertasks/kubernetes/index.rst index 253cbbcab..dcc83aa8f 100644 --- a/doc/source/usertasks/kubernetes/index.rst +++ b/doc/source/usertasks/kubernetes/index.rst @@ -80,15 +80,17 @@ NodePort usage restrictions nodeport-usage-restrictions ------------- -Cert Manager ------------- +---------------------- +Certificate Management +---------------------- .. toctree:: :maxdepth: 1 kubernetes-user-tutorials-cert-manager letsencrypt-example + internal-ca-and-nodeport-example-2afa2a84603a + issuers-in-distributed-cloud-fbc035675c0f -------------------------------- Vault secret and data management diff --git a/doc/source/usertasks/kubernetes/internal-ca-and-nodeport-example-2afa2a84603a.rst b/doc/source/usertasks/kubernetes/internal-ca-and-nodeport-example-2afa2a84603a.rst new file mode 100644 index 000000000..88a440fcb --- /dev/null +++ b/doc/source/usertasks/kubernetes/internal-ca-and-nodeport-example-2afa2a84603a.rst @@ -0,0 +1,155 @@ +.. _internal-ca-and-nodeport-example-2afa2a84603a: + +================================ +Internal CA and NodePort Example +================================ + +This section provides an example of how to configure an application to use +NodePort to expose its self-managed |TLS|-based service and to use an Internal +|CA| for signing CERTIFICATEs. + +Note that alternatively an External |CA| could be used with a NodePort-based +solution as well. + +.. rubric:: |prereq| + +This example requires that: + +- Ensure that your |prod| administrator has enabled use of the + cert-manager apiGroups in your |RBAC| policies. + +.. rubric:: |proc| + +#. Create an internal RootCA ISSUER in the default namespace by applying the + following manifest file. + + .. code-block:: none + + # Create a cluster-wide ISSUER for create self-signed certificates + --- + apiVersion: cert-manager.io/v1alpha2 + kind: ClusterIssuer + metadata: + name: system-selfsigning-issuer + spec: + selfSigned: {} + + + # Create a Certificate (and key) for my RootCA + --- + apiVersion: cert-manager.io/v1alpha2 + kind: Certificate + metadata: + name: abccompany-starlingx-rootca-certificate + spec: + secretName: abccompany-starlingx-rootca-certificate + duration: 8640h + commonName: "abccompany-starlingx-rootca" + isCA: true + issuerRef: + name: system-selfsigning-issuer + kind: ClusterIssuer + + + # Create the RootCA ISSUER + --- + apiVersion: cert-manager.io/v1alpha2 + kind: Issuer + metadata: + name: abccompany-starlingx-rootca-issuer + spec: + ca: + secretName: abccompany-starlingx-rootca-certificate + +#. Share the public certificate of your internal RootCA to clients such that + they can trust certificates signed by this RootCA. + + .. code-block:: none + + CERT64=`kubectl get secret abccompany-starlingx-rootca-certificate -n default -o yaml | fgrep tls.crt | fgrep -v "f:tls.crt" | awk '{print $2}'` + echo $CERT64 | base64 --decode > abccompany-starlingx-rootca-certificate.pem + +#. Create a deployment of an example demo application that uses NodePort to + expose its service and therefore manages its |TLS| connection on its own, + using a certificate it creates on its own. + + Apply the following manifest. + + Where ``10.10.10.45`` is the |OAM| Floating IP of the |prod| and + ``abccompany-starlingx.mycompany.com`` is the |FQDN| for this address. + + (You should substitute with the IP Address and |FQDN| for the |prod| + installation.) + + .. code-block:: none + + apiVersion: cert-manager.io/v1alpha2 + kind: Certificate + metadata: + name: abccompany-starlingx.mycompany.com-certificate + spec: + duration: 2160h # 90d + renewBefore: 360h # 15d + secretName: abccompany-starlingx.mycompany.com-certificate + issuerRef: + name: abccompany-starlingx-rootca-issuer + kind: Issuer + commonName: abccompany-starlingx.mycompany.com + organization: + - abccompany-starlingx + dnsNames: + - abccompany-starlingx.mycompany.com + ipAddresses: + - 10.10.10.45 + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: example-app + spec: + replicas: 1 + selector: + matchLabels: + app: example-app + template: + metadata: + labels: + app: example-app + spec: + containers: + - name: example-app + image: example-app # not a real app, could substitute ‘busybox’ here to look at mounted cert files inside container + imagePullPolicy: Always + ports: + - containerPort: 8443 + protocol: TCP + volumeMounts: + - name: mycert + mountPath: "/etc/mycert" # the files tls.crt, tls.key and ca.crt will be under /etc/mycert/ in container + readOnly: true + volumes: + - name: mycert + secret: + secretName: abccompany-starlingx.mycompany.com-certificate + --- + apiVersion: v1 + kind: Service + metadata: + name: example-app + labels: + app: example-app + spec: + type: NodePort + ports: + - port: 443 + protocol: TCP + targetPort: 8443 + nodePort: 31118 + selector: + app: example-app + +#. If example-app existed, you would access it from your browser + with ``https://abccompany-starlingx.mycompany.com:31118``. + + If you are using busybox to look at mounted cert files, attach to container + (e.g. ``kubectl exec busybox-... -it -- sh`` and ``cd /etc/mycert; ls``). diff --git a/doc/source/usertasks/kubernetes/issuers-in-distributed-cloud-fbc035675c0f.rst b/doc/source/usertasks/kubernetes/issuers-in-distributed-cloud-fbc035675c0f.rst new file mode 100644 index 000000000..8031085da --- /dev/null +++ b/doc/source/usertasks/kubernetes/issuers-in-distributed-cloud-fbc035675c0f.rst @@ -0,0 +1,53 @@ +.. _issuers-in-distributed-cloud-fbc035675c0f: + +============================ +Issuers in Distributed Cloud +============================ + +In a Distributed Cloud environment, end-user’s applications have a number of +options for the cert-manager ISSUERs they use: + +- (Recommended) As part of your application deployment on each subcloud, + create a cert-manager ISSUER for the External |CA| that you wish to use for + signing your certificates. + + - The External |CA|-type ISSUER is configured exactly the same way for + each of your application deployments on each subcloud, and + + - Your external clients need only trust a single External |CA|’s public + certificate. + +- As part of your application deployment on each subcloud, create a local + internal RootCA ``ca`` ISSUER for signing your certificates. + + - The local internal RootCA ``ca`` ISSUER should ideally be slightly + different (e.g. a unique subject) on each deployment, and + + - Your external clients need to trust each application deployment’s (on + each subcloud) local internal RootCA public certificate. + + - This option is not ideal since this could mean 100s of RootCA + Certificates. + +.. - As part of your application deployment on each subcloud, use the + |prod|’s Intermediate |CA| ISSUER for that subcloud + + - In a Distributed Cloud environment, |prod| manages a + hierarchy of |CAs|, anchored by a single RootCA at the + System Controller. + + See below: + + .. figure:: /usertasks/figures/figure_3_issuers_dist_cloud.png + :scale: 100% + + The RootCA Certificate and Intermediate |CA| Certificates are + created/renewed automatically by |prod|. + + - Your end-user’s application deployment on a subcloud can simply + create/sign CERTIFICATEs using the |prod|’s + DC-AdminEp-Intermediate-CA on the subcloud. + + - Your external clients need only trust the single |prod| + DC-AdminEp-Root-|CA|’s public certificate on the system Controller. + diff --git a/doc/source/usertasks/kubernetes/kubernetes-user-tutorials-cert-manager.rst b/doc/source/usertasks/kubernetes/kubernetes-user-tutorials-cert-manager.rst index 82b7fab66..06cf8f700 100644 --- a/doc/source/usertasks/kubernetes/kubernetes-user-tutorials-cert-manager.rst +++ b/doc/source/usertasks/kubernetes/kubernetes-user-tutorials-cert-manager.rst @@ -2,64 +2,161 @@ .. iac1588347002880 .. _kubernetes-user-tutorials-cert-manager: -============ -Cert Manager -============ +====================== +Certificate Management +====================== -|prod| integrates the open source project cert-manager. +|prod| integrates the open source project cert-manager +(http://cert-manager.io), in order to provide certificate management support +for end-users’ containerized applications. + +------------------ +Cert Manager Modes +------------------ Cert-manager is a native Kubernetes certificate management controller, that -supports certificate management with external certificate authorities \(CAs\). -nginx-ingress-controller is also integrated with |prod| in support of http-01 -challenges from CAs as part of cert-manager certificate requests. +supports the following general modes of operation: -For more information about Cert Manager, see `cert-manager.io -`__. +- Interacting with External Certificate Authorities (|CAs|) -.. _kubernetes-user-tutorials-cert-manager-section-lz5-gcw-nlb: + In this mode, a cert-manager ISSUER is configured to interact with an + External |CA| of a particular type. External |CA| types supported by + cert-manager are ACME, Vault or Venafi (note that |prod| has only + tested and validated cert-manager with ACME |CAs|). ------------------------------------- -Prerequisites for using Cert Manager ------------------------------------- + When a cert-manager CERTIFICATE is created using this External |CA| ISSUER, + cert-manager -.. _kubernetes-user-tutorials-cert-manager-ul-rd3-3cw-nlb: + - creates the private key and public certificate, -- Ensure that your |prod| administrator has shared the local registry's - public repository's credentials/secret with the namespace where you will - create certificates,. This will allow you to leverage the - ``registry.local:9001/public/cert-manager-acmesolver`` image. + - sends the Certificate Signing Request to the External |CA| using the + appropriate protocol for the type of External |CA|, and -- Ensure that your |prod| administrator has enabled use of the - cert-manager apiGroups in your RBAC policies. + - responds to any challenges (as specified in the CERTIFICATE specs) from + the |CA| -.. _kubernetes-user-tutorials-cert-manager-section-y5r-qcw-nlb: + The signed certificate is made available in a Kubernetes SECRET specified + in the CERTIFICATE spec. ----------------------------------------------- -Resources on Creating Issuers and Certificates ----------------------------------------------- + Cert-Manager will also automatically monitor CERTIFICATE expiry dates and + automatically send an updated Certificate Signing Request messages to the + External |CA|, prior to expiry of the CERTIFICATE (as specified in the + CERTIFICATE specs), in order to renew the CERTIFICATE and update the + Kubernetes SECRET holding the certificate. -.. _kubernetes-user-tutorials-cert-manager-ul-uts-5cw-nlb: + .. figure:: /usertasks/figures/figure_1_cert_manager.png + :scale: 100% -- Configuration documentation: +- Providing an Internal Certificate Authority - - `https://cert-manager.io/docs/configuration - `__/ + In this mode, a cert-manager ``selfsigned`` type ISSUER and ``ca`` type + ISSUER provides a non-challenging Root |CA| for signing certificates local to + the Kubernetes cluster. - This link provides details on creating different types of certificate - issuers or CAs. + A ``selfsigned`` type ISSUER is created to automatically create a private key + and certificate pair for the internal Root |CA|. -- Usage documentation: + Then a ``ca`` type ISSUER is created with this generated Root |CA|’s + private-key/certificate pair for signing. - - `https://cert-manager.io/docs/usage/certificate/ - `__ + When a cert-manager CERTIFICATE is created using this Internal ``ca`` + ISSUER, cert-manager - This link provides details on creating a standalone certificate. + - creates the private key and public certificate, and - - `https://cert-manager.io/docs/usage/ingress/ - `__ + - simply signs the certificate with the ``ca`` ISSUER’s + private-key/certificate pair. - This link provides details on adding a cert-manager annotation to an - Ingress in order to specify the certificate issuer for the ingress to - use to request the certificate for its https connection. + The signed certificate is made available in a Kubernetes SECRET specified + in the CERTIFICATE spec. -- :ref:`LetsEncrypt Example ` + Again, cert-Manager will automatically monitor CERTIFICATE expiry dates and + automatically request the internal ``ca`` ISSUER to sign an updated + certificate, prior to expiry of the CERTIFICATE (as specified in the + CERTIFICATE specs), in order to renew the CERTIFICATE and update the + Kubernetes SECRET holding the certificate. + + .. figure:: /usertasks/figures/figure_2_cert_manager.png + :scale: 100% + +- Combination of the above two modes + + For example in a particular RootCA - IntermediateCA - Server certificate + chain, + + - The RootCA ISSUER in cert-manager could be of type ``acme`` for + requesting the IntermediateCAs certificate from an external ACME |CA|, + + - While the IntermediateCA ISSUER in cert-manager could be of type ``ca`` + for signing the server certificates based on the intermediateCA + certificate (from the external ACME |CA|). + +--------------------------------------------------- +Using Cert Manager CERTIFICATES in your Application +--------------------------------------------------- + +How CERTIFICATEs (and their |TLS| type SECRETs) are created and integrated into +an end-user’s application depends on how the end-user has chosen to expose its +service externally. There are typically two options: + +- The end-user’s application uses ingress controller to expose its service + (the most common approach) + + In this scenario, the end-user’s application uses |prod|’s + integrated nginx ingress-controller to both originate/terminate the HTTPS + connection as well as deal with cert-manager for requesting the required + CERTIFICATE. + + Specifically, in this scenario, the end-user’s application’s helm chart or + yaml file must + + - create an INGRESS object that + + - specifies the details on ingress forwarding based on the URL + (hostname, port and path), and + + - specifies ``|TLS|`` mode along with cert-manager -specific + annotations for details on creating the CERTIFICATE for this + ingress connection with cert-manager; minimally the cert-manager + ISSUER to use must be specified. + + Nginx Ingress Controller will automatically detect when cert-manager renews + the server certificate and update its HTTPS connection to use the new + certificate. + + The end-user’s application does not deal with HTTPS or certificates at all. + +- The end-user’s application exposes its service with a NodePort and + originates/terminates HTTPS itself + + In this scenario, the end-user’s application is originating/terminating + HTTPS on its own, so it needs access to the Kubernetes SECRET holding the + |TLS| certificate, in order to establish the HTTPS connection. + + In this scenario, the end-user’s application’s helm chart or yaml file must + + - create the CERTIFICATE (referencing the desired ISSUER to use, and + indicating the SECRET to store the certificate in), + + - include the SECRET as a mounted volume in the pod spec + + - such that the application’s container can access the |TLS| + certificate as a |PEM| file for use in establishing the HTTPS + connection. + + Note that in this scenario, the application’s container must detect when + the mounted SECRET file changes due to cert-manager auto-renewing the + CERTIFICATE (and the associated SECRET), and update its HTTPS connection to + use the updated certificate. + +.. seealso:: + + See :ref:`External CA and Ingress Controller Example ` + section for an example of how to configure an application to use Ingress + Controller to both expose its TLS-based service and to use an External |CA| + for signing CERTIFICATEs. + + See :ref:`Internal CA and NodePort Example + ` section for an example of + how to configure an application to use NodePort to expose its self-managed + |TLS|-based service and to use an Internal |CA| for signing CERTIFICATEs. diff --git a/doc/source/usertasks/kubernetes/letsencrypt-example.rst b/doc/source/usertasks/kubernetes/letsencrypt-example.rst index 440757682..ed9f78436 100644 --- a/doc/source/usertasks/kubernetes/letsencrypt-example.rst +++ b/doc/source/usertasks/kubernetes/letsencrypt-example.rst @@ -2,11 +2,16 @@ .. nst1588348086813 .. _letsencrypt-example: -=================== -LetsEncrypt Example -=================== +========================================== +External CA and Ingress Controller Example +========================================== -The LetsEncrypt example illustrates cert-manager usage. +This section describes how to configure an application to use Ingress +Controller to both expose its |TLS|-based service and to use an External |CA| +for signing CERTIFICATEs. + +NOTE that alternatively an Internal |CA| could be used with an Ingress +Controller -based solution as well. .. rubric:: |prereq| @@ -14,15 +19,28 @@ This example requires that: .. _letsencrypt-example-ul-h3j-f2w-nlb: -- the LetsEncrypt CA in the public internet can send an http01 challenge to - the FQDN of your |prod|'s floating OAM IP Address. +- The LetsEncrypt |CA| in the public internet can send an http01 challenge to + the |FQDN| of the |prod|'s floating |OAM| IP Address. -- your |prod| has access to the kuard demo application at - gcr.io/kuar-demo/kuard-amd64:blue +- The |prod| has access to the kuard demo application at + `gcr.io/kuar-demo/kuard-amd64:blue `__ + +- Ensure that your |prod| administrator has shared the local + registry’s public repository’s credentials/secret with the namespace where + you will create certificates. This will allow you to leverage the + :command:`registry.local:9001/public/cert-manager-acmesolver` image. See + :ref:`Set up a Public Repository in Local Docker Registry + `. + +- Ensure that your |prod| administrator has enabled use of the + cert-manager apiGroups in your |RBAC| policies. + +- Ensure that your |prod| administrator has opened port 80 and 443 in + GlobalNetworkPolicy. .. rubric:: |proc| -#. Create a LetsEncrypt Issuer in the default namespace by applying the +#. Create a LetsEncrypt ISSUER in the default namespace by applying the following manifest file. .. code-block:: none @@ -48,10 +66,15 @@ This example requires that: #. Create a deployment of the kuard demo application \(`https://github.com/kubernetes-up-and-running/kuard - `__\) with an ingress + `__\) with an INGRESS using cert-manager by applying the following manifest file: - Substitute values in the example as required for your environment. + Where both ``starlingx.mycompany.com`` and + ``kuard.starlingx.mycompany.com`` are |FQDNs| that map to the |OAM| + Floating IP of |prod|. + + (You should substitute these for |FQDNs| for the |prod| installation.) + .. parsed-literal:: @@ -101,10 +124,10 @@ This example requires that: spec: tls: - hosts: - - kuard.my-fqdn-for-|prefix|.company.com + - kuard.starlingx.mycompany.com secretName: kuard-ingress-tls rules: - - host: kuard.my-fqdn-for-|prefix|.company.com + - host: kuard.starlingx.mycompany.com http: paths: - backend: @@ -113,5 +136,5 @@ This example requires that: path: / #. Access the kuard demo from your browser to inspect and verify that the - certificate is signed by LetsEncrypt CA. For this example, the URL - would be https://kuard.my-fqdn-for-|prefix|.company.com. + certificate is signed by LetsEncrypt |CA|. For this example, the URL + would be https://kuard.starlingx.mycompany.com.