diff --git a/.spelling b/.spelling index 17697568cc2..c46d967f388 100644 --- a/.spelling +++ b/.spelling @@ -79,6 +79,7 @@ HTTPRoute HashiCorp Helmfile IAM +IdP INWX IPs IPv6 @@ -94,6 +95,7 @@ KUARD Kirill-Garbar Knative Krew +kuard KubeCon Kubernetes Kyverno @@ -116,9 +118,11 @@ OperatorHub.io PEM PKCS#12 PKCS#8 +Pomerium PowerShell Prometheus RBAC +Redis RFC2136 RFC8555 RR @@ -257,6 +261,7 @@ namespace namespaced namespaces ndegory +oauth2 openshift-supported-versions powershell pre diff --git a/content/en/docs/tutorials/_index.md b/content/en/docs/tutorials/_index.md index dedf6cb860e..71ecdca346c 100644 --- a/content/en/docs/tutorials/_index.md +++ b/content/en/docs/tutorials/_index.md @@ -10,7 +10,8 @@ for you to learn from. Take a look! - [Backup and Restore Resources](./backup/): Backup the cert-manager resources in your cluster and then restore them. -- [Securing Ingresses with NGINX-Ingress and cert-manager](./acme/ingress/): Tutorial for deploying NGINX into your +- [Pomerium Ingress](./acme/pomerium-ingress/): Tutorial on using the Pomerium Ingress Controller with cert-manager. +- [Securing Ingresses with NGINX-Ingress and cert-manager](./acme/nginx-ingress/): Tutorial for deploying NGINX into your cluster and securing incoming connections with a certificate from Let's Encrypt. - [Issuing an ACME Certificate using DNS Validation](./acme/dns-validation/): Tutorial on how to resolve DNS ownership validation using DNS01 challenges. diff --git a/content/en/docs/tutorials/acme/example/pomerium-certificates.yaml b/content/en/docs/tutorials/acme/example/pomerium-certificates.yaml new file mode 100644 index 00000000000..7e07111417d --- /dev/null +++ b/content/en/docs/tutorials/acme/example/pomerium-certificates.yaml @@ -0,0 +1,36 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: pomerium-cert + namespace: pomerium +spec: + secretName: pomerium-tls + issuerRef: + name: pomerium-issuer + kind: Issuer + usages: + - server auth + - client auth + dnsNames: + - pomerium-proxy.pomerium.svc.cluster.local + - pomerium-authorize.pomerium.svc.cluster.local + - pomerium-databroker.pomerium.svc.cluster.local + - pomerium-authenticate.pomerium.svc.cluster.local +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: pomerium-redis-cert + namespace: pomerium +spec: + secretName: pomerium-redis-tls + issuerRef: + name: pomerium-issuer + kind: Issuer + usages: + - server auth + - client auth + dnsNames: + - pomerium-redis-master.pomerium.svc.cluster.local + - pomerium-redis-headless.pomerium.svc.cluster.local + - pomerium-redis-replicas.pomerium.svc.cluster.local diff --git a/content/en/docs/tutorials/acme/example/pomerium-production-issuer.yaml b/content/en/docs/tutorials/acme/example/pomerium-production-issuer.yaml new file mode 100644 index 00000000000..5cedb91f068 --- /dev/null +++ b/content/en/docs/tutorials/acme/example/pomerium-production-issuer.yaml @@ -0,0 +1,18 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: letsencrypt-prod +spec: + acme: + # The ACME server URL + server: https://acme-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: user@example.com + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: letsencrypt-prod + # Enable the HTTP-01 challenge provider + solvers: + - http01: + ingress: + class: pomerium \ No newline at end of file diff --git a/content/en/docs/tutorials/acme/example/pomerium-staging-issuer.yaml b/content/en/docs/tutorials/acme/example/pomerium-staging-issuer.yaml new file mode 100644 index 00000000000..54862cd3451 --- /dev/null +++ b/content/en/docs/tutorials/acme/example/pomerium-staging-issuer.yaml @@ -0,0 +1,18 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: letsencrypt-staging +spec: + acme: + # The ACME server URL + server: https://acme-staging-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: user@example.com + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: letsencrypt-staging + # Enable the HTTP-01 challenge provider + solvers: + - http01: + ingress: + class: pomerium \ No newline at end of file diff --git a/content/en/docs/tutorials/acme/example/pomerium-values.yaml b/content/en/docs/tutorials/acme/example/pomerium-values.yaml new file mode 100644 index 00000000000..2460377547d --- /dev/null +++ b/content/en/docs/tutorials/acme/example/pomerium-values.yaml @@ -0,0 +1,39 @@ +authenticate: + existingTLSSecret: pomerium-tls + idp: + provider: "google" + clientID: YOUR_CLIENT_ID + clientSecret: YOUR_SECRET + serviceAccount: YOUR_SERVICE_ACCOUNT + ingress: + annotations: + cert-manager.io/issuer: letsencrypt-staging + tls: + secretName: authenticate.localhost.pomerium.io-tls + +proxy: + existingTLSSecret: pomerium-tls + +databroker: + existingTLSSecret: pomerium-tls + storage: + clientTLS: + existingSecretName: pomerium-redis-tls + existingCASecretKey: ca.crt + +authorize: + existingTLSSecret: pomerium-tls + +redis: + enabled: true + generateTLS: false + tls: + certificateSecret: pomerium-redis-tls + +ingressController: + enabled: true + +config: + rootDomain: localhost.pomerium.io #Change this to your reserved domain space. + existingCASecret: pomerium-tls + generateTLS: false # On by default, disabled when cert-manager or another solution is in place. diff --git a/content/en/docs/tutorials/acme/ingress.md b/content/en/docs/tutorials/acme/nginx-ingress.md similarity index 100% rename from content/en/docs/tutorials/acme/ingress.md rename to content/en/docs/tutorials/acme/nginx-ingress.md diff --git a/content/en/docs/tutorials/acme/pomerium-ingress.md b/content/en/docs/tutorials/acme/pomerium-ingress.md new file mode 100644 index 00000000000..64580505601 --- /dev/null +++ b/content/en/docs/tutorials/acme/pomerium-ingress.md @@ -0,0 +1,280 @@ +--- +title: "Pomerium Ingress" +linkTitle: "Pomerium Ingress" +weight: 50 +type: "docs" +--- + +This tutorial covers installing the [Pomerium Ingress Controller](https://pomerium.com/docs/k8s/ingress.html) and securing it with cert-manager. [Pomerium](https://pomerium.com) is an identity-aware proxy that can also provide a custom ingress controller for your Kubernetes services. + +## Prerequisites + +1. Install [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and set the context to the cluster you'll be working with. + +1. Install Helm on your local computer. See [Installing Helm](https://helm.sh/docs/intro/install/) for the best installation method for your operating system. + +1. Pomerium connects to an identity provider (**IdP**) to authenticate users. See one of their [guides](https://www.pomerium.com/docs/identity-providers/) to learn how to set up your IdP of choice to provide oauth2 validation. + +1. This tutorial assumes you have a domain space reserved for this cluster (such as `*.cluster.example.com`). You will need access to DNS for this domain to assign A and CNAME records as needed. + +## Install cert-manager + +1. Create a namespace for cert-manager: + + ```bash + kubectl create namespace cert-manager + ``` + +1. Add the `jetstack` repository and update Helm: + + ```bash + helm repo add jetstack https://charts.jetstack.io + helm repo update + ``` + +1. Install cert-manager to your cluster: + + ```bash + helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace \ + --set installCRDs=true + ``` + +1. Confirm deployment with `kubectl get pods --namespace cert-manager`: + + ```bash + kubectl get pods --namespace cert-manager + NAME READY STATUS RESTARTS AGE + cert-manager-5d7f97b46d-8g942 1/1 Running 0 33s + cert-manager-cainjector-69d885bf55-6x5v2 1/1 Running 0 33s + cert-manager-webhook-8d7495f4-s5s6p 1/1 Running 0 33s + ``` + +## Configure a Private Certificate Issuer + +For secure communication between Pomerium services, create a private certificate issuer. This issuer will reside in the `pomerium` namespace, which we will use when creating the Ingress Controller. The certificates issued will only be used for communication between Pomerium components. + +1. Define an issuer in the file `pomerium-issuer.yaml`: + + ```yaml + apiVersion: cert-manager.io/v1 + kind: Issuer + metadata: + name: pomerium-ca + namespace: pomerium + spec: + selfSigned: {} + --- + apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: pomerium-ca + namespace: pomerium + spec: + isCA: true + secretName: pomerium-ca + commonName: pomerium ca + issuerRef: + name: pomerium-ca + kind: Issuer + --- + apiVersion: cert-manager.io/v1 + kind: Issuer + metadata: + name: pomerium-issuer + namespace: pomerium + spec: + ca: + secretName: pomerium-ca + ``` + +1. Deploy the issuer: + + ```bash + kubectl apply -f pomerium-issuer.yaml + ``` + +## Configure Let's Encrypt Issuer + +For communication between the Ingresses and the internet, we'll want to use certificates signed by a trusted certificate authority like Let's Encrypt. This example creates two Let's Encrypt issuers, one for staging and one for production. + +The Let's Encrypt production issuer has [strict rate limits](https://letsencrypt.org/docs/rate-limits/). Before your configuration is finalized you may have to recreate services several times, hitting those limits. It's easy to confuse rate limiting with errors in configuration or operation while building your stack. + +Because of this, we will start with the Let's Encrypt staging issuer. Once your configuration is all but finalized, we will switch to a production issuer. Both of these issuers are configured to use the [`HTTP01`](../../../configuration/acme/http01/) challenge provider. +
    +
  1. + +The following YAML defines a staging certificate issuer. You must update the email address to your own. The `email` field is required by Let's Encrypt and used to notify you of certificate expiration and updates. + +{{% include file="../example/pomerium-staging-issuer.yaml" language="yaml" %}} + +You can download and edit the example and apply it with `kubectl apply -f`, or edit, and apply the custom resource in one command: + +```bash +kubectl create --edit -f https://cert-manager.io/docs/tutorials/acme/example/pomerium-staging-issuer.yaml +``` +
  2. +
  3. + +Create a production issuer and deploy it. As with the staging issuer, update this example with your own email address: + +{{% include file="../example/pomerium-production-issuer.yaml" language="yaml" %}} + +```bash +kubectl create --edit -f https://cert-manager.io/docs/tutorials/acme/example/pomerium-production-issuer.yaml +``` +
  4. +
