Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,13 @@ jobs:
MOUNT_FEDERATION_EXAMPLE_VOLUME=""
EXTRA_FEATURES=""
MOUNT_FEDERATION_EXAMPLE_VOLUME="-v $PWD/custom-user-federation-example/build/libs/custom-user-federation-example-all.jar:/opt/keycloak/providers/custom-user-federation-example-all.jar:z"
if [[ "${{ matrix.keycloak-version }}" == "26.5.5" || "${{ matrix.keycloak-version }}" == "26.4.7"|| "${{ matrix.keycloak-version }}" == "26.3.5" || "${{ matrix.keycloak-version }}" == "26.2.5" ]]; then
if [[ "${{ matrix.keycloak-version }}" == "26.5.5" ]]; then
EXTRA_FEATURES=",admin-fine-grained-authz:v2"
elif [[ "${{ matrix.keycloak-version }}" == "26.4.7" || "${{ matrix.keycloak-version }}" == "26.3.5" || "${{ matrix.keycloak-version }}" == "26.2.5" ]]; then
EXTRA_FEATURES=",admin-fine-grained-authz:v1"
fi

if [[ "${{ matrix.keycloak-version }}" == "26.5.5" || "${{ matrix.keycloak-version }}" == "26.4.7" || "${{ matrix.keycloak-version }}" == "26.3.5" || "${{ matrix.keycloak-version }}" == "26.2.5" ]]; then
EXTRA_HTTP_CLIENT_AUTH="-e KC_HTTPS_CLIENT_AUTH=required"
EXTRA_HTTPS_CERT="-e KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/testdata/tls/server-cert.pem"
EXTRA_HTTPS_KEY="-e KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/testdata/tls/server-key.pem"
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ services:
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=password
- KC_LOG_CONSOLE_COLOR=true
- KC_FEATURES=preview,admin-fine-grained-authz:v1
- KC_FEATURES=preview,admin-fine-grained-authz:v2
- KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/testdata/tls/server-cert.pem
- KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/testdata/tls/server-key.pem
# Enable for remote java debugging
Expand Down
2 changes: 1 addition & 1 deletion keycloak/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ type Realm struct {
MaxFailureWaitSeconds int `json:"maxFailureWaitSeconds"` //Max Wait
MaxDeltaTimeSeconds int `json:"maxDeltaTimeSeconds"` //Failure Reset Time

AdminPermissionsEnabled bool `json:"adminPermissionsEnabled,omitempty"`
AdminPermissionsEnabled *bool `json:"adminPermissionsEnabled,omitempty"`

PasswordPolicy string `json:"passwordPolicy"`

Expand Down
3 changes: 3 additions & 0 deletions provider/resource_keycloak_group_permissions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
)

func TestAccKeycloakGroupPermission_basic(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)

groupName := acctest.RandomWithPrefix("tf-acc")

resource.Test(t, resource.TestCase{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
)

func TestAccKeycloakIdpTokenExchangeScopePermission_basic(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)
t.Parallel()

providerAlias := acctest.RandomWithPrefix("tf-acc")
Expand All @@ -32,6 +34,8 @@ func TestAccKeycloakIdpTokenExchangeScopePermission_basic(t *testing.T) {
}

func TestAccKeycloakIdpTokenExchangeScopePermission_createAfterManualDestroy(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)
t.Parallel()

var idpPermissions = &keycloak.IdentityProviderPermissions{}
Expand Down Expand Up @@ -67,6 +71,8 @@ func TestAccKeycloakIdpTokenExchangeScopePermission_createAfterManualDestroy(t *
}

func TestAccKeycloakIdpTokenExchangeScopePermission_import(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)
t.Parallel()

providerAlias := acctest.RandomWithPrefix("tf-acc")
Expand All @@ -93,6 +99,8 @@ func TestAccKeycloakIdpTokenExchangeScopePermission_import(t *testing.T) {
}

func TestAccKeycloakIdpTokenExchangeScopePermission_updatePolicyMultipleClients(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)
t.Parallel()

providerAlias := acctest.RandomWithPrefix("tf-acc")
Expand Down
3 changes: 3 additions & 0 deletions provider/resource_keycloak_openid_client_permissions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
)

func TestAccKeycloakOpenidClientPermission_basic(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)

clientId := acctest.RandomWithPrefix("tf-acc")
username := acctest.RandomWithPrefix("tf-acc")
email := acctest.RandomWithPrefix("tf-acc") + "@fakedomain.com"
Expand Down
4 changes: 3 additions & 1 deletion provider/resource_keycloak_realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,9 @@ func getRealmFromData(data *schema.ResourceData, keycloakVersion *version.Versio
}
realm.DefaultOptionalClientScopes = defaultOptionalClientScopes

