> ## Documentation Index
> Fetch the complete documentation index at: https://www.c1.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions integration

> Set up secretless authentication from GitHub Actions to C1 using the oidc-token-action.

<Warning>
  **Early access.** This feature is in early access, which means it's undergoing ongoing testing and development while we gather feedback, validate functionality, and improve outputs. Contact the C1 Support team if you'd like to try it out or share feedback.
</Warning>

The `conductorone/oidc-token-action` GitHub Action exchanges a GitHub Actions OIDC token for a C1 access token in a single step. No secrets to store or rotate.

## Prerequisites

* A service principal with a GitHub Actions federation trust. See [set up federation](/product/admin/service-principals/federation-setup) if you haven't created one yet.
* The trust's **client ID** (for example `swift-otter-19384@yourcompany.conductor.one/wfe`)

## Set up the workflow

Add the action to your workflow file. Your workflow must have `id-token: write` permission for GitHub to issue the OIDC token.

```yaml theme={"theme":{"light":"css-variables","dark":"css-variables"}}
# .github/workflows/deploy.yml
name: Deploy with C1

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: conductorone/oidc-token-action@v1
        with:
          audience: yourcompany.conductor.one
          client_id: swift-otter-19384@yourcompany.conductor.one/wfe

      # CONDUCTORONE_ACCESS_TOKEN is now set for all subsequent steps
```

The action:

1. Requests a GitHub OIDC token with your tenant domain as the audience
2. Exchanges it for a C1 access token via token exchange
3. Exports `CONDUCTORONE_ACCESS_TOKEN` and `CONDUCTORONE_CLIENT_ID` as environment variables
4. Masks the token in logs to prevent accidental exposure
5. Cleans up the environment variables when the job finishes

## Use with downstream tools

After the action runs, `CONDUCTORONE_ACCESS_TOKEN` is available to all subsequent steps. Every C1 tool recognizes this variable automatically.

### Cone CLI

```yaml theme={"theme":{"light":"css-variables","dark":"css-variables"}}
      - uses: conductorone/oidc-token-action@v1
        with:
          audience: yourcompany.conductor.one
          client_id: swift-otter-19384@yourcompany.conductor.one/wfe

      - run: cone whoami
```

### Terraform

```yaml theme={"theme":{"light":"css-variables","dark":"css-variables"}}
      - uses: conductorone/oidc-token-action@v1
        with:
          audience: yourcompany.conductor.one
          client_id: swift-otter-19384@yourcompany.conductor.one/wfe

      - uses: hashicorp/setup-terraform@v3
      - run: terraform apply
```

### Direct API calls

```yaml theme={"theme":{"light":"css-variables","dark":"css-variables"}}
      - uses: conductorone/oidc-token-action@v1
        with:
          audience: yourcompany.conductor.one
          client_id: swift-otter-19384@yourcompany.conductor.one/wfe

      - run: |
          curl -s "https://yourcompany.conductor.one/api/v1/apps" \
            -H "Authorization: Bearer $CONDUCTORONE_ACCESS_TOKEN"
```

## CEL expression examples

When creating the federation trust, the CEL expression controls which GitHub Actions workflows can authenticate. The expression evaluates against the GitHub OIDC token's claims.

### Restrict to a repository

```go theme={"theme":{"light":"css-variables","dark":"css-variables"}}
claims.repository == "acme/infra"
```

### Restrict to a repository and branch

```go theme={"theme":{"light":"css-variables","dark":"css-variables"}}
claims.repository == "acme/infra" && claims.ref == "refs/heads/main"
```

### Restrict to a repository and environment

```go theme={"theme":{"light":"css-variables","dark":"css-variables"}}
claims.repository == "acme/infra" && claims.environment == "production"
```

### Common GitHub OIDC claims

| Claim              | Example value                                             | Description                             |
| :----------------- | :-------------------------------------------------------- | :-------------------------------------- |
| `repository`       | `acme/infra`                                              | Owner and repository name               |
| `repository_owner` | `acme`                                                    | Repository owner (organization or user) |
| `ref`              | `refs/heads/main`                                         | Git ref that triggered the workflow     |
| `environment`      | `production`                                              | GitHub Environment name (if used)       |
| `job_workflow_ref` | `acme/infra/.github/workflows/deploy.yml@refs/heads/main` | Full workflow file reference            |
| `actor`            | `octocat`                                                 | GitHub user who triggered the run       |
| `event_name`       | `push`                                                    | Event that triggered the workflow       |

## Security best practices for GitHub Actions

<Warning>
  For production workloads, enable [GitHub Environments](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment) and add an environment constraint to your CEL expression. This prevents any branch or workflow in the repo from authenticating -- only jobs running in the specified environment can.
</Warning>

For maximum security, pin to a specific reusable workflow via `job_workflow_ref`:

```go theme={"theme":{"light":"css-variables","dark":"css-variables"}}
claims.job_workflow_ref == "acme/infra/.github/workflows/deploy.yml@refs/heads/main"
```

This ensures only a specific workflow file on a specific branch can authenticate, even if other workflows in the same repo have `id-token: write` permission.
