Skip to content

Commit 02341fe

Browse files
Added scim_config and scim_config_token resources
1 parent dc217c3 commit 02341fe

19 files changed

Lines changed: 1098 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Changes
2+
body: Added scim_config and scim_config_token resources
3+
time: 2026-04-07T08:42:00.212569+03:00

docs/resources/scim_config.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
page_title: "dbtcloud_scim_config Resource - dbtcloud"
3+
subcategory: ""
4+
description: |-
5+
Manages the SCIM configuration for a dbt Cloud account. SCIM (System for Cross-domain Identity Management) allows identity providers such as Okta and Azure AD to automatically provision and deprovision users and groups.
6+
This is a singleton resource — only one SCIM configuration exists per account. Destroying the resource resets the configuration to its defaults (SCIM disabled, manual updates allowed, license type not SCIM-controlled).
7+
Requires the SCIM feature to be enabled on the account (enterprise plans only).
8+
---
9+
10+
# dbtcloud_scim_config (Resource)
11+
12+
13+
Manages the SCIM configuration for a dbt Cloud account. SCIM (System for Cross-domain Identity Management) allows identity providers such as Okta and Azure AD to automatically provision and deprovision users and groups.
14+
15+
This is a singleton resource — only one SCIM configuration exists per account. Destroying the resource resets the configuration to its defaults (SCIM disabled, manual updates allowed, license type not SCIM-controlled).
16+
17+
Requires the SCIM feature to be enabled on the account (enterprise plans only).
18+
19+
## Example Usage
20+
21+
```terraform
22+
# Enable SCIM with strict IdP control — no manual updates, license type managed by SCIM.
23+
# This is the recommended configuration when using an identity provider such as
24+
# Okta or Azure AD as the single source of truth for user provisioning.
25+
resource "dbtcloud_scim_config" "main" {
26+
enabled = true
27+
manual_updates_allowed = false
28+
scim_controlled_license_type = true
29+
}
30+
```
31+
32+
<!-- schema generated by tfplugindocs -->
33+
## Schema
34+
35+
### Required
36+
37+
- `enabled` (Boolean) Whether SCIM provisioning is enabled for the account.
38+
- `manual_updates_allowed` (Boolean) Whether administrators can manually update users and groups that are managed by SCIM. When set to ~~~false~~~, SCIM is the sole source of truth for user and group management.
39+
- `scim_controlled_license_type` (Boolean) Whether the dbt Cloud license type (Developer, Read-Only, IT) is controlled by SCIM attribute mapping. When set to ~~~false~~~, license types are managed manually inside dbt Cloud.
40+
41+
### Read-Only
42+
43+
- `id` (String) The ID of the resource (matches the dbt Cloud account ID).
44+
45+
## Import
46+
47+
Import is supported using the following syntax:
48+
49+
```shell
50+
# Singleton resource — import using the dbt Cloud account ID.
51+
terraform import dbtcloud_scim_config.main 12345
52+
```
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
page_title: "dbtcloud_scim_config_token Resource - dbtcloud"
3+
subcategory: ""
4+
description: |-
5+
Manages a SCIM API token for a dbt Cloud account. SCIM tokens are used by identity providers (e.g. Okta, Azure AD) to provision and deprovision users and groups automatically.
6+
The token value is only available immediately after creation and is stored in Terraform state as a sensitive value. It cannot be retrieved from the API afterwards.
7+
Requires the SCIM feature to be enabled on the account (enterprise plans only).
8+
---
9+
10+
# dbtcloud_scim_config_token (Resource)
11+
12+
13+
Manages a SCIM API token for a dbt Cloud account. SCIM tokens are used by identity providers (e.g. Okta, Azure AD) to provision and deprovision users and groups automatically.
14+
15+
The token value is only available immediately after creation and is stored in Terraform state as a sensitive value. It cannot be retrieved from the API afterwards.
16+
17+
Requires the SCIM feature to be enabled on the account (enterprise plans only).
18+
19+
## Example Usage
20+
21+
```terraform
22+
# Create a SCIM token to allow an identity provider (e.g. Okta, Azure AD) to
23+
# provision and deprovision users and groups in dbt Cloud.
24+
#
25+
# The token value is returned only on creation and stored in Terraform state
26+
# as a sensitive value. It is never returned by subsequent API reads, so
27+
# changing the `name` forces a new token to be created.
28+
resource "dbtcloud_scim_config_token" "okta" {
29+
name = "okta-scim"
30+
}
31+
32+
# The token string can be passed to other resources or outputs.
33+
# Mark outputs as sensitive when exposing the token value.
34+
output "scim_token" {
35+
value = dbtcloud_scim_config_token.okta.token_string
36+
sensitive = true
37+
}
38+
```
39+
40+
<!-- schema generated by tfplugindocs -->
41+
## Schema
42+
43+
### Required
44+
45+
- `name` (String) A human-readable name for the token. Changing this value forces a new token to be created.
46+
47+
### Read-Only
48+
49+
- `created_at` (String) Timestamp when the token was created.
50+
- `id` (Number) The ID of the SCIM token.
51+
- `last_used` (String) Timestamp when the token was last used. Null if never used.
52+
- `token_string` (String, Sensitive) The SCIM token value. Only available immediately after creation — not returned by subsequent API reads. Store this value securely.
53+
54+
## Import
55+
56+
Import is supported using the following syntax:
57+
58+
```shell
59+
# Import a SCIM config token by its numeric ID.
60+
# Note: token_string will be empty after import — the API never returns the
61+
# token value after creation. This is expected and documented behaviour.
62+
terraform import dbtcloud_scim_config_token.okta 12345
63+
```
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
terraform {
2+
required_providers {
3+
dbtcloud = {
4+
source = "dbt-labs/dbtcloud"
5+
version = ">= 0.3"
6+
}
7+
}
8+
}
9+
10+
provider "dbtcloud" {
11+
account_id = 1234
12+
token = "xxxx"
13+
host_url = "https://dbt.com/api"
14+
}
15+
16+
# ── Case 1: SCIM global config ────────────────────────────────────────────────
17+
# Start: enabled=true, manual_updates_allowed=false, scim_controlled_license_type=false
18+
# Then toggle to test updates:
19+
# Step 2 — manual_updates_allowed=true
20+
# Step 3 — scim_controlled_license_type=true
21+
# Step 4 — enabled=false (disables SCIM entirely)
22+
resource "dbtcloud_scim_config" "main" {
23+
enabled = true
24+
manual_updates_allowed = true
25+
scim_controlled_license_type = true
26+
}
27+
28+
# ── Case 2: create a SCIM token ───────────────────────────────────────────────
29+
resource "dbtcloud_scim_config_token" "test" {
30+
name = "tf-test-scim"
31+
}
32+
33+
output "scim_token" {
34+
value = dbtcloud_scim_config_token.test.token_string
35+
sensitive = true
36+
}
37+
38+
# ── Case 3: read back current config (no-op plan) ─────────────────────────────
39+
# After applying Case 1, comment it out and uncomment this to verify no drift.
40+
# resource "dbtcloud_scim_config" "main" {
41+
# enabled = true
42+
# manual_updates_allowed = false
43+
# scim_controlled_license_type = false
44+
# }
45+
46+
# ── Case 4: enable manual updates ─────────────────────────────────────────────
47+
# Uncomment and re-apply to test updating manual_updates_allowed=true.
48+
# resource "dbtcloud_scim_config" "main" {
49+
# enabled = true
50+
# manual_updates_allowed = true
51+
# scim_controlled_license_type = false
52+
# }
53+
54+
# ── Case 5: enable scim_controlled_license_type ───────────────────────────────
55+
# Uncomment and re-apply to test enabling license type control via SCIM.
56+
# resource "dbtcloud_scim_config" "main" {
57+
# enabled = true
58+
# manual_updates_allowed = true
59+
# scim_controlled_license_type = true
60+
# }
61+
62+
# ── Case 6: disable SCIM entirely ─────────────────────────────────────────────
63+
# Uncomment and re-apply to verify enabled=false is accepted and reflected.
64+
# resource "dbtcloud_scim_config" "main" {
65+
# enabled = false
66+
# manual_updates_allowed = false
67+
# scim_controlled_license_type = false
68+
# }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Singleton resource — import using the dbt Cloud account ID.
2+
terraform import dbtcloud_scim_config.main 12345
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Enable SCIM with strict IdP control — no manual updates, license type managed by SCIM.
2+
# This is the recommended configuration when using an identity provider such as
3+
# Okta or Azure AD as the single source of truth for user provisioning.
4+
resource "dbtcloud_scim_config" "main" {
5+
enabled = true
6+
manual_updates_allowed = false
7+
scim_controlled_license_type = true
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Import a SCIM config token by its numeric ID.
2+
# Note: token_string will be empty after import — the API never returns the
3+
# token value after creation. This is expected and documented behaviour.
4+
terraform import dbtcloud_scim_config_token.okta 12345
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Create a SCIM token to allow an identity provider (e.g. Okta, Azure AD) to
2+
# provision and deprovision users and groups in dbt Cloud.
3+
#
4+
# The token value is returned only on creation and stored in Terraform state
5+
# as a sensitive value. It is never returned by subsequent API reads, so
6+
# changing the `name` forces a new token to be created.
7+
resource "dbtcloud_scim_config_token" "okta" {
8+
name = "okta-scim"
9+
}
10+
11+
# The token string can be passed to other resources or outputs.
12+
# Mark outputs as sensitive when exposing the token value.
13+
output "scim_token" {
14+
value = dbtcloud_scim_config_token.okta.token_string
15+
sensitive = true
16+
}

pkg/dbt_cloud/scim_config.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package dbt_cloud
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"strconv"
8+
"strings"
9+
)
10+
11+
type SCIMConfig struct {
12+
Enabled bool `json:"enabled"`
13+
ManualUpdatesAllowed bool `json:"manual_updates_allowed"`
14+
SCIMControlledLicenseType bool `json:"scim_controlled_license_type"`
15+
}
16+
17+
type SCIMConfigResponse struct {
18+
Data SCIMConfig `json:"data"`
19+
Status ResponseStatus `json:"status"`
20+
}
21+
22+
func (c *Client) GetSCIMConfig() (*SCIMConfig, error) {
23+
req, err := http.NewRequest(
24+
"GET",
25+
fmt.Sprintf(
26+
"%s/v3/accounts/%s/scim-config/",
27+
c.HostURL,
28+
strconv.FormatInt(c.AccountID, 10),
29+
),
30+
nil,
31+
)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
body, err := c.doRequestWithRetry(req)
37+
if err != nil {
38+
return nil, err
39+
}
40+
41+
resp := SCIMConfigResponse{}
42+
if err = json.Unmarshal(body, &resp); err != nil {
43+
return nil, err
44+
}
45+
46+
return &resp.Data, nil
47+
}
48+
49+
func (c *Client) UpdateSCIMConfig(cfg SCIMConfig) (*SCIMConfig, error) {
50+
payload, err := json.Marshal(cfg)
51+
if err != nil {
52+
return nil, err
53+
}
54+
55+
req, err := http.NewRequest(
56+
"POST",
57+
fmt.Sprintf(
58+
"%s/v3/accounts/%s/scim-config/",
59+
c.HostURL,
60+
strconv.FormatInt(c.AccountID, 10),
61+
),
62+
strings.NewReader(string(payload)),
63+
)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
body, err := c.doRequestWithRetry(req)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
resp := SCIMConfigResponse{}
74+
if err = json.Unmarshal(body, &resp); err != nil {
75+
return nil, err
76+
}
77+
78+
return &resp.Data, nil
79+
}

0 commit comments

Comments
 (0)