From bf36a29ca2c91f9e61b6b0f11f61f752f37e61dc Mon Sep 17 00:00:00 2001 From: Sanskar Jaiswal Date: Wed, 9 Aug 2023 17:10:45 +0530 Subject: [PATCH 1/5] add support for Kubernetes TLS keys for `flux create secret tls` Add support for using `tls.key`, `tls.crt` and `ca.crt` keys while generating a Secret, using the `--tls-key-file`, `--tls-crt-file` and `--ca-crt-file` flags respectively. Mark the flags `--key-file`, `--cert-file` and `--ca-file` as deprecated. Signed-off-by: Sanskar Jaiswal --- cmd/flux/create_secret_tls.go | 67 +++++++---- cmd/flux/create_secret_tls_test.go | 8 +- .../tls/deprecated-secret-tls.yaml | 107 ++++++++++++++++++ .../create_secret/tls/secret-tls.yaml | 16 ++- .../testdata/create_secret/tls/test-ca.pem | 11 ++ pkg/manifestgen/sourcesecret/options.go | 24 +++- pkg/manifestgen/sourcesecret/sourcesecret.go | 19 ++-- 7 files changed, 213 insertions(+), 39 deletions(-) create mode 100644 cmd/flux/testdata/create_secret/tls/deprecated-secret-tls.yaml create mode 100644 cmd/flux/testdata/create_secret/tls/test-ca.pem diff --git a/cmd/flux/create_secret_tls.go b/cmd/flux/create_secret_tls.go index ffe756512b..b244a6c5f8 100644 --- a/cmd/flux/create_secret_tls.go +++ b/cmd/flux/create_secret_tls.go @@ -38,8 +38,9 @@ var createSecretTLSCmd = &cobra.Command{ # Files are expected to be PEM-encoded. flux create secret tls certs \ --namespace=my-namespace \ - --cert-file=./client.crt \ - --key-file=./client.key \ + --tls-crt-file=./client.crt \ + --tls-key-file=./client.key \ + --ca-crt-file=./ca.crt \ --export > certs.yaml sops --encrypt --encrypted-regex '^(data|stringData)$' \ @@ -48,22 +49,37 @@ var createSecretTLSCmd = &cobra.Command{ } type secretTLSFlags struct { - certFile string - keyFile string - caFile string + certFile string + keyFile string + caFile string + caCrtFile string + tlsKeyFile string + tlsCrtFile string } var secretTLSArgs secretTLSFlags -func initSecretTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) { +func initSecretDeprecatedTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) { flags.StringVar(&args.certFile, "cert-file", "", "TLS authentication cert file path") flags.StringVar(&args.keyFile, "key-file", "", "TLS authentication key file path") flags.StringVar(&args.caFile, "ca-file", "", "TLS authentication CA file path") } +func initSecretTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) { + flags.StringVar(&args.tlsCrtFile, "tls-crt-file", "", "TLS authentication cert file path") + flags.StringVar(&args.tlsKeyFile, "tls-key-file", "", "TLS authentication key file path") + flags.StringVar(&args.caCrtFile, "ca-crt-file", "", "TLS authentication CA file path") +} + func init() { flags := createSecretTLSCmd.Flags() + initSecretDeprecatedTLSFlags(flags, &secretTLSArgs) initSecretTLSFlags(flags, &secretTLSArgs) + + flags.MarkDeprecated("cert-file", "please use --tls-crt-file instead") + flags.MarkDeprecated("key-file", "please use --tls-key-file instead") + flags.MarkDeprecated("ca-file", "please use --ca-crt-file instead") + createSecretCmd.AddCommand(createSecretTLSCmd) } @@ -75,33 +91,40 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error { return err } - caBundle := []byte{} - if secretTLSArgs.caFile != "" { - var err error - caBundle, err = os.ReadFile(secretTLSArgs.caFile) + opts := sourcesecret.Options{ + Name: name, + Namespace: *kubeconfigArgs.Namespace, + Labels: labels, + } + + if secretTLSArgs.caCrtFile != "" { + opts.CACrt, err = os.ReadFile(secretTLSArgs.caCrtFile) + if err != nil { + return fmt.Errorf("unable to read TLS CA file: %w", err) + } + } else if secretTLSArgs.caFile != "" { + opts.CAFile, err = os.ReadFile(secretTLSArgs.caFile) if err != nil { return fmt.Errorf("unable to read TLS CA file: %w", err) } } - var certFile, keyFile []byte - if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" { - if certFile, err = os.ReadFile(secretTLSArgs.certFile); err != nil { + if secretTLSArgs.tlsCrtFile != "" && secretTLSArgs.tlsKeyFile != "" { + if opts.TlsCrt, err = os.ReadFile(secretTLSArgs.tlsCrtFile); err != nil { + return fmt.Errorf("failed to read cert file: %w", err) + } + if opts.TlsKey, err = os.ReadFile(secretTLSArgs.tlsKeyFile); err != nil { + return fmt.Errorf("failed to read key file: %w", err) + } + } else if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" { + if opts.CertFile, err = os.ReadFile(secretTLSArgs.certFile); err != nil { return fmt.Errorf("failed to read cert file: %w", err) } - if keyFile, err = os.ReadFile(secretTLSArgs.keyFile); err != nil { + if opts.KeyFile, err = os.ReadFile(secretTLSArgs.keyFile); err != nil { return fmt.Errorf("failed to read key file: %w", err) } } - opts := sourcesecret.Options{ - Name: name, - Namespace: *kubeconfigArgs.Namespace, - Labels: labels, - CAFile: caBundle, - CertFile: certFile, - KeyFile: keyFile, - } secret, err := sourcesecret.Generate(opts) if err != nil { return err diff --git a/cmd/flux/create_secret_tls_test.go b/cmd/flux/create_secret_tls_test.go index 31d4920046..226ed8e3c3 100644 --- a/cmd/flux/create_secret_tls_test.go +++ b/cmd/flux/create_secret_tls_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -func TestCreateTlsSecretNoArgs(t *testing.T) { +func TestCreateTlsSecret(t *testing.T) { tests := []struct { name string args string @@ -15,9 +15,13 @@ func TestCreateTlsSecretNoArgs(t *testing.T) { assert: assertError("name is required"), }, { - args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --export", + args: "create secret tls certs --namespace=my-namespace --tls-crt-file=./testdata/create_secret/tls/test-cert.pem --tls-key-file=./testdata/create_secret/tls/test-key.pem --ca-crt-file=./testdata/create_secret/tls/test-ca.pem --export", assert: assertGoldenFile("testdata/create_secret/tls/secret-tls.yaml"), }, + { + args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --ca-file=./testdata/create_secret/tls/test-ca.pem --export", + assert: assertGoldenFile("testdata/create_secret/tls/deprecated-secret-tls.yaml"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/cmd/flux/testdata/create_secret/tls/deprecated-secret-tls.yaml b/cmd/flux/testdata/create_secret/tls/deprecated-secret-tls.yaml new file mode 100644 index 0000000000..04e01d63ba --- /dev/null +++ b/cmd/flux/testdata/create_secret/tls/deprecated-secret-tls.yaml @@ -0,0 +1,107 @@ +Flag --cert-file has been deprecated, please use --tls-crt-file instead +Flag --key-file has been deprecated, please use --tls-key-file instead +Flag --ca-file has been deprecated, please use --ca-crt-file instead +--- +apiVersion: v1 +kind: Secret +metadata: + name: certs + namespace: my-namespace +stringData: + caFile: | + -----BEGIN CERTIFICATE----- + MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw + GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw + NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49 + AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr + RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE + AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ + 4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O + 1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb + OD8EjjCMY69RMO0= + -----END CERTIFICATE----- + certFile: | + -----BEGIN CERTIFICATE----- + MIIFazCCA1OgAwIBAgIUT84jeO/ncOrqI+FY05Fzbg8Ed7MwDQYJKoZIhvcNAQEL + BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM + GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA4MDgxNDQyMzVaFw0yMjA4 + MDgxNDQyMzVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw + HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB + AQUAA4ICDwAwggIKAoICAQDn/rPsZ74oypiwCzLlx57zplTiCi/WLSF+MmLGuTvM + EQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgSj4YKULCMwwOl45hQPdCTEPJvUhCm + M+FuQ0czmEEJSjZtdLFz1B7QB/JemNnbfigxM9mlg58AlBhVJqn8q64wd/kC/W/K + JTLJuBiVf12ZiPoPfO4WSxAqD3opZ8gdbmK0KYQAhKjEto6ZrYGisfwU1gt3l8M7 + sCJSpEkOkpuQgJ8D+xzJS36VXBJQMMP9nAPps+x/rGFplsPMsXEFFiwvR1+FJZwz + lg2sJ91bLGZQ7vn74MfsGrxpiJwllRThJyT7C9V0sjb5trT2lEqZlP2dRSJYt7aJ + 1crEcdGSl6RIKgxSV6Hk8dh/ZaTjrTwaKxVkPo2IeEXy5xrR7DyonOQ6Yes0KOCm + JB5yHkFlIVEnLm/HZXEtm3bPHsFgTZuInyBCOMXpUESuVZIw8YK+Vd6AExGPPwZ4 + n5I/sCDxWII9owIj3LeLzdUG6JoroahhGmo8rgpbJpPnS+VgryQ/raUQjqDzDCuE + 9vKXKBlSUqK6H9A+NMc0mme7M8/GX7T7ewFGUB/xsdrcO4yXjqHnAe0yLf8epDjC + hh76bYqwwinVrmfcNcRxFVJZW2z0gGdgkOkOLaVVb9ggPV2SNAHbN4A+St/iRYR5 + awIDAQABo1MwUTAdBgNVHQ4EFgQUzMaCqVM30EZFfTeNUIJ5fNPAhaQwHwYDVR0j + BBgwFoAUzMaCqVM30EZFfTeNUIJ5fNPAhaQwDwYDVR0TAQH/BAUwAwEB/zANBgkq + hkiG9w0BAQsFAAOCAgEAVmk1rXtVkYR1Vs2Va/xrUaGXlFznhPU/Fft44kiEkkLp + mLVelWyAqvXYioqssZwuZnTjGz0DQPqzJjqwuGy4CHwPLmhCtfHplrbWo8a0ivYC + cL20KfZsG941siUh7LGBjTsq6mWBf2ytlFmg/fg93SgmqcEUAUcdps0JpZD8lgWB + ZMstfr6E3jaEus3OsvDD6hJNYZ5clJ5+ynLoWZ99A9JC0U46hmIZpRjbdSvasKpD + XrXTdpzyL/Do3znXE/yfoHv4//Rj2CpPHJLYRCIzvuf1mo1fWd53FjHvrbUvaHFz + CGuZROd4dC4Rx5nZw2ogIYvJ8m6HpIDkL3pBNSQJtIsvAYEQcotJoa5D/e9fu2Wr + +og37oCY4OXzViEBQvyxKD4cajNco1fgGKEaFROADwr3JceGI7Anq5W+xdUvAGNM + QuGeCueqNyrJ0CbQ1zEhwgpk/VYfB0u9m0bjMellRlKMdojby+FDCJtAJesx9no4 + SQXyx+aNHhj3qReysjGNwZvBk1IHL04HAT+ogNiYhTl1J/YON4MB5UN6Y2PxP6uG + KvJGPigx4fAwfR/d78o5ngwoH9m+8FUg8+qllJ8XgIbl/VXKTk3G4ceOm4eBmrel + DwWuBhELSjtXWPWhMlkiebgejDbAear53Lia2Cc43zx/KuhMHBTlKY/vY4F2YiI= + -----END CERTIFICATE----- + keyFile: | + -----BEGIN PRIVATE KEY----- + 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 + kOvbvVANrpsunlSAcpXm1qkV+G+xPnyJ + -----END PRIVATE KEY----- diff --git a/cmd/flux/testdata/create_secret/tls/secret-tls.yaml b/cmd/flux/testdata/create_secret/tls/secret-tls.yaml index 359af2b78a..6e2cdab1cf 100644 --- a/cmd/flux/testdata/create_secret/tls/secret-tls.yaml +++ b/cmd/flux/testdata/create_secret/tls/secret-tls.yaml @@ -5,7 +5,19 @@ metadata: name: certs namespace: my-namespace stringData: - certFile: | + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw + GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw + NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49 + AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr + RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE + AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ + 4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O + 1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb + OD8EjjCMY69RMO0= + -----END CERTIFICATE----- + tls.crt: | -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIUT84jeO/ncOrqI+FY05Fzbg8Ed7MwDQYJKoZIhvcNAQEL BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM @@ -37,7 +49,7 @@ stringData: KvJGPigx4fAwfR/d78o5ngwoH9m+8FUg8+qllJ8XgIbl/VXKTk3G4ceOm4eBmrel DwWuBhELSjtXWPWhMlkiebgejDbAear53Lia2Cc43zx/KuhMHBTlKY/vY4F2YiI= -----END CERTIFICATE----- - keyFile: | + tls.key: | -----BEGIN PRIVATE KEY----- MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDn/rPsZ74oypiw CzLlx57zplTiCi/WLSF+MmLGuTvMEQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgS diff --git a/cmd/flux/testdata/create_secret/tls/test-ca.pem b/cmd/flux/testdata/create_secret/tls/test-ca.pem new file mode 100644 index 0000000000..080bd24e6b --- /dev/null +++ b/cmd/flux/testdata/create_secret/tls/test-ca.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw +GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw +NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49 +AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr +RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ +4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O +1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb +OD8EjjCMY69RMO0= +-----END CERTIFICATE----- diff --git a/pkg/manifestgen/sourcesecret/options.go b/pkg/manifestgen/sourcesecret/options.go index ada27ce893..96e192c386 100644 --- a/pkg/manifestgen/sourcesecret/options.go +++ b/pkg/manifestgen/sourcesecret/options.go @@ -33,13 +33,19 @@ const ( const ( UsernameSecretKey = "username" PasswordSecretKey = "password" - CAFileSecretKey = "caFile" - CertFileSecretKey = "certFile" - KeyFileSecretKey = "keyFile" + CACrtSecretKey = "ca.crt" + TlsCrtSecretKey = "tls.crt" + TlsKeySecretKey = "tls.key" PrivateKeySecretKey = "identity" PublicKeySecretKey = "identity.pub" KnownHostsSecretKey = "known_hosts" BearerTokenKey = "bearerToken" + + // Depreacted: These keys are used in the generated secrets if the + // command was invoked with the deprecated TLS flags. + CAFileSecretKey = "caFile" + CertFileSecretKey = "certFile" + KeyFileSecretKey = "keyFile" ) type Options struct { @@ -54,12 +60,18 @@ type Options struct { Keypair *ssh.KeyPair Username string Password string - CAFile []byte - CertFile []byte - KeyFile []byte + CACrt []byte + TlsCrt []byte + TlsKey []byte TargetPath string ManifestFile string BearerToken string + + // Depreacted: These fields are used to store TLS data that + // specified by the deprecated TLS flags. + CAFile []byte + CertFile []byte + KeyFile []byte } func MakeDefaultOptions() Options { diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index 41849b70c6..4f8ccacc22 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -89,7 +89,7 @@ func Generate(options Options) (*manifestgen.Manifest, error) { } } - secret := buildSecret(keypair, hostKey, options.CAFile, options.CertFile, options.KeyFile, dockerCfgJson, options) + secret := buildSecret(keypair, hostKey, dockerCfgJson, options) b, err := yaml.Marshal(secret) if err != nil { return nil, err @@ -130,7 +130,7 @@ func LoadKeyPair(privateKey []byte, password string) (*ssh.KeyPair, error) { }, nil } -func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, dockerCfg []byte, options Options) (secret corev1.Secret) { +func buildSecret(keypair *ssh.KeyPair, hostKey, dockerCfg []byte, options Options) (secret corev1.Secret) { secret.TypeMeta = metav1.TypeMeta{ APIVersion: "v1", Kind: "Secret", @@ -156,13 +156,18 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, docke secret.StringData[BearerTokenKey] = options.BearerToken } - if len(caFile) != 0 { - secret.StringData[CAFileSecretKey] = string(caFile) + if len(options.CACrt) != 0 { + secret.StringData[CACrtSecretKey] = string(options.CACrt) + } else if len(options.CAFile) != 0 { + secret.StringData[CAFileSecretKey] = string(options.CAFile) } - if len(certFile) != 0 && len(keyFile) != 0 { - secret.StringData[CertFileSecretKey] = string(certFile) - secret.StringData[KeyFileSecretKey] = string(keyFile) + if len(options.TlsCrt) != 0 && len(options.TlsKey) != 0 { + secret.StringData[TlsCrtSecretKey] = string(options.TlsCrt) + secret.StringData[TlsKeySecretKey] = string(options.TlsKey) + } else if len(options.CertFile) != 0 && len(options.KeyFile) != 0 { + secret.StringData[CertFileSecretKey] = string(options.CertFile) + secret.StringData[KeyFileSecretKey] = string(options.KeyFile) } if keypair != nil && len(hostKey) != 0 { From b32051df5397bd9834027a14d68b3cef0a17c9f4 Mon Sep 17 00:00:00 2001 From: Sanskar Jaiswal Date: Wed, 9 Aug 2023 17:54:22 +0530 Subject: [PATCH 2/5] deprecate TLS flags for flux create secret helm Signed-off-by: Sanskar Jaiswal --- cmd/flux/create_secret_helm.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/flux/create_secret_helm.go b/cmd/flux/create_secret_helm.go index bf733adbc9..bca4b5fdce 100644 --- a/cmd/flux/create_secret_helm.go +++ b/cmd/flux/create_secret_helm.go @@ -41,15 +41,8 @@ var createSecretHelmCmd = &cobra.Command{ --export > repo-auth.yaml sops --encrypt --encrypted-regex '^(data|stringData)$' \ - --in-place repo-auth.yaml + --in-place repo-auth.yaml`, - # Create a Helm authentication secret using a custom TLS cert - flux create secret helm repo-auth \ - --username=username \ - --password=password \ - --cert-file=./cert.crt \ - --key-file=./key.crt \ - --ca-file=./ca.crt`, RunE: createSecretHelmCmdRun, } @@ -62,9 +55,16 @@ type secretHelmFlags struct { var secretHelmArgs secretHelmFlags func init() { - createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username") - createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password") - initSecretTLSFlags(createSecretHelmCmd.Flags(), &secretHelmArgs.secretTLSFlags) + flags := createSecretHelmCmd.Flags() + flags.StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username") + flags.StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password") + + initSecretDeprecatedTLSFlags(flags, &secretHelmArgs.secretTLSFlags) + deprecationMsg := "please use the command `flux create secret tls` to generate TLS secrets" + flags.MarkDeprecated("cert-file", deprecationMsg) + flags.MarkDeprecated("key-file", deprecationMsg) + flags.MarkDeprecated("ca-file", deprecationMsg) + createSecretCmd.AddCommand(createSecretHelmCmd) } From 2fc9d73c5fcda2086c7d80b1865202e8e2dd509a Mon Sep 17 00:00:00 2001 From: Sanskar Jaiswal Date: Wed, 9 Aug 2023 17:56:50 +0530 Subject: [PATCH 3/5] add flag `--ca-crt-file` to `flux create secret git` Add flag `--ca-crt-file` to `flux create secret git` to specify the path to CA certificate. It takes precedence over `--ca-file` and uses the key `ca.crt` in the generated Secret. Signed-off-by: Sanskar Jaiswal --- cmd/flux/create_secret_git.go | 14 +++++++++++--- cmd/flux/create_secret_git_test.go | 16 ++++++++++++++++ .../create_secret/git/secret-ca-crt.yaml | 11 +++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 cmd/flux/testdata/create_secret/git/secret-ca-crt.yaml diff --git a/cmd/flux/create_secret_git.go b/cmd/flux/create_secret_git.go index a9330cffbd..9865cbc988 100644 --- a/cmd/flux/create_secret_git.go +++ b/cmd/flux/create_secret_git.go @@ -88,6 +88,7 @@ type secretGitFlags struct { rsaBits flags.RSAKeyBits ecdsaCurve flags.ECDSACurve caFile string + caCrtFile string privateKeyFile string bearerToken string } @@ -102,6 +103,7 @@ func init() { createSecretGitCmd.Flags().Var(&secretGitArgs.rsaBits, "ssh-rsa-bits", secretGitArgs.rsaBits.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.ecdsaCurve, "ssh-ecdsa-curve", secretGitArgs.ecdsaCurve.Description()) createSecretGitCmd.Flags().StringVar(&secretGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates") + createSecretGitCmd.Flags().StringVar(&secretGitArgs.caCrtFile, "ca-crt-file", "", "path to TLS CA certificate file used for validating self-signed certificates; takes precedence over --ca-file") createSecretGitCmd.Flags().StringVar(&secretGitArgs.privateKeyFile, "private-key-file", "", "path to a passwordless private key file used for authenticating to the Git SSH server") createSecretGitCmd.Flags().StringVar(&secretGitArgs.bearerToken, "bearer-token", "", "bearer authentication token") @@ -160,12 +162,18 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error { if secretGitArgs.username != "" && secretGitArgs.password != "" && secretGitArgs.bearerToken != "" { return fmt.Errorf("user credentials and bearer token cannot be used together") } - if secretGitArgs.caFile != "" { - caBundle, err := os.ReadFile(secretGitArgs.caFile) + + // --ca-crt-file takes precedence over --ca-file. + if secretGitArgs.caCrtFile != "" { + opts.CACrt, err = os.ReadFile(secretGitArgs.caCrtFile) + if err != nil { + return fmt.Errorf("unable to read TLS CA file: %w", err) + } + } else if secretGitArgs.caFile != "" { + opts.CAFile, err = os.ReadFile(secretGitArgs.caFile) if err != nil { return fmt.Errorf("unable to read TLS CA file: %w", err) } - opts.CAFile = caBundle } default: return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme) diff --git a/cmd/flux/create_secret_git_test.go b/cmd/flux/create_secret_git_test.go index bdf2431d41..d4c84d0db5 100644 --- a/cmd/flux/create_secret_git_test.go +++ b/cmd/flux/create_secret_git_test.go @@ -1,10 +1,21 @@ package main import ( + "fmt" + "os" "testing" ) func TestCreateGitSecret(t *testing.T) { + file, err := os.CreateTemp(t.TempDir(), "ca-crt") + if err != nil { + t.Fatal("could not create CA certificate file") + } + _, err = file.Write([]byte("ca-data")) + if err != nil { + t.Fatal("could not write to CA certificate file") + } + tests := []struct { name string args string @@ -35,6 +46,11 @@ func TestCreateGitSecret(t *testing.T) { args: "create secret git bearer-token-auth --url=https://github.com/stefanprodan/podinfo --bearer-token=ghp_baR2qnFF0O41WlucePL3udt2N9vVZS4R0hAS --namespace=my-namespace --export", assert: assertGoldenFile("testdata/create_secret/git/git-bearer-token.yaml"), }, + { + name: "git authentication with CA certificate", + args: fmt.Sprintf("create secret git ca-crt --url=https://github.com/stefanprodan/podinfo --password=my-password --username=my-username --ca-crt-file=%s --namespace=my-namespace --export", file.Name()), + assert: assertGoldenFile("testdata/create_secret/git/secret-ca-crt.yaml"), + }, { name: "git authentication with basic auth and bearer token", args: "create secret git podinfo-auth --url=https://github.com/stefanprodan/podinfo --username=aaa --password=zzzz --bearer-token=aaaa --namespace=my-namespace --export", diff --git a/cmd/flux/testdata/create_secret/git/secret-ca-crt.yaml b/cmd/flux/testdata/create_secret/git/secret-ca-crt.yaml new file mode 100644 index 0000000000..958bd45fc1 --- /dev/null +++ b/cmd/flux/testdata/create_secret/git/secret-ca-crt.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: ca-crt + namespace: my-namespace +stringData: + ca.crt: ca-data + password: my-password + username: my-username + From 6464d6c7b474c1891fb35ccf86ea24083b4c22fe Mon Sep 17 00:00:00 2001 From: Sanskar Jaiswal Date: Thu, 10 Aug 2023 13:44:28 +0530 Subject: [PATCH 4/5] add deprecation warning per secret key field and constant Signed-off-by: Sanskar Jaiswal --- cmd/flux/create_secret_tls.go | 4 +-- pkg/manifestgen/sourcesecret/options.go | 32 ++++++++++++-------- pkg/manifestgen/sourcesecret/sourcesecret.go | 6 ++-- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/cmd/flux/create_secret_tls.go b/cmd/flux/create_secret_tls.go index b244a6c5f8..82f36743dd 100644 --- a/cmd/flux/create_secret_tls.go +++ b/cmd/flux/create_secret_tls.go @@ -110,10 +110,10 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error { } if secretTLSArgs.tlsCrtFile != "" && secretTLSArgs.tlsKeyFile != "" { - if opts.TlsCrt, err = os.ReadFile(secretTLSArgs.tlsCrtFile); err != nil { + if opts.TLSCrt, err = os.ReadFile(secretTLSArgs.tlsCrtFile); err != nil { return fmt.Errorf("failed to read cert file: %w", err) } - if opts.TlsKey, err = os.ReadFile(secretTLSArgs.tlsKeyFile); err != nil { + if opts.TLSKey, err = os.ReadFile(secretTLSArgs.tlsKeyFile); err != nil { return fmt.Errorf("failed to read key file: %w", err) } } else if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" { diff --git a/pkg/manifestgen/sourcesecret/options.go b/pkg/manifestgen/sourcesecret/options.go index 96e192c386..71b5f8bf21 100644 --- a/pkg/manifestgen/sourcesecret/options.go +++ b/pkg/manifestgen/sourcesecret/options.go @@ -34,18 +34,22 @@ const ( UsernameSecretKey = "username" PasswordSecretKey = "password" CACrtSecretKey = "ca.crt" - TlsCrtSecretKey = "tls.crt" - TlsKeySecretKey = "tls.key" + TLSCrtSecretKey = "tls.crt" + TLSKeySecretKey = "tls.key" PrivateKeySecretKey = "identity" PublicKeySecretKey = "identity.pub" KnownHostsSecretKey = "known_hosts" BearerTokenKey = "bearerToken" - // Depreacted: These keys are used in the generated secrets if the - // command was invoked with the deprecated TLS flags. - CAFileSecretKey = "caFile" + // Deprecated: Replaced by CACrtSecretKey, but kept for backwards + // compatibility with deprecated TLS flags. + CAFileSecretKey = "caFile" + // Deprecated: Replaced by TLSCrtSecretKey, but kept for backwards + // compatibility with deprecated TLS flags. CertFileSecretKey = "certFile" - KeyFileSecretKey = "keyFile" + // Deprecated: Replaced by TLSKeySecretKey, but kept for backwards + // compatibility with deprecated TLS flags. + KeyFileSecretKey = "keyFile" ) type Options struct { @@ -61,17 +65,21 @@ type Options struct { Username string Password string CACrt []byte - TlsCrt []byte - TlsKey []byte + TLSCrt []byte + TLSKey []byte TargetPath string ManifestFile string BearerToken string - // Depreacted: These fields are used to store TLS data that - // specified by the deprecated TLS flags. - CAFile []byte + // Deprecated: Replaced by CACrt, but kept for backwards compatibility + // with deprecated TLS flags. + CAFile []byte + // Deprecated: Replaced by TLSCrt, but kept for backwards compatibility + // with deprecated TLS flags. CertFile []byte - KeyFile []byte + // Deprecated: Replaced by TLSKey, but kept for backwards compatibility + // with deprecated TLS flags. + KeyFile []byte } func MakeDefaultOptions() Options { diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index 4f8ccacc22..25d3f59acf 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -162,9 +162,9 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, dockerCfg []byte, options Option secret.StringData[CAFileSecretKey] = string(options.CAFile) } - if len(options.TlsCrt) != 0 && len(options.TlsKey) != 0 { - secret.StringData[TlsCrtSecretKey] = string(options.TlsCrt) - secret.StringData[TlsKeySecretKey] = string(options.TlsKey) + if len(options.TLSCrt) != 0 && len(options.TLSKey) != 0 { + secret.StringData[TLSCrtSecretKey] = string(options.TLSCrt) + secret.StringData[TLSKeySecretKey] = string(options.TLSKey) } else if len(options.CertFile) != 0 && len(options.KeyFile) != 0 { secret.StringData[CertFileSecretKey] = string(options.CertFile) secret.StringData[KeyFileSecretKey] = string(options.KeyFile) From 8df27d8c3a57659e387ce0664ffce57f66c0825f Mon Sep 17 00:00:00 2001 From: Sanskar Jaiswal Date: Fri, 11 Aug 2023 15:19:49 +0530 Subject: [PATCH 5/5] modify `flux create secret tls` to create secrets of type TLS Signed-off-by: Sanskar Jaiswal --- cmd/flux/testdata/create_secret/tls/secret-tls.yaml | 1 + pkg/manifestgen/sourcesecret/sourcesecret.go | 1 + 2 files changed, 2 insertions(+) diff --git a/cmd/flux/testdata/create_secret/tls/secret-tls.yaml b/cmd/flux/testdata/create_secret/tls/secret-tls.yaml index 6e2cdab1cf..047c9221c7 100644 --- a/cmd/flux/testdata/create_secret/tls/secret-tls.yaml +++ b/cmd/flux/testdata/create_secret/tls/secret-tls.yaml @@ -102,3 +102,4 @@ stringData: XBQO4ig7vY8+1+L3w2xpTN95/rXAvB4BbO/DLea9ArikePoSJ+bVTj0YwrKBghep kOvbvVANrpsunlSAcpXm1qkV+G+xPnyJ -----END PRIVATE KEY----- +type: kubernetes.io/tls diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index 25d3f59acf..f468fa726d 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -163,6 +163,7 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, dockerCfg []byte, options Option } if len(options.TLSCrt) != 0 && len(options.TLSKey) != 0 { + secret.Type = corev1.SecretTypeTLS secret.StringData[TLSCrtSecretKey] = string(options.TLSCrt) secret.StringData[TLSKeySecretKey] = string(options.TLSKey) } else if len(options.CertFile) != 0 && len(options.KeyFile) != 0 {