feat: add GitLab CI provider support#559
Conversation
|
Lets say you have an OPKSSH server that accepts both GitLab Login ID Tokens and GitLab-CI ID Tokens. How do you tell the tokens apart? If you use the presence of GQ Signatures to tell them apart, an attacker could simply turn a captured GitLab Login ID Token into a GQ-signed Gitlab-CI ID Tokens and in so doing bind the attackers public key. |
50cbb2b to
6f426d4
Compare
|
Good point. I agree that the server must not distinguish GitLab Login tokens from GitLab CI tokens solely by the presence of a GQ signature. The unsafe version would be:
That is not sufficient, because a normal GitLab Login ID Token and a GitLab CI ID Token share the same issuer: If the only discriminator is "has GQ signature", then an attacker who obtains a normal GitLab Login ID Token could try to re-wrap / GQ-bind that token and make it look like a GitLab CI-style token. In that case the attacker would be changing the binding to their own public key, while still presenting a GitLab-issued token. So the distinction has to come from claims that are part of the ID token semantics, not just from the outer token/signature format. Normal GitLab loginNormal interactive GitLab login is configured with the GitLab OAuth client ID: Those tokens are expected to have an audience matching that client ID and are verified using the normal GitLab/OIDC verifier. GitLab CIGitLab CI is configured with an explicit OpenPubkey PKToken audience: Those tokens are expected to have an audience matching that value and are verified using the GitLab CI/GQ-bound verifier. Because of this, I removed the generic server-side marker: That marker was too broad because it selected the GitLab CI verifier without expressing which audience was expected. The server-side config now requires an explicit So the server should distinguish the two cases by configured issuer + expected audience/token type, not merely by whether the token is GQ-signed. Concretely, for a server accepting both normal GitLab and GitLab CI, the config should look like: The multi-provider wrapper is only there to work around the fact that If the underlying GitLab CI verifier skips client ID / audience validation, opkssh should enforce the configured |
Using just the audience here concerns me because the audience can be set to any value. Its almost certainly fine to use only audience, but just to be safe, is there anyway to tell GitLab an GitLab-CI tokens apart, other than the audience? Like GitLab-CI tokens can the claim |
|
Added an explicit GitLab CI token discriminator before invoking the GitLab CI/GQ verifier. The GitLab CI verifier in OpenPubkey uses
This avoids treating any GQ-bound token from the GitLab issuer as GitLab CI solely based on the presence of a GQ signature. Normal GitLab login tokens and GitLab CI tokens share the same issuer, so the server now uses the explicitly configured audience plus CI-specific claims to route the token to the GitLab CI verification path. The claim checks are only used as a fail-closed discriminator. The token is still cryptographically verified by the underlying GitLab CI/GQ verifier afterwards. |
Fixes: #52
openpubkey/verifier.NewFromManystores provider verifiers in a map keyed by issuer:https://github.com/openpubkey/openpubkey/blob/main/verifier/verifier.go#L126
Because of that, a verifier list cannot contain two providers with the same issuer. If two entries use the same issuer,
NewFromManyrejects them as duplicates.This becomes a problem for GitLab because both normal interactive GitLab login and GitLab CI tokens use the same issuer:
but they require different verification behavior:
GQ256) tokensA server may need to allow both at the same time, for example:
Both entries have the same issuer, but represent different accepted audiences/token types.