在Terraform中引用gitlab秘密

时间:2018-08-30 08:46:41

标签: amazon-web-services tensorflow amazon-s3 gitlab

我对Terraforms和gitlab CI还是很陌生,我在这里尝试做一些事情。

我想使用Terraform创建一个IAM用户和一个S3存储桶。使用策略允许该IAM用户对该S3存储桶进行某些操作。将IAM用户的凭据保存在工件中。 现在,以上内容将成为我的核心模块。

核心模块如下所示:

aws-s3-iam-combo.git

的内容

(用于运行所有Terraform的IAM用户的凭据,例如 admin-user ,将存储在gitlab机密中。)

main.tf

resource "aws_s3_bucket" "bucket" {
  bucket = "${var.name}"
  acl = "private"
  force_destroy = "true"

  tags {
    environment = "${var.tag_environment}"
    team        = "${var.tag_team}"
  }

  policy =<<EOF
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "${aws_iam_user.s3.arn}"
      },
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::${var.name}",
        "arn:aws:s3:::${var.name}/*"
      ]
    }
  ]
}
EOF
}

resource "aws_iam_user" "s3" {
  name = "${var.name}-s3"
  force_destroy = "true"
}

resource "aws_iam_access_key" "s3" {
  user = "${aws_iam_user.s3.name}"
}

resource "aws_iam_user_policy" "s3_policy" {
  name = "${var.name}-policy-s3"
  user = "${aws_iam_user.s3.name}"
  policy =<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::${var.name}",
        "arn:aws:s3:::${var.name}/*"
      ]
    }
  ]
}
EOF
}

outputs.tf

output "bucket" {
  value = "${aws_s3_bucket.bucket.bucket}"
}

output "bucket_id" {
  value = "${aws_s3_bucket.bucket.id}"
}

output "iam_access_key_id" {
  value = "${aws_iam_access_key.s3.id}"
}

output "iam_access_key_secret" {
  value = "${aws_iam_access_key.s3.secret}"
}

variables.tf

variable "name" {
  type = "string"
}

variable "tag_team" {
  type = "string"
  default = ""
}

variable "tag_environment" {
  type = "string"
  default = ""
}

variable "versioning" {
  type = "string"
  default = false
}

variable "profile" {
  type = "string"
  default = ""
}

该组织中现在需要创建S3存储桶的任何人都需要创建一个新的存储库,格式如下:

main.tf

module "aws-s3-john-doe" {
  source = "git::https://git@gitlab-address/terraform/aws-s3-iam-combo.git?ref=v0.0.1"
  name = "john-doe"
  tag_team = "my_team"
  tag_environment = "staging"
}

gitlab-ci.yml

stages:
  - plan
  - apply

plan:
  image: hashicorp/terraform
  stage: plan
  script:
    - terraform init
    - terraform plan

apply:
  image: hashicorp/terraform
  stage: apply
  script:
    - terraform init
    - terraform apply
  when: manual
  only:
    - master

然后管道将触发,并且当此存储库合并到主库时,将创建资源(S3和IAM用户),并且用户将具有该IAM用户的凭据。

现在的问题是,我们有多个AWS账户。可以这么说,如果开发人员想在某个帐户中创建S3,则上述设置将无法实现,因为 admin-user (其信誉属于gitlab机密)仅适用于一个帐户单独。

现在我不明白如何达到我的上述要求。我有以下想法:(请提出是否有更好的方法来做到这一点)

  1. 为每个有问题的AWS账户在gitlab密码中设置了多个不同的凭据
  2. 接受用户输入,将他们想要在其中创建资源的AWS账户指定为变量。所以像这样:

main.tf

module "aws-s3-john-doe" {
  source = "git::https://git@gitlab-address/terraform/aws-s3-iam-combo.git?ref=v0.0.1"
  name = "john-doe"
  tag_team = "my_team"
  tag_environment = "staging"
  aws_account = "account1"
}
  1. 然后在 aws-s3-iam-combo.git main.tf中以某种方式从gitlab机密中读取 account1 的信条。

现在我不知道如何实现上述目标,就像我如何从gitlab读取所需的秘密变量等。

有人可以在这里帮忙吗?

1 个答案:

答案 0 :(得分:1)

您之前问过这个问题,但是也许我的想法仍然可以帮助一个或另一个...

您可以使用envsubst进行此操作(要求将pkg gettext安装在运行程序或用于运行管道的Docker映像中)。

这里是一个例子:

首先,在项目设置中,将不同的用户帐户设置为环境变量(项目机密:

SECRET_1: my-secret-1
SECRET_2: my-secret-2
SECRET_3: my-secret-3

然后,创建一个包含Terraform变量的文件,我们将其命名为vars_template.tf

variable "gitlab_secrets" {
    description = "Variables from GitLab"
    type = "map"
    default = {
        secret_1 = "$SECRET_1"
        secret_2 = "$SECRET_2"
        secret_3 = "$SECRET_3"
    }
}

现在,您可以在CI管道中配置以下内容:

plan:dev:
  stage: plan dev
  script:
    - envsubst < vars_template.tf > ./vars_envsubst.tf
    - rm vars_template.tf
    - terraform init
    - terraform plan -out "planfile_dev"
  artifacts:
    paths:
      - environments/dev/planfile_dev
      - environments/dev/vars_envsubst.tf

apply:dev:
  stage: apply dev
  script:
    - cd environments/dev
    - rm vars_template.tf
    - terraform init
    - terraform apply -input=false "planfile_dev"
  dependencies:
    - plan:dev

请注意,必须删除原始的vars_template.tf,否则Terraform将抛出错误,该变量被多次定义。您可以通过将模板文件存储在Terraform工作目录之外的目录中来规避此问题。 但是从Terraform状态中,您可以看到正确替换了变量值:

"outputs": {
    "gitlab_secrets": {
        "sensitive": false,
        "type": "map",
        "value": {
            "secret_1": "my-secret-1",
            "secret_2": "my-secret-2",
            "secret_3": "my-secret-3"
        }
    }
}

然后您可以在Terraform资源等中使用"${vars.gitlab_secrets["secret_1"]}"访问值。

更新:请注意,此方法会将机密信息存储在Terraform状态文件中,如果该文件存储在S3存储桶中以与Terraform协同工作,则可能是安全隐患。存储桶至少应加密。另外,建议使用ACL限制对文件的访问,例如,只有用户 terraform 可以访问它。而且,当然,用户可以通过Terraoform outputs ...

揭露秘密。