Интеграция с LDAP/Active Directory, OAuth, SAML, ролевая модель, двухфакторная аутентификация.
Интеграция с LDAP/Active Directory, OAuth, SAML, ролевая модель, двухфакторная аутентификация
У вас 50 разработчиков в компании. Каждый день кто-то приходит, кто-то уходит. Менеджеры меняют команды. Как управлять доступом без боли?
Проблемы без централизованной аутентификации:
Решение:
Эта тема — о настройке корпоративной аутентификации в Gitea.
┌─────────────────────────────────────────────────────────────────────┐
│ Пользователи │
└─────────────────────────────────────────────────────────────────────┘
│ │ │
↓ ↓ ↓
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ LDAP/Active │ │ OAuth 2.0 │ │ SAML 2.0 │
│ Directory │ │ (Keycloak, │ │ (ADFS, Okta, │
│ │ │ Google) │ │ Ping) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
└────────────────────┼────────────────────┘
│
↓
┌─────────────────┐
│ Gitea │
│ Authentication │
│ Layer │
└─────────────────┘
│
↓
┌─────────────────┐
│ PostgreSQL │
│ (users, │
│ sessions) │
└─────────────────┘
Создание сервисного аккаунта для Gitea:
gitea-svcСтруктура AD:
dc=company,dc=ru
├── OU=Users
│ ├── CN=Ivanov, Ivan
│ │ ├── sAMAccountName: iivanov
│ │ ├── mail: iivanov@company.ru
│ │ └── memberOf: CN=developers
│ └── CN=Petrov, Petr
│ ├── sAMAccountName: ppetrov
│ └── memberOf: CN=admins
├── OU=Groups
│ ├── CN=developers
│ └── CN=admins
└── OU=Service Accounts
└── CN=gitea-svc
Вариант 1: Через app.ini
[source]
; Включение LDAP аутентификации
ENABLE_LDAP = true
; Источник аутентификации #1
[source.1]
NAME = Corporate LDAP
TYPE = ldap
; TYPE=2 для LDAP, TYPE=6 для Active Directory
SECURITY_PROTOCOL = ldaps
HOST = ldap.company.ru
PORT = 636
USER_DN = CN=gitea-svc,OU=Service Accounts,DC=company,DC=ru
USER_PASSWD = service_account_password
USER_SEARCH_BASE_DN = OU=Users,DC=company,DC=ru
USER_FILTER = (objectClass=person)
; Атрибуты
ATTRIBUTE_USERNAME = sAMAccountName
ATTRIBUTE_NAME = cn
ATTRIBUTE_SURNAME = sn
ATTRIBUTE_MAIL = mail
ATTRIBUTE_SSH_PUBLIC_KEY = sshPublicKey
; Синхронизация
ENABLE_SYNC = true
SYNC_ON_LOGIN = true
; Настройки для пользователей
ALLOW_USER_CREATE = true
AUTO_REGISTER = trueВариант 2: Через переменные окружения (Docker)
environment:
- GITEA__source__ENABLE_LDAP=true
- GITEA__source.1__NAME=Corporate LDAP
- GITEA__source.1__TYPE=6
- GITEA__source.1__SECURITY_PROTOCOL=ldaps
- GITEA__source.1__HOST=ldap.company.ru
- GITEA__source.1__PORT=636
- GITEA__source.1__USER_DN=CN=gitea-svc,OU=Service Accounts,DC=company,DC=ru
- GITEA__source.1__USER_PASSWD=service_password
- GITEA__source.1__USER_SEARCH_BASE_DN=OU=Users,DC=company,DC=ru
- GITEA__source.1__USER_FILTER=(objectClass=person)
- GITEA__source.1__ATTRIBUTE_USERNAME=sAMAccountName
- GITEA__source.1__ATTRIBUTE_NAME=cn
- GITEA__source.1__ATTRIBUTE_MAIL=mail
- GITEA__source.1__ENABLE_SYNC=true
- GITEA__source.1__SYNC_ON_LOGIN=true
- GITEA__source.1__AUTO_REGISTER=true| Поле | Значение |
|---|---|
| Название источника | Corporate LDAP |
| Протокол безопасности | LDAPS (TLS) |
| Сервер | ldap.company.ru |
| Порт | 636 |
| Привязка DN | CN=gitea-svc,OU=Service Accounts,DC=company,DC=ru |
| Пароль | (пароль сервисного аккаунта) |
| Базовый DN для пользователей | OU=Users,DC=company,DC=ru |
| Фильтр пользователей | (objectClass=person) |
| Атрибут имени пользователя | sAMAccountName |
| Атрибут имени | cn |
| Атрибут фамилии | sn |
| Атрибут email |
Проверка подключения из командной строки:
# Установка ldap-utils
sudo apt install -y ldap-utils
# Проверка подключения
ldapsearch -x -H ldaps://ldap.company.ru:636 \
-D "CN=gitea-svc,OU=Service Accounts,DC=company,DC=ru" \
-W \
-b "OU=Users,DC=company,DC=ru" \
"(sAMAccountName=iivanov)"
# Введите пароль при запросеОжидаемый вывод:
# iivanov, Users, company.ru
dn: CN=Ivanov\, Ivan,OU=Users,DC=company,DC=ru
sAMAccountName: iivanov
mail: iivanov@company.ru
cn: Ivanov, Ivan
Ручная синхронизация:
Автоматическая синхронизация:
[service]
; Синхронизация при входе
LDAP_SYNC_ON_LOGIN = true
[server]
; Периодическая синхронизация (cron)
; Запуск каждые 24 часа
CRON_SYNC_LDAP = @every 24hCron задача для синхронизации:
# /etc/cron.d/gitea-ldap-sync
0 2 * * * root docker exec gitea gitea admin auth ldap sync-allНастройка маппинга:
[source.1]
; Включение маппинга групп
GROUP_SEARCH_BASE_DN = OU=Groups,DC=company,DC=ru
GROUP_FILTER = (objectClass=group)
GROUP_NAME_ATTRIBUTE = cn
GROUP_MEMBER_ATTRIBUTE = member
USER_GROUP_ATTRIBUTE = memberOf
; Синхронизация членства в группах
SYNC_GROUPS = trueАвтоматическое создание организаций:
; Создание организации из LDAP группы
AUTO_CREATE_ORG = true
; Имя организации из атрибута
ORG_NAME_ATTRIBUTE = cnВключение OAuth в Gitea:
[oauth2]
ENABLE = true
; Время жизни токенов
ACCESS_TOKEN_EXPIRATION = 3600
REFRESH_TOKEN_EXPIRATION = 86400
; Минимальная длина secret
MINIMAL_TOKEN_LENGTH = 32Создание OAuth приложения:
https://ci.company.ru/oauth/callbackИспользование токена:
# Получение токена
curl -X POST http://git.company.ru/login/oauth/access_token \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=AUTH_CODE" \
-d "redirect_uri=https://ci.company.ru/oauth/callback"
# Ответ:
# {
# "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "token_type": "bearer",
# "expires_in": 3600,
# "refresh_token": "..."
# }
# Использование токена
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
http://git.company.ru/api/v1/userНастройка Keycloak как Identity Provider:
gitea-realmgitea-client
http://git.company.ru/user/oauth2/Keycloak/callbackНастройка Gitea:
[oauth2]
ENABLE = true
[source]
ENABLE_OAUTH2 = true
[source.oauth2_keycloak]
NAME = Keycloak SSO
PROVIDER = keycloak
; URL Keycloak
AUTH_URL = https://keycloak.company.ru/realms/gitea-realm/protocol/openid-connect/auth
TOKEN_URL = https://keycloak.company.ru/realms/gitea-realm/protocol/openid-connect/token
PROFILE_URL = https://keycloak.company.ru/realms/gitea-realm/protocol/openid-connect/userinfo
; Client credentials
CLIENT_ID = gitea-client
CLIENT_SECRET = your_client_secret
; Маппинг атрибутов
EMAIL_ATTRIBUTE = email
NAME_ATTRIBUTE = name
USERNAME_ATTRIBUTE = preferred_username
; Автоматическая регистрация
AUTO_REGISTER = trueДобавление через веб-интерфейс:
Создание relying party trust в ADFS:
Настройка идентификаторов:
Relying party trust identifier: https://git.company.ru/user/oauth2/SAML/callback
Assertion consumer service URL: https://git.company.ru/user/oauth2/SAML/callback
Настройка claims:
<!-- Email claim -->
<ClaimTypeReference>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress</ClaimTypeReference>
<OutgoingClaimType>Email</OutgoingClaimType>
<!-- Name claim -->
<ClaimTypeReference>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name</ClaimTypeReference>
<OutgoingClaimType>Name</OutgoingClaimType>
<!-- UPN claim -->
<ClaimTypeReference>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn</ClaimTypeReference>
<OutgoingClaimType>Username</OutgoingClaimType>Экспорт метаданных:
# Экспорт метаданных ADFS
Export-AdfsRelyingPartyTrust -TargetName "Gitea" -FilePath "C:\adfs-gitea.xml"[oauth2]
ENABLE = true
[source.oauth2_saml]
NAME = ADFS SAML
PROVIDER = saml
; SAML endpoint
AUTH_URL = https://adfs.company.ru/adfs/ls/
; SAML issuer (Gitea URL)
ISSUER = https://git.company.ru
; SAML callback
REDIRECT_URI = https://git.company.ru/user/oauth2/SAML/callback
; Сертификат ADFS (base64)
CERTIFICATE = |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiUMA0Gcg...
-----END CERTIFICATE-----
; Маппинг атрибутов
EMAIL_ATTRIBUTE = Email
NAME_ATTRIBUTE = Name
USERNAME_ATTRIBUTE = UPN
; Подпись запросов
SIGN_REQUESTS = true
; Автоматическая регистрация
AUTO_REGISTER = trueЗагрузка метаданных IdP:
Принудительное включение:
[security]
; Требовать 2FA для всех пользователей
ENABLE_2FA = true
; Запрет входа без 2FA
DISABLE_REGISTRATION = true
; Разрешить remember me с 2FA
ENABLE_REMEMBER_ME_2FA = trueПолитика 2FA через организацию:
CompanyПользователь:
Администратор:
# Проверка статуса 2FA у пользователей
docker exec gitea gitea admin user list --admin
# Сброс 2FA для пользователя (если потерял доступ)
docker exec gitea gitea admin user generate-2fa-bypass-codes --username iivanovВключение WebAuthn:
[webauthn]
ENABLE = true
; Домен для WebAuthn
DOMAIN = git.company.ru
; Timeout для аутентификации
TIMEOUT = 60000
; Разрешённые типы ключей
ATTESTATION_PREFERENCE = preferredРегистрация ключа:
| Роль | Описание | Права |
|---|---|---|
| Admin | Администратор Gitea | Полный доступ ко всем функциям |
| Owner | Владелец организации | Управление членами, репозиториями |
| Member | Участник организации | Доступ к репозиториям организации |
| Outside Collaborator | Внешний collaborator | Доступ к конкретным репозиториям |
| Read | Только чтение | Clone, просмотр issues |
| Write | Запись | Push, создание issues |
| Admin (репозитория) | Админ репозитория | Управление настройками репозитория |
Ограничение видимости:
[service]
; Требовать вход для просмотра репозиториев
REQUIRE_SIGNIN_VIEW = true
; Запрет анонимного создания организаций
DISABLE_REGISTRATION_ORG = true
; Только администраторы могут создавать организации
ALLOW_ONLY_ADMIN_CREATE_ORG = trueПолитики репозиториев:
[repository]
; Максимальный размер push (MB)
MAX_PUSH_FILES = 100
; Запрет force push по умолчанию
DEFAULT_DISABLE_PUSH = false
; Требовать signed commits
DEFAULT_REQUIRE_SIGNED_COMMITS = false# Защита ветки main
curl -X POST http://git.company.ru/api/v1/repos/{owner}/{repo}/branch_protections \
-H "Authorization: token $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"branch_name": "main",
"enable_push_whitelist": true,
"push_whitelist_usernames": ["admin", "lead-dev"],
"enable_merge_whitelist": true,
"merge_whitelist_usernames": ["admin", "lead-dev"],
"required_approvals": 2,
"enable_status_check": true,
"status_check_contexts": ["ci/test", "ci/build"]
}'Симптомы: Ошибка "LDAP connection failed" при тестировании.
Решение:
# Проверка доступности LDAP сервера
telnet ldap.company.ru 636
# Проверка сертификата
openssl s_client -connect ldap.company.ru:636 -showcerts
# Проверка учётных данных
ldapsearch -x -H ldaps://ldap.company.ru:636 \
-D "CN=gitea-svc,OU=Service Accounts,DC=company,DC=ru" \
-W -b "DC=company,DC=ru" "(objectClass=*)"Симптомы: Вход через LDAP работает, но пользователь не создаётся в Gitea.
Решение: Проверьте настройки:
AUTO_REGISTER = true
ALLOW_USER_CREATE = trueСимптомы: Ошибка подписи при SAML аутентификации.
Решение:
Следующий шаг: Best practices: политики, код-ревью, оптимизация
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.