pkg/client/keycloak/adapter/gocloak_adapter_client.go (210 lines of code) (raw):
package adapter
import (
"context"
"fmt"
"github.com/Nerzal/gocloak/v12"
"github.com/pkg/errors"
)
const defaultMax = 100
func (a GoCloakAdapter) AddDefaultScopeToClient(ctx context.Context, realmName, clientName string, scopes []ClientScope) error {
log := a.log.WithValues("clientName", clientName, logKeyRealm, realmName)
log.Info("Start add Default Client Scopes to client...")
clientID, err := a.GetClientID(clientName, realmName)
if err != nil {
return errors.Wrap(err, "error during GetClientId")
}
existingScopes, err := a.client.GetClientsDefaultScopes(ctx, a.token.AccessToken, realmName, clientID)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to get existing client scope for client %s", clientName))
}
existingScopesMap := make(map[string]*gocloak.ClientScope)
for _, s := range existingScopes {
if s != nil {
existingScopesMap[*s.ID] = s
}
}
for _, scope := range scopes {
if _, ok := existingScopesMap[scope.ID]; ok {
continue
}
err := a.client.AddDefaultScopeToClient(ctx, a.token.AccessToken, realmName, clientID, scope.ID)
if err != nil {
a.log.Error(err, fmt.Sprintf("failed link scope %s to client %s", scope.Name, clientName))
}
}
log.Info("End add Default Client Scopes to client...")
return nil
}
func (a GoCloakAdapter) AddOptionalScopeToClient(ctx context.Context, realmName, clientName string, scopes []ClientScope) error {
log := a.log.WithValues("clientName", clientName, logKeyRealm, realmName)
log.Info("Start add Optional Client Scopes to client...")
clientID, err := a.GetClientID(clientName, realmName)
if err != nil {
return errors.Wrap(err, "error during GetClientId")
}
existingScopes, err := a.client.GetClientsOptionalScopes(ctx, a.token.AccessToken, realmName, clientID)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to get existing client scope for client %s", clientName))
}
existingScopesMap := make(map[string]*gocloak.ClientScope)
for _, s := range existingScopes {
if s != nil {
existingScopesMap[*s.ID] = s
}
}
for _, scope := range scopes {
if _, ok := existingScopesMap[scope.ID]; ok {
continue
}
err := a.client.AddOptionalScopeToClient(ctx, a.token.AccessToken, realmName, clientID, scope.ID)
if err != nil {
a.log.Error(err, fmt.Sprintf("failed link scope %s to client %s", scope.Name, clientName))
}
}
log.Info("End add Optional Client Scopes to client...")
return nil
}
func (a GoCloakAdapter) GetPermissions(ctx context.Context, realm, idOfClient string) (map[string]gocloak.PermissionRepresentation, error) {
params := gocloak.GetPermissionParams{
Max: gocloak.IntP(defaultMax),
}
p, err := a.client.GetPermissions(ctx, a.token.AccessToken, realm, idOfClient, params)
if err != nil {
return nil, fmt.Errorf("failed to get permissions: %w", err)
}
permissions := make(map[string]gocloak.PermissionRepresentation, len(p))
for _, permission := range p {
if permission == nil || permission.Name == nil {
continue
}
permissions[*permission.Name] = *permission
}
return permissions, nil
}
func (a GoCloakAdapter) GetScopes(ctx context.Context, realm, idOfClient string) (map[string]gocloak.ScopeRepresentation, error) {
params := gocloak.GetScopeParams{
Max: gocloak.IntP(defaultMax),
Deep: gocloak.BoolP(false),
}
s, err := a.client.GetScopes(ctx, a.token.AccessToken, realm, idOfClient, params)
if err != nil {
return nil, fmt.Errorf("failed to get scopes: %w", err)
}
scopes := make(map[string]gocloak.ScopeRepresentation, len(s))
for _, scope := range s {
if scope == nil || scope.Name == nil {
continue
}
scopes[*scope.Name] = *scope
}
return scopes, nil
}
func (a GoCloakAdapter) GetResources(ctx context.Context, realm, idOfClient string) (map[string]gocloak.ResourceRepresentation, error) {
params := gocloak.GetResourceParams{
Max: gocloak.IntP(defaultMax),
Deep: gocloak.BoolP(false),
}
r, err := a.client.GetResources(ctx, a.token.AccessToken, realm, idOfClient, params)
if err != nil {
return nil, fmt.Errorf("failed to get resources: %w", err)
}
resources := make(map[string]gocloak.ResourceRepresentation, len(r))
for _, resource := range r {
if resource == nil || resource.Name == nil {
continue
}
resources[*resource.Name] = *resource
}
return resources, nil
}
// CreateResource creates a client authorization resource.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) CreateResource(ctx context.Context, realm, idOfClient string, resource gocloak.ResourceRepresentation) (*gocloak.ResourceRepresentation, error) {
p, err := a.client.CreateResource(ctx, a.token.AccessToken, realm, idOfClient, resource)
if err != nil {
return nil, fmt.Errorf("failed to create resource: %w", err)
}
return p, nil
}
// UpdateResource updates a client authorization resource.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) UpdateResource(ctx context.Context, realm, idOfClient string, resource gocloak.ResourceRepresentation) error {
if err := a.client.UpdateResource(ctx, a.token.AccessToken, realm, idOfClient, resource); err != nil {
return fmt.Errorf("failed to update resource: %w", err)
}
return nil
}
func (a GoCloakAdapter) DeleteResource(ctx context.Context, realm, idOfClient, resourceID string) error {
if err := a.client.DeleteResource(ctx, a.token.AccessToken, realm, idOfClient, resourceID); err != nil {
return fmt.Errorf("failed to delete resource: %w", err)
}
return nil
}
// CreateScope creates a client authorization permission.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) CreateScope(ctx context.Context, realm, idOfClient string, scope string) (*gocloak.ScopeRepresentation, error) {
scopeRepresentation := gocloak.ScopeRepresentation{
Name: &scope,
}
p, err := a.client.CreateScope(ctx, a.token.AccessToken, realm, idOfClient, scopeRepresentation)
if err != nil {
return nil, fmt.Errorf("failed to create scope: %w", err)
}
return p, nil
}
func (a GoCloakAdapter) DeleteScope(ctx context.Context, realm, idOfClient, scope string) error {
if err := a.client.DeleteScope(ctx, a.token.AccessToken, realm, idOfClient, scope); err != nil {
return fmt.Errorf("failed to delete scope: %w", err)
}
return nil
}
// CreatePermission creates a client authorization permission.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) CreatePermission(ctx context.Context, realm, idOfClient string, permission gocloak.PermissionRepresentation) (*gocloak.PermissionRepresentation, error) {
p, err := a.client.CreatePermission(ctx, a.token.AccessToken, realm, idOfClient, permission)
if err != nil {
return nil, fmt.Errorf("failed to create permission: %w", err)
}
return p, nil
}
// UpdatePermission updates a client authorization permission.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) UpdatePermission(ctx context.Context, realm, idOfClient string, permission gocloak.PermissionRepresentation) error {
if err := a.client.UpdatePermission(ctx, a.token.AccessToken, realm, idOfClient, permission); err != nil {
return fmt.Errorf("failed to update permission: %w", err)
}
return nil
}
func (a GoCloakAdapter) DeletePermission(ctx context.Context, realm, idOfClient, permissionID string) error {
if err := a.client.DeletePermission(ctx, a.token.AccessToken, realm, idOfClient, permissionID); err != nil {
return fmt.Errorf("failed to delete permission: %w", err)
}
return nil
}
func (a GoCloakAdapter) GetPolicies(ctx context.Context, realm, idOfClient string) (map[string]*gocloak.PolicyRepresentation, error) {
params := gocloak.GetPolicyParams{
Permission: gocloak.BoolP(false),
Max: gocloak.IntP(defaultMax),
}
p, err := a.client.GetPolicies(ctx, a.token.AccessToken, realm, idOfClient, params)
if err != nil {
return nil, fmt.Errorf("failed to get policies: %w", err)
}
policies := make(map[string]*gocloak.PolicyRepresentation, len(p))
for _, policy := range p {
if policy.Name == nil {
continue
}
policies[*policy.Name] = policy
}
return policies, nil
}
// CreatePolicy creates a client authorization policy.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) CreatePolicy(ctx context.Context, realm, idOfClient string, policy gocloak.PolicyRepresentation) (*gocloak.PolicyRepresentation, error) {
pl, err := a.client.CreatePolicy(ctx, a.token.AccessToken, realm, idOfClient, policy)
if err != nil {
return nil, fmt.Errorf("failed to create policy: %w", err)
}
return pl, nil
}
// UpdatePolicy updates a client authorization policy.
// nolint:gocritic // gocloak is a third party library, we can't change the function signature
func (a GoCloakAdapter) UpdatePolicy(ctx context.Context, realm, idOfClient string, policy gocloak.PolicyRepresentation) error {
if err := a.client.UpdatePolicy(ctx, a.token.AccessToken, realm, idOfClient, policy); err != nil {
return fmt.Errorf("failed to update policy: %w", err)
}
return nil
}
func (a GoCloakAdapter) DeletePolicy(ctx context.Context, realm, idOfClient, policyID string) error {
if err := a.client.DeletePolicy(ctx, a.token.AccessToken, realm, idOfClient, policyID); err != nil {
return fmt.Errorf("failed to delete policy: %w", err)
}
return nil
}