+ +You can confirm on the status of the issuers after you create them: + +```bash +kubectl describe issuer letsencrypt-staging +kubectl describe issuer letsencrypt-prod +``` + +You should see the issuer listed with a registered account. + + +## Install The Pomerium Ingress Controller + +
    +
  1. + +Set your `kubectl` context to the Pomerium namespace: + +```bash +kubectl config set-context --current --namespace=pomerium +``` + +
  2. + +Create certificate configurations for Pomerium. Our example is named `pomerium-certificates.yaml`: + +{{% include file="../example/pomerium-certificates.yaml" language="yaml" %}} + +Replace `localhost.pomerium.io` with the domain name you'll assign to the Ingress. Keep the subdomain `authenticate`. + +This example defines 2 certificates: + - One using the self-signed `pomerium-issuer` to encrypt traffic between Pomerium's services, + - One using the self-signed `pomerium-issuer` to encrypt traffic to and from the Redis service(s) used by Pomerium. + +Additional certificates will be issued as new Ingresses are created. +
  3. + +Apply the certificate configuration, and confirm: + +```bash +kubectl apply -f pomerium-certificates.yaml +``` + +```bash +kubectl get certificate +NAME READY SECRET AGE +pomerium-ca True pomerium-ca 10s +pomerium-cert True pomerium-tls 10s +pomerium-redis-cert True pomerium-redis-tls 10s +``` + +
  4. + +Create a values file for Helm to use when installing Pomerium. Our example is named `pomerium-values.yaml`. + +{{% include file="../example/pomerium-values.yaml" language="yaml" %}} + +The options required in the `authenticate.idp` block will vary depending on your identity provider. + +Update `config.rootDomain` to match your domain space. + +
  5. + +Add Pomerium's Helm repo: + +```bash +helm repo add pomerium https://helm.pomerium.io +``` + +
  6. + +Install Pomerium to the cluster: + +```bash +helm upgrade --install pomerium pomerium/pomerium --values ./pomerium-values.yaml +``` + +
  7. + +Use `kubectl` to confirm that the Pomerium Proxy has stood up, and get the external IP needed to route your domain space to the cluster: + +```bash +kubectl get svc pomerium-proxy +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +pomerium-proxy LoadBalancer 10.128.117.25 192.0.2.20 443:30006/TCP,9090:30707/TCP 2m37s +``` + +
