Skip to content

Commit

Permalink
feat: add OpenId client initial access token resource and implement i…
Browse files Browse the repository at this point in the history
…ts read, create and delete logic

test: creating and deleting initial access token
  • Loading branch information
Redestros committed Oct 8, 2023
1 parent bfee4d7 commit 46cdb14
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 0 deletions.
84 changes: 84 additions & 0 deletions keycloak/openid_client_initial_access_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package keycloak

import (
"context"
"encoding/json"
"fmt"
)

type OpenidClientInitialAccessToken struct {
Id string `json:"id,omitempty"`
RealmId string `json:"realm_id"`
Count int `json:"count"`
Expiration int `json:"expiration"`
RemainingCount int `json:"remaining_count"`
Token string `json:"token"`
}

type OpenidClientInitialAccessTokenCreateModel struct {
Count int `json:"count"`
Expiration int `json:"expiration"`
}

func (keycloakClient *KeycloakClient) NewOpenidClientInitialAccessToken(ctx context.Context, initialAccessToken *OpenidClientInitialAccessToken) (*OpenidClientInitialAccessToken, error) {
createModel := OpenidClientInitialAccessTokenCreateModel{
Count: initialAccessToken.Count,
Expiration: initialAccessToken.Expiration,
}

body, _, err := keycloakClient.post(ctx, fmt.Sprintf("/realms/%s/clients-initial-access", initialAccessToken.RealmId), createModel)
if err != nil {
return nil, err
}

var createdToken OpenidClientInitialAccessToken
conversionErr := json.Unmarshal(body, &createdToken)
if conversionErr != nil {
return nil, conversionErr
}
createdToken.RealmId = initialAccessToken.RealmId

initialAccessToken.Id = createdToken.Id
initialAccessToken.Token = createdToken.Token
return &createdToken, nil
}

func (keycloakClient *KeycloakClient) GetClientInitialAccessTokens(ctx context.Context, realmId string) (*[]OpenidClientInitialAccessToken, error) {

var initialAccessTokens []OpenidClientInitialAccessToken

err := keycloakClient.get(ctx, fmt.Sprintf("/realms/%s/clients-initial-access", realmId), &initialAccessTokens, nil)
if err != nil {
return nil, err
}

for k := range initialAccessTokens {
initialAccessTokens[k].RealmId = realmId
}

return &initialAccessTokens, nil
}

func (keycloakClient *KeycloakClient) GetClientInitialAccessToken(ctx context.Context, realmId, id string) (*OpenidClientInitialAccessToken, error) {

var initialAccessTokens []OpenidClientInitialAccessToken

err := keycloakClient.get(ctx, fmt.Sprintf("/realms/%s/clients-initial-access", realmId), &initialAccessTokens, nil)
if err != nil {
return nil, err
}

var token *OpenidClientInitialAccessToken
for k := range initialAccessTokens {
initialAccessTokens[k].RealmId = realmId
if initialAccessTokens[k].Id == id {
token = &initialAccessTokens[k]
}
}

return token, nil
}

func (keycloakClient *KeycloakClient) DeleteClientInitialAccessToken(ctx context.Context, realmId, id string) error {
return keycloakClient.delete(ctx, fmt.Sprintf("/realms/%s/clients-initial-access/%s", realmId, id), nil)
}
1 change: 1 addition & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ func KeycloakProvider(client *keycloak.KeycloakClient) *schema.Provider {
"keycloak_openid_client_time_policy": resourceKeycloakOpenidClientAuthorizationTimePolicy(),
"keycloak_openid_client_user_policy": resourceKeycloakOpenidClientAuthorizationUserPolicy(),
"keycloak_openid_client_client_policy": resourceKeycloakOpenidClientAuthorizationClientPolicy(),
"keycloak_openid_client_initial_access_token": resourceKeycloakOpenIdClientInitialAccessToken(),
"keycloak_openid_client_authorization_scope": resourceKeycloakOpenidClientAuthorizationScope(),
"keycloak_openid_client_authorization_permission": resourceKeycloakOpenidClientAuthorizationPermission(),
"keycloak_openid_client_service_account_role": resourceKeycloakOpenidClientServiceAccountRole(),
Expand Down
105 changes: 105 additions & 0 deletions provider/resource_keycloak_openid_client_initial_access_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package provider

import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
)

