# Secrets and GitProviders

> Cordium documentation. Canonical page: <https://octelium.com/docs/cordium/latest/workspaces/secrets>.

Cordium provides two *Space*-level resources for credentials: *Secrets*, which hold arbitrary sensitive values that are used by the *Workspaces* of the *Space*, and *GitProviders*, which let each *User* authenticate their *Workspaces*' git operations with their own git hosting account via OAuth2.

> **Note:**
>
> Before storing a credential as a Cordium *Secret*, consider whether the resource it protects can be exposed as an Octelium *Service* instead. In that case, the credential is stored as an Octelium *Secret* and injected by Octelium on a per-request basis, which means that it never enters the *Workspace* at all (read more [here](https://octelium.com/docs/cordium/latest/workspaces/secretless.md)).

## Secrets

A *Secret* belongs to a *Space* and is created by the *Space*'s admins. Its value is write-only: it is never returned by the API, not even to the admins who created it, and it is only resolved by the *Cluster* when a *Workspace* of the *Space* starts.

```bash
# Enter the value interactively
cordium create secret stripe-test-key.payments.cordium

# From a flag
cordium create secret sentry-dsn.payments.cordium --value "https://abc123@o1.ingest.sentry.io/42"

# From a file, or from stdin via "-"
cordium create secret service-account.payments.cordium --file ./service-account.json
vault kv get -field=token secret/ci/npm | cordium create secret npm-token.payments.cordium --file -

# From an environment variable
cordium create secret github-token.payments.cordium --from-env GITHUB_TOKEN
```

You can list and delete the *Secrets* of a *Space* as follows:

```bash
cordium get secret --space payments.cordium
cordium delete secret stripe-test-key.payments.cordium
```

*Secrets* cannot be updated. To rotate a *Secret*, delete it and create it again with the new value. The new value is used by the subsequent *Workspace* runs.

### Using Secrets

*Secrets* are always referred to by their full name (i.e. `<NAME>.<SPACE_FULL_NAME>`) and can only be used by the *Workspaces* and *Templates* of their own *Space*. They can be used in the following fields:

| Field                                                     | Usage                                                                                                                                                                                                                     |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `spec.runtime.envVars[].fromSecret`                       | Environment variables (read more [here](https://octelium.com/docs/cordium/latest/workspaces/runtime.md#environment-variables)).                                                                                           |
| `spec.repository.authentication.http.password.fromSecret` | HTTP basic authentication for cloning private repositories (read more [here](https://octelium.com/docs/cordium/latest/workspaces/repositories.md#private-repositories)). The same applies to the additional repositories. |
| `spec.image.registry.authentication.password.fromSecret`  | Pulling images from private registries (read more [here](https://octelium.com/docs/cordium/latest/workspaces/image.md#registry)).                                                                                         |
| `spec.runtime.envVars[].fromSecret` of a *Space*          | Environment variables injected into all the *Workspaces* of an `ORGANIZATION` *Space* (read more [here](https://octelium.com/docs/cordium/latest/workspaces/spaces.md#space-configuration)).                              |
| `clientSecret.fromSecret` of a *GitProvider*              | The OAuth2 client secret of a *GitProvider* (see below).                                                                                                                                                                  |

Here is an example:

```yaml
spec:
  image:
    registry:
      url: ghcr.io/acme-corp/dev-base:2026.10
      authentication:
        username: acme-bot
        password:
          fromSecret: ghcr-token.payments.cordium
  repository:
    url: https://github.com/acme-corp/payments-api
    authentication:
      http:
        username: x-access-token
        password:
          fromSecret: github-token.payments.cordium
  runtime:
    envVars:
      - key: STRIPE_SECRET_KEY
        fromSecret: stripe-test-key.payments.cordium
```

A *Workspace* that references a *Secret* that does not exist or that belongs to another *Space* is rejected when it is created or updated.

## GitProviders

A *GitProvider* is an OAuth2 application of a git hosting service that is registered in a *Space*. Once a *GitProvider* is attached to a *Template*, every *User* can sign in to the git hosting service with their own account for each of their *Workspaces* of that *Template*. Their OAuth2 token is then used by a git credential helper inside the *Workspace* for cloning, pulling and pushing, and their git `user.name` and `user.email` are automatically configured, which means that commits are attributed to the right person without sharing a common token among the team.

### Creating GitProviders

First, register an OAuth2 application at your git hosting service with the following callback URL:

```text
https://cordium.<DOMAIN>/auth/v1/callback
```

Then, store its client secret as a *Secret* of the *Space* and create the *GitProvider*. The following types are supported:

```bash
cordium create secret github-oauth.payments.cordium --from-env GITHUB_CLIENT_SECRET

# GitHub
cordium create gitprovider github.payments.cordium \
  --type github \
  --client-id Ov23liAbCdEf123456 \
  --client-secret-from-secret github-oauth.payments.cordium \
  --scope repo --scope read:user --scope user:email

# GitLab
cordium create gitprovider gitlab.payments.cordium \
  --type gitlab \
  --client-id 8f2c1e... \
  --client-secret-from-secret gitlab-oauth.payments.cordium

# A generic OAuth2 provider (e.g. Gitea, Forgejo or a self-hosted GitLab)
cordium create gitprovider forgejo.payments.cordium \
  --type oauth2 \
  --client-id 1b6e... \
  --client-secret-from-secret forgejo-oauth.payments.cordium \
  --auth-url https://git.example.com/login/oauth/authorize \
  --token-url https://git.example.com/login/oauth/access_token \
  --scope read:user --scope write:repository
```

You can list the *GitProviders* of a *Space* via `cordium get gitprovider --space payments.cordium`.

### Using GitProviders

Attach the *GitProvider* to a *Template* via its full name:

```yaml
spec:
  gitProvider: github.payments.cordium
  repository:
    url: https://github.com/acme-corp/payments-api
```

Since a *User* signs in to the git hosting service for a specific *Workspace*, the typical flow is as follows:

1. Create the *Workspace* without starting it, for example via `cordium create ws --template api-dev.payments.cordium`.
2. Open the *Workspace*'s page in the web portal and click **Sign in to Git provider**, which redirects you to the git hosting service's consent page and back to the portal.
3. Start the *Workspace*. Its repositories are now cloned with your token, and `git pull` and `git push` work inside it.

The sign-in is only offered while the *Workspace* is stopped, and the token is used on every subsequent run until it expires, in which case you can simply sign in again.
