Pular para o conteúdo principal

Jenkins OIDC, Gitea OIDC e Grafana SSO com o Casdoor: Um único login para uma stack DevOps auto-hospedada

· Leitura de 10 min
Yang Luo
Casdoor Maintainer

Cada ferramenta em uma típica stack DevOps auto-hospedada pode atuar como um cliente OpenID Connect: Gitea e Argo CD suportam OIDC nativamente, Jenkins faz isso através do plugin oic-auth, Grafana e Portainer através de OAuth 2.0 genérico, e MinIO, Harbor e GitLab através de suas configurações OIDC. Aponte todas elas para uma única instância do Casdoor, dê a cada ferramenta sua própria aplicação no Casdoor e coloque seus usuários em grupos do Casdoor. Cada ferramenta então lê a claim groups e decide quem é administrador. Este post lista a URL de callback, as chaves de configuração e o mapeamento de grupos para cada ferramenta, depois cobre as partes que elas compartilham.

A stack em resumo​

Todos os caminhos abaixo são relativos à URL pública da própria ferramenta. Registre-os em Redirect URLs da aplicação do Casdoor correspondente a essa ferramenta.

AppProtocolCallback URLGroup/role to admin mappingCasdoor doc
GiteaOIDC (OAuth2 auth source)/user/oauth2/<source-name>/callbackSim: grupo admin, grupo restrito, mapa de equipeGitea
JenkinsOIDC (oic-auth plugin)/securityRealm/finishLogin, logout /OicLogoutSim: claim de grupos mais segurança baseada em MatrixJenkins (OIDC)
GrafanaGeneric OAuth 2.0/login/generic_oauthSim: role_attribute_pathGrafana
Argo CDOIDC/auth/callback, CLI http://localhost:8085/auth/callbackSim: argocd-rbac-cmArgo CD
MinIOOIDCConsole /oauth_callbackPolíticas de uma claim (claim_name)MinIO
PortainerOAuth 2.0 (Custom)A URL base do PortainerApenas Business EditionPortainer
HarborOIDC/c/oidc/callbackSim: OIDC Admin Groupainda não disponível
GitLabOIDC (OmniAuth)/users/auth/openid_connect/callbackPremium e Ultimate: admin_groupsGitLab

O documento de descoberta que todo cliente OIDC precisa é https://<casdoor-host>/.well-known/openid-configuration. Se você nunca conectou um cliente OIDC ao Casdoor antes, Connect a standard OIDC client explica os endpoints.

Prepare o Casdoor uma vez​

Antes de tocar nas ferramentas, configure três coisas no Casdoor.

Groups. Crie grupos como devops-admins e devops-users na árvore da organização e adicione usuários a eles. Veja Groups.

Token group format. Por padrão, a claim groups nomeia cada grupo como <organization>/<group>. A maioria das ferramentas compara a claim com uma string simples que você digita, então defina Token group format na aba OIDC/OAuth de cada aplicação para Name (group). A claim então carrega devops-admins. As opções são descritas em Group format.

Token format. Mantenha Token format como JWT, o padrão. Nesse formato, o ID token carrega groups, roles e tag. JWT-Empty e JWT-Standard deixam todos os três fora do token, e JWT-Custom os carrega apenas se você selecioná-los em Token fields. A resposta /api/userinfo retorna groups e os nomes das roles quando o escopo profile é concedido, então ferramentas que leem userinfo ainda os veem.

Roles também funcionam. No formato JWT, a claim roles é um array de objetos de role, então combine com roles[*].name. Em /api/userinfo, é um array simples de nomes. Veja User roles.

Gitea​

Em Site Administration, adicione uma fonte de autenticação do tipo OAuth2 com provedor OpenID Connect, o client ID e secret, e a URL de descoberta do Casdoor. O nome que você dá à fonte faz parte da URL de callback: uma fonte chamada casdoor usa https://gitea.example.com/user/oauth2/casdoor/callback.

Para o mapeamento de grupos, preencha Claim name providing group names com groups, depois Group Claim value for administrator users com devops-admins. O Gitea também tem Group Claim value for restricted users e Map claimed groups to Organization teams. A mesma fonte via CLI:

