diff --git a/go.mod b/go.mod index dbdbddc7b..42f78c77d 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,7 @@ require ( github.com/fluxcd/pkg/testserver v0.4.0 github.com/fluxcd/pkg/version v0.2.2 github.com/fluxcd/source-controller/api v1.0.0 + github.com/foxcpp/go-mockdns v1.0.0 github.com/go-git/go-billy/v5 v5.4.1 github.com/go-git/go-git/v5 v5.7.0 github.com/go-logr/logr v1.2.4 @@ -253,6 +254,7 @@ require ( github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/miekg/dns v1.1.50 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/sha256-simd v1.0.1 // indirect diff --git a/go.sum b/go.sum index 0d79b3d6b..48d48a1cd 100644 --- a/go.sum +++ b/go.sum @@ -416,6 +416,7 @@ github.com/fluxcd/pkg/testserver v0.4.0/go.mod h1:gjOKX41okmrGYOa4oOF2fiLedDAfPo github.com/fluxcd/pkg/version v0.2.2 h1:ZpVXECeLA5hIQMft11iLp6gN3cKcz6UNuVTQPw/bRdI= github.com/fluxcd/pkg/version v0.2.2/go.mod h1:NGnh/no8S6PyfCDxRFrPY3T5BUnqP48MxfxNRU0z8C0= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= +github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -860,7 +861,9 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -1259,6 +1262,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1339,6 +1343,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1365,6 +1370,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1429,6 +1435,8 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1547,6 +1555,7 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1589,6 +1598,7 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= diff --git a/internal/controller/helmchart_controller_test.go b/internal/controller/helmchart_controller_test.go index 7e94ac775..c9653435c 100644 --- a/internal/controller/helmchart_controller_test.go +++ b/internal/controller/helmchart_controller_test.go @@ -2362,6 +2362,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) { workspaceDir := t.TempDir() + tt.registryOpts.disableDNSMocking = true server, err := setupRegistryServer(ctx, workspaceDir, tt.registryOpts) g.Expect(err).NotTo(HaveOccurred()) @@ -2472,7 +2473,9 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T g := NewWithT(t) tmpDir := t.TempDir() - server, err := setupRegistryServer(ctx, tmpDir, registryOptions{}) + server, err := setupRegistryServer(ctx, tmpDir, registryOptions{ + disableDNSMocking: true, + }) g.Expect(err).ToNot(HaveOccurred()) const ( diff --git a/internal/controller/helmrepository_controller_oci_test.go b/internal/controller/helmrepository_controller_oci_test.go index b2f11ccdf..92e206bc5 100644 --- a/internal/controller/helmrepository_controller_oci_test.go +++ b/internal/controller/helmrepository_controller_oci_test.go @@ -250,6 +250,7 @@ func TestHelmRepositoryOCIReconciler_authStrategy(t *testing.T) { WithStatusSubresource(&helmv1.HelmRepository{}) workspaceDir := t.TempDir() + tt.registryOpts.disableDNSMocking = true server, err := setupRegistryServer(ctx, workspaceDir, tt.registryOpts) g.Expect(err).NotTo(HaveOccurred()) diff --git a/internal/controller/ocirepository_controller_test.go b/internal/controller/ocirepository_controller_test.go index 15a2888f9..9ce99f4e5 100644 --- a/internal/controller/ocirepository_controller_test.go +++ b/internal/controller/ocirepository_controller_test.go @@ -18,7 +18,6 @@ package controller import ( "crypto/rand" - "crypto/rsa" "crypto/tls" "crypto/x509" "crypto/x509/pkix" @@ -26,9 +25,7 @@ import ( "errors" "fmt" "math/big" - "net" "net/http" - "net/http/httptest" "net/url" "os" "path" @@ -39,7 +36,6 @@ import ( "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/registry" gcrv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/mutate" . "github.com/onsi/gomega" @@ -80,8 +76,9 @@ func TestOCIRepository_Reconcile(t *testing.T) { if err != nil { g.Expect(err).ToNot(HaveOccurred()) } + defer regServer.Close() - podinfoVersions, err := pushMultiplePodinfoImages(regServer.registryHost, "6.1.4", "6.1.5", "6.1.6") + podinfoVersions, err := pushMultiplePodinfoImages(regServer.registryHost, true, "6.1.4", "6.1.5", "6.1.6") tests := []struct { name string @@ -146,6 +143,7 @@ func TestOCIRepository_Reconcile(t *testing.T) { URL: tt.url, Interval: metav1.Duration{Duration: 60 * time.Minute}, Reference: &ociv1.OCIRepositoryRef{}, + Insecure: true, }, } obj := origObj.DeepCopy() @@ -262,8 +260,9 @@ func TestOCIRepository_Reconcile_MediaType(t *testing.T) { if err != nil { g.Expect(err).ToNot(HaveOccurred()) } + defer regServer.Close() - podinfoVersions, err := pushMultiplePodinfoImages(regServer.registryHost, "6.1.4", "6.1.5", "6.1.6") + podinfoVersions, err := pushMultiplePodinfoImages(regServer.registryHost, true, "6.1.4", "6.1.5", "6.1.6") tests := []struct { name string @@ -314,6 +313,7 @@ func TestOCIRepository_Reconcile_MediaType(t *testing.T) { LayerSelector: &ociv1.OCILayerSelector{ MediaType: tt.mediaType, }, + Insecure: true, }, } @@ -373,6 +373,7 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { craneOpts []crane.Option secretOpts secretOptions tlsCertSecret *corev1.Secret + insecure bool provider string providerImg string want sreconcile.Result @@ -380,8 +381,10 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { assertConditions []metav1.Condition }{ { - name: "HTTP without basic auth", - want: sreconcile.ResultSuccess, + name: "HTTP without basic auth", + want: sreconcile.ResultSuccess, + craneOpts: []crane.Option{crane.Insecure}, + insecure: true, assertConditions: []metav1.Condition{ *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '' for ''"), *conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '' for ''"), @@ -393,10 +396,13 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { registryOpts: registryOptions{ withBasicAuth: true, }, - craneOpts: []crane.Option{crane.WithAuth(&authn.Basic{ - Username: testRegistryUsername, - Password: testRegistryPassword, - }), + insecure: true, + craneOpts: []crane.Option{ + crane.WithAuth(&authn.Basic{ + Username: testRegistryUsername, + Password: testRegistryPassword, + }), + crane.Insecure, }, secretOpts: secretOptions{ username: testRegistryUsername, @@ -414,10 +420,13 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { registryOpts: registryOptions{ withBasicAuth: true, }, - craneOpts: []crane.Option{crane.WithAuth(&authn.Basic{ - Username: testRegistryUsername, - Password: testRegistryPassword, - }), + insecure: true, + craneOpts: []crane.Option{ + crane.WithAuth(&authn.Basic{ + Username: testRegistryUsername, + Password: testRegistryPassword, + }), + crane.Insecure, }, secretOpts: secretOptions{ username: testRegistryUsername, @@ -435,11 +444,14 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { registryOpts: registryOptions{ withBasicAuth: true, }, - wantErr: true, - craneOpts: []crane.Option{crane.WithAuth(&authn.Basic{ - Username: testRegistryUsername, - Password: testRegistryPassword, - }), + insecure: true, + wantErr: true, + craneOpts: []crane.Option{ + crane.WithAuth(&authn.Basic{ + Username: testRegistryUsername, + Password: testRegistryPassword, + }), + crane.Insecure, }, assertConditions: []metav1.Condition{ *conditions.TrueCondition(sourcev1.FetchFailedCondition, ociv1.OCIPullFailedReason, "failed to determine artifact digest"), @@ -452,10 +464,13 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { registryOpts: registryOptions{ withBasicAuth: true, }, - craneOpts: []crane.Option{crane.WithAuth(&authn.Basic{ - Username: testRegistryUsername, - Password: testRegistryPassword, - }), + insecure: true, + craneOpts: []crane.Option{ + crane.WithAuth(&authn.Basic{ + Username: testRegistryUsername, + Password: testRegistryPassword, + }), + crane.Insecure, }, secretOpts: secretOptions{ username: "wrong-pass", @@ -467,16 +482,19 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { }, }, { - name: "HTTP registry - basic auth with invalid serviceaccount", - want: sreconcile.ResultEmpty, - wantErr: true, + name: "HTTP registry - basic auth with invalid serviceaccount", + want: sreconcile.ResultEmpty, + wantErr: true, + insecure: true, registryOpts: registryOptions{ withBasicAuth: true, }, - craneOpts: []crane.Option{crane.WithAuth(&authn.Basic{ - Username: testRegistryUsername, - Password: testRegistryPassword, - }), + craneOpts: []crane.Option{ + crane.WithAuth(&authn.Basic{ + Username: testRegistryUsername, + Password: testRegistryPassword, + }), + crane.Insecure, }, secretOpts: secretOptions{ username: "wrong-pass", @@ -559,25 +577,32 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { wantErr: true, provider: "aws", providerImg: "oci://123456789000.dkr.ecr.us-east-2.amazonaws.com/test", + craneOpts: []crane.Option{ + crane.Insecure, + }, assertConditions: []metav1.Condition{ *conditions.TrueCondition(sourcev1.FetchFailedCondition, sourcev1.AuthenticationFailedReason, "failed to get credential from"), }, }, { - name: "with contextual login provider and secretRef", + name: "secretRef takes precedence over provider", want: sreconcile.ResultSuccess, registryOpts: registryOptions{ withBasicAuth: true, }, - craneOpts: []crane.Option{crane.WithAuth(&authn.Basic{ - Username: testRegistryUsername, - Password: testRegistryPassword, - })}, + craneOpts: []crane.Option{ + crane.WithAuth(&authn.Basic{ + Username: testRegistryUsername, + Password: testRegistryPassword, + }), + crane.Insecure, + }, secretOpts: secretOptions{ username: testRegistryUsername, password: testRegistryPassword, includeSecret: true, }, + insecure: true, provider: "azure", assertConditions: []metav1.Condition{ *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '' for ''"), @@ -607,8 +632,8 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { workspaceDir := t.TempDir() server, err := setupRegistryServer(ctx, workspaceDir, tt.registryOpts) - g.Expect(err).NotTo(HaveOccurred()) + defer server.Close() img, err := createPodinfoImageFromTar("podinfo-6.1.6.tar", "6.1.6", server.registryHost, tt.craneOpts...) g.Expect(err).ToNot(HaveOccurred()) @@ -664,6 +689,9 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { Name: tt.tlsCertSecret.Name, } } + if tt.insecure { + obj.Spec.Insecure = true + } r := &OCIRepositoryReconciler{ Client: clientBuilder.Build(), @@ -672,7 +700,7 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { patchOptions: getPatchOptions(ociRepositoryReadyCondition.Owned, "sc"), } - opts := craneOptions(ctx, true) + opts := craneOptions(ctx, tt.insecure) opts = append(opts, crane.WithAuthFromKeychain(authn.DefaultKeychain)) repoURL, err := r.getArtifactURL(obj, opts) g.Expect(err).To(BeNil()) @@ -706,34 +734,34 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { func TestOCIRepository_CertSecret(t *testing.T) { g := NewWithT(t) - srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err := createTLSServer() + tmpDir := t.TempDir() + regServer, err := setupRegistryServer(ctx, tmpDir, registryOptions{ + withTLS: true, + withClientCertAuth: true, + }) g.Expect(err).ToNot(HaveOccurred()) + defer regServer.Close() - srv.StartTLS() - defer srv.Close() - - transport := &http.Transport{ - TLSClientConfig: &tls.Config{}, - } - // Use the server cert as a CA cert, so the client trusts the - // server cert. (Only works because the server uses the same - // cert in both roles). pool := x509.NewCertPool() - pool.AddCert(srv.Certificate()) - transport.TLSClientConfig.RootCAs = pool - transport.TLSClientConfig.Certificates = []tls.Certificate{clientTLSCert} + pool.AppendCertsFromPEM(tlsCA) + clientTLSCert, err := tls.X509KeyPair(clientPublicKey, clientPrivateKey) + g.Expect(err).ToNot(HaveOccurred()) - srv.Client().Transport = transport - pi, err := createPodinfoImageFromTar("podinfo-6.1.5.tar", "6.1.5", srv.URL, []crane.Option{ - crane.WithTransport(srv.Client().Transport), + transport := http.DefaultTransport.(*http.Transport) + transport.TLSClientConfig = &tls.Config{ + RootCAs: pool, + Certificates: []tls.Certificate{clientTLSCert}, + } + pi, err := createPodinfoImageFromTar("podinfo-6.1.5.tar", "6.1.5", regServer.registryHost, []crane.Option{ + crane.WithTransport(transport), }...) g.Expect(err).NotTo(HaveOccurred()) tlsSecretClientCert := corev1.Secret{ - StringData: map[string]string{ - oci.CACert: string(rootCertPEM), - oci.ClientCert: string(clientCertPEM), - oci.ClientKey: string(clientKeyPEM), + Data: map[string][]byte{ + oci.CACert: tlsCA, + oci.ClientCert: clientPublicKey, + oci.ClientKey: clientPrivateKey, }, } @@ -758,17 +786,17 @@ func TestOCIRepository_CertSecret(t *testing.T) { url: pi.url, digest: pi.digest, expectreadyconition: false, - expectedstatusmessage: "unexpected status code 400 Bad Request: Client sent an HTTP request to an HTTPS server", + expectedstatusmessage: "tls: failed to verify certificate: x509:", }, { name: "test connection with with incorrect private key", url: pi.url, digest: pi.digest, certSecret: &corev1.Secret{ - StringData: map[string]string{ - oci.CACert: string(rootCertPEM), - oci.ClientCert: string(clientCertPEM), - oci.ClientKey: string("invalid-key"), + Data: map[string][]byte{ + oci.CACert: tlsCA, + oci.ClientCert: clientPublicKey, + oci.ClientKey: []byte("invalid-key"), }, }, expectreadyconition: false, @@ -859,8 +887,9 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) { tmpDir := t.TempDir() server, err := setupRegistryServer(ctx, tmpDir, registryOptions{}) g.Expect(err).ToNot(HaveOccurred()) + defer server.Close() - podinfoVersions, err := pushMultiplePodinfoImages(server.registryHost, "6.1.4", "6.1.5", "6.1.6") + podinfoVersions, err := pushMultiplePodinfoImages(server.registryHost, true, "6.1.4", "6.1.5", "6.1.6") img6 := podinfoVersions["6.1.6"] img5 := podinfoVersions["6.1.5"] @@ -1001,6 +1030,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) { URL: fmt.Sprintf("oci://%s/podinfo", server.registryHost), Interval: metav1.Duration{Duration: interval}, Timeout: &metav1.Duration{Duration: timeout}, + Insecure: true, }, } @@ -1034,26 +1064,16 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) { func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { g := NewWithT(t) - tmpDir := t.TempDir() - server, err := setupRegistryServer(ctx, tmpDir, registryOptions{}) - g.Expect(err).ToNot(HaveOccurred()) - - podinfoVersions, err := pushMultiplePodinfoImages(server.registryHost, "6.1.4", "6.1.5") - g.Expect(err).ToNot(HaveOccurred()) - img4 := podinfoVersions["6.1.4"] - img5 := podinfoVersions["6.1.5"] - tests := []struct { name string reference *ociv1.OCIRepositoryRef insecure bool - digest string want sreconcile.Result wantErr bool wantErrMsg string shouldSign bool keyless bool - beforeFunc func(obj *ociv1.OCIRepository) + beforeFunc func(obj *ociv1.OCIRepository, tag, revision string) assertConditions []metav1.Condition }{ { @@ -1061,7 +1081,6 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { reference: &ociv1.OCIRepositoryRef{ Tag: "6.1.4", }, - digest: img4.digest.String(), shouldSign: true, want: sreconcile.ResultSuccess, assertConditions: []metav1.Condition{ @@ -1075,7 +1094,6 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { reference: &ociv1.OCIRepositoryRef{ Tag: "6.1.5", }, - digest: img5.digest.String(), wantErr: true, wantErrMsg: "failed to verify the signature using provider 'cosign': no matching signatures were found for ''", want: sreconcile.ResultEmpty, @@ -1090,7 +1108,6 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { reference: &ociv1.OCIRepositoryRef{ Tag: "6.1.5", }, - digest: img5.digest.String(), wantErr: true, want: sreconcile.ResultEmpty, keyless: true, @@ -1103,21 +1120,19 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { { name: "verify failed before, removed from spec, remove condition", reference: &ociv1.OCIRepositoryRef{Tag: "6.1.4"}, - digest: img4.digest.String(), - beforeFunc: func(obj *ociv1.OCIRepository) { + beforeFunc: func(obj *ociv1.OCIRepository, tag, revision string) { conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, "VerifyFailed", "fail msg") obj.Spec.Verify = nil - obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", img4.tag, img4.digest.String())} + obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", tag, revision)} }, want: sreconcile.ResultSuccess, }, { name: "same artifact, verified before, change in obj gen verify again", reference: &ociv1.OCIRepositoryRef{Tag: "6.1.4"}, - digest: img4.digest.String(), shouldSign: true, - beforeFunc: func(obj *ociv1.OCIRepository) { - obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", img4.tag, img4.digest.String())} + beforeFunc: func(obj *ociv1.OCIRepository, tag, revision string) { + obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", tag, revision)} // Set Verified with old observed generation and different reason/message. conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified") // Set new object generation. @@ -1131,11 +1146,10 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { { name: "no verify for already verified, verified condition remains the same", reference: &ociv1.OCIRepositoryRef{Tag: "6.1.4"}, - digest: img4.digest.String(), shouldSign: true, - beforeFunc: func(obj *ociv1.OCIRepository) { + beforeFunc: func(obj *ociv1.OCIRepository, tag, revision string) { // Artifact present and custom verified condition reason/message. - obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", img4.tag, img4.digest.String())} + obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", tag, revision)} conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified") }, want: sreconcile.ResultSuccess, @@ -1144,19 +1158,17 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { }, }, { - name: "insecure registries are not supported", + name: "signed image on an insecure registry passes verification", reference: &ociv1.OCIRepositoryRef{ - Tag: "6.1.4", + Tag: "6.1.6", }, - digest: img4.digest.String(), shouldSign: true, insecure: true, - wantErr: true, - want: sreconcile.ResultEmpty, + want: sreconcile.ResultSuccess, assertConditions: []metav1.Condition{ *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '' for ''"), *conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '' for ''"), - *conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "cosign does not support insecure registries"), + *conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of revision "), }, }, } @@ -1179,6 +1191,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { keys, err := cosign.GenerateKeyPair(pf) g.Expect(err).ToNot(HaveOccurred()) + tmpDir := t.TempDir() err = os.WriteFile(path.Join(tmpDir, "cosign.key"), keys.PrivateBytes, 0600) g.Expect(err).ToNot(HaveOccurred()) @@ -1190,15 +1203,32 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { "cosign.pub": keys.PublicBytes, }} - err = r.Create(ctx, secret) - if err != nil { - g.Expect(err).NotTo(HaveOccurred()) + g.Expect(r.Create(ctx, secret)).NotTo(HaveOccurred()) + + caSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ca-cert-cosign", + Generation: 1, + }, + Data: map[string][]byte{ + "caFile": tlsCA, + }, } + g.Expect(r.Create(ctx, caSecret)).ToNot(HaveOccurred()) + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) + workspaceDir := t.TempDir() + regOpts := registryOptions{ + withTLS: !tt.insecure, + } + server, err := setupRegistryServer(ctx, workspaceDir, regOpts) + g.Expect(err).NotTo(HaveOccurred()) + defer server.Close() + obj := &ociv1.OCIRepository{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "verify-oci-source-signature-", @@ -1216,6 +1246,10 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { if tt.insecure { obj.Spec.Insecure = true + } else { + obj.Spec.CertSecretRef = &meta.LocalObjectReference{ + Name: "ca-cert-cosign", + } } if !tt.keyless { @@ -1226,12 +1260,15 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { obj.Spec.Reference = tt.reference } + podinfoVersions, err := pushMultiplePodinfoImages(server.registryHost, tt.insecure, tt.reference.Tag) + g.Expect(err).ToNot(HaveOccurred()) + keychain, err := r.keychain(ctx, obj) if err != nil { g.Expect(err).ToNot(HaveOccurred()) } - opts := craneOptions(ctx, true) + opts := craneOptions(ctx, false) opts = append(opts, crane.WithAuthFromKeychain(keychain)) artifactURL, err := r.getArtifactURL(obj, opts) g.Expect(err).ToNot(HaveOccurred()) @@ -1250,21 +1287,22 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) { SkipConfirmation: true, TlogUpload: false, - Registry: coptions.RegistryOptions{Keychain: keychain, AllowInsecure: true}, + Registry: coptions.RegistryOptions{Keychain: keychain, AllowInsecure: true, AllowHTTPRegistry: tt.insecure}, }, []string{artifactURL}) g.Expect(err).ToNot(HaveOccurred()) } + image := podinfoVersions[tt.reference.Tag] assertConditions := tt.assertConditions for k := range assertConditions { - assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "", fmt.Sprintf("%s@%s", tt.reference.Tag, tt.digest)) + assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "", fmt.Sprintf("%s@%s", tt.reference.Tag, image.digest.String())) assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "", artifactURL) assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "", "cosign") } if tt.beforeFunc != nil { - tt.beforeFunc(obj) + tt.beforeFunc(obj, image.tag, image.digest.String()) } g.Expect(r.Client.Create(ctx, obj)).ToNot(HaveOccurred()) @@ -1298,7 +1336,7 @@ func TestOCIRepository_reconcileSource_noop(t *testing.T) { server, err := setupRegistryServer(ctx, tmpDir, registryOptions{}) g.Expect(err).ToNot(HaveOccurred()) - _, err = pushMultiplePodinfoImages(server.registryHost, "6.1.5") + _, err = pushMultiplePodinfoImages(server.registryHost, true, "6.1.5") g.Expect(err).ToNot(HaveOccurred()) // NOTE: The following verifies if it was a noop run by checking the @@ -1431,6 +1469,7 @@ func TestOCIRepository_reconcileSource_noop(t *testing.T) { Reference: &ociv1.OCIRepositoryRef{Tag: "6.1.5"}, Interval: metav1.Duration{Duration: interval}, Timeout: &metav1.Duration{Duration: timeout}, + Insecure: true, }, } @@ -1711,7 +1750,7 @@ func TestOCIRepository_getArtifactURL(t *testing.T) { server, err := setupRegistryServer(ctx, tmpDir, registryOptions{}) g.Expect(err).ToNot(HaveOccurred()) - imgs, err := pushMultiplePodinfoImages(server.registryHost, "6.1.4", "6.1.5", "6.1.6") + imgs, err := pushMultiplePodinfoImages(server.registryHost, true, "6.1.4", "6.1.5", "6.1.6") g.Expect(err).ToNot(HaveOccurred()) tests := []struct { @@ -1778,6 +1817,7 @@ func TestOCIRepository_getArtifactURL(t *testing.T) { URL: tt.url, Interval: metav1.Duration{Duration: interval}, Timeout: &metav1.Duration{Duration: timeout}, + Insecure: true, }, } @@ -2299,11 +2339,25 @@ func createPodinfoImageFromTar(tarFileName, tag, registryURL string, opts ...cra }, nil } -func pushMultiplePodinfoImages(serverURL string, versions ...string) (map[string]podinfoImage, error) { +func pushMultiplePodinfoImages(serverURL string, insecure bool, versions ...string) (map[string]podinfoImage, error) { podinfoVersions := make(map[string]podinfoImage) + var opts []crane.Option + // If the registry is insecure then instruct configure an insecure HTTP client, + // otherwise add the root CA certificate since the HTTPS server is self signed. + if insecure { + opts = append(opts, crane.Insecure) + } else { + transport := http.DefaultTransport.(*http.Transport) + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(tlsCA) + transport.TLSClientConfig = &tls.Config{ + RootCAs: pool, + } + opts = append(opts, crane.WithTransport(transport)) + } for i := 0; i < len(versions); i++ { - pi, err := createPodinfoImageFromTar(fmt.Sprintf("podinfo-%s.tar", versions[i]), versions[i], serverURL) + pi, err := createPodinfoImageFromTar(fmt.Sprintf("podinfo-%s.tar", versions[i]), versions[i], serverURL, opts...) if err != nil { return nil, err } @@ -2362,75 +2416,6 @@ func createCert(template, parent *x509.Certificate, pub interface{}, parentPriv return } -func createTLSServer() (*httptest.Server, []byte, []byte, []byte, tls.Certificate, error) { - var clientTLSCert tls.Certificate - var rootCertPEM, clientCertPEM, clientKeyPEM []byte - - srv := httptest.NewUnstartedServer(registry.New()) - - // Create a self-signed cert to use as the CA and server cert. - rootKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - rootCertTmpl, err := certTemplate() - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - rootCertTmpl.IsCA = true - rootCertTmpl.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature - rootCertTmpl.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth} - rootCertTmpl.IPAddresses = []net.IP{net.ParseIP("127.0.0.1")} - var rootCert *x509.Certificate - rootCert, rootCertPEM, err = createCert(rootCertTmpl, rootCertTmpl, &rootKey.PublicKey, rootKey) - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - - rootKeyPEM := pem.EncodeToMemory(&pem.Block{ - Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rootKey), - }) - - // Create a TLS cert using the private key and certificate. - rootTLSCert, err := tls.X509KeyPair(rootCertPEM, rootKeyPEM) - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - - // To trust a client certificate, the server must be given a - // CA cert pool. - pool := x509.NewCertPool() - pool.AddCert(rootCert) - - srv.TLS = &tls.Config{ - ClientAuth: tls.RequireAndVerifyClientCert, - Certificates: []tls.Certificate{rootTLSCert}, - ClientCAs: pool, - } - - // Create a client cert, signed by the "CA". - clientKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - clientCertTmpl, err := certTemplate() - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - clientCertTmpl.KeyUsage = x509.KeyUsageDigitalSignature - clientCertTmpl.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} - _, clientCertPEM, err = createCert(clientCertTmpl, rootCert, &clientKey.PublicKey, rootKey) - if err != nil { - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err - } - // Encode and load the cert and private key for the client. - clientKeyPEM = pem.EncodeToMemory(&pem.Block{ - Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(clientKey), - }) - clientTLSCert, err = tls.X509KeyPair(clientCertPEM, clientKeyPEM) - return srv, rootCertPEM, clientCertPEM, clientKeyPEM, clientTLSCert, err -} - func TestOCIContentConfigChanged(t *testing.T) { tests := []struct { name string diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 2602e5545..e9434f20f 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -21,12 +21,16 @@ import ( "context" "fmt" "io" + "io/ioutil" + "log" "math/rand" + "net" "os" "path/filepath" "testing" "time" + "github.com/foxcpp/go-mockdns" "github.com/phayes/freeport" "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" @@ -95,9 +99,11 @@ var ( ) var ( - tlsPublicKey []byte - tlsPrivateKey []byte - tlsCA []byte + tlsPublicKey []byte + tlsPrivateKey []byte + tlsCA []byte + clientPublicKey []byte + clientPrivateKey []byte ) var ( @@ -114,11 +120,18 @@ type registryClientTestServer struct { registryHost string workspaceDir string registryClient *helmreg.Client + dnsServer *mockdns.Server } type registryOptions struct { - withBasicAuth bool - withTLS bool + withBasicAuth bool + withTLS bool + withClientCertAuth bool + // Allow disbaling DNS mocking since Helm OCI doesn't yet suppot + // insecure OCI registries, which means we need Docker's automatic + // connection downgrading if the registry is hosted on localhost. + // Once Helm OCI supports insecure registries, we can get rid of this. + disableDNSMocking bool } func setupRegistryServer(ctx context.Context, workspaceDir string, opts registryOptions) (*registryClientTestServer, error) { @@ -150,7 +163,28 @@ func setupRegistryServer(ctx context.Context, workspaceDir string, opts registry } server.registryHost = fmt.Sprintf("localhost:%d", port) - config.HTTP.Addr = fmt.Sprintf("127.0.0.1:%d", port) + + // Change the registry host to a host which is not localhost and + // mock DNS to map example.com to 127.0.0.1. + // This is required because Docker enforces HTTP if the registry + // is hosted on localhost/127.0.0.1. + if !opts.disableDNSMocking { + server.registryHost = fmt.Sprintf("example.com:%d", port) + // Disable DNS server logging as it is extremely chatty. + dnsLog := log.Default() + dnsLog.SetOutput(ioutil.Discard) + server.dnsServer, err = mockdns.NewServerWithLogger(map[string]mockdns.Zone{ + "example.com.": { + A: []string{"127.0.0.1"}, + }, + }, dnsLog, false) + if err != nil { + return nil, err + } + server.dnsServer.PatchNet(net.DefaultResolver) + } + + config.HTTP.Addr = fmt.Sprintf(":%d", port) config.HTTP.DrainTimeout = time.Duration(10) * time.Second config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} @@ -178,6 +212,10 @@ func setupRegistryServer(ctx context.Context, workspaceDir string, opts registry if opts.withTLS { config.HTTP.TLS.Certificate = "testdata/certs/server.pem" config.HTTP.TLS.Key = "testdata/certs/server-key.pem" + // Configure CA certificates only if client cert authentication is enabled. + if opts.withClientCertAuth { + config.HTTP.TLS.ClientCAs = []string{"testdata/certs/ca.pem"} + } } // setup logger options @@ -198,6 +236,13 @@ func setupRegistryServer(ctx context.Context, workspaceDir string, opts registry return server, nil } +func (r *registryClientTestServer) Close() { + if r.dnsServer != nil { + mockdns.UnpatchNet(net.DefaultResolver) + r.dnsServer.Close() + } +} + func TestMain(m *testing.M) { initTestTLS() @@ -229,11 +274,13 @@ func TestMain(m *testing.M) { panic(fmt.Sprintf("failed to create workspace directory: %v", err)) } testRegistryServer, err = setupRegistryServer(ctx, testWorkspaceDir, registryOptions{ - withBasicAuth: true, + withBasicAuth: true, + disableDNSMocking: true, }) if err != nil { panic(fmt.Sprintf("Failed to create a test registry server: %v", err)) } + defer testRegistryServer.Close() if err := (&GitRepositoryReconciler{ Client: testEnv, @@ -355,6 +402,14 @@ func initTestTLS() { if err != nil { panic(err) } + clientPrivateKey, err = os.ReadFile("testdata/certs/client-key.pem") + if err != nil { + panic(err) + } + clientPublicKey, err = os.ReadFile("testdata/certs/client.pem") + if err != nil { + panic(err) + } } func newTestStorage(s *testserver.HTTPServer) (*Storage, error) { diff --git a/internal/controller/testdata/certs/Makefile b/internal/controller/testdata/certs/Makefile index dca2408c3..22b40466b 100644 --- a/internal/controller/testdata/certs/Makefile +++ b/internal/controller/testdata/certs/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -all: server-key.pem +all: server-key.pem client-key.pem ca-key.pem: ca-csr.json cfssl gencert -initca ca-csr.json | cfssljson -bare ca – @@ -28,3 +28,13 @@ server-key.pem: server-csr.json ca-config.json ca-key.pem server-csr.json | cfssljson -bare server sever.pem: server-key.pem server.csr: server-key.pem + +client-key.pem: client-csr.json ca-config.json ca-key.pem + cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -profile=web-servers \ + client-csr.json | cfssljson -bare client +client.pem: client-key.pem +client.csr: client-key.pem diff --git a/internal/controller/testdata/certs/client-csr.json b/internal/controller/testdata/certs/client-csr.json new file mode 100644 index 000000000..0baf11601 --- /dev/null +++ b/internal/controller/testdata/certs/client-csr.json @@ -0,0 +1,9 @@ +{ + "CN": "example.com", + "hosts": [ + "127.0.0.1", + "localhost", + "example.com", + "www.example.com" + ] +} diff --git a/internal/controller/testdata/certs/client-key.pem b/internal/controller/testdata/certs/client-key.pem new file mode 100644 index 000000000..b39c483d0 --- /dev/null +++ b/internal/controller/testdata/certs/client-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICpqb1p1TH98yoFXEEt6JmWc/Snb8NaYyz8jfTOVDBLOoAoGCCqGSM49 +AwEHoUQDQgAERjzob4CCuyv+cYPyTYCPHwGuqSNGNuX3UGWpxvzwEqjYEWiePlOz +eJLk4DWaVX8CmVakNLsK/EHnBv9ErG7QYQ== +-----END EC PRIVATE KEY----- diff --git a/internal/controller/testdata/certs/client.csr b/internal/controller/testdata/certs/client.csr new file mode 100644 index 000000000..41f498804 --- /dev/null +++ b/internal/controller/testdata/certs/client.csr @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBHDCBwwIBADAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABEY86G+Agrsr/nGD8k2Ajx8BrqkjRjbl91Blqcb88BKo2BFo +nj5Ts3iS5OA1mlV/AplWpDS7CvxB5wb/RKxu0GGgSzBJBgkqhkiG9w0BCQ4xPDA6 +MDgGA1UdEQQxMC+CCWxvY2FsaG9zdIILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxl +LmNvbYcEfwAAATAKBggqhkjOPQQDAgNIADBFAiAHmtr9fDDx5eyFfY7r5m8xA4Wh +Jm+TB6/czvXRNNOKzAIhAN7ln6BpneEm2oqIBGqvfc3pETC6jdGJxCfYw+X+7von +-----END CERTIFICATE REQUEST----- diff --git a/internal/controller/testdata/certs/client.pem b/internal/controller/testdata/certs/client.pem new file mode 100644 index 000000000..4a85663ea --- /dev/null +++ b/internal/controller/testdata/certs/client.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB7DCCAZKgAwIBAgIUPJmKtZ6CfSxybx2BSsVS5EVun0swCgYIKoZIzj0EAwIw +GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjMwNzE5MTExMzAwWhcNMzMw +NzE2MTExMzAwWjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABEY86G+Agrsr/nGD8k2Ajx8BrqkjRjbl91Blqcb88BKo2BFo +nj5Ts3iS5OA1mlV/AplWpDS7CvxB5wb/RKxu0GGjgbowgbcwDgYDVR0PAQH/BAQD +AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA +MB0GA1UdDgQWBBTgAyCQoH/EJqz/nY5DJa/uvWWshzAfBgNVHSMEGDAWgBQGyUiU +1QEZiMAqjsnIYTwZ4yp5wzA4BgNVHREEMTAvgglsb2NhbGhvc3SCC2V4YW1wbGUu +Y29tgg93d3cuZXhhbXBsZS5jb22HBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgKSJH +YvhKiXcUUzRoL6FsXQeAlhemSg3lD9se+BhRF8ECIQDx2UpWFLDe5NOPqhrcR1Sd +haFriAG8eR1yD3u3nJvY6g== +-----END CERTIFICATE-----