diff --git a/.github/release.yml b/.github/release.yml index 6bd8eafa08..10209f2eee 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -3,18 +3,15 @@ changelog: labels: - skip changelog categories: - - title: 🚀 Features - labels: - - enhancement - title: 💣 Breaking Changes labels: - change + - title: 🚀 Features + labels: + - enhancement - title: 🐛 Bug Fixes labels: - bug - - title: 📝 Documentation - labels: - - documentation - title: 📦 Helm Chart labels: - helm_chart @@ -24,6 +21,9 @@ changelog: - title: 🔨 Maintenance labels: - chore + - title: 📝 Documentation + labels: + - documentation - title: ⬆️ Dependencies labels: - dependencies diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c4bebece10..08c6f2a242 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: types: [go] pass_filenames: false - repo: https://github.com/golangci/golangci-lint - rev: v1.51.2 + rev: v1.52.0 hooks: - id: golangci-lint args: [--new-from-patch=/tmp/diff.patch] diff --git a/deployments/common/crds/k8s.nginx.org_policies.yaml b/deployments/common/crds/k8s.nginx.org_policies.yaml index b4a24adc0c..25b15f2704 100644 --- a/deployments/common/crds/k8s.nginx.org_policies.yaml +++ b/deployments/common/crds/k8s.nginx.org_policies.yaml @@ -92,6 +92,8 @@ spec: properties: clientCertSecret: type: string + crlFileName: + type: string verifyClient: type: string verifyDepth: diff --git a/deployments/helm-chart-dos-arbitrator/.helmignore b/deployments/helm-chart-dos-arbitrator/.helmignore deleted file mode 100644 index c1347c2c27..0000000000 --- a/deployments/helm-chart-dos-arbitrator/.helmignore +++ /dev/null @@ -1,2 +0,0 @@ -# Patterns to ignore when building packages. -*.png diff --git a/deployments/helm-chart-dos-arbitrator/Chart.yaml b/deployments/helm-chart-dos-arbitrator/Chart.yaml deleted file mode 100644 index 0aabca8340..0000000000 --- a/deployments/helm-chart-dos-arbitrator/Chart.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: nginx-appprotect-dos-arbitrator -version: 0.1.0 -appVersion: 1.1.0 -apiVersion: v1 -kubeVersion: ">= 1.22.0-0" -description: NGINX App Protect Dos arbitrator -icon: https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.0.2/deployments/helm-chart-dos-arbitrator/chart-icon.png -home: https://github.com/nginxinc/kubernetes-ingress -sources: - - https://github.com/nginxinc/kubernetes-ingress/tree/v3.0.2/deployments/helm-chart-dos-arbitrator -keywords: - - appprotect-dos - - nginx - - arbitrator -maintainers: - - name: nginxinc - email: kubernetes@nginx.com diff --git a/deployments/helm-chart-dos-arbitrator/README.md b/deployments/helm-chart-dos-arbitrator/README.md deleted file mode 100644 index 82094ea720..0000000000 --- a/deployments/helm-chart-dos-arbitrator/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# NGINX App Protect DoS Arbitrator Helm Chart - -## Introduction - -This chart deploys the NGINX App Protect DoS Arbitrator in your Kubernetes cluster. - -## Prerequisites - - - A [Kubernetes Version Supported by the Ingress Controller](https://docs.nginx.com/nginx-ingress-controller/technical-specifications/#supported-kubernetes-versions) - - Helm 3.0+. - - Git. - -## Getting the Chart Sources - -This step is required if you're installing the chart using its sources. Additionally, the step is also required for managing the custom resource definitions (CRDs), which the Ingress Controller requires by default, or for upgrading/deleting the CRDs. - -1. Clone the Ingress Controller repo: - ```console - $ git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v3.0.2 - ``` -2. Change your working directory to /deployments/helm-chart-dos-arbitrator: - ```console - $ cd kubernetes-ingress/deployments/helm-chart-dos-arbitrator - ``` - -## Adding the Helm Repository - -This step is required if you're installing the chart via the helm repository. - -```console -$ helm repo add nginx-stable https://helm.nginx.com/stable -$ helm repo update -``` - -## Installing the Chart - -### Installing via Helm Repository - -To install the chart with the release name my-release-dos (my-release-dos is the name that you choose): - -```console -$ helm install my-release-dos nginx-stable/nginx-appprotect-dos-arbitrator -``` - - -### Installing Using Chart Sources - -To install the chart with the release name my-release-dos (my-release-dos is the name that you choose): - -```console -$ helm install my-release-dos . -``` - -The command deploys the App Protect DoS Arbitrator in your Kubernetes cluster in the default configuration. The configuration section lists the parameters that can be configured during installation. - -## Upgrading the Chart - -### Upgrading the Release - -To upgrade the release `my-release-dos`: - -#### Upgrade Using Chart Sources: - -```console -$ helm upgrade my-release-dos . -``` - -#### Upgrade via Helm Repository: - -```console -$ helm upgrade my-release-dos nginx-stable/nginx-appprotect-dos-arbitrator -``` - -## Uninstalling the Chart - -### Uninstalling the Release - -To uninstall/delete the release `my-release-dos`: - -```console -$ helm uninstall my-release-dos -``` - -The command removes all the Kubernetes components associated with the release and deletes the release. - -## Configuration - -The following tables lists the configurable parameters of the NGINX App Protect DoS Arbitrator chart and their default values. - -Parameter | Description | Default ---- | --- | --- -`arbitrator.resources` | The resources of the Arbitrator pods. | limits:
cpu: 500m
memory: 128Mi -`arbitrator.image.repository` | The image repository of the Arbitrator image. | docker-registry.nginx.com/nap-dos/app_protect_dos_arb -`arbitrator.image.tag` | The tag of the Arbitrator image. | 1.1.0 -`arbitrator.image.pullPolicy` | The pull policy for the Arbitrator image. | IfNotPresent diff --git a/deployments/helm-chart-dos-arbitrator/chart-icon.png b/deployments/helm-chart-dos-arbitrator/chart-icon.png deleted file mode 100644 index 52961c9a6f..0000000000 Binary files a/deployments/helm-chart-dos-arbitrator/chart-icon.png and /dev/null differ diff --git a/deployments/helm-chart-dos-arbitrator/templates/_helpers.tpl b/deployments/helm-chart-dos-arbitrator/templates/_helpers.tpl deleted file mode 100644 index 02714455be..0000000000 --- a/deployments/helm-chart-dos-arbitrator/templates/_helpers.tpl +++ /dev/null @@ -1,18 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{/* -Expand the name of the chart. -*/}} -{{- define "arbitrator.name" -}} -{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create labels -*/}} -{{- define "arbitrator.labels" -}} -app.kubernetes.io/name: {{ include "arbitrator.name" . }} -helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} diff --git a/deployments/helm-chart-dos-arbitrator/templates/controller-deployment.yaml b/deployments/helm-chart-dos-arbitrator/templates/controller-deployment.yaml deleted file mode 100644 index 66d448a4ba..0000000000 --- a/deployments/helm-chart-dos-arbitrator/templates/controller-deployment.yaml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "arbitrator.name" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "arbitrator.labels" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ include "arbitrator.name" . }} - template: - metadata: - labels: - app: {{ include "arbitrator.name" . }} - spec: - containers: - - name: {{ include "arbitrator.name" . }} - image: "{{ .Values.arbitrator.image.repository }}:{{ .Values.arbitrator.image.tag }}" - imagePullPolicy: "{{ .Values.arbitrator.image.pullPolicy }}" - resources: -{{ toYaml .Values.arbitrator.resources | indent 12 }} - ports: - - containerPort: 3000 - securityContext: - allowPrivilegeEscalation: false - runAsUser: 1001 - capabilities: - drop: - - ALL diff --git a/deployments/helm-chart-dos-arbitrator/templates/controller-service.yaml b/deployments/helm-chart-dos-arbitrator/templates/controller-service.yaml deleted file mode 100644 index f55a9fd8d2..0000000000 --- a/deployments/helm-chart-dos-arbitrator/templates/controller-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: svc-appprotect-dos-arb - namespace: {{ .Release.Namespace }} - labels: {{- include "arbitrator.labels" . | nindent 4 }} -spec: - selector: - app: {{ include "arbitrator.name" . }} - ports: - - name: arb - port: 3000 - protocol: TCP - targetPort: 3000 - clusterIP: None diff --git a/deployments/helm-chart-dos-arbitrator/values.yaml b/deployments/helm-chart-dos-arbitrator/values.yaml deleted file mode 100644 index eeacd9d3cf..0000000000 --- a/deployments/helm-chart-dos-arbitrator/values.yaml +++ /dev/null @@ -1,16 +0,0 @@ -arbitrator: - ## The resources of the Arbitrator pods. - resources: - limits: - cpu: 500m - memory: 128Mi - - image: - ## The image repository of the Arbitrator. - repository: docker-registry.nginx.com/nap-dos/app_protect_dos_arb - - ## The tag of the Arbitrator image. - tag: "1.1.0" - - ## The pull policy for the Arbitrator image. - pullPolicy: IfNotPresent diff --git a/deployments/helm-chart/README.md b/deployments/helm-chart/README.md index 5f2fd8183d..78ffe0791b 100644 --- a/deployments/helm-chart/README.md +++ b/deployments/helm-chart/README.md @@ -13,7 +13,7 @@ This chart deploys the NGINX Ingress Controller in your Kubernetes cluster. - Alternatively, pull an Ingress Controller image with NGINX Plus and push it to your private registry by following the instructions from [here](https://docs.nginx.com/nginx-ingress-controller/installation/pulling-ingress-controller-image). - Alternatively, you can build an Ingress Controller image with NGINX Plus and push it to your private registry by following the instructions from [here](https://docs.nginx.com/nginx-ingress-controller/installation/building-ingress-controller-image). - Update the `controller.image.repository` field of the `values-plus.yaml` accordingly. - - If you’d like to use App Protect DoS, please install App Protect DoS Arbitrator helm chart. Make sure to install in the same namespace as the NGINX Ingress Controller. Note that if you install multiple NGINX Ingress Controllers in the same namespace, they will need to share the same Arbitrator because it is not possible to install more than one Arbitrator in a single namespace. + - If you’d like to use App Protect DoS, please install App Protect DoS Arbitrator [helm chart](https://github.com/nginxinc/nap-dos-arbitrator-helm-chart). Make sure to install in the same namespace as the NGINX Ingress Controller. Note that if you install multiple NGINX Ingress Controllers in the same namespace, they will need to share the same Arbitrator because it is not possible to install more than one Arbitrator in a single namespace. ## CRDs diff --git a/deployments/helm-chart/crds/k8s.nginx.org_policies.yaml b/deployments/helm-chart/crds/k8s.nginx.org_policies.yaml index b4a24adc0c..25b15f2704 100644 --- a/deployments/helm-chart/crds/k8s.nginx.org_policies.yaml +++ b/deployments/helm-chart/crds/k8s.nginx.org_policies.yaml @@ -92,6 +92,8 @@ spec: properties: clientCertSecret: type: string + crlFileName: + type: string verifyClient: type: string verifyDepth: diff --git a/docs/content/app-protect-dos/installation-with-helm-dos-arbitrator.md b/docs/content/app-protect-dos/installation-with-helm-dos-arbitrator.md deleted file mode 100644 index 6c70cd9a16..0000000000 --- a/docs/content/app-protect-dos/installation-with-helm-dos-arbitrator.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Installation with Helm App Protect DoS Arbitrator -description: -weight: 1900 -doctypes: [""] -toc: true -docs: "DOCS-582" ---- - -## Prerequisites - - - A [Kubernetes Version Supported by the Ingress Controller](https://docs.nginx.com/nginx-ingress-controller/technical-specifications/#supported-kubernetes-versions) - - Helm 3.0+. - - Git. - -## Getting the Chart Sources - -This step is required if you're installing the chart using its sources. Additionally, the step is also required for managing the custom resource definitions (CRDs), which the Ingress Controller requires by default, or for upgrading/deleting the CRDs. - -1. Clone the Ingress Controller repo: - ```console - $ git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v3.0.2 - ``` -2. Change your working directory to /deployments/helm-chart-dos-arbitrator: - ```console - $ cd kubernetes-ingress/deployments/helm-chart-dos-arbitrator - ``` - -## Adding the Helm Repository - -This step is required if you're installing the chart via the helm repository. - -```console -$ helm repo add nginx-stable https://helm.nginx.com/stable -$ helm repo update -``` - -## Installing the Chart - -### Installing via Helm Repository - -To install the chart with the release name my-release-dos (my-release-dos is the name that you choose): - -```console -$ helm install my-release-dos nginx-stable/nginx-appprotect-dos-arbitrator -``` - - -### Installing Using Chart Sources - -To install the chart with the release name my-release-dos (my-release-dos is the name that you choose): - -```console -$ helm install my-release-dos . -``` - -The command deploys the App Protect DoS Arbitrator in your Kubernetes cluster in the default configuration. The configuration section lists the parameters that can be configured during installation. - -## Upgrading the Chart - -### Upgrading the Release - -To upgrade the release `my-release-dos`: - -#### Upgrade Using Chart Sources: - -```console -$ helm upgrade my-release-dos . -``` - -#### Upgrade via Helm Repository: - -```console -$ helm upgrade my-release-dos nginx-stable/nginx-appprotect-dos-arbitrator -``` - -## Uninstalling the Chart - -### Uninstalling the Release - -To uninstall/delete the release `my-release-dos`: - -```console -$ helm uninstall my-release-dos -``` - -The command removes all the Kubernetes components associated with the release and deletes the release. - -## Configuration - -The following tables lists the configurable parameters of the NGINX App Protect DoS Arbitrator chart and their default values. - -Parameter | Description | Default ---- | --- | --- -`arbitrator.resources` | The resources of the Arbitrator pods. | limits:
cpu: 500m
memory: 128Mi -`arbitrator.image.repository` | The image repository of the Arbitrator image. | docker-registry.nginx.com/nap-dos/app_protect_dos_arb -`arbitrator.image.tag` | The tag of the Arbitrator image. | latest -`arbitrator.image.pullPolicy` | The pull policy for the Arbitrator image. | IfNotPresent diff --git a/docs/content/app-protect-dos/installation.md b/docs/content/app-protect-dos/installation.md index e0fb8787f0..3b7cb1e589 100644 --- a/docs/content/app-protect-dos/installation.md +++ b/docs/content/app-protect-dos/installation.md @@ -23,13 +23,26 @@ This document provides an overview of the steps required to use NGINX App Protec $ cd kubernetes-ingress/deployments ``` -## Create the namespace and service account +## Install the App Protect DoS Arbitrator + +### Helm Chart + +The App Protect DoS Arbitrator can be installed using the [NGINX App Protect DoS Helm Chart](https://github.com/nginxinc/nap-dos-arbitrator-helm-chart). +If you have the NGINX Helm Repository already added, you can install the App Protect DoS Arbitrator by running the following command: ```bash - kubectl apply -f common/ns-and-sa.yaml +helm install my-release-dos nginx-stable/nginx-appprotect-dos-arbitrator ``` -## Install the App Protect DoS Arbitrator +### YAML Manifests + +Alternatively, you can install the App Protect DoS Arbitrator using the YAML manifests provided in the Ingress Controller repo. + +- Create the namespace and service account + +```bash + kubectl apply -f common/ns-and-sa.yaml +``` - Deploy the app protect dos arbitrator ```bash diff --git a/docs/content/configuration/policy-resource.md b/docs/content/configuration/policy-resource.md index 3ed5c7b87d..60c7ab9017 100644 --- a/docs/content/configuration/policy-resource.md +++ b/docs/content/configuration/policy-resource.md @@ -262,6 +262,17 @@ ingressMTLS: verifyDepth: 1 ``` +Below is an example of the `ingress-mtls-secret` using the secret type `nginx.org/ca` +```yaml +kind: Secret +metadata: + name: ingress-mtls-secret +apiVersion: v1 +type: nginx.org/ca +data: + ca.crt: +``` + A VirtualServer that references an IngressMTLS policy must: * Enable [TLS termination](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualservertls). * Reference the policy in the VirtualServer [`spec`](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserver-specification). It is not allowed to reference an IngressMTLS policy in a [`route `](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserverroute) or in a VirtualServerRoute [`subroute`](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserverroutesubroute). @@ -284,12 +295,58 @@ We use the `requestHeaders` of the [Action.Proxy](/nginx-ingress-controller/conf > Note: The feature is implemented using the NGINX [ngx_http_ssl_module](https://nginx.org/en/docs/http/ngx_http_ssl_module.html). +#### Using a Certificate Revocation List +The IngressMTLS policy supports configuring at CRL for your policy. +This can be done in one of two ways. + +> Note: Only one of these configurations options can be used at a time. + +1. Adding the `ca.crl` field to the `nginx.org/ca` secret type, which accepts a base64 encoded certificate revocation list (crl). + Example YAML: +```yaml +kind: Secret +metadata: + name: ingress-mtls-secret +apiVersion: v1 +type: nginx.org/ca +data: + ca.crt: + ca.crl: +``` + +2. Adding the `crlFileName` field to your IngressMTLS policy spec with the name of the CRL file. + +> Note: This configuration option should only be used when using a CRL that is larger than 1MiB +> Otherwise we recommend using the `nginx.org/ca` secret type for managing your CRL. + +Example YAML: +```yaml +apiVersion: k8s.nginx.org/v1 +kind: Policy +metadata: + name: ingress-mtls-policy +spec: +ingressMTLS: + clientCertSecret: ingress-mtls-secret + crlFileName: webapp.crl + verifyClient: "on" + verifyDepth: 1 +``` + +**IMPORTANT NOTE** +When configuring a CRL with the `ingressMTLS.crlFileName` field, there is additional context to keep in mind: +1. The Ingress Controller will expect the CRL, in this case `webapp.crl`, will be in `/etc/nginx/secrets`. A volume mount will need to be added to the Ingress Controller deployment add your CRL to `/etc/nginx/secrets` +2. When updating the content of your CRL (e.g a new certificate has been revoked), NGINX will need to be reloaded to pick up the latest changes. Depending on your environment this may require updating the name of your CRL and applying this update to your `ingress-mtls.yaml` policy to ensure NGINX picks up the latest CRL. + +Please refer to the Kubernetes documentation on [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) to find the best implementation for your environment. + {{% table %}} |Field | Description | Type | Required | | ---| ---| ---| --- | |``clientCertSecret`` | The name of the Kubernetes secret that stores the CA certificate. It must be in the same namespace as the Policy resource. The secret must be of the type ``nginx.org/ca``, and the certificate must be stored in the secret under the key ``ca.crt``, otherwise the secret will be rejected as invalid. | ``string`` | Yes | |``verifyClient`` | Verification for the client. Possible values are ``"on"``, ``"off"``, ``"optional"``, ``"optional_no_ca"``. The default is ``"on"``. | ``string`` | No | |``verifyDepth`` | Sets the verification depth in the client certificates chain. The default is ``1``. | ``int`` | No | +|``crlFileName`` | The file name of the Certificate Revocation List. The Ingress Controller will look for this file in `/etc/nginx/secrets` | ``string`` | No | {{% /table %}} #### IngressMTLS Merging Behavior diff --git a/docs/content/configuration/security.md b/docs/content/configuration/security.md index c7d335c7a4..accbf55e4a 100644 --- a/docs/content/configuration/security.md +++ b/docs/content/configuration/security.md @@ -42,7 +42,70 @@ We recommend the following for the most secure configuration: we recommend [configuring HTTPS](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-prometheus-tls-secret) for Prometheus. ### Snippets - Snippets allow you to insert raw NGINX config into different contexts of NGINX configuration and are supported for [Ingress](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-snippets/), [VirtualServer/VirtualServerRoute](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#using-snippets), and [TransportServer](/nginx-ingress-controller/configuration/transportserver-resource/#using-snippets) resources. Additionally, the [ConfigMap](/nginx-ingress-controller/configuration/global-configuration/configmap-resource#snippets-and-custom-templates) resource configures snippets globally. Snippets are disabled by default. To use snippets, set the [`enable-snippets`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-enable-snippets) command-line argument. Note that for the ConfigMap resource, snippets are always enabled. + +### Configure root filesystem as read-only +> **Note**: This feature is available for both the NGINX and NGINX Plus editions. NGINX AppProtect WAF and NGINX AppProtect DoS are not yet supported by this feature. + +The F5 Nginx Ingress Controller (NIC) has various protections against attacks, such as running the service as non-root to avoid changes to files. An additional industry best practice is having root filesystems set as read-only so that the attack surface is further reduced by limiting changes to binaries and libraries. + +Currently we do not set read-only root filesystem as default. Instead, this is an opt-in feature available on the [helm-chart](/nginx-ingress-controller/installation-with-helm/#configuration) via `controller.readOnlyRootFilesystem`. +When using manifests instead of Helm, uncomment the following sections of the deployment: + * `readOnlyRootFilesystem: true`, + * The entire `volumeMounts` section, + * The entire `initContiners` section, + * For `initContainers:image:`, use exact same image used for regular NIC installation. +Refer to the below code-block for guidance: + +``` +# fsGroup: 101 #nginx +. +. +. +# volumes: +# - name: nginx-etc +# emptyDir: {} +# - name: nginx-cache +# emptyDir: {} +# - name: nginx-lib +# emptyDir: {} +# - name: nginx-log +# emptyDir: {} +. +. +. +# readOnlyRootFilesystem: true +. +. +. +# volumeMounts: +# - mountPath: /etc/nginx +# name: nginx-etc +# - mountPath: /var/cache/nginx +# name: nginx-cache +# - mountPath: /var/lib/nginx +# name: nginx-lib +# - mountPath: /var/log/nginx +# name: nginx-log +. +. +. +# initContainers: +# - image: : +# imagePullPolicy: IfNotPresent +# name: init-nginx-ingress +# command: ['cp', '-vdR', '/etc/nginx/.', '/mnt/etc'] +# securityContext: +# allowPrivilegeEscalation: false +# readOnlyRootFilesystem: true +# runAsUser: 101 #nginx +# runAsNonRoot: true +# capabilities: +# drop: +# - ALL +# volumeMounts: +# - mountPath: /mnt/etc +# name: nginx-etc +``` diff --git a/examples/custom-resources/ingress-mtls/README.md b/examples/custom-resources/ingress-mtls/README.md index 85b88e1470..2f679ff2b8 100644 --- a/examples/custom-resources/ingress-mtls/README.md +++ b/examples/custom-resources/ingress-mtls/README.md @@ -2,6 +2,9 @@ In this example, we deploy a web application, configure load balancing for it via a VirtualServer, and apply an Ingress MTLS policy. +> Note: The Ingress MTLS policy supports configuring a Certificate Revocation List (CRL). +> See [Using a Certificate Revocation List](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#using-a-certificate-revocation-list) for details on how to set this option. + ## Prerequisites 1. Follow the [installation](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/) instructions to deploy the Ingress Controller. diff --git a/hack/common-release-prep.sh b/hack/common-release-prep.sh index 95675c846c..b22bf9fdbd 100755 --- a/hack/common-release-prep.sh +++ b/hack/common-release-prep.sh @@ -22,8 +22,6 @@ FILES_TO_UPDATE_IC_VERSION=( deployments/helm-chart/values-nsm.yaml deployments/helm-chart/values-plus.yaml deployments/helm-chart/values.yaml - deployments/helm-chart-dos-arbitrator/Chart.yaml - deployments/helm-chart-dos-arbitrator/README.md ) FILE_TO_UPDATE_HELM_CHART_VERSION=(deployments/helm-chart/Chart.yaml) diff --git a/internal/configs/configurator.go b/internal/configs/configurator.go index 2e5478e3b3..e0e7ab37e5 100644 --- a/internal/configs/configurator.go +++ b/internal/configs/configurator.go @@ -59,8 +59,11 @@ const JWTKeyKey = "jwk" // HtpasswdFileKey is the key of the data field of a Secret where the HTTP basic authorization list must be stored const HtpasswdFileKey = "htpasswd" -// CAKey is the key of the data field of a Secret where the cert must be stored. -const CAKey = "ca.crt" +// CACrtKey is the key of the data field of a Secret where the cert must be stored. +const CACrtKey = "ca.crt" + +// CACrlKey is the key of the data field of a Secret where the cert revocation list must be stored. +const CACrlKey = "ca.crl" // ClientSecretKey is the key of the data field of a Secret where the OIDC client secret must be stored. const ClientSecretKey = "client-secret" @@ -727,8 +730,12 @@ func generateTLSPassthroughHostsConfig(tlsPassthroughPairs map[string]tlsPassthr func (cnf *Configurator) addOrUpdateCASecret(secret *api_v1.Secret) string { name := objectMetaToFileName(&secret.ObjectMeta) - data := GenerateCAFileContent(secret) - return cnf.nginxManager.CreateSecret(name, data, nginx.TLSSecretFileMode) + crtData, crlData := GenerateCAFileContent(secret) + crtSecretName := fmt.Sprintf("%s-%s", name, CACrtKey) + crlSecretName := fmt.Sprintf("%s-%s", name, CACrlKey) + crtFileName := cnf.nginxManager.CreateSecret(crtSecretName, crtData, nginx.TLSSecretFileMode) + crlFileName := cnf.nginxManager.CreateSecret(crlSecretName, crlData, nginx.TLSSecretFileMode) + return fmt.Sprintf("%s %s", crtFileName, crlFileName) } func (cnf *Configurator) addOrUpdateJWKSecret(secret *api_v1.Secret) string { @@ -818,12 +825,14 @@ func GenerateCertAndKeyFileContent(secret *api_v1.Secret) []byte { } // GenerateCAFileContent generates a pem file content from the TLS secret. -func GenerateCAFileContent(secret *api_v1.Secret) []byte { - var res bytes.Buffer +func GenerateCAFileContent(secret *api_v1.Secret) ([]byte, []byte) { + var caKey bytes.Buffer + var caCrl bytes.Buffer - res.Write(secret.Data[CAKey]) + caKey.Write(secret.Data[CACrtKey]) + caCrl.Write(secret.Data[CACrlKey]) - return res.Bytes() + return caKey.Bytes(), caCrl.Bytes() } // DeleteIngress deletes NGINX configuration for the Ingress resource. diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index 5c2e792211..29fc7310ff 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -91,6 +91,7 @@ type SSL struct { // IngressMTLS defines TLS configuration for a server. This is a subset of TLS specifically for clients auth. type IngressMTLS struct { ClientCert string + ClientCrl string VerifyClient string VerifyDepth int } diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index a40aeea15a..846320e58a 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -115,6 +115,9 @@ server { {{ with $s.IngressMTLS }} ssl_client_certificate {{ .ClientCert }}; + {{ if .ClientCrl }} + ssl_crl {{ .ClientCrl }}; + {{ end }} ssl_verify_client {{ .VerifyClient }}; ssl_verify_depth {{ .VerifyDepth }}; {{ end }} diff --git a/internal/configs/version2/nginx.virtualserver.tmpl b/internal/configs/version2/nginx.virtualserver.tmpl index d3de0d7022..2f2d604cb7 100644 --- a/internal/configs/version2/nginx.virtualserver.tmpl +++ b/internal/configs/version2/nginx.virtualserver.tmpl @@ -70,6 +70,9 @@ server { {{ with $s.IngressMTLS }} ssl_client_certificate {{ .ClientCert }}; + {{ if .ClientCrl }} + ssl_crl {{ .ClientCrl }}; + {{ end }} ssl_verify_client {{ .VerifyClient }}; ssl_verify_depth {{ .VerifyDepth }}; {{ end }} diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 84b2619790..fc41497d87 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -7,15 +7,14 @@ import ( "strings" "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/configs/version2" "github.com/nginxinc/kubernetes-ingress/internal/k8s/secrets" "github.com/nginxinc/kubernetes-ingress/internal/nginx" + conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1" api_v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" - - "github.com/nginxinc/kubernetes-ingress/internal/configs/version2" - conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1" ) const ( @@ -908,10 +907,32 @@ func (p *policiesCfg) addIngressMTLSConfig( verifyClient = ingressMTLS.VerifyClient } - p.IngressMTLS = &version2.IngressMTLS{ - ClientCert: secretRef.Path, - VerifyClient: verifyClient, - VerifyDepth: verifyDepth, + caFields := strings.Fields(secretRef.Path) + + if _, hasCrlKey := secretRef.Secret.Data[CACrlKey]; hasCrlKey && ingressMTLS.CrlFileName != "" { + res.addWarningf("Both ca.crl in the Secret and ingressMTLS.crlFileName fields cannot be used. ca.crl in %s will be ignored and %s will be applied", secretKey, polKey) + } + + if ingressMTLS.CrlFileName != "" { + p.IngressMTLS = &version2.IngressMTLS{ + ClientCert: caFields[0], + ClientCrl: fmt.Sprintf("%s/%s", DefaultSecretPath, ingressMTLS.CrlFileName), + VerifyClient: verifyClient, + VerifyDepth: verifyDepth, + } + } else if _, hasCrlKey := secretRef.Secret.Data[CACrlKey]; hasCrlKey { + p.IngressMTLS = &version2.IngressMTLS{ + ClientCert: caFields[0], + ClientCrl: caFields[1], + VerifyClient: verifyClient, + VerifyDepth: verifyDepth, + } + } else { + p.IngressMTLS = &version2.IngressMTLS{ + ClientCert: caFields[0], + VerifyClient: verifyClient, + VerifyDepth: verifyDepth, + } } return res } diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index c6fc69863f..d42f538d8f 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -2691,7 +2691,9 @@ func TestGeneratePolicies(t *testing.T) { vsNamespace: "default", vsName: "test", } - ingressMTLSCertPath := "/etc/nginx/secrets/default-ingress-mtls-secret" + ingressMTLSCertPath := "/etc/nginx/secrets/default-ingress-mtls-secret-ca.crt" + ingressMTLSCrlPath := "/etc/nginx/secrets/default-ingress-mtls-secret-ca.crl" + ingressMTLSCertAndCrlPath := fmt.Sprintf("%s %s", ingressMTLSCertPath, ingressMTLSCrlPath) policyOpts := policyOptions{ tls: true, secretRefs: map[string]*secrets.SecretReference{ @@ -2701,6 +2703,15 @@ func TestGeneratePolicies(t *testing.T) { }, Path: ingressMTLSCertPath, }, + "default/ingress-mtls-secret-crl": { + Secret: &api_v1.Secret{ + Type: secrets.SecretTypeCA, + Data: map[string][]byte{ + "ca.crl": []byte("base64crl"), + }, + }, + Path: ingressMTLSCertAndCrlPath, + }, "default/egress-mtls-secret": { Secret: &api_v1.Secret{ Type: api_v1.SecretTypeTLS, @@ -3085,6 +3096,71 @@ func TestGeneratePolicies(t *testing.T) { }, msg: "ingressMTLS reference", }, + { + policyRefs: []conf_v1.PolicyReference{ + { + Name: "ingress-mtls-policy-crl", + Namespace: "default", + }, + }, + policies: map[string]*conf_v1.Policy{ + "default/ingress-mtls-policy-crl": { + ObjectMeta: meta_v1.ObjectMeta{ + Name: "ingress-mtls-policy-crl", + Namespace: "default", + }, + Spec: conf_v1.PolicySpec{ + IngressMTLS: &conf_v1.IngressMTLS{ + ClientCertSecret: "ingress-mtls-secret-crl", + VerifyClient: "off", + }, + }, + }, + }, + context: "spec", + expected: policiesCfg{ + IngressMTLS: &version2.IngressMTLS{ + ClientCert: ingressMTLSCertPath, + ClientCrl: ingressMTLSCrlPath, + VerifyClient: "off", + VerifyDepth: 1, + }, + }, + msg: "ingressMTLS reference with ca.crl field in secret", + }, + { + policyRefs: []conf_v1.PolicyReference{ + { + Name: "ingress-mtls-policy-crl", + Namespace: "default", + }, + }, + policies: map[string]*conf_v1.Policy{ + "default/ingress-mtls-policy-crl": { + ObjectMeta: meta_v1.ObjectMeta{ + Name: "ingress-mtls-policy-crl", + Namespace: "default", + }, + Spec: conf_v1.PolicySpec{ + IngressMTLS: &conf_v1.IngressMTLS{ + ClientCertSecret: "ingress-mtls-secret", + CrlFileName: "default-ingress-mtls-secret-ca.crl", + VerifyClient: "off", + }, + }, + }, + }, + context: "spec", + expected: policiesCfg{ + IngressMTLS: &version2.IngressMTLS{ + ClientCert: ingressMTLSCertPath, + ClientCrl: ingressMTLSCrlPath, + VerifyClient: "off", + VerifyDepth: 1, + }, + }, + msg: "ingressMTLS reference with crl field in policy", + }, { policyRefs: []conf_v1.PolicyReference{ { @@ -3263,6 +3339,9 @@ func TestGeneratePoliciesFails(t *testing.T) { dryRunOverride := true rejectCodeOverride := 505 + ingressMTLSCertPath := "/etc/nginx/secrets/default-ingress-mtls-secret-ca.crt" + ingressMTLSCrlPath := "/etc/nginx/secrets/default-ingress-mtls-secret-ca.crl" + tests := []struct { policyRefs []conf_v1.PolicyReference policies map[string]*conf_v1.Policy @@ -3840,14 +3919,14 @@ func TestGeneratePoliciesFails(t *testing.T) { Secret: &api_v1.Secret{ Type: secrets.SecretTypeCA, }, - Path: "/etc/nginx/secrets/default-ingress-mtls-secret", + Path: ingressMTLSCertPath, }, }, }, context: "spec", expected: policiesCfg{ IngressMTLS: &version2.IngressMTLS{ - ClientCert: "/etc/nginx/secrets/default-ingress-mtls-secret", + ClientCert: ingressMTLSCertPath, VerifyClient: "on", VerifyDepth: 1, }, @@ -3887,7 +3966,7 @@ func TestGeneratePoliciesFails(t *testing.T) { Secret: &api_v1.Secret{ Type: secrets.SecretTypeCA, }, - Path: "/etc/nginx/secrets/default-ingress-mtls-secret", + Path: ingressMTLSCertPath, }, }, }, @@ -3932,7 +4011,7 @@ func TestGeneratePoliciesFails(t *testing.T) { Secret: &api_v1.Secret{ Type: secrets.SecretTypeCA, }, - Path: "/etc/nginx/secrets/default-ingress-mtls-secret", + Path: ingressMTLSCertPath, }, }, }, @@ -3950,6 +4029,59 @@ func TestGeneratePoliciesFails(t *testing.T) { expectedOidc: &oidcPolicyCfg{}, msg: "ingress mtls missing TLS config", }, + { + policyRefs: []conf_v1.PolicyReference{ + { + Name: "ingress-mtls-policy", + Namespace: "default", + }, + }, + policies: map[string]*conf_v1.Policy{ + "default/ingress-mtls-policy": { + ObjectMeta: meta_v1.ObjectMeta{ + Name: "ingress-mtls-policy", + Namespace: "default", + }, + Spec: conf_v1.PolicySpec{ + IngressMTLS: &conf_v1.IngressMTLS{ + ClientCertSecret: "ingress-mtls-secret", + CrlFileName: "default-ingress-mtls-secret-ca.crl", + }, + }, + }, + }, + policyOpts: policyOptions{ + tls: true, + secretRefs: map[string]*secrets.SecretReference{ + "default/ingress-mtls-secret": { + Secret: &api_v1.Secret{ + Type: secrets.SecretTypeCA, + Data: map[string][]byte{ + "ca.crl": []byte("base64crl"), + }, + }, + Path: ingressMTLSCertPath, + }, + }, + }, + context: "spec", + expected: policiesCfg{ + IngressMTLS: &version2.IngressMTLS{ + ClientCert: ingressMTLSCertPath, + ClientCrl: ingressMTLSCrlPath, + VerifyClient: "on", + VerifyDepth: 1, + }, + ErrorReturn: nil, + }, + expectedWarnings: Warnings{ + nil: { + `Both ca.crl in the Secret and ingressMTLS.crlFileName fields cannot be used. ca.crl in default/ingress-mtls-secret will be ignored and default/ingress-mtls-policy will be applied`, + }, + }, + expectedOidc: &oidcPolicyCfg{}, + msg: "ingress mtls ca.crl and ingressMTLS.Crl set", + }, { policyRefs: []conf_v1.PolicyReference{ { diff --git a/pkg/apis/configuration/v1/types.go b/pkg/apis/configuration/v1/types.go index e1a3465a95..f994afcda3 100644 --- a/pkg/apis/configuration/v1/types.go +++ b/pkg/apis/configuration/v1/types.go @@ -456,6 +456,7 @@ type BasicAuth struct { // IngressMTLS defines an Ingress MTLS policy. type IngressMTLS struct { ClientCertSecret string `json:"clientCertSecret"` + CrlFileName string `json:"crlFileName"` VerifyClient string `json:"verifyClient"` VerifyDepth *int `json:"verifyDepth"` } diff --git a/tests/data/ingress-mtls/client-auth/crl/webapp.crl b/tests/data/ingress-mtls/client-auth/crl/webapp.crl new file mode 100644 index 0000000000..a836c07e04 --- /dev/null +++ b/tests/data/ingress-mtls/client-auth/crl/webapp.crl @@ -0,0 +1,19 @@ +-----BEGIN X509 CRL----- +MIIDBDCB7TANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMxETAPBgNVBAgM +CE1hcnlsYW5kMRIwEAYDVQQHDAlCYWx0aW1vcmUxGTAXBgNVBAoMEFRlc3QgQ0Es +IExpbWl0ZWQxIzAhBgNVBAsMGlNlcnZlciBSZXNlYXJjaCBEZXBhcnRtZW50MRAw +DgYDVQQDDAdUZXN0IENBMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29t +Fw0yMzAzMTMxODAyMjJaFw0yMzA0MTIxODAyMjJaMBQwEgIBAhcNMjMwMzEzMTgw +MjEyWjANBgkqhkiG9w0BAQsFAAOCAgEARsCPzIZjRkuKPej4Tu79kzENW/E6976c +Xk7h5tKhLwN54NUtt3JRLpVPApPXgO7auZ9kIbX/Di+rzK8WpPehTIx4oTlrKclZ +OXl3tPYBgvg2G5qhTw2P/N4C35O1gmZYKYqXxGzJ9AVu9ZcWRRczUB9yZfTupDh8 +6JtNwbBUZNGiR2FEyJ/XSPB1UyrAkb2VMN7A5XFHi+yYqkKlkpSKhcOcyFqzE0/q +D9WV7zrmT20uMXkeBUm9XHjXtWE20oMODPGDDA5H6FZi/NH1pSkKTcx8R7X4fehV +9BTMYyTCVpUIIHndou4v1RIvPriE/OPlxP0cDVB6euWDWogIvr2Y4izyGtstZZoN +Md0QcXWMXSR0wShBtD5Lb9r0K8LOKnyuQTUSGivncbFj6MQ4NSqM14Iw3d8z0zj0 +89oxAQXMkojvm6IeyY/aJUZqIOvNz1xdhnd5smZChAGSULxgXleaGF87W+v18nJT +8/7sUbsOQGQ+uP9tcWpf3rlx1UD5dgUoJlwkRMzgOoAv07rdqdldd8AWVbwLryFv +4DuLMNUDD+lObWq4T7A4NsoSZvPnj+Np83/uBXE/Ffozbic2R8VIoSKGcaX8thfa +joPL5JkxjFFzfFrp02/WFSMwq3slkBBjHadwjMq6bBry142aiNQn8p4lkvWWDoQ+ +igkH3EDgCVc= +-----END X509 CRL----- diff --git a/tests/data/ingress-mtls/client-auth/not-revoked/client-cert.pem b/tests/data/ingress-mtls/client-auth/not-revoked/client-cert.pem new file mode 100644 index 0000000000..0544bf1b10 --- /dev/null +++ b/tests/data/ingress-mtls/client-auth/not-revoked/client-cert.pem @@ -0,0 +1,108 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Maryland, L=Baltimore, O=Test CA, Limited, OU=Server Research Department, CN=Test CA/emailAddress=test@example.com + Validity + Not Before: Mar 13 17:58:36 2023 GMT + Not After : Mar 12 17:58:36 2024 GMT + Subject: C=US, ST=MD, L=Baltimore, O=Test Server, Limited, CN=Test Server + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a7:85:20:1a:81:39:bf:55:a7:2b:2b:c7:bf:fa: + 9f:e2:26:7e:f2:21:61:fa:d9:39:4e:ab:0e:38:6e: + fe:5d:e2:5a:fc:99:1b:42:30:b7:ee:21:50:4b:cc: + 79:bd:ee:9f:2c:5b:69:76:99:b5:00:69:4f:9c:70: + 7b:9e:4e:be:2e:63:d0:69:ec:bc:b2:4d:ba:40:f4: + 00:38:0a:75:26:8a:17:9f:e5:b6:37:9e:3e:34:da: + 1e:52:7f:e8:88:8b:30:26:3f:1e:5d:b3:0d:1a:c8: + 70:02:65:ef:ad:d1:66:a9:e3:eb:d5:2d:02:98:5c: + 54:e1:e2:91:30:57:68:7e:f3:c2:8d:14:9a:c7:19: + 0e:3f:af:03:24:e1:0f:c2:7d:22:b7:6b:36:c2:fd: + 4c:e1:a9:d9:1f:fc:ec:05:c3:95:dd:17:96:9e:d0: + 99:30:2d:07:6f:b7:6a:ea:11:63:b6:b2:09:50:1c: + 35:83:a6:90:95:c2:c1:73:6a:5d:87:ad:27:0f:b1: + 51:a3:73:c4:b5:2b:05:f8:3b:4a:63:1c:dd:dd:b7: + 2f:b4:58:49:42:3f:7e:4a:3e:89:68:7f:06:b5:52: + 04:3f:8c:db:7e:ce:5e:1e:64:39:ad:d0:93:24:f7: + 55:c8:aa:4e:85:a1:5b:a5:8d:44:cf:15:1e:6a:b1: + 00:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 60:B1:14:DA:79:DA:4E:5C:A7:8F:C9:E1:4F:53:E4:0A:03:71:0F:22 + X509v3 Authority Key Identifier: + keyid:90:AA:F8:42:B6:84:01:09:18:39:76:A1:59:BF:19:29:04:94:6C:2B + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Subject Alternative Name: + DNS:example.com, DNS:webapp.example.com, DNS:mail.example.com, DNS:ftp.example.com + Netscape Comment: + OpenSSL Generated Certificate + Signature Algorithm: sha256WithRSAEncryption + 44:6a:06:f7:ba:cb:1d:fa:c9:bf:ab:62:7c:f0:e3:2c:a3:11: + 2a:aa:17:85:3a:b7:ba:0f:ab:03:65:63:a8:a8:d4:33:a6:85: + 16:ce:b6:96:3b:dc:d2:c2:8a:36:75:f5:7b:e6:a8:9b:1d:e7: + c6:fb:24:97:51:47:df:e2:ae:7b:76:0f:ef:29:aa:f5:1f:14: + b4:89:2f:16:51:f8:19:05:35:43:c4:ea:2b:69:7d:07:56:39: + 73:56:bf:86:6b:5a:90:32:2b:0a:3a:26:92:f9:01:37:30:4d: + 13:4f:f5:c6:3b:dc:23:f6:cb:4e:f0:0a:25:75:0b:26:92:70: + 12:ec:af:1b:1b:21:25:bf:5b:0c:81:97:2b:22:57:c2:5a:c7: + 6a:c6:1d:e8:f9:b9:ae:8e:ca:51:14:4f:7e:d4:21:43:a9:f7: + 43:87:53:83:7e:6e:e5:04:65:72:09:f6:b0:f6:45:c7:9c:31: + 03:88:bb:56:3d:c6:a8:fa:2f:f3:4c:92:5a:89:a1:5c:2e:14: + dd:8f:1b:7f:67:a3:63:52:11:20:1a:5b:a9:a4:68:80:ec:4b: + ee:40:f6:b2:c8:a1:d5:d1:af:eb:de:3d:c8:cb:f2:75:6e:12: + 53:1b:70:f9:db:ef:4d:e4:76:17:80:7a:4f:be:5f:b2:dc:33: + 85:81:fc:27:8f:da:cd:dd:4c:bd:31:50:eb:4a:cb:db:9b:c2: + 1c:db:43:86:e1:ca:15:1d:58:47:33:14:9a:80:7e:53:8b:52: + 1d:f9:98:84:10:df:5a:d7:0e:ef:c7:6d:aa:14:f0:09:fa:67: + 94:50:8f:d5:e1:07:5c:8b:bb:2f:73:49:50:ef:1e:d9:12:27: + 20:fb:bb:52:70:0c:d6:00:d2:bd:62:ff:1d:8c:07:91:c4:34: + 65:dd:9b:f1:40:67:db:d7:ad:d1:7a:96:f4:61:91:42:f4:9d: + a4:70:a8:31:70:97:1a:19:9d:ca:0d:41:b4:cc:95:0d:00:0b: + 6b:a0:28:ce:74:ee:69:73:b3:fc:58:13:7b:40:9b:29:99:94: + ba:26:91:20:33:89:44:46:58:b3:36:be:e3:18:20:6b:52:3c: + 7a:90:5f:82:a5:aa:f0:cc:6e:4d:26:9d:6e:2d:b6:2c:a6:7c: + 80:a9:d6:9d:34:e3:ac:bb:f0:e8:78:8d:93:2f:6f:31:3f:5f: + 91:5c:fc:d8:8c:bc:5a:8e:f0:67:c1:df:6b:08:5e:34:56:93: + 19:6a:c0:51:a4:9b:b3:3f:38:2e:c1:17:45:00:74:d9:3d:45: + b2:1b:76:e8:52:4f:e6:1f:7e:62:c7:b6:82:78:4e:40:56:cf: + 6b:93:f8:7d:be:27:0a:f2 +-----BEGIN CERTIFICATE----- +MIIFXzCCA0egAwIBAgIBATANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +ETAPBgNVBAgMCE1hcnlsYW5kMRIwEAYDVQQHDAlCYWx0aW1vcmUxGTAXBgNVBAoM +EFRlc3QgQ0EsIExpbWl0ZWQxIzAhBgNVBAsMGlNlcnZlciBSZXNlYXJjaCBEZXBh +cnRtZW50MRAwDgYDVQQDDAdUZXN0IENBMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4 +YW1wbGUuY29tMB4XDTIzMDMxMzE3NTgzNloXDTI0MDMxMjE3NTgzNlowYzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgMAk1EMRIwEAYDVQQHDAlCYWx0aW1vcmUxHTAbBgNV +BAoMFFRlc3QgU2VydmVyLCBMaW1pdGVkMRQwEgYDVQQDDAtUZXN0IFNlcnZlcjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKeFIBqBOb9Vpysrx7/6n+Im +fvIhYfrZOU6rDjhu/l3iWvyZG0Iwt+4hUEvMeb3unyxbaXaZtQBpT5xwe55Ovi5j +0GnsvLJNukD0ADgKdSaKF5/ltjeePjTaHlJ/6IiLMCY/Hl2zDRrIcAJl763RZqnj +69UtAphcVOHikTBXaH7zwo0UmscZDj+vAyThD8J9IrdrNsL9TOGp2R/87AXDld0X +lp7QmTAtB2+3auoRY7ayCVAcNYOmkJXCwXNqXYetJw+xUaNzxLUrBfg7SmMc3d23 +L7RYSUI/fko+iWh/BrVSBD+M237OXh5kOa3QkyT3VciqToWhW6WNRM8VHmqxAP8C +AwEAAaOB2DCB1TAdBgNVHQ4EFgQUYLEU2nnaTlynj8nhT1PkCgNxDyIwHwYDVR0j +BBgwFoAUkKr4QraEAQkYOXahWb8ZKQSUbCswCQYDVR0TBAIwADALBgNVHQ8EBAMC +BaAwTQYDVR0RBEYwRIILZXhhbXBsZS5jb22CEndlYmFwcC5leGFtcGxlLmNvbYIQ +bWFpbC5leGFtcGxlLmNvbYIPZnRwLmV4YW1wbGUuY29tMCwGCWCGSAGG+EIBDQQf +Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOC +AgEARGoG97rLHfrJv6tifPDjLKMRKqoXhTq3ug+rA2VjqKjUM6aFFs62ljvc0sKK +NnX1e+aomx3nxvskl1FH3+Kue3YP7ymq9R8UtIkvFlH4GQU1Q8TqK2l9B1Y5c1a/ +hmtakDIrCjomkvkBNzBNE0/1xjvcI/bLTvAKJXULJpJwEuyvGxshJb9bDIGXKyJX +wlrHasYd6Pm5ro7KURRPftQhQ6n3Q4dTg35u5QRlcgn2sPZFx5wxA4i7Vj3GqPov +80ySWomhXC4U3Y8bf2ejY1IRIBpbqaRogOxL7kD2ssih1dGv6949yMvydW4SUxtw ++dvvTeR2F4B6T75fstwzhYH8J4/azd1MvTFQ60rL25vCHNtDhuHKFR1YRzMUmoB+ +U4tSHfmYhBDfWtcO78dtqhTwCfpnlFCP1eEHXIu7L3NJUO8e2RInIPu7UnAM1gDS +vWL/HYwHkcQ0Zd2b8UBn29et0XqW9GGRQvSdpHCoMXCXGhmdyg1BtMyVDQALa6Ao +znTuaXOz/FgTe0CbKZmUuiaRIDOJREZYsza+4xgga1I8epBfgqWq8MxuTSadbi22 +LKZ8gKnWnTTjrLvw6HiNky9vMT9fkVz82Iy8Wo7wZ8HfawheNFaTGWrAUaSbsz84 +LsEXRQB02T1Fsht26FJP5h9+Yse2gnhOQFbPa5P4fb4nCvI= +-----END CERTIFICATE----- diff --git a/tests/data/ingress-mtls/client-auth/not-revoked/client-key.pem b/tests/data/ingress-mtls/client-auth/not-revoked/client-key.pem new file mode 100644 index 0000000000..bbef35f917 --- /dev/null +++ b/tests/data/ingress-mtls/client-auth/not-revoked/client-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnhSAagTm/Vacr +K8e/+p/iJn7yIWH62TlOqw44bv5d4lr8mRtCMLfuIVBLzHm97p8sW2l2mbUAaU+c +cHueTr4uY9Bp7LyyTbpA9AA4CnUmihef5bY3nj402h5Sf+iIizAmPx5dsw0ayHAC +Ze+t0Wap4+vVLQKYXFTh4pEwV2h+88KNFJrHGQ4/rwMk4Q/CfSK3azbC/Uzhqdkf +/OwFw5XdF5ae0JkwLQdvt2rqEWO2sglQHDWDppCVwsFzal2HrScPsVGjc8S1KwX4 +O0pjHN3dty+0WElCP35KPolofwa1UgQ/jNt+zl4eZDmt0JMk91XIqk6FoVuljUTP +FR5qsQD/AgMBAAECggEAAnGSslBIQ15AfgS5eTdytZ3SJD4Qa9RXXappHrGfzEbN +BPpGx4RmanbZ8QEelYKxl7gNpclANq1Sl/mcFAcaBxs1oxXs+rzfhqsIhcjBRLqm +9ZIoQk9woNy9rH5pKfS90xEApGVEP6vE1oQeJu7zDG9itU1eyFIwessPSyE7SP7H +Pae6gTgb0KUyobs2IwER+2e8vwnb2wZXgiazIemPo6RKpydBVpKSgI+pR4Yr5NrY +ZhGCKs0U9EyeT5JwFNYsbU2noaw9Anty7i2BU5Im/6NyJC5Q59QvqFyWGf7RG7Mq +blz+uvnuooWUoSp4FT7sPZNCHRcHbsS1Y0Kol/RHwQKBgQDdTb2wkEvnJPNs8Hlk +ouE2LXuvtwB0DopLN0W1TIazOeN6yPFlVC61E98GeVZO4DLrINrbTyED1fgtCioM +6Qbh4BhJHCG8PQPLug2TjLZs3f4kADey2jTfkvdD2yYdDFK5jv001NBG86mjIFOb +5pShh+Pb/NMTAkuYpZX4QNpnmQKBgQDByLhYSWHDSZdcpoWyBy95zPTXtZmHLqbo +0rOoGXQrJviVBY/OrweskNKLOBujjxGG6R8DXFrFJjLZ+8unk1WY38bXb8paN8M7 +8xU2A4b1VuagsMqbMAzmVb2B6kooLtCpnF0D3CiBFlHYOi5wW5KBxsz1HnU9cfJd ++lrFD+WsVwKBgQDDRamvdmPDXZN9+OLkreRTTebpsWyw+3OD0w2rYA8rblUPLufy +JUnhddtBdyd1CddkKeVzxmq3W8JU27cnFSeBf59uQ2hxFNWYml8IZw1BGtD5K0f6 +hRhKfv+33FPRJeKI4WcDixUMxkxVKF0eH2Pe9G1W28vT5h6WXuXp3C/bYQKBgGM3 +tQMnF1IY1NHQRPXA7hLr2JS1W1U2kqj0cJ3p4mvRuUb7oQTO4xv8zoAPiz80GmI7 +6/AZkjQM+c5YOI6lRhdOxA08JJwKnwCL1llgdvIYu16dBi9s673nOm9RGQT360hc +UdePGoH1fpQ6PdqzWBDwS7JZFOgP9msdquno2MxjAoGAIvW6rXq5WVNjs2bOIpL3 +SI9QxZ9dlhCyRf14T2+2h4GoenkSaiQoLhJ5BHy2ydQUUM4u0EEjkLz/xLxmh6uS +n8b2suXTBdHCp6C73FVc8JvBUWEfj4W8a1tLO53DcbW0YVmk6mL7otw8WBi6LqJz +nCrwLitwRCcXPXDcA32ZpU4= +-----END PRIVATE KEY----- diff --git a/tests/data/ingress-mtls/client-auth/revoked/client-cert.pem b/tests/data/ingress-mtls/client-auth/revoked/client-cert.pem new file mode 100644 index 0000000000..52161ec1cd --- /dev/null +++ b/tests/data/ingress-mtls/client-auth/revoked/client-cert.pem @@ -0,0 +1,108 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Maryland, L=Baltimore, O=Test CA, Limited, OU=Server Research Department, CN=Test CA/emailAddress=test@example.com + Validity + Not Before: Mar 13 17:58:49 2023 GMT + Not After : Mar 12 17:58:49 2024 GMT + Subject: C=US, ST=MD, L=Baltimore, O=Test Server, Limited, CN=Test Server + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b2:0f:05:bb:7a:78:62:15:44:db:ae:fc:c1:4a: + 84:94:dc:04:2e:47:64:f3:16:f1:db:d6:87:25:72: + ac:3d:75:d1:66:4c:6a:7b:b6:40:6b:83:41:c1:0d: + 35:08:11:23:a0:e1:60:17:41:0f:98:28:aa:06:28: + bc:06:3b:70:49:4d:93:09:84:0e:7b:83:ee:2e:51: + 93:5f:c3:d6:8c:4a:c9:7b:88:08:2e:58:1a:d4:01: + 2c:e9:35:9d:37:57:28:54:ff:10:95:47:d6:e4:4d: + 4d:5f:ea:eb:4e:59:15:d7:df:83:1d:78:f7:97:96: + 69:84:61:ff:ed:b9:b9:ab:b5:51:aa:f1:29:87:07: + 4e:f2:40:d6:dd:07:e8:1b:38:fb:01:90:a5:91:dd: + 20:a5:23:7c:2a:ad:d0:06:12:b4:d2:8f:14:9b:95: + 79:38:54:27:62:1f:7a:27:d7:39:11:fe:ec:43:04: + 1e:58:fe:1b:98:0a:78:f1:2e:fc:9f:aa:3a:ea:c4: + b4:c1:e2:9c:97:23:59:29:dc:ae:e4:42:d8:0b:6d: + d3:f5:ee:7b:70:48:22:79:c4:12:cf:b1:9e:32:47: + c0:e0:77:c9:52:59:0d:54:7f:0c:36:e8:ee:7e:1a: + 13:f1:cd:6b:4a:56:63:0a:b2:1b:b2:55:64:0c:45: + 1f:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 32:E3:A1:81:20:9D:8A:37:D3:F4:04:A4:18:20:3E:97:29:A3:D6:9B + X509v3 Authority Key Identifier: + keyid:90:AA:F8:42:B6:84:01:09:18:39:76:A1:59:BF:19:29:04:94:6C:2B + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Subject Alternative Name: + DNS:example.com, DNS:webapp.example.com, DNS:mail.example.com, DNS:ftp.example.com + Netscape Comment: + OpenSSL Generated Certificate + Signature Algorithm: sha256WithRSAEncryption + 50:37:17:f3:ee:44:32:55:d7:29:5e:79:d2:f7:c2:12:f2:dd: + 5f:63:5e:fb:2d:97:0f:69:0a:f9:62:7f:2e:b0:e7:d5:00:3e: + f4:78:03:0d:fa:ac:de:c1:cb:69:c0:f3:c8:15:b0:71:1e:79: + f7:b8:0a:b9:76:e9:54:da:5e:20:04:7a:4b:f1:99:e1:fa:2b: + 3c:63:4a:67:a8:ef:7b:99:0d:95:fc:65:c4:b3:ff:25:25:97: + fc:33:45:a7:07:94:2f:09:9a:24:82:24:27:09:66:31:fe:cd: + 04:7c:4d:e1:2e:82:b0:a8:e9:37:e4:7b:6c:4c:06:19:04:0f: + 82:2d:8b:91:4c:4e:fd:87:ac:56:77:02:da:3f:36:08:0d:57: + 78:f0:14:2f:31:a0:74:30:cd:6a:58:de:9e:fa:a7:ce:a8:f5: + 7f:f4:2c:70:3c:a7:86:3d:2e:49:c8:06:a2:91:88:5e:98:d2: + d6:13:97:13:2f:53:e0:42:16:e1:e0:1e:09:e8:39:d7:4f:0b: + 14:d0:c6:33:28:08:f7:01:7c:69:a3:21:cf:8f:2d:bf:08:64: + 1a:fd:88:34:f9:7a:fd:b2:71:ba:9e:32:37:44:bb:6e:e3:a0: + 35:6a:e8:bf:cb:20:35:53:95:4d:46:ae:f6:a5:ab:d6:a1:13: + e2:ab:55:8e:eb:a2:25:d0:e0:ff:d3:d5:d5:7f:15:d2:72:b1: + a9:27:05:f5:fa:20:4c:74:f2:e4:af:8f:cf:a0:c4:03:86:f7: + f2:90:1f:77:87:92:1e:80:2c:8f:e9:26:a3:39:d7:04:9e:e5: + 2d:04:bb:05:43:a4:53:2b:b0:ec:f1:d0:5e:4a:81:64:84:3f: + ff:0a:32:74:d7:39:a7:54:83:ac:61:54:77:5f:fc:a2:5c:a3: + 98:9f:0c:fe:82:aa:40:3e:b2:93:f2:cf:4e:d8:21:d1:e0:16: + ac:cd:3c:57:88:e4:43:77:1a:1b:b8:d4:2b:fa:a6:93:60:d1: + b5:7f:ce:e0:6d:2d:21:cf:e2:2e:17:3b:d9:7a:62:78:9f:8f: + 26:1e:3e:e4:c6:13:22:12:9c:cc:9d:ad:34:6f:ac:bb:91:35: + e1:5e:22:fb:fe:db:5f:32:96:3b:e1:e2:e1:e1:6f:b6:29:20: + a4:df:9b:21:13:5c:88:5c:f6:f6:22:8f:a7:35:f4:3c:0c:e0: + 10:88:35:72:4f:ff:38:44:3e:4f:7f:4b:e6:54:c0:41:2c:1c: + aa:28:92:a9:78:11:c9:31:99:b2:2f:6f:2b:b1:34:01:8c:f2: + 92:44:7b:a5:a4:9a:31:96:12:24:02:bd:43:69:2a:a9:71:ff: + bc:90:b0:d0:c4:fe:0c:6d +-----BEGIN CERTIFICATE----- +MIIFXzCCA0egAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +ETAPBgNVBAgMCE1hcnlsYW5kMRIwEAYDVQQHDAlCYWx0aW1vcmUxGTAXBgNVBAoM +EFRlc3QgQ0EsIExpbWl0ZWQxIzAhBgNVBAsMGlNlcnZlciBSZXNlYXJjaCBEZXBh +cnRtZW50MRAwDgYDVQQDDAdUZXN0IENBMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4 +YW1wbGUuY29tMB4XDTIzMDMxMzE3NTg0OVoXDTI0MDMxMjE3NTg0OVowYzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgMAk1EMRIwEAYDVQQHDAlCYWx0aW1vcmUxHTAbBgNV +BAoMFFRlc3QgU2VydmVyLCBMaW1pdGVkMRQwEgYDVQQDDAtUZXN0IFNlcnZlcjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALIPBbt6eGIVRNuu/MFKhJTc +BC5HZPMW8dvWhyVyrD110WZManu2QGuDQcENNQgRI6DhYBdBD5goqgYovAY7cElN +kwmEDnuD7i5Rk1/D1oxKyXuICC5YGtQBLOk1nTdXKFT/EJVH1uRNTV/q605ZFdff +gx1495eWaYRh/+25uau1UarxKYcHTvJA1t0H6Bs4+wGQpZHdIKUjfCqt0AYStNKP +FJuVeThUJ2IfeifXORH+7EMEHlj+G5gKePEu/J+qOurEtMHinJcjWSncruRC2Att +0/Xue3BIInnEEs+xnjJHwOB3yVJZDVR/DDbo7n4aE/HNa0pWYwqyG7JVZAxFH4EC +AwEAAaOB2DCB1TAdBgNVHQ4EFgQUMuOhgSCdijfT9ASkGCA+lymj1pswHwYDVR0j +BBgwFoAUkKr4QraEAQkYOXahWb8ZKQSUbCswCQYDVR0TBAIwADALBgNVHQ8EBAMC +BaAwTQYDVR0RBEYwRIILZXhhbXBsZS5jb22CEndlYmFwcC5leGFtcGxlLmNvbYIQ +bWFpbC5leGFtcGxlLmNvbYIPZnRwLmV4YW1wbGUuY29tMCwGCWCGSAGG+EIBDQQf +Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOC +AgEAUDcX8+5EMlXXKV550vfCEvLdX2Ne+y2XD2kK+WJ/LrDn1QA+9HgDDfqs3sHL +acDzyBWwcR5597gKuXbpVNpeIAR6S/GZ4forPGNKZ6jve5kNlfxlxLP/JSWX/DNF +pweULwmaJIIkJwlmMf7NBHxN4S6CsKjpN+R7bEwGGQQPgi2LkUxO/YesVncC2j82 +CA1XePAULzGgdDDNaljenvqnzqj1f/QscDynhj0uScgGopGIXpjS1hOXEy9T4EIW +4eAeCeg5108LFNDGMygI9wF8aaMhz48tvwhkGv2INPl6/bJxup4yN0S7buOgNWro +v8sgNVOVTUau9qWr1qET4qtVjuuiJdDg/9PV1X8V0nKxqScF9fogTHTy5K+Pz6DE +A4b38pAfd4eSHoAsj+kmoznXBJ7lLQS7BUOkUyuw7PHQXkqBZIQ//woydNc5p1SD +rGFUd1/8olyjmJ8M/oKqQD6yk/LPTtgh0eAWrM08V4jkQ3caG7jUK/qmk2DRtX/O +4G0tIc/iLhc72XpieJ+PJh4+5MYTIhKczJ2tNG+su5E14V4i+/7bXzKWO+Hi4eFv +tikgpN+bIRNciFz29iKPpzX0PAzgEIg1ck//OEQ+T39L5lTAQSwcqiiSqXgRyTGZ +si9vK7E0AYzykkR7paSaMZYSJAK9Q2kqqXH/vJCw0MT+DG0= +-----END CERTIFICATE----- diff --git a/tests/data/ingress-mtls/client-auth/revoked/client-key.pem b/tests/data/ingress-mtls/client-auth/revoked/client-key.pem new file mode 100644 index 0000000000..29aa3cb919 --- /dev/null +++ b/tests/data/ingress-mtls/client-auth/revoked/client-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCyDwW7enhiFUTb +rvzBSoSU3AQuR2TzFvHb1oclcqw9ddFmTGp7tkBrg0HBDTUIESOg4WAXQQ+YKKoG +KLwGO3BJTZMJhA57g+4uUZNfw9aMSsl7iAguWBrUASzpNZ03VyhU/xCVR9bkTU1f +6utOWRXX34MdePeXlmmEYf/tubmrtVGq8SmHB07yQNbdB+gbOPsBkKWR3SClI3wq +rdAGErTSjxSblXk4VCdiH3on1zkR/uxDBB5Y/huYCnjxLvyfqjrqxLTB4pyXI1kp +3K7kQtgLbdP17ntwSCJ5xBLPsZ4yR8Dgd8lSWQ1Ufww26O5+GhPxzWtKVmMKshuy +VWQMRR+BAgMBAAECggEBAKR2la/d5hWKWaikD1elsaIhOkdYsFiL5+dLVlbzfT3j +df+MM4qDAyuK+BANV99UnVj68ptn/7RmUu0PcOQ8wHEkktxmOk5BxJzJwlrg82lv +pnxQYGYWAOmzED1zxPwZp+oiEboguc7zy7T9skwSosda7qspUV+VkW6yaga01ldO +v1TKrmWjgF/ENIAdbSQnlw+Be1Kn9Giw7IXz/euGzEA+UXEH1wVuwSuTsb6u+z7+ +sAE0N9bSCQbWeA+8xsL0d09g5l3y82Gu3ZOcCYguCWn9pruu5WKkwGix/kKAvMPd +6rXtNr9XzgTtiKW2G7IdSm+L/gbXf40UKCeYfq2vTMECgYEA2p924rQiQoT0SG5M +w0olh4GqOQzQjc4Z6ZvvC5CxJa+SN3X+94PdC+hbFQMyk2Xb3DLTtylwZwkPgfK7 +XZJAieuKNG5q6iUUExof8s2PHdwiEIrZ3q2f5n+Xqjv/2E7EfYhA2tAG2FQBw7av +BWmhaBOZZNffHx4rtg2/fMIziskCgYEA0IArzPttRIquLO79zlZv//XSbNuDCNq+ +sgXJsz5wFkb/AU7xbYXEvQNbcttD5fwCC9Jo0sLbl9+CO6K0zndIe7/C9VvH118Q +1DH6R7p1c4iHlt8s0K/r80xdQk5D7N634h9c9gr/vx3vK56MxPvR7JUTecIoIyIf +IC5XacTZEvkCgYBUkwYB05/BTf/WmVz225NDJaU9ZrizcvzRQ7KpLbNqGc6dx/b3 +t7pmpd++dDs3jFsOh1ch71T9dyLZqZZUL4TqFgWkHOcdZ3Spoxyi6GSqL4O6FI0O +OOq317pLb+ScwHQBABnezEUpoO4B0YVJucBoK9TWjzBQsHJGfnEKiXI5CQKBgQDD +B9Fw6ZL5NVvdjiR9eR9E5zXRO7gjdTJBpeZZM0N3oytvlt+AmktAnr5Q/sdRftyP +IF+LHlh4hMr2a6kDJFL55pNAHX0eeb9tLd62b7TjwEdMmi/6eUSVjc4CcuFY1bBd +5QZ45Cr8I80QGTwGGqPv0DaqgzI2QvmoiZCc0FRZSQKBgQDVzkBadKdbl3C0o+SH +oPqzbhO4ZnuEpCh39IXa7GsWpdHh5YrvO/W/6xOD3cAnkjNAYspW6k59QCVWy+QH +816ZeJH0/tWudGyNyTjbv05K5/UvKrWKFtUgEgdDLYS+/az4FOHmZ1I78wXYQ3cZ +k8y6CD0kDPyOEUiADfrwGdjfiw== +-----END PRIVATE KEY----- diff --git a/tests/data/ingress-mtls/policies/ingress-mtls-crl.yaml b/tests/data/ingress-mtls/policies/ingress-mtls-crl.yaml new file mode 100644 index 0000000000..b47db9c7de --- /dev/null +++ b/tests/data/ingress-mtls/policies/ingress-mtls-crl.yaml @@ -0,0 +1,10 @@ +apiVersion: k8s.nginx.org/v1 +kind: Policy +metadata: + name: ingress-mtls-policy +spec: + ingressMTLS: + clientCertSecret: ingress-mtls-secret + verifyClient: "on" + verifyDepth: 1 + crlFileName: webapp.crl diff --git a/tests/data/ingress-mtls/secret/ingress-mtls-secret-crl.yaml b/tests/data/ingress-mtls/secret/ingress-mtls-secret-crl.yaml new file mode 100644 index 0000000000..0df25da297 --- /dev/null +++ b/tests/data/ingress-mtls/secret/ingress-mtls-secret-crl.yaml @@ -0,0 +1,8 @@ +kind: Secret +metadata: + name: ingress-mtls-secret +apiVersion: v1 +type: nginx.org/ca +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdNekNDQkJ1Z0F3SUJBZ0lKQU51ZlJyMkJoLzliTUEwR0NTcUdTSWIzRFFFQkN3VUFNSUduTVFzd0NRWUQKVlFRR0V3SlZVekVSTUE4R0ExVUVDQXdJVFdGeWVXeGhibVF4RWpBUUJnTlZCQWNNQ1VKaGJIUnBiVzl5WlRFWgpNQmNHQTFVRUNnd1FWR1Z6ZENCRFFTd2dUR2x0YVhSbFpERWpNQ0VHQTFVRUN3d2FVMlZ5ZG1WeUlGSmxjMlZoCmNtTm9JRVJsY0dGeWRHMWxiblF4RURBT0JnTlZCQU1NQjFSbGMzUWdRMEV4SHpBZEJna3Foa2lHOXcwQkNRRVcKRUhSbGMzUkFaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNekV6TVRjMU5UQTJXaGNOTWpRd016RXlNVGMxTlRBMgpXakNCcHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ01DRTFoY25sc1lXNWtNUkl3RUFZRFZRUUhEQWxDCllXeDBhVzF2Y21VeEdUQVhCZ05WQkFvTUVGUmxjM1FnUTBFc0lFeHBiV2wwWldReEl6QWhCZ05WQkFzTUdsTmwKY25abGNpQlNaWE5sWVhKamFDQkVaWEJoY25SdFpXNTBNUkF3RGdZRFZRUUREQWRVWlhOMElFTkJNUjh3SFFZSgpLb1pJaHZjTkFRa0JGaEIwWlhOMFFHVjRZVzF3YkdVdVkyOXRNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DCkFnOEFNSUlDQ2dLQ0FnRUEyeU5QNHRoWjBzY1V0cDZ5SVArUGdXU3lucEIybWE3WkRlNzBobDY3OFdvRkZITXkKbUNyczJPNzhwV2wxZVFNcTBoZDA4UUNJTGErY1V4bmMwS3BQWkw4Um1BUUo3SnZHN3BuN1Mwb2tnMVBiTU82Zwo1ZWVldDBJdEh4Tkt1YWVGTTVKS0pLdFhmN0p6TWkwMTdDZTBXZ3V5ZHZWVUxENXFkM2ZLdW5UNlRTOUZ5blpLCjlmSE5MdGdBaFZnMHg2bWJGUlFBYXBUejFMaGhUaEt4eDRNbHI1WGpBS01la1d5T0d4am9WbUZubFNocXdqTWsKMVAyaCtiWlRrZnRxQWh4VzVwaGlGRmRrTW15dnIvYUQyRW9aU2xGa1RtSmtnQnhJaysvRzhZQWtjZXFOelo5eQpMLzRvWWU1VTdrV0lYZTlPT0k5djFpZW02ODE5bVNOU3dpVFZhOFRQcWR0elcwUHplYW1QZG9TckVWV0JlL3hZCk9ZWDhaaWF1NlVCU3U2bGQ1VUxBTGJYUlp6RHUxYzVvelZzdkN0cE1HV1oxZWtDVDhVNEdwRzhQUyszcUJkUGwKWUhxeWR0TnhGeFZ5OE1odU1IWnhacVY4dXpMTlRlakpram03V3dERHpBd1RIbm1uMVREdHZrVlBCQWZGenhuTgoreGRKdmZvQ21EUEsraHZmMUVRRGF4RU5sSHVYYnZpclNqL2FDaXJqTTdhb0UxR2VRSXo2MEk5QWpuTHc1a29tCmFCcjZadU1ET1ZFSmhBMnRnZXJOOGYzMFJHOGtBTWZTRUYwdUExWTVteEw2b0hueWw5SStmNlBmc2diSlIzMnQKM2s1S2RNQ2xSTTc1YmpaUDNIeVpWdGZVQ09iRnJPMlRVT2NUd29zUUlScXh5dVFJd0JYWHVFdTNBdEVDQXdFQQpBYU5nTUY0d0hRWURWUjBPQkJZRUZKQ3ErRUsyaEFFSkdEbDJvVm0vR1NrRWxHd3JNQjhHQTFVZEl3UVlNQmFBCkZKQ3ErRUsyaEFFSkdEbDJvVm0vR1NrRWxHd3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdDd1lEVlIwUEJBUUQKQWdFR01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQzhLRWg5ZVZFSmFneFU2dS9BcTJPR3dhQVlwc2hDdU1vTwpTRVhiRkhDWWI1VEIyUnUzOXJPQ21TTmljZVlUMnJTenZLenF2bzM4aW9Pc3ZsdUFxTUF5VzRJVG53R1FPZ2ZPCitpUG1FS1V0RERjQ2VOQWY0OTZacjR4R25XS2l3RE9SVEI5N001SndaTnRpTGRReTU3S05wUC9nM3BXVHo4Y3QKODA3VEJ0T25kVFhhWkhBV0RaU0lCMXFaUEZWMHhvRUtPdS9TWXh5c2U4ZDBaNGhtZDE0TWVrQzFCZ2w4Y1NRagowajhrdUhXb2pIaUdVcW1ZRTdYd0hMMzRkeGxzb3RIVWhiNHhkREdGYTJlKzBZUVpzSlhFQW9pclcxbkRVektyCk5uOUlpUlR4eHUraXBYR0ZqLzVFbFFGTjRlUmE4dFZrYzJjODlUZUtBYjVkZ2ZCM0tNTUlKM0NwMExKQ2hva2wKdWhLbXptL0xuZ3FYL0dSQXFSWDRIaE82ZmZKbldDb2NsUGVFeFA0MnQ3a21EMXRlZzkrRGhVbGxnRk1RS3JnYwpaUUlMZW9CNWw2NlBPeVFVdWZjUzRJN2VzaHNlWXI4bWtSelRJTDM3cmxURWR1bWtpYmNXYVE5TjhGdFBHbUVxCnhuVFZBeEQ5TlE0WWJkUjNub1RIbkREYm1XUWJIbmc4ZWtzeGpUTHcrdDVsWGxtQ09Mb2VWZ3VxZnVnSzhMTUsKTSs4MWNUNHp6bkhkU0pxcVBSYitBUlFDZ3ArZzYwRGtpTUx1NzdCbzZQQ2o5NzRtYnZwQnpPaVlIdThkak52Sgp0L1dMcWdPU25reithUGRwVGE5M0Q5YUlBS3V6WURPbmp3OW9TUytnZUd0TmRoWUdPeWxLdDE4ZndZMGsrUTJ2CkNMT1pYZEYrWmc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + ca.crl: LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tCk1JSURCRENCN1RBTkJna3Foa2lHOXcwQkFRc0ZBRENCcHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ00KQ0UxaGNubHNZVzVrTVJJd0VBWURWUVFIREFsQ1lXeDBhVzF2Y21VeEdUQVhCZ05WQkFvTUVGUmxjM1FnUTBFcwpJRXhwYldsMFpXUXhJekFoQmdOVkJBc01HbE5sY25abGNpQlNaWE5sWVhKamFDQkVaWEJoY25SdFpXNTBNUkF3CkRnWURWUVFEREFkVVpYTjBJRU5CTVI4d0hRWUpLb1pJaHZjTkFRa0JGaEIwWlhOMFFHVjRZVzF3YkdVdVkyOXQKRncweU16QXpNVE14T0RBeU1qSmFGdzB5TXpBME1USXhPREF5TWpKYU1CUXdFZ0lCQWhjTk1qTXdNekV6TVRndwpNakV5V2pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVJzQ1B6SVpqUmt1S1BlajRUdTc5a3pFTlcvRTY5NzZjClhrN2g1dEtoTHdONTROVXR0M0pSTHBWUEFwUFhnTzdhdVo5a0liWC9EaStyeks4V3BQZWhUSXg0b1RscktjbFoKT1hsM3RQWUJndmcyRzVxaFR3MlAvTjRDMzVPMWdtWllLWXFYeEd6SjlBVnU5WmNXUlJjelVCOXlaZlR1cERoOAo2SnROd2JCVVpOR2lSMkZFeUovWFNQQjFVeXJBa2IyVk1ON0E1WEZIaSt5WXFrS2xrcFNLaGNPY3lGcXpFMC9xCkQ5V1Y3enJtVDIwdU1Ya2VCVW05WEhqWHRXRTIwb01PRFBHRERBNUg2RlppL05IMXBTa0tUY3g4UjdYNGZlaFYKOUJUTVl5VENWcFVJSUhuZG91NHYxUkl2UHJpRS9PUGx4UDBjRFZCNmV1V0RXb2dJdnIyWTRpenlHdHN0WlpvTgpNZDBRY1hXTVhTUjB3U2hCdEQ1TGI5cjBLOExPS255dVFUVVNHaXZuY2JGajZNUTROU3FNMTRJdzNkOHowemowCjg5b3hBUVhNa29qdm02SWV5WS9hSlVacUlPdk56MXhkaG5kNXNtWkNoQUdTVUx4Z1hsZWFHRjg3Vyt2MThuSlQKOC83c1Vic09RR1ErdVA5dGNXcGYzcmx4MVVENWRnVW9KbHdrUk16Z09vQXYwN3JkcWRsZGQ4QVdWYndMcnlGdgo0RHVMTU5VREQrbE9iV3E0VDdBNE5zb1NadlBuaitOcDgzL3VCWEUvRmZvemJpYzJSOFZJb1NLR2NhWDh0aGZhCmpvUEw1Smt4akZGemZGcnAwMi9XRlNNd3Ezc2xrQkJqSGFkd2pNcTZiQnJ5MTQyYWlOUW44cDRsa3ZXV0RvUSsKaWdrSDNFRGdDVmM9Ci0tLS0tRU5EIFg1MDkgQ1JMLS0tLS0K diff --git a/tests/suite/test_ingress_mtls.py b/tests/suite/test_ingress_mtls.py index 170af4ab57..0993e4c345 100644 --- a/tests/suite/test_ingress_mtls.py +++ b/tests/suite/test_ingress_mtls.py @@ -7,6 +7,7 @@ from suite.utils.resources_utils import create_secret_from_yaml, delete_secret, wait_before_test from suite.utils.ssl_utils import create_sni_session from suite.utils.vs_vsr_resources_utils import ( + delete_and_create_vs_from_yaml, patch_v_s_route_from_yaml, patch_virtual_server_from_yaml, read_vs, @@ -33,6 +34,14 @@ invalid_crt = f"{TEST_DATA}/ingress-mtls/client-auth/invalid/client-cert.pem" invalid_key = f"{TEST_DATA}/ingress-mtls/client-auth/invalid/client-cert.pem" +mtls_secret_crl = f"{TEST_DATA}/ingress-mtls/secret/ingress-mtls-secret-crl.yaml" +mtls_pol_crl = f"{TEST_DATA}/ingress-mtls/policies/ingress-mtls-crl.yaml" + +crt_not_revoked = f"{TEST_DATA}/ingress-mtls/client-auth/not-revoked/client-cert.pem" +key_not_revoked = f"{TEST_DATA}/ingress-mtls/client-auth/not-revoked/client-key.pem" +crt_revoked = f"{TEST_DATA}/ingress-mtls/client-auth/revoked/client-cert.pem" +key_revoked = f"{TEST_DATA}/ingress-mtls/client-auth/revoked/client-key.pem" + def setup_policy(kube_apis, test_namespace, mtls_secret, tls_secret, policy): print(f"Create ingress-mtls secret") @@ -225,6 +234,158 @@ def test_ingress_mtls_policy_cert( ) assert resp.status_code == expected_code and expected_text in resp.text and exception in ssl_exception + @pytest.mark.smoke + @pytest.mark.parametrize( + "policy_src, vs_src, mtls_secret_in, expected_code, expected_text, vs_message, vs_state", + [ + ( + mtls_pol_valid_src, + mtls_vs_spec_src, + mtls_secret_crl, + 200, + "Server address:", + "added or updated", + "Valid", + ), + ( + mtls_pol_crl, + mtls_vs_spec_src, + mtls_sec_valid_src, + 404, + "Not Found", + "added or updated", + "Invalid", + ), + ( + mtls_pol_crl, + mtls_vs_spec_src, + mtls_secret_crl, + 404, + "Not Found", + "added or updated ; with warning(s)", + "Invalid", + ), + ], + ) + def test_ingress_mtls_polciy_crl( + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + policy_src, + mtls_secret_in, + vs_src, + expected_code, + expected_text, + vs_message, + vs_state, + ): + session = create_sni_session() + mtls_secret, tls_secret, pol_name = setup_policy( + kube_apis, + test_namespace, + mtls_secret_in, + tls_sec_valid_src, + policy_src, + ) + + delete_and_create_vs_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + vs_src, + virtual_server_setup.namespace, + ) + wait_before_test() + resp = session.get( + virtual_server_setup.backend_1_url_ssl, + cert=(crt_not_revoked, key_not_revoked), + headers={"host": virtual_server_setup.vs_host}, + allow_redirects=False, + verify=False, + ) + vs_res = read_vs(kube_apis.custom_objects, test_namespace, virtual_server_setup.vs_name) + teardown_policy(kube_apis, test_namespace, tls_secret, pol_name, mtls_secret) + + delete_and_create_vs_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + std_vs_src, + virtual_server_setup.namespace, + ) + assert ( + resp.status_code == expected_code + and expected_text in resp.text + and vs_message in vs_res["status"]["message"] + and vs_res["status"]["state"] == vs_state + ) + + @pytest.mark.parametrize( + "certificate, expected_code, expected_text, exception", + [ + ((crt_not_revoked, key_not_revoked), 200, "Server address:", ""), + ("", 400, "No required SSL certificate was sent", ""), + ((crt_revoked, key_revoked), 400, "The SSL certificate error", ""), + ], + ) + def test_ingress_mtls_policy_cert_crl( + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + certificate, + expected_code, + expected_text, + exception, + ): + """ + Test ingress-mtls with valid and invalid policy + """ + session = create_sni_session() + mtls_secret, tls_secret, pol_name = setup_policy( + kube_apis, + test_namespace, + mtls_secret_crl, + tls_sec_valid_src, + mtls_pol_valid_src, + ) + + print(f"Patch vs with policy: {mtls_pol_valid_src}") + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + mtls_vs_spec_src, + virtual_server_setup.namespace, + ) + wait_before_test() + ssl_exception = "" + resp = "" + try: + resp = session.get( + virtual_server_setup.backend_1_url_ssl, + cert=certificate, + headers={"host": virtual_server_setup.vs_host}, + allow_redirects=False, + verify=False, + ) + except requests.exceptions.SSLError as e: + print(f"SSL certificate exception: {e}") + ssl_exception = str(e) + resp = mock.Mock() + resp.status_code = "None" + resp.text = "None" + + teardown_policy(kube_apis, test_namespace, tls_secret, pol_name, mtls_secret) + + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + std_vs_src, + virtual_server_setup.namespace, + ) + assert resp.status_code == expected_code and expected_text in resp.text and exception in ssl_exception + @pytest.mark.policies @pytest.mark.parametrize(