diff --git a/deployment/helm/node-feature-discovery/Chart.lock b/deployment/helm/node-feature-discovery/Chart.lock new file mode 100644 index 0000000000..a539c76953 --- /dev/null +++ b/deployment/helm/node-feature-discovery/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: spire + repository: https://spiffe.github.io/helm-charts-hardened/ + version: 0.24.1 +digest: sha256:f3b4dc973a59682bf3aa5ca9b53322f57935dd093081e82a37b8082e00becbe9 +generated: "2024-12-20T16:52:40.180416+01:00" diff --git a/deployment/helm/node-feature-discovery/Chart.yaml b/deployment/helm/node-feature-discovery/Chart.yaml index 553fc3c07b..a96696f494 100644 --- a/deployment/helm/node-feature-discovery/Chart.yaml +++ b/deployment/helm/node-feature-discovery/Chart.yaml @@ -13,3 +13,7 @@ keywords: - node-labels type: application version: 0.2.1 +dependencies: + - name: spire + version: 0.24.1 + repository: https://spiffe.github.io/helm-charts-hardened/ diff --git a/deployment/helm/node-feature-discovery/charts/spire-0.24.1.tgz b/deployment/helm/node-feature-discovery/charts/spire-0.24.1.tgz new file mode 100644 index 0000000000..2ed7d582e0 Binary files /dev/null and b/deployment/helm/node-feature-discovery/charts/spire-0.24.1.tgz differ diff --git a/deployment/helm/node-feature-discovery/templates/master.yaml b/deployment/helm/node-feature-discovery/templates/master.yaml index da3ca2408f..610c3a67a6 100644 --- a/deployment/helm/node-feature-discovery/templates/master.yaml +++ b/deployment/helm/node-feature-discovery/templates/master.yaml @@ -144,11 +144,25 @@ spec: {{- with .Values.master.extraArgs }} {{- toYaml . | nindent 12 }} {{- end }} + {{- if .Values.spire.enabled }} + - "-enable-spiffe" + {{- end }} volumeMounts: + {{- if .Values.spire.enabled }} + - name: spire-agent-socket + mountPath: /run/spire/agent-sockets + readOnly: true + {{- end }} - name: nfd-master-conf mountPath: "/etc/kubernetes/node-feature-discovery" readOnly: true volumes: + {{- if .Values.spire.enabled }} + - name: spire-agent-socket + hostPath: + path: /run/spire/agent-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/worker.yaml b/deployment/helm/node-feature-discovery/templates/worker.yaml index 5fd1ab7444..e576239f96 100644 --- a/deployment/helm/node-feature-discovery/templates/worker.yaml +++ b/deployment/helm/node-feature-discovery/templates/worker.yaml @@ -109,12 +109,20 @@ spec: {{- with .Values.gc.extraArgs }} {{- toYaml . | nindent 8 }} {{- end }} + {{- if .Values.spire.enabled }} + - "-enable-spiffe" + {{- end }} ports: - containerPort: {{ .Values.worker.metricsPort | default "8081"}} name: metrics - containerPort: {{ .Values.worker.healthPort | default "8082" }} name: health volumeMounts: + {{- if .Values.spire.enabled }} + - name: spire-agent-socket + mountPath: /run/spire/agent-sockets + readOnly: true + {{- end }} - name: host-boot mountPath: "/host-boot" readOnly: true @@ -145,6 +153,12 @@ spec: mountPath: "/etc/kubernetes/node-feature-discovery" readOnly: true volumes: + {{- if .Values.spire.enabled }} + - name: spire-agent-socket + hostPath: + path: /run/spire/agent-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 68440f9c6e..3bc73d2447 100644 --- a/deployment/helm/node-feature-discovery/values.yaml +++ b/deployment/helm/node-feature-discovery/values.yaml @@ -597,3 +597,47 @@ prometheus: enable: false scrapeInterval: 10s labels: {} + +spire: + enabled: true + global: + spire: + clusterName: "nfd" + trustDomain: "nfd.io" + spire-agent: + kubeletConnectByHostname: "true" + workloadAttestors: + unix: + enabled: true + spire-server: + controllerManager: + enabled: true + identities: + clusterStaticEntries: + node: + parentID: spiffe://nfd.io/spire/server + spiffeID: spiffe://nfd.io/root + selectors: + - k8s_psat:agent_ns:nfd + - k8s_psat:agent_sa:nfd-agent + - k8s_psat:cluster:nfd + nfd: + parentID: spiffe://nfd.io/root + spiffeID: spiffe://nfd.io/worker + selectors: + - k8s:pod-label:app.kubernetes.io/name:node-feature-discovery + + + caSubject: + commonName: "nfd.io" + country: "US" + organization: "SPIFFE" + + upstream: + enabled: false + spiffe-csi-driver: + enabled: false + spiffe-oidc-discovery-provider: + enabled: false + tornjak-frontend: + enabled: false diff --git a/go.mod b/go.mod index de94b32651..6e1b80732a 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/prometheus/client_golang v1.19.1 github.com/smartystreets/goconvey v1.8.1 github.com/spf13/cobra v1.8.1 + github.com/spiffe/go-spiffe/v2 v2.4.0 github.com/stretchr/testify v1.10.0 github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 @@ -68,6 +69,7 @@ require ( github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -120,6 +122,7 @@ require ( github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/zeebo/errs v1.3.0 // indirect go.etcd.io/etcd/api/v3 v3.5.16 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect go.etcd.io/etcd/client/v3 v3.5.16 // indirect diff --git a/go.sum b/go.sum index 6929b56b3f..9cf2647075 100644 --- a/go.sum +++ b/go.sum @@ -66,6 +66,8 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/ github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -113,27 +115,6 @@ github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgY github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= -github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -249,6 +230,8 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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/spiffe/go-spiffe/v2 v2.4.0 h1:j/FynG7hi2azrBG5cvjRcnQ4sux/VNj8FAVc99Fl66c= +github.com/spiffe/go-spiffe/v2 v2.4.0/go.mod h1:m5qJ1hGzjxjtrkGHZupoXHo/FDWwCB1MdSyBzfHugx0= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -256,7 +239,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -274,6 +256,8 @@ github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chq github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= +github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0= diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go index 8e5ad9975a..1fdb14dbac 100644 --- a/pkg/nfd-master/nfd-master.go +++ b/pkg/nfd-master/nfd-master.go @@ -52,12 +52,6 @@ import ( "sigs.k8s.io/yaml" nfdclientset "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned" - klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog" - spiffe "sigs.k8s.io/node-feature-discovery/pkg/utils/spiffe" - - taintutils "k8s.io/kubernetes/pkg/util/taints" - "sigs.k8s.io/yaml" - "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/nodefeaturerule" @@ -65,11 +59,12 @@ import ( nfdfeatures "sigs.k8s.io/node-feature-discovery/pkg/features" "sigs.k8s.io/node-feature-discovery/pkg/utils" klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog" + spiffe "sigs.k8s.io/node-feature-discovery/pkg/utils/spiffe" "sigs.k8s.io/node-feature-discovery/pkg/version" ) // SocketPath specifies Spiffe Socket Path -const SocketPath = "unix:///run/spire/sockets/agent.sock" +const SocketPath = "unix:///run/spire/agent-sockets/api.sock" // Labels are a Kubernetes representation of discovered features. type Labels map[string]string @@ -700,6 +695,14 @@ func (m *nfdMaster) getAndMergeNodeFeatures(nodeName string) (*nfdv1alpha1.NodeF return filteredObjs[i].Namespace < filteredObjs[j].Namespace }) + // If spiffe is enabled, we should filter out the non verified NFD objects + if m.config.EnableSpiffe { + filteredObjs, err = m.getVerifiedNFDObjects(filteredObjs) + if err != nil { + return &nfdv1alpha1.NodeFeature{}, err + } + } + if len(filteredObjs) > 0 { // Merge in features // @@ -755,55 +758,6 @@ func (m *nfdMaster) nfdAPIUpdateOneNode(cli k8sclient.Interface, node *corev1.No return fmt.Errorf("failed to merge NodeFeature objects for node %q: %w", node.Name, err) } - // Sort our objects - sort.Slice(objs, func(i, j int) bool { - // Objects in our nfd namespace gets into the beginning of the list - if objs[i].Namespace == m.namespace && objs[j].Namespace != m.namespace { - return true - } - if objs[i].Namespace != m.namespace && objs[j].Namespace == m.namespace { - return false - } - // After the nfd namespace, sort objects by their name - if objs[i].Name != objs[j].Name { - return objs[i].Name < objs[j].Name - } - // Objects with the same name are sorted by their namespace - return objs[i].Namespace < objs[j].Namespace - }) - - // If spiffe is enabled, we should filter out the non verified NFD objects - if m.config.EnableSpiffe { - objs, err = m.getVerifiedNFDObjects(objs) - if err != nil { - return err - } - } - - klog.V(1).InfoS("processing of node initiated by NodeFeature API", "nodeName", node.Name) - - features := nfdv1alpha1.NewNodeFeatureSpec() - - if len(objs) > 0 { - // Merge in features - // - // NOTE: changing the rule api to support handle multiple objects instead - // of merging would probably perform better with lot less data to copy. - features = objs[0].Spec.DeepCopy() - if m.config.AutoDefaultNs { - features.Labels = addNsToMapKeys(features.Labels, nfdv1alpha1.FeatureLabelNs) - } - for _, o := range objs[1:] { - s := o.Spec.DeepCopy() - if m.config.AutoDefaultNs { - s.Labels = addNsToMapKeys(s.Labels, nfdv1alpha1.FeatureLabelNs) - } - s.MergeInto(features) - } - - klog.V(4).InfoS("merged nodeFeatureSpecs", "newNodeFeatureSpec", utils.DelayedDumper(features)) - } - // Update node labels et al. This may also mean removing all NFD-owned // labels (et al.), for example in the case no NodeFeature objects are // present. @@ -1528,7 +1482,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 7877806214..5eff6d87ef 100644 --- a/pkg/nfd-worker/nfd-worker.go +++ b/pkg/nfd-worker/nfd-worker.go @@ -17,8 +17,6 @@ limitations under the License. package nfdworker import ( - "crypto/tls" - "crypto/x509" b64 "encoding/base64" "encoding/json" "fmt" @@ -35,24 +33,22 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/validation" k8sclient "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" - klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog" "sigs.k8s.io/yaml" - apiequality "k8s.io/apimachinery/pkg/api/equality" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" nfdclient "sigs.k8s.io/node-feature-discovery/api/generated/clientset/versioned" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1" "sigs.k8s.io/node-feature-discovery/pkg/utils" + klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog" spiffe "sigs.k8s.io/node-feature-discovery/pkg/utils/spiffe" "sigs.k8s.io/node-feature-discovery/pkg/version" "sigs.k8s.io/node-feature-discovery/source" - - // Register all source packages _ "sigs.k8s.io/node-feature-discovery/source/cpu" _ "sigs.k8s.io/node-feature-discovery/source/custom" _ "sigs.k8s.io/node-feature-discovery/source/fake" @@ -67,7 +63,7 @@ import ( ) // SocketPath specifies Spiffe Socket Path -const SocketPath = "unix:///run/spire/sockets/agent.sock" +const SocketPath = "unix:///run/spire/agent-sockets/api.sock" // NfdWorker is the interface for nfd-worker daemon type NfdWorker interface { @@ -785,7 +781,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..3625b8b1be 100644 --- a/pkg/utils/spiffe/spiffe.go +++ b/pkg/utils/spiffe/spiffe.go @@ -3,7 +3,9 @@ Copyright 2024 The Kubernetes 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. @@ -11,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package utils +package spiffe import ( "context" @@ -25,10 +27,19 @@ 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" +const WorkerSpiffeID = "spiffe://nfd.io/worker" type SpiffeClient struct { WorkloadApiClient workloadapi.Client @@ -44,7 +55,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 +81,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 @@ -112,7 +123,7 @@ func (s *SpiffeClient) GetWorkerKeys() (crypto.Signer, crypto.PublicKey, error) for _, svid := range svids { if svid.ID.String() == WorkerSpiffeID { - return svid.PrivateKey, svid.PrivateKey.Public, nil + return svid.PrivateKey, svid.PrivateKey.Public(), nil } } diff --git a/pkg/utils/spiffe/spiffe_test.go b/pkg/utils/spiffe/spiffe_test.go index 8fc9f17e2d..7bfbe22e1a 100644 --- a/pkg/utils/spiffe/spiffe_test.go +++ b/pkg/utils/spiffe/spiffe_test.go @@ -3,7 +3,9 @@ Copyright 2024 The Kubernetes 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. @@ -11,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package utils +package spiffe import ( "crypto" @@ -76,15 +78,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 +123,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) } }