diff --git a/.changelog/1638.txt b/.changelog/1638.txt new file mode 100644 index 0000000000..af581c728d --- /dev/null +++ b/.changelog/1638.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +`kubernetes/provider.go`: Add `tls_server_name` kubernetes provider options. +``` \ No newline at end of file diff --git a/kubernetes/provider.go b/kubernetes/provider.go index c3c88a783f..b0ba79ba3e 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -63,6 +63,12 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", false), Description: "Whether server should be accessed without verifying the TLS certificate.", }, + "tls_server_name": { + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_TLS_SERVER_NAME", ""), + Description: "Server name passed to the server for SNI and is used in the client to check server certificates against.", + }, "client_certificate": { Type: schema.TypeString, Optional: true, @@ -524,7 +530,7 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) authInfo, authInfoOk := d.GetOk("config_context_auth_info") cluster, clusterOk := d.GetOk("config_context_cluster") if ctxOk || authInfoOk || clusterOk { - ctxSuffix = "; overriden context" + ctxSuffix = "; overridden context" if ctxOk { overrides.CurrentContext = kubectx.(string) ctxSuffix += fmt.Sprintf("; config ctx: %s", overrides.CurrentContext) @@ -540,7 +546,7 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) overrides.Context.Cluster = cluster.(string) ctxSuffix += fmt.Sprintf("; cluster: %s", overrides.Context.Cluster) } - log.Printf("[DEBUG] Using overidden context: %#v", overrides.Context) + log.Printf("[DEBUG] Using overridden context: %#v", overrides.Context) } } @@ -548,6 +554,9 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) if v, ok := d.GetOk("insecure"); ok { overrides.ClusterInfo.InsecureSkipTLSVerify = v.(bool) } + if v, ok := d.GetOk("tls_server_name"); ok { + overrides.ClusterInfo.TLSServerName = v.(string) + } if v, ok := d.GetOk("cluster_ca_certificate"); ok { overrides.ClusterInfo.CertificateAuthorityData = bytes.NewBufferString(v.(string)).Bytes() } diff --git a/kubernetes/provider_test.go b/kubernetes/provider_test.go index e2f935eb91..7cb009ef26 100644 --- a/kubernetes/provider_test.go +++ b/kubernetes/provider_test.go @@ -120,6 +120,7 @@ func unsetEnv(t *testing.T) func() { "KUBE_CLIENT_KEY_DATA": e.ClientKeyData, "KUBE_CLUSTER_CA_CERT_DATA": e.ClusterCACertData, "KUBE_INSECURE": e.Insecure, + "KUBE_TLS_SERVER_NAME": e.TLSServerName, "KUBE_TOKEN": e.Token, } @@ -150,6 +151,7 @@ func getEnv() *currentEnv { ClientKeyData: os.Getenv("KUBE_CLIENT_KEY_DATA"), ClusterCACertData: os.Getenv("KUBE_CLUSTER_CA_CERT_DATA"), Insecure: os.Getenv("KUBE_INSECURE"), + TLSServerName: os.Getenv("KUBE_TLS_SERVER_NAME"), Token: os.Getenv("KUBE_TOKEN"), } if v := os.Getenv("KUBE_CONFIG_PATH"); v != "" { @@ -449,5 +451,6 @@ type currentEnv struct { ClientKeyData string ClusterCACertData string Insecure string + TLSServerName string Token string } diff --git a/manifest/provider/configure.go b/manifest/provider/configure.go index 8c18757d02..9763ef9d10 100644 --- a/manifest/provider/configure.go +++ b/manifest/provider/configure.go @@ -287,6 +287,26 @@ func (s *RawProviderServer) ConfigureProvider(ctx context.Context, req *tfprotov } overrides.ClusterInfo.InsecureSkipTLSVerify = insecure + // Handle 'tls_server_name' attribute + // + var tlsServerName string + if !providerConfig["tls_server_name"].IsNull() && providerConfig["tls_server_name"].IsKnown() { + err = providerConfig["tls_server_name"].As(&tlsServerName) + if err != nil { + // invalid attribute type - this shouldn't happen, bail out for now + response.Diagnostics = append(response.Diagnostics, &tfprotov5.Diagnostic{ + Severity: tfprotov5.DiagnosticSeverityError, + Summary: "Provider configuration: failed to assert type of 'tls_server_name' value", + Detail: err.Error(), + }) + return response, nil + } + overrides.ClusterInfo.TLSServerName = tlsServerName + } + if tlsServerName, ok := os.LookupEnv("KUBE_TLS_SERVER_NAME"); ok && tlsServerName != "" { + overrides.ClusterInfo.TLSServerName = tlsServerName + } + hasCA := len(overrides.ClusterInfo.CertificateAuthorityData) != 0 hasCert := len(overrides.AuthInfo.ClientCertificateData) != 0 defaultTLS := hasCA || hasCert || overrides.ClusterInfo.InsecureSkipTLSVerify diff --git a/manifest/provider/provider_config.go b/manifest/provider/provider_config.go index 919041fbc5..44a7072c8f 100644 --- a/manifest/provider/provider_config.go +++ b/manifest/provider/provider_config.go @@ -57,6 +57,17 @@ func GetProviderConfigSchema() *tfprotov5.Schema { DescriptionKind: 0, Deprecated: false, }, + { + Name: "tls_server_name", + Type: tftypes.String, + Description: "Server name passed to the server for SNI and is used in the client to check server certificates against.", + Required: false, + Optional: true, + Computed: false, + Sensitive: false, + DescriptionKind: 0, + Deprecated: false, + }, { Name: "client_certificate", Type: tftypes.String, diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index a2a94a23a9..2e5d2d6ad2 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -171,6 +171,7 @@ The following arguments are supported: * `username` - (Optional) The username to use for HTTP basic authentication when accessing the Kubernetes API. Can be sourced from `KUBE_USER`. * `password` - (Optional) The password to use for HTTP basic authentication when accessing the Kubernetes API. Can be sourced from `KUBE_PASSWORD`. * `insecure` - (Optional) Whether the server should be accessed without verifying the TLS certificate. Can be sourced from `KUBE_INSECURE`. Defaults to `false`. +* `tls_server_name` - (Optional) Server name passed to the server for SNI and is used in the client to check server certificates against. Can be sourced from `KUBE_TLS_SERVER_NAME`. * `client_certificate` - (Optional) PEM-encoded client certificate for TLS authentication. Can be sourced from `KUBE_CLIENT_CERT_DATA`. * `client_key` - (Optional) PEM-encoded client certificate key for TLS authentication. Can be sourced from `KUBE_CLIENT_KEY_DATA`. * `cluster_ca_certificate` - (Optional) PEM-encoded root certificates bundle for TLS authentication. Can be sourced from `KUBE_CLUSTER_CA_CERT_DATA`.