diff --git a/baton/argo-cd.mdx b/baton/argo-cd.mdx index c49461ca..4e37472f 100644 --- a/baton/argo-cd.mdx +++ b/baton/argo-cd.mdx @@ -8,16 +8,69 @@ sidebarTitle: "ArgoCD" ## Capabilities -| Resource | Sync | Provision | -| :--- | :--- | :--- | -| Accounts | | | -| Roles | | | +| Resource | Sync | Provision | Deprovision | +| :--- | :--- | :--- | :--- | +| Accounts | | | | +| Roles | | | — | -The ArgoCD connector supports [automatic account provisioning](/product/admin/account-provisioning). +The ArgoCD connector supports [automatic account provisioning and deprovisioning](/product/admin/account-provisioning). When a new account is created by C1, the account's password will be sent to a [vault](/product/admin/vaults). -This connector does not support account deprovisioning. You must deprovision accounts directly in ArgoCD. +The connector also supports credential rotation for local accounts: C1 sets a new random password +and sends it to a vault. ArgoCD rejects every session and API token issued before a password +change, so rotation also cuts off the account's existing access. + +## Connector actions + +Connector actions are custom capabilities that extend C1 automations with app-specific operations. + +| Automation step | Actions offered | How the target is selected | +| :--- | :--- | :--- | +| Account lifecycle action | `enable_user`, `disable_user` | The step's own target-account selector — either the account in context or a specific account. C1 resolves `user_id` from that account. | +| [Perform connector action](/product/admin/automations-steps-reference#perform-connector-action) | `revoke_tokens` | Set `user_id` to the ArgoCD account name. | + +| Action name | Additional fields | Description | +| :--- | :--- | :--- | +| `disable_user` | `user_id` (string, required) | Disables an ArgoCD local account. ArgoCD rejects the account's password and API tokens while it is disabled. Reversible with `enable_user`. | +| `enable_user` | `user_id` (string, required) | Re-enables a disabled ArgoCD local account, restoring its existing password and API tokens. | +| `revoke_tokens` | `user_id` (string, required) | Revokes every API token issued to an ArgoCD local account. The account, its password and its enabled state are unchanged. Run it with `disable_user` when a re-enabled account must not get its old tokens back. | + +## Account lifecycle + +The connector manages ArgoCD **local accounts**. ArgoCD's Account API exposes no delete, disable +or enable endpoint, so the connector changes accounts through the Kubernetes API, using the +permissions described in [Gather ArgoCD credentials](#gather-argocd-credentials). + +- **Disable / enable** (the `disable_user` and `enable_user` actions) are reversible. The account + keeps its password and API tokens, which ArgoCD refuses while the account is disabled and + accepts again once it is enabled. +- **Revoke API tokens** (the `revoke_tokens` action) removes the account's API tokens without + touching the account itself. +- **Rotate password** (credential rotation) sets a new random password and invalidates every + session and API token issued before it. +- **Delete** (account deprovisioning) is permanent. It revokes the account's API tokens, removes + its role grants and direct permissions, removes the account, and purges its stored credentials, + so an account created later with the same name inherits none of them. + +Use `disable_user` to suspend access you may need to restore, and delete to remove the account +for good. + +**Notes:** + +- The built-in `admin` account cannot be disabled, enabled, rotated, stripped of its tokens or + deleted. The connector also refuses to do any of these, except enable, to the account it + authenticates as, since it would lock itself out of ArgoCD. SSO/Dex-managed identities are not + local accounts, so there is nothing for the connector to manage for them. +- Disabling a disabled account, enabling an enabled account, revoking the tokens of an account + that has none, or deleting an account that is already gone is reported as success. The actions + and rotation fail with a not-found error for an account ArgoCD does not know. +- Account names may contain only alphanumerics, `-` and `_`. Names containing `.` are rejected, + since ArgoCD cannot address them as accounts. +- Deleting an account rewrites `policy.csv` in `argocd-rbac-cm`, which removes its `#` comment lines. +- Revoking tokens and rotating another account's password need the `accounts, update` ArgoCD RBAC + permission for the connector's account. Deleting accounts also requires the `secrets` Kubernetes + permissions described below. ## Gather ArgoCD credentials @@ -25,10 +78,12 @@ Configuring the connector requires you to pass in credentials generated in ArgoC ### Create a Role with required permissions -The connector needs permissions to read and modify ArgoCD ConfigMaps. Create a Role that grants access to the following ConfigMaps: +The connector needs permissions to read and modify ArgoCD ConfigMaps, and to read and patch the +ArgoCD Secret. Create a Role that grants access to the following objects: -- `argocd-rbac-cm`: Contains RBAC policies and role grants (needs read and write access) -- `argocd-cm`: Contains ArgoCD configuration including user accounts (needs write access for provisioning) +- `argocd-rbac-cm` ConfigMap: Contains RBAC policies and role grants (needs read and write access) +- `argocd-cm` ConfigMap: Contains ArgoCD configuration including user accounts (needs write access for provisioning, deprovisioning and the enable/disable actions) +- `argocd-secret` Secret: Contains local accounts' password hashes and API token records (needs read and write access for account deletion) ```yaml apiVersion: rbac.authorization.k8s.io/v1 @@ -40,6 +95,10 @@ rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "patch", "update"] + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["argocd-secret"] + verbs: ["get", "patch"] ``` **Required Permissions Explained:** @@ -48,6 +107,13 @@ rules: - `list`: List ConfigMaps in the namespace (required to discover and access the ConfigMaps) - `patch`: Partially update ConfigMaps (used to modify RBAC policies and user accounts) - `update`: Fully update ConfigMaps (used as an alternative to patch for modifying ConfigMaps) +- `get`/`patch` on `secrets`: Read and purge a deleted account's stored credentials in `argocd-secret`. Restricted to that one Secret by name, so the connector cannot read the repository and cluster credentials that also live in the `argocd` namespace. Only needed for account deletion; omit the rule entirely if you do not use it. + + + The `argocd-secret` permissions are new. Existing deployments must re-apply this role before + account deletion is used. Without them the credential-purge step fails with a `403` after the + account has already been deleted, leaving its stored credentials in place. + Apply with: diff --git a/baton/azure-devops.mdx b/baton/azure-devops.mdx index d99ae4c0..32efc201 100644 --- a/baton/azure-devops.mdx +++ b/baton/azure-devops.mdx @@ -146,7 +146,8 @@ You can authenticate the Azure DevOps connector in three ways: OAuth (interactiv - vso.graph - vso.tokenadministration (required to sync personal access tokens) - vso.auditlog (required if you enable incremental sync) - - vso.identity (optional — required only when **Legacy group identity resolution** is enabled) + - vso.identity (optional — required when **Legacy group identity resolution** is enabled, or to sync all team administrators) + - vso.security\_manage (optional — required to sync all team administrators) **For full provisioning (read/write) access:** - user\_impersonation (required - Azure DevOps only allows delegated permissions) @@ -155,7 +156,8 @@ You can authenticate the Azure DevOps connector in three ways: OAuth (interactiv - vso.memberentitlementmanagement\_write - vso.tokenadministration (required to sync personal access tokens) - vso.auditlog (required if you enable incremental sync) - - vso.identity (optional — required only when **Legacy group identity resolution** is enabled) + - vso.identity (optional — required when **Legacy group identity resolution** is enabled, or to sync all team administrators) + - vso.security\_manage (optional — required to sync all team administrators) Click **Add permissions**. @@ -267,6 +269,9 @@ Azure DevOps groups, configure the connector with OAuth To enable incremental sync (optional): - **Audit Log: Read** - Required if you want to enable the incremental sync feature, which syncs only changes since the last sync (`vso.auditlog`) - **Identity: Read** - Required only if you also enable **Legacy group identity resolution** to resolve legacy group descriptors via the Identities API (`vso.identity`). This setting defaults to off and is separate from Graph: Read. + To sync all team administrators, including those who aren't team members (optional): + - **Security: Manage** - Required to read the team's administrators (`vso.security_manage`) + - **Identity: Read** - Required to identify each team administrator (`vso.identity`) Click **Create**. diff --git a/baton/azure.mdx b/baton/azure.mdx index 91ad4dc1..639f0a6a 100644 --- a/baton/azure.mdx +++ b/baton/azure.mdx @@ -15,6 +15,7 @@ The Microsoft Azure connector uses the [Cloud Infrastructure Access](/product/ad | Accounts | | | | Groups | | | | Managed identities | | | +| Enterprise applications | | | | Azure roles | | | | Tenant root | | | | Management groups | | | @@ -22,7 +23,7 @@ The Microsoft Azure connector uses the [Cloud Infrastructure Access](/product/ad | Subscriptions | | | | Azure resources (opt-in) | | | - This connector pulls account, group, and managed identity information from the Entra ID connector. You'll configure this relationship when setting up the connector. + This connector pulls account, group, managed identity, and enterprise application information from the Entra ID connector. You'll configure this relationship when setting up the connector. ## Gather Azure credentials @@ -168,10 +169,68 @@ az role assignment delete \ ### Optional configuration -Two additional settings are available in the connector's configuration form: +Three additional settings are available in the connector's configuration form: - **Azure cloud** — the Azure cloud environment to connect to: `public` (default), `usgovernment`, or `china`. This is the only way to point the connector at the US Government or China clouds instead of the public Azure cloud. - **Skip roles with no assignments** — when enabled, only Azure roles with at least one active assignment are synced, instead of every role definition in scope. +- **Sync sub-resources** — which kinds of nested sub-resource to sync. Leave empty to sync none. Sub-resources are not a separate resource type: each one is synced as an **Azure resource**, nested under the Azure resource that owns it. + + +**Sync sub-resources only has an effect if the Azure resources resource type is enabled.** + +Sub-resources are synced as children of the Azure resources that own them — a blob container is +synced under its storage account. If Azure resources are not being synced, there are no parents +to sync them under, and enabling this setting does nothing. + + +#### Supported sub-resource types + +Each value below is a scope Azure documents as directly role-assignable. Everything listed here +syncs as an Azure resource — the values select which kinds are included, not which resource types +exist. Select only the ones you need: **each selected value costs one extra API call per parent +resource, on every sync.** + +| Value | Syncs, as an Azure resource | Nested under | +| :--- | :--- | :--- | +| `blob_containers` | Blob containers | Storage accounts | +| `storage_queues` | Storage queues | Storage accounts | +| `storage_tables` | Storage tables | Storage accounts | +| `service_bus_queues` | Service Bus queues | Service Bus namespaces | +| `service_bus_topics` | Service Bus topics | Service Bus namespaces | +| `event_hubs` | Event hubs | Event Hubs namespaces | +| `subnets` | Subnets | Virtual networks | + +Not currently supported: Key Vault secrets, keys and certificates (listing them requires a Key +Vault data-plane connection, which is separate from the Azure Resource Manager access this +connector uses), Azure Files shares, Service Bus topic subscriptions, and Event Hubs consumer +groups. + +#### Why sync sub-resources + +Azure allows a role to be assigned directly at a sub-resource scope. A common example is granting +`Storage Blob Data Contributor` on a single blob container rather than on the whole storage +account: + +``` +/subscriptions/{id}/resourceGroups/{rg}/providers/Microsoft.Storage/storageAccounts/{account}/blobServices/default/containers/{container} +``` + +Assignments made at those scopes are only visible in C1 if the sub-resource itself is synced. +With this setting disabled, access granted on an individual container does not appear anywhere, +even though the storage account above it syncs normally. + +The trade-off is API calls: each selected type costs one additional request per parent resource +per sync — selecting all three storage types means three extra calls for every storage account in +the tenant. That is why nothing is selected by default, and why the types are chosen individually +rather than with a single on/off switch. + + +If a resource cannot be listed because it does not offer that sub-resource at all — a disabled +storage account, or a Premium account that has no queue or table service — the connector skips it +and continues syncing everything else. A permissions error is different: if the connector is not +allowed to list a resource's children, the sync fails, because silently syncing less access than +exists would be misleading. + ## Configure the Azure connector @@ -227,8 +286,9 @@ Click **Save**. Finally, tell the connector where to find the identities that will be used for this app in C1. 1. In the **Shared identity source** area of the page, click **Edit**. 2. Select your Entra connector. - 3. **Optional.** Limit the identities pulled from the connector you selected to only those with a certain entitlement by setting the entitlement. - 4. Click **Save**. + 3. Under **Only import identities of type**, select **Users**, **Groups**, and **Apps**. Azure reports both managed identities and enterprise applications as service principals, so role assignments held by an enterprise application only resolve when **Apps** is selected. + 4. **Optional.** Limit the identities pulled from the connector you selected to only those with a certain entitlement by setting the entitlement. + 5. Click **Save**. The connector's label changes to **Syncing**, followed by **Connected**. You can view the logs to ensure that information is syncing. diff --git a/baton/coupa.mdx b/baton/coupa.mdx index 19381edf..174a7fc5 100644 --- a/baton/coupa.mdx +++ b/baton/coupa.mdx @@ -50,7 +50,7 @@ C1 can create Coupa user accounts. When you configure account provisioning for t Every field is optional to C1. Map **First name** and **Last name** regardless — Coupa has no other source for a new user's name. -Accounts are created active. Coupa authenticates through SSO, so no password is set. +Accounts are created active. The connector does not set a password. Custom fields are sent in Coupa's `custom-fields` namespace. License assignments can also be managed after account creation through C1 License Management. diff --git a/baton/databricks.mdx b/baton/databricks.mdx index 7e61eccb..4e8ca893 100644 --- a/baton/databricks.mdx +++ b/baton/databricks.mdx @@ -21,13 +21,9 @@ The Databricks connector supports [automatic account provisioning and deprovisio [This connector syncs non-human identities](/product/admin/nhi) and displays them on the **Identities overview** dashboard. - -Provisioning **account groups** requires OAuth authentication. It is not available when authenticating with a workspace token, because the Databricks API does not allow provisioning account groups from a workspace token. Workspace-scoped groups can still be provisioned with a workspace token. - - ## Authentication methods -The connector authenticates with **OAuth** — an account-level service principal's client ID and secret. This is the only method currently offered. +The connector authenticates with **OAuth** — an account-level service principal's client ID and secret. This is the only authentication method the connector supports. ## Gather Databricks credentials