Repository: cloudflare/cloudflare-go
Pull request #2786 (2024-07-25 15:51:32)

DLP-1890: add support for Risk Score Integrations
https://developers.cloudflare.com/api/operations/dlp-zt-risk-score-integration-create

## Description

Adds support for the Risk Score Integrations API to the CF Go library.

## Has your change been tested?

Unit tests. Have also tested these changes alongside my terraform-provider-cloudflare changes to check it works.

## Types of changes

What sort of change does your code introduce/modify?

- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## 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/


github-actions[bot]: Oops! It looks like no changelog entry is attached to this PR. Please include a release note as described in https://github.com/cloudflare/cloudflare-go/blob/master/docs/changelog-process.md.

Example: 

~~~
```release-note:TYPE
Release note
```
~~~

If you do not require a release note to be included, please add the `workflow/skip-changelog-entry` label.

Patch:
diff --git a/.changelog/2778.txt b/.changelog/2778.txt
deleted file mode 100644
index b3e90fdc7..000000000
--- a/.changelog/2778.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-```release-note:enhancement
-devices_policy: Add new tunnel_protocol field to policy
-```
diff --git a/.changelog/2786.txt b/.changelog/2786.txt
new file mode 100644
index 000000000..15064cef5
--- /dev/null
+++ b/.changelog/2786.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+risk_score_integration: Add support for Risk Score Integrations
+```
\ No newline at end of file
diff --git a/devices_policy.go b/devices_policy.go
index 0da365d58..1a8b03b9d 100644
--- a/devices_policy.go
+++ b/devices_policy.go
@@ -59,7 +59,6 @@ type DeviceSettingsPolicy struct {
 	Description         *string           `json:"description"`
 	LANAllowMinutes     *uint             `json:"lan_allow_minutes"`
 	LANAllowSubnetSize  *uint             `json:"lan_allow_subnet_size"`
-	TunnelProtocol      *string           `json:"tunnel_protocol"`
 }
 
 type DeviceSettingsPolicyResponse struct {
@@ -90,7 +89,6 @@ type CreateDeviceSettingsPolicyParams struct {
 	Description         *string        `json:"description,omitempty"`
 	LANAllowMinutes     *uint          `json:"lan_allow_minutes,omitempty"`
 	LANAllowSubnetSize  *uint          `json:"lan_allow_subnet_size,omitempty"`
-	TunnelProtocol      *string        `json:"tunnel_protocol,omitempty"`
 }
 
 type UpdateDefaultDeviceSettingsPolicyParams struct {
@@ -111,7 +109,6 @@ type UpdateDefaultDeviceSettingsPolicyParams struct {
 	Description         *string        `json:"description,omitempty"`
 	LANAllowMinutes     *uint          `json:"lan_allow_minutes,omitempty"`
 	LANAllowSubnetSize  *uint          `json:"lan_allow_subnet_size,omitempty"`
-	TunnelProtocol      *string        `json:"tunnel_protocol,omitempty"`
 }
 
 type UpdateDeviceSettingsPolicyParams struct {
@@ -133,7 +130,6 @@ type UpdateDeviceSettingsPolicyParams struct {
 	Description         *string        `json:"description,omitempty"`
 	LANAllowMinutes     *uint          `json:"lan_allow_minutes,omitempty"`
 	LANAllowSubnetSize  *uint          `json:"lan_allow_subnet_size,omitempty"`
-	TunnelProtocol      *string        `json:"tunnel_protocol,omitempty"`
 }
 
 type ListDeviceSettingsPoliciesResponse struct {
diff --git a/zt_risk_score_integration.go b/zt_risk_score_integration.go
new file mode 100644
index 000000000..a80ef1da6
--- /dev/null
+++ b/zt_risk_score_integration.go
@@ -0,0 +1,180 @@
+package cloudflare
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/goccy/go-json"
+)
+
+var (
+	ErrMissingRiskScoreIntegrationID = errors.New("missing required Risk Score Integration UUID")
+)
+
+// Represents a Risk Score Sharing Integration.
+// If enabled, Cloudflare will share changes in user risk score with the specified vendor.
+type RiskScoreIntegration struct {
+	ID              string     `json:"id,omitempty"`
+	IntegrationType string     `json:"integration_type,omitempty"`
+	TenantUrl       string     `json:"tenant_url,omitempty"`
+	ReferenceID     string     `json:"reference_id,omitempty"`
+	AccountTag      string     `json:"account_tag,omitempty"`
+	WellKnownUrl    string     `json:"well_known_url,omitempty"`
+	Active          *bool      `json:"active,omitempty"`
+	CreatedAt       *time.Time `json:"created_at,omitempty"`
+}
+
+// The properties required to create a new risk score integration.
+type RiskScoreIntegrationCreateRequest struct {
+	IntegrationType string `json:"integration_type,omitempty"`
+	TenantUrl       string `json:"tenant_url,omitempty"`
+	ReferenceID     string `json:"reference_id,omitempty"`
+}
+
+// The properties required to update a risk score integration.
+type RiskScoreIntegrationUpdateRequest struct {
+	IntegrationType string `json:"integration_type,omitempty"`
+	TenantUrl       string `json:"tenant_url,omitempty"`
+	ReferenceID     string `json:"reference_id,omitempty"`
+	Active          *bool  `json:"active,omitempty"`
+}
+
+// A list of risk score integrations as returned from the API.
+type RiskScoreIntegrationListResponse struct {
+	Result []RiskScoreIntegration `json:"result"`
+	Response
+}
+
+// A risk score integration as returned from the API.
+type RiskScoreIntegrationResponse struct {
+	Result RiskScoreIntegration `json:"result"`
+	Response
+}
+
+type ListRiskScoreIntegrationParams struct{}
+
+// GetRiskScoreIntegration returns a single Risk Score Integration by its ID.
+//
+// API reference: https://developers.cloudflare.com/api/operations/dlp-zt-risk-score-integration-get
+func (api *API) GetRiskScoreIntegration(ctx context.Context, rc *ResourceContainer, integrationID string) (RiskScoreIntegration, error) {
+	if rc.Identifier == "" {
+		return RiskScoreIntegration{}, ErrMissingResourceIdentifier
+	}
+
+	if integrationID == "" {
+		return RiskScoreIntegration{}, ErrMissingRiskScoreIntegrationID
+	}
+
+	uri := buildURI(fmt.Sprintf("/%s/%s/zt_risk_scoring/integrations/%s", rc.Level, rc.Identifier, integrationID), nil)
+
+	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+	if err != nil {
+		return RiskScoreIntegration{}, err
+	}
+
+	var integrationResponse RiskScoreIntegrationResponse
+	err = json.Unmarshal(res, &integrationResponse)
+	if err != nil {
+		return RiskScoreIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return integrationResponse.Result, nil
+}
+
+// ListRiskScoreIntegrations returns all Risk Score Integrations for an account.
+//
+// API reference: https://developers.cloudflare.com/api/operations/dlp-zt-risk-score-integration-list
+func (api *API) ListRiskScoreIntegrations(ctx context.Context, rc *ResourceContainer, params ListRiskScoreIntegrationParams) ([]RiskScoreIntegration, error) {
+	if rc.Identifier == "" {
+		return []RiskScoreIntegration{}, ErrMissingResourceIdentifier
+	}
+
+	uri := buildURI(fmt.Sprintf("/%s/%s/zt_risk_scoring/integrations", rc.Level, rc.Identifier), nil)
+
+	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+	if err != nil {
+		return []RiskScoreIntegration{}, err
+	}
+
+	var integrationsResponse RiskScoreIntegrationListResponse
+	err = json.Unmarshal(res, &integrationsResponse)
+	if err != nil {
+		return []RiskScoreIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return integrationsResponse.Result, nil
+}
+
+// CreateRiskScoreIntegration creates a new Risk Score Integration.
+//
+// API reference: https://developers.cloudflare.com/api/operations/dlp-zt-risk-score-integration-create
+func (api *API) CreateRiskScoreIntegration(ctx context.Context, rc *ResourceContainer, params RiskScoreIntegrationCreateRequest) (RiskScoreIntegration, error) {
+	if rc.Identifier == "" {
+		return RiskScoreIntegration{}, ErrMissingResourceIdentifier
+	}
+
+	uri := buildURI(fmt.Sprintf("/%s/%s/zt_risk_scoring/integrations", rc.Level, rc.Identifier), nil)
+
+	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
+	if err != nil {
+		return RiskScoreIntegration{}, err
+	}
+
+	var integrationResponse RiskScoreIntegrationResponse
+	err = json.Unmarshal(res, &integrationResponse)
+	if err != nil {
+		return RiskScoreIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return integrationResponse.Result, nil
+}
+
+// UpdateRiskScoreIntegration updates a Risk Score Integration.
+//
+// Can be used to disable or active the integration using the "active" boolean property.
+// API reference: https://developers.cloudflare.com/api/operations/dlp-zt-risk-score-integration-update
+func (api *API) UpdateRiskScoreIntegration(ctx context.Context, rc *ResourceContainer, integrationID string, params RiskScoreIntegrationUpdateRequest) (RiskScoreIntegration, error) {
+	if rc.Identifier == "" {
+		return RiskScoreIntegration{}, ErrMissingResourceIdentifier
+	}
+
+	if integrationID == "" {
+		return RiskScoreIntegration{}, ErrMissingRiskScoreIntegrationID
+	}
+
+	uri := buildURI(fmt.Sprintf("/%s/%s/zt_risk_scoring/integrations/%s", rc.Level, rc.Identifier, integrationID), nil)
+
+	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
+	if err != nil {
+		return RiskScoreIntegration{}, err
+	}
+
+	var integrationResponse RiskScoreIntegrationResponse
+	err = json.Unmarshal(res, &integrationResponse)
+	if err != nil {
+		return RiskScoreIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return integrationResponse.Result, nil
+}
+
+// DeleteRiskScoreIntegration deletes a Risk Score Integration.
+//
+// API reference: https://developers.cloudflare.com/api/operations/dlp-zt-risk-score-integration-delete
+func (api *API) DeleteRiskScoreIntegration(ctx context.Context, rc *ResourceContainer, integrationID string) error {
+	if rc.Identifier == "" {
+		return ErrMissingResourceIdentifier
+	}
+
+	if integrationID == "" {
+		return ErrMissingRiskScoreIntegrationID
+	}
+
+	uri := buildURI(fmt.Sprintf("/%s/%s/zt_risk_scoring/integrations/%s", rc.Level, rc.Identifier, integrationID), nil)
+
+	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
+	return err
+}


Test patch:
diff --git a/devices_policy_test.go b/devices_policy_test.go
index d2db00023..c78a13838 100644
--- a/devices_policy_test.go
+++ b/devices_policy_test.go
@@ -45,7 +45,6 @@ var (
 		Description:        nil,
 		LANAllowMinutes:    nil,
 		LANAllowSubnetSize: nil,
-		TunnelProtocol:     StringPtr("wireguard"),
 	}
 
 	nonDefaultDeviceSettingsPolicy = DeviceSettingsPolicy{
@@ -79,7 +78,6 @@ var (
 		Description:        StringPtr("Test Description"),
 		LANAllowMinutes:    UintPtr(120),
 		LANAllowSubnetSize: UintPtr(31),
-		TunnelProtocol:     StringPtr("masque"),
 	}
 
 	defaultDeviceSettingsPolicyJson = `{
@@ -113,8 +111,7 @@ var (
 		"allowed_to_leave": true,
 		"enabled": true,
 		"default": true,
-		"exclude_office_ips":false,
-		"tunnel_protocol":"wireguard"
+		"exclude_office_ips":false
 	}`
 
 	nonDefaultDeviceSettingsPolicyJson = fmt.Sprintf(`{
@@ -155,8 +152,7 @@ var (
 		"exclude_office_ips":true,
 		"description":"Test Description",
 		"lan_allow_minutes": 120,
-		"lan_allow_subnet_size": 31,
-		"tunnel_protocol":"masque"
+		"lan_allow_subnet_size": 31
 	}`, deviceSettingsPolicyID, deviceSettingsPolicyMatch)
 )
 
diff --git a/zt_risk_score_integration_test.go b/zt_risk_score_integration_test.go
new file mode 100644
index 000000000..64a94cd0b
--- /dev/null
+++ b/zt_risk_score_integration_test.go
@@ -0,0 +1,259 @@
+package cloudflare
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"strconv"
+	"testing"
+	"time"
+
+	"github.com/goccy/go-json"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestListRiskScoreIntegrations(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `
+		{
+			"result": [
+				{
+					"id": "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+					"account_tag": "f772f54476db1178347e5bfba3c9ac83",
+					"integration_type": "Okta",
+					"reference_id": "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+					"tenant_url": "https://my-tenant.oktapreview.com",
+					"well_known_url": "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+					"active": true,
+					"created_at": "2024-06-13T18:17:22Z"
+				},
+				{
+					"id": "0d5e7916-0b18-4a22-839f-b82e33a87843",
+					"account_tag": "f772f54476db1178347e5bfba3c9ac83",
+					"integration_type": "Okta",
+					"reference_id": "d77c9506-00bc-43aa-8e95-3223351ea330",
+					"tenant_url": "https://my-tenant-2.oktapreview.com",
+					"well_known_url": "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/0d5e7916-0b18-4a22-839f-b82e33a87843",
+					"active": false,
+					"created_at": "2024-06-13T18:17:22Z"
+				}
+			],
+			"success": true,
+			"errors": [],
+			"messages": []
+		}
+		`)
+	}
+
+	createdAt, _ := time.Parse(time.RFC3339, "2024-06-13T18:17:22Z")
+
+	want := []RiskScoreIntegration{
+		{
+			ID:              "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+			AccountTag:      "f772f54476db1178347e5bfba3c9ac83",
+			IntegrationType: "Okta",
+			ReferenceID:     "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+			TenantUrl:       "https://my-tenant.oktapreview.com",
+			WellKnownUrl:    "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+			Active:          BoolPtr(true),
+			CreatedAt:       &createdAt,
+		},
+		{
+			ID:              "0d5e7916-0b18-4a22-839f-b82e33a87843",
+			AccountTag:      "f772f54476db1178347e5bfba3c9ac83",
+			IntegrationType: "Okta",
+			ReferenceID:     "d77c9506-00bc-43aa-8e95-3223351ea330",
+			TenantUrl:       "https://my-tenant-2.oktapreview.com",
+			WellKnownUrl:    "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/0d5e7916-0b18-4a22-839f-b82e33a87843",
+			Active:          BoolPtr(false),
+			CreatedAt:       &createdAt,
+		},
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/zt_risk_scoring/integrations", handler)
+
+	actual, err := client.ListRiskScoreIntegrations(context.Background(), AccountIdentifier(testAccountID), ListRiskScoreIntegrationParams{})
+	require.NoError(t, err)
+	require.Equal(t, want, actual)
+}
+
+func TestGetRiskScoreIntegration(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": {
+				"id": "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+				"account_tag": "f772f54476db1178347e5bfba3c9ac83",
+				"integration_type": "Okta",
+				"reference_id": "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+				"tenant_url": "https://my-tenant.oktapreview.com",
+				"well_known_url": "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+				"active": true,
+				"created_at": "2024-06-13T18:17:22Z"
+			}
+		}`)
+	}
+
+	createdAt, _ := time.Parse(time.RFC3339, "2024-06-13T18:17:22Z")
+
+	want := RiskScoreIntegration{
+		ID:              "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+		AccountTag:      "f772f54476db1178347e5bfba3c9ac83",
+		IntegrationType: "Okta",
+		ReferenceID:     "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+		TenantUrl:       "https://my-tenant.oktapreview.com",
+		WellKnownUrl:    "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+		Active:          BoolPtr(true),
+		CreatedAt:       &createdAt,
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/zt_risk_scoring/integrations/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9", handler)
+
+	actual, err := client.GetRiskScoreIntegration(context.Background(), AccountIdentifier(testAccountID), "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9")
+	require.NoError(t, err)
+	require.Equal(t, want, actual)
+}
+
+func TestCreateRiskScoreIntegration(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")
+
+		var reqBody RiskScoreIntegrationCreateRequest
+		err := json.NewDecoder(r.Body).Decode(&reqBody)
+		require.Nil(t, err)
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": {
+				"id": "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+				"account_tag": "f772f54476db1178347e5bfba3c9ac83",
+				"integration_type": "`+reqBody.IntegrationType+`",
+				"reference_id": "`+reqBody.ReferenceID+`",
+				"tenant_url": "`+reqBody.TenantUrl+`",
+				"well_known_url": "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+				"active": true,
+				"created_at": "2024-06-13T18:17:22Z"
+			}
+		}`)
+	}
+
+	createdAt, _ := time.Parse(time.RFC3339, "2024-06-13T18:17:22Z")
+
+	want := RiskScoreIntegration{
+		ID:              "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+		AccountTag:      "f772f54476db1178347e5bfba3c9ac83",
+		IntegrationType: "Okta",
+		ReferenceID:     "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+		TenantUrl:       "https://my-tenant.oktapreview.com",
+		WellKnownUrl:    "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+		Active:          BoolPtr(true),
+		CreatedAt:       &createdAt,
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/zt_risk_scoring/integrations", handler)
+
+	integration := RiskScoreIntegrationCreateRequest{
+		IntegrationType: "Okta",
+		TenantUrl:       "https://my-tenant.oktapreview.com",
+		ReferenceID:     "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+	}
+	actual, err := client.CreateRiskScoreIntegration(context.Background(), AccountIdentifier(testAccountID), integration)
+	require.NoError(t, err)
+	require.Equal(t, want, actual)
+}
+
+func TestUpdateRiskScoreIntegration(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")
+
+		var reqBody RiskScoreIntegrationUpdateRequest
+		err := json.NewDecoder(r.Body).Decode(&reqBody)
+		require.Nil(t, err)
+
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": {
+				"id": "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+				"account_tag": "f772f54476db1178347e5bfba3c9ac83",
+				"integration_type": "`+reqBody.IntegrationType+`",
+				"reference_id": "`+reqBody.ReferenceID+`",
+				"tenant_url": "`+reqBody.TenantUrl+`",
+				"well_known_url": "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+				"active": `+strconv.FormatBool(*reqBody.Active)+`,
+				"created_at": "2024-06-13T18:17:22Z"
+			}
+		}`)
+	}
+
+	createdAt, _ := time.Parse(time.RFC3339, "2024-06-13T18:17:22Z")
+
+	want := RiskScoreIntegration{
+		ID:              "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+		AccountTag:      "f772f54476db1178347e5bfba3c9ac83",
+		IntegrationType: "Okta",
+		ReferenceID:     "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+		TenantUrl:       "https://my-tenant.oktapreview.com",
+		WellKnownUrl:    "https://ssf.risk-score.teams.cloudflare.com/.well-known/sse-configuration/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9",
+		Active:          BoolPtr(false),
+		CreatedAt:       &createdAt,
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/zt_risk_scoring/integrations/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9", handler)
+
+	integration := RiskScoreIntegrationUpdateRequest{
+		IntegrationType: "Okta",
+		TenantUrl:       "https://my-tenant.oktapreview.com",
+		ReferenceID:     "72f826ea-8744-4dcb-a00e-8cc00bb6d34b",
+		Active:          BoolPtr(false),
+	}
+
+	actual, err := client.UpdateRiskScoreIntegration(context.Background(), AccountIdentifier(testAccountID), "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9", integration)
+	require.NoError(t, err)
+	require.Equal(t, want, actual)
+}
+
+func TestDeleteRiskScoreIntegration(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `{
+			"result": null,
+			"success": true,
+			"errors": [],
+			"messages": []
+		}`)
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/zt_risk_scoring/integrations/91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9", handler)
+
+	err := client.DeleteRiskScoreIntegration(context.Background(), AccountIdentifier(testAccountID), "91dbf25d-2b51-415e-a6df-5a6d2ff4f7e9")
+	require.NoError(t, err)
+}