Фотография на обложке от Криса Барбалиса на Unsplash.
Все началось со следующего вопроса: Как безопасно хранить ключи пользователей AWS IAM (Access и Secret), созданные IaC?
Представьте себе следующий сценарий: у вас есть Bucket, в котором будут храниться активы вашего Frontend. Ваш Frontend живет в другом хранилище, и вы используете, в моем примере, GitHub Actions для развертывания (перемещения) этих файлов в Bucket. Вы хотите дать разрешение своим GitHub Actions на выполнение этого и только этого.
Конечно, вы можете добавить свои учетные данные в репозиторий, но вы дадите ему слишком много разрешений.
Вы можете создать пользователя в вашей инфраструктуре, который будет иметь только те разрешения, которые нужны GitHub Actions. Это уже звучит гораздо лучше. Вопрос в том, где хранить ключи этого пользователя?
- Мы можем иметь ключи в качестве выходных данных нашего стека. Это небезопасно, каждый, кто имеет доступ к логам вашего GitHub Action, может их увидеть (представьте себе репозиторий с открытым исходным кодом).
- Мы можем хранить эти ключи в SSM. Это работает, но каждый, кто имеет доступ к SSM, имеет к нему доступ (в моем случае это не очень важно).
- Мы можем хранить эти ключи в Secrets Manager. Это работает, но каждый, кто имеет доступ к Secrets Manager, имеет к нему доступ (в моем случае это не очень важно).
- Мы можем генерировать ключи вручную. Это работает, но об этом будет знать только тот, кто сгенерировал ключи (надеюсь, он сохранит их в 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.
Разбиваем на шаги:
- Нам нужна политика, которая позволит нам перемещать файлы в Bucket (не более того);
- Нам нужна роль, которая будет приниматься GitHub Actions, и эта роль должна использовать политику из шага 1.
- Нам нужен провайдер идентификации 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
Как это выглядит в коде?
- Представим, что у нас есть ведро Bucket
const bucket = new Bucket(this, "Bucket");
- Давайте создадим OIDC, следуя документации
const provider = new OpenIdConnectProvider(this, "GitHubProvider", {
url: "https://token.actions.githubusercontent.com",
clientIds: ["sts.amazonaws.com"], // Referred as "Audience" in the documentation
});
- Создадим нашу роль (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.
- Давайте предоставим необходимые разрешения нашей роли
bucket.grantPut(role);
После развертывания все готово на стороне AWS, теперь перейдем на сторону GitHub.
- Давайте обновим наше действие на 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