我们在部署配置期间做的第一件事就是为 CI/CD 工具创建凭据。

对于 AWS,最简单的方法是使用编程密钥创建 IAM 用户。它们被放入 CI/CD 工具内部的机密或环境变量中,分别为:AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY。它被称为长期凭证,因为默认情况下没有过期时间。我们必须自己轮换它们。

另一种更安全的方法是使用短期凭证,它会在特定时间后自动失效。

在本文中,我将介绍使用 *OpenID Connect 协议、CircleCI 作为部署平台和 AWS 作为目标的示例解决方案。我不会深入研究协议细节。

主要思想概述

这是一个简化的图表,显示了整个过程的样子。

[图像描述](https://res.cloudinary.com/practicaldev/image/fetch/s---XwA06Ts--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to -uploads.s3.amazonaws.com/uploads/articles/0plb3x33m7zenn320rhv.png)

我们需要在 AWS 中授权两件事:

  • OIDC 令牌

  • AWS IAM 角色

OIDC Token 将由 CircleCI 生成,但 IAM Role 需要由我们创建。

Terraform - 创建 IAM 角色和 OIDC 提供程序

main.tf - 很常见。无需说明

terraform {
  required_version = "1.1.4"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.8.0"
    }
  }
}

provider "aws" {
  region = "eu-central-1"
}

进入全屏模式 退出全屏模式

变量.tf

我们需要 3 个值来在 AWS 中配置我们的 IAM 角色和 OIDC 提供者资源。circleci_org_idcircleci_thumbprint用于创建 OIDC Provider,它们对于我们的目的来说是相当静态的(我们在同一个 CircleCI 组织中有多个存储库/CircleCI 项目)。

circleci_project_id允许我们将 IAM 角色限制为特定项目。我们希望从特定(一个或多个)项目而不是整个组织向 AWS 授权。

variable "circleci_org_id" {
  default = "CHANGE_ME"
  description = "CircleCI Organization ID"
}

variable "circleci_thumbprint" {
  # https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
  default = "CHANGE_ME"
  description = "Fingerprint of CircleCI servers"
}

variable "circleci_project_id" {
  default = "CHANGE_ME"
  description = "CircleCI Project ID"
}

进入全屏模式 退出全屏模式

oidc.tf

最重要的部分。我们有 OIDC 提供者和 IAM 角色以及联合主体和 2 个条件。它们与来自 OIDC 令牌的值进行比较。第二个条件包含架构:

"org/${var.circleci_org_id}/project/${var.circleci_project_id}/user/*"

进入全屏模式 退出全屏模式

这意味着,对特定 CircleCI 组织中的特定 CircleCI 项目具有权限的所有用户都能够成功运行此管道。整个配置与连接到 CircleCI 的 Github 平台一起使用,因此 Github 管理权限。

最后,我们将其他权限附加到角色。

resource "aws_iam_openid_connect_provider" "default" {
  url             = "https://oidc.circleci.com/org/${var.circleci_org_id}"
  client_id_list  = [var.circleci_org_id]
  thumbprint_list = [var.circleci_thumbprint]
}

###########################################################


data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "circleci" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"]

    principals {
      type = "Federated"
      identifiers = [
        "${aws_iam_openid_connect_provider.default.arn}"
      ]
    }

    condition {
      test     = "StringEquals"
      variable = "oidc.circleci.com/org/${var.circleci_org_id}:aud"
      values   = [var.circleci_org_id]
    }

    condition {
      test     = "ForAnyValue:StringLike"
      variable = "oidc.circleci.com/org/${var.circleci_org_id}:sub"
      values   = ["org/${var.circleci_org_id}/project/${var.circleci_project_id}/user/*"]
    }
  }
}

resource "aws_iam_role" "circleci" {
  name                 = "circleci"
  path                 = "/"
  assume_role_policy   = data.aws_iam_policy_document.circleci.json
}

resource "aws_iam_role_policy_attachment" "attach_1" {
  role       = aws_iam_role.circleci.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}

进入全屏模式 退出全屏模式

CircleCI配置

.circleci/config.yml

version: 2.1

orbs:
  aws-cli: circleci/aws-cli@3.0.0


commands:
  aws-oidc-setup:
    description: Setup AWS auth using OIDC token
    parameters:
      aws-role-arn:
        type: string
    steps:
      - run:
          name: Get short-term credentials
          command: |
            STS=($(aws sts assume-role-with-web-identity --role-arn << parameters.aws-role-arn >> --role-session-name "${CIRCLE_BRANCH}-${CIRCLE_BUILD_NUM}" --web-identity-token "${CIRCLE_OIDC_TOKEN}" --duration-seconds 900 --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text))
            echo "export AWS_ACCESS_KEY_ID=${STS[0]}" >> $BASH_ENV
            echo "export AWS_SECRET_ACCESS_KEY=${STS[1]}" >> $BASH_ENV
            echo "export AWS_SESSION_TOKEN=${STS[2]}" >> $BASH_ENV
      - run:
          name: Verify AWS credentials
          command: aws sts get-caller-identity

jobs:

  test:
    executor: aws-cli/default
    steps:
      - checkout
      - aws-cli/install
      - aws-oidc-setup:
          aws-role-arn: "arn:aws:iam::XXXXXXXXXXXX:role/circleci"
      - run:
          name: Test AWS connection
          command: aws s3 ls


workflows:
  build_and_deploy:
    jobs:
      - test:
          context:
            - example-context

进入全屏模式 退出全屏模式

在这里,我们使用用于在 AWS 中授权的自定义命令进行配置。有几件重要的事情:

  • parameters.aws-role-arn-> 之前创建的 IAM 角色

  • role-session-name-> 可以是任何东西。它将在 AWS CloudTrail 中显示为user字段

  • CIRCLE_OIDC_TOKEN-> 它是 OIDC 令牌。如果作业使用任何上下文,它由 CircleCI 添加。这就是我在工作流程中添加example-context的原因。此上下文也可以为空。

  • duration-seconds- 令牌有效时间

您可以在作业中使用 SSH 检查CIRCLE_OIDC_TOKEN内部的内容,并在此处对其进行解码:jwt.io

circleci@a094c7852509:~$ echo $CIRCLE_OIDC_TOKEN

eyJraWQiOiJhSzlqNmRZQm8zS0R3NGdmV3k4eGRNTFU1UThPeWNzcW44S.......

进入全屏模式 退出全屏模式

文档

  • https://circleci.com/docs/2.0/openid-connect-tokens/

  • https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html

这是我的第一篇文章,所以欢迎反馈:)

Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