From 46095ee04e520d5c97020c4d826c3664793670a7 Mon Sep 17 00:00:00 2001 From: rebelice Date: Thu, 15 Jan 2026 15:39:03 +0800 Subject: [PATCH] docs: add Workload Identity documentation for GitLab CI/CD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation for configuring Workload Identity with GitLab CI/CD, enabling secure authentication to Bytebase without long-lived credentials. - Create new gitlab-ci.mdx with step-by-step configuration guide - Include token exchange example using /v1/users/me for verification - Add complete GitOps workflow example with SQL review and rollout - Support self-hosted GitLab instances - Add troubleshooting section for common issues - Update docs.json navigation to include new page 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../workload-identity/gitlab-ci.mdx | 199 ++++++++++++++++++ docs/docs.json | 3 +- 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 docs/administration/user-groups/workload-identity/gitlab-ci.mdx diff --git a/docs/administration/user-groups/workload-identity/gitlab-ci.mdx b/docs/administration/user-groups/workload-identity/gitlab-ci.mdx new file mode 100644 index 00000000..cde83099 --- /dev/null +++ b/docs/administration/user-groups/workload-identity/gitlab-ci.mdx @@ -0,0 +1,199 @@ +--- +title: Workload Identity for GitLab CI/CD +--- + +This guide explains how to configure Workload Identity for GitLab CI/CD to authenticate with Bytebase without storing long-lived credentials. + +## Step 1: Create a Workload Identity in Bytebase + +1. Go to **IAM & Admin** > **Users & Groups**. +2. Click **Add User** in the upper-right corner. +3. Select **Workload Identity** as the Type. +4. Fill in the configuration: + +| Field | Description | Example | +|-------|-------------|---------| +| **Name** | Display name for this identity | `GitLab Deploy` | +| **Email** | Unique email prefix (automatically appended with `@workload.bytebase.com`) | `gitlab-deploy` | +| **Platform** | Select GitLab CI | `GitLab CI` | +| **Group / Username** | GitLab group or username (required) | `my-group` | +| **Project** | Project name (leave empty to allow all projects) | `my-project` | +| **Allowed Branches/Tags** | Select branch/tag restrictions | `All branches and tags` | +| **Roles** | Assign workspace roles | `GitOps Service Agent` | + +5. Click **Confirm** to create the Workload Identity. + +## Step 2: Assign Roles + +After creating the Workload Identity, assign the `GitOps Service Agent` role to enable automated CI/CD workflows: + +1. Go to your project's **Settings** > **Members**. +2. Click **Grant Access**. +3. Enter the Workload Identity email (e.g., `gitlab-ci-deploy@workload.bytebase.com`). +4. Select the **GitOps Service Agent** role. +5. Click **Confirm**. + + + +The `GitOps Service Agent` role is designed for automated CI/CD workflows, allowing the identity to create and execute database changes. See [Roles and Permissions](/administration/roles) for details. + + + +## Step 3: Configure GitLab CI/CD Pipeline + +In your GitLab CI/CD pipeline, add the following configuration: + +### Request OIDC Token + +Add `id_tokens` configuration to get the JWT token from GitLab: + +```yaml +stages: + - deploy + +deploy-database: + stage: deploy + image: alpine:latest + id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.com + variables: + BYTEBASE_URL: https://bytebase.example.com + WORKLOAD_IDENTITY_EMAIL: gitlab-ci-deploy@workload.bytebase.com + before_script: + - apk add --no-cache curl jq + script: + - | + # Exchange GitLab OIDC token for Bytebase API token + RESPONSE=$(curl -s -X POST "${BYTEBASE_URL}/v1/auth:exchangeToken" \ + -H "Content-Type: application/json" \ + -d "{\"token\": \"${GITLAB_OIDC_TOKEN}\", \"email\": \"${WORKLOAD_IDENTITY_EMAIL}\"}") + + ACCESS_TOKEN=$(echo $RESPONSE | jq -r '.accessToken') + if [ "$ACCESS_TOKEN" = "null" ] || [ -z "$ACCESS_TOKEN" ]; then + echo "Failed to get access token" + echo $RESPONSE + exit 1 + fi + + # Verify the token by calling the user info API + USER_INFO=$(curl -s "${BYTEBASE_URL}/v1/users/me" \ + -H "Authorization: Bearer $ACCESS_TOKEN") + echo "Authenticated as: $USER_INFO" + rules: + - if: $CI_COMMIT_BRANCH == "main" +``` + +## Complete Example + +Here's a complete GitOps workflow that uses Workload Identity to deploy database migrations: + +```yaml +# .gitlab-ci.yml +stages: + - review + - deploy + +variables: + BYTEBASE_URL: https://bytebase.example.com + WORKLOAD_IDENTITY_EMAIL: gitlab-deploy@workload.bytebase.com + +# SQL Review on merge requests +sql-review: + stage: review + image: bytebase/sql-review-action:latest + id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.com + script: + - | + # Exchange OIDC token for Bytebase token + export BYTEBASE_TOKEN=$(curl -s -X POST "${BYTEBASE_URL}/v1/auth:exchangeToken" \ + -H "Content-Type: application/json" \ + -d "{\"token\": \"${GITLAB_OIDC_TOKEN}\", \"email\": \"${WORKLOAD_IDENTITY_EMAIL}\"}" \ + | jq -r '.accessToken') + + # Run SQL review + sql-review --url ${BYTEBASE_URL} --token ${BYTEBASE_TOKEN} \ + --file-pattern "migrations/**/*.sql" + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + changes: + - migrations/** + +# Deploy on merge to main +rollout: + stage: deploy + image: bytebase/bytebase-action:latest + id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.com + script: + - | + # Exchange OIDC token for Bytebase token + export BYTEBASE_TOKEN=$(curl -s -X POST "${BYTEBASE_URL}/v1/auth:exchangeToken" \ + -H "Content-Type: application/json" \ + -d "{\"token\": \"${GITLAB_OIDC_TOKEN}\", \"email\": \"${WORKLOAD_IDENTITY_EMAIL}\"}" \ + | jq -r '.accessToken') + + # Create release and rollout + bytebase-action rollout \ + --url ${BYTEBASE_URL} \ + --token ${BYTEBASE_TOKEN} \ + --file-pattern "migrations/**/*.sql" \ + --project projects/my-project \ + --targets instances/prod/databases/mydb + rules: + - if: $CI_COMMIT_BRANCH == "main" + changes: + - migrations/** +``` + + + +For more details on GitOps workflows, see [GitOps Overview](/gitops/overview) and [Migration-Based Workflow](/gitops/migration-based-workflow/overview). + + + +## Self-Hosted GitLab + +For self-hosted GitLab instances, update the audience (`aud`) to match your GitLab instance URL: + +```yaml +id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.your-company.com +``` + +When creating the Workload Identity in Bytebase, ensure the configuration matches your self-hosted GitLab instance. + +## Troubleshooting + +### Token Exchange Fails + +If the token exchange returns an error: + +1. **Verify the project path and branch**: Check that your pipeline's project path and branch match the configured values in Bytebase. + +2. **Check the audience**: Ensure the `aud` in your `id_tokens` configuration matches your GitLab instance URL (e.g., `https://gitlab.com` for GitLab.com). + +3. **Verify OIDC is enabled**: GitLab CI/CD OIDC tokens require GitLab 15.7 or later. + +### Permission Denied + +If API calls return permission errors: + +1. Verify the Workload Identity has the `GitOps Service Agent` role assigned. +2. Check that the Workload Identity is a member of the target project. + +### Debug Token Claims + +To inspect the OIDC token claims, decode the JWT: + +```yaml +script: + - | + echo "$GITLAB_OIDC_TOKEN" | cut -d. -f2 | base64 -d | jq . +``` + +This shows the token's claims including `sub`, `aud`, `namespace_path`, `project_path`, and `ref` that Bytebase validates. diff --git a/docs/docs.json b/docs/docs.json index b2e70759..1956e80b 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -247,7 +247,8 @@ "group": "Users & Groups", "pages": [ "administration/user-groups/overview", - "administration/user-groups/workload-identity/github-actions" + "administration/user-groups/workload-identity/github-actions", + "administration/user-groups/workload-identity/gitlab-ci" ] }, "administration/roles",