+ +## Define a Test Service + +To test our new Ingress Controller, we will add the [kuard](https://github.com/kubernetes-up-and-running/kuard) app to our cluster and define an Ingress for it. + +
  1. + +Define the kuard deployment and associated service: + +{{% include file="../example/deployment.yaml" language="yaml" %}} + +{{% include file="../example/service.yaml" language="yaml" %}} + +You can download and reference these files locally, or you can reference them from the GitHub source repository for this documentation. + +To install the example service from the tutorial files straight from GitHub: + +```bash +kubectl apply -f https://cert-manager.io/docs/tutorials/acme/example/deployment.yaml +kubectl apply -f https://netlify.cert-manager.io/docs/tutorials/acme/example/service.yaml +``` +
  2. + +Create a new Ingress manifest (`example-ingress.yaml`) for our test service: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: kuard + annotations: + cert-manager.io/issuer: letsencrypt-staging + ingress.pomerium.io/policy: '[{"allow":{"and":[{"domain":{"is":"example.com"}}]}}]' +spec: + ingressClassName: pomerium + rules: + - host: kuard.localhost.pomerium.io + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: kuard + port: + number: 80 + tls: + - hosts: + - kuard.localhost.pomerium.io + secretName: kuard.localhost.pomerium.io-tls +``` + +Again, change the references to `localhost.pomerium.io` to match your domain space. + +
  3. + +Apply the Ingress manifest to the cluster: + + ```bash + kubectl apply -f example-ingress.yaml + ``` +
+ +The Pomerium Ingress Controller will use cert-manager to automatically provision a certificate from the `letsencrypt-staging` issuer for the route to `kuard.localhost.pomerium.io`. + +Once you've configured all your application services correctly in the cluster, adjust the issuer for your Ingresses (including the Authenticate service) to use `letsencrypt-prod`.