Skip to main content

Vault Secrets Backend Plugin

The Vault Secrets Backend provides HashiCorp Vault integration with support for both GCP IAM authentication (production) and JWT-based authentication (development).

Overview

PropertyValue
Package@internal/backstage-plugin-vault-secrets-backend
TypeBackend
Plugin IDvault-secrets
AuthGCP IAM + JWT

Architecture

API Endpoints

Health & Debug

MethodEndpointDescription
GET/healthVault connection status
GET/debug/configConfiguration info
GET/debug/jwtJWT claims inspection
GET/user-infoCurrent user information

Secret Operations

MethodEndpointDescription
GET/secretsList secrets
GET/secrets/:path(*)Read secret
POST/secrets/:path(*)Write secret
DELETE/secrets/:path(*)Delete secret

Authentication

Dual Auth Strategy

GCP IAM Authentication (Production)

When running on Cloud Run, the backend authenticates to Vault using GCP IAM:

// Automatic when GOOGLE_CLOUD_PROJECT is set
const auth = new GoogleAuth();
const client = await auth.getIdTokenClient(vaultIapAudience);

JWT Authentication (Development)

For local development, JWT tokens from Backstage are used:

// JWT claims extracted for user/group info
interface JWTClaims {
sub: string; // User reference
ent: string[]; // Entity claims (groups)
"github.teams": string[]; // GitHub team memberships
}

Access Control

User Keystore Access

Users can only access their own keystore:

Group Keystore Access

Users can access group keystores if they're a member:

Path Structure

vault/
├── users/
│ ├── john.doe/
│ │ ├── github-token
│ │ ├── aws-credentials
│ │ └── ssh-key
│ └── jane.smith/
│ └── api-key

└── groups/
├── platform-team/
│ ├── tfc-token
│ ├── gcp-credentials
│ └── shared-api-key
└── devops/
└── prod-db-password

Configuration

# app-config.yaml
vault:
address: ${VAULT_ADDR}
secretEngine: secret # KV v2 engine path
skipTlsVerify: false # Set true for development

Environment Variables

VariableDescriptionRequired
VAULT_ADDRVault server addressYes
VAULT_TOKENVault token (development)Dev only
VAULT_ROLEGCP IAM role (production)Prod only

Security Features

GitHub Team Validation

For group keystores, the backend validates GitHub team membership:

// Teams are extracted from JWT claims
const githubTeams = claims["github.teams"] || [];

// Normalize team names for comparison
const normalizeTeam = (team: string) =>
team.toLowerCase().replace(/[^a-z0-9-]/g, "-");

// Check membership
const hasAccess = githubTeams.some(
(team) => normalizeTeam(team) === normalizeTeam(groupName),
);

Error Messages

Clear, actionable error messages for access issues:

{
"error": "Access Denied",
"message": "You are not a member of the 'platform-team' group",
"yourGroups": ["devops", "engineering"],
"requiredGroup": "platform-team"
}

Debug Endpoints

/debug/jwt

Inspect JWT claims for troubleshooting:

{
"sub": "user:default/john.doe",
"ent": ["group:default/platform-team"],
"github.teams": ["Platform Team", "Engineering"]
}

/debug/config

View non-sensitive configuration:

{
"vaultAddress": "https://vault.example.com",
"secretEngine": "secret",
"authMethod": "gcp-iam"
}