Skip to content

Commit 0e62e8b

Browse files
committed
feat: add support for trust config
1 parent 0f70445 commit 0e62e8b

File tree

6 files changed

+133
-11
lines changed

6 files changed

+133
-11
lines changed

api/v1alpha1/modelvalidation_types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,25 @@ type PublicKeyConfig struct {
5353
KeyPath string `json:"keyPath,omitempty"`
5454
}
5555

56+
// ClientTrustConfig defines the configuration for client trust settings,
57+
// used when working with private rekor/fulcio instances.
58+
type ClientTrustConfig struct {
59+
// TrustConfigPath is the path to the trust configuration file.
60+
// This specifies the trust configuration needed for using private rekor/fulcio instances
61+
// and should conform to the ClientTrustConfig message.
62+
// +kubebuilder:validation:Required
63+
TrustConfigPath string `json:"trustConfigPath,omitempty"`
64+
}
65+
5666
// ValidationConfig defines the various methods available for validating model signatures.
5767
// At least one validation method must be specified.
5868
type ValidationConfig struct {
5969
SigstoreConfig *SigstoreConfig `json:"sigstoreConfig,omitempty"`
6070
PkiConfig *PkiConfig `json:"pkiConfig,omitempty"`
6171
PublicKeyConfig *PublicKeyConfig `json:"publicKeyConfig,omitempty"`
72+
// +kubebuilder:validation:Optional
73+
// ClientTrustConfig is the configuration for client trust settings.
74+
ClientTrustConfig *ClientTrustConfig `json:"clientTrustConfig,omitempty"`
6275
}
6376

6477
// ModelValidationSpec defines the desired state of ModelValidation
@@ -172,6 +185,11 @@ func (vc *ValidationConfig) GetConfigHash() string {
172185
hasher.Write([]byte(vc.PublicKeyConfig.KeyPath))
173186
}
174187

188+
if vc.ClientTrustConfig != nil {
189+
hasher.Write([]byte("clienttrust"))
190+
hasher.Write([]byte(vc.ClientTrustConfig.TrustConfigPath))
191+
}
192+
175193
return fmt.Sprintf("%x", hasher.Sum(nil))[:16] // Use first 16 chars for brevity
176194
}
177195

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/ml.sigstore.dev_modelvalidations.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ spec:
5858
config:
5959
description: Configuration for validation methods.
6060
properties:
61+
clientTrustConfig:
62+
description: ClientTrustConfig is the configuration for client
63+
trust settings.
64+
properties:
65+
trustConfigPath:
66+
description: |-
67+
TrustConfigPath is the path to the trust configuration file.
68+
This specifies the trust configuration needed for using private rekor/fulcio instances
69+
and should conform to the ClientTrustConfig message.
70+
type: string
71+
required:
72+
- trustConfigPath
73+
type: object
6174
pkiConfig:
6275
description: |-
6376
PkiConfig defines the PKI-based verification configuration

internal/testutil/testutil.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type TestModelValidationOptions struct {
3131
CertificateCA string
3232
CertIdentity string
3333
CertOidcIssuer string
34+
TrustConfigPath string
3435
}
3536

3637
// TestPodOptions holds configuration for creating test Pod resources
@@ -102,6 +103,13 @@ func CreateTestModelValidation(opts TestModelValidationOptions) *v1alpha1.ModelV
102103
}
103104
}
104105

106+
// Add ClientTrustConfig if trust config path is provided
107+
if opts.TrustConfigPath != "" {
108+
mv.Spec.Config.ClientTrustConfig = &v1alpha1.ClientTrustConfig{
109+
TrustConfigPath: opts.TrustConfigPath,
110+
}
111+
}
112+
105113
return mv
106114
}
107115