realm.AdminPermissionsEnabled = data.Get("admin_permissions_enabled").(bool)
if isAttributeInConfig(data, "admin_permissions_enabled") {
realm.AdminPermissionsEnabled = boolPointer(data.Get("admin_permissions_enabled").(bool))
}

//OTPPolicy
if v, ok := data.GetOk("otp_policy"); ok {
Expand Down
61 changes: 59 additions & 2 deletions provider/resource_keycloak_realm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,34 @@ func TestAccKeycloakRealm_admin_permissions_enabled(t *testing.T) {
})
}

func TestAccKeycloakRealm_admin_permissions_disabled(t *testing.T) {
if ok, _ := keycloakClient.VersionIsGreaterThanOrEqualTo(testCtx, keycloak.Version_26_5); !ok {
t.Skip()
}

realmName := acctest.RandomWithPrefix("tf-acc")

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakRealmDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakRealm_basic(realmName, realmName, realmName),
Check: testAccCheckKeycloakRealmExists("keycloak_realm.realm"),
},
{
Config: testKeycloakRealm_admin_permission_enabled(realmName),
Check: testAccCheckKeycloakRealm_admin_permissions_enabled("keycloak_realm.realm"),
},
{
Config: testKeycloakRealm_admin_permission_disabled(realmName),
Check: testAccCheckKeycloakRealm_admin_permissions_disabled("keycloak_realm.realm"),
},
},
})
}

func testKeycloakRealm_admin_permission_enabled(realm string) string {

return fmt.Sprintf(`
Expand All @@ -1023,15 +1051,44 @@ resource "keycloak_realm" "realm" {
`, realm)
}

func testKeycloakRealm_admin_permission_disabled(realm string) string {

return fmt.Sprintf(`
resource "keycloak_realm" "realm" {
realm = "%s"
enabled = true
admin_permissions_enabled = false
}
`, realm)
}

func testAccCheckKeycloakRealm_admin_permissions_disabled(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
realm, err := getRealmFromState(s, resourceName)
if err != nil {
return err
}

if realm.AdminPermissionsEnabled == nil {
return fmt.Errorf("expected realm %s to have admin permissions explicitly set to false but was nil", realm.Realm)
}
if *realm.AdminPermissionsEnabled {
return fmt.Errorf("expected realm %s to have admin permissions disabled but was true", realm.Realm)
}

return nil
}
}

func testAccCheckKeycloakRealm_admin_permissions_enabled(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
realm, err := getRealmFromState(s, resourceName)
if err != nil {
return err
}

if !realm.AdminPermissionsEnabled {
return fmt.Errorf("expected realm %s to have admin permissions enabled but was %t", realm.Realm, realm.AdminPermissionsEnabled)
if realm.AdminPermissionsEnabled == nil || !*realm.AdminPermissionsEnabled {
return fmt.Errorf("expected realm %s to have admin permissions enabled but was %v", realm.Realm, realm.AdminPermissionsEnabled)
}

return nil
Expand Down
3 changes: 3 additions & 0 deletions provider/resource_keycloak_users_permissions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
)

func TestAccKeycloakUsersPermission_basic(t *testing.T) {
// only supported with admin-fine-grained-authz:v1, not v2
skipIfVersionIsGreaterThanOrEqualTo(testCtx, t, keycloakClient, keycloak.Version_26_5)

realmName := acctest.RandomWithPrefix("tf-acc")
username := acctest.RandomWithPrefix("tf-acc")
email := acctest.RandomWithPrefix("tf-acc") + "@fakedomain.com"
Expand Down
20 changes: 14 additions & 6 deletions provider/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,27 @@ func stringPointer(s string) *string {
return &s
}

func boolPointer(b bool) *bool {
return &b
}

// isAttributeInConfig returns true if the specified attribute is explicitly present in the user's config
func isAttributeInConfig(d *schema.ResourceData, attrName string) bool {
rawConfig := d.GetRawConfig()
if rawConfig.IsNull() || !rawConfig.IsKnown() {
return false
}
return !rawConfig.GetAttr(attrName).IsNull()
}

// suppressDiffWhenNotInConfig returns a DiffSuppressFunc that suppresses diffs
// when the specified attribute is not present in the config (null).
// This allows:
// - Clearing a field with an empty string (field = "")
// - Keeping the server value when the field is not in the config
func suppressDiffWhenNotInConfig(attrName string) schema.SchemaDiffSuppressFunc {
return func(k, old, new string, d *schema.ResourceData) bool {
rawConfig := d.GetRawConfig()
if rawConfig.IsNull() || !rawConfig.IsKnown() {
return true
}
configValue := rawConfig.GetAttr(attrName)
return configValue.IsNull()
return !isAttributeInConfig(d, attrName)
}
}

Expand Down
Loading