FR
live

GitLab Secrets Manager expands to Kubernetes and Terraform to unify secret management

GitLab extends its OpenBao-powered Secrets Manager to the External Secrets Operator, Terraform, and a direct API, beyond CI/CD alone. The pitch: replace scattered secret stores across CI/CD, Kubernetes, and IaC with a single audited source of truth.

A heavy steel key cabinet fixed to a concrete wall, neat rows of identical keys hanging inside, one single amber-lit key held aloft by a gloved hand.

August 6, 2026. GitLab announces that its Secrets Manager now reaches beyond the CI/CD pipeline. The service, powered by OpenBao and exposed through a Vault-compatible KV v2 API, can now feed Kubernetes via the External Secrets Operator, Terraform and OpenTofu, and any external automation through a dedicated API. It closes a familiar loop: the secret scattered across three stores that nobody can correlate.

The starting problem is well known. A team keeps one vault for CI/CD, another for Kubernetes workloads, a third — often .tfvars files committed by mistake — for Terraform. Three tools to operate, three access models to keep in sync, and an audit trail impossible to reconstruct when a secret leaks. GitLab’s promise is simple: one source of truth. And that source has to be auditable: when a secret leaks, the first question — who had access, and since when — should be answered in a single query, not across three tools.

What actually changes

GitLab’s Secrets Manager is not new. It is in public beta for Premium and Ultimate customers, and CI/CD has accessed it since version 19.0. What changed is the opening beyond the pipeline, along three paths.

First, Kubernetes. The External Secrets Operator (ESO) syncs secrets from the Secrets Manager through its Vault provider. A workload carries a short-lived JWT, which ESO exchanges for an OpenBao token, then writes the value into a native Kubernetes Secret. The core of the setup is two objects:

yaml
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: gitlab-secrets-manager
  namespace: my-app
spec:
  provider:
    vault:
      server: https://secrets.gitlab.com
      path: secrets/kv
      version: v2
      namespace: org_5/group_42/project_99
      auth:
        jwt:
          path: api_jwt/cel
          role: all_api
          secretRef:
            name: gitlab-access-token
            key: token
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: my-app
spec:
  refreshInterval: 45m
  secretStoreRef:
    name: gitlab-secrets-manager
    kind: SecretStore
  target:
    name: synced-secret
  data:
    - secretKey: value
      remoteRef:
        key: explicit/<secret_name>
        property: value

The namespace field on the SecretStore maps the GitLab hierarchy — organization, group, project — and bounds what this store can reach. The ExternalSecret then pulls values every refreshInterval, so a rotation propagates without a redeploy.

The security model: short tokens, strict scopes

Under the hood, everything runs on short-lived tokens. No workload holds a permanent credential: GitLab mints a JWT with a limited lifetime, which ESO, Terraform, or the API exchange for an ephemeral OpenBao token. It is just-in-time authentication at work: the exposure window for a stolen secret is measured in minutes, not months.

The namespace acts as the boundary. Each SecretStore is scoped to a precise GitLab hierarchy — an organization, a group, a project — and can only read the secrets that live there. It mirrors the existing GitLab permission model: a project sees only its own secrets, never its neighbor’s. For a platform team, that removes the classic shared-vault scenario where one service token ends up opening every door.

The benefit shows in incident response. With short-lived tokens and per-project namespaces, a leaked credential has a small blast radius and expires on its own — you don’t have to rotate a fleet of long-lived service accounts. That is the difference between a cleanup measured in minutes and one measured in weeks.

Terraform and OpenTofu, without .tfvars

The second path targets IaC. .tfvars and the Terraform state remain two of the biggest sources of leaked credentials: the value ends up on disk or pushed into a repository. GitLab proposes reading the secret as a data source, authenticating with a JWT minted at plan or apply time:

hcl
data "external" "gitlab_secrets_token" {
  program = ["bash", "${path.module}/scripts/mint_token.sh"]
  query = { project_id = var.gitlab_project_id }
}

provider "vault" {
  address   = data.external.gitlab_secrets_token.result.server
  namespace = data.external.gitlab_secrets_token.result.namespace
  auth_login_jwt {
    mount = data.external.gitlab_secrets_token.result.auth_path
    role  = data.external.gitlab_secrets_token.result.role
    jwt   = data.external.gitlab_secrets_token.result.jwt
  }
}

data "vault_kv_secret_v2" "my_secret" {
  mount = data.external.gitlab_secrets_token.result.mount
  name  = "${data.external.gitlab_secrets_token.result.secrets_path}/<secret_name>"
}

