From 75227820179dcdaaa18eee6cc10454e291444668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Wed, 19 Jul 2023 09:51:17 +0200 Subject: [PATCH] Add support to log with a JWT auth method (#342) This is an alternative of giving a Consul token in the provider configuration or as en environment variable and can be use in Terraform Cloud runs by setting the `use_terraform_cloud_workload_identity` parameter. Closes https://github.com/hashicorp/terraform-provider-consul/issues/334 --- consul/resource_provider.go | 119 +++++++++++-- consul/resource_provider_test.go | 156 ++++++++++++------ docs/index.md | 60 ++++--- .../consul_peering/data-source.tf | 3 - .../consul_peerings/data-source.tf | 3 - examples/kv/main.tf | 3 - examples/kv/variables.tf | 3 - examples/resources/consul_peering/resource.tf | 3 - .../consul_peering_token/resource.tf | 3 - templates/{index.md => index.md.tmpl} | 26 +-- 10 files changed, 255 insertions(+), 124 deletions(-) rename templates/{index.md => index.md.tmpl} (50%) diff --git a/consul/resource_provider.go b/consul/resource_provider.go index a436c607..3fc9b62b 100644 --- a/consul/resource_provider.go +++ b/consul/resource_provider.go @@ -8,6 +8,7 @@ import ( "fmt" "log" "net/http" + "os" "strings" consulapi "github.com/hashicorp/consul/api" @@ -31,8 +32,9 @@ func Provider() terraform.ResourceProvider { return &schema.Provider{ Schema: map[string]*schema.Schema{ "datacenter": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + Description: "The datacenter to use. Defaults to that of the agent.", }, "address": { @@ -42,6 +44,7 @@ func Provider() terraform.ResourceProvider { "CONSUL_ADDRESS", "CONSUL_HTTP_ADDR", }, "localhost:8500"), + Description: `The HTTP(S) API address of the agent to use. Defaults to "127.0.0.1:8500".`, }, "scheme": { @@ -51,12 +54,14 @@ func Provider() terraform.ResourceProvider { "CONSUL_SCHEME", "CONSUL_HTTP_SCHEME", }, ""), + Description: `The URL scheme of the agent to use ("http" or "https"). Defaults to "http".`, }, "http_auth": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("CONSUL_HTTP_AUTH", ""), + DefaultFunc: schema.EnvDefaultFunc("CONSUL_HTTP_AUTH", nil), + Description: "HTTP Basic Authentication credentials to be used when communicating with Consul, in the format of either `user` or `user:pass`. This may also be specified using the `CONSUL_HTTP_AUTH` environment variable.", }, "ca_file": { @@ -64,12 +69,14 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("CONSUL_CA_FILE", nil), ConflictsWith: []string{"ca_pem"}, + Description: "A path to a PEM-encoded certificate authority used to verify the remote agent's certificate.", }, "ca_pem": { Type: schema.TypeString, Optional: true, ConflictsWith: []string{"ca_file"}, + Description: "PEM-encoded certificate authority used to verify the remote agent's certificate.", }, "cert_file": { @@ -77,12 +84,14 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("CONSUL_CERT_FILE", nil), ConflictsWith: []string{"cert_pem"}, + Description: "A path to a PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`.", }, "cert_pem": { Type: schema.TypeString, Optional: true, ConflictsWith: []string{"cert_file"}, + Description: "PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`.", }, "key_file": { @@ -90,24 +99,28 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("CONSUL_KEY_FILE", nil), ConflictsWith: []string{"key_pem"}, + Description: "A path to a PEM-encoded private key, required if `cert_file` or `cert_pem` is specified.", }, "key_pem": { Type: schema.TypeString, Optional: true, ConflictsWith: []string{"key_file"}, + Description: "PEM-encoded private key, required if `cert_file` or `cert_pem` is specified.", }, "ca_path": { Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("CONSUL_CAPATH", ""), + Description: "A path to a directory of PEM-encoded certificate authority files to use to check the authenticity of client and server connections. Can also be specified with the `CONSUL_CAPATH` environment variable.", }, "insecure_https": { - Type: schema.TypeBool, - Optional: true, - Default: false, + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Boolean value to disable SSL certificate verification; setting this value to true is not recommended for production use. Only use this with scheme set to "https".`, }, "token": { @@ -117,7 +130,42 @@ func Provider() terraform.ResourceProvider { DefaultFunc: schema.MultiEnvDefaultFunc([]string{ "CONSUL_TOKEN", "CONSUL_HTTP_TOKEN", - }, ""), + }, nil), + Description: "The ACL token to use by default when making requests to the agent. Can also be specified with `CONSUL_HTTP_TOKEN` or `CONSUL_TOKEN` as an environment variable.", + }, + + "auth_jwt": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: "Authenticates to Consul using a JWT authentication method.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auth_method": { + Type: schema.TypeString, + Required: true, + Description: "The name of the auth method to use for login.", + }, + "bearer_token": { + Type: schema.TypeString, + Optional: true, + Description: "The bearer token to present to the auth method during login for authentication purposes. For the Kubernetes auth method this is a [Service Account Token (JWT)](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens).", + }, + "use_terraform_cloud_workload_identity": { + Type: schema.TypeBool, + Optional: true, + Description: "Whether to use a [Terraform Workload Identity token](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/workload-identity-tokens). The token will be read from the `TFC_WORKLOAD_IDENTITY_TOKEN` environment variable.", + }, + "meta": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Specifies arbitrary KV metadata linked to the token. Can be useful to track origins.", + }, + }, + }, }, "namespace": { @@ -129,18 +177,18 @@ func Provider() terraform.ResourceProvider { Type: schema.TypeList, Optional: true, Sensitive: true, - Description: "Additional headers to send with each Consul request.", + Description: "A configuration block, described below, that provides additional headers to be sent along with all requests to the Consul server. This block can be specified multiple times.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, Required: true, - Description: "The header name", + Description: "The name of the header.", }, "value": { Type: schema.TypeString, Required: true, - Description: "The header value", + Description: "The value of the header.", }, }, }, @@ -235,11 +283,53 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { parsedHeaders.Add(header["name"].(string), header["value"].(string)) } client.SetHeaders(parsedHeaders) + + authJWT := d.Get("auth_jwt").([]interface{}) + if len(authJWT) > 0 { + authConfig := authJWT[0].(map[string]interface{}) + authMethod := authConfig["auth_method"].(string) + tfeWorkloadIdentity := authConfig["use_terraform_cloud_workload_identity"].(bool) + bearerToken := authConfig["bearer_token"].(string) + + if tfeWorkloadIdentity { + bearerToken = os.Getenv("TFC_WORKLOAD_IDENTITY_TOKEN") + if bearerToken == "" { + return nil, fmt.Errorf("auth_jwt.use_terraform_cloud_workload_identity has been set but no token found in TFC_WORKLOAD_IDENTITY_TOKEN environment variable") + } + + } else if bearerToken == "" { + return nil, fmt.Errorf("either auth_jwt.bearer_token or auth_jwt.use_terraform_cloud_workload_identity should be set") + } + + meta := map[string]string{} + for k, v := range authConfig["meta"].(map[string]interface{}) { + meta[k] = v.(string) + } + _, wOpts := getOptions(d, config) + token, _, err := client.ACL().Login(&consulapi.ACLLoginParams{ + AuthMethod: authMethod, + BearerToken: bearerToken, + Meta: meta, + }, wOpts) + if err != nil { + return nil, fmt.Errorf("failed to login using JWT auth method %q: %v", authMethod, err) + } + config.Token = token.SecretID + } + return config, nil } func getClient(d *schema.ResourceData, meta interface{}) (*consulapi.Client, *consulapi.QueryOptions, *consulapi.WriteOptions) { - client := meta.(*Config).client + config := meta.(*Config) + client := config.client + qOpts, wOpts := getOptions(d, config) + return client, qOpts, wOpts +} + +func getOptions(d *schema.ResourceData, meta interface{}) (*consulapi.QueryOptions, *consulapi.WriteOptions) { + config := meta.(*Config) + client := config.client var dc, token, namespace, partition string if v, ok := d.GetOk("datacenter"); ok { dc = v.(string) @@ -255,8 +345,8 @@ func getClient(d *schema.ResourceData, meta interface{}) (*consulapi.Client, *co } if dc == "" { - if meta.(*Config).Datacenter != "" { - dc = meta.(*Config).Datacenter + if config.Datacenter != "" { + dc = config.Datacenter } else { info, _ := client.Agent().Self() if info != nil { @@ -277,7 +367,8 @@ func getClient(d *schema.ResourceData, meta interface{}) (*consulapi.Client, *co Partition: partition, Token: token, } - return client, qOpts, wOpts + + return qOpts, wOpts } type stateWriter struct { diff --git a/consul/resource_provider_test.go b/consul/resource_provider_test.go index 555e3e84..9c7743d9 100644 --- a/consul/resource_provider_test.go +++ b/consul/resource_provider_test.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "os/exec" + "regexp" "strings" "testing" "time" @@ -23,14 +24,116 @@ const ( initialManagementToken = "12345678-1234-1234-1234-1234567890ab" ) +var _ terraform.ResourceProvider = Provider() + func TestResourceProvider(t *testing.T) { if err := Provider().(*schema.Provider).InternalValidate(); err != nil { t.Fatalf("err: %s", err) } -} -func TestResourceProvider_impl(t *testing.T) { - var _ terraform.ResourceProvider = Provider() + testCases := map[string]struct { + Config string + ExpectError *regexp.Regexp + }{ + "ca_path": { + Config: ` + provider "consul" { + ca_path = "test-fixtures/capath" + scheme = "https" + } + + data "consul_key_prefix" "app" { + path_prefix = "test" + }`, + ExpectError: regexp.MustCompile("server gave HTTP response to HTTPS client"), + }, + "insecure_https": { + Config: ` + provider "consul" { + scheme = "https" + insecure_https = true + } + + data "consul_key_prefix" "app" { + path_prefix = "test" + }`, + ExpectError: regexp.MustCompile("server gave HTTP response to HTTPS client"), + }, + "insecure_https_err": { + Config: ` + provider "consul" { + address = "demo.consul.io:80" + datacenter = "nyc3" + scheme = "http" + insecure_https = true + } + + data "consul_key_prefix" "app" { + path_prefix = "test" + }`, + ExpectError: regexp.MustCompile("insecure_https is meant to be used when scheme is https"), + }, + "auth_jwt": { + Config: ` + provider "consul" { + address = "demo.consul.io:80" + auth_jwt { + auth_method = "jwt" + bearer_token = "..." + } + } + + data "consul_key_prefix" "app" { + path_prefix = "test" + }`, + ExpectError: regexp.MustCompile("failed to login using JWT auth method"), + }, + "auth_jwt_no_token": { + Config: ` + provider "consul" { + address = "demo.consul.io:80" + auth_jwt { + auth_method = "jwt" + } + } + + data "consul_key_prefix" "app" { + path_prefix = "test" + }`, + ExpectError: regexp.MustCompile("either auth_jwt.bearer_token or auth_jwt.use_terraform_cloud_workload_identity should be set"), + }, + "auth_jwt_tfc_workload_identity": { + Config: ` + provider "consul" { + address = "demo.consul.io:80" + auth_jwt { + auth_method = "jwt" + use_terraform_cloud_workload_identity = true + } + } + + data "consul_key_prefix" "app" { + path_prefix = "test" + }`, + ExpectError: regexp.MustCompile("no token found in TFC_WORKLOAD_IDENTITY_TOKEN environment variable"), + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + providers, _ := startTestServer(t) + + resource.Test(t, resource.TestCase{ + Providers: providers, + Steps: []resource.TestStep{ + { + Config: tc.Config, + ExpectError: tc.ExpectError, + }, + }, + }) + }) + } } func TestResourceProvider_Configure(t *testing.T) { @@ -97,53 +200,6 @@ func TestResourceProvider_ConfigureTLSPem(t *testing.T) { } } -func TestResourceProvider_CAPath(t *testing.T) { - rp := Provider() - - raw := map[string]interface{}{ - "address": "demo.consul.io:90", - "ca_path": "test-fixtures/capath", - "scheme": "https", - } - - err := rp.Configure(terraform.NewResourceConfigRaw(raw)) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestResourceProvider_ConfigureTLSInsecureHttps(t *testing.T) { - rp := Provider() - - raw := map[string]interface{}{ - "address": "demo.consul.io:80", - "datacenter": "nyc3", - "scheme": "https", - "insecure_https": true, - } - - err := rp.Configure(terraform.NewResourceConfigRaw(raw)) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestResourceProvider_ConfigureTLSInsecureHttpsMismatch(t *testing.T) { - rp := Provider() - - raw := map[string]interface{}{ - "address": "demo.consul.io:80", - "datacenter": "nyc3", - "scheme": "http", - "insecure_https": true, - } - - err := rp.Configure(terraform.NewResourceConfigRaw(raw)) - if err == nil { - t.Fatal("Provider should error if insecure_https is set but scheme is not https") - } -} - // Some resources have some attributes that allows for overriding the configuration // of the provider like "token", "datacenter", "namespace" or "partition". This // causes some issues when reading resources after a user changed it as the new diff --git a/docs/index.md b/docs/index.md index e52f0913..d94b7849 100644 --- a/docs/index.md +++ b/docs/index.md @@ -57,34 +57,56 @@ The known compatibility between this provider and Consul is: | Terraform provider version | Consul version | | -------------------------- | -------------- | +| 2.17.0 | >= 1.14.0 | +| 2.16.0 | >= 1.13.0 | | 2.15.0 | >= 1.11.0 | | 2.14.0 | >= 1.10.0 | | 2.13.0 | >= 1.10.0 | -## Argument Reference -The following arguments are supported: + +## Schema -* `address` - (Optional) The HTTP(S) API address of the agent to use. Defaults to "127.0.0.1:8500". -* `scheme` - (Optional) The URL scheme of the agent to use ("http" or "https"). Defaults to "http". -* `http_auth` - (Optional) HTTP Basic Authentication credentials to be used when communicating with Consul, in the format of either `user` or `user:pass`. This may also be specified using the `CONSUL_HTTP_AUTH` environment variable. -* `datacenter` - (Optional) The datacenter to use. Defaults to that of the agent. -* `token` - (Optional) The ACL token to use by default when making requests to the agent. Can also be specified with `CONSUL_HTTP_TOKEN` or `CONSUL_TOKEN` as an environment variable. -* `ca_file` - (Optional) A path to a PEM-encoded certificate authority used to verify the remote agent's certificate. -* `ca_pem` - (Optional) PEM-encoded certificate authority used to verify the remote agent's certificate. -* `cert_file` - (Optional) A path to a PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`. -* `cert_pem` - (Optional) PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`. -* `key_file`- (Optional) A path to a PEM-encoded private key, required if `cert_file` or `cert_pem` is specified. -* `key_pem`- (Optional) PEM-encoded private key, required if `cert_file` or `cert_pem` is specified. -* `ca_path` - (Optional) A path to a directory of PEM-encoded certificate authority files to use to check the authenticity of client and server connections. Can also be specified with the `CONSUL_CAPATH` environment variable. -* `insecure_https`- (Optional) Boolean value to disable SSL certificate verification; setting this value to true is not recommended for production use. Only use this with scheme set to "https". -* `header` - (Optional) A configuration block, described below, that provides additional headers to be sent along with all requests to the Consul server. This block can be specified multiple times. +### Optional -The `header` configuration block accepts the following arguments: +- `address` (String) The HTTP(S) API address of the agent to use. Defaults to "127.0.0.1:8500". +- `auth_jwt` (Block List, Max: 1) Authenticates to Consul using a JWT authentication method. (see [below for nested schema](#nestedblock--auth_jwt)) +- `ca_file` (String) A path to a PEM-encoded certificate authority used to verify the remote agent's certificate. +- `ca_path` (String) A path to a directory of PEM-encoded certificate authority files to use to check the authenticity of client and server connections. Can also be specified with the `CONSUL_CAPATH` environment variable. +- `ca_pem` (String) PEM-encoded certificate authority used to verify the remote agent's certificate. +- `cert_file` (String) A path to a PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`. +- `cert_pem` (String) PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`. +- `datacenter` (String) The datacenter to use. Defaults to that of the agent. +- `header` (Block List) A configuration block, described below, that provides additional headers to be sent along with all requests to the Consul server. This block can be specified multiple times. (see [below for nested schema](#nestedblock--header)) +- `http_auth` (String) HTTP Basic Authentication credentials to be used when communicating with Consul, in the format of either `user` or `user:pass`. This may also be specified using the `CONSUL_HTTP_AUTH` environment variable. +- `insecure_https` (Boolean) Boolean value to disable SSL certificate verification; setting this value to true is not recommended for production use. Only use this with scheme set to "https". +- `key_file` (String) A path to a PEM-encoded private key, required if `cert_file` or `cert_pem` is specified. +- `key_pem` (String) PEM-encoded private key, required if `cert_file` or `cert_pem` is specified. +- `namespace` (String) +- `scheme` (String) The URL scheme of the agent to use ("http" or "https"). Defaults to "http". +- `token` (String, Sensitive) The ACL token to use by default when making requests to the agent. Can also be specified with `CONSUL_HTTP_TOKEN` or `CONSUL_TOKEN` as an environment variable. - * `name` - (Required) The name of the header. + +### Nested Schema for `auth_jwt` - * `value` - (Required) The value of the header. +Required: + +- `auth_method` (String) The name of the auth method to use for login. + +Optional: + +- `bearer_token` (String) The bearer token to present to the auth method during login for authentication purposes. For the Kubernetes auth method this is a [Service Account Token (JWT)](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens). +- `meta` (Map of String) Specifies arbitrary KV metadata linked to the token. Can be useful to track origins. +- `use_terraform_cloud_workload_identity` (Boolean) Whether to use a [Terraform Workload Identity token](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/workload-identity-tokens). The token will be read from the `TFC_WORKLOAD_IDENTITY_TOKEN` environment variable. + + + +### Nested Schema for `header` + +Required: + +- `name` (String) The name of the header. +- `value` (String) The value of the header. ## Environment Variables diff --git a/examples/data-sources/consul_peering/data-source.tf b/examples/data-sources/consul_peering/data-source.tf index 8d3a3bb2..6451ced4 100644 --- a/examples/data-sources/consul_peering/data-source.tf +++ b/examples/data-sources/consul_peering/data-source.tf @@ -1,6 +1,3 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - data "consul_peering" "basic" { peer_name = "peered-cluster" } diff --git a/examples/data-sources/consul_peerings/data-source.tf b/examples/data-sources/consul_peerings/data-source.tf index b36fb33b..646c357d 100644 --- a/examples/data-sources/consul_peerings/data-source.tf +++ b/examples/data-sources/consul_peerings/data-source.tf @@ -1,4 +1 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - data "consul_peerings" "peers" {} diff --git a/examples/kv/main.tf b/examples/kv/main.tf index d849a6d9..515ebde4 100644 --- a/examples/kv/main.tf +++ b/examples/kv/main.tf @@ -1,6 +1,3 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - # Setup the Consul provisioner to use the demo cluster provider "consul" { address = "demo.consul.io:80" diff --git a/examples/kv/variables.tf b/examples/kv/variables.tf index 0caa092b..2cb9be01 100644 --- a/examples/kv/variables.tf +++ b/examples/kv/variables.tf @@ -1,6 +1,3 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - variable "aws_region" { description = "The AWS region to create resources in." default = "us-east-1" diff --git a/examples/resources/consul_peering/resource.tf b/examples/resources/consul_peering/resource.tf index 3e5dd14e..ceef5437 100644 --- a/examples/resources/consul_peering/resource.tf +++ b/examples/resources/consul_peering/resource.tf @@ -1,6 +1,3 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - # Create a peering between the EU and US Consul clusters provider "consul" { diff --git a/examples/resources/consul_peering_token/resource.tf b/examples/resources/consul_peering_token/resource.tf index 6c68e994..7730205b 100644 --- a/examples/resources/consul_peering_token/resource.tf +++ b/examples/resources/consul_peering_token/resource.tf @@ -1,6 +1,3 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - resource "consul_peering_token" "token" { peer_name = "eu-cluster" } diff --git a/templates/index.md b/templates/index.md.tmpl similarity index 50% rename from templates/index.md rename to templates/index.md.tmpl index e52f0913..f86c3cbc 100644 --- a/templates/index.md +++ b/templates/index.md.tmpl @@ -57,34 +57,14 @@ The known compatibility between this provider and Consul is: | Terraform provider version | Consul version | | -------------------------- | -------------- | +| 2.17.0 | >= 1.14.0 | +| 2.16.0 | >= 1.13.0 | | 2.15.0 | >= 1.11.0 | | 2.14.0 | >= 1.10.0 | | 2.13.0 | >= 1.10.0 | -## Argument Reference -The following arguments are supported: - -* `address` - (Optional) The HTTP(S) API address of the agent to use. Defaults to "127.0.0.1:8500". -* `scheme` - (Optional) The URL scheme of the agent to use ("http" or "https"). Defaults to "http". -* `http_auth` - (Optional) HTTP Basic Authentication credentials to be used when communicating with Consul, in the format of either `user` or `user:pass`. This may also be specified using the `CONSUL_HTTP_AUTH` environment variable. -* `datacenter` - (Optional) The datacenter to use. Defaults to that of the agent. -* `token` - (Optional) The ACL token to use by default when making requests to the agent. Can also be specified with `CONSUL_HTTP_TOKEN` or `CONSUL_TOKEN` as an environment variable. -* `ca_file` - (Optional) A path to a PEM-encoded certificate authority used to verify the remote agent's certificate. -* `ca_pem` - (Optional) PEM-encoded certificate authority used to verify the remote agent's certificate. -* `cert_file` - (Optional) A path to a PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`. -* `cert_pem` - (Optional) PEM-encoded certificate provided to the remote agent; requires use of `key_file` or `key_pem`. -* `key_file`- (Optional) A path to a PEM-encoded private key, required if `cert_file` or `cert_pem` is specified. -* `key_pem`- (Optional) PEM-encoded private key, required if `cert_file` or `cert_pem` is specified. -* `ca_path` - (Optional) A path to a directory of PEM-encoded certificate authority files to use to check the authenticity of client and server connections. Can also be specified with the `CONSUL_CAPATH` environment variable. -* `insecure_https`- (Optional) Boolean value to disable SSL certificate verification; setting this value to true is not recommended for production use. Only use this with scheme set to "https". -* `header` - (Optional) A configuration block, described below, that provides additional headers to be sent along with all requests to the Consul server. This block can be specified multiple times. - -The `header` configuration block accepts the following arguments: - - * `name` - (Required) The name of the header. - - * `value` - (Required) The value of the header. +{{ .SchemaMarkdown | trimspace }} ## Environment Variables