internal/webhooks/pod_webhook.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,28 +130,27 @@ func validationConfigToArgs(logger logr.Logger, cfg v1alpha1.ValidationConfig, s
130130
"--identity", cfg.SigstoreConfig.CertificateIdentity,
131131
"--identity_provider", cfg.SigstoreConfig.CertificateOidcIssuer,
132132
)
133-
return res
134-
}
135-
136-
if cfg.PublicKeyConfig != nil {
133+
} else if cfg.PublicKeyConfig != nil {
137134
logger.Info("found public-key config")
138135
res = append(res,
139136
"key",
140137
fmt.Sprintf("--signature=%s", signaturePath),
141138
"--public_key", cfg.PublicKeyConfig.KeyPath,
142139
)
143-
return res
144-
}
145-
146-
if cfg.PkiConfig != nil {
140+
} else if cfg.PkiConfig != nil {
147141
logger.Info("found pki config")
148142
res = append(res,
149143
"certificate",
150144
fmt.Sprintf("--signature=%s", signaturePath),
151145
"--certificate_chain", cfg.PkiConfig.CertificateAuthority,
152146
)
153-
return res
147+
} else {
148+
logger.Info("missing validation config")
149+
return []string{}
150+
}
151+
152+
if cfg.ClientTrustConfig != nil {
153+
res = append(res, "--trust_config", cfg.ClientTrustConfig.TrustConfigPath)
154154
}
155-
logger.Info("missing validation config")
156-
return []string{}
155+
return res
157156
}

internal/webhooks/pod_webhook_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,69 @@ var _ = Describe("Pod webhook", func() {
139139
}
140140
Expect(foundTrackedPod).To(BeTrue(), "Pod should be tracked in status")
141141
})
142+
143+
It("Should add trust_config argument when ClientTrustConfig is provided", func() {
144+
trustConfigName := "trust-config-test"
145+
trustConfigNamespace := fmt.Sprintf("trust-config-ns-%d", time.Now().UnixNano())
146+
147+
By("Creating the Namespace for trust config test")
148+
trustConfigNs := &corev1.Namespace{
149+
ObjectMeta: metav1.ObjectMeta{
150+
Name: trustConfigNamespace,
151+
},
152+
}
153+
err := k8sClient.Create(ctx, trustConfigNs)
154+
Expect(err).To(Not(HaveOccurred()))
155+
156+
By("Create ModelValidation with ClientTrustConfig")
157+
trustMv := testutil.CreateTestModelValidation(testutil.TestModelValidationOptions{
158+
Name: trustConfigName,
159+
Namespace: trustConfigNamespace,
160+
ConfigType: "sigstore",
161+
CertIdentity: "[email protected]",
162+
CertOidcIssuer: "https://accounts.google.com",
163+
TrustConfigPath: "/path/to/trust-config.json",
164+
})
165+
err = k8sClient.Create(ctx, trustMv)
166+
Expect(err).To(Not(HaveOccurred()))
167+
168+
statusTracker.AddModelValidation(ctx, trustMv)
169+
170+
By("create labeled pod with trust config")
171+
trustPod := testutil.CreateTestPod(testutil.TestPodOptions{
172+
Name: "trust-config-pod",
173+
Namespace: trustConfigNamespace,
174+
Labels: map[string]string{constants.ModelValidationLabel: trustConfigName},
175+
})
176+
err = k8sClient.Create(ctx, trustPod)
177+
Expect(err).To(Not(HaveOccurred()))
178+
179+
By("Checking that validation sidecar was created with trust config")
180+
foundTrustPod := &corev1.Pod{}
181+
Eventually(ctx, func(ctx context.Context) []corev1.Container {
182+
_ = k8sClient.Get(ctx, types.NamespacedName{Name: "trust-config-pod", Namespace: trustConfigNamespace}, foundTrustPod)
183+
return foundTrustPod.Spec.InitContainers
184+
}, 5*time.Second).Should(HaveLen(1))
185+
186+
By("Verifying trust_config argument is present")
187+
initContainer := foundTrustPod.Spec.InitContainers[0]
188+
args := initContainer.Args
189+
Expect(args).To(ContainElement("--trust_config"))
190+
191+
// Find the index of --trust_config and verify the next element is the path
192+
trustConfigIndex := -1
193+
for i, arg := range args {
194+
if arg == "--trust_config" {
195+
trustConfigIndex = i
196+
break
197+
}
198+
}
199+
Expect(trustConfigIndex).To(BeNumerically(">=", 0), "trust_config argument should be present")
200+
Expect(trustConfigIndex+1).To(BeNumerically("<", len(args)), "trust_config should have a value")
201+
Expect(args[trustConfigIndex+1]).To(Equal("/path/to/trust-config.json"))
202+
203+
By("Cleanup trust config namespace")
204+
_ = k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: trustConfigNamespace}})
205+
})
142206
})
143207
})

0 commit comments

Comments
 (0)