Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Управление секретами
secrets_management

Управление секретами

Хранение и использование secrets, encryption, ротация ключей.

Управление секретами в CI/CD

Секреты — критический компонент безопасности пайплайнов. Неправильное управление секретами приводит к утечкам данных и компрометации инфраструктуры.

#Что такое секреты в CI/CD?

Секреты (Secrets) — конфиденциальные данные, которые используются в пайплайнах, но не должны храниться в открытом виде в репозитории.

Типы секретов:

  • API-ключи и токены доступа (GitHub, GitLab, AWS, GCP, Azure)
  • Пароли от баз данных и внешних сервисов
  • SSH-ключи для деплоя
  • TLS-сертификаты и приватные ключи
  • Токены OAuth и service accounts

Почему нельзя хранить секреты в коде:

# ❌ НИКОГДА НЕ ДЕЛАЙТЕ ТАК jobs: deploy: steps: - run: | export AWS_SECRET_KEY="AKIAIOSFODNN7EXAMPLE" aws s3 cp dist/ s3://my-bucket/

Последствия утечки:

  • Компрометация облачной инфраструктуры
  • Доступ к базам данных с пользовательской информацией
  • Финансовые потери и репутационный ущерб
  • Необходимость экстренной ротации всех ключей

#GitHub Secrets

#Типы секретов в GitHub

GitHub поддерживает три уровня секретов:

УровеньОбласть действияГде настраивать
RepositoryОдин репозиторийSettings → Secrets and variables → Actions
EnvironmentКонкретное окружение (staging, production)Settings → Environments
OrganizationВсе репозитории организацииOrganization Settings → Secrets and variables → Actions

#Создание секретов

Через веб-интерфейс:

  1. Перейдите в репозиторий на GitHub
  2. Settings → Secrets and variables → Actions
  3. New repository secret
  4. Укажите имя (например, DATABASE_URL) и значение
  5. Save secret

Через GitHub CLI:

# Установка секрета для репозитория gh secret set DATABASE_URL --body "postgresql://user:pass@host:5432/db" # Установка секрета для организации gh secret set DATABASE_URL --body "postgresql://user:pass@host:5432/db" --org my-org # Просмотр списка секретов gh secret list

#Использование секретов в workflow

Базовое использование:

jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy to production run: ./deploy.sh env: DATABASE_URL: ${{ secrets.DATABASE_URL }} API_KEY: ${{ secrets.API_KEY }}

Важно: Секреты недоступны в логах. GitHub автоматически маскирует их значения.

#Ограничения на секреты

ПараметрОграничение
Максимальный размер64 KB на секрет
Имя секретаТолько латиница, цифры, подчёркивание
Количество секретов100 на репозиторий (бесплатный тариф)

#Environment Secrets

Секреты окружений обеспечивают дополнительную защиту для production:

jobs: deploy-staging: runs-on: ubuntu-latest environment: staging # Использует секреты staging steps: - run: ./deploy.sh env: DATABASE_URL: ${{ secrets.DATABASE_URL }} deploy-production: runs-on: ubuntu-latest environment: production # Использует секреты production needs: deploy-staging steps: - run: ./deploy.sh env: DATABASE_URL: ${{ secrets.DATABASE_URL }}

Защита окружений:

  1. Settings → Environments → New environment
  2. Включите Required reviewers — требуется аппрув перед деплоем
  3. Включите Wait timer — задержка перед выполнением
  4. Настройте Deployment branches — ограничение на ветки

#Secrets для pull request от fork

Важное ограничение: Секреты репозитория недоступны в workflow, запущенных из fork.

# Workflow из fork НЕ получит доступ к secrets on: pull_request: # Запуск из fork — secrets недоступны

Решение — workflow_run:

# Шаг 1: Workflow для PR (без секретов) name: PR Tests on: pull_request: jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm test # Шаг 2: Workflow с секретами (запускается после мержа) name: Deploy on: workflow_run: workflows: ["PR Tests"] types: - completed branches: - main jobs: deploy: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - run: ./deploy.sh env: DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

#GitLab CI Variables

#Типы переменных в GitLab

GitLab поддерживает несколько уровней переменных:

УровеньОбласть действияПриоритет
ProjectОдин проектНизкий
GroupВсе проекты группыСредний
InstanceВесь GitLab instanceВысокий
EnvironmentКонкретное окружениеНаивысший

#Создание переменных

Через веб-интерфейс:

  1. Settings → CI/CD → Variables
  2. Add variable
  3. Укажите ключ (например, DATABASE_URL) и значение
  4. Настройте опции:
    • Type — Variable или File
    • Environment scope — Ограничение по окружению
    • Protect variable — Только для защищённых веток
    • Mask variable — Маскировка в логах

Через API:

curl --request POST \ --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ --data "key=DATABASE_URL&value=postgresql://user:pass@host:5432/db" \ "https://gitlab.com/api/v4/projects/$PROJECT_ID/variables"

Через GitLab CLI (glab):

glab variable create DATABASE_URL "postgresql://user:pass@host:5432/db"

#Использование в .gitlab-ci.yml

Базовое использование:

deploy: stage: deploy script: - ./deploy.sh variables: # Переопределение или добавление переменных DEPLOY_ENV: production

Доступ к переменным:

test: script: # Прямое использование - echo "Deploying to $DEPLOY_ENV" # Через export - export API_KEY=$API_KEY - ./run-tests.sh # В команде - DATABASE_URL=$DATABASE_URL npm run migrate

#Protected Variables

Защищённые переменные доступны только на защищённых ветках и тегах:

# .gitlab-ci.yml deploy-production: stage: deploy variables: # Эта переменная должна быть защищена в настройках PROD_SECRET: $PROD_SECRET script: - ./deploy-prod.sh only: - main # Защищённая ветка

