mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
306 lines
15 KiB
Plaintext
306 lines
15 KiB
Plaintext
---
|
|
title: "Kubernetes Issuer"
|
|
description: "Learn how to automatically provision and manage TLS certificates in Kubernetes using Infisical PKI"
|
|
---
|
|
|
|
## Concept
|
|
|
|
The Infisical PKI Issuer is an installable Kubernetes [cert-manager](https://cert-manager.io/) controller that uses Infisical PKI to sign certificate requests. The issuer is perfect for getting X.509 certificates for ingresses and other Kubernetes resources and capable of automatically renewing certificates as needed.
|
|
|
|
As part of the workflow, you install `cert-manager`, the Infisical PKI Issuer, and configure resources to represent the connection details to your Infisical PKI and the certificates you wish to issue. Each issued certificate and corresponding private key is made available in a Kubernetes secret.
|
|
|
|
We recommend reading the [cert-manager documentation](https://cert-manager.io/docs/) for a fuller understanding of all the moving parts.
|
|
|
|
## Workflow
|
|
|
|
A typical workflow for using the Infisical PKI Issuer to issue certificates for your Kubernetes resources consists of the following steps:
|
|
|
|
1. Creating a machine identity in Infisical.
|
|
2. Creating a Kubernetes secret to store the credentials of the machine identity.
|
|
3. Installing `cert-manager` into your Kubernetes cluster.
|
|
4. Installing the Infisical PKI Issuer controller into your Kubernetes cluster.
|
|
5. Creating an `Issuer` or `ClusterIssuer` resource in your Kubernetes cluster to represent the Infisical PKI issuer you wish to use.
|
|
6. Create the approver policy to accept certificate request.
|
|
7. Creating a `Certificate` resource in your Kubernetes cluster to represent a certificate you wish to issue. As part of this step, you specify the Kubernetes `Secret` to create and store the issued certificate and private key.
|
|
8. Consuming the issued certificate across your Kubernetes resources from the specified Kubernetes `Secret`.
|
|
|
|
## Guide
|
|
|
|
In the following steps, we explore how to install the Infisical PKI Issuer using [kubectl](https://github.com/kubernetes/kubectl) and use it to obtain certificates for your Kubernetes resources.
|
|
|
|
<Steps>
|
|
<Step title="Create an identity in Infisical">
|
|
|
|
Follow the instructions [here](/documentation/platform/identities/universal-auth) to configure a [machine identity](/documentation/platform/identities/machine-identities) in Infisical with Universal Auth.
|
|
|
|
By the end of this step, you should have a **Client ID** and **Client Secret** on hand as part of the Universal Auth configuration for the Infisical PKI Issuer to authenticate with Infisical; this will be useful in steps 4 and 5.
|
|
|
|
<Note>
|
|
Currently, the Infisical PKI Issuer only supports authenticating with Infisical via the [Universal Auth](/documentation/platform/identities/universal-auth) authentication method.
|
|
|
|
We're planning to add support for [Kubernetes Auth](/documentation/platform/identities/kubernetes-auth) in the near future.
|
|
</Note>
|
|
</Step>
|
|
<Step title="Install cert-manager">
|
|
Install `cert-manager` into your Kubernetes cluster by following the instructions [here](https://cert-manager.io/docs/installation/) or by running the following command:
|
|
|
|
```bash
|
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.yaml
|
|
```
|
|
</Step>
|
|
<Step title="Install the Issuer Controller">
|
|
Install the Infisical PKI Issuer controller into your Kubernetes cluster using one of the following methods:
|
|
|
|
<Tabs>
|
|
<Tab title="Helm">
|
|
```bash
|
|
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
|
|
helm install infisical-pki-issuer infisical-helm-charts/infisical-pki-issuer
|
|
```
|
|
</Tab>
|
|
<Tab title="kubectl">
|
|
```bash
|
|
kubectl apply -f https://raw.githubusercontent.com/Infisical/infisical-issuer/main/build/install.yaml
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
</Step>
|
|
<Step title="Create Kubernetes Secret for Infisical PKI Issuer">
|
|
Start by creating a Kubernetes `Secret` containing the **Client Secret** from step 1. As mentioned previously, this will be used by the Infisical PKI issuer to authenticate with Infisical.
|
|
|
|
<Tabs>
|
|
<Tab title="kubectl command">
|
|
```bash
|
|
kubectl create secret generic issuer-infisical-client-secret \
|
|
--namespace <namespace_you_want_to_issue_certificates_in> \
|
|
--from-literal=clientSecret=<client_secret>
|
|
```
|
|
</Tab>
|
|
<Tab title="Configuration file">
|
|
```yaml secret-issuer.yaml
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: issuer-infisical-client-secret
|
|
namespace: <namespace_you_want_to_issue_certificates_in>
|
|
data:
|
|
clientSecret: <client_secret>
|
|
```
|
|
|
|
```bash
|
|
kubectl apply -f secret-issuer.yaml
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
</Step>
|
|
<Step title="Create Infisical PKI Issuer">
|
|
Next, create the Infisical PKI Issuer by filling out `url`, `clientId`, `projectId` or `certificateTemplateName`, and applying the following configuration file for the `Issuer` resource.
|
|
This configuration file specifies the connection details to your Infisical PKI CA to be used for issuing certificates.
|
|
|
|
```yaml infisical-issuer.yaml
|
|
apiVersion: infisical-issuer.infisical.com/v1alpha1
|
|
kind: Issuer
|
|
metadata:
|
|
name: issuer-infisical
|
|
namespace: <namespace_you_want_to_issue_certificates_in>
|
|
spec:
|
|
url: "https://app.infisical.com" # the URL of your Infisical instance
|
|
projectId: <project_id> # the ID of the project you want to use to issue certificates
|
|
certificateTemplateName: <certificate_template_name> # the name of the certificate template you want to use to issue certificates against
|
|
authentication:
|
|
universalAuth:
|
|
clientId: <client_id> # the Client ID from step 1
|
|
secretRef: # reference to the Secret created in step 4
|
|
name: "issuer-infisical-client-secret"
|
|
key: "clientSecret"
|
|
```
|
|
|
|
```
|
|
kubectl apply -f infisical-issuer.yaml
|
|
```
|
|
|
|
You can check that the issuer was created successfully by running the following command:
|
|
|
|
```bash
|
|
kubectl get issuers.infisical-issuer.infisical.com -n <namespace_of_issuer> -o wide
|
|
```
|
|
|
|
```bash
|
|
NAME AGE
|
|
issuer-infisical 21h
|
|
```
|
|
|
|
<Note>
|
|
An `Issuer` is a namespaced resource, and it is not possible to issue certificates from an `Issuer` in a different namespace.
|
|
This means you will need to create an `Issuer` in each namespace you wish to obtain `Certificates` in.
|
|
|
|
If you want to create a single `Issuer` that can be consumed in multiple namespaces, you should consider creating a `ClusterIssuer` resource. This is almost identical to the `Issuer` resource, however is non-namespaced so it can be used to issue `Certificates` across all namespaces.
|
|
|
|
You can read more about the `Issuer` and `ClusterIssuer` resources [here](https://cert-manager.io/docs/configuration/).
|
|
</Note>
|
|
</Step>
|
|
<Step title="Create Approver Policy">
|
|
If you create a `CertificateRequest` now, you'll notice it's neither approved nor denied. This is expected because by default cert-manager approver controller requires an approver-policy.
|
|
|
|
To enable approval, create the following YAML file and apply it:
|
|
|
|
```yaml infisical-approver-policy.yaml
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRole
|
|
metadata:
|
|
name: infisical-issuer-approver
|
|
rules:
|
|
# Permission to approve or deny CertificateRequests for signers in cert-manager.io API group
|
|
- apiGroups: ['cert-manager.io']
|
|
resources: ['signers']
|
|
verbs: ['approve']
|
|
resourceNames:
|
|
# Grant approval permissions for namespaced issuers
|
|
- "issuers.infisical-issuer.infisical.com/default.issuer-infisical"
|
|
# Grant approval permissions for cluster-scoped issuers
|
|
- "clusterissuers.infisical-issuer.infisical.com/clusterissuer-infisical"
|
|
---
|
|
# Bind the cert-manager service account to the new role
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRoleBinding
|
|
metadata:
|
|
name: infisical-issuer-approver-binding
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: cert-manager
|
|
namespace: cert-manager
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: ClusterRole
|
|
name: infisical-issuer-approver
|
|
```
|
|
|
|
```
|
|
kubectl apply -f infisical-approver-policy.yaml
|
|
```
|
|
|
|
This configuration creates a `ClusterRole` named `infisical-issuer-approver` that grants approval permissions for specific Infisical issuer types. It then binds this role to the cert-manager service account, allowing it to approve certificate requests from your Infisical issuers.
|
|
|
|
For information, check out [cert manager approval policy doc](https://cert-manager.io/docs/policy/approval/approver-policy/).
|
|
</Step>
|
|
<Step title="Create Certificate">
|
|
|
|
Finally, create a `Certificate` by applying the following configuration file.
|
|
This configuration file specifies the details of the (end-entity/leaf) certificate to be issued.
|
|
|
|
```yaml certificate-issuer.yaml
|
|
apiVersion: cert-manager.io/v1
|
|
kind: Certificate
|
|
metadata:
|
|
name: certificate-by-issuer
|
|
namespace: <namespace_you_want_to_issue_certificates_in>
|
|
spec:
|
|
commonName: certificate-by-issuer.example.com # the common name for the certificate
|
|
secretName: certificate-by-issuer # the name of the Kubernetes Secret to create and store the certificate and private key in
|
|
issuerRef:
|
|
name: issuer-infisical
|
|
group: infisical-issuer.infisical.com
|
|
kind: Issuer
|
|
privateKey: # the algorithm and key size to use
|
|
algorithm: ECDSA
|
|
size: 256
|
|
duration: 48h # the ttl for the certificate
|
|
renewBefore: 12h # the time before the certificate expiry that the certificate should be automatically renewed
|
|
```
|
|
|
|
The above sample configuration file specifies a certificate to be issued with the common name `certificate-by-issuer.example.com` and ECDSA private key using the P-256 curve, valid for 48 hours; the certificate will be automatically renewed by `cert-manager` 12 hours before expiry.
|
|
The certificate is issued by the issuer `issuer-infisical` created in the previous step and the resulting certificate and private key will be stored in a secret named `certificate-by-issuer`.
|
|
|
|
Note that the full list of the fields supported on the `Certificate` resource can be found in the API reference documentation [here](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec).
|
|
|
|
You can check that the certificate was created successfully by running the following command:
|
|
|
|
```bash
|
|
kubectl get certificates -n <namespace_of_your_certificate> -o wide
|
|
```
|
|
|
|
```bash
|
|
NAME READY SECRET ISSUER STATUS AGE
|
|
certificate-by-issuer True certificate-by-issuer issuer-infisical Certificate is up to date and has not expired 20h
|
|
```
|
|
</Step>
|
|
<Step title="Use Certificate in Kubernetes Secret">
|
|
Since the actual certificate and private key are stored in a Kubernetes secret, we can check that the secret was created successfully by running the following command:
|
|
|
|
```bash
|
|
kubectl get secret certificate-by-issuer -n <namespace_of_your_certificate>
|
|
```
|
|
|
|
```bash
|
|
NAME TYPE DATA AGE
|
|
certificate-by-issuer kubernetes.io/tls 2 26h
|
|
```
|
|
|
|
We can `describe` the secret to get more information about it:
|
|
|
|
```bash
|
|
kubectl describe secret certificate-by-issuer -n default
|
|
```
|
|
|
|
```bash
|
|
Name: certificate-by-issuer
|
|
Namespace: default
|
|
Labels: controller.cert-manager.io/fao=true
|
|
Annotations: cert-manager.io/alt-names:
|
|
cert-manager.io/certificate-name: certificate-by-issuer
|
|
cert-manager.io/common-name: certificate-by-issuer.example.com
|
|
cert-manager.io/ip-sans:
|
|
cert-manager.io/issuer-group: infisical-issuer.infisical.com
|
|
cert-manager.io/issuer-kind: Issuer
|
|
cert-manager.io/issuer-name: issuer-infisical
|
|
cert-manager.io/uri-sans:
|
|
|
|
Type: kubernetes.io/tls
|
|
|
|
Data
|
|
====
|
|
ca.crt: 1306 bytes
|
|
tls.crt: 2380 bytes
|
|
tls.key: 227 bytes
|
|
```
|
|
|
|
Here, `ca.crt` is the Root CA certificate, `tls.crt` is the requested certificate followed by the certificate chain, and `tls.key` is the private key for the certificate.
|
|
|
|
We can decode the certificate and print it out using `openssl`:
|
|
|
|
```bash
|
|
kubectl get secret certificate-by-issuer -n default -o jsonpath='{.data.tls\.crt}' | base64 --decode | openssl x509 -text -noout
|
|
```
|
|
|
|
In any case, the certificate is ready to be used as Kubernetes Secret by your Kubernetes resources.
|
|
</Step>
|
|
|
|
</Steps>
|
|
|
|
## FAQ
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="What fields can be configured on the Certificate resource?">
|
|
The full list of the fields supported on the `Certificate` resource can be found in the API reference documentation [here](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec).
|
|
|
|
<Note>
|
|
Currently, not all fields are supported by the Infisical PKI Issuer.
|
|
</Note>
|
|
|
|
</Accordion>
|
|
<Accordion title="Can certificates be renewed automatically?">
|
|
Yes. `cert-manager` will automatically renew certificates according to the `renewBefore` threshold of expiry as
|
|
specified in the corresponding `Certificate` resource.
|
|
|
|
You can read more about the `renewBefore` field [here](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec).
|
|
|
|
</Accordion>
|
|
<Accordion title="Why is my CertificateRequest not being approved, showing 'CertificateRequest has not been approved yet. Ignoring.'?">
|
|
If you see log messages similar to:
|
|
```
|
|
"CertificateRequest has not been approved yet. Ignoring.","controller":"certificaterequest","controllerGroup":"cert-manager.io","controllerKind":"CertificateRequest","CertificateRequest":{"name":"skynet-infisical-rta-rsa2048-1","namespace":"infisical-system"},"namespace":"infisical-system","name":"skynet-infisical-rta-rsa2048-1","reconcileID":"bfb7cad9-d867-45b5-b3a3-0139e731b7a6"}
|
|
```
|
|
This indicates that the `CertificateRequest` has been created, but `cert-manager` has not yet approved it. This typically occurs because a necessary approver policy is missing. Refer to the documentation above to create an approver policy.
|
|
</Accordion>
|
|
</AccordionGroup>
|