Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting HTTP headers #730

Merged
merged 4 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions vault/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"log"
"net/http"
"os"
"strings"

Expand Down Expand Up @@ -157,6 +158,26 @@ func Provider() terraform.ResourceProvider {
DefaultFunc: schema.EnvDefaultFunc("VAULT_NAMESPACE", ""),
Description: "The namespace to use. Available only for Vault Enterprise",
},
"headers": {
Lucretius marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeList,
Optional: true,
Sensitive: true,
Description: "The headers to send with each Vault request.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "The header name",
},
"value": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to get test coverage of the name and value fields? It would be cool to see what the Terraform config looks like when they're populated.

Copy link
Contributor Author

@Lucretius Lucretius May 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied the basic token name test, and just added a custom provider configuration which included a header. It doesn't test any header related functionality (which would depend on individual use cases), only that the headers don't cause errors when Vault is doing things (in the case of this test, token lookup)

Type: schema.TypeString,
Required: true,
Description: "The header value",
},
},
},
},
},
ConfigureFunc: providerConfigure,
DataSourcesMap: dataSourcesMap,
Expand Down Expand Up @@ -637,6 +658,21 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
if err != nil {
return nil, fmt.Errorf("failed to configure Vault API: %s", err)
}
// Set headers if provided
headers := d.Get("headers").([]interface{})
tyrannosaurus-becks marked this conversation as resolved.
Show resolved Hide resolved
parsedHeaders := client.Headers().Clone()

if parsedHeaders == nil {
parsedHeaders = make(http.Header)
}

for _, h := range headers {
header := h.(map[string]interface{})
if name, ok := header["name"]; ok {
parsedHeaders.Add(name.(string), header["value"].(string))
}
}
client.SetHeaders(parsedHeaders)

client.SetMaxRetries(d.Get("max_retries").(int))

Expand Down
40 changes: 40 additions & 0 deletions vault/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,29 @@ func TestAccAuthLoginProviderConfigure(t *testing.T) {
}
}

func TestTokenReadProviderConfigureWithHeaders(t *testing.T) {
rootProvider := Provider().(*schema.Provider)

rootProviderResource := &schema.Resource{
Schema: rootProvider.Schema,
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testProviders,
Steps: []resource.TestStep{
{
Config: testHeaderConfig("auth", "123"),
Check: testTokenName_check("token-testtoken"),
},
},
})

rootProviderData := rootProviderResource.TestResourceData()
if _, err := providerConfigure(rootProviderData); err != nil {
t.Fatal(err)
}
}

func TestAccNamespaceProviderConfigure(t *testing.T) {
isEnterprise := os.Getenv("TF_ACC_ENTERPRISE")
if isEnterprise == "" {
Expand Down Expand Up @@ -584,6 +607,23 @@ func TestAccTokenName(t *testing.T) {
}
}

func testHeaderConfig(headerName, headerValue string) string {
providerConfig := fmt.Sprintf(`
provider "vault" {
headers {
name = "%s"
value = "%s"
}
token_name = "testtoken"
}

data "vault_generic_secret" "test" {
path = "/auth/token/lookup-self"
}
`, headerName, headerValue)
return providerConfig
}

// Using the data lookup generic_secret to inspect used token
// by terraform (this enables check of token name)
func testTokenNameConfig(tokenNameSchema bool, tokenName string) string {
Expand Down
10 changes: 10 additions & 0 deletions website/docs/index.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ variables in order to keep credential information out of the configuration.
* `namespace` - (Optional) Set the namespace to use. May be set via the
`VAULT_NAMESPACE` environment variable. *Available only for Vault Enterprise*.

* `headers` - (Optional) A configuration block, described below, that provides headers
to be sent along with all requests to the Vault server. This block can be specified
multiple times.

The `auth_login` configuration block accepts the following arguments:

* `path` - (Required) The login path of the auth backend. For example, login with
Expand All @@ -171,6 +175,12 @@ The `client_auth` configuration block accepts the following arguments:
* `key_file` - (Required) Path to a file on local disk that contains the
PEM-encoded private key for which the authentication certificate was issued.

The `headers` configuration block accepts the following arguments:

* `name` - (Required) The name of the header.

* `value` - (Required) The value of the header.

## Example Usage

```hcl
Expand Down