diff --git a/content/docs/sidebar.json b/content/docs/sidebar.json
index fc87ae242f..cb882db95b 100644
--- a/content/docs/sidebar.json
+++ b/content/docs/sidebar.json
@@ -731,6 +731,10 @@
"children": ["github-app", "custom-gitlab-server"]
},
"single-sign-on",
+ {
+ "label": "OpenID Connect",
+ "slug": "openid-connect"
+ },
"troubleshooting"
]
},
diff --git a/content/docs/studio/user-guide/account-management/index.md b/content/docs/studio/user-guide/account-management/index.md
index 5e73b17ce9..ebcb533fad 100644
--- a/content/docs/studio/user-guide/account-management/index.md
+++ b/content/docs/studio/user-guide/account-management/index.md
@@ -122,6 +122,14 @@ you can find more details about required permissions [here][data remote].
Finally, click `Save credentials`.
+
+
+DVC Studio also supports
+[OpenID Connect authentication](/doc/studio/user-guide/openid-connect) for some
+cloud providers.
+
+
+
## Teams
In this section, you can view all the teams you are member of.
diff --git a/content/docs/studio/user-guide/openid-connect.md b/content/docs/studio/user-guide/openid-connect.md
new file mode 100644
index 0000000000..f74c81f3b0
--- /dev/null
+++ b/content/docs/studio/user-guide/openid-connect.md
@@ -0,0 +1,300 @@
+# OpenID Connect (OIDC)
+
+DVC Studio can use OpenID Connect to access cloud resources securely, without
+requiring manual configuration of static credentials.
+
+To use OIDC, first follow the [cloud configuration](#cloud-configuration)
+instructions and then the [Studio configuration](#studio-configuration)
+instructions.
+
+## Cloud configuration
+
+
+
+### Generic configuration options
+
+- OpenID Connect Discovery URL:
+ https://studio.iterative.ai/api/.well-known/openid-configuration
+
+- Subject claim format: `credentials:{owner}/{name}` where `{owner}` is the name
+ of the DVC Studio **user** or **team** owning the credentials, and `{name}` is
+ the name of the DVC Studio
+ [credentials](/doc/studio/user-guide/account-management#cloud-credentials).
+
+
+
+### Terraform examples
+
+The following Terraform examples illustrate how to configure the supported cloud
+providers, granting DVC Studio access to object storage resources through OpenID
+Connect. Update the fields as described below and then apply the Terraform
+configuration. Make note of the outputs of `terraform apply`, since you will
+need to enter those for [Studio configuration](#studio-configuration).
+
+
+
+Replace the sample `credentials:example-team/example-credentials` subject claim
+condition. Replace `example-team` with the Studio **user** or **team** owning
+the credentials, and replace `example-credentials` with any name you want to use
+for those credentials. This name must match what you enter during
+[Studio configuration](#studio-configuration).
+
+
+
+
+
+### Amazon Web Services
+
+```hcl
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 4.16"
+ }
+ }
+
+ required_version = ">= 1.2.0"
+}
+
+provider "aws" {
+ region = "us-east-1"
+}
+
+locals {
+ provider = "studio.iterative.ai/api"
+ condition = "credentials:example-team/example-credentials"
+}
+
+data "tls_certificate" "studio" {
+ url = "https://${local.provider}"
+}
+
+data "aws_iam_policy_document" "studio_assume_role" {
+ statement {
+ effect = "Allow"
+ actions = ["sts:AssumeRoleWithWebIdentity"]
+
+ principals {
+ type = "Federated"
+ identifiers = [aws_iam_openid_connect_provider.studio.arn]
+ }
+
+ condition {
+ test = "ForAnyValue:StringLike"
+ variable = "${aws_iam_openid_connect_provider.studio.url}:sub"
+ values = [local.condition]
+ }
+ }
+}
+
+data "aws_iam_policy_document" "studio" {
+ statement {
+ actions = ["s3:*"]
+ resources = ["*"]
+ }
+}
+
+resource "aws_iam_openid_connect_provider" "studio" {
+ url = data.tls_certificate.studio.url
+ client_id_list = ["sts.amazonaws.com"]
+ thumbprint_list = [data.tls_certificate.studio.certificates.0.sha1_fingerprint]
+}
+
+resource "aws_iam_role" "studio" {
+ max_session_duration = 12 * 60 * 60 # 12 hours
+ assume_role_policy = data.aws_iam_policy_document.studio_assume_role.json
+
+ inline_policy {
+ name = "studio"
+ policy = data.aws_iam_policy_document.studio.json
+ }
+}
+
+output "role_arn" {
+ value = aws_iam_role.studio.arn
+}
+```
+
+
+
+
+### Google Cloud
+
+```hcl
+terraform {
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = "5.13.0"
+ }
+ }
+}
+
+provider "google" {
+ project = "iterative-sandbox"
+ region = "us-central1"
+}
+
+locals {
+ provider = "studio.iterative.ai/api"
+ condition = "credentials:example-team/example-credentials"
+}
+
+data "google_project" "current" {}
+
+resource "google_project_organization_policy" "credential_lifetime_extension" {
+ project = data.google_project.current.project_id
+ constraint = "constraints/iam.allowServiceAccountCredentialLifetimeExtension"
+
+ list_policy {
+ allow {
+ all = true
+ }
+ }
+}
+
+resource "google_iam_workload_identity_pool" "studio" {
+ workload_identity_pool_id = "iterative-studio"
+}
+
+resource "google_iam_workload_identity_pool_provider" "studio" {
+ workload_identity_pool_provider_id = "studio"
+ workload_identity_pool_id = google_iam_workload_identity_pool.studio.workload_identity_pool_id
+
+ attribute_mapping = {
+ "google.subject" = "assertion.sub"
+ }
+
+ oidc {
+ issuer_uri = "https://${local.provider}"
+ }
+}
+
+resource "google_service_account" "studio" {
+ account_id = "iterative-studio"
+}
+
+resource "google_service_account_iam_binding" "workload_identity_binding" {
+ service_account_id = google_service_account.studio.name
+ role = "roles/iam.workloadIdentityUser"
+ members = ["principal://iam.googleapis.com/${google_iam_workload_identity_pool.studio.name}/subject/${local.condition}"]
+}
+
+resource "google_project_iam_member" "studio" {
+ project = data.google_project.current.project_id
+ role = "roles/storage.admin"
+ member = "serviceAccount:${google_service_account.studio.email}"
+}
+
+output "workload_identity_provider" {
+ value = google_iam_workload_identity_pool_provider.studio.name
+}
+
+output "service_account" {
+ value = google_service_account.studio.email
+}
+
+output "project_id" {
+ value = data.google_project.current.project_id
+}
+```
+
+
+
+
+### Microsoft Azure
+
+```hcl
+terraform {
+ required_providers {
+ azurerm = {
+ source = "hashicorp/azurerm"
+ version = "3.61.0"
+ }
+ azuread = {
+ source = "hashicorp/azuread"
+ version = "2.30.0"
+ }
+ }
+}
+
+provider "azuread" {}
+
+provider "azurerm" {
+ features {}
+}
+
+locals {
+ provider = "studio.iterative.ai/api"
+ condition = "credentials:example-team/example-credentials"
+}
+
+data "azuread_client_config" "current" {}
+data "azurerm_subscription" "current" {}
+
+resource "azuread_application" "studio" {
+ display_name = "studio"
+
+ api {
+ requested_access_token_version = 2
+ }
+}
+
+resource "azuread_service_principal" "studio" {
+ application_id = azuread_application.studio.application_id
+ owners = [data.azuread_client_config.current.object_id]
+}
+
+resource "azuread_application_federated_identity_credential" "studio" {
+ application_object_id = azuread_application.studio.object_id
+ display_name = azuread_application.studio.display_name
+ audiences = ["api://AzureADTokenExchange"]
+ issuer = "https://${local.provider}"
+ subject = local.condition
+}
+
+resource "azurerm_role_definition" "studio" {
+ name = azuread_application.studio.display_name
+ scope = data.azurerm_subscription.current.id
+ permissions {
+ actions = [
+ "Microsoft.Storage/storageAccounts/listKeys/action",
+ "Microsoft.Storage/storageAccounts/read",
+ ]
+ }
+}
+
+resource "azurerm_role_assignment" "example" {
+ name = azurerm_role_definition.studio.role_definition_id
+ scope = data.azurerm_subscription.current.id
+ role_definition_id = azurerm_role_definition.studio.role_definition_resource_id
+ principal_id = azuread_service_principal.studio.object_id
+}
+
+output "azure_subscription_id" {
+ value = basename(data.azurerm_subscription.current.id)
+}
+
+output "azure_tenant_id" {
+ value = data.azurerm_subscription.current.tenant_id
+}
+
+output "azure_client_id" {
+ value = azuread_application.studio.application_id
+}
+```
+
+
+
+## Studio configuration
+
+[Create new credentials](/doc/studio/user-guide/account-management#cloud-credentials)
+and configure them as follows:
+
+1. Choose an adequate OIDC variant on the provider field; e.g. _Amazon Web
+ Services (OIDC)_.
+2. Enter the name for the credentials. This must match the name used during
+ [cloud configuration](#cloud-configuration).
+3. Fill the remaining fields with the outputs of the cloud configuration
+ described above.