Repository: cloudflare/cloudflare-go
Pull request #3618 (2024-11-18 16:02:03)

Adds identity update behavior field to Access Identity Providers
## Description

Adds identity update behavior field to Access Identity Provider SCIM Config. This field controls how we send updated identity information from SCIM to Access.

## Has your change been tested?

Unit tests

## Screenshots (if appropriate):

## Types of changes

What sort of change does your code introduce/modify?

- [x] New feature (non-breaking change which adds functionality)

## Checklist:

- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.
- [x] This change is using publicly documented in [cloudflare/api-schemas](https://github.com/cloudflare/api-schemas) 
      and relies on stable APIs.

[1]: https://help.github.com/articles/closing-issues-using-keywords/



Patch:
diff --git a/.changelog/3618.txt b/.changelog/3618.txt
new file mode 100644
index 000000000..e0200c566
--- /dev/null
+++ b/.changelog/3618.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+access_identity_provider: Adds identity_update_behavior to SCIM config.
+```
diff --git a/access_identity_provider.go b/access_identity_provider.go
index a1ffc8ced..c53f4e05d 100644
--- a/access_identity_provider.go
+++ b/access_identity_provider.go
@@ -58,6 +58,7 @@ type AccessIdentityProviderScimConfiguration struct {
 	UserDeprovision        bool   `json:"user_deprovision,omitempty"`
 	SeatDeprovision        bool   `json:"seat_deprovision,omitempty"`
 	GroupMemberDeprovision bool   `json:"group_member_deprovision,omitempty"`
+	IdentityUpdateBehavior string `json:"identity_update_behavior,omitempty"`
 }
 
 // AccessIdentityProvidersListResponse is the API response for multiple


Test patch:
diff --git a/access_identity_provider_test.go b/access_identity_provider_test.go
index e92854151..383d9ebb7 100644
--- a/access_identity_provider_test.go
+++ b/access_identity_provider_test.go
@@ -185,6 +185,91 @@ func TestCreateAccessIdentityProvider(t *testing.T) {
 		assert.Equal(t, want, actual)
 	}
 }
+
+func TestCreateAccessIdentityProviderScimConfig(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": {
+				"id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
+				"name": "Widget Corps SCIM",
+				"type": "github",
+				"config": {
+					"client_id": "example_id",
+					"client_secret": "a-secret-key",
+					"conditional_access_enabled": true
+				},
+				"scim_config": {
+					"enabled": true,
+					"user_deprovision": true,
+					"seat_deprovision": true,
+					"identity_update_behavior": "automatic",
+					"secret": "123123123"
+				}
+			}
+		}
+		`)
+	}
+
+	newIdentityProvider := CreateAccessIdentityProviderParams{
+		Name: "Widget Corps SCIM",
+		Type: "github",
+		Config: AccessIdentityProviderConfiguration{
+			ClientID:                 "example_id",
+			ClientSecret:             "a-secret-key",
+			ConditionalAccessEnabled: true,
+		},
+		ScimConfig: AccessIdentityProviderScimConfiguration{
+			Enabled:                true,
+			UserDeprovision:        true,
+			SeatDeprovision:        true,
+			IdentityUpdateBehavior: "automatic",
+		},
+	}
+
+	want := AccessIdentityProvider{
+		ID:   "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
+		Name: "Widget Corps SCIM",
+		Type: "github",
+		Config: AccessIdentityProviderConfiguration{
+			ClientID:                 "example_id",
+			ClientSecret:             "a-secret-key",
+			ConditionalAccessEnabled: true,
+		},
+		ScimConfig: AccessIdentityProviderScimConfiguration{
+			Enabled:                true,
+			UserDeprovision:        true,
+			SeatDeprovision:        true,
+			GroupMemberDeprovision: false,
+			IdentityUpdateBehavior: "automatic",
+			Secret:                 "123123123",
+		},
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers", handler)
+
+	actual, err := client.CreateAccessIdentityProvider(context.Background(), testAccountRC, newIdentityProvider)
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+
+	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers", handler)
+
+	actual, err = client.CreateAccessIdentityProvider(context.Background(), testZoneRC, newIdentityProvider)
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+}
+
 func TestUpdateAccessIdentityProvider(t *testing.T) {
 	setup()
 	defer teardown()
@@ -246,6 +331,88 @@ func TestUpdateAccessIdentityProvider(t *testing.T) {
 	}
 }
 
+func TestUpdateAccessIdentityProviderScimConfig(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": {
+				"id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
+				"name": "Widget Corps Scim",
+				"type": "github",
+				"config": {
+					"client_id": "example_id",
+					"client_secret": "a-secret-key"
+				},
+				"scim_config": {
+					"enabled": true,
+					"user_deprovision": false,
+					"seat_deprovision": false,
+					"group_member_deprovision": true,
+					"identity_update_behavior": "reauth"
+				}
+			}
+		}
+		`)
+	}
+
+	updatedIdentityProvider := UpdateAccessIdentityProviderParams{
+		ID:   "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
+		Name: "Widget Corps Scim",
+		Type: "github",
+		Config: AccessIdentityProviderConfiguration{
+			ClientID:     "example_id",
+			ClientSecret: "a-secret-key",
+		},
+		ScimConfig: AccessIdentityProviderScimConfiguration{
+			Enabled:                true,
+			UserDeprovision:        false,
+			SeatDeprovision:        false,
+			GroupMemberDeprovision: true,
+			IdentityUpdateBehavior: "reauth",
+		},
+	}
+
+	want := AccessIdentityProvider{
+		ID:   "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
+		Name: "Widget Corps Scim",
+		Type: "github",
+		Config: AccessIdentityProviderConfiguration{
+			ClientID:     "example_id",
+			ClientSecret: "a-secret-key",
+		},
+		ScimConfig: AccessIdentityProviderScimConfiguration{
+			Enabled:                true,
+			UserDeprovision:        false,
+			SeatDeprovision:        false,
+			GroupMemberDeprovision: true,
+			IdentityUpdateBehavior: "reauth",
+		},
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
+
+	actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountRC, updatedIdentityProvider)
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+
+	mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler)
+
+	actual, err = client.UpdateAccessIdentityProvider(context.Background(), testZoneRC, updatedIdentityProvider)
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+}
+
 func TestDeleteAccessIdentityProvider(t *testing.T) {
 	setup()
 	defer teardown()