access control
GitLab Ultimate Access Control
This guide covers access control mechanisms in GitLab Ultimate including protected branches, merge request approvals, code owners, push rules, and environment protection. Access control ensures code quality, security, and compliance through enforced workflows.
Overview
GitLab Ultimate provides comprehensive access control capabilities:
- Protected Branches - Control who can merge and push to critical branches
- Protected Tags - Prevent unauthorized tag creation and deletion
- Merge Request Approvals - Require code review before merging
- Code Owners (CODEOWNERS) - Assign ownership and require approval
- Push Rules - Enforce commit standards and prevent problematic changes
- Environment Protection - Control deployments to sensitive environments
- Branch Rules - Unified interface for all protection rules
Protected Branches
Overview
Protected branches control which users can merge and push code changes, prevent accidental deletion, enforce code review, and manage approval requirements.
Configuration
Basic Protection:
- Navigate to: Settings > Repository > Branch Rules
- Select branch to protect (e.g.,
main,production) - Configure protection rules:
- Allowed to merge
- Allowed to push and merge
- Allowed to force push
- Require approval before merging
Protection Levels:
- No one - Completely blocks action
- Maintainers - Only project maintainers
- Developers + Maintainers - Developer role and above
- Specific users/groups - Granular control (Premium/Ultimate)
Recommended Configurations
Production Branch:
Branch: main
Allowed to merge: Maintainers only
Allowed to push: No one (force merge requests)
Allowed to force push: No one (disabled)
Require approval: Yes (2 approvals)
Code owner approval: Required
Pipelines must succeed: Yes
Development Branch:
Branch: development
Allowed to merge: Developers + Maintainers
Allowed to push: No one (force merge requests)
Allowed to force push: No one (disabled)
Require approval: Yes (1 approval)
Code owner approval: Optional
Pipelines must succeed: Yes
Release Branches:
Branches: release/*
Allowed to merge: Maintainers only
Allowed to push: No one (force merge requests)
Allowed to force push: No one (disabled)
Require approval: Yes (2 approvals)
Code owner approval: Required
Pipelines must succeed: Yes
Advanced Protection Rules
Wildcard Patterns:
Protect multiple branches with patterns:
Pattern: release/*
Protects: release/v1.0, release/v2.0, release/v2.1, etc.
Pattern: hotfix/*
Protects: hotfix/security-patch, hotfix/critical-bug, etc.
Pattern: feature/*
Protects: All feature branches
Premium/Ultimate Features:
- Specific users/groups - Granular permission assignment
- Deploy keys - Allow automated deployments
- No one exception - Completely block operations
- Code owner approval - Require approval from code owners
- Multiple approval rules - Different rules for different changes
Branch Protection Best Practices
- Always Protect
main- Never allow direct pushes to production branch - Force Merge Requests - Set "Allowed to push" to "No one"
- Disable Force Push - Maintain commit history integrity
- Require Pipeline Success - Ensure tests pass before merge
- Enable Code Owners - Assign ownership and responsibility
- Multiple Approvals - Require 2+ approvals for critical branches
- Separation of Duties - Prevent author approval
Example: Enterprise Configuration
Protected Branches Configuration - Enterprise Standards main (production): merge: allowed: ["@maintainers", "@tech-leads"] approvals_required: 2 code_owners_required: true prevent_author_approval: true push: allowed: [] # No one can push directly force_push: false pipeline: must_succeed: true required_jobs: - security_scanning - automated_tests - code_quality development (staging): merge: allowed: ["@developers", "@maintainers"] approvals_required: 1 code_owners_required: false prevent_author_approval: true push: allowed: [] # Force merge requests force_push: false pipeline: must_succeed: true release/* (release branches): merge: allowed: ["@release-managers"] approvals_required: 3 # Tech lead, QA, Product code_owners_required: true prevent_author_approval: true push: allowed: [] force_push: false pipeline: must_succeed: true deployment_approvals: - environment: production approvers: ["@devops-team", "@cto"] approvals_required: 2
Protected Tags
Overview
Protected tags prevent unauthorized creation and deletion of Git tags, ensuring release integrity and version control.
Configuration
Protecting Tags:
- Navigate to: Settings > Repository > Protected Tags
- Click "Add tag"
- Configure:
- Tag name or pattern
- Allowed to create
- Allowed to delete (Ultimate only)
Tag Protection Levels:
- No one - Block all tag creation
- Maintainers - Only maintainers can create tags
- Developers + Maintainers - Developer role and above
- Specific users/groups - Granular control (Ultimate)
Recommended Configurations
Release Tags:
Pattern: v*
Allowed to create: Maintainers only
Allowed to delete: No one
Purpose: Protect version tags (v1.0.0, v2.1.3, etc.)
Deployment Tags:
Pattern: deploy-*
Allowed to create: @devops-team
Allowed to delete: Maintainers only
Purpose: Control deployment markers
Best Practices
- Protect Version Tags - Use pattern
v*for semantic versions - Block Deletion - Set "Allowed to delete" to "No one"
- Restrict Creation - Only allow maintainers or release managers
- Use Patterns - Protect entire tag namespaces
- Audit Tag Changes - Monitor audit events for tag operations
Merge Request Approvals
Overview
Merge request approvals enforce code review by requiring explicit approval before merging. They ensure code quality, knowledge sharing, and compliance with change management policies.
Configuration
Basic Approval Rules:
- Navigate to: Settings > Merge Requests > Approval Rules
- Click "Add approval rule"
- Configure:
- Rule name
- Approvals required
- Eligible approvers
- Target branches
- Additional settings
Approval Rule Structure:
Approval Rule: Code Review
Approvals required: 2
Eligible approvers: @senior-developers, @tech-leads
Target branches: main, development
Prevent author approval: Yes
Prevent committers approval: Yes
Remove approvals on push: Yes
Approval Rule Types
Basic Rules:
Simple approval requirements:
Rule: General Code Review
Approvals Required: 1
Eligible Approvers: All project members with Developer role or higher
Specific Approvers (Premium/Ultimate):
Require approval from designated individuals or groups:
Rule: Senior Developer Review
Approvals Required: 1
Eligible Approvers:
- @alice
- @bob
- @senior-dev-team
Target Branches: main
Code Owner Rules (Premium/Ultimate):
Require approval from code owners:
Rule: Code Owner Approval
Approvals Required: 1 per code owner section
Eligible Approvers: Defined in CODEOWNERS file
Applies to: Files matching CODEOWNERS patterns
External Approval (Ultimate):
Require approval from external systems:
Rule: External Security Scan
Type: External approval
External URL: https://security-tool.example.com/approve
External Token: $SECURITY_TOOL_TOKEN
Advanced Approval Settings
Prevent Author Approval:
Author cannot approve their own merge request:
Setting: Prevent approval by author
Status: Enabled
Effect: MR author must get approval from others
Compliance: Separation of duties
Prevent Committers Approval:
Users who committed to MR cannot approve:
Setting: Prevent approval by merge request committers
Status: Enabled
Effect: Only non-contributors can approve
Use Case: Strict separation of duties
Remove Approvals on Push:
New commits remove existing approvals:
Setting: Remove all approvals when commits are added
Status: Enabled
Effect: Forces re-review after changes
Ensures: Latest code is reviewed
Require Approval from Code Owners:
Code owner approval required for files they own:
Setting: Require approval from code owners
Status: Enabled
Effect: CODEOWNERS file controls approvals
Target: Protected branches only
Override Approval Rules:
Allow approvers to approve despite approval rules:
Setting: Allow approval by committers
Status: Disabled (recommended)
Effect: Strict approval enforcement
Use Case: Compliance requirements
Multiple Approval Rules
Combining Rules:
Multiple approval rules can be configured simultaneously:
Rule 1: General Code Review
Approvals: 1
Approvers: @developers
Rule 2: Senior Developer Review
Approvals: 1
Approvers: @senior-developers
Applies when: Changes to /app/models/*
Rule 3: Security Review
Approvals: 1
Approvers: @security-team
Applies when: Changes to /app/controllers/auth*
Rule 4: Database Review
Approvals: 1
Approvers: @dba-team
Applies when: Changes to /db/migrate/*
Total Required Approvals: Depends on files changed
Example: MR touching /app/models/user.rb requires 2 approvals
(General + Senior Developer)
Approval Workflows
Standard Workflow:
1. Developer creates MR
2. CI/CD pipeline runs
3. Reviewer(s) review code
4. Reviewer(s) approve MR
5. All approval rules satisfied
6. Developer (or maintainer) merges
Separation of Duties Workflow:
1. Developer creates MR
2. CI/CD pipeline runs
3. Code owner reviews (cannot be author)
4. Code owner approves
5. Senior developer reviews (cannot be author or committer)
6. Senior developer approves
7. Security scans pass
8. Maintainer merges (cannot be author)
Best Practices
- Require Multiple Approvals - At least 2 approvals for production code
- Prevent Self-Approval - Enable "Prevent author approval"
- Remove on Push - Force re-review after changes
- Use Code Owners - Assign ownership and responsibility
- Target Critical Branches - Apply strict rules to
main,production - External Approvals - Integrate security tools and scanners
- Document Rules - Explain why each rule exists
Code Owners (CODEOWNERS)
Overview
CODEOWNERS files define individuals or teams responsible for specific code sections. Code owners are automatically requested as reviewers and can be required to approve changes.
CODEOWNERS File
File Location:
GitLab checks three locations (in order):
./CODEOWNERS(repository root)./docs/CODEOWNERS(docs directory)./.gitlab/CODEOWNERS(GitLab directory)
Basic Syntax:
# CODEOWNERS
# Default owners for everything
* @tech-lead
# Frontend code
/app/javascript/ @frontend-team
# Backend code
/app/models/ @backend-team
/app/controllers/ @backend-team
# Database migrations
/db/migrate/ @dba-team
# Infrastructure
/terraform/ @devops-team
/kubernetes/ @devops-team
# Security-critical code
/app/models/user.rb @security-team
/app/controllers/sessions_controller.rb @security-team
# Documentation
/docs/ @technical-writers
# CI/CD configuration
/.gitlab-ci.yml @devops-team
Advanced CODEOWNERS Syntax
Multiple Owners:
# All listed owners must approve
/app/api/ @api-team @architecture-team
Groups as Owners:
# Use GitLab groups
/secure/ @security/appsec-team
/payments/ @finance/payment-team
Specific Files:
# Exact file matches
package.json @frontend-lead
Dockerfile @devops-lead
Wildcard Patterns:
# Any file with specific extension
*.rb @ruby-team
*.js @javascript-team
*.sql @dba-team
# Any file matching pattern
test_*.py @qa-team
*_spec.rb @test-automation-team
Sectional Code Owners (Ultimate):
Require multiple approvals from different sections:
# CODEOWNERS
# Section: Frontend [2]
# Requires 2 approvals from frontend team
/app/javascript/ @frontend-team
# Section: Backend [1]
# Requires 1 approval from backend team
/app/models/ @backend-team
/app/controllers/ @backend-team
# Section: Security [2]
# Requires 2 approvals from security team
/app/controllers/sessions_controller.rb @security-team
/app/models/user.rb @security-team
Syntax Format:
# Section: <name> [<number>]
<path> <owners>
Enabling Code Owner Approval
Configuration:
- Navigate to: Settings > Repository > Branch Rules
- Select protected branch
- Enable: "Require approval from code owners"
Effect:
- Code owners automatically added as reviewers
- Code owner approval required before merge
- MR cannot merge without code owner approval
- Applies only to protected branches
Code Owner Workflow
Developer Perspective:
1. Create feature branch
2. Make changes to /app/models/user.rb
3. Create MR
4. GitLab detects CODEOWNERS file
5. @security-team automatically added as reviewers
6. Developer waits for security team approval
7. After approval, developer can merge (if has permission)
Code Owner Perspective:
1. Notification: MR ready for review
2. Review changes in owned files
3. Check security implications
4. Test changes if needed
5. Approve or request changes
6. MR can now merge (if all rules satisfied)
Best Practices
- Start Broad, Get Specific - Default owner for everything, specific owners for critical code
- Use Teams, Not Individuals - Avoid single points of failure
- Document Sections - Use comments to explain ownership
- Regular Reviews - Update CODEOWNERS as team structure changes
- Test Changes - Verify CODEOWNERS patterns match intended files
- Multiple Approvals - Use sectional owners for critical code
- Balance Coverage - Don't make every file require approval
Troubleshooting
Code owner approval showing as optional:
- Verify "Require approval from code owners" enabled on protected branch
- Check CODEOWNERS file is in correct location
- Ensure code owners have at least Developer role
- Verify patterns match changed files
Wrong code owners requested:
- Check CODEOWNERS file syntax
- Verify GitLab group/user references
- Test patterns with different files
- Review CODEOWNERS precedence (last match wins)
Code owners not receiving notifications:
- Verify notification settings
- Check group membership
- Ensure email notifications enabled
- Review user's merge request notification preferences
Push Rules
Overview
Push rules enforce standards on commits before they're accepted into the repository. They prevent problematic changes and ensure quality and compliance.
Availability
- Premium/Ultimate: Full push rule capabilities
- Free: Limited push rules via server hooks
Configuration
Enabling Push Rules:
- Navigate to: Settings > Repository > Push Rules
- Configure desired rules
- Save changes
Available Push Rules
Commit Message Rules:
Rule: Require commit message pattern
Pattern: ^(feat|fix|docs|style|refactor|test|chore):\s.+
Example: feat: add user authentication
Effect: Rejects commits not following conventional commits
Rule: Deny commit messages matching pattern
Pattern: (WIP|fixup|squash)
Effect: Prevents work-in-progress commits on protected branches
Rule: Require branch name pattern
Pattern: ^(feature|bugfix|hotfix|release)/
Example: feature/user-authentication
Effect: Enforces branch naming convention
File and Path Rules:
Rule: Reject files over size limit
Size: 100 MB
Effect: Prevents large files (binaries, datasets)
Rule: Prevent files matching pattern
Pattern: .(exe|dll|so)$
Effect: Blocks executable files
Rule: Require files matching pattern
Pattern: ^CHANGELOG.md$
Effect: Ensures changelog is updated
Author and Committer Rules:
Rule: Check whether author is GitLab user
Effect: Commits must have valid GitLab user email
Rule: Reject unsigned commits
Effect: Requires GPG-signed commits
Rule: Do not allow users to remove Git tags with git push
Effect: Prevents accidental tag deletion
Advanced Rules (Ultimate):
Rule: Maximum file name length
Length: 255 characters
Effect: Prevents filesystem issues
Rule: Commit author's email
Pattern: @company.com$
Effect: Requires corporate email addresses
Example Push Rule Configuration
Enterprise Standards:
Push Rules Configuration Commit Messages: Commit message must match: ^(feat|fix|docs|refactor|test|chore):\s.+ Branch name must match: ^(feature|bugfix|hotfix|release)/[a-z0-9-]+$ Commit message cannot contain: WIP|TODO|FIXME Files: Maximum file size: 50 MB Prevent pushing files matching: \.(exe|dll|so|dylib)$ Prevent pushing secret files: (\.env|credentials|secrets) Authors: Check whether author is GitLab user: Yes Require GPG-signed commits: Yes Author email must match: @company\.com$ Tags: Do not allow users to remove Git tags: Yes Member Check: Restrict commits by author (email) to existing GitLab users: Yes
Best Practices
- Conventional Commits - Enforce commit message format
- Block Large Files - Prevent repository bloat
- Require Signatures - Enable GPG signing for verification
- Corporate Emails - Require company email addresses
- Protect Tags - Prevent accidental tag deletion
- Branch Naming - Enforce consistent branch names
- Test Rules - Verify rules work as expected before enforcing
Troubleshooting
Push rejected by push rule:
Error: Commit message does not match required pattern
Resolution:
1. Review push rule configuration
2. Check commit message format
3. Amend commit message: git commit --amend
4. Force push: git push --force-with-lease
False rejections:
Issue: Valid commits rejected
Resolution:
1. Review push rule patterns
2. Test regex patterns with actual commit messages
3. Adjust pattern or exclude specific commits
4. Temporarily disable rule if needed
Environment Protection
Overview
Environment protection controls deployments to sensitive environments like production and staging. It ensures only authorized personnel can deploy and provides approval workflows.
Configuration
Protecting Environments:
- Navigate to: Deployments > Environments
- Select environment (e.g.,
production) - Click "Protect"
- Configure protection rules:
- Allowed to deploy
- Required approvals
- Approval users/groups
Protection Levels
Basic Protection:
Environment: production
Allowed to deploy: Maintainers only
Required approvals: 0
Effect: Only maintainers can trigger deployments
Approval-Required Protection (Premium/Ultimate):
Environment: production
Allowed to deploy: Developers + Maintainers
Required approvals: 2
Approval groups:
- @devops-team
- @product-owners
Effect: Deployment must be approved by both groups
Deployment Approval Workflow
Approval Process:
1. Pipeline reaches deployment job
2. Job pauses, waiting for approval
3. Notification sent to approval groups
4. Approvers review deployment
5. Approvers approve or reject
6. If approved: Deployment proceeds
7. If rejected: Deployment cancelled
Example:
# .gitlab-ci.yml deploy_production: stage: deploy environment: name: production url: https://app.example.com script: - ./deploy.sh production rules: - if: '$CI_COMMIT_BRANCH == "main"' when: manual # Deployment approval required (configured in environment settings)
Approval UI:
Pipeline: #12345
Job: deploy_production
Status: Waiting for approval
Required Approvals: 2
@alice (DevOps Lead) - Approved
³ @bob (Product Owner) - Pending
Approve | Reject
Multiple Approvals
Configuration:
Environment: production
Approvals Required: 3
Approval Groups:
- @devops-team (1 approval)
- @security-team (1 approval)
- @product-team (1 approval)
Effect: At least 1 person from each group must approve
Best Practices
- Protect Production - Always protect production environment
- Multiple Approvals - Require 2+ approvals for critical environments
- Diverse Approvers - Include different teams (DevOps, Security, Product)
- Manual Deployments - Use
when: manualfor production jobs - Rollback Capability - Ensure easy rollback if issues occur
- Audit Deployments - Review deployment audit events
- Schedule Windows - Consider maintenance windows for deployments
Branch Rules (Unified Interface)
Overview
Branch Rules provide a unified interface for managing all protection rules in one place. They simplify configuration by consolidating protected branches, approval rules, and other protections.
Accessing Branch Rules
Navigation: Settings > Repository > Branch Rules
Features:
- View all protection rules for a branch
- Configure multiple protections in one interface
- See effective permissions clearly
- Manage push rules and approval rules together
Branch Rule Components
Complete Branch Rule:
Branch: main
Protection Rules:
Allowed to merge: Maintainers
Allowed to push: No one
Allowed to force push: No one
Require code owner approval: Yes
Approval Rules:
General Review: 2 approvals required
Approvers: @senior-developers
Security Review: 1 approval required
Approvers: @security-team
Applies to: Security-related files
Prevent author approval: Yes
Pipeline Requirements:
Pipelines must succeed: Yes
Required jobs:
- security_scanning
- automated_tests
Optional jobs:
- performance_tests
Push Rules:
Commit message pattern: ^(feat|fix|docs):\s.+
Reject unsigned commits: Yes
Maximum file size: 50 MB
Status Checks:
External approval: Security Scanner
External approval: License Compliance
Configuring Branch Rules
Creating Complete Rule:
- Navigate to Branch Rules
- Add target branches (use patterns for multiple)
- Configure all protections:
- Push and merge permissions
- Approval requirements
- Pipeline requirements
- Push rules
- External checks
Example:
Target: release/*
Protection:
- Merge: Release Managers only
- Push: No one
- Force push: Disabled
Approvals:
- 3 approvals required
- Code owners must approve
- No self-approval
Pipeline:
- Must succeed
- Security scans required
- E2E tests required
Push Rules:
- Signed commits required
- Corporate email required
Best Practices
- Use Patterns - Protect multiple branches with wildcards
- Consistent Rules - Apply same rules to similar branches
- Document Rules - Add descriptions explaining requirements
- Regular Review - Audit rules quarterly
- Test Changes - Verify rules work as expected
- Gradual Rollout - Start strict on
main, expand to other branches
Security Best Practices
Defense in Depth
Multiple Layers:
Layer 1: Branch Protection
- No direct push to main
- Force push disabled
Layer 2: Merge Request Approval
- 2 approvals required
- No self-approval
- Code owner approval
Layer 3: Pipeline Requirements
- Security scans must pass
- Tests must pass
- Code quality checks
Layer 4: Deployment Approval
- Production requires approval
- Multiple approvers
- Audit trail
Layer 5: Monitoring
- Audit events enabled
- Real-time alerts
- Regular reviews
Compliance Configuration
SOC 2 / SOX Compliance:
Protected Branches:
main protected
No direct push
Force push disabled
Code owner approval required
Merge Requests:
2+ approvals required
Prevent author approval
Prevent committer approval
Remove approvals on push
Separation of Duties:
Different person approves
Different person merges
Different person deploys
Audit Trail:
All changes logged
Audit events enabled
Event streaming configured
Regular Audits
Quarterly Review Checklist:
Verify protected branch configuration
Review approval rule effectiveness
Check code owner assignments
Audit push rule violations
Review environment protection
Verify separation of duties
Check audit event retention
Update documentation
Troubleshooting
Common Issues
Cannot push to protected branch:
Error: You are not allowed to push code to protected branch main.
Resolution:
1. Check protected branch settings
2. Verify user role and permissions
3. Use merge request instead of direct push
4. Contact project maintainer if needed
Merge request blocked by approval rules:
Issue: MR cannot merge despite having approvals
Checklist:
All approval rules satisfied?
Code owner approval obtained?
Pipeline passed successfully?
No conflicts with target branch?
Protected branch rules met?
Code owner approval not working:
Issue: Code owner approval shown as optional
Resolution:
1. Verify CODEOWNERS file exists
2. Check file location (root, docs/, or .gitlab/)
3. Ensure "Require code owner approval" enabled
4. Verify patterns match changed files
5. Check code owners have correct role
References
- Protected Branches Documentation
- Merge Request Approvals Documentation
- Code Owners Documentation
- Push Rules Documentation
- Environment Protection Documentation
Next Steps
- Security Policies - Enforce security requirements automatically
- Compliance - Meet regulatory requirements
- Vulnerability Management - Track and remediate issues