Настройка защиты:

  1. Settings → Repository → Protected branches
  2. Выберите ветку (например, main)
  3. Allowed to merge: Maintainers
  4. Allowed to push: No one

#Masked Variables

Маскированные переменные скрываются в логах:

Требования для маскировки:

  • Минимум 8 символов
  • Не начинается с CI_ или GITLAB_
  • Содержит только буквы, цифры, _, -, /, =, +, %

Проверка маскировки:

test: script: - echo "Secret: $SECRET_VAR" # В логе будет: Secret: [MASKED]

#OIDC: Аутентификация без секретов

#Проблема долгосрочных секретов

Традиционный подход (небезопасный):

# ❌ Хранение долгосрочных секретов jobs: deploy: steps: - run: aws s3 cp dist/ s3://bucket/ env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Проблемы:

  • Секреты нужно ротировать вручную
  • При утечке — компрометация до ротации
  • Сложно отозвать доступ для конкретного workflow

#OIDC: Как это работает

OpenID Connect (OIDC) позволяет получать временные токены доступа:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  GitHub Actions │────▶│  OIDC Provider  │────▶│  Cloud Provider │
│                 │     │   (GitHub)      │     │  (AWS/GCP/Azure)│
│  1. Запрос токена│     │  2. Выдача JWT  │     │  3. Обмен на    │
│                 │     │                 │     │  временные creds│
└─────────────────┘     └─────────────────┘     └─────────────────┘

#Настройка OIDC для AWS

Шаг 1: Создание OIDC провайдера в AWS

# Создание Identity Provider aws iam create-open-id-connect-provider \ --url https://token.actions.githubusercontent.com \ --client-id-list sts.amazonaws.com \ --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1

Шаг 2: Создание IAM Role с доверием

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" }, "StringLike": { "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*" } } } ] }

Шаг 3: Workflow с OIDC

jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write # Обязательно для OIDC contents: read 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-role aws-region: us-east-1 - name: Deploy to S3 run: aws s3 cp dist/ s3://my-bucket/

#Настройка OIDC для GCP

Шаг 1: Создание Workload Identity Pool

gcloud iam workload-identity-pools create "github-pool" \ --project="my-project" \ --location="global" \ --display-name="GitHub Actions Pool"

Шаг 2: Создание провайдера

gcloud iam workload-identity-pools providers create-oidc "github-provider" \ --project="my-project" \ --location="global" \ --workload-identity-pool="github-pool" \ --display-name="GitHub Provider" \ --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \ --issuer-uri="https://token.actions.githubusercontent.com"

Шаг 3: Workflow для GCP

jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - name: Authenticate to Google Cloud uses: google-github-actions/auth@v2 with: workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/github-pool/providers/github-provider' service_account: 'deploy@my-project.iam.gserviceaccount.com' - name: Deploy to GKE run: gcloud container clusters get-credentials my-cluster

#Настройка OIDC для Azure

Шаг 1: Создание Federated Identity Credential

az identity federated-credential create \ --name "github-credential" \ --identity-name "github-identity" \ --resource-group "my-rg" \ --issuer "https://token.actions.githubusercontent.com" \ --subject "repo:my-org/my-repo:ref:refs/heads/main"

Шаг 2: Workflow для Azure

jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - name: Azure Login uses: azure/login@v1 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Deploy to Azure run: az webapp deploy --name my-app --src-path dist/

#Best Practices

#1. Principle of Least Privilege

Плохо:

# Слишком широкие права permissions: contents: write packages: write actions: write

Хорошо:

# Только необходимые права permissions: contents: read # Только чтение кода id-token: write # Для OIDC

#2. Ротация секретов

Автоматическая ротация через GitHub Actions:

name: Rotate Secrets on: schedule: - cron: '0 0 1 * *' # 1-го числа каждого месяца jobs: rotate: runs-on: ubuntu-latest steps: - name: Generate new API key run: | NEW_KEY=$(curl -X POST https://api.service.com/keys | jq .key) gh secret set API_KEY --body "$NEW_KEY"

#3. Аудит использования секретов

Включение аудита в GitHub:

  1. Organization Settings → Settings → Audit log
  2. Экспорт логов для анализа

Пример запроса в audit log:

action:secret.created OR action:secret.updated

#4. Шифрование секретов

Использование age для шифрования:

# Генерация ключа age-keygen -o key.txt # Шифрование секрета age -R key.txt secret.env > secret.env.age # Дешифрование в пайплайне age -d -i key.txt secret.env.age > secret.env
jobs: deploy: steps: - name: Decrypt secrets run: | echo "${{ secrets.AGE_KEY }}" > key.txt age -d -i key.txt secret.env.age > secret.env

#5. Валидация секретов

Проверка наличия обязательных секретов:

jobs: validate: runs-on: ubuntu-latest steps: - name: Check required secrets run: | required_secrets=("DATABASE_URL" "API_KEY" "DEPLOY_TOKEN") for secret in "${required_secrets[@]}"; do if [ -z "${!secret}" ]; then echo "Missing required secret: $secret" exit 1 fi done env: DATABASE_URL: ${{ secrets.DATABASE_URL }} API_KEY: ${{ secrets.API_KEY }} DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

#Сравнение GitHub и GitLab

ФункцияGitHub ActionsGitLab CI
Repository secrets✅✅
Environment secrets✅✅ (через Environment scope)
Organization/Group secrets✅✅
Masked variables✅ (автоматически)✅ (требует настройки)
Protected variables❌✅
OIDC✅✅ (с GitLab 15.0)
File variables❌✅
Максимальный размер64 KB36 KB

Далее: Permissions и безопасность workflow