GitLab Access Control
Access control determines who can see your code, who can change it, and who can manage the project. GitLab gives administrators precise control over every action through roles, protected branches, deploy keys, and access tokens.
The Layers of Access Control
Layer 1: Project/Group visibility (Public / Internal / Private) Layer 2: Member roles (Guest / Reporter / Developer / Maintainer / Owner) Layer 3: Protected branches (who can push and merge) Layer 4: Protected tags (who can create version tags) Layer 5: Deploy keys and access tokens (machine-to-machine access) Layer 6: IP allowlisting (block access from outside approved ranges)
Project Visibility Revisited
| Visibility | Who Can See the Repository | Who Can Clone It |
|---|---|---|
| Public | Anyone, including anonymous visitors | Anyone (read-only) |
| Internal | Any signed-in GitLab user | Any signed-in user |
| Private | Invited members only | Invited members only |
Role Permissions — A Detailed Breakdown
Action Guest Reporter Developer Maintainer Owner ─────────────────────────────────────────────────────────────────────── View issues ✅ ✅ ✅ ✅ ✅ Create issues ❌ ✅ ✅ ✅ ✅ Push to non-protected ❌ ❌ ✅ ✅ ✅ Create merge requests ❌ ❌ ✅ ✅ ✅ Merge MRs ❌ ❌ ❌ ✅ ✅ Manage members ❌ ❌ ❌ ✅ ✅ Edit project settings ❌ ❌ ❌ ✅ ✅ Delete project ❌ ❌ ❌ ❌ ✅ Transfer project ❌ ❌ ❌ ❌ ✅
Protected Branches — Guarding Critical Code
Protected branches block direct pushes and restrict who can merge into them. This ensures the main branch only receives reviewed, approved code.
Settings → Repository → Protected Branches → Add protected branch Branch: main Allowed to merge: Maintainers Allowed to push: No one Require approvals: 2 Result: ───────────────────────────────────────────────────────────── Developer pushes to feature branch ✅ Developer pushes directly to main ❌ (rejected) Developer opens MR → 2 approvals → Maintainer merges ✅ ─────────────────────────────────────────────────────────────
Protected Tags
Tags mark release versions (like v2.1.0). Protecting a tag pattern ensures only authorised members create version tags.
Protected tag: v*.*.* Allowed to create: Maintainers and Owners only Developer runs: git tag v2.1.0 && git push --tags Result: ❌ rejected — Developer cannot create protected tags
Deploy Keys — Read-Only Machine Access
A deploy key is an SSH key registered in GitLab that gives a server read-only (or read-write) access to a specific repository — without tying access to a human user account.
Use case: A production server needs to pull the latest code.
─────────────────────────────────────────────────────────────────────
Without deploy key: Use someone's personal account → access breaks
when they leave the company ❌
With deploy key: Server uses its own SSH key → access independent
of any human account ✅
─────────────────────────────────────────────────────────────────────
Add a deploy key: Settings → Repository → Deploy Keys → Add deploy key
Paste the server's public SSH key → choose read-only or read-write
Access Tokens
Access tokens are passwords for automated tools (scripts, CI jobs, third-party integrations). There are three types:
| Token Type | Scope | Best For |
|---|---|---|
| Personal Access Token | Your entire account | Personal scripts, CLI tools |
| Project Access Token | One project only | CI/CD, project-specific integrations |
| Group Access Token | One group and its projects | Team-wide automation |
Create a Personal Access Token at Preferences → Access Tokens. Set the minimum scopes needed (e.g. read_repository only — not full api access) and set an expiry date.
Token Scopes — Least Privilege Principle
Common token scopes: ───────────────────────────────────────────────────────── api → full API access (powerful — use sparingly) read_api → read-only API access read_repository → clone and pull code write_repository → push code read_registry → pull container images write_registry → push container images ───────────────────────────────────────────────────────── Rule: grant only the scopes the tool actually needs.
IP Allowlisting
On GitLab Premium and Ultimate, you can restrict group access to specific IP address ranges. Any request from outside those ranges — even with valid credentials — gets blocked.
Group: acme-corp IP allowlist: 203.0.113.0/24 ← only office network Employee at office (203.0.113.45) → access granted ✅ Employee on home Wi-Fi (185.4.x.x) → access denied ❌ Attacker elsewhere (45.x.x.x) → access denied ❌
Configure at Group Settings → General → Permissions → Restrict access by IP address.
Two-Factor Authentication Enforcement
Group Owners can require all members to enable two-factor authentication. Members who do not comply lose access to the group until they set it up.
Group Settings → General → Permissions → Require all users in this group to set up two-factor authentication Grace period: 7 days ───────────────────────────────────────────────────────────────── Members without 2FA: shown a warning banner After grace period: access to group revoked until 2FA is enabled
Audit Events — Who Did What and When
GitLab records every significant action — who logged in, who changed a permission, who pushed to a protected branch — in the Audit Events log.
Audit Events (last 24 hours) ────────────────────────────────────────────────────────────────────── Event Author Target Time ────────────────────────────────────────────────────────────────────── Changed member role Sara john@co.com 10:42 AM Pushed to protected branch Arjun main 09:15 AM ❌ blocked Deleted deploy key Riya server-key 08:30 AM Added member Owner new@co.com 08:00 AM ──────────────────────────────────────────────────────────────────────
Find audit events at Group → Secure → Audit Events or for an instance at Admin Area → Monitoring → Audit Events.
