From 96c68a074ec8f316f359debe78c2093286e150b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20OYEZ?= Date: Mon, 29 Mar 2021 08:57:19 +0000 Subject: [PATCH] Introducing additional headers for requests configuration --- docs/index.md | 1 + example/main.tf | 3 +++ keycloak/keycloak_client.go | 16 +++++++++++++++- keycloak/keycloak_client_test.go | 4 +++- provider/provider.go | 13 ++++++++++++- provider/provider_test.go | 4 +++- 6 files changed, 37 insertions(+), 4 deletions(-) diff --git a/docs/index.md b/docs/index.md index 5a9c4cab3..db8312281 100644 --- a/docs/index.md +++ b/docs/index.md @@ -80,3 +80,4 @@ The following arguments are supported: - `tls_insecure_skip_verify` - (Optional) Allows ignoring insecure certificates when set to true. Defaults to false. Disabling security check is dangerous and should be avoided. - `root_ca_certificate` - (Optional) Allows x509 calls using an unknown CA certificate (for development purposes) - `base_path` - (Optional) The base path used for accessing the Keycloak REST API. Defaults to `/auth` +- `additional_headers` - (Optional) A map of custom headers to add to each requests, to work with proxy filtering requests without these headers for example. Defaults to an empty map. diff --git a/example/main.tf b/example/main.tf index 3cf6efc74..406f4732a 100644 --- a/example/main.tf +++ b/example/main.tf @@ -11,6 +11,9 @@ provider "keycloak" { client_id = "terraform" client_secret = "884e0f95-0f42-4a63-9b1f-94274655669e" url = "http://localhost:8080" + additional_headers = { + foo = "bar" + } } resource "keycloak_realm" "test" { diff --git a/keycloak/keycloak_client.go b/keycloak/keycloak_client.go index 1fdbc0cd3..4f41935be 100644 --- a/keycloak/keycloak_client.go +++ b/keycloak/keycloak_client.go @@ -27,6 +27,7 @@ type KeycloakClient struct { initialLogin bool userAgent string version *version.Version + additionalHeaders map[string]string } type ClientCredentials struct { @@ -45,7 +46,7 @@ const ( tokenUrl = "%s/realms/%s/protocol/openid-connect/token" ) -func NewKeycloakClient(url, basePath, clientId, clientSecret, realm, username, password string, initialLogin bool, clientTimeout int, caCert string, tlsInsecureSkipVerify bool, userAgent string) (*KeycloakClient, error) { +func NewKeycloakClient(url, basePath, clientId, clientSecret, realm, username, password string, initialLogin bool, clientTimeout int, caCert string, tlsInsecureSkipVerify bool, userAgent string, additionalHeaders map[string]string) (*KeycloakClient, error) { cookieJar, err := cookiejar.New(&cookiejar.Options{ PublicSuffixList: publicsuffix.List, }) @@ -94,6 +95,7 @@ func NewKeycloakClient(url, basePath, clientId, clientSecret, realm, username, p initialLogin: initialLogin, realm: realm, userAgent: userAgent, + additionalHeaders: additionalHeaders, } if keycloakClient.initialLogin { @@ -117,6 +119,10 @@ func (keycloakClient *KeycloakClient) login() error { return err } + for header, value := range keycloakClient.additionalHeaders { + accessTokenRequest.Header.Set(header, value) + } + accessTokenRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded") if keycloakClient.userAgent != "" { @@ -178,6 +184,10 @@ func (keycloakClient *KeycloakClient) refresh() error { return err } + for header, value := range keycloakClient.additionalHeaders { + refreshTokenRequest.Header.Set(header, value) + } + refreshTokenRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded") if keycloakClient.userAgent != "" { @@ -239,6 +249,10 @@ func (keycloakClient *KeycloakClient) addRequestHeaders(request *http.Request) { tokenType := keycloakClient.clientCredentials.TokenType accessToken := keycloakClient.clientCredentials.AccessToken + for header, value := range keycloakClient.additionalHeaders { + request.Header.Set(header, value) + } + request.Header.Set("Authorization", fmt.Sprintf("%s %s", tokenType, accessToken)) request.Header.Set("Accept", "application/json") diff --git a/keycloak/keycloak_client_test.go b/keycloak/keycloak_client_test.go index 174749da9..9dc9653fc 100644 --- a/keycloak/keycloak_client_test.go +++ b/keycloak/keycloak_client_test.go @@ -53,7 +53,9 @@ func TestAccKeycloakApiClientRefresh(t *testing.T) { t.Fatal("KEYCLOAK_CLIENT_TIMEOUT must be an integer") } - keycloakClient, err := NewKeycloakClient(os.Getenv("KEYCLOAK_URL"), "/auth", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), os.Getenv("KEYCLOAK_USER"), os.Getenv("KEYCLOAK_PASSWORD"), true, clientTimeout, "", false, "") + keycloakClient, err := NewKeycloakClient(os.Getenv("KEYCLOAK_URL"), "/auth", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), os.Getenv("KEYCLOAK_USER"), os.Getenv("KEYCLOAK_PASSWORD"), true, clientTimeout, "", false, "", map[string]string{ + "foo": "bar", + }) if err != nil { t.Fatalf("%s", err) } diff --git a/provider/provider.go b/provider/provider.go index 892434d09..25bcf4e18 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -159,6 +159,13 @@ func KeycloakProvider(client *keycloak.KeycloakClient) *schema.Provider { Type: schema.TypeString, Default: "/auth", }, + "additional_headers": { + Optional: true, + Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, }, } @@ -178,12 +185,16 @@ func KeycloakProvider(client *keycloak.KeycloakClient) *schema.Provider { clientTimeout := data.Get("client_timeout").(int) tlsInsecureSkipVerify := data.Get("tls_insecure_skip_verify").(bool) rootCaCertificate := data.Get("root_ca_certificate").(string) + additionalHeaders := make(map[string]string) + for k, v := range data.Get("additional_headers").(map[string]interface{}) { + additionalHeaders[k] = v.(string) + } var diags diag.Diagnostics userAgent := fmt.Sprintf("HashiCorp Terraform/%s (+https://www.terraform.io) Terraform Plugin SDK/%s", provider.TerraformVersion, meta.SDKVersionString()) - keycloakClient, err := keycloak.NewKeycloakClient(url, basePath, clientId, clientSecret, realm, username, password, initialLogin, clientTimeout, rootCaCertificate, tlsInsecureSkipVerify, userAgent) + keycloakClient, err := keycloak.NewKeycloakClient(url, basePath, clientId, clientSecret, realm, username, password, initialLogin, clientTimeout, rootCaCertificate, tlsInsecureSkipVerify, userAgent, additionalHeaders) if err != nil { diags = append(diags, diag.Diagnostic{ Severity: diag.Error, diff --git a/provider/provider_test.go b/provider/provider_test.go index b47723551..ea3970664 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -26,7 +26,9 @@ var requiredEnvironmentVariables = []string{ func init() { userAgent := fmt.Sprintf("HashiCorp Terraform/%s (+https://www.terraform.io) Terraform Plugin SDK/%s", schema.Provider{}.TerraformVersion, meta.SDKVersionString()) - keycloakClient, _ = keycloak.NewKeycloakClient(os.Getenv("KEYCLOAK_URL"), "/auth", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), "", "", true, 5, "", false, userAgent) + keycloakClient, _ = keycloak.NewKeycloakClient(os.Getenv("KEYCLOAK_URL"), "/auth", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), "", "", true, 5, "", false, userAgent, map[string]string{ + "foo": "bar", + }) testAccProvider = KeycloakProvider(keycloakClient) testAccProviderFactories = map[string]func() (*schema.Provider, error){ "keycloak": func() (*schema.Provider, error) {