diff --git a/path_config.go b/path_config.go index 460e9af8..9d12bc5a 100644 --- a/path_config.go +++ b/path_config.go @@ -33,10 +33,11 @@ func pathConfig(b *kubeAuthBackend) *framework.Path { "kubernetes_ca_cert": { Type: framework.TypeString, - Description: "PEM encoded CA cert for use by the TLS client used to talk with the API.", + Description: "Optional PEM encoded CA cert for use by the TLS client used to talk with the API.", DisplayAttrs: &framework.DisplayAttributes{ Name: "Kubernetes CA Certificate", }, + Required: false, }, "token_reviewer_jwt": { Type: framework.TypeString, @@ -56,6 +57,7 @@ extracted. Not every installation of Kubernetes exposes these keys.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Service account verification keys", }, + Required: false, }, "issuer": { Type: framework.TypeString, @@ -141,10 +143,6 @@ func (b *kubeAuthBackend) pathConfigWrite(ctx context.Context, req *logical.Requ } } - if disableLocalJWT && caCert == "" { - return logical.ErrorResponse("kubernetes_ca_cert must be given when disable_local_ca_jwt is true"), nil - } - config := &kubeConfig{ PublicKeys: make([]interface{}, len(pemList)), PEMKeys: pemList, @@ -161,11 +159,11 @@ func (b *kubeAuthBackend) pathConfigWrite(ctx context.Context, req *logical.Requ // Determine if we load the local CA cert or the CA cert provided // by the kubernetes_ca_cert path into the backend's HTTP client - certPool := x509.NewCertPool() tlsConfig := &tls.Config{ MinVersion: tls.VersionTLS12, } if disableLocalJWT || len(caCert) > 0 { + certPool := x509.NewCertPool() certPool.AppendCertsFromPEM([]byte(config.CACert)) tlsConfig.RootCAs = certPool @@ -175,7 +173,10 @@ func (b *kubeAuthBackend) pathConfigWrite(ctx context.Context, req *logical.Requ if err != nil { return nil, err } - + certPool, err := x509.SystemCertPool() + if err != nil { + certPool = x509.NewCertPool() + } certPool.AppendCertsFromPEM([]byte(localCACert)) tlsConfig.RootCAs = certPool diff --git a/path_config_test.go b/path_config_test.go index 20afab63..6e34140d 100644 --- a/path_config_test.go +++ b/path_config_test.go @@ -535,6 +535,65 @@ func TestConfig_LocalJWTRenewal(t *testing.T) { } } +func TestConfig_SystemCa(t *testing.T) { + testCases := map[string]struct { + config map[string]interface{} + setupInClusterFiles bool + expected *kubeConfig + }{ + "no CA default to system": { + config: map[string]interface{}{ + "kubernetes_host": "host", + "disable_local_ca_jwt": false, + "kubernetes_ca_cert": "", + }, + setupInClusterFiles: true, + + expected: &kubeConfig{ + PublicKeys: []interface{}{}, + PEMKeys: []string{}, + Host: "host", + CACert: testLocalCACert, + TokenReviewerJWT: testLocalJWT, + DisableISSValidation: true, + DisableLocalCAJwt: false, + }, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + b, storage := getBackend(t) + + if tc.setupInClusterFiles { + cleanup := setupLocalFiles(t, b) + defer cleanup() + } + + req := &logical.Request{ + Operation: logical.CreateOperation, + Path: configPath, + Storage: storage, + Data: tc.config, + } + + resp, err := b.HandleRequest(context.Background(), req) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("err:%s resp:%#v\n", err, resp) + } + + conf, err := b.(*kubeAuthBackend).loadConfig(context.Background(), storage) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(tc.expected, conf) { + t.Fatalf("expected did not match actual: expected %#v\n got %#v\n", tc.expected, conf) + } + }) + } +} + var testLocalCACert string = `-----BEGIN CERTIFICATE----- MIIDVDCCAjwCCQDFiyFY1M6afTANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJV UzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEgMB4GA1UE