GITHUB_TOKEN, OIDC, least privilege, аудит и логирование.
Безопасность CI/CD пайплайнов критична для защиты кода и инфраструктуры. Изучите GITHUB_TOKEN permissions, OIDC, аудит и лучшие практики.
GITHUB_TOKEN — автоматически генерируемый токен доступа для GitHub Actions. Выдаётся каждому запуску workflow.
Характеристики:
Токен предоставляет доступ к ресурсам репозитория:
┌─────────────────────────────────────────┐
│ GITHUB_TOKEN Scope │
├─────────────────────────────────────────┤
│ ✅ Чтение/запись репозитория │
│ ✅ Создание релизов и тегов │
│ ✅ Управление issues и PR │
│ ✅ Работа с Packages (GHCR) │
│ ✅ Trigger workflow_dispatch │
│ ❌ Доступ к secrets (из fork) │
│ ❌ Изменение настроек репозитория │
│ ❌ Доступ к другим репозиториям │
└─────────────────────────────────────────┘
Автоматическое использование:
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# GITHUB_TOKEN доступен автоматически
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Явная передача:
steps:
- name: Push changes
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add .
git commit -m "Auto-update"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}По умолчанию GitHub устанавливает права в зависимости от настроек организации:
Настройки организации:
Рекомендация: Всегда явно указывайте permissions в workflow.
Синтаксис:
permissions:
contents: read # Чтение кода репозитория
packages: write # Запись в Packages
issues: read # Чтение issues
pull-requests: write # Запись в PR
id-token: write # OIDC токены
actions: read # Чтение информации о workflow
security-events: write # Запись security eventsУровни доступа:
read — только чтениеwrite — чтение и записьnone — доступ запрещёнТолько чтение кода:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm testДеплой в GHCR:
permissions:
contents: read
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
run: docker push ghcr.io/my-org/my-app:latestСоздание релиза:
permissions:
contents: write # Для создания релиза и загрузки артефактов
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: dist/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}OIDC для облака:
permissions:
contents: read
id-token: write # Обязательно для OIDC
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions
aws-region: us-east-1Можно переопределять permissions на уровне job:
permissions:
contents: read # Default для всех jobs
jobs:
test:
runs-on: ubuntu-latest
# Наследует contents: read
steps:
- run: npm test
deploy:
runs-on: ubuntu-latest
permissions:
contents: write # Переопределение для job
id-token: write
steps:
- run: ./deploy.shПлохо:
# Слишком широкие права
permissions:
contents: write
packages: write
issues: write
pull-requests: write
actions: writeХорошо:
# Только необходимые права
permissions:
contents: read # Только для checkoutОпасный триггер — pull_request_target:
# ❌ ОПАСНО: workflow имеет доступ к secrets и правам base branch
on:
pull_request_target:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Злоумышленник может выполнить код в контексте mainБезопасная альтернатива:
# ✅ Безопасно: workflow запускается в контексте PR
on:
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Нет доступа к secrets, код выполняется в изоляцииПроверка inputs в workflow_dispatch:
on:
workflow_dispatch:
inputs:
version:
description: 'Version to deploy'
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Validate version
run: |
if ! [[ "${{ github.event.inputs.version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid version format"
exit 1
fi
shell: bash
- name: Deploy
run: ./deploy.sh ${{ github.event.inputs.version }}Опасно — интерполяция user input:
# ❌ Уязвимо к injection
on:
issue_comment:
types: [created]
jobs:
deploy:
if: github.event.comment.body == '/deploy'
steps:
- run: ./deploy.sh ${{ github.event.comment.user.login }}Безопасно — валидация и экранирование:
# ✅ Безопасно
jobs:
deploy:
steps:
- name: Validate username
run: |
USERNAME="${{ github.event.comment.user.login }}"
if ! [[ "$USERNAME" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Invalid username"
exit 1
fi
echo "USERNAME=$USERNAME" >> $GITHUB_ENV
- run: ./deploy.sh "$USERNAME"Плохо — использование тегов:
# ❌ Тег может быть перемещён
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4Хорошо — pin к полному хешу:
# ✅ Полный SHA хеш
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2Автоматизация через Dependabot:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"Доступ к audit log:
Полезные фильтры:
# Все действия с секретами
action:secret.created OR action:secret.updated OR action:secret.deleted
# Изменения workflow permissions
action:workflow_permission.changed
# Запуски workflow с elevated permissions
action:workflow_run.created
Экспорт логов:
# Через GitHub CLI
gh api /orgs/{org}/audit-log > audit-log.jsonПросмотр логов:
Download log archiveАнализ логов:
# Распаковка логов
tar -xzf run-logs.zip
# Поиск по логам
grep -r "error" *.txtИнтеграция с Security tab:
permissions:
security-events: write
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run CodeQL
uses: github/codeql-action/analyze@v3
with:
upload: trueПроблемы:
1. Изоляция через контейнеры:
jobs:
build:
runs-on: self-hosted
container:
image: node:20-alpine
steps:
- run: npm test2. Очистка после выполнения:
# Скрипт очистки runner
#!/bin/bash
rm -rf /home/runner/work/*
docker system prune -af
git clean -fdx3. Ограничение сети:
# Firewall правила для runner
iptables -A OUTPUT -d api.github.com -j ACCEPT
iptables -A OUTPUT -d registry.npmjs.org -j ACCEPT
iptables -A OUTPUT -j DROP4. Rotation runner tokens:
# Регенерация токена runner
./config.sh remove
./config.sh --url https://github.com/my-org/my-repo --token NEW_TOKENНастройка защиты:
Использование в .gitlab-ci.yml:
deploy-production:
stage: deploy
script:
- ./deploy.sh
only:
- main # Защищённая ветка
environment:
name: productionСоздание защищённой переменной:
Использование:
deploy:
script:
- ./deploy.sh
variables:
PROD_TOKEN: $PROD_TOKEN # Доступна только на protected branchesАвтоматический токен для job:
# Доступ к API GitLab из job
deploy:
script:
- curl --header "JOB-TOKEN: $CI_JOB_TOKEN" \
"https://gitlab.com/api/v4/projects/$CI_PROJECT_ID"Ограничение доступа Job Token:
| Функция | GitHub Actions | GitLab CI |
|---|---|---|
| Автоматический токен | GITHUB_TOKEN | CI_JOB_TOKEN |
| Permissions модель | Явный блок permissions | Protected branches/variables |
| OIDC | ✅ | ✅ (с 15.0) |
| Audit log | Organization level | Instance/Group level |
| Self-hosted runners | ✅ | ✅ (gitlab-runner) |
| Pin actions | SHA hash | SHA hash |
Безопасность workflow требует комплексного подхода:
permissionspull_request_target — может дать доступ к secretsВ следующей теме вы изучите supply chain security: подписывание образов, SLSA и защиту зависимостей.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.