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
18 changes: 18 additions & 0 deletions developer/terraform-best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@

Use [conductorone_custom_app_entitlement](https://registry.terraform.io/providers/ConductorOne/conductorone/latest/docs/resources/custom_app_entitlement) when you need to create a virtual entitlement for a permission not yet discovered by a connector.

This resource also supports the `match_baton_id` field, which links the Terraform resource to an external ID (such as an Okta group ID). When the connector syncs, C1 merges the two rather than creating a duplicate.

Check warning on line 98 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L98

Did you really mean 'Okta'?

```hcl
data "conductorone_app" "okta_app" {
Expand Down Expand Up @@ -184,7 +184,7 @@
}
```

### Example: configure multistep provisioning

Check warning on line 187 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L187

Did you really mean 'multistep'?

Use this pattern when granting access requires more than one provisioning action — for example, delegating to another app's entitlement before running the connector.

Expand Down Expand Up @@ -217,6 +217,7 @@
- **Terraform import is not required.** Reference the entitlement by ID using a data source lookup.
- **JSON encoding is required** for `multi_step` provisioning and `account_provision` config blocks.
- **Entitlement owners** are managed with a separate resource, [conductorone_app_entitlement_owner](https://registry.terraform.io/providers/ConductorOne/conductorone/latest/docs/resources/app_entitlement_owner). Owners are always a list of C1 users — the resource accepts `user_ids` only, and setting the list replaces any existing owners for that entitlement. See the example below.
- **App-level owners** are managed with [conductorone_app_owner](https://registry.terraform.io/providers/ConductorOne/conductorone/latest/docs/resources/app_owner), which takes an `app_id` and a `user_ids` list. Setting `user_ids` replaces any existing owners for the app, and changing either field forces the resource to be replaced.

### Example: manage entitlement owners

Expand All @@ -233,6 +234,23 @@
}
```

### Example: manage app owners

Use the same pattern with `conductorone_app_owner` to set the owners of an app, replacing any owners currently set.

```hcl
resource "conductorone_app_owner" "aws_owners" {
app_id = data.conductorone_app.aws.id
user_ids = [
data.conductorone_user.alice.id,
]
}
```

<Note>
When looking up users, the [conductorone_user](https://registry.terraform.io/providers/ConductorOne/conductorone/latest/docs/data-sources/user) data source returns a single user matching your search criteria, while [conductorone_users](https://registry.terraform.io/providers/ConductorOne/conductorone/latest/docs/data-sources/users) returns a paginated `list` of matching users. Use `conductorone_user` when you need one user's ID (as in the examples above) and `conductorone_users` when you need to iterate over multiple users.
</Note>

<Tip>
`duration_grant` and `duration_unset` are mutually exclusive. Set `duration_grant` to a duration string in seconds (for example, `"3600s"` for one hour) to cap how long a grant lasts. Set `duration_unset = {}` for no maximum duration. Never set both.
</Tip>
Expand All @@ -241,7 +259,7 @@

## Creating access profiles

Access profiles group multiple entitlements into a single requestable bundle. The C1 UI calls these "access profiles," but the Terraform provider and API use the term "catalog" — you'll see `catalog_id` as a field name throughout these resources.

Check warning on line 262 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L262

Did you really mean 'requestable'?

A fully configured access profile requires five related resources:

Expand Down Expand Up @@ -277,15 +295,15 @@
| `REQUEST_CATALOG_ENROLLMENT_BEHAVIOR_BYPASS_ENTITLEMENT_REQUEST_POLICY` | Bypasses individual entitlement approval policies. Users get all entitlements in a single request. |
| `REQUEST_CATALOG_ENROLLMENT_BEHAVIOR_ENFORCE_ENTITLEMENT_REQUEST_POLICY` | Enforces each entitlement's approval policy individually during enrollment. |

**`unenrollment_behavior`** — controls what happens to a user's entitlements when they unenroll:

Check warning on line 298 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L298

Did you really mean 'unenroll'?

| Value | Behavior |
|---|---|
| `REQUEST_CATALOG_UNENROLLMENT_BEHAVIOR_REVOKE_ALL` | Revokes all entitlements in the profile. |
| `REQUEST_CATALOG_UNENROLLMENT_BEHAVIOR_REVOKE_UNJUSTIFIED` | Revokes only entitlements the user doesn't hold through another path. |
| `REQUEST_CATALOG_UNENROLLMENT_BEHAVIOR_LEAVE_ACCESS_AS_IS` | Leaves all entitlements in place after unenrollment. |

Check warning on line 304 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L304

Did you really mean 'unenrollment'?

**`unenrollment_entitlement_behavior`** — controls whether approval policies are enforced when revoking entitlements at unenrollment:

Check warning on line 306 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L306

Did you really mean 'unenrollment'?

| Value | Behavior |
|---|---|
Expand All @@ -293,7 +311,7 @@
| `REQUEST_CATALOG_UNENROLLMENT_ENTITLEMENT_BEHAVIOR_ENFORCE` | Enforces each entitlement's revoke policy individually. |

- **`request_bundle`**: Set to `"true"` to allow users to request the entire profile as a bundle rather than individual entitlements.
- **`create_requests`**: Set to `"true"` to create provisioning tasks when users enroll or unenroll.

Check warning on line 314 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L314

Did you really mean 'unenroll'?

### Step 2: Set the grant and revoke policies

Expand Down Expand Up @@ -414,7 +432,7 @@
### Keep in mind

- Always use `depends_on` to ensure the policy (Step 2) is applied before bundle automation (Step 5).
- Use Option A for single-workspace configs. Use Option B when entitlements span multiple workspaces, or when you need per-entitlement `create_requests` settings.

Check warning on line 435 in developer/terraform-best-practices.mdx

View check run for this annotation

Mintlify / Mintlify Validation (conductorone) - vale-spellcheck

developer/terraform-best-practices.mdx#L435

Did you really mean 'configs'?
- Keep `published = "false"` while configuring. This prevents users from requesting an incomplete profile.

---
Expand Down
11 changes: 11 additions & 0 deletions product/admin/groups.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ Yes. Add the group's entitlement to an app's [requestable entitlements](/product

Members added through a request aren't removed by the group's membership automation rule — the same protection that already applies to users you add manually.

</Accordion>
<Accordion title="How do I fetch C1 groups with the API?">

There is no dedicated groups endpoint in the C1 API. C1 groups are resources of the group resource type in the C1 app, so you fetch them with the app resource endpoints:

1. Find the group resource type for the C1 app: `GET /api/v1/apps/{app_id}/resource_types`
2. List the group resources of that type: `GET /api/v1/apps/{app_id}/resource_types/{app_resource_type_id}/resources`
3. To get a group's entitlements (such as its member entitlement), list the entitlements associated with that resource: `GET /api/v1/apps/{app_id}/entitlements/resource_types/{app_resource_type_id}/resources/{app_resource_id}`

In each request, `app_id` is the ID of the built-in C1 app.

</Accordion>
</AccordionGroup>

Expand Down