Access Tokens
Guide to configuring GitLab access tokens for GitPulse.
Types of tokens
graph TB
subgraph "GitLab Tokens"
PAT["Personal Access Token"]
GAT["Group Access Token"]
PAT2["Project Access Token"]
OAUTH["OAuth2 Token"]
end
PAT --> |"Suitable for"| DEV["Development"]
GAT --> |"Suitable for"| PROD["Production"]
PAT2 --> |"Suitable for"| SINGLE["Single project"]
OAUTH --> |"Suitable for"| USER["User context"]
| Type | Using | Scope | Lifetime |
| Personal Access Token | Development | User-level | Configurable |
| Group Access Token | Production | Group-level | Max 1 year |
| Project Access Token | Single project | Project-level | Max 1 year |
| OAuth2 Token | User auth | User-level | Short-lived |
Personal Access Token
Creation
- Sign in to GitLab
- Click on avatar -> Preferences
- In the left menu: Access Tokens
- Fill in:
- Token name:
GitPulse Production or GitPulse Development - Expiration date: Max 1 year (365 days)
- Scopes: See below
Required scopes
| Text Only |
|---|
| Yes api - Full API access
Yes read_api - Read-only API access
Yes read_user - Read user info
Yes read_repository - Clone/fetch repositories
□ write_repository - Push (not needed)
|
Minimum privilege
For production, use only the minimum required permissions. For read-only access, the following are sufficient: read_api, read_repository.
An example
| Bash |
|---|
| # Token looks like this:
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
# Test the token
curl -H "Private-Token: ${GITLAB_TOKEN}" \
"https://gitlab.kpi.tuke.sk/api/v4/user"
|
Group Access Token
For production deployment, we recommend Group Access Token.
Creation
- Go to GitLab Group (eg
/kpi/tp-2024) - Settings -> Access Tokens
- Fill in:
- Token name:
GitPulse Sync Token - Expiration date: End of semester
- Role:
Reporter or Developer - Scopes:
api, read_repository
Advantages
- It is not tied to a specific user
- It works even if the user leaves
- More granular scope control
- Audit log at group level
Project Access Token
For single-project integration:
| Bash |
|---|
| # At the project level: Settings -> Access Tokens
# Create a token with the Reporter role and read_api scope
|
Configuration in GitPulse
Environment variables
| Bash |
|---|
| # .env
GITLAB_URL=https://gitlab.kpi.tuke.sk
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
# For multiple instances (advanced)
GITLAB_TOKENS='[
{"name": "primary", "token": "glpat-xxx", "url": "https://gitlab.kpi.tuke.sk"},
{"name": "backup", "token": "glpat-yyy", "url": "https://gitlab.example.com"}
]'
|
Docker secrets (production)
| YAML |
|---|
| # docker-compose.yml
services:
api:
secrets:
- gitlab_token
environment:
GITLAB_TOKEN_FILE: /run/secrets/gitlab_token
secrets:
gitlab_token:
file: ./secrets/gitlab_token.txt
|
| Bash |
|---|
| # Create the secret file
mkdir -p secrets
echo "glpat-xxxxxxxxxxxxxxxxxxxx" > secrets/gitlab_token.txt
chmod 600 secrets/gitlab_token.txt
|
Token rotation
Automatic notification
| Python |
|---|
| # Monitoring token expiration
from datetime import datetime, timedelta
def check_token_expiry(token_info: dict) -> bool:
expiry = datetime.fromisoformat(token_info['expires_at'])
warning_threshold = datetime.now() + timedelta(days=30)
if expiry < warning_threshold:
send_alert(f"Token expires in {(expiry - datetime.now()).days} days")
return True
return False
|
Manual rotation
| Bash |
|---|
| # 1. Create a new token (see above)
# 2. Update .env
nano .env
# Change GITLAB_TOKEN to the new one
# 3. Restart services
docker compose restart api worker
# 4. Verify functionality
curl http://localhost:8000/api/v1/health
# 5. Revoke the old token in GitLab UI
|
Zero-downtime rotation
| Bash |
|---|
| # 1. Add the new token as secondary
GITLAB_TOKEN_NEW=glpat-newtoken
# 2. Update configuration to use both
# (application tries primary, then fallback)
# 3. Switch to the new one as primary
GITLAB_TOKEN=${GITLAB_TOKEN_NEW}
# 4. Remove the old one
|
Troubleshooting
The token does not work
| Bash |
|---|
| # Test basic access
curl -I -H "Private-Token: ${GITLAB_TOKEN}" \
"https://gitlab.kpi.tuke.sk/api/v4/user"
# Expected response: HTTP 200
# If 401: Token is invalid or expired
# If 403: Insufficient permissions
|
Rate limiting
| Bash |
|---|
| # Check rate limit headers
curl -i -H "Private-Token: ${GITLAB_TOKEN}" \
"https://gitlab.kpi.tuke.sk/api/v4/projects" | head -20
# RateLimit-Limit: 600
# RateLimit-Remaining: 599
# RateLimit-Reset: 1699999999
|
Scope problems
| Bash |
|---|
| # Test read-only scope
curl -H "Private-Token: ${GITLAB_TOKEN}" \
"https://gitlab.kpi.tuke.sk/api/v4/projects/123/repository/commits"
# Test API scope
curl -H "Private-Token: ${GITLAB_TOKEN}" \
"https://gitlab.kpi.tuke.sk/api/v4/projects/123/issues"
|
Safety recommendations
Best practices
- Use Group/Project tokens instead of Personal tokens
- Minimum permissions - only necessary scopes
- Short expiration - max 6 months for production
- Rotation - regular exchange of tokens
- Audit - monitor token usage
What to avoid
Token sharing between environments Tokens in Git repository Personal tokens in production Tokens without expiration
Audit log
| SQL |
|---|
| -- All API calls with the token
SELECT
timestamp,
endpoint,
method,
response_status,
user_agent
FROM api_audit_log
WHERE token_hash = 'sha256:xxxx'
ORDER BY timestamp DESC
LIMIT 100;
|
Further reading