mirror of
https://github.com/quay/quay.git
synced 2026-01-26 06:21:37 +03:00
90 lines
2.6 KiB
Markdown
90 lines
2.6 KiB
Markdown
# API & Authentication
|
|
|
|
## API Architecture
|
|
|
|
**API v1** (`endpoints/api/`): REST API for UI and programmatic access
|
|
- Flask-based with resource decorators
|
|
- Session-based auth with CSRF tokens
|
|
- Endpoints return JSON
|
|
|
|
**API v2** (`endpoints/v2/`): OCI/Docker Registry Protocol
|
|
- JWT bearer token authentication
|
|
- Implements Docker Registry HTTP API V2
|
|
- Scope-based access control
|
|
|
|
## Testing API v1 (Session Auth)
|
|
|
|
```bash
|
|
# 1. Get CSRF token and establish session
|
|
CSRF_TOKEN=$(curl -s -c cookies.txt -b cookies.txt "http://localhost:8080/csrf_token" | jq -r '.csrf_token')
|
|
|
|
# 2. Sign in
|
|
curl -s -c cookies.txt -b cookies.txt -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Requested-With: XMLHttpRequest" \
|
|
-H "X-CSRF-Token: $CSRF_TOKEN" \
|
|
-d '{"username": "admin", "password": "password"}' \
|
|
"http://localhost:8080/api/v1/signin"
|
|
|
|
# 3. Use session cookies for API calls
|
|
curl -s -b cookies.txt "http://localhost:8080/api/v1/user/"
|
|
```
|
|
|
|
**Note:** Basic auth does NOT work with local dev for API v1.
|
|
|
|
## Testing API v2 (JWT Bearer Tokens)
|
|
|
|
```bash
|
|
# Get bearer token
|
|
TOKEN=$(curl -s -u username:password "http://localhost:8080/v2/auth?service=localhost:8080" | jq -r '.token')
|
|
|
|
# Use for v2 calls
|
|
curl -s -H "Authorization: Bearer $TOKEN" "http://localhost:8080/v2/_catalog"
|
|
|
|
# With specific scope
|
|
TOKEN=$(curl -s -u username:password \
|
|
"http://localhost:8080/v2/auth?service=localhost:8080&scope=repository:namespace/repo:pull" \
|
|
| jq -r '.token')
|
|
```
|
|
|
|
## Adding API v1 Endpoints
|
|
|
|
1. Add endpoint to file in `endpoints/api/`
|
|
2. Use appropriate decorators:
|
|
```python
|
|
from endpoints.api import resource, nickname, require_repo_read
|
|
|
|
@resource('/v1/repository/<namespace>/<repository>/example')
|
|
class RepositoryExample(RepositoryParamResource):
|
|
@require_repo_read(allow_for_global_readonly_superuser=True)
|
|
@nickname('getExample')
|
|
def get(self, namespace, repository):
|
|
# Implementation
|
|
```
|
|
3. Create model interface in `*_models_interface.py`
|
|
4. Implement model in `*_models_pre_oci.py`
|
|
5. Add tests in `endpoints/api/test/` or `test/`
|
|
|
|
## Permission Decorators
|
|
|
|
```python
|
|
# Repository permissions
|
|
@require_repo_read(allow_for_global_readonly_superuser=True)
|
|
@require_repo_write
|
|
@require_repo_admin
|
|
|
|
# User permissions
|
|
@require_user_admin
|
|
@require_fresh_login
|
|
|
|
# Superuser
|
|
@require_scope(scopes.SUPERUSER)
|
|
```
|
|
|
|
## Key Files
|
|
|
|
- `endpoints/api/__init__.py` - Core API setup, helper functions
|
|
- `endpoints/decorators.py` - Permission decorators
|
|
- `endpoints/exception.py` - API exceptions (Unauthorized, NotFound, etc.)
|
|
- `auth/permissions.py` - Permission classes
|