Skip to content

Commit

Permalink
chore: misc improvements for extra_config attribute (#584)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrparkers authored Sep 3, 2021
1 parent 4e66a3e commit 25dd52b
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 347 deletions.
10 changes: 5 additions & 5 deletions docs/resources/openid_client.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ resource "keycloak_openid_client" "openid_client" {
]
login_theme = "keycloak"
extra_config = {
"key1" = "value1"
"key2" = "value2"
}
"key1" = "value1"
"key2" = "value2"
}
}
```

Expand Down Expand Up @@ -86,7 +86,7 @@ is set to `true`.
- `backchannel_logout_url` - (Optional) The URL that will cause the client to log itself out when a logout request is sent to this realm. If omitted, no logout request will be sent to the client is this case.
- `backchannel_logout_session_required` - (Optional) When `true`, a sid (session ID) claim will be included in the logout token when the backchannel logout URL is used. Defaults to `true`.
- `backchannel_logout_revoke_offline_sessions` - (Optional) Specifying whether a "revoke_offline_access" event is included in the Logout Token when the Backchannel Logout URL is used. Keycloak will revoke offline sessions when receiving a Logout Token with this event.
- `extra_config` - (Optional) A map of key/value pairs to add extra configuration attributes to this client. This can be used for custom attributes, or to add configuration attributes that is not yet supported by this Terraform provider. Use this attribute at your own risk, as s may conflict with top-level configuration attributes in future provider updates.
- `extra_config` - (Optional) A map of key/value pairs to add extra configuration attributes to this client. This can be used for custom attributes, or to add configuration attributes that are not yet supported by this Terraform provider. Use this attribute at your own risk, as it may conflict with top-level configuration attributes in future provider updates.

## Attributes Reference

Expand Down
62 changes: 62 additions & 0 deletions keycloak/extra_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package keycloak

import (
"encoding/json"
"reflect"
"strconv"
"strings"
)

func unmarshalExtraConfig(data []byte, reflectValue reflect.Value, extraConfig *map[string]interface{}) error {
err := json.Unmarshal(data, extraConfig)
if err != nil {
return err
}

for i := 0; i < reflectValue.NumField(); i++ {
structField := reflectValue.Type().Field(i)
jsonKey := strings.Split(structField.Tag.Get("json"), ",")[0]
if jsonKey != "-" {
configValue, ok := (*extraConfig)[jsonKey]
if ok {
field := reflectValue.FieldByName(structField.Name)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
field.SetString(configValue.(string))
} else if field.Kind() == reflect.Bool {
boolVal, err := strconv.ParseBool(configValue.(string))
if err == nil {
field.Set(reflect.ValueOf(KeycloakBoolQuoted(boolVal)))
}
}
delete(*extraConfig, jsonKey)
}
}
}
}

return nil
}

func marshalExtraConfig(reflectValue reflect.Value, extraConfig map[string]interface{}) ([]byte, error) {
out := map[string]interface{}{}

for k, v := range extraConfig {
out[k] = v
}

for i := 0; i < reflectValue.NumField(); i++ {
jsonKey := strings.Split(reflectValue.Type().Field(i).Tag.Get("json"), ",")[0]
if jsonKey != "-" {
field := reflectValue.Field(i)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
out[jsonKey] = field.String()
} else if field.Kind() == reflect.Bool {
out[jsonKey] = KeycloakBoolQuoted(field.Bool())
}
}
}
}
return json.Marshal(out)
}
65 changes: 8 additions & 57 deletions keycloak/identity_provider.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package keycloak

import (
"encoding/json"
"fmt"
"log"
"reflect"
"strconv"
"strings"
)

type IdentityProviderConfig struct {
Expand Down Expand Up @@ -69,60 +66,6 @@ type IdentityProvider struct {
Config *IdentityProviderConfig `json:"config"`
}

func (f *IdentityProviderConfig) UnmarshalJSON(data []byte) error {
f.ExtraConfig = map[string]interface{}{}
err := json.Unmarshal(data, &f.ExtraConfig)
if err != nil {
return err
}
v := reflect.ValueOf(f).Elem()
for i := 0; i < v.NumField(); i++ {
structField := v.Type().Field(i)
jsonKey := strings.Split(structField.Tag.Get("json"), ",")[0]
if jsonKey != "-" {
value, ok := f.ExtraConfig[jsonKey]
if ok {
field := v.FieldByName(structField.Name)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
field.SetString(value.(string))
} else if field.Kind() == reflect.Bool {
boolVal, err := strconv.ParseBool(value.(string))
if err == nil {
field.Set(reflect.ValueOf(KeycloakBoolQuoted(boolVal)))
}
}
delete(f.ExtraConfig, jsonKey)
}
}
}
}
return nil
}

func (f *IdentityProviderConfig) MarshalJSON() ([]byte, error) {
out := map[string]interface{}{}

for k, v := range f.ExtraConfig {
out[k] = v
}
v := reflect.ValueOf(f).Elem()
for i := 0; i < v.NumField(); i++ {
jsonKey := strings.Split(v.Type().Field(i).Tag.Get("json"), ",")[0]
if jsonKey != "-" {
field := v.Field(i)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
out[jsonKey] = field.String()
} else if field.Kind() == reflect.Bool {
out[jsonKey] = KeycloakBoolQuoted(field.Bool())
}
}
}
}
return json.Marshal(out)
}

func (keycloakClient *KeycloakClient) NewIdentityProvider(identityProvider *IdentityProvider) error {
log.Printf("[WARN] Realm: %s", identityProvider.Realm)
_, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/identity-provider/instances", identityProvider.Realm), identityProvider)
Expand Down Expand Up @@ -152,3 +95,11 @@ func (keycloakClient *KeycloakClient) UpdateIdentityProvider(identityProvider *I
func (keycloakClient *KeycloakClient) DeleteIdentityProvider(realm, alias string) error {
return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias), nil)
}

func (f *IdentityProviderConfig) UnmarshalJSON(data []byte) error {
return unmarshalExtraConfig(data, reflect.ValueOf(f).Elem(), &f.ExtraConfig)
}

func (f *IdentityProviderConfig) MarshalJSON() ([]byte, error) {
return marshalExtraConfig(reflect.ValueOf(f).Elem(), f.ExtraConfig)
}
53 changes: 2 additions & 51 deletions keycloak/identity_provider_mapper.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package keycloak

import (
"encoding/json"
"fmt"
"log"
"reflect"
"strconv"
"strings"
)

type IdentityProviderMapperConfig struct {
Expand Down Expand Up @@ -68,55 +65,9 @@ func (keycloakClient *KeycloakClient) DeleteIdentityProviderMapper(realm, alias,
}

func (f *IdentityProviderMapperConfig) UnmarshalJSON(data []byte) error {
f.ExtraConfig = map[string]interface{}{}
err := json.Unmarshal(data, &f.ExtraConfig)
if err != nil {
return err
}
v := reflect.ValueOf(f).Elem()
for i := 0; i < v.NumField(); i++ {
structField := v.Type().Field(i)
jsonKey := strings.Split(structField.Tag.Get("json"), ",")[0]
if jsonKey != "-" {
value, ok := f.ExtraConfig[jsonKey]
if ok {
field := v.FieldByName(structField.Name)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
field.SetString(value.(string))
} else if field.Kind() == reflect.Bool {
boolVal, err := strconv.ParseBool(value.(string))
if err == nil {
field.Set(reflect.ValueOf(KeycloakBoolQuoted(boolVal)))
}
}
delete(f.ExtraConfig, jsonKey)
}
}
}
}
return nil
return unmarshalExtraConfig(data, reflect.ValueOf(f).Elem(), &f.ExtraConfig)
}

func (f *IdentityProviderMapperConfig) MarshalJSON() ([]byte, error) {
out := map[string]interface{}{}

for k, v := range f.ExtraConfig {
out[k] = v
}
v := reflect.ValueOf(f).Elem()
for i := 0; i < v.NumField(); i++ {
jsonKey := strings.Split(v.Type().Field(i).Tag.Get("json"), ",")[0]
if jsonKey != "-" {
field := v.Field(i)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
out[jsonKey] = field.String()
} else if field.Kind() == reflect.Bool {
out[jsonKey] = KeycloakBoolQuoted(field.Bool())
}
}
}
}
return json.Marshal(out)
return marshalExtraConfig(reflect.ValueOf(f).Elem(), f.ExtraConfig)
}
22 changes: 19 additions & 3 deletions keycloak/keycloak_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"strings"
"time"

Expand All @@ -28,6 +29,7 @@ type KeycloakClient struct {
userAgent string
version *version.Version
additionalHeaders map[string]string
debug bool
}

type ClientCredentials struct {
Expand Down Expand Up @@ -109,6 +111,12 @@ func NewKeycloakClient(url, basePath, clientId, clientSecret, realm, username, p
}
}

if tfLog, ok := os.LookupEnv("TF_LOG"); ok {
if tfLog == "DEBUG" {
keycloakClient.debug = true
}
}

return &keycloakClient, nil
}

Expand Down Expand Up @@ -391,7 +399,7 @@ func (keycloakClient *KeycloakClient) sendRaw(path string, requestBody []byte) (
func (keycloakClient *KeycloakClient) post(path string, requestBody interface{}) ([]byte, string, error) {
resourceUrl := keycloakClient.baseUrl + apiUrl + path

payload, err := json.Marshal(requestBody)
payload, err := keycloakClient.marshal(requestBody)
if err != nil {
return nil, "", err
}
Expand All @@ -409,7 +417,7 @@ func (keycloakClient *KeycloakClient) post(path string, requestBody interface{})
func (keycloakClient *KeycloakClient) put(path string, requestBody interface{}) error {
resourceUrl := keycloakClient.baseUrl + apiUrl + path

payload, err := json.Marshal(requestBody)
payload, err := keycloakClient.marshal(requestBody)
if err != nil {
return err
}
Expand All @@ -433,7 +441,7 @@ func (keycloakClient *KeycloakClient) delete(path string, requestBody interface{
)

if requestBody != nil {
payload, err = json.Marshal(requestBody)
payload, err = keycloakClient.marshal(requestBody)
if err != nil {
return err
}
Expand All @@ -448,3 +456,11 @@ func (keycloakClient *KeycloakClient) delete(path string, requestBody interface{

return err
}

func (keycloakClient *KeycloakClient) marshal(requestBody interface{}) ([]byte, error) {
if keycloakClient.debug {
return json.MarshalIndent(requestBody, "", " ")
}

return json.Marshal(requestBody)
}
53 changes: 2 additions & 51 deletions keycloak/openid_client.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package keycloak

import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
)

type OpenidClientRole struct {
Expand Down Expand Up @@ -354,55 +351,9 @@ func (keycloakClient *KeycloakClient) DetachOpenidClientOptionalScopes(realmId,
}

func (f *OpenidClientAttributes) UnmarshalJSON(data []byte) error {
f.ExtraConfig = map[string]interface{}{}
err := json.Unmarshal(data, &f.ExtraConfig)
if err != nil {
return err
}
v := reflect.ValueOf(f).Elem()
for i := 0; i < v.NumField(); i++ {
structField := v.Type().Field(i)
jsonKey := strings.Split(structField.Tag.Get("json"), ",")[0]
if jsonKey != "-" {
value, ok := f.ExtraConfig[jsonKey]
if ok {
field := v.FieldByName(structField.Name)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
field.SetString(value.(string))
} else if field.Kind() == reflect.Bool {
boolVal, err := strconv.ParseBool(value.(string))
if err == nil {
field.Set(reflect.ValueOf(KeycloakBoolQuoted(boolVal)))
}
}
delete(f.ExtraConfig, jsonKey)
}
}
}
}
return nil
return unmarshalExtraConfig(data, reflect.ValueOf(f).Elem(), &f.ExtraConfig)
}

func (f *OpenidClientAttributes) MarshalJSON() ([]byte, error) {
out := map[string]interface{}{}

for k, v := range f.ExtraConfig {
out[k] = v
}
v := reflect.ValueOf(f).Elem()
for i := 0; i < v.NumField(); i++ {
jsonKey := strings.Split(v.Type().Field(i).Tag.Get("json"), ",")[0]
if jsonKey != "-" {
field := v.Field(i)
if field.IsValid() && field.CanSet() {
if field.Kind() == reflect.String {
out[jsonKey] = field.String()
} else if field.Kind() == reflect.Bool {
out[jsonKey] = KeycloakBoolQuoted(field.Bool())
}
}
}
}
return json.Marshal(out)
return marshalExtraConfig(reflect.ValueOf(f).Elem(), f.ExtraConfig)
}
Loading

0 comments on commit 25dd52b

Please sign in to comment.