-
Notifications
You must be signed in to change notification settings - Fork 324
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
resource to enable the token exchange idp permission (#318)
* resource to enable the token excahnge idp permission + auto create of client policy * fmt * Update provider/resource_keycloak_identity_provider_token_exchange_scope_permission.go Co-authored-by: Michael Parker <michael@parker.gg> * improved docs+ IsError409 helper method + better policy_type validation method + improved policy name creator logic * fmt Co-authored-by: Tom Rutsaert <tom.rutsaert@axians.com> Co-authored-by: Michael Parker <michael@parker.gg>
- Loading branch information
1 parent
6e58f05
commit 731c4cc
Showing
8 changed files
with
1,006 additions
and
64 deletions.
There are no files selected for viewing
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
88 changes: 88 additions & 0 deletions
88
docs/resources/keycloak_identity_provider_token_exchange_scope_permission.md
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,88 @@ | ||
# keycloak_identity_provider_token_exchange_scope_permission | ||
|
||
Allows you to manage Identity Provider "Token exchange" Scope Based Permissions. | ||
|
||
This is part of a preview keycloak feature. You need to enable this feature to be able to use this resource. | ||
More information about enabling the preview feature can be found here: https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange | ||
|
||
When enabling Identity Provider Permissions, Keycloak does several things automatically: | ||
1. Enable Authorization on build-in realm-management client | ||
1. Create a "token-exchange" scope | ||
1. Create a resource representing the identity provider | ||
1. Create a scope based permission for the "token-exchange" scope and identity provider resource | ||
|
||
The only thing that is missing is a policy set on the permission. | ||
As the policy lives within the context of the realm-management client, you cannot create a policy resource and link to from with your _.tf_ file. This would also cause an implicit cycle dependency. | ||
Thus, the only way to manage this in terraform is to create and manage the policy internally from within this terraform resource itself. | ||
At the moment only a client policy type is supported. The client policy will automatically be created for the clients parameter. | ||
|
||
### Example Usage | ||
|
||
```hcl | ||
resource "keycloak_realm" "token-exchange_realm" { | ||
realm = "token-exchange_destination_realm" | ||
enabled = true | ||
} | ||
resource keycloak_oidc_identity_provider token-exchange_my_oidc_idp { | ||
realm = keycloak_realm.token-exchange_realm.id | ||
alias = "myIdp" | ||
authorization_url = "http://localhost:8080/auth/realms/someRealm/protocol/openid-connect/auth" | ||
token_url = "http://localhost:8080/auth/realms/someRealm/protocol/openid-connect/token" | ||
client_id = "clientId" | ||
client_secret = "secret" | ||
default_scopes = "openid" | ||
} | ||
resource "keycloak_openid_client" "token-exchange_webapp_client" { | ||
realm_id = keycloak_realm.token-exchange_realm.id | ||
name = "webapp_client" | ||
client_id = "webapp_client" | ||
client_secret = "secret" | ||
description = "a webapp client on the destination realm" | ||
access_type = "CONFIDENTIAL" | ||
standard_flow_enabled = true | ||
valid_redirect_uris = [ | ||
"http://localhost:8080/*", | ||
] | ||
} | ||
//relevant part | ||
resource "keycloak_identity_provider_token_exchange_scope_permission" "oidc_idp_permission" { | ||
realm_id = keycloak_realm.token-exchange_realm.id | ||
provider_alias = keycloak_oidc_identity_provider.token-exchange_my_oidc_idp.alias | ||
policy_type = "client" | ||
clients = [keycloak_openid_client.token-exchange_webapp_client.id] | ||
} | ||
``` | ||
|
||
### Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
- `realm_id` - (Required) The realm this group exists in. | ||
- `provider_alias` - (Required) Alias of the identity provider. | ||
- `policy_type` - (Optional) Defaults to "client" This is also the only value policy type supported by this provider. | ||
- `clients` - (Required) Ids of the clients for which a policy will be created and set on scope based token exchange permission. | ||
|
||
### Attributes Reference | ||
|
||
In addition to the arguments listed above, the following computed attributes are exported: | ||
|
||
- `policy_id` - Policy id that will be set on the scope based token exchange permission automatically created by enabling permissions on the reference identity provider. | ||
- `authorization_resource_server_id` - Resource server id representing the realm management client on which this permission is managed. | ||
- `authorization_idp_resource_id` - Resource id representing the identity provider, this automatically created by keycloak. | ||
- `authorization_token_exchange_scope_permission_id` - Permission id representing the Permission with scope 'Token Exchange' and the resource 'authorization_idp_resource_id', this automatically created by keycloak, the policy id will be set on this permission. | ||
|
||
|
||
### Import | ||
|
||
This resource can be imported using the format | ||
`{{realm_id}}/{{provider_alias}}`, where `provider_alias` is the alias that you assign to the identity provider upon creation. | ||
|
||
Example: | ||
|
||
```bash | ||
$ terraform import keycloak_identity_provider_token_exchange_scope_permission.my_permission my-realm/my_idp | ||
``` | ||
|
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,57 @@ | ||
resource "keycloak_realm" "token-exchange_source_realm" { | ||
realm = "token-exchange_source_realm" | ||
enabled = true | ||
} | ||
|
||
resource "keycloak_openid_client" "token-exchange_destination_client" { | ||
realm_id = keycloak_realm.token-exchange_source_realm.id | ||
name = "destination_client" | ||
client_id = "destination_client" | ||
client_secret = "secret" | ||
description = "a client used by the destination realm" | ||
access_type = "CONFIDENTIAL" | ||
standard_flow_enabled = true | ||
valid_redirect_uris = [ | ||
"http://localhost:8080/*", | ||
] | ||
} | ||
|
||
resource "keycloak_realm" "token-exchange_destination_realm" { | ||
realm = "token-exchange_destination_realm" | ||
enabled = true | ||
} | ||
|
||
resource keycloak_oidc_identity_provider token-exchange_source_oidc_idp { | ||
realm = keycloak_realm.token-exchange_destination_realm.id | ||
alias = "source" | ||
authorization_url = "http://localhost:8080/auth/realms/${keycloak_realm.token-exchange_source_realm.id}/protocol/openid-connect/auth" | ||
token_url = "http://localhost:8080/auth/realms/${keycloak_realm.token-exchange_source_realm.id}/protocol/openid-connect/token" | ||
user_info_url = "http://localhost:8080/auth/realms/${keycloak_realm.token-exchange_source_realm.id}/protocol/openid-connect/userinfo" | ||
jwks_url = "http://localhost:8080/auth/realms/${keycloak_realm.token-exchange_source_realm.id}/protocol/openid-connect/certs" | ||
validate_signature = true | ||
client_id = keycloak_openid_client.token-exchange_destination_client.client_id | ||
client_secret = keycloak_openid_client.token-exchange_destination_client.client_secret | ||
default_scopes = "openid" | ||
} | ||
|
||
resource "keycloak_openid_client" "token-exchange_webapp_client" { | ||
realm_id = keycloak_realm.token-exchange_destination_realm.id | ||
name = "webapp_client" | ||
client_id = "webapp_client" | ||
client_secret = "secret" | ||
description = "a webapp client on the destination realm" | ||
access_type = "CONFIDENTIAL" | ||
standard_flow_enabled = true | ||
valid_redirect_uris = [ | ||
"http://localhost:8080/*", | ||
] | ||
} | ||
|
||
//token exchange feature enabler | ||
resource "keycloak_identity_provider_token_exchange_scope_permission" "source_oidc_idp_permission" { | ||
realm_id = keycloak_realm.token-exchange_destination_realm.id | ||
provider_alias = keycloak_oidc_identity_provider.token-exchange_source_oidc_idp.alias | ||
policy_type = "client" | ||
clients = [keycloak_openid_client.token-exchange_webapp_client.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,46 @@ | ||
package keycloak | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
type IdentityProviderPermissionsInput struct { | ||
Enabled bool `json:"enabled"` | ||
} | ||
|
||
type IdentityProviderPermissions struct { | ||
RealmId string `json:"-"` | ||
ProviderAlias string `json:"-"` | ||
Enabled bool `json:"enabled"` | ||
Resource string `json:"resource"` | ||
ScopePermissions map[string]interface{} `json:"scopePermissions"` | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) EnableIdentityProviderPermissions(realmId, providerAlias string) error { | ||
return keycloakClient.put(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/management/permissions", realmId, providerAlias), IdentityProviderPermissionsInput{Enabled: true}) | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) DisableIdentityProviderPermissions(realmId, providerAlias string) error { | ||
return keycloakClient.put(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/management/permissions", realmId, providerAlias), IdentityProviderPermissionsInput{Enabled: false}) | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) GetIdentityProviderPermissions(realmId, providerAlias string) (*IdentityProviderPermissions, error) { | ||
var identityProviderPermissions IdentityProviderPermissions | ||
identityProviderPermissions.RealmId = realmId | ||
identityProviderPermissions.ProviderAlias = providerAlias | ||
|
||
err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/management/permissions", realmId, providerAlias), &identityProviderPermissions, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &identityProviderPermissions, nil | ||
} | ||
|
||
func (identityProviderPermissions *IdentityProviderPermissions) GetTokenExchangeScopedPermissionId() (string, error) { | ||
if identityProviderPermissions.Enabled { | ||
return identityProviderPermissions.ScopePermissions["token-exchange"].(string), nil | ||
} else { | ||
return "", fmt.Errorf("identity provider permissions are not enabled, thus can not return the linked 'token-exchange' scope based permission") | ||
} | ||
} |
Oops, something went wrong.