diff --git a/cmd/approver/main.go b/cmd/approver/main.go deleted file mode 100644 index abcf4c3..0000000 --- a/cmd/approver/main.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "fmt" - "os" - - ctrl "sigs.k8s.io/controller-runtime" - - "github.com/cert-manager/csi-driver-spiffe/internal/approver/app" -) - -func main() { - cmd := app.NewCommand(ctrl.SetupSignalHandler()) - if err := cmd.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } -} diff --git a/cmd/csi/main.go b/cmd/main.go similarity index 100% rename from cmd/csi/main.go rename to cmd/main.go diff --git a/deploy/charts/csi-driver-spiffe/README.md b/deploy/charts/csi-driver-spiffe/README.md index cf3853d..6d16e37 100644 --- a/deploy/charts/csi-driver-spiffe/README.md +++ b/deploy/charts/csi-driver-spiffe/README.md @@ -13,50 +13,27 @@ For example: ```yaml registry: quay.io -repository: - driver: jetstack/cert-manager-csi-driver-spiffe - approver: jetstack/cert-manager-csi-driver-spiffe-approver +repository: jetstack/cert-manager-csi-driver-spiffe ``` -#### **image.repository.driver** ~ `string` +#### **image.repository** ~ `string` > Default value: > ```yaml > quay.io/jetstack/cert-manager-csi-driver-spiffe > ``` -Target image repository for the csi-driver driver DaemonSet. -#### **image.repository.approver** ~ `string` -> Default value: -> ```yaml -> quay.io/jetstack/cert-manager-csi-driver-spiffe-approver -> ``` - -Target image repository for the csi-driver approver Deployment. +Target image repository. #### **image.tag** ~ `string` Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. -#### **image.digest** ~ `object` -> Default value: -> ```yaml -> {} -> ``` -#### **image.digest.driver** ~ `string` - -Target csi-driver driver digest. Override any tag, if set. -For example: - -```yaml -driver: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 -``` - -#### **image.digest.approver** ~ `string` +#### **image.digest** ~ `string` -Target csi-driver approver digest. Override any tag, if set. +Target image digest. Override any tag, if set. For example: ```yaml -approver: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 +digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 ``` #### **image.pullPolicy** ~ `string` @@ -65,14 +42,14 @@ approver: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb2 > IfNotPresent > ``` -Kubernetes imagePullPolicy on DaemonSet. +Kubernetes imagePullPolicy on Deployment. #### **imagePullSecrets** ~ `array` > Default value: > ```yaml > [] > ``` -Optional secrets used for pulling the csi-driver-spiffe and csi-driver-spiffe-approver container images +Optional secrets used for pulling the csi-driver-spiffe container image For example: @@ -316,102 +293,6 @@ Kubernetes imagePullPolicy on liveness probe. > ``` The port that will expose the liveness of the csi-driver -#### **app.approver.replicaCount** ~ `number` -> Default value: -> ```yaml -> 1 -> ``` - -Number of replicas of the approver to run. -#### **app.approver.signerName** ~ `string` -> Default value: -> ```yaml -> clusterissuers.cert-manager.io/* -> ``` - -The signer name that csi-driver-spiffe approver will be given permission to approve and deny. CertificateRequests referencing this signer name can be processed by the SPIFFE approver. See: https://cert-manager.io/docs/concepts/certificaterequest/#approval -#### **app.approver.readinessProbe.port** ~ `number` -> Default value: -> ```yaml -> 6060 -> ``` - -Container port to expose csi-driver-spiffe-approver HTTP readiness probe on default network interface. -#### **app.approver.metrics.port** ~ `number` -> Default value: -> ```yaml -> 9402 -> ``` - -Port for exposing Prometheus metrics on 0.0.0.0 on path '/metrics'. -#### **app.approver.metrics.service.enabled** ~ `bool` -> Default value: -> ```yaml -> true -> ``` - -Create a Service resource to expose metrics endpoint. -#### **app.approver.metrics.service.type** ~ `string` -> Default value: -> ```yaml -> ClusterIP -> ``` - -Service type to expose metrics. -#### **app.approver.metrics.service.servicemonitor.enabled** ~ `bool` -> Default value: -> ```yaml -> false -> ``` - -Create Prometheus ServiceMonitor resource for cert-manager-csi-driver-spiffe approver. -#### **app.approver.metrics.service.servicemonitor.prometheusInstance** ~ `string` -> Default value: -> ```yaml -> default -> ``` - -The value for the "prometheus" label on the ServiceMonitor. This allows for multiple Prometheus instances selecting difference ServiceMonitors using label selectors. -#### **app.approver.metrics.service.servicemonitor.interval** ~ `string` -> Default value: -> ```yaml -> 10s -> ``` - -The interval that the Prometheus will scrape for metrics. -#### **app.approver.metrics.service.servicemonitor.scrapeTimeout** ~ `string` -> Default value: -> ```yaml -> 5s -> ``` - -The timeout on each metric probe request. -#### **app.approver.metrics.service.servicemonitor.labels** ~ `object` -> Default value: -> ```yaml -> {} -> ``` - -Additional labels to give the ServiceMonitor resource. -#### **app.approver.resources** ~ `object` -> Default value: -> ```yaml -> {} -> ``` - -Kubernetes pod resource limits for cert-manager-csi-driver-spiffe approver - -For example: - -```yaml -resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi -``` #### **priorityClassName** ~ `string` > Default value: > ```yaml diff --git a/deploy/charts/csi-driver-spiffe/templates/_helpers.tpl b/deploy/charts/csi-driver-spiffe/templates/_helpers.tpl index b1d2dd0..5394b89 100644 --- a/deploy/charts/csi-driver-spiffe/templates/_helpers.tpl +++ b/deploy/charts/csi-driver-spiffe/templates/_helpers.tpl @@ -42,32 +42,3 @@ See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linke {{- if .digest -}}{{ printf "@%s" .digest }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} {{- end }} {{- end }} - -{{/* -Variants of the above image template which are addapted for the custom values format used in this chart: - registry: quay.io - repository: - driver: jetstack/cert-manager-csi-driver-spiffe - approver: jetstack/cert-manager-csi-driver-spiffe-approver - tag: vX.Y.Z - digest: - driver: sha256:... - approver: sha256:... - pullPolicy: IfNotPresent -*/}} -{{- define "image-driver" -}} -{{- $defaultTag := index . 1 -}} -{{- with index . 0 -}} -{{- if .registry -}}{{ printf "%s/%s" .registry .repository.driver }}{{- else -}}{{- .repository.driver -}}{{- end -}} -{{- if .digest.driver -}}{{ printf "@%s" .digest.driver }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} -{{- end }} -{{- end }} - -{{- define "image-approver" -}} -{{- $defaultTag := index . 1 -}} -{{- with index . 0 -}} -{{- if .registry -}}{{ printf "%s/%s" .registry .repository.approver }}{{- else -}}{{- .repository.approver -}}{{- end -}} -{{- if .digest.approver -}}{{ printf "@%s" .digest.approver }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} -{{- end }} -{{- end }} - diff --git a/deploy/charts/csi-driver-spiffe/templates/clusterrole.yaml b/deploy/charts/csi-driver-spiffe/templates/clusterrole.yaml index 7d8690c..f2e2285 100644 --- a/deploy/charts/csi-driver-spiffe/templates/clusterrole.yaml +++ b/deploy/charts/csi-driver-spiffe/templates/clusterrole.yaml @@ -8,25 +8,3 @@ rules: - apiGroups: ["cert-manager.io"] resources: ["certificaterequests"] verbs: ["watch", "create", "delete", "list"] ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - labels: - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver -rules: -- apiGroups: ["cert-manager.io"] - resources: ["certificaterequests"] - verbs: ["list", "watch"] -- apiGroups: ["cert-manager.io"] - resources: ["certificaterequests/status"] - verbs: ["update"] - -- apiGroups: ["cert-manager.io"] - resources: ["signers"] - verbs: ["approve"] - resourceNames: ["{{.Values.app.approver.signerName}}"] -- apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] diff --git a/deploy/charts/csi-driver-spiffe/templates/clusterrolebinding.yaml b/deploy/charts/csi-driver-spiffe/templates/clusterrolebinding.yaml index b0eea5c..43de11d 100644 --- a/deploy/charts/csi-driver-spiffe/templates/clusterrolebinding.yaml +++ b/deploy/charts/csi-driver-spiffe/templates/clusterrolebinding.yaml @@ -12,18 +12,3 @@ subjects: - kind: ServiceAccount name: {{ include "cert-manager-csi-driver-spiffe.name" . }} namespace: {{ .Release.Namespace }} ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - labels: - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver -subjects: -- kind: ServiceAccount - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - namespace: {{ .Release.Namespace }} diff --git a/deploy/charts/csi-driver-spiffe/templates/daemonset.yaml b/deploy/charts/csi-driver-spiffe/templates/daemonset.yaml index efee836..886120d 100644 --- a/deploy/charts/csi-driver-spiffe/templates/daemonset.yaml +++ b/deploy/charts/csi-driver-spiffe/templates/daemonset.yaml @@ -60,7 +60,7 @@ spec: add: ["SYS_ADMIN"] allowPrivilegeEscalation: true runAsUser: 0 - image: "{{ template "image-driver" (tuple .Values.image $.Chart.AppVersion) }}" + image: "{{ template "image" (tuple .Values.image $.Chart.AppVersion) }}" imagePullPolicy: {{ .Values.image.pullPolicy }} args : - --log-level={{ .Values.app.logLevel }} diff --git a/deploy/charts/csi-driver-spiffe/templates/deployment.yaml b/deploy/charts/csi-driver-spiffe/templates/deployment.yaml deleted file mode 100644 index cd30823..0000000 --- a/deploy/charts/csi-driver-spiffe/templates/deployment.yaml +++ /dev/null @@ -1,54 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - namespace: {{ .Release.Namespace }} - labels: - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.app.approver.replicaCount }} - selector: - matchLabels: - app: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - template: - metadata: - labels: - app: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 8 }} - spec: - serviceAccountName: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - containers: - - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - image: "{{ template "image-approver" (tuple .Values.image $.Chart.AppVersion) }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - containerPort: {{ .Values.app.approver.metrics.port }} - readinessProbe: - httpGet: - port: {{ .Values.app.approver.readinessProbe.port }} - path: "/readyz" - initialDelaySeconds: 3 - periodSeconds: 7 - args: - - --log-level={{ .Values.app.logLevel }} - - --csi-driver-name={{ .Values.app.name }} - - - --certificate-request-duration={{ .Values.app.certificateRequestDuration }} - - --issuer-name={{ .Values.app.issuer.name }} - - --issuer-kind={{ .Values.app.issuer.kind }} - - --issuer-group={{ .Values.app.issuer.group }} - - --trust-domain={{ .Values.app.trustDomain }} - - - --leader-election-namespace=$(POD_NAMESPACE) - - "--metrics-bind-address=:{{.Values.app.approver.metrics.port}}" - - "--readiness-probe-bind-address=:{{.Values.app.approver.readinessProbe.port}}" - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - resources: -{{- toYaml .Values.app.approver.resources | nindent 12 }} - {{- with .Values.priorityClassName }} - priorityClassName: {{ . | quote }} - {{- end }} diff --git a/deploy/charts/csi-driver-spiffe/templates/metrics-service.yaml b/deploy/charts/csi-driver-spiffe/templates/metrics-service.yaml deleted file mode 100644 index cb84ae3..0000000 --- a/deploy/charts/csi-driver-spiffe/templates/metrics-service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.app.approver.metrics.service.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver-metrics - namespace: {{ .Release.Namespace }} - labels: - app: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} -spec: - type: {{ .Values.app.approver.metrics.service.type }} - ports: - - port: {{ .Values.app.approver.metrics.port }} - targetPort: {{ .Values.app.approver.metrics.port }} - protocol: TCP - name: metrics - selector: - app: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver -{{- end }} diff --git a/deploy/charts/csi-driver-spiffe/templates/metrics-servicemonitor.yaml b/deploy/charts/csi-driver-spiffe/templates/metrics-servicemonitor.yaml deleted file mode 100644 index 5174c04..0000000 --- a/deploy/charts/csi-driver-spiffe/templates/metrics-servicemonitor.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if and .Values.app.approver.metrics.service.enabled .Values.app.approver.metrics.service.servicemonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - labels: - app: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} - prometheus: {{ .Values.app.approver.metrics.service.servicemonitor.prometheusInstance }} -{{- if .Values.app.approver.metrics.service.servicemonitor.labels }} -{{ toYaml .Values.app.approver.metrics.service.servicemonitor.labels | indent 4}} -{{- end }} -spec: - jobLabel: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - selector: - matchLabels: - app: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} - endpoints: - - targetPort: {{ .Values.app.approver.metrics.port }} - path: "/metrics" - interval: {{ .Values.app.approver.metrics.service.servicemonitor.interval }} - scrapeTimeout: {{ .Values.app.approver.metrics.service.servicemonitor.scrapeTimeout }} -{{- end }} diff --git a/deploy/charts/csi-driver-spiffe/templates/role.yaml b/deploy/charts/csi-driver-spiffe/templates/role.yaml deleted file mode 100644 index 8df5440..0000000 --- a/deploy/charts/csi-driver-spiffe/templates/role.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - namespace: {{ .Release.Namespace }} - labels: - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} -rules: -- apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["get", "update", "create"] diff --git a/deploy/charts/csi-driver-spiffe/templates/rolebinding.yaml b/deploy/charts/csi-driver-spiffe/templates/rolebinding.yaml deleted file mode 100644 index c5f5f0f..0000000 --- a/deploy/charts/csi-driver-spiffe/templates/rolebinding.yaml +++ /dev/null @@ -1,15 +0,0 @@ -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - namespace: {{ .Release.Namespace }} - labels: - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver -subjects: -- kind: ServiceAccount - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver - namespace: {{ .Release.Namespace }} diff --git a/deploy/charts/csi-driver-spiffe/templates/serviceaccount.yaml b/deploy/charts/csi-driver-spiffe/templates/serviceaccount.yaml index d28649c..e578c2f 100644 --- a/deploy/charts/csi-driver-spiffe/templates/serviceaccount.yaml +++ b/deploy/charts/csi-driver-spiffe/templates/serviceaccount.yaml @@ -9,15 +9,3 @@ metadata: labels: {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} name: {{ include "cert-manager-csi-driver-spiffe.name" . }} ---- -apiVersion: v1 -kind: ServiceAccount -{{- with .Values.imagePullSecrets }} -imagePullSecrets: - {{- toYaml . | nindent 8 }} -{{- end }} -metadata: - namespace: {{ .Release.Namespace }} - labels: - {{- include "cert-manager-csi-driver-spiffe.labels" . | nindent 4 }} - name: {{ include "cert-manager-csi-driver-spiffe.name" . }}-approver diff --git a/deploy/charts/csi-driver-spiffe/values.schema.json b/deploy/charts/csi-driver-spiffe/values.schema.json index 0bf6d55..2003f82 100644 --- a/deploy/charts/csi-driver-spiffe/values.schema.json +++ b/deploy/charts/csi-driver-spiffe/values.schema.json @@ -27,9 +27,6 @@ "helm-values.app": { "additionalProperties": false, "properties": { - "approver": { - "$ref": "#/$defs/helm-values.app.approver" - }, "certificateRequestDuration": { "$ref": "#/$defs/helm-values.app.certificateRequestDuration" }, @@ -54,144 +51,6 @@ }, "type": "object" }, - "helm-values.app.approver": { - "additionalProperties": false, - "properties": { - "metrics": { - "$ref": "#/$defs/helm-values.app.approver.metrics" - }, - "readinessProbe": { - "$ref": "#/$defs/helm-values.app.approver.readinessProbe" - }, - "replicaCount": { - "$ref": "#/$defs/helm-values.app.approver.replicaCount" - }, - "resources": { - "$ref": "#/$defs/helm-values.app.approver.resources" - }, - "signerName": { - "$ref": "#/$defs/helm-values.app.approver.signerName" - } - }, - "type": "object" - }, - "helm-values.app.approver.metrics": { - "additionalProperties": false, - "properties": { - "port": { - "$ref": "#/$defs/helm-values.app.approver.metrics.port" - }, - "service": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service" - } - }, - "type": "object" - }, - "helm-values.app.approver.metrics.port": { - "default": 9402, - "description": "Port for exposing Prometheus metrics on 0.0.0.0 on path '/metrics'.", - "type": "number" - }, - "helm-values.app.approver.metrics.service": { - "additionalProperties": false, - "properties": { - "enabled": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.enabled" - }, - "servicemonitor": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.servicemonitor" - }, - "type": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.type" - } - }, - "type": "object" - }, - "helm-values.app.approver.metrics.service.enabled": { - "default": true, - "description": "Create a Service resource to expose metrics endpoint.", - "type": "boolean" - }, - "helm-values.app.approver.metrics.service.servicemonitor": { - "additionalProperties": false, - "properties": { - "enabled": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.servicemonitor.enabled" - }, - "interval": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.servicemonitor.interval" - }, - "labels": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.servicemonitor.labels" - }, - "prometheusInstance": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.servicemonitor.prometheusInstance" - }, - "scrapeTimeout": { - "$ref": "#/$defs/helm-values.app.approver.metrics.service.servicemonitor.scrapeTimeout" - } - }, - "type": "object" - }, - "helm-values.app.approver.metrics.service.servicemonitor.enabled": { - "default": false, - "description": "Create Prometheus ServiceMonitor resource for cert-manager-csi-driver-spiffe approver.", - "type": "boolean" - }, - "helm-values.app.approver.metrics.service.servicemonitor.interval": { - "default": "10s", - "description": "The interval that the Prometheus will scrape for metrics.", - "type": "string" - }, - "helm-values.app.approver.metrics.service.servicemonitor.labels": { - "default": {}, - "description": "Additional labels to give the ServiceMonitor resource.", - "type": "object" - }, - "helm-values.app.approver.metrics.service.servicemonitor.prometheusInstance": { - "default": "default", - "description": "The value for the \"prometheus\" label on the ServiceMonitor. This allows for multiple Prometheus instances selecting difference ServiceMonitors using label selectors.", - "type": "string" - }, - "helm-values.app.approver.metrics.service.servicemonitor.scrapeTimeout": { - "default": "5s", - "description": "The timeout on each metric probe request.", - "type": "string" - }, - "helm-values.app.approver.metrics.service.type": { - "default": "ClusterIP", - "description": "Service type to expose metrics.", - "type": "string" - }, - "helm-values.app.approver.readinessProbe": { - "additionalProperties": false, - "properties": { - "port": { - "$ref": "#/$defs/helm-values.app.approver.readinessProbe.port" - } - }, - "type": "object" - }, - "helm-values.app.approver.readinessProbe.port": { - "default": 6060, - "description": "Container port to expose csi-driver-spiffe-approver HTTP readiness probe on default network interface.", - "type": "number" - }, - "helm-values.app.approver.replicaCount": { - "default": 1, - "description": "Number of replicas of the approver to run.", - "type": "number" - }, - "helm-values.app.approver.resources": { - "default": {}, - "description": "Kubernetes pod resource limits for cert-manager-csi-driver-spiffe approver\n\nFor example:\nresources:\n limits:\n cpu: 100m\n memory: 128Mi\n requests:\n cpu: 100m\n memory: 128Mi", - "type": "object" - }, - "helm-values.app.approver.signerName": { - "default": "clusterissuers.cert-manager.io/*", - "description": "The signer name that csi-driver-spiffe approver will be given permission to approve and deny. CertificateRequests referencing this signer name can be processed by the SPIFFE approver. See: https://cert-manager.io/docs/concepts/certificaterequest/#approval", - "type": "string" - }, "helm-values.app.certificateRequestDuration": { "default": "1h", "description": "Duration requested for requested certificates.", @@ -465,55 +324,21 @@ "type": "object" }, "helm-values.image.digest": { - "additionalProperties": false, - "default": {}, - "properties": { - "approver": { - "$ref": "#/$defs/helm-values.image.digest.approver" - }, - "driver": { - "$ref": "#/$defs/helm-values.image.digest.driver" - } - }, - "type": "object" - }, - "helm-values.image.digest.approver": { - "description": "Target csi-driver approver digest. Override any tag, if set.\nFor example:\napprover: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20", - "type": "string" - }, - "helm-values.image.digest.driver": { - "description": "Target csi-driver driver digest. Override any tag, if set.\nFor example:\ndriver: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20", + "description": "Target image digest. Override any tag, if set.\nFor example:\ndigest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20", "type": "string" }, "helm-values.image.pullPolicy": { "default": "IfNotPresent", - "description": "Kubernetes imagePullPolicy on DaemonSet.", + "description": "Kubernetes imagePullPolicy on Deployment.", "type": "string" }, "helm-values.image.registry": { - "description": "Target image registry. This value is prepended to the target image repository, if set.\nFor example:\nregistry: quay.io\nrepository:\n driver: jetstack/cert-manager-csi-driver-spiffe\n approver: jetstack/cert-manager-csi-driver-spiffe-approver", + "description": "Target image registry. This value is prepended to the target image repository, if set.\nFor example:\nregistry: quay.io\nrepository: jetstack/cert-manager-csi-driver-spiffe", "type": "string" }, "helm-values.image.repository": { - "additionalProperties": false, - "properties": { - "approver": { - "$ref": "#/$defs/helm-values.image.repository.approver" - }, - "driver": { - "$ref": "#/$defs/helm-values.image.repository.driver" - } - }, - "type": "object" - }, - "helm-values.image.repository.approver": { - "default": "quay.io/jetstack/cert-manager-csi-driver-spiffe-approver", - "description": "Target image repository for the csi-driver approver Deployment.", - "type": "string" - }, - "helm-values.image.repository.driver": { "default": "quay.io/jetstack/cert-manager-csi-driver-spiffe", - "description": "Target image repository for the csi-driver driver DaemonSet.", + "description": "Target image repository.", "type": "string" }, "helm-values.image.tag": { @@ -522,7 +347,7 @@ }, "helm-values.imagePullSecrets": { "default": [], - "description": "Optional secrets used for pulling the csi-driver-spiffe and csi-driver-spiffe-approver container images\n\nFor example:\nimagePullSecrets:\n- name: secret-name", + "description": "Optional secrets used for pulling the csi-driver-spiffe container image\n\nFor example:\nimagePullSecrets:\n- name: secret-name", "items": {}, "type": "array" }, diff --git a/deploy/charts/csi-driver-spiffe/values.yaml b/deploy/charts/csi-driver-spiffe/values.yaml index b4560ea..c443077 100644 --- a/deploy/charts/csi-driver-spiffe/values.yaml +++ b/deploy/charts/csi-driver-spiffe/values.yaml @@ -2,40 +2,28 @@ image: # Target image registry. This value is prepended to the target image repository, if set. # For example: # registry: quay.io - # repository: - # driver: jetstack/cert-manager-csi-driver-spiffe - # approver: jetstack/cert-manager-csi-driver-spiffe-approver + # repository: jetstack/cert-manager-csi-driver-spiffe # +docs:property # registry: quay.io - repository: - # Target image repository for the csi-driver driver DaemonSet. - driver: quay.io/jetstack/cert-manager-csi-driver-spiffe - # Target image repository for the csi-driver approver Deployment. - approver: quay.io/jetstack/cert-manager-csi-driver-spiffe-approver + # Target image repository. + repository: quay.io/jetstack/cert-manager-csi-driver-spiffe # Override the image tag to deploy by setting this variable. # If no value is set, the chart's appVersion is used. # +docs:property # tag: vX.Y.Z - digest: {} - # Target csi-driver driver digest. Override any tag, if set. - # For example: - # driver: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 - # +docs:property=image.digest.driver - # driver: sha256:... - - # Target csi-driver approver digest. Override any tag, if set. - # For example: - # approver: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 - # +docs:property=image.digest.approver - # approver: sha256:... + # Target image digest. Override any tag, if set. + # For example: + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + # +docs:property + # digest: sha256:... - # Kubernetes imagePullPolicy on DaemonSet. + # Kubernetes imagePullPolicy on Deployment. pullPolicy: IfNotPresent -# Optional secrets used for pulling the csi-driver-spiffe and csi-driver-spiffe-approver container images +# Optional secrets used for pulling the csi-driver-spiffe container image # # For example: # imagePullSecrets: @@ -161,55 +149,6 @@ app: # The port that will expose the liveness of the csi-driver port: 9809 - # Options for approver controller - approver: - # Number of replicas of the approver to run. - replicaCount: 1 - # The signer name that csi-driver-spiffe approver will be given - # permission to approve and deny. CertificateRequests referencing this - # signer name can be processed by the SPIFFE approver. See: - # https://cert-manager.io/docs/concepts/certificaterequest/#approval - signerName: "clusterissuers.cert-manager.io/*" - readinessProbe: - # Container port to expose csi-driver-spiffe-approver HTTP readiness - # probe on default network interface. - port: 6060 - - metrics: - # Port for exposing Prometheus metrics on 0.0.0.0 on path '/metrics'. - port: 9402 - # Service to expose metrics endpoint. - service: - # Create a Service resource to expose metrics endpoint. - enabled: true - # Service type to expose metrics. - type: ClusterIP - # ServiceMonitor resource for this Service. - servicemonitor: - # Create Prometheus ServiceMonitor resource for cert-manager-csi-driver-spiffe approver. - enabled: false - # The value for the "prometheus" label on the ServiceMonitor. This allows - # for multiple Prometheus instances selecting difference ServiceMonitors - # using label selectors. - prometheusInstance: default - # The interval that the Prometheus will scrape for metrics. - interval: 10s - # The timeout on each metric probe request. - scrapeTimeout: 5s - # Additional labels to give the ServiceMonitor resource. - labels: {} - # Kubernetes pod resource limits for cert-manager-csi-driver-spiffe approver - # - # For example: - # resources: - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - resources: {} - # Optional priority class to be used for the csi-driver pods. priorityClassName: "" diff --git a/internal/approver/app/app.go b/internal/approver/app/app.go deleted file mode 100644 index 84e6885..0000000 --- a/internal/approver/app/app.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package app - -import ( - "context" - "fmt" - - "github.com/cert-manager/cert-manager/pkg/api" - "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/scale/scheme" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/metrics/server" - - "github.com/cert-manager/csi-driver-spiffe/internal/approver/app/options" - "github.com/cert-manager/csi-driver-spiffe/internal/approver/controller" - "github.com/cert-manager/csi-driver-spiffe/internal/approver/evaluator" -) - -const ( - helpOutput = "A cert-manager Approver that is paired with a cert-manager SPIFFE CSI driver" -) - -var intscheme = runtime.NewScheme() - -func init() { - utilruntime.Must(scheme.AddToScheme(intscheme)) - utilruntime.Must(api.AddToScheme(intscheme)) -} - -// NewCommand returns an new command instance of the approver component of csi-driver-spiffe. -func NewCommand(ctx context.Context) *cobra.Command { - opts := options.New() - - cmd := &cobra.Command{ - Use: "csi-driver-spiffe-approver", - Short: helpOutput, - Long: helpOutput, - PreRunE: func(cmd *cobra.Command, args []string) error { - return opts.Complete() - }, - RunE: func(cmd *cobra.Command, args []string) error { - log := opts.Logr.WithName("main") - - mgr, err := ctrl.NewManager(opts.RestConfig, ctrl.Options{ - Scheme: intscheme, - LeaderElection: true, - LeaderElectionNamespace: opts.Controller.LeaderElectionNamespace, - LeaderElectionID: opts.DriverName, - LeaderElectionReleaseOnCancel: true, - LeaderElectionResourceLock: "leases", - ReadinessEndpointName: "/readyz", - HealthProbeBindAddress: opts.Controller.ReadyzAddress, - Metrics: server.Options{ - BindAddress: opts.Controller.MetricsAddress, - }, - Logger: opts.Logr.WithName("manager"), - }) - if err != nil { - return fmt.Errorf("failed to create manager: %w", err) - } - if err := mgr.AddReadyzCheck("manager", healthz.Ping); err != nil { - return err - } - - evaluator := evaluator.New(evaluator.Options{ - TrustDomain: opts.CertManager.TrustDomain, - CertificateRequestDuration: opts.CertManager.CertificateRequestDuration, - }) - - if err := controller.AddApprover(ctx, opts.Logr, controller.Options{ - IssuerRef: opts.CertManager.IssuerRef, - Evaluator: evaluator, - Manager: mgr, - }); err != nil { - return fmt.Errorf("failed to register approver controller: %w", err) - } - - log.Info("starting SPIFFE approver...") - - return mgr.Start(ctx) - }, - } - - opts.Prepare(cmd) - - return cmd -} diff --git a/internal/approver/app/options/options.go b/internal/approver/app/options/options.go deleted file mode 100644 index 8839081..0000000 --- a/internal/approver/app/options/options.go +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package options - -import ( - "time" - - cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" - "github.com/spf13/pflag" - _ "k8s.io/client-go/plugin/pkg/client/auth" - - "github.com/cert-manager/csi-driver-spiffe/internal/flags" -) - -// Options are the CSI Approver flag options. -type Options struct { - *flags.Flags - - // CertManager are options specific to created cert-manager - // CertificateRequests. - CertManager OptionsCertManager - - // Controller are options specific to the controller. - Controller OptionsController -} - -// OptionsController are options specific to the Kubernetes controller. -type OptionsController struct { - // ReadyzAddress is the TCP address for exposing the HTTP readiness probe - // which will be served on the HTTP path '/readyz'. - ReadyzAddress string - - // MetricsAddress is the TCP address for exposing HTTP Prometheus metrics - // which will be served on the HTTP path '/metrics'. The value "0" will - // disable exposing metrics. - MetricsAddress string - - // LeaderElectionNamespace is the namespace that the approver controller will - // lease election in. - LeaderElectionNamespace string -} - -// OptionsCertManager are options specific to cert-manager and the evaluator. -type OptionsCertManager struct { - // TrustDomain is the Trust Domain the evaluator will enforce requests request - // for. - TrustDomain string - - // CertificateRequestDuration is the duration the evaluator will enforce - // CertificateRequest request for. - CertificateRequestDuration time.Duration - - // IssuerRef is the issuer reference that will be used to match on created - // CertificateRequests. - IssuerRef cmmeta.ObjectReference -} - -func New() *Options { - o := new(Options) - o.Flags = flags.New(). - Add("cert-manager", o.addCertManagerFlags). - Add("Controller", o.addControllerFlags) - return o -} - -func (o *Options) addCertManagerFlags(fs *pflag.FlagSet) { - fs.StringVar(&o.CertManager.TrustDomain, "trust-domain", "cluster.local", - "The trust domain this approver ensures is present on requests.") - - fs.DurationVar(&o.CertManager.CertificateRequestDuration, "certificate-request-duration", time.Hour, - "The duration which is enforced for requests to have.") - - fs.StringVar(&o.CertManager.IssuerRef.Name, "issuer-name", "my-spiffe-ca", - "Name of issuer which is matched against to evaluate on.") - fs.StringVar(&o.CertManager.IssuerRef.Kind, "issuer-kind", "ClusterIssuer", - "Kind of issuer which is matched against to evaluate on.") - fs.StringVar(&o.CertManager.IssuerRef.Group, "issuer-group", "cert-manager.io", - "Group of issuer which is matched against to evaluate on.") -} - -func (o *Options) addControllerFlags(fs *pflag.FlagSet) { - fs.StringVar(&o.Controller.LeaderElectionNamespace, - "leader-election-namespace", "cert-manager", - "Namespace to use for controller leader election.") - - fs.StringVar(&o.Controller.ReadyzAddress, "readiness-probe-bind-address", ":6060", - "TCP address for exposing the HTTP readiness probe which will be served on "+ - "the HTTP path '/readyz'.") - - fs.StringVar(&o.Controller.MetricsAddress, "metrics-bind-address", ":9402", - "TCP address for exposing HTTP Prometheus metrics which will be served on the "+ - "HTTP path '/metrics'. The value \"0\" will disable exposing metrics.") -} diff --git a/internal/approver/controller/controller.go b/internal/approver/controller/controller.go deleted file mode 100644 index 6d7a9f3..0000000 --- a/internal/approver/controller/controller.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controller - -import ( - "context" - "os" - - apiutil "github.com/cert-manager/cert-manager/pkg/api/util" - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" - "github.com/go-logr/logr" - apierrors "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/predicate" - - "github.com/cert-manager/csi-driver-spiffe/internal/approver/evaluator" -) - -type Options struct { - // IssuerRef will be used to match against CertificateRequest that need - // evaluation. - IssuerRef cmmeta.ObjectReference - - // Evaluator will be used to evaluate whether CertificateRequests should be - // Approved or Denied. - Evaluator evaluator.Interface - - // Manager is a controller-runtime Manager that the Approver controller will - // be registered against. - Manager manager.Manager -} - -// approver watches for CertificateRequests which have been created by the -// SPIFFE CSI driver and evaluates whether they should be approved or denied. -type approver struct { - // log is logger for the approver controller. - log logr.Logger - - // client is a client for interacting with the Kubernetes API. - client client.Client - - // lister makes requests to the informer cache for getting and listing - // objects. - lister client.Reader - - // issuerRef is the issuerRef that will be matched on CertificateRequests for - // evaluation. - issuerRef cmmeta.ObjectReference - - // evaluator evaluates matched CertificateRequests for whether they should be - // approved or denied. - evaluator evaluator.Interface -} - -// AddApprover will register the approver controller. -func AddApprover(ctx context.Context, log logr.Logger, opts Options) error { - a := &approver{ - log: log.WithName("controller"), - client: opts.Manager.GetClient(), - lister: opts.Manager.GetCache(), - issuerRef: opts.IssuerRef, - evaluator: opts.Evaluator, - } - - return ctrl.NewControllerManagedBy(opts.Manager). - For(new(cmapi.CertificateRequest)). - WithEventFilter(predicate.NewPredicateFuncs(func(obj client.Object) bool { - var req cmapi.CertificateRequest - err := a.lister.Get(ctx, client.ObjectKeyFromObject(obj), &req) - if apierrors.IsNotFound(err) { - // Ignore CertificateRequests that have been deleted. - return false - } - - // If an error happens here and we do nothing, we run the risk of not - // processing CertificateRequests. - // Exiting error is the safest option, as it will force a resync on all - // CertificateRequests on start. - if err != nil { - a.log.Error(err, "failed to list all CertificateRequests, exiting error") - os.Exit(1) - } - - // Ignore requests that already have an Approved or Denied condition. - if apiutil.CertificateRequestIsApproved(&req) || apiutil.CertificateRequestIsDenied(&req) { - return false - } - - return req.Spec.IssuerRef == a.issuerRef - })). - Complete(a) -} - -// Reconcile is called when a CertificateRequest is synced which has been -// neither approved or denied yet, and matches the issuerRef configured. -func (a *approver) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - log := a.log.WithValues("namespace", req.NamespacedName.Namespace, "name", req.NamespacedName.Name) - log.V(2).Info("syncing certificaterequest") - defer log.V(2).Info("finished syncing certificaterequest") - - var cr cmapi.CertificateRequest - if err := a.lister.Get(ctx, req.NamespacedName, &cr); err != nil { - return ctrl.Result{}, client.IgnoreNotFound(err) - } - - if err := a.evaluator.Evaluate(&cr); err != nil { - log.Error(err, "denying request") - apiutil.SetCertificateRequestCondition(&cr, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "spiffe.csi.cert-manager.io", "Denied request: "+err.Error()) - return ctrl.Result{}, a.client.Status().Update(ctx, &cr) - } - - log.Info("approving request") - apiutil.SetCertificateRequestCondition(&cr, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "spiffe.csi.cert-manager.io", "Approved request") - return ctrl.Result{}, a.client.Status().Update(ctx, &cr) -} diff --git a/internal/approver/controller/controller_test.go b/internal/approver/controller/controller_test.go deleted file mode 100644 index e50e015..0000000 --- a/internal/approver/controller/controller_test.go +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controller - -import ( - "context" - "errors" - "testing" - "time" - - "github.com/cert-manager/cert-manager/pkg/api" - apiutil "github.com/cert-manager/cert-manager/pkg/api/util" - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" - "github.com/stretchr/testify/assert" - apiequality "k8s.io/apimachinery/pkg/api/equality" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2/klogr" - fakeclock "k8s.io/utils/clock/testing" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" - - "github.com/cert-manager/csi-driver-spiffe/internal/approver/evaluator" - "github.com/cert-manager/csi-driver-spiffe/internal/approver/evaluator/fake" -) - -func Test_Reconcile(t *testing.T) { - var ( - fixedTime = time.Date(2021, 01, 01, 01, 0, 0, 0, time.UTC) - fixedmetatime = &metav1.Time{Time: fixedTime} - fixedclock = fakeclock.NewFakeClock(fixedTime) - ) - - tests := map[string]struct { - existingCRObjects []client.Object - evaluator evaluator.Interface - expResult ctrl.Result - expError bool - expObjects []client.Object - }{ - "if CertificateRequest doesn't exist, ignore": { - existingCRObjects: []client.Object{}, - expResult: ctrl.Result{}, - expError: false, - evaluator: nil, - expObjects: []client.Object{}, - }, - "if evaluator returns error, update Denied with error": { - existingCRObjects: []client.Object{ - &cmapi.CertificateRequest{ - TypeMeta: metav1.TypeMeta{Kind: "CertificateRequest", APIVersion: "cert-manager.io/v1"}, - ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns", Name: "test-cr", ResourceVersion: "10"}, - }, - }, - expResult: ctrl.Result{}, - evaluator: fake.New().WithEvaluate(func(_ *cmapi.CertificateRequest) error { - return errors.New("this is an error") - }), - expError: false, - expObjects: []client.Object{ - &cmapi.CertificateRequest{ - TypeMeta: metav1.TypeMeta{Kind: "CertificateRequest", APIVersion: "cert-manager.io/v1"}, - ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns", Name: "test-cr", ResourceVersion: "11"}, - Status: cmapi.CertificateRequestStatus{ - Conditions: []cmapi.CertificateRequestCondition{ - cmapi.CertificateRequestCondition{ - Type: cmapi.CertificateRequestConditionDenied, - Status: cmmeta.ConditionTrue, - Reason: "spiffe.csi.cert-manager.io", - Message: "Denied request: this is an error", - LastTransitionTime: fixedmetatime, - }, - }, - }, - }, - }, - }, - "if evaluator doesn't return error, update Approved": { - existingCRObjects: []client.Object{ - &cmapi.CertificateRequest{ - TypeMeta: metav1.TypeMeta{Kind: "CertificateRequest", APIVersion: "cert-manager.io/v1"}, - ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns", Name: "test-cr", ResourceVersion: "10"}, - }, - }, - expResult: ctrl.Result{}, - evaluator: fake.New().WithEvaluate(func(_ *cmapi.CertificateRequest) error { - return nil - }), - expError: false, - expObjects: []client.Object{ - &cmapi.CertificateRequest{ - TypeMeta: metav1.TypeMeta{Kind: "CertificateRequest", APIVersion: "cert-manager.io/v1"}, - ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns", Name: "test-cr", ResourceVersion: "11"}, - Status: cmapi.CertificateRequestStatus{ - Conditions: []cmapi.CertificateRequestCondition{ - cmapi.CertificateRequestCondition{ - Type: cmapi.CertificateRequestConditionApproved, - Status: cmmeta.ConditionTrue, - Reason: "spiffe.csi.cert-manager.io", - Message: "Approved request", - LastTransitionTime: fixedmetatime, - }, - }, - }, - }, - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - apiutil.Clock = fixedclock - - fakeclient := fakeclient.NewClientBuilder(). - WithScheme(api.Scheme). - WithObjects(test.existingCRObjects...). - WithStatusSubresource(test.existingCRObjects...). - Build() - - a := &approver{ - client: fakeclient, - lister: fakeclient, - log: klogr.New(), - evaluator: test.evaluator, - } - - result, err := a.Reconcile(context.TODO(), ctrl.Request{NamespacedName: types.NamespacedName{Namespace: "test-ns", Name: "test-cr"}}) - assert.Equalf(t, test.expError, err != nil, "%v", err) - assert.Equal(t, test.expResult, result) - - for _, expectedObject := range test.expObjects { - expObj := expectedObject.(client.Object) - var actual client.Object - switch expObj.(type) { - case *cmapi.CertificateRequest: - actual = &cmapi.CertificateRequest{} - default: - t.Errorf("unexpected object kind in expected: %#+v", expObj) - } - - err := fakeclient.Get(context.TODO(), client.ObjectKeyFromObject(expObj), actual) - if err != nil { - t.Errorf("unexpected error getting expected object: %s", err) - } else if !apiequality.Semantic.DeepEqual(expObj, actual) { - t.Errorf("unexpected expected object, exp=%#+v got=%#+v", expObj, actual) - } - } - }) - } -} diff --git a/internal/approver/controller/test/controller.go b/internal/approver/controller/test/controller.go deleted file mode 100644 index 3eff4ec..0000000 --- a/internal/approver/controller/test/controller.go +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package test - -import ( - "time" - - "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/envtest" -) - -func init() { - wait.ForeverTestTimeout = time.Second * 60 -} - -var ( - env *envtest.Environment -) diff --git a/internal/approver/controller/test/controller_test.go b/internal/approver/controller/test/controller_test.go deleted file mode 100644 index 2f58707..0000000 --- a/internal/approver/controller/test/controller_test.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package test - -import ( - "os" - "testing" - - "github.com/onsi/ginkgo/v2" - "github.com/onsi/gomega" - "sigs.k8s.io/controller-runtime/pkg/envtest" -) - -func Test_controllers(t *testing.T) { - certManagerCrds := os.Getenv("CERT_MANAGER_CRDS") - if len(certManagerCrds) == 0 { - t.Fatal("CERT_MANAGER_CRDS must be set to the path of the cert-manager CRDs") - } - - env = &envtest.Environment{ - AttachControlPlaneOutput: false, - CRDDirectoryPaths: []string{certManagerCrds}, - } - - t.Logf("starting API server...") - if _, err := env.Start(); err != nil { - t.Fatalf("failed to start control plane: %v", err) - } - t.Logf("running API server at %q", env.Config.Host) - - // Register cleanup func to stop the api-server after the test has finished. - t.Cleanup(func() { - t.Log("stopping API server") - if err := env.Stop(); err != nil { - t.Fatalf("failed to shut down control plane: %v", err) - } - }) - - gomega.RegisterFailHandler(ginkgo.Fail) - - suiteConfig, reporterConfig := ginkgo.GinkgoConfiguration() - - // Turn on verbose by default to get spec names - reporterConfig.Verbose = true - // Turn on EmitSpecProgress to get spec progress (especially on interrupt) - suiteConfig.EmitSpecProgress = true - // Randomize specs as well as suites - suiteConfig.RandomizeAllSpecs = true - - ginkgo.RunSpecs(t, "unit-controller", suiteConfig, reporterConfig) -} diff --git a/internal/approver/controller/test/suite.go b/internal/approver/controller/test/suite.go deleted file mode 100644 index 5cdfaab..0000000 --- a/internal/approver/controller/test/suite.go +++ /dev/null @@ -1,183 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package test - -import ( - "context" - "errors" - - apiutil "github.com/cert-manager/cert-manager/pkg/api/util" - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/klog/v2/klogr" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/metrics/server" - - "github.com/cert-manager/csi-driver-spiffe/internal/approver/controller" - evaluatorfake "github.com/cert-manager/csi-driver-spiffe/internal/approver/evaluator/fake" -) - -var _ = Context("Approval", func() { - var ( - ctx context.Context - cancel func() - - cl client.Client - namespace corev1.Namespace - - evaluator = evaluatorfake.New() - issuerRef = cmmeta.ObjectReference{ - Name: "spiffe-ca", - Kind: "ClusterIssuer", - Group: "cert-manager.io", - } - ) - - JustBeforeEach(func() { - ctx, cancel = context.WithCancel(context.TODO()) - - scheme := runtime.NewScheme() - Expect(corev1.AddToScheme(scheme)).NotTo(HaveOccurred()) - Expect(cmapi.AddToScheme(scheme)).NotTo(HaveOccurred()) - - var err error - cl, err = client.New(env.Config, client.Options{Scheme: scheme}) - Expect(err).NotTo(HaveOccurred()) - - namespace = corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "test-csi-driver-spiffe-", - }, - } - Expect(cl.Create(ctx, &namespace)).NotTo(HaveOccurred()) - - log := klogr.New().WithName("testing") - mgr, err := ctrl.NewManager(env.Config, ctrl.Options{ - Scheme: scheme, - LeaderElection: true, - Metrics: server.Options{ - BindAddress: "0", - }, - LeaderElectionNamespace: namespace.Name, - LeaderElectionID: "cert-manager-csi-driver-spiffe-approver", - LeaderElectionReleaseOnCancel: true, - Logger: log, - }) - Expect(err).NotTo(HaveOccurred()) - - Expect(controller.AddApprover(ctx, log, controller.Options{ - Manager: mgr, - Evaluator: evaluator, - IssuerRef: issuerRef, - })).NotTo(HaveOccurred()) - - By("Running Approver controller") - go mgr.Start(ctx) - - By("Waiting for Leader Election") - <-mgr.Elected() - - By("Waiting for Informers to Sync") - Expect(mgr.GetCache().WaitForCacheSync(ctx)).Should(BeTrue()) - }) - - JustAfterEach(func() { - Expect(cl.Delete(ctx, &namespace)).NotTo(HaveOccurred()) - cancel() - }) - - It("should ignore CertificateRequest that have the wrong IssuerRef", func() { - cr := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "cert-manager-csi-driver-spiffe-", - Namespace: namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: []byte("request"), - IssuerRef: cmmeta.ObjectReference{ - Name: "not-spiffe-ca", - Kind: "ClusterIssuer", - Group: "cert-manager.io", - }, - }, - } - Expect(cl.Create(ctx, &cr)).NotTo(HaveOccurred()) - - Consistently(func() bool { - Eventually(func() error { - return cl.Get(ctx, client.ObjectKeyFromObject(&cr), &cr) - }).Should(BeNil()) - return apiutil.CertificateRequestIsApproved(&cr) || apiutil.CertificateRequestIsDenied(&cr) - }, "3s").Should(BeFalse(), "expected neither approved not denied") - }) - - It("should deny CertificateRequest when the evaluator returns error", func() { - evaluator.WithEvaluate(func(_ *cmapi.CertificateRequest) error { - return errors.New("this is an error") - }) - - cr := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "cert-manager-csi-driver-spiffe-", - Namespace: namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: []byte("request"), - IssuerRef: issuerRef, - }, - } - Expect(cl.Create(ctx, &cr)).NotTo(HaveOccurred()) - - Eventually(func() bool { - Eventually(func() error { - return cl.Get(ctx, client.ObjectKeyFromObject(&cr), &cr) - }).Should(BeNil()) - return apiutil.CertificateRequestIsDenied(&cr) - }).Should(BeTrue(), "expected denial") - }) - - It("should approve CertificateRequest when the evaluator returns nil", func() { - evaluator.WithEvaluate(func(_ *cmapi.CertificateRequest) error { - return nil - }) - - cr := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "cert-manager-csi-driver-spiffe-", - Namespace: namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: []byte("request"), - IssuerRef: issuerRef, - }, - } - Expect(cl.Create(ctx, &cr)).NotTo(HaveOccurred()) - - Eventually(func() bool { - Eventually(func() error { - return cl.Get(ctx, client.ObjectKeyFromObject(&cr), &cr) - }).Should(BeNil()) - return apiutil.CertificateRequestIsApproved(&cr) - }).Should(BeTrue(), "expected approval") - }) -}) diff --git a/internal/approver/evaluator/evaluator.go b/internal/approver/evaluator/evaluator.go deleted file mode 100644 index e2fc759..0000000 --- a/internal/approver/evaluator/evaluator.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package evaluator - -import ( - "fmt" - "time" - - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - "github.com/cert-manager/cert-manager/pkg/util" - utilpki "github.com/cert-manager/cert-manager/pkg/util/pki" -) - -var ( - requiedUsages = []cmapi.KeyUsage{ - cmapi.UsageKeyEncipherment, - cmapi.UsageDigitalSignature, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - } -) - -// Interface is the Evaluator which is used for determining whether a -// CertificateRequest should be approved or denied. -type Interface interface { - Evaluate(*cmapi.CertificateRequest) error -} - -// Options is the options to configure the evaluator. -type Options struct { - // TrustDomain is the trust domain that will be asserted when evaluating - // CertificateRequests URI SANs. - TrustDomain string - - // CertificateRequestDuration is the duration that users _must_ request for, - // else the request will be denied. - CertificateRequestDuration time.Duration -} - -// internal is the internal implementation of the evaluator that should be used -// when running the approver controller. -type internal struct { - // trustDomain is the trust domain that will be asserted when evaluating - // CertificateRequests URI SANs. - trustDomain string - - // certificateRequestDuration is the duration that users _must_ request for, - // else the request will be denied. - certificateRequestDuration time.Duration -} - -// New constructs a new evaluator. -func New(opts Options) Interface { - return &internal{ - trustDomain: opts.TrustDomain, - certificateRequestDuration: opts.CertificateRequestDuration, - } -} - -// Evaluate evaluates whether a CertificateRequest should be approved or -// denied. A CertificateRequest should be denied if this function returns an -// error, should be approved otherwise. -func (i *internal) Evaluate(req *cmapi.CertificateRequest) error { - csr, err := utilpki.DecodeX509CertificateRequestBytes(req.Spec.Request) - if err != nil { - return fmt.Errorf("failed to parse request: %w", err) - } - - if req.Spec.Duration == nil || req.Spec.Duration.Duration != i.certificateRequestDuration { - return fmt.Errorf("requested certificate doesn't match required, required=%q got=%v", - i.certificateRequestDuration.String(), req.Spec.Duration) - } - - if err := csr.CheckSignature(); err != nil { - return fmt.Errorf("signature check failed for csr: %w", err) - } - - // if the csr contains any other options set, error - if len(csr.DNSNames) > 0 || len(csr.IPAddresses) > 0 || - len(csr.Subject.CommonName) > 0 || len(csr.EmailAddresses) > 0 { - return fmt.Errorf("forbidden extensions, DNS=%q IPs=%q CommonName=%q Emails=%q", - csr.DNSNames, csr.IPAddresses, csr.Subject.CommonName, csr.EmailAddresses) - } - - if err := validateCSRExtentions(csr); err != nil { - return err - } - - if req.Spec.IsCA { - return fmt.Errorf("request contains spec.isCA=true") - } - - if !util.EqualKeyUsagesUnsorted(req.Spec.Usages, requiedUsages) { - return fmt.Errorf("request contains wrong usages, exp=%v got=%v", requiedUsages, req.Spec.Usages) - } - - if err := i.validateIdentity(csr, req.Spec.Username); err != nil { - return err - } - - return nil -} diff --git a/internal/approver/evaluator/evaluator_test.go b/internal/approver/evaluator/evaluator_test.go deleted file mode 100644 index 28a6f9a..0000000 --- a/internal/approver/evaluator/evaluator_test.go +++ /dev/null @@ -1,322 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package evaluator - -import ( - "bytes" - "encoding/pem" - "testing" - "time" - - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - utilpki "github.com/cert-manager/cert-manager/pkg/util/pki" - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" -) - -func Test_Evaluate(t *testing.T) { - pk, err := utilpki.GenerateECPrivateKey(utilpki.ECCurve521) - assert.NoError(t, err) - - tests := map[string]struct { - req func(t *testing.T) *cmapi.CertificateRequest - expErr bool - }{ - "if request contains a badly encoded PEM, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: []byte("bad-pem"), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - }} - }, - expErr: true, - }, - "if request duration is nil, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: nil, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request contains DNS names, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - DNSNames: []string{"example.com"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request contains IPs, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - IPAddresses: []string{"1.2.3.4"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request contains common name, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - CommonName: "example.com", - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request contains email addresses, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - EmailAddresses: []string{"alice@example.com"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request is with isCA=true, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - IsCA: true, - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request has the wrong usages, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request has the wrong usages encoded in the request, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - EncodeUsagesInRequest: pointer.Bool(true), - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - Usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - cmapi.UsageCertSign, cmapi.UsageCodeSigning, - }, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if request has the wrong identity, expect error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/httpbin"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: true, - }, - "if is valid, expect no error": { - req: func(t *testing.T) *cmapi.CertificateRequest { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: cmapi.ECDSAKeyAlgorithm}, - URIs: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - }, - }) - assert.NoError(t, err) - csrDER, err := utilpki.EncodeCSR(csr, pk) - assert.NoError(t, err) - csrPEM := bytes.NewBuffer([]byte{}) - assert.NoError(t, pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})) - return &cmapi.CertificateRequest{Spec: cmapi.CertificateRequestSpec{ - Request: csrPEM.Bytes(), - Duration: &metav1.Duration{Duration: time.Hour}, - Username: "system:serviceaccount:sandbox:sleep", - Usages: []cmapi.KeyUsage{ - cmapi.UsageServerAuth, cmapi.UsageClientAuth, - cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, - }, - }} - }, - expErr: false, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - i := &internal{ - trustDomain: "foo.bar", - certificateRequestDuration: time.Hour, - } - - err := i.Evaluate(test.req(t)) - assert.Equal(t, test.expErr, err != nil, "%v", err) - }) - } -} diff --git a/internal/approver/evaluator/extensions.go b/internal/approver/evaluator/extensions.go deleted file mode 100644 index 8521318..0000000 --- a/internal/approver/evaluator/extensions.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package evaluator - -import ( - "bytes" - "crypto/x509" - "crypto/x509/pkix" - "encoding/asn1" - "fmt" - - utilerrors "k8s.io/apimachinery/pkg/util/errors" -) - -const ( - // Mapping from the type of an identity to the OID tag value for the X.509 - // SAN field (see https://tools.ietf.org/html/rfc5280#appendix-A.2) - // - // SubjectAltName ::= GeneralNames - // - // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - // - // GeneralName ::= CHOICE { - // uniformResourceIdentifier [6] IA5String, - // } - asn1TagURI = 6 -) - -var ( - // Copied from https://github.com/golang/go/blob/dev.boringcrypto.go1.16/src/crypto/x509/x509.go - oidExtensionKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15} - oidExtensionExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37} - oidExtensionSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17} - - oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} - oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} - - allowedKeyUsages = [][]byte{ - {3, 2, 7, 128}, // x509.KeyUsageDigitalSignature - {3, 2, 5, 32}, // x509.KeyUsageKeyEncipherment - } -) - -// validateCSRExtentions validates the given certificate signing request -// contains only valid extensions, including URI sans, key usages, and extended -// key usages. Any other extensions will error. -func validateCSRExtentions(csr *x509.CertificateRequest) error { - var el []error - - if len(csr.ExtraExtensions) > 0 { - el = append(el, fmt.Errorf("forbidden extensions: %v", csr.Extensions)) - } - - for _, extension := range csr.Extensions { - switch { - case extension.Id.Equal(oidExtensionSubjectAltName): - el = append(el, validateSubjectAltNameExtension(extension)) - - case extension.Id.Equal(oidExtensionKeyUsage): - el = append(el, validateKeyUsageExtension(extension.Value)) - - case extension.Id.Equal(oidExtensionExtendedKeyUsage): - el = append(el, validateExtendedKeyUsageExtension(extension)) - - default: - el = append(el, fmt.Errorf("forbidden extension: %s", extension.Id)) - } - } - - return utilerrors.NewAggregate(el) -} - -// validateKeyUsageExtension validates that the passed extension value contains -// accepted key usages -func validateKeyUsageExtension(value []byte) error { - if len(value) != 4 { - return fmt.Errorf("forbidden key usage: %v", value) - } - - extValue := make([]byte, len(value)) - copy(extValue, value) - - // Clear allowed usages bits from value - for _, usage := range allowedKeyUsages { - for i, b := range usage { - extValue[i] = extValue[i] &^ b - } - } - - // If usage bits are not empty, forbidden usages used - if !bytes.Equal(extValue, []byte{0, 0, 0, 0}) { - return fmt.Errorf("forbidden key usage: %v", value) - } - - return nil -} - -// validateExtendedKeyUsageExtension validates that the passed extension -// contains accepted extended key usages -func validateExtendedKeyUsageExtension(extension pkix.Extension) error { - if !extension.Id.Equal(oidExtensionExtendedKeyUsage) { - return fmt.Errorf("non extended key usage extension: %s", extension.Id) - } - - var asn1ExtendedUsages []asn1.ObjectIdentifier - _, err := asn1.Unmarshal(extension.Value, &asn1ExtendedUsages) - if err != nil { - return fmt.Errorf("failed to parse extended key usages: %s", err) - } - - var el []error - for _, usage := range asn1ExtendedUsages { - if !usage.Equal(oidExtKeyUsageClientAuth) && !usage.Equal(oidExtKeyUsageServerAuth) { - el = append(el, fmt.Errorf("forbidden extended key usage: %s", usage)) - } - } - - return utilerrors.NewAggregate(el) -} - -// validateSubjectAltNameExtension validates that the passed extension is a -// correctly encoded URI SAN, and is no other SAN type -func validateSubjectAltNameExtension(ext pkix.Extension) error { - if !ext.Id.Equal(oidExtensionSubjectAltName) { - return fmt.Errorf("extension is not a SAN type: %s", ext.Id) - } - - var sequence asn1.RawValue - if rest, err := asn1.Unmarshal(ext.Value, &sequence); err != nil { - return fmt.Errorf("failed to unmarshal san extension: %v", err) - } else if len(rest) != 0 { - return fmt.Errorf("san extension incorrectly encoded: %v", ext.Value) - } - - // Check the rawValue is a sequence. - if !sequence.IsCompound || sequence.Tag != asn1.TagSequence || sequence.Class != asn1.ClassUniversal { - return fmt.Errorf("san extension is incorrectly encoded: %v", ext.Value) - } - - for bytes := sequence.Bytes; len(bytes) > 0; { - var ( - rawValue asn1.RawValue - err error - ) - - bytes, err = asn1.Unmarshal(bytes, &rawValue) - if err != nil { - return err - } - - // Only URI SANs are permitted for SPIFFE certificates - if rawValue.Tag != asn1TagURI { - return fmt.Errorf("non uri san extension given: %s", rawValue.Bytes) - } - } - - return nil -} diff --git a/internal/approver/evaluator/extensions_test.go b/internal/approver/evaluator/extensions_test.go deleted file mode 100644 index 737b1ea..0000000 --- a/internal/approver/evaluator/extensions_test.go +++ /dev/null @@ -1,378 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package evaluator - -import ( - "crypto/x509" - "crypto/x509/pkix" - "encoding/asn1" - "fmt" - "testing" - - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - pkiutil "github.com/cert-manager/cert-manager/pkg/util/pki" - "github.com/stretchr/testify/assert" -) - -var ( - disallowedX509KeyUsages = []interface{}{ - x509.KeyUsageContentCommitment, - x509.KeyUsageDataEncipherment, - x509.KeyUsageKeyAgreement, - x509.KeyUsageCertSign, - x509.KeyUsageCRLSign, - x509.KeyUsageEncipherOnly, - x509.KeyUsageDecipherOnly, - } - - allowedX509KeyUsages = []interface{}{ - x509.KeyUsageDigitalSignature, - x509.KeyUsageKeyEncipherment, - } - - disallowedX509ExtKeyUsages = []interface{}{ - x509.ExtKeyUsageAny, - x509.ExtKeyUsageCodeSigning, - x509.ExtKeyUsageEmailProtection, - x509.ExtKeyUsageIPSECEndSystem, - x509.ExtKeyUsageIPSECTunnel, - x509.ExtKeyUsageIPSECUser, - x509.ExtKeyUsageTimeStamping, - x509.ExtKeyUsageOCSPSigning, - x509.ExtKeyUsageMicrosoftServerGatedCrypto, - x509.ExtKeyUsageNetscapeServerGatedCrypto, - x509.ExtKeyUsageMicrosoftCommercialCodeSigning, - x509.ExtKeyUsageMicrosoftKernelCodeSigning, - } - - allowedX509ExtKeyUsages = []interface{}{ - x509.ExtKeyUsageServerAuth, - x509.ExtKeyUsageClientAuth, - } -) - -func Test_validateCSRExtentions(t *testing.T) { - sk, err := pkiutil.GenerateRSAPrivateKey(2048) - assert.NoError(t, err) - - tests := map[string]struct { - emails []string - dns []string - uris []string - ips []string - usages []cmapi.KeyUsage - expErr bool - }{ - "if single URI name exists, shouldn't error": { - uris: []string{"spiffe://foo.bar"}, - expErr: false, - }, - "if single URI name exist with allowed usages, shouldn't error": { - uris: []string{"spiffe://foo.bar"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - }, - expErr: false, - }, - "if multiple URI names exist with allowed usages, shouldn't error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - }, - expErr: false, - }, - "if multiple URI names exist, dns name, and allowed usages, should error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - dns: []string{"foo.bar"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - }, - expErr: true, - }, - "if multiple URI names exist, ips, and allowed usages, should error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - ips: []string{"1.2.3.4"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - }, - expErr: true, - }, - "if multiple URI names exist, emails, and allowed usages, should error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - emails: []string{"hello@example.com"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - }, - expErr: true, - }, - "if multiple URI names exist, emails, dns, ips, and allowed usages, should error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - dns: []string{"foo.bar"}, - ips: []string{"1.2.3.4"}, - emails: []string{"hello@example.com"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - }, - expErr: true, - }, - "if multiple URI names exist, and subset allowed usages, shouldn't error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageServerAuth, - }, - expErr: false, - }, - "if multiple URI names exist, with disallowed usages, should error": { - uris: []string{"spiffe://foo.bar", "spiffe://bar.foo"}, - usages: []cmapi.KeyUsage{ - cmapi.UsageDigitalSignature, - cmapi.UsageKeyEncipherment, - cmapi.UsageClientAuth, - cmapi.UsageServerAuth, - cmapi.UsageCertSign, - }, - expErr: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - csr, err := pkiutil.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - EmailAddresses: test.emails, - DNSNames: test.dns, - IPAddresses: test.ips, - Usages: test.usages, - URIs: test.uris, - }, - }) - assert.NoError(t, err) - - // Re encode/parse csr to simulate real x509 csr parsing - csrDER, err := pkiutil.EncodeCSR(csr, sk) - assert.NoError(t, err) - - csr, err = x509.ParseCertificateRequest(csrDER) - assert.NoError(t, err) - - err = validateCSRExtentions(csr) - assert.Equal(t, test.expErr, err != nil, "%v", err) - }) - } -} - -func Test_validateExtendedKeyUsageExtension(t *testing.T) { - type testcase struct { - usages []x509.ExtKeyUsage - expErr bool - } - - var ( - tests []testcase - // Generate powerset of both disallowed and allowed usages - disallowedExtUsagesPowerset = powerset(disallowedX509ExtKeyUsages) - allowedExtUsagesPowerset = append(powerset(allowedX509ExtKeyUsages), nil) - ) - - // Expect all sets with any disallowed usages to always fail - for _, disallowed := range disallowedExtUsagesPowerset { - for _, allowed := range allowedExtUsagesPowerset { - var extUsages []x509.ExtKeyUsage - for _, usage := range append(disallowed, allowed...) { - extUsages = append(extUsages, usage.(x509.ExtKeyUsage)) - } - - tests = append(tests, testcase{extUsages, true}) - } - } - - for _, allowed := range allowedExtUsagesPowerset { - var extUsages []x509.ExtKeyUsage - for _, usage := range allowed { - extUsages = append(extUsages, usage.(x509.ExtKeyUsage)) - } - - tests = append(tests, testcase{extUsages, true}) - } - - for _, test := range tests { - t.Run(fmt.Sprintf("ext usages [%v] expErr=%t", test.usages, test.expErr), func(t *testing.T) { - var ids []asn1.ObjectIdentifier - for _, usage := range test.usages { - id, ok := pkiutil.OIDFromExtKeyUsage(usage) - assert.True(t, ok, "%v", usage) - - ids = append(ids, id) - } - - val, err := asn1.Marshal(ids) - assert.NoError(t, err) - - extension := pkix.Extension{ - Id: oidExtensionKeyUsage, - Value: val, - } - - err = validateExtendedKeyUsageExtension(extension) - assert.Equal(t, test.expErr, err != nil, "%v", err) - }) - } -} - -func Test_validateKeyUsageExtension(t *testing.T) { - type testcase struct { - usage x509.KeyUsage - expErr bool - } - - var ( - tests []testcase - // Generate powerset of both disallowed and allowed usages - disallowedUsagesPowerset = powerset(disallowedX509KeyUsages) - allowedUsagesPowerset = append(powerset(allowedX509KeyUsages), nil) - ) - - // Expect all sets with any disallowed usages to always fail - for _, disallowed := range disallowedUsagesPowerset { - for _, allowed := range allowedUsagesPowerset { - var ku x509.KeyUsage - for _, use := range append(disallowed, allowed...) { - ku |= use.(x509.KeyUsage) - } - - tests = append(tests, testcase{ku, true}) - } - } - - // Expect all sets with only allowed or empty usages to always pass - for _, allowed := range allowedUsagesPowerset { - var ku x509.KeyUsage - for _, use := range allowed { - ku |= use.(x509.KeyUsage) - } - - tests = append(tests, testcase{ku, false}) - } - - for _, test := range tests { - t.Run(fmt.Sprintf("usage [%v] expErr=%t", test.usage, test.expErr), func(t *testing.T) { - ext, err := buildASN1KeyUsageRequest(test.usage) - if err != nil { - t.Fatal(err) - } - - err = validateKeyUsageExtension(ext.Value) - assert.Equal(t, test.expErr, err != nil, "%v", err) - }) - } -} - -// Adapted from https://github.com/mxschmitt/golang-combinations -func powerset(set []interface{}) (subsets [][]interface{}) { - length := uint(len(set)) - - // Go through all possible combinations of objects - // from 1 (only first object in subset) to 2^length (all objects in subset) - //math.Pow( - for subsetBits := 1; subsetBits < (1 << length); subsetBits++ { - var subset []interface{} - - for object := uint(0); object < length; object++ { - // checks if object is contained in subset - // by checking if bit 'object' is set in subsetBits - if (subsetBits>>object)&1 == 1 { - // add object to subset - subset = append(subset, set[object]) - } - } - // add subset to subsets - subsets = append(subsets, subset) - } - - return subsets -} - -// Copied from x509.go -func reverseBitsInAByte(in byte) byte { - b1 := in>>4 | in<<4 - b2 := b1>>2&0x33 | b1<<2&0xcc - b3 := b2>>1&0x55 | b2<<1&0xaa - return b3 -} - -// Adapted from x509.go -func buildASN1KeyUsageRequest(usage x509.KeyUsage) (pkix.Extension, error) { - OIDExtensionKeyUsage := pkix.Extension{ - Id: oidExtensionKeyUsage, - } - var a [2]byte - a[0] = reverseBitsInAByte(byte(usage)) - a[1] = reverseBitsInAByte(byte(usage >> 8)) - - l := 1 - if a[1] != 0 { - l = 2 - } - - bitString := a[:l] - var err error - OIDExtensionKeyUsage.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)}) - if err != nil { - return pkix.Extension{}, err - } - - return OIDExtensionKeyUsage, nil -} - -// asn1BitLength returns the bit-length of bitString by considering the -// most-significant bit in a byte to be the "first" bit. This convention -// matches ASN.1, but differs from almost everything else. -func asn1BitLength(bitString []byte) int { - bitLen := len(bitString) * 8 - - for i := range bitString { - b := bitString[len(bitString)-i-1] - - for bit := uint(0); bit < 8; bit++ { - if (b>>bit)&1 == 1 { - return bitLen - } - bitLen-- - } - } - - return 0 -} diff --git a/internal/approver/evaluator/fake/fake.go b/internal/approver/evaluator/fake/fake.go deleted file mode 100644 index ecb4300..0000000 --- a/internal/approver/evaluator/fake/fake.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package fake - -import ( - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - - "github.com/cert-manager/csi-driver-spiffe/internal/approver/evaluator" -) - -var _ evaluator.Interface = &FakeEvaluator{} - -// FakeEvaluator is a implementation of Evaluator which can be mocked for testing. -type FakeEvaluator struct { - funcEvaluate func(*cmapi.CertificateRequest) error -} - -// New returns a new FakeEvaluator -func New() *FakeEvaluator { - return &FakeEvaluator{ - funcEvaluate: func(_ *cmapi.CertificateRequest) error { - return nil - }, - } -} - -func (f *FakeEvaluator) WithEvaluate(fn func(_ *cmapi.CertificateRequest) error) *FakeEvaluator { - f.funcEvaluate = fn - return f -} - -func (f *FakeEvaluator) Evaluate(req *cmapi.CertificateRequest) error { - return f.funcEvaluate(req) -} diff --git a/internal/approver/evaluator/identity.go b/internal/approver/evaluator/identity.go deleted file mode 100644 index fd97d8e..0000000 --- a/internal/approver/evaluator/identity.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package evaluator - -import ( - "crypto/x509" - "fmt" - "strings" -) - -// validateIdentity validates that the SPIFFE ID contained in the X.509 -// certificate request matches that in the username. -// The username should be the Username as it appears on the CertificateRequest. -// This should be the ServiceAccount of the mounting Pod who has been -// impersonated to create the request. -func (i *internal) validateIdentity(csr *x509.CertificateRequest, username string) error { - split := strings.Split(username, ":") - if len(split) != 4 || split[0] != "system" || split[1] != "serviceaccount" { - return fmt.Errorf("got non-serviceaccount encoded username: %q", username) - } - - if len(csr.URIs) != 1 { - return fmt.Errorf("expected exactly 1 SPIFFE URI present on request, got=%d", len(csr.URIs)) - } - - if csr.URIs[0].Scheme != "spiffe" { - return fmt.Errorf("URI scheme is not spiffe: %s", csr.URIs[0].Scheme) - } - - expSpiffeID := fmt.Sprintf("spiffe://%s/ns/%s/sa/%s", i.trustDomain, split[2], split[3]) - if csr.URIs[0].String() != expSpiffeID { - return fmt.Errorf("unexpected SPIFFE ID requested, exp=%q got=%q", expSpiffeID, csr.URIs[0].String()) - } - - return nil -} diff --git a/internal/approver/evaluator/identity_test.go b/internal/approver/evaluator/identity_test.go deleted file mode 100644 index 1f1d5dd..0000000 --- a/internal/approver/evaluator/identity_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package evaluator - -import ( - "crypto/x509" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_validateIdentity(t *testing.T) { - tests := map[string]struct { - uris []string - username string - expErr bool - }{ - "if username is malformed, expect error": { - uris: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - username: "system:serviceaccount:foo", - expErr: true, - }, - "if multiple URIs defined, expect error": { - uris: []string{ - "spiffe://foo.bar/ns/sandbox/sa/sleep", - "spiffe://foo.bar/ns/sandbox/sa/httpbin", - }, - username: "system:serviceaccount:sandbox:sleep", - expErr: true, - }, - "if URI is not using SPIFFE, expect error": { - uris: []string{"http://foo.bar/ns/sandbox/sa/sleep"}, - username: "system:serviceaccount:sandbox:sleep", - expErr: true, - }, - "if trust domain is wrong, expect error": { - uris: []string{"spiffe://bar.foo/ns/sandbox/sa/sleep"}, - username: "system:serviceaccount:sandbox:sleep", - expErr: true, - }, - "if SPIFFE ID doesn't match the username, expect error": { - uris: []string{"spiffe://foo.bar/ns/sandbox/sa/httpbin"}, - username: "system:serviceaccount:sandbox:sleep", - expErr: true, - }, - "if SPIFFE ID matches username, don't expect error": { - uris: []string{"spiffe://foo.bar/ns/sandbox/sa/sleep"}, - username: "system:serviceaccount:sandbox:sleep", - expErr: false, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - i := &internal{trustDomain: "foo.bar"} - - var uris []*url.URL - for _, uriStr := range test.uris { - uri, err := url.Parse(uriStr) - assert.NoError(t, err) - uris = append(uris, uri) - } - - err := i.validateIdentity(&x509.CertificateRequest{URIs: uris}, test.username) - assert.Equalf(t, test.expErr, err != nil, "%v", err) - }) - } -} diff --git a/make/00_mod.mk b/make/00_mod.mk index 6b9848f..550f62e 100644 --- a/make/00_mod.mk +++ b/make/00_mod.mk @@ -17,11 +17,9 @@ repo_name := github.com/cert-manager/csi-driver-spiffe kind_cluster_name := csi-driver-spiffe kind_cluster_config := $(bin_dir)/scratch/kind_cluster.yaml -oci_platforms := linux/amd64,linux/arm64 +build_names := manager -build_names := manager approver - -go_manager_main_dir := ./cmd/csi +go_manager_main_dir := ./cmd go_manager_mod_dir := . go_manager_ldflags := -X $(repo_name)/internal/version.AppVersion=$(VERSION) -X $(repo_name)/internal/version.GitCommit=$(GITCOMMIT) oci_manager_base_image_flavor := csi-static @@ -29,14 +27,6 @@ oci_manager_image_name := quay.io/jetstack/cert-manager-csi-driver-spiffe oci_manager_image_tag := $(VERSION) oci_manager_image_name_development := cert-manager.local/cert-manager-csi-driver-spiffe -go_approver_main_dir := ./cmd/approver -go_approver_mod_dir := . -go_approver_ldflags := -X $(repo_name)/internal/version.AppVersion=$(VERSION) -X $(repo_name)/internal/version.GitCommit=$(GITCOMMIT) -oci_approver_base_image_flavor := static -oci_approver_image_name := quay.io/jetstack/cert-manager-csi-driver-spiffe-approver -oci_approver_image_tag := $(VERSION) -oci_approver_image_name_development := cert-manager.local/cert-manager-csi-driver-spiffe-approver - deploy_name := csi-driver-spiffe deploy_namespace := cert-manager @@ -55,7 +45,6 @@ helm_verify_values := 1 define helm_values_mutation_function $(YQ) \ '( .image.repository.driver = "$(oci_manager_image_name)" ) | \ - ( .image.repository.approver = "$(oci_approver_image_name)" ) | \ ( .image.tag = "$(oci_manager_image_tag)" )' \ $1 --inplace endef diff --git a/make/02_mod.mk b/make/02_mod.mk index 2343b9e..e275c0b 100644 --- a/make/02_mod.mk +++ b/make/02_mod.mk @@ -24,12 +24,10 @@ include make/test-unit.mk ## Publish all release artifacts (image + helm chart) ## @category [shared] Release release: $(helm_chart_archive) - $(MAKE) oci-push-manager oci-push-approver + $(MAKE) oci-push-manager @echo "RELEASE_OCI_MANAGER_IMAGE=$(oci_manager_image_name)" >> "$(GITHUB_OUTPUT)" @echo "RELEASE_OCI_MANAGER_TAG=$(oci_manager_image_tag)" >> "$(GITHUB_OUTPUT)" - @echo "RELEASE_OCI_APPROVER_IMAGE=$(oci_manager_image_name)" >> "$(GITHUB_OUTPUT)" - @echo "RELEASE_OCI_APPROVER_TAG=$(oci_manager_image_tag)" >> "$(GITHUB_OUTPUT)" @echo "RELEASE_HELM_CHART_NAME=$(helm_chart_name)" >> "$(GITHUB_OUTPUT)" @echo "RELEASE_HELM_CHART_VERSION=$(helm_chart_version)" >> "$(GITHUB_OUTPUT)" @echo "RELEASE_HELM_CHART_TAR=$(helm_chart_archive)" >> "$(GITHUB_OUTPUT)" diff --git a/make/test-e2e.mk b/make/test-e2e.mk index 6b19f63..adeab44 100644 --- a/make/test-e2e.mk +++ b/make/test-e2e.mk @@ -22,7 +22,6 @@ e2e-setup-cert-manager: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) --namespace cert-manager \ --repo https://charts.jetstack.io \ --set installCRDs=true \ - --set extraArgs={--controllers='*\,-certificaterequests-approver'} \ --set image.repository=$(quay.io/jetstack/cert-manager-controller.REPO) \ --set image.tag=$(quay.io/jetstack/cert-manager-controller.TAG) \ --set image.pullPolicy=Never \ @@ -40,16 +39,6 @@ e2e-setup-cert-manager: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) .PHONY: e2e-setup-example e2e-setup-example: | e2e-setup-cert-manager kind-cluster $(NEEDS_KUBECTL) $(KUBECTL) apply --server-side -f ./deploy/example/clusterissuer.yaml - - sleep 3 - - cr_name=$$($(KUBECTL) get cr -n cert-manager --no-headers -o custom-columns=":metadata.name") && \ - $(KUBECTL) patch cr $$cr_name \ - -n cert-manager \ - --subresource status \ - --type merge \ - --patch '{"status": {"conditions": [{"type": "Approved", "status": "True", "reason": "manual"}]}}' - $(KUBECTL) wait --for=condition=ready clusterissuer csi-driver-spiffe-ca # The "install" target can be run on its own with any currently active cluster, @@ -57,15 +46,13 @@ e2e-setup-example: | e2e-setup-cert-manager kind-cluster $(NEEDS_KUBECTL) # When a "test-e2e" target is run, the currently active cluster must be the kind # cluster created by the "kind-cluster" target. ifeq ($(findstring test-e2e,$(MAKECMDGOALS)),test-e2e) -install: e2e-setup-example kind-cluster oci-load-manager oci-load-approver +install: e2e-setup-example kind-cluster oci-load-manager endif test-e2e-deps: INSTALL_OPTIONS := -test-e2e-deps: INSTALL_OPTIONS += --set image.repository.driver=$(oci_manager_image_name_development) -test-e2e-deps: INSTALL_OPTIONS += --set image.repository.approver=$(oci_approver_image_name_development) +test-e2e-deps: INSTALL_OPTIONS += --set image.repository=$(oci_manager_image_name_development) test-e2e-deps: INSTALL_OPTIONS += --set image.pullPolicy=Never test-e2e-deps: INSTALL_OPTIONS += --set app.trustDomain=foo.bar -test-e2e-deps: INSTALL_OPTIONS += --set app.approver.signerName=clusterissuers.cert-manager.io/csi-driver-spiffe-ca test-e2e-deps: INSTALL_OPTIONS += --set app.issuer.name=csi-driver-spiffe-ca test-e2e-deps: INSTALL_OPTIONS += --set app.driver.volumes[0].name=root-cas test-e2e-deps: INSTALL_OPTIONS += --set app.driver.volumes[0].secret.secretName=csi-driver-spiffe-ca diff --git a/test/e2e/suite/approval/approval.go b/test/e2e/suite/approval/approval.go deleted file mode 100644 index a012d85..0000000 --- a/test/e2e/suite/approval/approval.go +++ /dev/null @@ -1,247 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package approval - -import ( - "bytes" - "crypto" - "encoding/pem" - "fmt" - "time" - - apiutil "github.com/cert-manager/cert-manager/pkg/api/util" - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - utilpki "github.com/cert-manager/cert-manager/pkg/util/pki" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" - "k8s.io/utils/ptr" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/cert-manager/csi-driver-spiffe/test/e2e/framework" -) - -var _ = framework.CasesDescribe("Approval", func() { - f := framework.NewDefaultFramework("Approval") - - var ( - pk crypto.Signer - serviceAccount corev1.ServiceAccount - role rbacv1.Role - rolebinding rbacv1.RoleBinding - cl client.Client - ) - - JustBeforeEach(func() { - By("Creating test resources") - var err error - pk, err = utilpki.GenerateECPrivateKey(utilpki.ECCurve521) - Expect(err).NotTo(HaveOccurred()) - - serviceAccount = corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{Namespace: f.Namespace.Name, GenerateName: "csi-driver-spiffe-approval-test-"}, - } - Expect(f.Client().Create(f.Context(), &serviceAccount)).NotTo(HaveOccurred()) - - role = rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "csi-driver-spiffe-approval-test-", - Namespace: f.Namespace.Name, - }, - Rules: []rbacv1.PolicyRule{{ - Verbs: []string{"create"}, - APIGroups: []string{"cert-manager.io"}, - Resources: []string{"certificaterequests"}, - }}, - } - Expect(f.Client().Create(f.Context(), &role)).NotTo(HaveOccurred()) - - rolebinding = rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "csi-driver-spiffe-approval-test-", - Namespace: f.Namespace.Name, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: role.Name, - }, - Subjects: []rbacv1.Subject{{ - Kind: "ServiceAccount", - Name: serviceAccount.Name, - Namespace: f.Namespace.Name, - }}, - } - Expect(f.Client().Create(f.Context(), &rolebinding)).NotTo(HaveOccurred()) - - impersonateRestConfig := *f.Config().RestConfig - impersonateRestConfig.Impersonate = rest.ImpersonationConfig{UserName: fmt.Sprintf("system:serviceaccount:%s:%s", f.Namespace.Name, serviceAccount.Name)} - cl, err = client.New(&impersonateRestConfig, client.Options{Scheme: f.Client().Scheme()}) - Expect(err).NotTo(HaveOccurred()) - }) - - JustAfterEach(func() { - By("Cleaning up test resources") - Expect(f.Client().Delete(f.Context(), &rolebinding)).NotTo(HaveOccurred()) - Expect(f.Client().Delete(f.Context(), &role)).NotTo(HaveOccurred()) - Expect(f.Client().Delete(f.Context(), &serviceAccount)).NotTo(HaveOccurred()) - }) - - It("should approve a valid request", func() { - By("Creating valid request") - certificateRequest := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "test-request-", - Namespace: f.Namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: genCSRPEM(pk, cmapi.ECDSAKeyAlgorithm, fmt.Sprintf("spiffe://foo.bar/ns/%s/sa/%s", f.Namespace.Name, serviceAccount.Name)), - Duration: &metav1.Duration{Duration: time.Hour}, - IssuerRef: f.Config().IssuerRef, - IsCA: false, - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth, cmapi.UsageServerAuth}, - }, - } - Expect(cl.Create(f.Context(), &certificateRequest)).NotTo(HaveOccurred()) - - By("Waiting for valid request to be approved") - Eventually(func() bool { - Expect(f.Client().Get(f.Context(), client.ObjectKeyFromObject(&certificateRequest), &certificateRequest)).NotTo(HaveOccurred()) - return apiutil.CertificateRequestIsApproved(&certificateRequest) - }, "5s", "1s").Should(BeTrue(), "expected request to become approved in time") - }) - - It("should deny a request with the wrong duration", func() { - By("Creating request with wrong duration") - certificateRequest := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "test-request-", - Namespace: f.Namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: genCSRPEM(pk, cmapi.ECDSAKeyAlgorithm, fmt.Sprintf("spiffe://foo.bar/ns/%s/sa/%s", f.Namespace.Name, serviceAccount.Name)), - Duration: &metav1.Duration{Duration: time.Hour * 3}, - IssuerRef: f.Config().IssuerRef, - IsCA: false, - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth, cmapi.UsageServerAuth}, - }, - } - Expect(cl.Create(f.Context(), &certificateRequest)).NotTo(HaveOccurred()) - - By("Waiting for valid request to be denied") - Eventually(func() bool { - Expect(f.Client().Get(f.Context(), client.ObjectKeyFromObject(&certificateRequest), &certificateRequest)).NotTo(HaveOccurred()) - return apiutil.CertificateRequestIsDenied(&certificateRequest) - }, "5s", "1s").Should(BeTrue(), "expected request to be denied in time") - }) - - It("should deny a request with the wrong SPIFFE ID", func() { - By("Creating request with wrong SPIFFE ID") - certificateRequest := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "test-request-", - Namespace: f.Namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: genCSRPEM(pk, cmapi.ECDSAKeyAlgorithm, fmt.Sprintf("spiffe://foo.bar/ns/%s/sa/%s", f.Namespace.Name, "not-the-right-sa")), - Duration: &metav1.Duration{Duration: time.Hour}, - IssuerRef: f.Config().IssuerRef, - IsCA: false, - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth, cmapi.UsageServerAuth}, - }, - } - Expect(cl.Create(f.Context(), &certificateRequest)).NotTo(HaveOccurred()) - - By("Waiting for valid request to be denied") - Eventually(func() bool { - Expect(f.Client().Get(f.Context(), client.ObjectKeyFromObject(&certificateRequest), &certificateRequest)).NotTo(HaveOccurred()) - return apiutil.CertificateRequestIsDenied(&certificateRequest) - }, "5s", "1s").Should(BeTrue(), "expected request to be denied in time") - }) - - It("should deny a request with the wrong key usages", func() { - By("Creating request with wrong key usages") - certificateRequest := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "test-request-", - Namespace: f.Namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: genCSRPEM(pk, cmapi.ECDSAKeyAlgorithm, fmt.Sprintf("spiffe://foo.bar/ns/%s/sa/%s", f.Namespace.Name, serviceAccount.Name)), - Duration: &metav1.Duration{Duration: time.Hour}, - IssuerRef: f.Config().IssuerRef, - IsCA: false, - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth, cmapi.UsageServerAuth, cmapi.UsageCertSign}, - }, - } - Expect(cl.Create(f.Context(), &certificateRequest)).NotTo(HaveOccurred()) - - By("Waiting for valid request to be denied") - Eventually(func() bool { - Expect(f.Client().Get(f.Context(), client.ObjectKeyFromObject(&certificateRequest), &certificateRequest)).NotTo(HaveOccurred()) - return apiutil.CertificateRequestIsDenied(&certificateRequest) - }, "5s", "1s").Should(BeTrue(), "expected request to be denied in time") - }) - - It("should deny a request with the wrong key type", func() { - pk, err := utilpki.GenerateRSAPrivateKey(2048) - Expect(err).NotTo(HaveOccurred()) - - By("Creating request with wrong key type") - certificateRequest := cmapi.CertificateRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "test-request-", - Namespace: f.Namespace.Name, - }, - Spec: cmapi.CertificateRequestSpec{ - Request: genCSRPEM(pk, cmapi.RSAKeyAlgorithm, fmt.Sprintf("spiffe://foo.bar/ns/%s/sa/%s", f.Namespace.Name, serviceAccount.Name)), - Duration: &metav1.Duration{Duration: time.Hour}, - IssuerRef: f.Config().IssuerRef, - IsCA: false, - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth, cmapi.UsageServerAuth, cmapi.UsageCertSign}, - }, - } - Expect(cl.Create(f.Context(), &certificateRequest)).NotTo(HaveOccurred()) - - By("Waiting for valid request to be denied") - Eventually(func() bool { - Expect(f.Client().Get(f.Context(), client.ObjectKeyFromObject(&certificateRequest), &certificateRequest)).NotTo(HaveOccurred()) - return apiutil.CertificateRequestIsDenied(&certificateRequest) - }, "5s", "1s").Should(BeTrue(), "expected request to be denied in time") - }) -}) - -func genCSRPEM(pk crypto.Signer, alg cmapi.PrivateKeyAlgorithm, uri string) []byte { - csr, err := utilpki.GenerateCSR(&cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - PrivateKey: &cmapi.CertificatePrivateKey{Algorithm: alg}, - URIs: []string{uri}, - EncodeUsagesInRequest: ptr.To(false), - }, - }) - Expect(err).NotTo(HaveOccurred()) - csrDER, err := utilpki.EncodeCSR(csr, pk) - Expect(err).NotTo(HaveOccurred()) - csrPEM := bytes.NewBuffer([]byte{}) - Expect(err).NotTo(HaveOccurred()) - Expect(pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})).ToNot(HaveOccurred()) - - return csrPEM.Bytes() -} diff --git a/test/e2e/suite/import.go b/test/e2e/suite/import.go index 8638cda..fc371ad 100644 --- a/test/e2e/suite/import.go +++ b/test/e2e/suite/import.go @@ -17,7 +17,6 @@ limitations under the License. package suite import ( - _ "github.com/cert-manager/csi-driver-spiffe/test/e2e/suite/approval" _ "github.com/cert-manager/csi-driver-spiffe/test/e2e/suite/carotation" _ "github.com/cert-manager/csi-driver-spiffe/test/e2e/suite/fsgroup" )