gitea admin auth add-oauth \
--name casdoor \
--provider openidConnect \
--key <client-id> \
--secret <client-secret> \
--auto-discover-url https://door.example.com/.well-known/openid-configuration \
--group-claim-name groups \
--admin-group devops-admins

Jenkins​

O Jenkins não possui suporte OIDC próprio. Instale o plugin OpenId Connect Authentication, escolha-o como realm de segurança e use a configuração well-known. O callback de login é /securityRealm/finishLogin e o callback de logout é /OicLogout; adicione ambos ao Casdoor. No JCasC:

jenkins:
securityRealm:
oic:
serverConfiguration:
wellKnown:
wellKnownOpenIDConfigurationUrl: https://door.example.com/.well-known/openid-configuration
clientId: <client-id>
clientSecret: <client-secret>
userNameField: name
fullNameFieldName: displayName
emailFieldName: email
groupsFieldName: groups
logoutFromOpenidProvider: true
properties:
- "pkce"

O plugin apenas passa os grupos para o Jenkins. Os direitos vêm da estratégia de autorização: com segurança baseada em Matrix, cada linha da tabela é um usuário ou um grupo, então adicione uma linha para devops-admins e dê a ela Overall/Administer. Escolher o plugin como realm de segurança desativa outros métodos de login, então configure a propriedade escapeHatch do plugin (um nome de usuário e secret de fallback) antes de salvar. O Casdoor também tem seu próprio plugin para Jenkins, descrito em Jenkins plugin, mas o plugin OIDC genérico é o que este post assume.

Grafana​

O Grafana usa OAuth genérico. Seu callback é /login/generic_oauth. O scopes padrão do Grafana é user:email, então defina explicitamente os escopos OIDC:

[auth.generic_oauth]
enabled = true
name = Casdoor
client_id = <client-id>
client_secret = <client-secret>
scopes = openid profile email
auth_url = https://door.example.com/login/oauth/authorize
token_url = https://door.example.com/api/login/oauth/access_token
api_url = https://door.example.com/api/userinfo
use_pkce = true
groups_attribute_path = groups
role_attribute_path = contains(groups[*], 'devops-admins') && 'Admin' || contains(groups[*], 'devops-users') && 'Editor' || 'Viewer'
role_attribute_strict = true

O Grafana avalia o role_attribute_path primeiro contra o token de ID, depois contra a resposta do userinfo e, por fim, contra o token de acesso. Os resultados válidos são None, Viewer, Editor, Admin e GrafanaAdmin; este último requer allow_assign_grafana_admin = true. O allowed_groups restringe o login aos grupos listados e requer groups_attribute_path. A sincronização de equipes é um recurso do Grafana Enterprise e do Grafana Cloud.

Argo CD​

O Argo CD se comunica diretamente com o Casdoor, sem usar seu Dex integrado. O callback do navegador é /auth/callback. argocd login --sso inicia um servidor local na porta 8085 por padrão e usa http://localhost:8085/auth/callback, portanto registre essa URL também.

Defina url e oidc.config (com name, issuer, clientID, clientSecret, requestedScopes) no argocd-cm. O requestedScopes padrão do Argo CD adiciona um escopo groups. O Casdoor não precisa dele, pois o token de ID JWT sempre inclui groups, então nosso guia solicita ["openid", "profile", "email"]. Os grupos são mapeados no argocd-rbac-cm, onde scopes tem como padrão [groups]:

data:
policy.default: role:readonly
policy.csv: |
g, devops-admins, role:admin

O passo a passo completo, incluindo o segredo do cliente no argocd-secret, está no guia Argo CD.

MinIO​

O MinIO lê as políticas de uma única claim, definida com claim_name (padrão policy). Ele não faz mapeamento de grupos. O quickstart do Casdoor no MinIO e nosso guia usam a claim tag do Casdoor: coloque um nome de política do MinIO, como readwrite, no campo Tag do usuário, então:

mc admin config set myminio identity_openid \
config_url="https://door.example.com/.well-known/openid-configuration" \
client_id=<client-id> client_secret=<client-secret> claim_name="tag"

role_policy é a alternativa: todo usuário que fizer login através deste provedor receberá as políticas listadas, e ela não pode ser combinada com claim_name. O callback do Console é <console-url>/oauth_callback. Atrás de um proxy, defina MINIO_BROWSER_REDIRECT_URL; a chave antiga redirect_uri está obsoleta. Observe que o repositório GitHub minio/minio foi arquivado e seu README afirma que não é mais mantido, então verifique qual build do MinIO você executa antes de depender dessas configurações.

Portainer​

O Portainer usa um provedor OAuth Personalizado. Preencha Authorization URL (/login/oauth/authorize), Access token URL (/api/login/oauth/access_token) e Resource URL (/api/userinfo) em seu host Casdoor, e defina Redirect URL para a URL base do Portainer. Há também um campo Logout URL. No Portainer CE, Automatic team membership é marcado como um recurso da Business Edition, e a configuração que atribui direitos de administrador a grupos existe apenas na Business Edition. Na CE, usuários criados pelo provisionamento automático recebem a função de usuário padrão e você promove administradores manualmente.

Harbor e GitLab​

O Harbor exibe sua URI de redirecionamento na parte inferior da página de configurações OIDC: <harbor-url>/c/oidc/callback. Defina OIDC Provider Endpoint como a URL do Casdoor, Group Claim Name como groups e OIDC Admin Group como devops-admins. O Harbor lê a claim de grupo do token de ID, fornecida pelo formato JWT. Você só pode alternar o Harbor da autenticação por banco de dados para OIDC antes que existam usuários locais.

A documentação OIDC do GitLab possui uma seção sobre o Casdoor e exige que o Casdoor seja servido via HTTPS. O callback é /users/auth/openid_connect/callback. Funções baseadas em grupos (groups_attribute, admin_groups, required_groups, external_groups) exigem GitLab Premium ou Ultimate.

Ferramentas sem OIDC​

Para dashboards internos que não possuem login próprio, coloque-os atrás do plugin openid-connect do Apache APISIX (discovery, client_id, client_secret, redirect_uri, bearer_only), conforme o guia do APISIX, ou atrás do nginx conforme descrito em Autenticação SSO com Nginx.

Uma aplicação por ferramenta ou uma compartilhada​

Uma única aplicação Casdoor com os callbacks de todas as ferramentas em suas Redirect URLs funciona, mas uma aplicação por ferramenta é mais fácil de gerenciar:

  • Cada ferramenta tem seu próprio segredo de cliente, então um segredo vazado do Jenkins não expõe o Grafana.
  • Token group format, Token format e a expiração do token são específicos da aplicação, então você pode dar ao Argo CD Name (group) sem alterar as claims de outra ferramenta.
  • O Casdoor verifica post_logout_redirect_uri contra as Redirect URLs da aplicação, então cada lista permanece curta e específica.

Os usuários ainda fazem login apenas uma vez: após o primeiro login, o cookie de sessão do Casdoor permite que o redirecionamento para a próxima ferramenta seja concluído sem solicitar senha.

Sair​

O endpoint de encerramento de sessão do Casdoor é /api/logout, listado como end_session_endpoint no documento de descoberta. Ele aceita id_token_hint, post_logout_redirect_uri, client_id e state, e só redireciona para uma URL listada nas Redirect URLs da aplicação. Fazer logout do Casdoor termina a sessão do Casdoor e os tokens daquela sessão, mas cada ferramenta também mantém seu próprio cookie de sessão. Configure o logout em cada ferramenta:

  • Jenkins: logoutFromOpenidProvider, com /OicLogout registrado.
  • Grafana: signout_redirect_url.
  • Argo CD: logoutURL em oidc.config, por exemplo https://door.example.com/api/logout?id_token_hint={{token}}&post_logout_redirect_uri={{logoutRedirectURL}}.
  • Harbor: OIDC Session Logout.
  • Portainer: Logout URL.

Os detalhes do endpoint estão em RP-initiated logout.

Referências​