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

Custom Identity Provider with extra custom config #135

Closed
tomrutsaert opened this issue Jul 17, 2019 · 4 comments
Closed

Custom Identity Provider with extra custom config #135

tomrutsaert opened this issue Jul 17, 2019 · 4 comments

Comments

@tomrutsaert
Copy link
Contributor

We have a custom oidc identity provider with custom config.
I would like to add this extra config to this terraform keycloak provider.
I do not how to go forward with this.

Do I change the IdentityProvider implementation to change IdentityProviderConfig struct to be just a map[string]interface{} where i do a mapping per field so that the have the correct json key?
for example:

func getOidcIdentityProviderFromData(data *schema.ResourceData) (*keycloak.IdentityProvider, error) {
	rec, _ := getIdentityProviderFromData(data)
	rec.ProviderId = "oidc"

	config := make(map[string]interface{})
	if v, ok := data.GetOk("config"); ok {
		for key, value := range v.(map[string]interface{}) {
			if key == "backchannel_supported" {
				config["backchannelSupported"] = keycloak.KeycloakBoolQuoted(value.(bool))
			}else if key == "jwks_url" {
				config["useJwksUrl"] = keycloak.KeycloakBoolQuoted(true)
				config["jwksUrl"] = value.(string)

			}else if ....	{
	                      .....
			}else{
				config[key] = value.(string)  // all extra config
			}
		}
	}
	rec.Config = config

Or do I create a CustomIdentityProvider struct which has the same methods as IdentityProvider, but where all config parameters are part of a map[string]interface{}
I still would have to map every field like in the solution above.

Or do you have another suggestion?

@tomrutsaert
Copy link
Contributor Author

tomrutsaert commented Jul 17, 2019

The solution might be in writing a custom Marshal and Unmarshal method, where additional config will come from an extra_config field in the idp resource

func (f *IdentityProviderConfig) UnmarshalJSON(data []byte) error {
	f.ExtraConfig = map[string]interface{}{}
	err := json.Unmarshal(data, &f.ExtraConfig)
	if err != nil {
		return err
	}
	knownkey, ok := f.ExtraConfig["knownkey"].(string)
	if !ok {
		return errors.New("knownkey must exist and be a string")
	}
	f.KnownKey = knownkey
	delete(f.ExtraConfig, "knownkey")
	return nil
}

func (f *IdentityProviderConfig) MarshalJSON() ([]byte, error) {
	out := map[string]interface{}{}
	for k, v := range f.ExtraConfig {
		out[k] = v
	}
	out["knownkey"] = f.Knownkey
	return json.Marshal(out)
}

something like this

@mrparkers
Copy link
Contributor

I like the idea of the extra_config field, although I don't actually use identity providers in Keycloak so I am not sure how valuable my opinion is.

@AndrewChubatiuk implemented most (if not all) of this, so I'd defer to his opinion or anyone else who actually uses this. Any thoughts here?

@AndrewChubatiuk
Copy link
Contributor

AndrewChubatiuk commented Jul 18, 2019

@mrparkers @tomrutsaert
I like idea of having one keycloak_identity_provider resource for all types of providers with validation schemas for config attribute map for all identity provider types except custom. And in this case IdentityProviderConfig struct can be replaced with map[string]interface

@tomrutsaert
Copy link
Contributor Author

Keep in mind, that most custom implementations will build upon or extend an existing identity provider type, and thus also want the those existing identity provider attributes with validation.
Therefor I went with the extra_config within config. I have implemented everything in identity_provider built only extended the resource_keyclaok_oidc_identity_provider
It should be minimal effort to do the same for resource_keycloak_saml_identity_provider.
(I did not do the saml part, because making a working test would take time)
@mrparkers and @AndrewChubatiuk Please take a look at PR: #137

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants