Skip to content

Commit

Permalink
adds import support for keycloak_generic_client_role_mapper (#310)
Browse files Browse the repository at this point in the history
  • Loading branch information
javefang authored Jun 5, 2020
1 parent 0f9368e commit 44e0c53
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 6 deletions.
71 changes: 67 additions & 4 deletions docs/resources/keycloak_generic_client_role_mapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ the token or assertion. When `full_scope_allowed` is set to `false` for a
client, role scope mapping allows you to limit the roles that get declared
inside an access token for a client.

### Example Usage (Realm role)
### Example Usage (Realm Role to Client)

```hcl
resource "keycloak_realm" "realm" {
Expand Down Expand Up @@ -38,8 +38,7 @@ resource "keycloak_generic_client_role_mapper" "client_role_mapper" {
}
```

### Example Usage (Client role)

### Example Usage (Client Role to Client)

```hcl
resource "keycloak_realm" "realm" {
Expand Down Expand Up @@ -88,11 +87,75 @@ resource "keycloak_generic_client_role_mapper" "client_b_role_mapper" {
}
```

### Example Usage (Realm Role to Client Scope)

```hcl
resource "keycloak_realm" "realm" {
realm = "my-realm"
enabled = true
}
resource "keycloak_openid_client_scope" "client_scope" {
realm_id = keycloak_realm.realm.id
name = "my-client-scope"
}
resource "keycloak_role" "realm_role" {
realm_id = keycloak_realm.realm.id
name = "my-realm-role"
description = "My Realm Role"
}
resource "keycloak_generic_client_role_mapper" "client_role_mapper" {
realm_id = keycloak_realm.realm.id
client_scope_id = keycloak_openid_client_scope.client_scope.id
role_id = keycloak_role.realm_role.id
}
```

### Example Usage (Client Role to Client Scope)

```hcl
resource "keycloak_realm" "realm" {
realm = "my-realm"
enabled = true
}
resource "keycloak_openid_client" "client" {
realm_id = keycloak_realm.realm.id
client_id = "client"
name = "client"
enabled = true
access_type = "BEARER-ONLY"
}
resource "keycloak_role" "client_role" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.client.id
name = "my-client-role"
description = "My Client Role"
}
resource "keycloak_openid_client_scope" "client_scope" {
realm_id = keycloak_realm.realm.id
name = "my-client-scope"
}
resource "keycloak_generic_client_role_mapper" "client_b_role_mapper" {
realm_id = keycloak_realm.realm.id
client_scope_id = keycloak_client_scope.client_scope.id
role_id = keycloak_role.client_role.id
}
```

### Argument Reference

The following arugments are supported:

- `realm_id` - (Required) The realm this role mapper exists within
- `client_id` - (Required) The ID of the client this role mapper is created for
- `client_id` - (Optional) The ID of the client this role mapper is added to
- `client_scope_id` - (Optional) The ID of the client scope this role mapper is added to
- `role_id` - (Required) The ID of the role to be added to this role mapper

29 changes: 28 additions & 1 deletion provider/resource_keycloak_generic_client_role_mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
Expand All @@ -12,7 +13,9 @@ func resourceKeycloakGenericClientRoleMapper() *schema.Resource {
Create: resourceKeycloakGenericClientRoleMapperCreate,
Read: resourceKeycloakGenericClientRoleMapperRead,
Delete: resourceKeycloakGenericClientRoleMapperDelete,

Importer: &schema.ResourceImporter{
State: resourceKeycloakGenericClientRoleMapperImport,
},
Schema: map[string]*schema.Schema{
"realm_id": {
Type: schema.TypeString,
Expand Down Expand Up @@ -108,3 +111,27 @@ func resourceKeycloakGenericClientRoleMapperDelete(data *schema.ResourceData, me

return keycloakClient.DeleteRoleScopeMapping(realmId, clientId, clientScopeId, role)
}

func resourceKeycloakGenericClientRoleMapperImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")

if len(parts) != 6 {
return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/client/{{clientId}}/scope-mappings/{{roleClientId}}/{{roleId}}, {{realmId}}/client-scope/{{clientScopeId}}/scope-mappings/{{roleClientId}}/{{roleId}}")
}

parentResourceType := parts[1]
parentResourceId := parts[2]

d.Set("realm_id", parts[0])

if parentResourceType == "client" {
d.Set("client_id", parentResourceId)
} else if parentResourceType == "client-scope" {
d.Set("client_scope_id", parentResourceId)
} else {
return nil, fmt.Errorf("the associated parent resource must be either a client or a client-scope")
}

d.Set("role_id", parts[5])
return []*schema.ResourceData{d}, nil
}
66 changes: 65 additions & 1 deletion provider/resource_keycloak_generic_client_role_mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package provider

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
"testing"
)

func TestGenericRoleMapper_basic(t *testing.T) {
Expand All @@ -27,6 +28,32 @@ func TestGenericRoleMapper_basic(t *testing.T) {
})
}

func TestGenericRoleMapper_import(t *testing.T) {
realmName := "terraform-" + acctest.RandString(10)
parentClientName := "client1-" + acctest.RandString(10)
parentRoleName := "role-" + acctest.RandString(10)
childClientName := "client2-" + acctest.RandString(10)

resourceName := "keycloak_generic_client_role_mapper.child-client-with-parent-client-role"

resource.Test(t, resource.TestCase{
Providers: testAccProviders,
PreCheck: func() { testAccPreCheck(t) },
Steps: []resource.TestStep{
{
Config: testKeycloakGenericRoleMapping_basic(realmName, parentClientName, parentRoleName, childClientName),
Check: testAccCheckKeycloakScopeMappingExists(resourceName),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: getGenericRoleMapperId(resourceName),
},
},
})
}

func TestGenericRoleMapperClientScope_basic(t *testing.T) {
realmName := "terraform-" + acctest.RandString(10)
clientName := "client-" + acctest.RandString(10)
Expand All @@ -45,6 +72,32 @@ func TestGenericRoleMapperClientScope_basic(t *testing.T) {
})
}

func TestGenericRoleMapperClientScope_import(t *testing.T) {
realmName := "terraform-" + acctest.RandString(10)
clientName := "client-" + acctest.RandString(10)
roleName := "role-" + acctest.RandString(10)
clientScopeName := "clientscope-" + acctest.RandString(10)

resourceName := "keycloak_generic_client_role_mapper.clientscope-with-client-role"

resource.Test(t, resource.TestCase{
Providers: testAccProviders,
PreCheck: func() { testAccPreCheck(t) },
Steps: []resource.TestStep{
{
Config: testKeycloakGenericRoleMappingClientScope_basic(realmName, clientName, roleName, clientScopeName),
Check: testAccCheckKeycloakScopeMappingExists(resourceName),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: getGenericRoleMapperId(resourceName),
},
},
})
}

func TestGenericRoleMapper_createAfterManualDestroy(t *testing.T) {
var role = &keycloak.Role{}
var childClient = &keycloak.GenericClient{}
Expand Down Expand Up @@ -259,3 +312,14 @@ func getOpenidClientScopeFromState(s *terraform.State, resourceName string) (*ke

return client, nil
}

func getGenericRoleMapperId(resourceName string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return "", fmt.Errorf("resource not found: %s", resourceName)
}

return rs.Primary.ID, nil
}
}

0 comments on commit 44e0c53

Please sign in to comment.