From 65e5b03ab2fbdb93482f6809a73304d7c9ec514f Mon Sep 17 00:00:00 2001 From: TessaIO Date: Sun, 14 Apr 2024 20:42:11 +0200 Subject: [PATCH] deploy: add spire manifests in helm and kustomize Signed-off-by: TessaIO --- .../master-config/nfd-master.conf.example | 1 + .../worker-config/nfd-worker.conf.example | 1 + .../templates/master.yaml | 14 +++++ .../templates/spire-agent-cluster-role.yaml | 26 ++++++++ .../templates/spire-agent-configmap.yaml | 45 ++++++++++++++ .../templates/spire-agent-daemonset.yaml | 57 +++++++++++++++++ .../spire-agent-service-account.yaml | 6 ++ .../templates/spire-bundle-configmap.yaml | 6 ++ .../templates/spire-server-cluster-role.yaml | 50 +++++++++++++++ .../templates/spire-server-configmap.yaml | 58 +++++++++++++++++ .../spire-server-service-account.yaml | 6 ++ .../templates/spire-server-service.yaml | 15 +++++ .../templates/spire-server-statefulset.yaml | 62 +++++++++++++++++++ .../templates/worker.yaml | 14 +++++ .../helm/node-feature-discovery/values.yaml | 5 ++ deployment/overlays/spiffe/kustomization.yaml | 16 +++++ deployment/overlays/spiffe/namespace.yaml | 4 ++ .../spiffe/spire-agent-cluster-role.yaml | 23 +++++++ .../spiffe/spire-agent-configmap.yaml | 43 +++++++++++++ .../spiffe/spire-agent-daemonset.yaml | 55 ++++++++++++++++ .../spiffe/spire-agent-service-account.yaml | 4 ++ .../spiffe/spire-bundle-configmap.yaml | 4 ++ .../spiffe/spire-server-cluster-role.yaml | 45 ++++++++++++++ .../spiffe/spire-server-configmap.yaml | 56 +++++++++++++++++ .../spiffe/spire-server-service-account.yaml | 4 ++ .../overlays/spiffe/spire-server-service.yaml | 13 ++++ .../spiffe/spire-server-statefulset.yaml | 60 ++++++++++++++++++ go.mod | 33 ++-------- go.sum | 25 ++------ pkg/nfd-master/nfd-master.go | 8 ++- pkg/nfd-worker/nfd-worker.go | 8 ++- pkg/utils/spiffe/spiffe.go | 15 ++++- pkg/utils/spiffe/spiffe_test.go | 27 ++++++-- 33 files changed, 752 insertions(+), 57 deletions(-) create mode 100644 deployment/helm/node-feature-discovery/templates/spire-agent-cluster-role.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-agent-configmap.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-agent-daemonset.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-agent-service-account.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-bundle-configmap.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-server-cluster-role.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-server-configmap.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-server-service-account.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-server-service.yaml create mode 100644 deployment/helm/node-feature-discovery/templates/spire-server-statefulset.yaml create mode 100644 deployment/overlays/spiffe/kustomization.yaml create mode 100644 deployment/overlays/spiffe/namespace.yaml create mode 100644 deployment/overlays/spiffe/spire-agent-cluster-role.yaml create mode 100644 deployment/overlays/spiffe/spire-agent-configmap.yaml create mode 100644 deployment/overlays/spiffe/spire-agent-daemonset.yaml create mode 100644 deployment/overlays/spiffe/spire-agent-service-account.yaml create mode 100644 deployment/overlays/spiffe/spire-bundle-configmap.yaml create mode 100644 deployment/overlays/spiffe/spire-server-cluster-role.yaml create mode 100644 deployment/overlays/spiffe/spire-server-configmap.yaml create mode 100644 deployment/overlays/spiffe/spire-server-service-account.yaml create mode 100644 deployment/overlays/spiffe/spire-server-service.yaml create mode 100644 deployment/overlays/spiffe/spire-server-statefulset.yaml diff --git a/deployment/components/master-config/nfd-master.conf.example b/deployment/components/master-config/nfd-master.conf.example index 8aa0cb29ce..114531f421 100644 --- a/deployment/components/master-config/nfd-master.conf.example +++ b/deployment/components/master-config/nfd-master.conf.example @@ -6,6 +6,7 @@ # enableTaints: false # labelWhiteList: "foo" # resyncPeriod: "2h" +# enableSpiffe: true # klog: # addDirHeader: false # alsologtostderr: false diff --git a/deployment/components/worker-config/nfd-worker.conf.example b/deployment/components/worker-config/nfd-worker.conf.example index 9a3bfd85b7..ef1e8cdcfa 100644 --- a/deployment/components/worker-config/nfd-worker.conf.example +++ b/deployment/components/worker-config/nfd-worker.conf.example @@ -2,6 +2,7 @@ # labelWhiteList: # noPublish: false # sleepInterval: 60s +# enableSpiffe: true # featureSources: [all] # labelSources: [all] # klog: diff --git a/deployment/helm/node-feature-discovery/templates/master.yaml b/deployment/helm/node-feature-discovery/templates/master.yaml index bb1f24938b..caba5d3f9b 100644 --- a/deployment/helm/node-feature-discovery/templates/master.yaml +++ b/deployment/helm/node-feature-discovery/templates/master.yaml @@ -115,12 +115,20 @@ spec: - "-feature-gates={{ $key }}={{ $value }}" {{- end }} - "-metrics={{ .Values.master.metricsPort | default "8081" }}" + {{- if .Values.spiffe.enable }} + - "-enable-spiffe" + {{- end }} volumeMounts: {{- if .Values.tls.enable }} - name: nfd-master-cert mountPath: "/etc/kubernetes/node-feature-discovery/certs" readOnly: true {{- end }} + {{- if .Values.spiffe.enable }} + - name: spire-agent-socket + mountPath: /run/spire/sockets + readOnly: true + {{- end }} - name: nfd-master-conf mountPath: "/etc/kubernetes/node-feature-discovery" readOnly: true @@ -130,6 +138,12 @@ spec: secret: secretName: nfd-master-cert {{- end }} + {{- if .Values.spiffe.enable }} + - name: spire-agent-socket + hostPath: + path: /run/spire/sockets + type: Directory + {{- end }} - name: nfd-master-conf configMap: name: {{ include "node-feature-discovery.fullname" . }}-master-conf diff --git a/deployment/helm/node-feature-discovery/templates/spire-agent-cluster-role.yaml b/deployment/helm/node-feature-discovery/templates/spire-agent-cluster-role.yaml new file mode 100644 index 0000000000..9115dac5c6 --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-agent-cluster-role.yaml @@ -0,0 +1,26 @@ +{{- if .Values.spiffe.enable }} +# Required cluster role to allow spire-agent to query k8s API server +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-agent-cluster-role +rules: +- apiGroups: [""] + resources: ["pods","nodes","nodes/proxy"] + verbs: ["get"] + +--- +# Binds above cluster role to spire-agent service account +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-agent-cluster-role-binding +subjects: +- kind: ServiceAccount + name: spire-agent + namespace: {{ include "node-feature-discovery.namespace" . }} +roleRef: + kind: ClusterRole + name: spire-agent-cluster-role + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-agent-configmap.yaml b/deployment/helm/node-feature-discovery/templates/spire-agent-configmap.yaml new file mode 100644 index 0000000000..bc7e634563 --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-agent-configmap.yaml @@ -0,0 +1,45 @@ +{{- if .Values.spiffe.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-agent +data: + agent.conf: | + agent { + data_dir = "/run/spire" + log_level = "DEBUG" + server_address = "spire-server" + server_port = "8081" + socket_path = "/run/spire/sockets/agent.sock" + trust_bundle_path = "/run/spire/bundle/bundle.crt" + trust_domain = "nfd.com" + } + plugins { + NodeAttestor "k8s_sat" { + plugin_data { + cluster = "nfd" + } + } + KeyManager "memory" { + plugin_data { + } + } + WorkloadAttestor "k8s" { + plugin_data { + skip_kubelet_verification = true + node_name_env = "MY_NODE_NAME" + } + } + WorkloadAttestor "unix" { + plugin_data { + } + } + } + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-agent-daemonset.yaml b/deployment/helm/node-feature-discovery/templates/spire-agent-daemonset.yaml new file mode 100644 index 0000000000..37ff0994a2 --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-agent-daemonset.yaml @@ -0,0 +1,57 @@ +{{- if .Values.spiffe.enable }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: spire-agent + labels: + app: spire-agent +spec: + selector: + matchLabels: + app: spire-agent + template: + metadata: + labels: + app: spire-agent + spec: + hostPID: true + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + serviceAccountName: spire-agent + initContainers: + - name: init + # This is a small image with wait-for-it, choose whatever image + # you prefer that waits for a service to be up. This image is built + # from https://github.com/lqhl/wait-for-it + image: cgr.dev/chainguard/wait-for-it + args: ["-t", "30", "spire-server:8081"] + containers: + - name: spire-agent + image: ghcr.io/spiffe/spire-agent:1.5.1 + args: ["-config", "/run/spire/config/agent.conf"] + env: + - name: MY_NODE_NAME + valueFrom: + fieldRef: + fieldPath: status.podIP + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + - name: spire-bundle + mountPath: /run/spire/bundle + - name: spire-agent-socket + mountPath: /run/spire/sockets + readOnly: false + volumes: + - name: spire-config + configMap: + name: spire-agent + - name: spire-bundle + configMap: + name: spire-bundle + - name: spire-agent-socket + hostPath: + path: /run/spire/sockets + type: DirectoryOrCreate +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-agent-service-account.yaml b/deployment/helm/node-feature-discovery/templates/spire-agent-service-account.yaml new file mode 100644 index 0000000000..9dc8afa57c --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-agent-service-account.yaml @@ -0,0 +1,6 @@ +{{- if .Values.spiffe.enable }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: spire-agent +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-bundle-configmap.yaml b/deployment/helm/node-feature-discovery/templates/spire-bundle-configmap.yaml new file mode 100644 index 0000000000..3b3179b909 --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-bundle-configmap.yaml @@ -0,0 +1,6 @@ +{{- if .Values.spiffe.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-bundle +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-server-cluster-role.yaml b/deployment/helm/node-feature-discovery/templates/spire-server-cluster-role.yaml new file mode 100644 index 0000000000..59163ffc9d --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-server-cluster-role.yaml @@ -0,0 +1,50 @@ +{{- if .Values.spiffe.enable }} +# Role (namespace scoped) to be able to push certificate bundles to a configmap +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-configmap-role +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["patch", "get", "list"] +--- +# Binds above role to spire-server service account +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-configmap-role-binding + namespace: {{ include "node-feature-discovery.namespace" . }} +subjects: +- kind: ServiceAccount + name: spire-server + namespace: {{ include "node-feature-discovery.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: spire-server-configmap-role +--- +# ClusterRole to allow spire-server node attestor to query Token Review API +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-trust-role +rules: +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +--- +# Binds above cluster role to spire-server service account +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-trust-role-binding +subjects: +- kind: ServiceAccount + name: spire-server + namespace: {{ include "node-feature-discovery.namespace" . }} +roleRef: + kind: ClusterRole + name: spire-server-trust-role + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-server-configmap.yaml b/deployment/helm/node-feature-discovery/templates/spire-server-configmap.yaml new file mode 100644 index 0000000000..09720d01fa --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-server-configmap.yaml @@ -0,0 +1,58 @@ +{{- if .Values.spiffe.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + socket_path = "/tmp/spire-server/private/api.sock" + trust_domain = "nfd.com" + data_dir = "/run/spire/data" + log_level = "DEBUG" + #AWS requires the use of RSA. EC cryptography is not supported + ca_key_type = "rsa-2048" + ca_subject = { + country = ["US"], + organization = ["SPIFFE"], + common_name = "nfd.com", + } + } + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + NodeAttestor "k8s_sat" { + plugin_data { + clusters = { + "nfd" = { + use_token_review_api_validation = true + service_account_allow_list = ["{{ include "node-feature-discovery.namespace" . }}:spire-agent"] + } + } + } + } + KeyManager "disk" { + plugin_data { + keys_path = "/run/spire/data/keys.json" + } + } + Notifier "k8sbundle" { + plugin_data { + namespace = "{{ include "node-feature-discovery.namespace" . }}" + } + } + } + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-server-service-account.yaml b/deployment/helm/node-feature-discovery/templates/spire-server-service-account.yaml new file mode 100644 index 0000000000..f7924166e0 --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-server-service-account.yaml @@ -0,0 +1,6 @@ +{{- if .Values.spiffe.enable }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: spire-server +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-server-service.yaml b/deployment/helm/node-feature-discovery/templates/spire-server-service.yaml new file mode 100644 index 0000000000..fbe64cb304 --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-server-service.yaml @@ -0,0 +1,15 @@ +{{- if .Values.spiffe.enable }} +apiVersion: v1 +kind: Service +metadata: + name: spire-server +spec: + type: NodePort + ports: + - name: grpc + port: 8081 + targetPort: 8081 + protocol: TCP + selector: + app: spire-server +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/spire-server-statefulset.yaml b/deployment/helm/node-feature-discovery/templates/spire-server-statefulset.yaml new file mode 100644 index 0000000000..7e9200d08a --- /dev/null +++ b/deployment/helm/node-feature-discovery/templates/spire-server-statefulset.yaml @@ -0,0 +1,62 @@ +{{- if .Values.spiffe.enable }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: spire-server + labels: + app: spire-server +spec: + replicas: 1 + selector: + matchLabels: + app: spire-server + serviceName: spire-server + template: + metadata: + labels: + app: spire-server + spec: + serviceAccountName: spire-server + containers: + - name: spire-server + image: ghcr.io/spiffe/spire-server:1.5.1 + args: + - -config + - /run/spire/config/server.conf + ports: + - containerPort: 8081 + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + - name: spire-data + mountPath: /run/spire/data + readOnly: false + livenessProbe: + httpGet: + path: /live + port: 8080 + failureThreshold: 2 + initialDelaySeconds: 15 + periodSeconds: 60 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: spire-config + configMap: + name: spire-server + volumeClaimTemplates: + - metadata: + name: spire-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +{{- end }} diff --git a/deployment/helm/node-feature-discovery/templates/worker.yaml b/deployment/helm/node-feature-discovery/templates/worker.yaml index 364259cacc..be74d70541 100644 --- a/deployment/helm/node-feature-discovery/templates/worker.yaml +++ b/deployment/helm/node-feature-discovery/templates/worker.yaml @@ -85,10 +85,18 @@ spec: - "-feature-gates={{ $key }}={{ $value }}" {{- end }} - "-metrics={{ .Values.worker.metricsPort | default "8081"}}" + {{- if .Values.spiffe.enable }} + - "-enable-spiffe" + {{- end }} ports: - name: metrics containerPort: {{ .Values.worker.metricsPort | default "8081"}} volumeMounts: + {{- if .Values.spiffe.enable }} + - name: spire-agent-socket + mountPath: /run/spire/sockets + readOnly: true + {{- end }} - name: host-boot mountPath: "/host-boot" readOnly: true @@ -127,6 +135,12 @@ spec: readOnly: true {{- end }} volumes: + {{- if .Values.spiffe.enable }} + - name: spire-agent-socket + hostPath: + path: /run/spire/sockets + type: Directory + {{- end }} - name: host-boot hostPath: path: "/boot" diff --git a/deployment/helm/node-feature-discovery/values.yaml b/deployment/helm/node-feature-discovery/values.yaml index fae4b75497..afb998fa18 100644 --- a/deployment/helm/node-feature-discovery/values.yaml +++ b/deployment/helm/node-feature-discovery/values.yaml @@ -15,6 +15,9 @@ featureGates: priorityClassName: "" +spiffe: + enable: true + master: enable: true config: ### @@ -26,6 +29,7 @@ master: # enableTaints: false # labelWhiteList: "foo" # resyncPeriod: "2h" + # enableSpiffe: true # klog: # addDirHeader: false # alsologtostderr: false @@ -144,6 +148,7 @@ worker: # labelWhiteList: # noPublish: false # sleepInterval: 60s + # enableSpiffe: true # featureSources: [all] # labelSources: [all] # klog: diff --git a/deployment/overlays/spiffe/kustomization.yaml b/deployment/overlays/spiffe/kustomization.yaml new file mode 100644 index 0000000000..035abe0ee7 --- /dev/null +++ b/deployment/overlays/spiffe/kustomization.yaml @@ -0,0 +1,16 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: node-feature-discovery + +resources: +- spire-agent-cluster-role.yaml +- spire-agent-configmap.yaml +- spire-agent-daemonset.yaml +- spire-agent-service-account.yaml +- spire-bundle-configmap.yaml +- spire-server-cluster-role.yaml +- spire-server-configmap.yaml +- spire-server-service-account.yaml +- spire-server-service.yaml +- spire-server-statefulset.yaml diff --git a/deployment/overlays/spiffe/namespace.yaml b/deployment/overlays/spiffe/namespace.yaml new file mode 100644 index 0000000000..8e54de2e34 --- /dev/null +++ b/deployment/overlays/spiffe/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: node-feature-discovery diff --git a/deployment/overlays/spiffe/spire-agent-cluster-role.yaml b/deployment/overlays/spiffe/spire-agent-cluster-role.yaml new file mode 100644 index 0000000000..9937da9e58 --- /dev/null +++ b/deployment/overlays/spiffe/spire-agent-cluster-role.yaml @@ -0,0 +1,23 @@ +# Required cluster role to allow spire-agent to query k8s API server +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-agent-cluster-role +rules: +- apiGroups: [""] + resources: ["pods","nodes","nodes/proxy"] + verbs: ["get"] + +--- +# Binds above cluster role to spire-agent service account +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-agent-cluster-role-binding +subjects: +- kind: ServiceAccount + name: spire-agent +roleRef: + kind: ClusterRole + name: spire-agent-cluster-role + apiGroup: rbac.authorization.k8s.io diff --git a/deployment/overlays/spiffe/spire-agent-configmap.yaml b/deployment/overlays/spiffe/spire-agent-configmap.yaml new file mode 100644 index 0000000000..e5b9e53f0d --- /dev/null +++ b/deployment/overlays/spiffe/spire-agent-configmap.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-agent +data: + agent.conf: | + agent { + data_dir = "/run/spire" + log_level = "DEBUG" + server_address = "spire-server" + server_port = "8081" + socket_path = "/run/spire/sockets/agent.sock" + trust_bundle_path = "/run/spire/bundle/bundle.crt" + trust_domain = "nfd.com" + } + plugins { + NodeAttestor "k8s_sat" { + plugin_data { + cluster = "nfd" + } + } + KeyManager "memory" { + plugin_data { + } + } + WorkloadAttestor "k8s" { + plugin_data { + skip_kubelet_verification = true + node_name_env = "MY_NODE_NAME" + } + } + WorkloadAttestor "unix" { + plugin_data { + } + } + } + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } diff --git a/deployment/overlays/spiffe/spire-agent-daemonset.yaml b/deployment/overlays/spiffe/spire-agent-daemonset.yaml new file mode 100644 index 0000000000..831cd8a86d --- /dev/null +++ b/deployment/overlays/spiffe/spire-agent-daemonset.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: spire-agent + labels: + app: spire-agent +spec: + selector: + matchLabels: + app: spire-agent + template: + metadata: + labels: + app: spire-agent + spec: + hostPID: true + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + serviceAccountName: spire-agent + initContainers: + - name: init + # This is a small image with wait-for-it, choose whatever image + # you prefer that waits for a service to be up. This image is built + # from https://github.com/lqhl/wait-for-it + image: cgr.dev/chainguard/wait-for-it + args: ["-t", "30", "spire-server:8081"] + containers: + - name: spire-agent + image: ghcr.io/spiffe/spire-agent:1.5.1 + args: ["-config", "/run/spire/config/agent.conf"] + env: + - name: MY_NODE_NAME + valueFrom: + fieldRef: + fieldPath: status.podIP + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + - name: spire-bundle + mountPath: /run/spire/bundle + - name: spire-agent-socket + mountPath: /run/spire/sockets + readOnly: false + volumes: + - name: spire-config + configMap: + name: spire-agent + - name: spire-bundle + configMap: + name: spire-bundle + - name: spire-agent-socket + hostPath: + path: /run/spire/sockets + type: DirectoryOrCreate diff --git a/deployment/overlays/spiffe/spire-agent-service-account.yaml b/deployment/overlays/spiffe/spire-agent-service-account.yaml new file mode 100644 index 0000000000..36a0e4dd00 --- /dev/null +++ b/deployment/overlays/spiffe/spire-agent-service-account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: spire-agent diff --git a/deployment/overlays/spiffe/spire-bundle-configmap.yaml b/deployment/overlays/spiffe/spire-bundle-configmap.yaml new file mode 100644 index 0000000000..7ad63a5a89 --- /dev/null +++ b/deployment/overlays/spiffe/spire-bundle-configmap.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-bundle diff --git a/deployment/overlays/spiffe/spire-server-cluster-role.yaml b/deployment/overlays/spiffe/spire-server-cluster-role.yaml new file mode 100644 index 0000000000..06f1786bd3 --- /dev/null +++ b/deployment/overlays/spiffe/spire-server-cluster-role.yaml @@ -0,0 +1,45 @@ +# Role (namespace scoped) to be able to push certificate bundles to a configmap +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-configmap-role +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["patch", "get", "list"] +--- +# Binds above role to spire-server service account +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-configmap-role-binding +subjects: +- kind: ServiceAccount + name: spire-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: spire-server-configmap-role +--- +# ClusterRole to allow spire-server node attestor to query Token Review API +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-trust-role +rules: +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +--- +# Binds above cluster role to spire-server service account +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-trust-role-binding +subjects: +- kind: ServiceAccount + name: spire-server +roleRef: + kind: ClusterRole + name: spire-server-trust-role + apiGroup: rbac.authorization.k8s.io diff --git a/deployment/overlays/spiffe/spire-server-configmap.yaml b/deployment/overlays/spiffe/spire-server-configmap.yaml new file mode 100644 index 0000000000..ff5c6d77f2 --- /dev/null +++ b/deployment/overlays/spiffe/spire-server-configmap.yaml @@ -0,0 +1,56 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + socket_path = "/tmp/spire-server/private/api.sock" + trust_domain = "nfd.com" + data_dir = "/run/spire/data" + log_level = "DEBUG" + #AWS requires the use of RSA. EC cryptography is not supported + ca_key_type = "rsa-2048" + ca_subject = { + country = ["US"], + organization = ["SPIFFE"], + common_name = "nfd.com", + } + } + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + NodeAttestor "k8s_sat" { + plugin_data { + clusters = { + "nfd" = { + use_token_review_api_validation = true + service_account_allow_list = ["{{ include "node-feature-discovery.namespace" . }}:spire-agent"] + } + } + } + } + KeyManager "disk" { + plugin_data { + keys_path = "/run/spire/data/keys.json" + } + } + Notifier "k8sbundle" { + plugin_data { + namespace = "{{ include "node-feature-discovery.namespace" . }}" + } + } + } + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } diff --git a/deployment/overlays/spiffe/spire-server-service-account.yaml b/deployment/overlays/spiffe/spire-server-service-account.yaml new file mode 100644 index 0000000000..acf9944260 --- /dev/null +++ b/deployment/overlays/spiffe/spire-server-service-account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: spire-server diff --git a/deployment/overlays/spiffe/spire-server-service.yaml b/deployment/overlays/spiffe/spire-server-service.yaml new file mode 100644 index 0000000000..cf9c1f067e --- /dev/null +++ b/deployment/overlays/spiffe/spire-server-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: spire-server +spec: + type: NodePort + ports: + - name: grpc + port: 8081 + targetPort: 8081 + protocol: TCP + selector: + app: spire-server diff --git a/deployment/overlays/spiffe/spire-server-statefulset.yaml b/deployment/overlays/spiffe/spire-server-statefulset.yaml new file mode 100644 index 0000000000..e6fd227214 --- /dev/null +++ b/deployment/overlays/spiffe/spire-server-statefulset.yaml @@ -0,0 +1,60 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: spire-server + labels: + app: spire-server +spec: + replicas: 1 + selector: + matchLabels: + app: spire-server + serviceName: spire-server + template: + metadata: + labels: + app: spire-server + spec: + serviceAccountName: spire-server + containers: + - name: spire-server + image: ghcr.io/spiffe/spire-server:1.5.1 + args: + - -config + - /run/spire/config/server.conf + ports: + - containerPort: 8081 + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + - name: spire-data + mountPath: /run/spire/data + readOnly: false + livenessProbe: + httpGet: + path: /live + port: 8080 + failureThreshold: 2 + initialDelaySeconds: 15 + periodSeconds: 60 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: spire-config + configMap: + name: spire-server + volumeClaimTemplates: + - metadata: + name: spire-data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/go.mod b/go.mod index 15cc43ec81..459efa9fd7 100644 --- a/go.mod +++ b/go.mod @@ -42,23 +42,7 @@ require ( ) require ( - github.com/Microsoft/go-winio v0.6.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.29 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/autorest/mocks v0.4.2 // indirect - github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect - github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b // indirect - github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.8.25 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect @@ -78,8 +62,8 @@ require ( github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ghodss/yaml v1.0.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -123,11 +107,7 @@ require ( github.com/smarty/assertions v1.15.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect - github.com/vishvananda/netlink v1.1.0 // indirect - github.com/vishvananda/netns v0.0.4 // indirect - github.com/vmware/govmomi v0.30.6 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/zeebo/errs v1.3.0 // indirect go.etcd.io/etcd/api/v3 v3.5.10 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect @@ -145,17 +125,16 @@ require ( go.uber.org/zap v1.26.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/mod v0.15.0 // indirect - golang.org/x/oauth2 v0.14.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.18.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect - gopkg.in/gcfg.v1 v1.2.3 // indirect + google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 8cbf631d45..6fa5c82e36 100644 --- a/go.sum +++ b/go.sum @@ -37,7 +37,7 @@ cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFO cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -606,13 +606,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab h1:UKkYhof1njT1/xq4SEg5z+VpTgjmNeHwPGRQl7takDI= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.8.25 h1:fRMwXiwk3qDwc0P05eHnh+y2v07JdtsfQ1fuAc69m9g= -github.com/Microsoft/hcsshim v0.8.25/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= @@ -672,15 +667,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/container-storage-interface/spec v1.8.0 h1:D0vhF3PLIZwlwZEf2eNbpujGCNwspwTYf2idJRJx4xI= -github.com/container-storage-interface/spec v1.8.0/go.mod h1:ROLik+GhPslwwWRNFF1KasPzroNARibH2rfz1rkg4H0= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs= @@ -750,7 +738,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -1119,7 +1106,6 @@ github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyh github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spiffe/go-spiffe/v2 v2.2.0 h1:9Vf06UsvsDbLYK/zJ4sYsIsHmMFknUD+feA7IYoWMQY= github.com/spiffe/go-spiffe/v2 v2.2.0/go.mod h1:Urzb779b3+IwDJD2ZbN8fVl3Aa8G4N/PiUe6iXC0XxU= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= @@ -1138,7 +1124,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index e0de78db51..235f27b08b 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -1486,7 +1486,13 @@ func (m *nfdMaster) getVerifiedNFDObjects(objs []*v1alpha1.NodeFeature) ([]*v1al } for _, obj := range objs { - isSignatureVerified, err := spiffe.VerifyDataSignature(obj.Spec, obj.Annotations["signature"], workerPrivateKey, workerPublicKey) + spiffeObj := spiffe.SpiffeObject{ + Spec: obj.Spec, + Name: obj.Name, + Namespace: obj.Namespace, + Labels: obj.Labels, + } + isSignatureVerified, err := spiffe.VerifyDataSignature(spiffeObj, obj.Annotations["signature"], workerPrivateKey, workerPublicKey) if err != nil { return nil, fmt.Errorf("failed to verify NodeFeature signature: %w", err) } diff --git a/pkg/nfd-worker/nfd-worker.go b/pkg/nfd-worker/nfd-worker.go index fb225d56c4..2765dbf49e 100644 --- a/pkg/nfd-worker/nfd-worker.go +++ b/pkg/nfd-worker/nfd-worker.go @@ -864,7 +864,13 @@ func (m *nfdWorker) signNodeFeatureCR(nfr *nfdv1alpha1.NodeFeature) error { return fmt.Errorf("error while getting worker keys: %w", err) } - signature, err := spiffe.SignData(nfr.Spec, workerPrivateKey) + spiffeObject := spiffe.SpiffeObject{ + Spec: nfr.Spec, + Name: nfr.Name, + Namespace: nfr.Namespace, + Labels: nfr.Labels, + } + signature, err := spiffe.SignData(spiffeObject, workerPrivateKey) if err != nil { return fmt.Errorf("failed to sign CRD data using Spiffe: %w", err) diff --git a/pkg/utils/spiffe/spiffe.go b/pkg/utils/spiffe/spiffe.go index 542f4bde17..7ea8af2e22 100644 --- a/pkg/utils/spiffe/spiffe.go +++ b/pkg/utils/spiffe/spiffe.go @@ -4,6 +4,7 @@ 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. @@ -11,7 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package utils +package spiffe import ( "context" @@ -25,8 +26,16 @@ import ( "fmt" "github.com/spiffe/go-spiffe/v2/workloadapi" + nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" ) +type SpiffeObject struct { + Spec nfdv1alpha1.NodeFeatureSpec + Name string + Namespace string + Labels map[string]string +} + // WorkerSpiffeID is the SpiffeID of the worker const WorkerSpiffeID = "spiffe://nfd.com/worker" @@ -44,7 +53,7 @@ func NewSpiffeClient(socketPath string) (*SpiffeClient, error) { return &spiffeClient, nil } -func SignData(data interface{}, privateKey crypto.Signer) ([]byte, error) { +func SignData(data SpiffeObject, privateKey crypto.Signer) ([]byte, error) { stringifyData, err := json.Marshal(data) if err != nil { return []byte{}, err @@ -70,7 +79,7 @@ func SignData(data interface{}, privateKey crypto.Signer) ([]byte, error) { } } -func VerifyDataSignature(data interface{}, signedData string, privateKey crypto.Signer, publicKey crypto.PublicKey) (bool, error) { +func VerifyDataSignature(data SpiffeObject, signedData string, privateKey crypto.Signer, publicKey crypto.PublicKey) (bool, error) { stringifyData, err := json.Marshal(data) if err != nil { return false, err diff --git a/pkg/utils/spiffe/spiffe_test.go b/pkg/utils/spiffe/spiffe_test.go index 8fc9f17e2d..f07b1af9bf 100644 --- a/pkg/utils/spiffe/spiffe_test.go +++ b/pkg/utils/spiffe/spiffe_test.go @@ -4,6 +4,7 @@ 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. @@ -11,7 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package utils +package spiffe import ( "crypto" @@ -76,15 +77,23 @@ func TestVerify(t *testing.T) { } for _, tt := range tc { - signedData, err := SignData(spec, tt.privateKey) + spiffeObj := SpiffeObject{ + Spec: spec, + Name: "test", + Namespace: "test", + Labels: map[string]string{ + "random": "test", + }, + } + signedData, err := SignData(spiffeObj, tt.privateKey) assert.NoError(t, err) - isVerified, err := VerifyDataSignature(spec, b64.StdEncoding.EncodeToString(signedData), tt.privateKey, tt.publicKey) + isVerified, err := VerifyDataSignature(spiffeObj, b64.StdEncoding.EncodeToString(signedData), tt.privateKey, tt.publicKey) assert.NoError(t, err) assert.True(t, isVerified) signedData = append(signedData, "random"...) - isVerified, err = VerifyDataSignature(spec, b64.StdEncoding.EncodeToString(signedData), tt.privateKey, tt.publicKey) + isVerified, err = VerifyDataSignature(spiffeObj, b64.StdEncoding.EncodeToString(signedData), tt.privateKey, tt.publicKey) if tt.wantErr { assert.Error(t, err) } else { @@ -113,7 +122,15 @@ func TestSignData(t *testing.T) { } for _, tt := range tc { - _, err := SignData(spec, tt.privateKey) + spiffeObj := SpiffeObject{ + Spec: spec, + Name: "test", + Namespace: "test", + Labels: map[string]string{ + "random": "test", + }, + } + _, err := SignData(spiffeObj, tt.privateKey) assert.NoError(t, err) } }