output "secret_value" {
  value     = data.vault_kv_secret_v2.my_secret.data["value"]
  sensitive = true
}

Nothing passes through a CI/CD variable or a local file: the secret is read at runtime, then surfaced as a sensitive output. The third path, the Secrets Manager API, covers everything else — a script, a home-grown operator, an observability tool — that previously had to hardcode credentials.

What it costs, and what it demands

The commercial model deserves a read before you commit. The Secrets Manager is free during the beta; at general availability it becomes a paid feature, billed through GitLab Credits, with an explicit opt-in and advance notice. Availability covers GitLab.com and Self-Managed; GitLab Dedicated follows.

The architecture rests on OpenBao, the community fork of Vault born after HashiCorp’s license change. In practice, anything that speaks Vault — the vault CLI, ESO, the Terraform providers — can connect. That is both the product’s strength and its limit: GitLab is not reinventing the wheel, it is standardizing on an already widely deployed API, which lowers adoption friction but also narrows differentiation against a self-hosted Vault or OpenBao.

What is missing today, for now: there is no dynamic secrets engine or PKI backend yet, and the audit surface — who read which secret, when — is younger than Vault’s. Teams with heavy compliance needs should treat those gaps as a checklist, not a blocker.

Why OpenBao, and what it changes for you

The choice of OpenBao is not a detail. When HashiCorp moved Vault to the BUSL license, part of the community forked it to create OpenBao, kept under MPL-2.0. By standardizing its Secrets Manager on a Vault-compatible KV v2 API, GitLab avoids two pitfalls: reinventing a proprietary protocol, and depending on a license some customers find restrictive.

The practical consequence: the entire existing Vault ecosystem — the CLI, the Terraform providers, ESO, the SDKs — works as-is. You don’t retrain teams on a new tool; you plug in what they already know. Against a self-hosted OpenBao, GitLab brings no secret extra capability: it brings integration, and the disappearance of a server to operate.

Migrating without breaking anything

The trap of such a tool is wanting to switch everything at once. Don’t. The cautious sequence has three steps: inventory the secrets and their consumers, switch scope by scope — start with a non-critical project, wire up ESO then Terraform — and coexist for a few weeks, the old store and the new running in parallel.

One point people forget: the exit. The day GitLab starts billing the feature, or the day you change your mind, you’ll need a way back. Document the provenance of every secret — where it’s stored, who reads it, how often — before you migrate. A secret whose trail you’ve lost is a secret you can no longer rotate without breakage. Treat the migration like any other infrastructure change: reversible, observable, and rolled back by the same automation that rolled it forward.

The cold verdict

If you are already on GitLab Premium or Ultimate and juggling several secret stores, the consolidation is worth it: you drop a tool to operate and, more importantly, you get back a single audit trail — something security teams have asked for for years. The ESO provider covers the most common Kubernetes case, and the data source read fixes the committed-.tfvars problem.

If you are multi-cloud, multi-CI, or need fine-grained dynamic secretsdynamic secrets, PKI, rotation at scale — stay on self-hosted Vault or OpenBao: GitLab Secrets Manager is still young, and its advanced capabilities are limited next to a mature Vault.

In all cases, don’t migrate production secrets during the beta. Today’s free tier hides a future billing model that is not yet defined; wait for GA, the GitLab Credits price, and test recovery on a non-critical scope. A secret is not something you migrate casually.

References

The cyber brief, every Tuesday

The flaws that matter and the patches to apply, in a ten-minute read.

No spam. One-click unsubscribe.
read next

On the same topic

PostgreSQL ships 28 security fixes in one go and puts version 14 on the clock

On August 13, 2026, the PostgreSQL project released 18.6, 17.11, 16.15, 15.19, 14.24 and 19 Beta 3, fixing 28 security vulnerabilities — a record — including a dozen memory bugs exploitable for code execution. Apply the minor release now, and if you are still on version 14, plan the major upgrade before November 12, 2026.

Terraform 1.16 allows import blocks inside modules and keeps secrets across plan and apply

On August 12, 2026 HashiCorp shipped Terraform 1.16 in release candidate, with two major changes: import blocks now work inside modules, and the new store block on terraform_data keeps ephemeral and sensitive values across plan and apply. Teams adopting Terraform over existing infrastructure gain the lever they were missing.

← Back to the feed

Type at least two characters.

navigate open esc dismiss