Skip to content

Commit 840e717

Browse files
committed
Add CLI flag for OCIRepo verify secret
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
1 parent ae0c3c8 commit 840e717

5 files changed

+158
-10
lines changed

cmd/flux/create_source_oci.go

+27-10
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,18 @@ var createSourceOCIRepositoryCmd = &cobra.Command{
5151
}
5252

5353
type sourceOCIRepositoryFlags struct {
54-
url string
55-
tag string
56-
semver string
57-
digest string
58-
secretRef string
59-
serviceAccount string
60-
certSecretRef string
61-
ignorePaths []string
62-
provider flags.SourceOCIProvider
63-
insecure bool
54+
url string
55+
tag string
56+
semver string
57+
digest string
58+
secretRef string
59+
serviceAccount string
60+
certSecretRef string
61+
verifyProvider flags.SourceOCIVerifyProvider
62+
verifySecretRef string
63+
ignorePaths []string
64+
provider flags.SourceOCIProvider
65+
insecure bool
6466
}
6567

6668
var sourceOCIRepositoryArgs = newSourceOCIFlags()
@@ -80,6 +82,8 @@ func init() {
8082
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of the Kubernetes image pull secret (type 'kubernetes.io/dockerconfigjson')")
8183
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.serviceAccount, "service-account", "", "the name of the Kubernetes service account that refers to an image pull secret")
8284
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.certSecretRef, "cert-ref", "", "the name of a secret to use for TLS certificates")
85+
createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.verifyProvider, "verify-provider", sourceOCIRepositoryArgs.verifyProvider.Description())
86+
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifySecretRef, "verify-secret-ref", "", "the name of a secret to use for signature verification")
8387
createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)")
8488
createSourceOCIRepositoryCmd.Flags().BoolVar(&sourceOCIRepositoryArgs.insecure, "insecure", false, "for when connecting to a non-TLS registries over plain HTTP")
8589

@@ -156,6 +160,19 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
156160
}
157161
}
158162

163+
if provider := sourceOCIRepositoryArgs.verifyProvider.String(); provider != "" {
164+
repository.Spec.Verify = &sourcev1.OCIRepositoryVerification{
165+
Provider: provider,
166+
}
167+
if secretName := sourceOCIRepositoryArgs.verifySecretRef; secretName != "" {
168+
repository.Spec.Verify.SecretRef = &meta.LocalObjectReference{
169+
Name: secretName,
170+
}
171+
}
172+
} else if sourceOCIRepositoryArgs.verifySecretRef != "" {
173+
return fmt.Errorf("a verification provider must be specified when a secret is specified")
174+
}
175+
159176
if createArgs.export {
160177
return printExport(exportOCIRepository(repository))
161178
}

cmd/flux/create_source_oci_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ func TestCreateSourceOCI(t *testing.T) {
3636
args: "create source oci podinfo",
3737
assertFunc: assertError("url is required"),
3838
},
39+
{
40+
name: "verify provider not specified",
41+
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-secret-ref=cosign-pub",
42+
assertFunc: assertError("a verification provider must be specified when a secret is specified"),
43+
},
3944
{
4045
name: "export manifest",
4146
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --export",
@@ -46,6 +51,11 @@ func TestCreateSourceOCI(t *testing.T) {
4651
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --secret-ref=creds --export",
4752
assertFunc: assertGoldenFile("./testdata/oci/export_with_secret.golden"),
4853
},
54+
{
55+
name: "export manifest with verify secret",
56+
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --verify-provider=cosign --verify-secret-ref=cosign-pub --export",
57+
assertFunc: assertGoldenFile("./testdata/oci/export_with_verify_secret.golden"),
58+
},
4959
}
5060

5161
for _, tt := range tests {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
apiVersion: source.toolkit.fluxcd.io/v1beta2
3+
kind: OCIRepository
4+
metadata:
5+
name: podinfo
6+
namespace: flux-system
7+
spec:
8+
interval: 10m0s
9+
ref:
10+
tag: 6.3.5
11+
url: oci://ghcr.io/stefanprodan/manifests/podinfo
12+
verify:
13+
provider: cosign
14+
secretRef:
15+
name: cosign-pub
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright 2023 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package flags
18+
19+
import (
20+
"fmt"
21+
"strings"
22+
23+
"github.com/fluxcd/flux2/v2/internal/utils"
24+
)
25+
26+
var supportedSourceOCIVerifyProviders = []string{
27+
"cosign",
28+
}
29+
30+
type SourceOCIVerifyProvider string
31+
32+
func (p *SourceOCIVerifyProvider) String() string {
33+
return string(*p)
34+
}
35+
36+
func (p *SourceOCIVerifyProvider) Set(str string) error {
37+
if strings.TrimSpace(str) == "" {
38+
return fmt.Errorf("no source OCI verify provider given, please specify %s",
39+
p.Description())
40+
}
41+
if !utils.ContainsItemString(supportedSourceOCIVerifyProviders, str) {
42+
return fmt.Errorf("source OCI verify provider '%s' is not supported, must be one of: %v",
43+
str, strings.Join(supportedSourceOCIVerifyProviders, ", "))
44+
}
45+
*p = SourceOCIVerifyProvider(str)
46+
return nil
47+
}
48+
49+
func (p *SourceOCIVerifyProvider) Type() string {
50+
return "sourceOCIVerifyProvider"
51+
}
52+
53+
func (p *SourceOCIVerifyProvider) Description() string {
54+
return fmt.Sprintf(
55+
"the OCI verify provider name to use for signature verification, available options are: (%s)",
56+
strings.Join(supportedSourceOCIVerifyProviders, ", "),
57+
)
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//go:build !e2e
2+
// +build !e2e
3+
4+
/*
5+
Copyright 2023 The Flux authors
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package flags
21+
22+
import (
23+
"testing"
24+
)
25+
26+
func TestSourceOCIVerifyProvider_Set(t *testing.T) {
27+
tests := []struct {
28+
name string
29+
str string
30+
expect string
31+
expectErr bool
32+
}{
33+
{"supported", "cosign", "cosign", false},
34+
{"unsupported", "unsupported", "", true},
35+
{"empty", "", "", true},
36+
}
37+
for _, tt := range tests {
38+
t.Run(tt.name, func(t *testing.T) {
39+
var s SourceOCIVerifyProvider
40+
if err := s.Set(tt.str); (err != nil) != tt.expectErr {
41+
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
42+
}
43+
if str := s.String(); str != tt.expect {
44+
t.Errorf("Set() = %v, expect %v", str, tt.expect)
45+
}
46+
})
47+
}
48+
}

0 commit comments

Comments
 (0)