Использование AWS через GitHub Actions без секретных ключей

Фотография на обложке от Криса Барбалиса на Unsplash.

Все началось со следующего вопроса: Как безопасно хранить ключи пользователей AWS IAM (Access и Secret), созданные IaC?

Представьте себе следующий сценарий: у вас есть Bucket, в котором будут храниться активы вашего Frontend. Ваш Frontend живет в другом хранилище, и вы используете, в моем примере, GitHub Actions для развертывания (перемещения) этих файлов в Bucket. Вы хотите дать разрешение своим GitHub Actions на выполнение этого и только этого.

Конечно, вы можете добавить свои учетные данные в репозиторий, но вы дадите ему слишком много разрешений.

Вы можете создать пользователя в вашей инфраструктуре, который будет иметь только те разрешения, которые нужны GitHub Actions. Это уже звучит гораздо лучше. Вопрос в том, где хранить ключи этого пользователя?

  1. Мы можем иметь ключи в качестве выходных данных нашего стека. Это небезопасно, каждый, кто имеет доступ к логам вашего GitHub Action, может их увидеть (представьте себе репозиторий с открытым исходным кодом).
  2. Мы можем хранить эти ключи в SSM. Это работает, но каждый, кто имеет доступ к SSM, имеет к нему доступ (в моем случае это не очень важно).
  3. Мы можем хранить эти ключи в Secrets Manager. Это работает, но каждый, кто имеет доступ к Secrets Manager, имеет к нему доступ (в моем случае это не очень важно).
  4. Мы можем генерировать ключи вручную. Это работает, но об этом будет знать только тот, кто сгенерировал ключи (надеюсь, он сохранит их в GitHub Secrets и забудет об этом).

Все описанные выше шаги в той или иной степени работают. Единственный вариант, который не требует никаких ручных усилий, — это вариант 1, который является наименее безопасным.

Лучшим, насколько я понимаю, является другой подход. Я хотел бы рассмотреть его шаг за шагом и как настроить его с помощью AWS CDK.

OpenID Connect (OIDC)

С октября 2021 года GitHub Actions разрешает его: https://github.blog/changelog/2021-10-27-github-actions-secure-cloud-deployments-with-openid-connect/.

OpenID Connect позволяет подключить внешнего провайдера (GitHub Actions) к вашей учетной записи AWS. Подробнее об этом можно прочитать здесь: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html.

Внешний провайдер возьмет на себя определенную роль, которая будет иметь необходимые нам разрешения (политики). Подробнее о ролях IAM можно прочитать здесь: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html.

Разбиваем на шаги:

  1. Нам нужна политика, которая позволит нам перемещать файлы в Bucket (не более того);
  2. Нам нужна роль, которая будет приниматься GitHub Actions, и эта роль должна использовать политику из шага 1.
  3. Нам нужен провайдер идентификации OIDC для подключения наших GitHub Actions.

GitHub и AWS имеют обширную документацию по этому вопросу:

  • Configuring OpenID Connect in Amazon Web Services
  • Создание провайдеров идентификации OpenID Connect (OIDC)
  • aws-actions/configure-aws-credentials предполагаемая роль
  • Модуль AWS CDK IAM — Провайдеры OpenID Connect

Как это выглядит в коде?

  1. Представим, что у нас есть ведро Bucket
const bucket = new Bucket(this, "Bucket");
Вход в полноэкранный режим Выход из полноэкранного режима
  1. Давайте создадим OIDC, следуя документации
const provider = new OpenIdConnectProvider(this, "GitHubProvider", {
  url: "https://token.actions.githubusercontent.com",
  clientIds: ["sts.amazonaws.com"], // Referred as "Audience" in the documentation
});
Войдите в полноэкранный режим Выход из полноэкранного режима
  1. Создадим нашу роль (AWS CDK позволяет легко связать роль с поставщиком идентификационных данных)
const role = new Role(this, "Role", {
  assumedBy: new OpenIdConnectPrincipal(provider, {
    StringEquals: {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", // "Audience" from above
    },
    StringLike: {
      "token.actions.githubusercontent.com:sub":
        "repo:<ORGANIZATION>/<REPOSITORY>:*", // Organization and repository that are allowed to assume this role
    },
  }),
});
Войти в полноэкранный режим Выход из полноэкранного режима

Приведенный выше пример немного отличается от того, который задокументирован на GitHub. Здесь я делаю его более гибким (например, его могут использовать все филиалы).

Свойство assumedBy может быть настроено:

  • Вы можете играть с условиями: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html
  • Вы можете использовать другие свойства из полезной нагрузки: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token.
  1. Давайте предоставим необходимые разрешения нашей роли
bucket.grantPut(role);
Войти в полноэкранный режим Выйти из полноэкранного режима

После развертывания все готово на стороне AWS, теперь перейдем на сторону GitHub.

  1. Давайте обновим наше действие на GitHub, чтобы принять роль
# Before
...
- name: Configure AWS Credentials 🔧
  uses: aws-actions/configure-aws-credentials@v1.6.1 # Version at the time of this writing
  with: # We are loading keys stored in secrets
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: eu-central-1
- run: npm run deploy # Just an example

# After
...
permissions:
  id-token: write
  contents: read # This is required for actions/checkout (GitHub documentation mentions that)
...
- name: Configure AWS Credentials 🔧
  uses: aws-actions/configure-aws-credentials@v1.6.1 # Version at the time of this writing
  with: # We are loading keys stored in secrets
    role-to-assume: arn:aws:iam::<ACCOUNT>:role/<ROLE-NAME> # You can specify the role name when creating it or AWS will automatically generate one for you
    aws-region: eu-central-1
- run: npm run deploy # Just an example
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь мы можем безопасно снять секреты с GitHub, а также нам не нужен никакой «специальный» пользователь для развертывания через GitHub Actions.


Это очень помогло мне «обернуть» знания, и я верю, что это может помочь и другим людям.

Ссылки:

  • https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
  • https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html
  • https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam-readme.html
  • https://github.com/aws-actions/configure-aws-credentials
  • https://aws.plainenglish.io/no-more-aws-access-keys-in-github-secrets-6fea25c9e1a4
  • https://awsteele.com/blog/2021/09/15/aws-federation-comes-to-github-actions.html
  • https://dev.to/mmiranda/github-actions-autenticando-na-aws-via-oidc-2cf

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *