Accounts, Two-Factor Authentication, SSH Keys, Access Tokens, Service Accounts, and Credentials: Configuration, Design Choices, and Tradeoffs
Compare GitLab credential and service-identity options by protocol, resource reach, lifetime, ownership, tier availability, and operational tradeoffs.
Learning objectives
- Choose SSH or HTTPS Git transport based on credential custody and operational constraints rather than habit.
- Compare personal, project, group, job, trigger, and deploy tokens by identity, resource reach, and supported operations.
- Explain when service accounts improve automation ownership and when a shorter-lived workload identity is preferable.
- Account for GitLab.com versus Self-Managed/Dedicated tier and SSO differences in credential design.
- Design a complete issue-store-use-rotate-revoke-evidence lifecycle for production credentials.
1. Start with the operation, not the credential you already have
A common production anti-pattern is “we already have a PAT, so use
it everywhere.” The safer sequence is operation → target resource →
protocol → principal → minimum permission → lifetime → storage →
rotation/revocation. The same repository may legitimately use SSH
for a developer, CI_JOB_TOKEN in a pipeline, and a
deploy token for an external package consumer.
2. SSH versus HTTPS for Git transport
| Dimension | SSH | HTTPS |
|---|---|---|
| Credential | Private key on client; public key registered with GitLab | Access token/password-equivalent handled by a credential helper |
| Human workstation | Excellent when SSH agent/key custody is well managed | Excellent when enterprise credential manager/SSO tooling favors HTTPS |
| Rotation | Add/remove key; private key lifecycle is local | Rotate/revoke token; update credential store |
| Failure diagnosis | Host, username, selected identity file, registered key, project permission | URL/host, credential helper entry, token validity/scope, project permission |
| Common mistake | Wrong key/account chosen by SSH agent/config | Embedding token in remote URL or shell history |
Neither protocol is universally more secure. The security outcome depends on key/token custody, endpoint verification, lifecycle, least privilege, and operational tooling.
3. Personal, project, group, job, and deploy tokens solve different ownership problems
| Need | Prefer considering | Why | Avoid by default |
|---|---|---|---|
| Interactive user API/CLI | glab OAuth or a minimally scoped PAT/fine-grained PAT | Human identity and explicit authorization | Sharing a team-wide PAT |
| One-project external automation | Project access token where available, or another project-bound mechanism | Resource ownership survives employee turnover | Owner-level personal PAT |
| Group-wide automation | Group access token where available or service account with minimal group membership | Aligns identity reach with group boundary | Unbounded personal token |
| GitLab CI job calling supported GitLab resources | CI_JOB_TOKEN |
Short-lived, job-derived identity | Long-lived PAT stored as a CI variable |
| Read/deploy access to repository/registry/package | Deploy token | Narrow non-human distribution credential | Using it as if it were a general API token |
| External pipeline trigger | Pipeline trigger token with narrow project ownership and secret handling | Purpose-built to start pipelines | Publishing the trigger token in source or URLs/logs |
4. Personal access tokens: broad identity, intentionally narrow permissions
A legacy PAT belongs to a user. Its scope can limit operations, but its resource reach starts from the user’s access. Current GitLab also provides fine-grained PATs that let you select specific resource/permission boundaries; current official docs mark fine-grained PATs generally available in GitLab 19.2. For older Self-Managed versions, verify whether the feature exists and which endpoints/operations are supported.
For read-only automation, prefer read_api,
read_user, or repository-specific read permissions when
they satisfy the task instead of full api. For Git over
HTTPS, repository scopes/permissions matter separately from API
access. Token expiration and rotation should match the task rather
than the maximum allowed lifetime.
5. Project/group access tokens: resource-owned bot identities
Project and group access tokens are attached to resource scopes rather than a normal human account. GitLab creates bot-style users behind these credentials. This makes ownership and offboarding cleaner, but the bot's assigned role and token scope still determine authority.
The free mandatory path therefore learns their architecture using documentation/fixtures rather than requiring a subscription.
6. CI_JOB_TOKEN: workload identity, not a saved secret
GitLab generates CI_JOB_TOKEN when a job starts and
revokes it after the job finishes. It authenticates only to
supported resources/endpoints. Cross-project access can require the
source project/group to be on the target project's job-token
allowlist, and the user who triggered the job must have sufficient
target permission.
This means a job token failure is not solved by “make the token longer-lived.” Diagnose endpoint support, target allowlist, triggering-user access, protected resource rules, and job context. Chapters 10–20 will exercise these mechanics in CI/CD.
7. Deploy tokens: narrow distribution identity
Deploy tokens are designed for selected Git, container registry, and package registry operations without binding the credential to a human. They are available across GitLab tiers/offerings, but they do not authenticate to the general GitLab public API. That boundary is valuable: a deployment consumer should not gain unrelated API power merely because it can pull an artifact.
8. Human users versus service accounts
Long-running automation should not silently depend on “Alice's token.” A service account is a non-human identity whose lifecycle can be owned by the team. Current GitLab service accounts authenticate using PATs, cannot use normal UI sign-in, and must be explicitly added to groups/projects with appropriate roles. Creation roles and quotas vary by offering; treat those as current product policy.
A service account is still not automatically the best fit. If an
operation runs only inside a GitLab job and
CI_JOB_TOKEN supports it, the job token has a much
shorter natural lifetime. If an external system only pulls images, a
deploy token can be narrower.
9. SSO/SAML changes authorization context without replacing every credential
GitLab.com group SAML SSO is a Premium/Ultimate capability. Organizations can enforce SSO for web activity and, optionally, Git/Dependency Proxy activity. A user can therefore authenticate successfully to GitLab.com and still be denied access to an SSO-enforced group hierarchy until the required SSO session/identity state is satisfied.
Credentials not tied to regular users—such as project/group access tokens, service accounts, and deploy keys—have different SSO enforcement behavior. Do not assume a human's working SSO session proves a bot credential is governed the same way.
10. Lifecycle design: issue, store, use, rotate, revoke, prove
- Issue: name the owner, purpose, target resource, minimum permissions, and expiry.
- Store: use OS credential managers, secret stores, or GitLab CI/CD secret mechanisms appropriate to the environment—not repository files.
- Use: pass secrets through headers/stdin/environment mechanisms that avoid logs and process arguments where practical.
- Rotate: create new credential, migrate consumers, verify, then revoke old credential; avoid surprise outages.
- Revoke: do it at the credential issuer, not only by deleting a local copy.
- Prove: retain non-secret metadata/audit evidence showing which identity, scope, expiry, and system consumed it.
11. Worked design scenario
A team has three operations: developers push source, GitLab CI reads
another project’s package metadata, and a deployment VM pulls a
container image. A least-privilege design might use individual SSH
keys for developers, CI_JOB_TOKEN plus the target
allowlist for the supported cross-project CI operation, and a
read-registry deploy token for the VM. One Owner PAT reused across
all three is operationally convenient but creates a larger blast
radius, weaker offboarding boundaries, and unnecessary API
authority.
| Criterion | Three-purpose credentials | One broad PAT |
|---|---|---|
| Blast radius | Bounded per workload | Large |
| Rotation | Independent | Coupled outage risk |
| Audit ownership | Clear principal per use | Mixed |
| Offboarding | Developer key removal does not break deployment | Human departure can break automation |
| Compatibility | Must verify each endpoint/protocol | Often broad, but that is not a security benefit |
Knowledge check
An external VM only needs to pull a private container image. Why might a deploy token be better than an Owner PAT?
A deploy token can be limited to the distribution operation and is not a general API credential, reducing blast radius and decoupling the workload from a human account.
A CI_JOB_TOKEN cannot call a desired API endpoint. Should you copy a Maintainer PAT into the job immediately?
No. First verify whether the endpoint supports job tokens, whether allowlist and triggering-user permissions are correct, and whether a narrower workload credential exists. A broad PAT is a last resort, not the default repair.
Why can a read-only PAT still be too powerful?
Read-only describes operations, not resource reach. If the user can see many private groups/projects, a personal token may expose a wide read surface.
Does SSO authentication automatically grant group membership?
No. Authentication through the IdP and authorization/membership are related but distinct. Current SAML/SCIM configuration can provision or enforce membership, but the user's effective role still controls actions.
Summary
Credential selection is architecture: SSH versus HTTPS is a transport choice; PATs carry human identity; project/group tokens align with resource ownership where available; job tokens are short-lived workload identity; deploy tokens narrow distribution access; service accounts decouple automation from employee lifecycle; and SSO adds another authorization/session boundary. Choose the narrowest credential that the protocol and endpoint actually support.
Official references
- GitLab Docs — Token overview
- GitLab Docs — Access token scopes
- GitLab Docs — Two-factor authentication
- GitLab Docs — 2FA troubleshooting and recovery
- GitLab Docs — Passkeys
- GitLab Docs — SSH keys
- GitLab CLI — Authentication
- GitLab CLI — glab auth status
- GitLab Docs — Personal access tokens
- GitLab Docs — Project access tokens
- GitLab Docs — Group access tokens
- GitLab Docs — Deploy tokens
- GitLab Docs — CI/CD job token
- GitLab Docs — Service accounts
- GitLab Docs — REST API authentication
- GitLab Docs — Fine-grained personal access tokens
- GitLab Docs — SAML SSO for GitLab.com groups
- GitLab Docs — Pipeline trigger tokens
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.