-
Notifications
You must be signed in to change notification settings - Fork 307
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new resources: keycloak_identity_provider and mappers (#92)
- Loading branch information
1 parent
4e09fae
commit e899c32
Showing
22 changed files
with
3,232 additions
and
228 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package keycloak | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
) | ||
|
||
type IdentityProviderConfig struct { | ||
Key string `json:"key,omitempty"` | ||
HostIp string `json:"hostIp,omitempty"` | ||
UseJwksUrl KeycloakBoolQuoted `json:"useJwksUrl,omitempty"` | ||
ClientId string `json:"clientId,omitempty"` | ||
ClientSecret string `json:"clientSecret,omitempty"` | ||
DisableUserInfo KeycloakBoolQuoted `json:"disableUserInfo"` | ||
HideOnLoginPage KeycloakBoolQuoted `json:"hideOnLoginPage"` | ||
NameIDPolicyFormat string `json:"nameIDPolicyFormat,omitempty"` | ||
SingleLogoutServiceUrl string `json:"singleLogoutServiceUrl,omitempty"` | ||
SingleSignOnServiceUrl string `json:"singleSignOnServiceUrl,omitempty"` | ||
SigningCertificate string `json:"signingCertificate,omitempty"` | ||
SignatureAlgorithm string `json:"signatureAlgorithm,omitempty"` | ||
XmlSignKeyInfoKeyNameTransformer string `json:"xmlSignKeyInfoKeyNameTransformer,omitempty"` | ||
PostBindingAuthnRequest KeycloakBoolQuoted `json:"postBindingAuthnRequest,omitempty"` | ||
PostBindingResponse KeycloakBoolQuoted `json:"postBindingResponse,omitempty"` | ||
PostBindingLogout KeycloakBoolQuoted `json:"postBindingLogout,omitempty"` | ||
ForceAuthn KeycloakBoolQuoted `json:"forceAuthn,omitempty"` | ||
WantAuthnRequestsSigned KeycloakBoolQuoted `json:"wantAuthnRequestsSigned,omitempty"` | ||
WantAssertionsSigned KeycloakBoolQuoted `json:"wantAssertionsSigned,omitempty"` | ||
WantAssertionsEncrypted KeycloakBoolQuoted `json:"wantAssertionsEncrypted,omitempty"` | ||
BackchannelSupported KeycloakBoolQuoted `json:"backchannelSupported,omitempty"` | ||
ValidateSignature KeycloakBoolQuoted `json:"validateSignature,omitempty"` | ||
AuthorizationUrl string `json:"authorizationUrl,omitempty"` | ||
TokenUrl string `json:"tokenUrl,omitempty"` | ||
LoginHint string `json:"loginHint,omitempty"` | ||
UILocales KeycloakBoolQuoted `json:"uiLocales,omitempty"` | ||
} | ||
|
||
type IdentityProvider struct { | ||
Realm string `json:"-"` | ||
InternalId string `json:"internalId,omitempty"` | ||
Alias string `json:"alias"` | ||
DisplayName string `json:"displayName"` | ||
ProviderId string `json:"providerId"` | ||
Enabled bool `json:"enabled"` | ||
StoreToken bool `json:"storeToken"` | ||
AddReadTokenRoleOnCreate bool `json:"addReadTokenRoleOnCreate"` | ||
AuthenticateByDefault bool `json:"authenticateByDefault"` | ||
LinkOnly bool `json:"linkOnly"` | ||
TrustEmail bool `json:"trustEmail"` | ||
FirstBrokerLoginFlowAlias string `json:"firstBrokerLoginFlowAlias"` | ||
PostBrokerLoginFlowAlias string `json:"postBrokerLoginFlowAlias"` | ||
Config *IdentityProviderConfig `json:"config"` | ||
} | ||
|
||
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) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) GetIdentityProvider(realm, alias string) (*IdentityProvider, error) { | ||
var identityProvider IdentityProvider | ||
identityProvider.Realm = realm | ||
|
||
err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias), &identityProvider) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &identityProvider, nil | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) UpdateIdentityProvider(identityProvider *IdentityProvider) error { | ||
return keycloakClient.put(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", identityProvider.Realm, identityProvider.Alias), identityProvider) | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) DeleteIdentityProvider(realm, alias string) error { | ||
return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package keycloak | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
) | ||
|
||
type IdentityProviderMapperConfig struct { | ||
UserAttribute string `json:"user.attribute,omitempty"` | ||
Claim string `json:"claim,omitempty"` | ||
ClaimValue string `json:"claim.value,omitempty"` | ||
HardcodedAttribute string `json:"attribute,omitempty"` | ||
Attribute string `json:"attribute.name,omitempty"` | ||
AttributeValue string `json:"attribute.value,omitempty"` | ||
AttributeFriendlyName string `json:"attribute.friendly.name,omitempty"` | ||
Template string `json:"template,omitempty"` | ||
Role string `json:"role,omitempty"` | ||
} | ||
|
||
type IdentityProviderMapper struct { | ||
Realm string `json:"-"` | ||
Provider string `json:"-"` | ||
Id string `json:"id,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
IdentityProviderAlias string `json:"identityProviderAlias,omitempty"` | ||
IdentityProviderMapper string `json:"identityProviderMapper,omitempty"` | ||
Config *IdentityProviderMapperConfig `json:"config,omitempty"` | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) NewIdentityProviderMapper(identityProviderMapper *IdentityProviderMapper) error { | ||
log.Printf("[WARN] Realm: %s", identityProviderMapper.Realm) | ||
location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers", identityProviderMapper.Realm, identityProviderMapper.IdentityProviderAlias), identityProviderMapper) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
identityProviderMapper.Id = getIdFromLocationHeader(location) | ||
|
||
return nil | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) GetIdentityProviderMapper(realm, alias, id string) (*IdentityProviderMapper, error) { | ||
var identityProviderMapper IdentityProviderMapper | ||
identityProviderMapper.Realm = realm | ||
identityProviderMapper.IdentityProviderAlias = alias | ||
|
||
err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", realm, alias, id), &identityProviderMapper) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &identityProviderMapper, nil | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) UpdateIdentityProviderMapper(identityProviderMapper *IdentityProviderMapper) error { | ||
return keycloakClient.put(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", identityProviderMapper.Realm, identityProviderMapper.IdentityProviderAlias, identityProviderMapper.Id), identityProviderMapper) | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) DeleteIdentityProviderMapper(realm, alias, id string) error { | ||
return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", realm, alias, id)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package provider | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/mrparkers/terraform-provider-keycloak/keycloak" | ||
"strings" | ||
) | ||
|
||
type identityProviderDataGetterFunc func(data *schema.ResourceData) (*keycloak.IdentityProvider, error) | ||
type identityProviderDataSetterFunc func(data *schema.ResourceData, identityProvider *keycloak.IdentityProvider) error | ||
|
||
func resourceKeycloakIdentityProvider() *schema.Resource { | ||
return &schema.Resource{ | ||
Delete: resourceKeycloakIdentityProviderDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: resourceKeycloakIdentityProviderImport, | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"alias": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Description: "The alias uniquely identifies an identity provider and it is also used to build the redirect uri.", | ||
}, | ||
"realm": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Description: "Realm Name", | ||
}, | ||
"internal_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Description: "Internal Identity Provider Id", | ||
}, | ||
"display_name": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Default: "", | ||
Description: "Friendly name for Identity Providers.", | ||
}, | ||
"enabled": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: true, | ||
Description: "Enable/disable this identity provider.", | ||
}, | ||
"store_token": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: true, | ||
Description: "Enable/disable if tokens must be stored after authenticating users.", | ||
}, | ||
"add_read_token_role_on_create": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
ForceNew: true, | ||
Description: "Enable/disable if new users can read any stored tokens. This assigns the broker.read-token role.", | ||
}, | ||
"authenticate_by_default": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
Description: "Enable/disable authenticate users by default.", | ||
}, | ||
"link_only": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
Description: "If true, users cannot log in through this provider. They can only link to this provider. This is useful if you don't want to allow login from the provider, but want to integrate with a provider", | ||
}, | ||
"trust_email": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
Description: "If enabled then email provided by this provider is not verified even if verification is enabled for the realm.", | ||
}, | ||
"first_broker_login_flow_alias": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Default: "first broker login", | ||
Description: "Alias of authentication flow, which is triggered after first login with this identity provider. Term 'First Login' means that there is not yet existing Keycloak account linked with the authenticated identity provider account.", | ||
}, | ||
"post_broker_login_flow_alias": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Default: "", | ||
Description: "Alias of authentication flow, which is triggered after each login with this identity provider. Useful if you want additional verification of each user authenticated with this identity provider (for example OTP). Leave this empty if you don't want any additional authenticators to be triggered after login with this identity provider. Also note, that authenticator implementations must assume that user is already set in ClientSession as identity provider already set it.", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func getIdentityProviderFromData(data *schema.ResourceData) (*keycloak.IdentityProvider, error) { | ||
rec := &keycloak.IdentityProvider{ | ||
Realm: data.Get("realm").(string), | ||
Alias: data.Get("alias").(string), | ||
DisplayName: data.Get("display_name").(string), | ||
Enabled: data.Get("enabled").(bool), | ||
StoreToken: data.Get("store_token").(bool), | ||
AddReadTokenRoleOnCreate: data.Get("add_read_token_role_on_create").(bool), | ||
AuthenticateByDefault: data.Get("authenticate_by_default").(bool), | ||
LinkOnly: data.Get("link_only").(bool), | ||
TrustEmail: data.Get("trust_email").(bool), | ||
FirstBrokerLoginFlowAlias: data.Get("first_broker_login_flow_alias").(string), | ||
PostBrokerLoginFlowAlias: data.Get("post_broker_login_flow_alias").(string), | ||
InternalId: data.Get("internal_id").(string), | ||
} | ||
return rec, nil | ||
} | ||
|
||
func setIdentityProviderData(data *schema.ResourceData, identityProvider *keycloak.IdentityProvider) error { | ||
data.SetId(identityProvider.Alias) | ||
data.Set("internal_id", identityProvider.InternalId) | ||
data.Set("realm", identityProvider.Realm) | ||
data.Set("alias", identityProvider.Alias) | ||
data.Set("display_name", identityProvider.DisplayName) | ||
data.Set("enabled", identityProvider.Enabled) | ||
data.Set("store_token", identityProvider.StoreToken) | ||
data.Set("add_read_token_role_on_create", identityProvider.AddReadTokenRoleOnCreate) | ||
data.Set("authenticate_by_default", identityProvider.AuthenticateByDefault) | ||
data.Set("link_only", identityProvider.LinkOnly) | ||
data.Set("trust_email", identityProvider.TrustEmail) | ||
data.Set("first_broker_login_flow_alias", identityProvider.FirstBrokerLoginFlowAlias) | ||
data.Set("post_broker_login_flow_alias", identityProvider.PostBrokerLoginFlowAlias) | ||
return nil | ||
} | ||
|
||
func resourceKeycloakIdentityProviderDelete(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
|
||
realm := data.Get("realm").(string) | ||
alias := data.Get("alias").(string) | ||
|
||
return keycloakClient.DeleteIdentityProvider(realm, alias) | ||
} | ||
|
||
func resourceKeycloakIdentityProviderImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { | ||
parts := strings.Split(d.Id(), "/") | ||
|
||
if len(parts) != 2 { | ||
return nil, fmt.Errorf("Invalid import. Supported import formats: {{realm}}/{{identityProviderAlias}}") | ||
} | ||
|
||
d.Set("realm", parts[0]) | ||
d.SetId(parts[1]) | ||
|
||
return []*schema.ResourceData{d}, nil | ||
} | ||
|
||
func resourceKeycloakIdentityProviderCreate(getIdentityProviderFromData identityProviderDataGetterFunc, setDataFromIdentityProvider identityProviderDataSetterFunc) func(data *schema.ResourceData, meta interface{}) error { | ||
return func(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
identityProvider, err := getIdentityProviderFromData(data) | ||
if err = keycloakClient.NewIdentityProvider(identityProvider); err != nil { | ||
return err | ||
} | ||
if err = setDataFromIdentityProvider(data, identityProvider); err != nil { | ||
return err | ||
} | ||
return resourceKeycloakIdentityProviderRead(setDataFromIdentityProvider)(data, meta) | ||
} | ||
} | ||
|
||
func resourceKeycloakIdentityProviderRead(setDataFromIdentityProvider identityProviderDataSetterFunc) func(data *schema.ResourceData, meta interface{}) error { | ||
return func(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
realm := data.Get("realm").(string) | ||
alias := data.Get("alias").(string) | ||
identityProvider, err := keycloakClient.GetIdentityProvider(realm, alias) | ||
if err != nil { | ||
return handleNotFoundError(err, data) | ||
} | ||
if err = setDataFromIdentityProvider(data, identityProvider); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
func resourceKeycloakIdentityProviderUpdate(getIdentityProviderFromData identityProviderDataGetterFunc, setDataFromIdentityProvider identityProviderDataSetterFunc) func(data *schema.ResourceData, meta interface{}) error { | ||
return func(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
identityProvider, err := getIdentityProviderFromData(data) | ||
if err = keycloakClient.UpdateIdentityProvider(identityProvider); err != nil { | ||
return err | ||
} | ||
if err = setDataFromIdentityProvider(data, identityProvider); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
} |
Oops, something went wrong.