func resourceKeycloakOpenIdClientInitialAccessToken() *schema.Resource {
return &schema.Resource{
ReadContext: resourceKeycloakOpenIdClientInitialAccessTokenRead,
CreateContext: resourceKeycloakOpenIdClientInitialAccessTokenCreate,
DeleteContext: resourceKeycloakOpenIdClientInitialAccessTokenDelete,
Schema: map[string]*schema.Schema{
"realm_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"token_count": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"remaining_count": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"expiration": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"token_value": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}

func resourceKeycloakOpenIdClientInitialAccessTokenRead(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
keycloakClient := meta.(*keycloak.KeycloakClient)
realmId := data.Get("realm_id").(string)
tokens, err := keycloakClient.GetClientInitialAccessTokens(ctx, realmId)
if err != nil {
return diag.FromErr(err)
}

id := data.Id()
list := *tokens
for i := range list {
if list[i].Id == id {
data.SetId(id)
data.Set("realm_id", list[i].RealmId)
data.Set("token_count", list[i].Count)
data.Set("remaining_count", list[i].RemainingCount)
data.Set("expiration", list[i].Expiration)
data.Set("token_value", list[i].Token)
}
}
return nil
}

func resourceKeycloakOpenIdClientInitialAccessTokenCreate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
keycloakClient := meta.(*keycloak.KeycloakClient)

initialAccessToken := getOpenidClientInitialAccessTokenFromData(data)
createdToken, err := keycloakClient.NewOpenidClientInitialAccessToken(ctx, initialAccessToken)
if err != nil {
return diag.FromErr(err)
}

data.SetId(createdToken.Id)
data.Set("realm_id", createdToken.RealmId)
data.Set("token_count", createdToken.Count)
data.Set("remaining_count", createdToken.RemainingCount)
data.Set("expiration", createdToken.Expiration)
data.Set("token_value", createdToken.Token)

return nil
}

func resourceKeycloakOpenIdClientInitialAccessTokenDelete(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
keycloakClient := meta.(*keycloak.KeycloakClient)

realmId := data.Get("realm_id").(string)
id := data.Id()

return diag.FromErr(keycloakClient.DeleteClientInitialAccessToken(ctx, realmId, id))
}

func getOpenidClientInitialAccessTokenFromData(data *schema.ResourceData) *keycloak.OpenidClientInitialAccessToken {
initialAccessToken := &keycloak.OpenidClientInitialAccessToken{
Id: data.Id(),
RealmId: data.Get("realm_id").(string),
Count: data.Get("token_count").(int),
Expiration: data.Get("expiration").(int),
}

return initialAccessToken
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package provider

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
"strings"
"testing"
)

func TestAccKeycloakOpenidClientsInitialAccessToken_basic(t *testing.T) {
realmName := acctest.RandomWithPrefix("tf-acc")

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakOpenidClientsInitialAccessTokenDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakOpenidClientInitialAccessToken_basic(realmName),
Check: testAccCheckOpenidClientInitialAccessTokenExists("keycloak_openid_client_initial_access_token.test_initial_access_token"),
},
},
})
}

func testAccCheckOpenidClientInitialAccessTokenExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, err := getOpenidClientInitialAccessTokenState(s, resourceName)
if err != nil {
return err
}

return nil
}
}

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

realm := rs.Primary.Attributes["realm_id"]
id := rs.Primary.ID

token, err := keycloakClient.GetClientInitialAccessToken(testCtx, realm, id)
if err != nil {
return nil, fmt.Errorf("error getting realm events config: %s", err)
}

return token, nil
}

func testAccCheckKeycloakOpenidClientsInitialAccessTokenDestroy() resource.TestCheckFunc {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
if rs.Type != "keycloak_openid_client_initial_access_token" || strings.HasPrefix(name, "data") {
continue
}

id := rs.Primary.ID
realm := rs.Primary.Attributes["realm_id"]

role, _ := keycloakClient.GetClientInitialAccessToken(testCtx, realm, id)
if role != nil {
return fmt.Errorf("%s with id %s still exists", name, id)
}
}

return nil
}
}

func testKeycloakOpenidClientInitialAccessToken_basic(realm string) string {
return fmt.Sprintf(`
resource "keycloak_realm" "realm" {
realm = "%s"
}
resource "keycloak_openid_client_initial_access_token" "test_initial_access_token" {
realm_id = keycloak_realm.realm.id
token_count = 2
expiration = 345600
}
`, realm)
}

0 comments on commit 46cdb14

Please sign in to comment.