diff --git a/api/secrets/models/update_externaldns_tls.go b/api/secrets/models/update_externaldns_tls.go index 12bea409..52fdac45 100644 --- a/api/secrets/models/update_externaldns_tls.go +++ b/api/secrets/models/update_externaldns_tls.go @@ -12,4 +12,9 @@ type UpdateExternalDNSTLSRequest struct { // // required: true Certificate string `json:"certificate"` + + // Skip validation of certificate and private key + // + // required: false + SkipValidation bool `json:"skipValidation"` } diff --git a/api/secrets/secret_controller.go b/api/secrets/secret_controller.go index b881c529..0f6d0bd7 100644 --- a/api/secrets/secret_controller.go +++ b/api/secrets/secret_controller.go @@ -274,7 +274,7 @@ func (c *secretController) UpdateComponentExternalDNSTLS(accounts models.Account handler := c.getSecretHandler(accounts) - if err := handler.UpdateComponentExternalDNSSecretData(r.Context(), appName, envName, componentName, fqdn, requestBody.Certificate, requestBody.PrivateKey); err != nil { + if err := handler.UpdateComponentExternalDNSSecretData(r.Context(), appName, envName, componentName, fqdn, requestBody.Certificate, requestBody.PrivateKey, requestBody.SkipValidation); err != nil { c.ErrorResponse(w, r, err) return } diff --git a/api/secrets/secret_controller_test.go b/api/secrets/secret_controller_test.go index 2324b5d5..6465bc51 100644 --- a/api/secrets/secret_controller_test.go +++ b/api/secrets/secret_controller_test.go @@ -327,6 +327,24 @@ func (s *externalDNSSecretTestSuite) Test_UpdateSuccess() { s.Equal(expectedSecretData, secret.Data) } +func (s *externalDNSSecretTestSuite) Test_SkipValidationDoesNotCallValidator() { + appName, envName, componentName, fqdn := "app", "env", "comp", "my.example.com" + privateKey, cert := "any private key", "any certificate" + ns := operatorutils.GetEnvironmentNamespace(appName, envName) + s.Require().NoError(s.setupTestResources(appName, envName, componentName, []radixv1.RadixDeployExternalDNS{{FQDN: fqdn}}, radixv1.DeploymentActive)) + s.Require().NoError(s.setupSecretForExternalDNS(ns, fqdn, nil, nil)) + + response := s.executeRequest(appName, envName, componentName, fqdn, &secretModels.UpdateExternalDNSTLSRequest{PrivateKey: privateKey, Certificate: cert, SkipValidation: true}) + s.Equal(200, response.Code) + expectedSecretData := map[string][]byte{ + corev1.TLSCertKey: []byte(cert), + corev1.TLSPrivateKeyKey: []byte(privateKey), + } + secret, err := s.kubeClient.CoreV1().Secrets(ns).Get(context.Background(), fqdn, metav1.GetOptions{}) + s.Require().NoError(err) + s.Equal(expectedSecretData, secret.Data) +} + func (s *externalDNSSecretTestSuite) Test_RadixDeploymentNotActive() { appName, envName, componentName, fqdn := "app", "env", "comp", "my.example.com" privateKey, cert := "any private key", "any certificate" diff --git a/api/secrets/secret_handler.go b/api/secrets/secret_handler.go index bd4835de..e7b05b78 100644 --- a/api/secrets/secret_handler.go +++ b/api/secrets/secret_handler.go @@ -139,7 +139,7 @@ func (eh *SecretHandler) ChangeComponentSecret(ctx context.Context, appName, env return eh.setSecretKeyValue(ctx, ns, secretObjName, map[string][]byte{partName: []byte(newSecretValue)}) } -func (eh *SecretHandler) UpdateComponentExternalDNSSecretData(ctx context.Context, appName, envName, componentName, fqdn string, certificate, privateKey string) error { +func (eh *SecretHandler) UpdateComponentExternalDNSSecretData(ctx context.Context, appName, envName, componentName, fqdn string, certificate, privateKey string, skipValidation bool) error { rdList, err := kubequery.GetRadixDeploymentsForEnvironment(ctx, eh.userAccount.RadixClient, appName, envName) if err != nil { return radixhttp.UnexpectedError("Failed to get deployments", err) @@ -165,10 +165,13 @@ func (eh *SecretHandler) UpdateComponentExternalDNSSecretData(ctx context.Contex } certificateBytes, privateKeyBytes := []byte(certificate), []byte(privateKey) - tlsValidator := eh.getTLSValidatorOrDefault() - if valid, validationMsgs := tlsValidator.ValidateX509Certificate(certificateBytes, privateKeyBytes, fqdn); !valid { - return radixhttp.ValidationError("TLS", strings.Join(validationMsgs, ", ")) + if !skipValidation { + tlsValidator := eh.getTLSValidatorOrDefault() + + if valid, validationMsgs := tlsValidator.ValidateX509Certificate(certificateBytes, privateKeyBytes, fqdn); !valid { + return radixhttp.ValidationError("TLS", strings.Join(validationMsgs, ", ")) + } } ns := operatorutils.GetEnvironmentNamespace(appName, envName) diff --git a/go.mod b/go.mod index 63491c9c..c4bd1768 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/equinor/radix-api go 1.21 require ( - github.com/equinor/radix-common v1.7.1 + github.com/equinor/radix-common v1.8.0 github.com/equinor/radix-job-scheduler v1.8.5 github.com/equinor/radix-operator v1.47.6-0.20240102073852-648f9e23dec0 github.com/evanphx/json-patch/v5 v5.7.0 @@ -41,6 +41,7 @@ require ( github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/elnormous/contenttype v1.0.4 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/go.sum b/go.sum index ea670fc5..f2ecc3a0 100644 --- a/go.sum +++ b/go.sum @@ -73,14 +73,16 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elnormous/contenttype v1.0.4 h1:FjmVNkvQOGqSX70yvocph7keC8DtmJaLzTTq6ZOQCI8= +github.com/elnormous/contenttype v1.0.4/go.mod h1:5KTOW8m1kdX1dLMiUJeN9szzR2xkngiv2K+RVZwWBbI= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/equinor/radix-common v1.7.1 h1:kl7Tuo2VEo2WHGm/vkvktrZ9t9S3Nht7Mob3CSIzcJI= -github.com/equinor/radix-common v1.7.1/go.mod h1:M6mhgHtFQ3rnjJnyOuECXiZOh7XQ5xVeHMyCAU+YPzQ= +github.com/equinor/radix-common v1.8.0 h1:4mMu36mvJi2QSPEiKOUUJG/Z5EUrPkf0/lRO1qzkt5c= +github.com/equinor/radix-common v1.8.0/go.mod h1:8wGBEAa6auVB3yQ5pImahQzrL3w1ZYTu6N7EXLpJKUk= github.com/equinor/radix-job-scheduler v1.8.5 h1:ahw6FkFpPV167B1/w7/aQKpVMmU5Vc7UBO8411ZtYck= github.com/equinor/radix-job-scheduler v1.8.5/go.mod h1:rNIQU1eCInLV8Yl+5SRITOUU52QwYioYrIGQcsDc3kg= github.com/equinor/radix-operator v1.47.6-0.20240102073852-648f9e23dec0 h1:GbGRsmGmDwwoZre8cF55pid4NgC9DJECENHAlDsYyrE= diff --git a/swaggerui/html/swagger.json b/swaggerui/html/swagger.json index 631855e7..5a747134 100644 --- a/swaggerui/html/swagger.json +++ b/swaggerui/html/swagger.json @@ -7537,6 +7537,11 @@ "description": "Private key in PEM format", "type": "string", "x-go-name": "PrivateKey" + }, + "skipValidation": { + "description": "Skip validation of certificate and private key", + "type": "boolean", + "x-go-name": "SkipValidation" } }, "x-go-name": "UpdateExternalDNSTLSRequest",