Saltar al contenido principal

JWT de tareas

Cuando la emisión de JWT está habilitada en el servidor, una plantilla puede generar un token firmado de corta duración para cada tarea que lance. El token se expone al playbook o script en ejecución como la variable de entorno SEMAPHORE_JWT y puede intercambiarse por credenciales en cualquier sistema que admita autenticación JWT, como OpenBao o HashiCorp Vault.

La ventaja frente a un secreto de larga duración almacenado en el almacén de claves es que cada tarea obtiene un token nuevo que identifica la ejecución exacta de la tarea (proyecto, plantilla, id de usuario) y que expira poco después de que la tarea finalice.

Habilitar JWT en una plantilla

En el formulario de la plantilla, desplácese hasta la sección JWT (solo aparece cuando el administrador ha habilitado la emisión de JWT) y marque JWT habilitado.

Puede configurar las siguientes opciones por plantilla:

CampoDescripción
AudienciaUna o más cadenas emitidas en el claim aud. Establézcalo con el o los identificadores que espera su sistema de destino (por ejemplo, la URL del servidor OpenBao). Se admiten hasta 32 entradas.
TTLDuración de vida del token expresada como duración (30s, 10m, 1h, ...). Si se deja vacío, se utiliza el valor global jwt.default_ttl. El TTL no debe superar el valor global jwt.max_ttl.

Claims del token

Cada token contiene los siguientes claims, en los que puede confiar al conceder acceso en el sistema de destino:

ClaimEjemploNotas
isshttps://semaphore.example.comConfigurado por el administrador.
audhttps://bao.example.comDe la lista de audiencias de la plantilla.
subtask:1234Único por ejecución de tarea.
iat / nbf / expClaims de tiempo estándar.
jtiIdentificador único del token.
project_id7Proyecto al que pertenece la plantilla.
template_id42La plantilla que generó la tarea.
user_id67Usuario que lanzó la tarea (se omite en ejecuciones programadas o de integraciones)

Utilice estos claims para delimitar el acceso en el lado consumidor. Por ejemplo, un rol de OpenBao que solo acepte tokens con project_id = 7 y un template_id específico.

Uso del token dentro de una tarea

Semaphore exporta el token como SEMAPHORE_JWT en el entorno del proceso de la tarea.

#!/usr/bin/env bash

# Bash example
echo "Look at my fancy token: $SEMAPHORE_JWT"
# Ansible example
- name: Read secret from OpenBao KVv2 via JWT auth
ansible.builtin.set_fact:
openbao_secret_value: >-
{{ lookup(
'community.hashi_vault.hashi_vault',
secret='kv/data/semaphore/demo:value',
auth_method='jwt',
url='https://bao.example.com',
role_id=bao_role,
jwt=lookup('ansible.builtin.env', 'SEMAPHORE_JWT')
) }}

Ejemplo: OpenBao

El siguiente recorrido configura OpenBao para que confíe en los JWT de Semaphore y los intercambie por una contraseña de demostración. Reemplace semaphore.example.com y bao.example.com por sus propios nombres de host.

1. Configurar el método de autenticación JWT

Habilite el método de autenticación JWT y apúntelo al endpoint JWKS de su instancia de Semaphore. OpenBao utiliza la clave pública que obtiene allí para verificar cada token.

bao auth enable jwt

bao write auth/jwt/config \
jwks_url="https://semaphore.example.com/.well-known/jwks.json" \
bound_issuer="https://semaphore.example.com"

2. Definir una política

Conceda los permisos que necesita una tarea. El siguiente ejemplo permite leer la credencial de demostración ubicada en kv/data/semaphore/demo:

bao policy write semaphore-demo-policy - <<EOF
path "kv/data/semaphore/demo" {
capabilities = ["read"]
}
EOF

3. Definir un rol de OpenBao vinculado a una plantilla

Un rol de OpenBao decide qué tareas de Semaphore pueden asumir qué política. Utilice los claims específicos de Semaphore (project_id, template_id, ...) como bound_claims para que solo la plantilla prevista pueda usar el rol:

bao write auth/jwt/role/semaphore-demo-role - <<EOF
{
"role_type": "jwt",
"user_claim": "sub",
"bound_audiences": "https://bao.example.com",
"bound_claims": {
"project_id": "7",
"template_id": "42"
},
"policies": ["semaphore-demo-policy"],
}
EOF

Restrinja siempre cada rol con al menos un claim project_id o template_id. Sin una vinculación, cualquier JWT emitido por su instancia de Semaphore podría asumir el rol.

Puede encontrar la lista completa de parámetros de configuración admitidos aquí

4. Configurar la plantilla

En la plantilla de Semaphore que ejecuta el playbook de despliegue:

  • Marque JWT habilitado.
  • Establezca Audiencia en https://bao.example.com; esto coincide con bound_audiences en el rol de OpenBao.
  • Opcionalmente, establezca TTL en 15m para que el token expire poco después de que la tarea finalice.

5. Usar el token en la tarea

- hosts: localhost
gather_facts: false
tasks:
- name: Read secret from OpenBao KVv2 via JWT auth
ansible.builtin.set_fact:
openbao_secret_value: >-
{{ lookup(
'community.hashi_vault.hashi_vault',
secret='kv/data/semaphore/demo:value',
auth_method='jwt',
url='https://bao.example.com',
role_id='semaphore-demo-role',
jwt=lookup('ansible.builtin.env', 'SEMAPHORE_JWT')
) }}

La tarea ahora se autentica contra OpenBao sin ningún secreto compartido previamente 🎉