-
Notifications
You must be signed in to change notification settings - Fork 330
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new resource: resource_keycloak_openid_client_service_account_realm_r…
…ole (#202)
- Loading branch information
1 parent
6c8bf69
commit 57d19b8
Showing
4 changed files
with
362 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package keycloak | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
type OpenidClientServiceAccountRealmRole struct { | ||
Id string `json:"id"` | ||
RealmId string `json:"-"` | ||
ServiceAccountUserId string `json:"-"` | ||
Name string `json:"name,omitempty"` | ||
Description string `json:"description"` | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRealmRole(serviceAccountRole *OpenidClientServiceAccountRealmRole) error { | ||
serviceAccountRoles := []OpenidClientServiceAccountRealmRole{*serviceAccountRole} | ||
|
||
_, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/users/%s/role-mappings/realm", serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId), serviceAccountRoles) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRealmRole(realm, serviceAccountUserId, roleId string) error { | ||
serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRealmRole(realm, serviceAccountUserId, roleId) | ||
if err != nil { | ||
return err | ||
} | ||
serviceAccountRoles := []OpenidClientServiceAccountRealmRole{*serviceAccountRole} | ||
err = keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/realm", realm, serviceAccountUserId), &serviceAccountRoles) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRealmRole(realm, serviceAccountUserId, roleId string) (*OpenidClientServiceAccountRealmRole, error) { | ||
serviceAccountRoles := []OpenidClientServiceAccountRealmRole{ | ||
{ | ||
Id: roleId, | ||
RealmId: realm, | ||
ServiceAccountUserId: serviceAccountUserId, | ||
}, | ||
} | ||
err := keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s/role-mappings/realm", realm, serviceAccountUserId), &serviceAccountRoles, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
for _, serviceAccountRole := range serviceAccountRoles { | ||
if serviceAccountRole.Id == roleId { | ||
serviceAccountRole.RealmId = realm | ||
serviceAccountRole.ServiceAccountUserId = serviceAccountUserId | ||
return &serviceAccountRole, nil | ||
} | ||
} | ||
return &OpenidClientServiceAccountRealmRole{}, nil | ||
} |
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
125 changes: 125 additions & 0 deletions
125
provider/resource_keycloak_openid_client_service_account_realm_role.go
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,125 @@ | ||
package provider | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/mrparkers/terraform-provider-keycloak/keycloak" | ||
"strings" | ||
) | ||
|
||
func resourceKeycloakOpenidClientServiceAccountRealmRole() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceKeycloakOpenidClientServiceAccountRealmRoleCreate, | ||
Read: resourceKeycloakOpenidClientServiceAccountRealmRoleRead, | ||
Delete: resourceKeycloakOpenidClientServiceAccountRealmRoleDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: resourceKeycloakOpenidClientServiceAccountRealmRoleImport, | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"service_account_user_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"realm_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"role": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func getOpenidClientServiceAccountRealmRoleFromData(data *schema.ResourceData, keycloakClient *keycloak.KeycloakClient) (*keycloak.OpenidClientServiceAccountRealmRole, error) { | ||
roleName := data.Get("role").(string) | ||
realmId := data.Get("realm_id").(string) | ||
serviceAccountRoleId := data.Get("service_account_user_id").(string) | ||
|
||
role, err := keycloakClient.GetRoleByName(realmId, "", roleName) | ||
if err != nil { | ||
if keycloak.ErrorIs404(err) { | ||
role = &keycloak.Role{Id: ""} | ||
} else { | ||
return nil, err | ||
} | ||
} | ||
|
||
return &keycloak.OpenidClientServiceAccountRealmRole{ | ||
Id: role.Id, | ||
Name: roleName, | ||
RealmId: realmId, | ||
ServiceAccountUserId: serviceAccountRoleId, | ||
}, nil | ||
} | ||
|
||
func setOpenidClientServiceAccountRealmRoleData(data *schema.ResourceData, serviceAccountRole *keycloak.OpenidClientServiceAccountRealmRole) { | ||
data.SetId(fmt.Sprintf("%s/%s", serviceAccountRole.ServiceAccountUserId, serviceAccountRole.Id)) | ||
data.Set("realm_id", serviceAccountRole.RealmId) | ||
data.Set("service_account_user_id", serviceAccountRole.ServiceAccountUserId) | ||
data.Set("role", serviceAccountRole.Name) | ||
} | ||
|
||
func resourceKeycloakOpenidClientServiceAccountRealmRoleCreate(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
serviceAccountRole, err := getOpenidClientServiceAccountRealmRoleFromData(data, keycloakClient) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = keycloakClient.NewOpenidClientServiceAccountRealmRole(serviceAccountRole) | ||
if err != nil { | ||
return err | ||
} | ||
setOpenidClientServiceAccountRealmRoleData(data, serviceAccountRole) | ||
return resourceKeycloakOpenidClientServiceAccountRealmRoleRead(data, meta) | ||
} | ||
|
||
func resourceKeycloakOpenidClientServiceAccountRealmRoleRead(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
|
||
serviceAccountRole, err := getOpenidClientServiceAccountRealmRoleFromData(data, keycloakClient) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
serviceAccountRole, err = keycloakClient.GetOpenidClientServiceAccountRealmRole(serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.Id) | ||
if err != nil { | ||
return handleNotFoundError(err, data) | ||
} | ||
|
||
setOpenidClientServiceAccountRealmRoleData(data, serviceAccountRole) | ||
|
||
return nil | ||
} | ||
|
||
func resourceKeycloakOpenidClientServiceAccountRealmRoleDelete(data *schema.ResourceData, meta interface{}) error { | ||
keycloakClient := meta.(*keycloak.KeycloakClient) | ||
|
||
serviceAccountRole, err := getOpenidClientServiceAccountRealmRoleFromData(data, keycloakClient) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = keycloakClient.DeleteOpenidClientServiceAccountRealmRole(serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.Id) | ||
if err != nil { | ||
return handleNotFoundError(err, data) | ||
} | ||
return nil | ||
} | ||
|
||
func resourceKeycloakOpenidClientServiceAccountRealmRoleImport(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: {{realmId}}/{{serviceAccountUserId}}/{{roleId}}") | ||
} | ||
d.Set("realm_id", parts[0]) | ||
d.Set("service_account_user_id", parts[1]) | ||
d.SetId(fmt.Sprintf("%s/%s", parts[1], parts[2])) | ||
|
||
return []*schema.ResourceData{d}, nil | ||
} |
177 changes: 177 additions & 0 deletions
177
provider/resource_keycloak_openid_client_service_account_realm_role_test.go
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,177 @@ | ||
package provider | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"github.com/mrparkers/terraform-provider-keycloak/keycloak" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
func TestAccKeycloakOpenidClientServiceAccountRealmRole_basic(t *testing.T) { | ||
realmName := "terraform-" + acctest.RandString(10) | ||
clientId := "terraform-" + acctest.RandString(10) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
Providers: testAccProviders, | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
CheckDestroy: testAccCheckKeycloakOpenidClientServiceAccountRealmRoleDestroy(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testKeycloakOpenidClientServiceAccountRealmRole_basic(realmName, clientId), | ||
Check: testAccCheckKeycloakOpenidClientServiceAccountRealmRoleExists("keycloak_openid_client_service_account_realm_role.test"), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccKeycloakOpenidClientServiceAccountRealmRole_createAfterManualDestroy(t *testing.T) { | ||
var serviceAccountRole = &keycloak.OpenidClientServiceAccountRealmRole{} | ||
|
||
realmName := "terraform-" + acctest.RandString(10) | ||
clientId := "terraform-" + acctest.RandString(10) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
Providers: testAccProviders, | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
CheckDestroy: testAccCheckKeycloakOpenidClientServiceAccountRealmRoleDestroy(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testKeycloakOpenidClientServiceAccountRealmRole_basic(realmName, clientId), | ||
Check: testAccCheckKeycloakOpenidClientServiceAccountRealmRoleFetch("keycloak_openid_client_service_account_realm_role.test", serviceAccountRole), | ||
}, | ||
{ | ||
PreConfig: func() { | ||
keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) | ||
|
||
err := keycloakClient.DeleteOpenidClientServiceAccountRealmRole(serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.Id) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
}, | ||
Config: testKeycloakOpenidClientServiceAccountRealmRole_basic(realmName, clientId), | ||
Check: testAccCheckKeycloakOpenidClientServiceAccountRealmRoleExists("keycloak_openid_client_service_account_realm_role.test"), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccKeycloakOpenidClientServiceAccountRealmRole_basicUpdateRealm(t *testing.T) { | ||
firstRealm := "terraform-" + acctest.RandString(10) | ||
secondRealm := "terraform-" + acctest.RandString(10) | ||
clientId := "terraform-" + acctest.RandString(10) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
Providers: testAccProviders, | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
CheckDestroy: testAccCheckKeycloakOpenidClientServiceAccountRealmRoleDestroy(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testKeycloakOpenidClientServiceAccountRealmRole_basic(firstRealm, clientId), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckKeycloakOpenidClientServiceAccountRealmRoleExists("keycloak_openid_client_service_account_realm_role.test"), | ||
resource.TestCheckResourceAttr("keycloak_openid_client_service_account_realm_role.test", "realm_id", firstRealm), | ||
), | ||
}, | ||
{ | ||
Config: testKeycloakOpenidClientServiceAccountRealmRole_basic(secondRealm, clientId), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckKeycloakOpenidClientServiceAccountRealmRoleExists("keycloak_openid_client_service_account_realm_role.test"), | ||
resource.TestCheckResourceAttr("keycloak_openid_client_service_account_realm_role.test", "realm_id", secondRealm), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckKeycloakOpenidClientServiceAccountRealmRoleExists(resourceName string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
_, err := getKeycloakOpenidClientServiceAccountRealmRoleFromState(s, resourceName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckKeycloakOpenidClientServiceAccountRealmRoleFetch(resourceName string, serviceAccountRole *keycloak.OpenidClientServiceAccountRealmRole) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
fetchedServiceAccountRole, err := getKeycloakOpenidClientServiceAccountRealmRoleFromState(s, resourceName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
serviceAccountRole.ServiceAccountUserId = fetchedServiceAccountRole.ServiceAccountUserId | ||
serviceAccountRole.RealmId = fetchedServiceAccountRole.RealmId | ||
serviceAccountRole.Id = fetchedServiceAccountRole.Id | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckKeycloakOpenidClientServiceAccountRealmRoleDestroy() resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "keycloak_openid_client_service_account_realm_role" { | ||
continue | ||
} | ||
|
||
realmId := rs.Primary.Attributes["realm_id"] | ||
serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] | ||
id := strings.Split(rs.Primary.ID, "/")[1] | ||
|
||
keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) | ||
|
||
serviceAccountRole, _ := keycloakClient.GetOpenidClientServiceAccountRealmRole(realmId, serviceAccountUserId, id) | ||
if serviceAccountRole != nil { | ||
return fmt.Errorf("service account role exists") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func getKeycloakOpenidClientServiceAccountRealmRoleFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientServiceAccountRealmRole, error) { | ||
keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) | ||
|
||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return nil, fmt.Errorf("resource not found: %s", resourceName) | ||
} | ||
|
||
realmId := rs.Primary.Attributes["realm_id"] | ||
serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] | ||
id := strings.Split(rs.Primary.ID, "/")[1] | ||
|
||
serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRealmRole(realmId, serviceAccountUserId, id) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting service account role mapping: %s", err) | ||
} | ||
|
||
return serviceAccountRole, nil | ||
} | ||
|
||
func testKeycloakOpenidClientServiceAccountRealmRole_basic(realm, clientId string) string { | ||
return fmt.Sprintf(` | ||
resource keycloak_realm test { | ||
realm = "%s" | ||
} | ||
resource keycloak_openid_client test { | ||
client_id = "%s" | ||
realm_id = "${keycloak_realm.test.id}" | ||
access_type = "CONFIDENTIAL" | ||
service_accounts_enabled = true | ||
} | ||
resource keycloak_openid_client_service_account_realm_role test { | ||
service_account_user_id = "${keycloak_openid_client.test.service_account_user_id}" | ||
realm_id = "${keycloak_realm.test.id}" | ||
role = "offline_access" | ||
} | ||
`, realm, clientId) | ||
} |