Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provision aws tokens for rust-lang/rust #666

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
48 changes: 48 additions & 0 deletions terragrunt/accounts/ci-staging/rustc-ci/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions terragrunt/accounts/ci-staging/rustc-ci/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
source = "../../../modules//rustc-ci"
}

include {
path = find_in_parent_folders()
merge_strategy = "deep"
}

inputs = {
repo = "bors-kindergarten"
}
48 changes: 48 additions & 0 deletions terragrunt/accounts/legacy/rustc-ci-prod/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions terragrunt/accounts/legacy/rustc-ci-prod/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
terraform {
source = "../../../modules//rustc-ci"
}

include {
path = find_in_parent_folders()
merge_strategy = "deep"
}

inputs = {
repo = "rust"
caches_bucket = "rust-lang-ci-sccache2"
artifacts_bucket = "rust-lang-ci2"
artifacts_domain = "ci-artifacts.rust-lang.org"
caches_domain = "ci-caches.rust-lang.org"
}
2 changes: 1 addition & 1 deletion terragrunt/modules/gha-iam-user/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
github = {
source = "integrations/github"
version = "~> 6.2.3"
version = "~> 6.2"
}
}
}
Expand Down
63 changes: 63 additions & 0 deletions terragrunt/modules/rustc-ci/_terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
terraform {
required_version = "~> 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.86"
}
}
}

variable "repo" {
description = "GitHub repository to authorize. E.g. `rust`. GitHub org is hardcoded to `rust-lang`."
type = string
validation {
condition = !can(regex("/", var.repo))
error_message = "The repo variable must not contain `/`. Only provide the repository name."
}
validation {
condition = length(var.repo) > 0
error_message = "The repo variable must not be empty."
}
}

variable "artifacts_bucket" {
description = "ID of the existing S3 bucket to store build artifacts. If unspecified, a new bucket is created."
type = string
default = null
validation {
condition = var.artifacts_bucket == null || length(var.artifacts_bucket) > 0
error_message = "The artifacts_bucket variable must not be empty when specified."
}
}

variable "caches_bucket" {
description = "ID of the existing S3 bucket to store caches. If unspecified, a new bucket is created."
type = string
default = null
validation {
condition = var.caches_bucket == null || length(var.caches_bucket) > 0
error_message = "The caches_bucket variable must not be empty when specified."
}
}

variable "artifacts_domain" {
description = "Domain name for the CloudFront distribution in front of the artifacts bucket."
type = string
default = null
validation {
condition = var.artifacts_domain == null || length(var.artifacts_domain) > 0
error_message = "The artifacts_domain variable must not be empty when specified."
}
}

variable "caches_domain" {
description = "Domain name for the CloudFront distribution in front of the caches bucket."
type = string
default = null
validation {
condition = var.caches_domain == null || length(var.caches_domain) > 0
error_message = "The caches_domain variable must not be empty when specified."
}
}
180 changes: 180 additions & 0 deletions terragrunt/modules/rustc-ci/artifacts.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
locals {
rustc_builds = "rustc-builds"
rustc_builds_alt = "rustc-builds-alt"
iam_prefix = "rustc-ci--rust-lang--${var.repo}"

s3_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "ArtifactsBucketWrite"
Effect = "Allow"
Resource = [
"${aws_s3_bucket.artifacts.arn}/${local.rustc_builds}",
"${aws_s3_bucket.artifacts.arn}/${local.rustc_builds}/*",
"${aws_s3_bucket.artifacts.arn}/${local.rustc_builds_alt}",
"${aws_s3_bucket.artifacts.arn}/${local.rustc_builds_alt}/*",
]
Action = [
"s3:GetObject",
"s3:DeleteObject",
"s3:PutObject",
"s3:PutObjectAcl",
]
},
{
Sid = "ArtifactsBucketList"
Effect = "Allow"
Resource = "${aws_s3_bucket.artifacts.arn}"
Action = [
"s3:ListBucket",
],
},
{
Sid = "HeadBuckets",
Effect = "Allow",
Resource = "*"
Action = [
"s3:HeadBucket",
"s3:GetBucketLocation",
],
},
]
})
}

# For rust-lang this was imported.
resource "aws_s3_bucket" "artifacts" {
bucket = var.artifacts_bucket != null ? var.artifacts_bucket : "rust-lang-ci2"
}

resource "aws_s3_bucket_lifecycle_configuration" "artifacts_lifecycle" {
bucket = aws_s3_bucket.artifacts.id

rule {
status = "Enabled"
id = "cleanup-${local.rustc_builds}"

// Note that this applies equally to rustc-builds and rustc-builds-alt, as
// it is a prefix.
filter {
prefix = local.rustc_builds
}

expiration {
days = 168
}

noncurrent_version_expiration {
// This is *in addition* to the delete_artifacts_after_days above; we
// don't really need to keep CI artifacts around in an inaccessible state.
noncurrent_days = 1
}

abort_incomplete_multipart_upload {
days_after_initiation = 1
}
}
}

resource "aws_s3_bucket_policy" "artifacts" {
bucket = aws_s3_bucket.artifacts.id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Principal = {
AWS = "*"
}
Sid = "PublicReadGetObject"
Effect = "Allow"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.artifacts.arn}/*"
},
]
})
}

module "artifacts_user" {
source = "../gha-iam-user"

org = "rust-lang"
repo = var.repo

user_name = "${local.iam_prefix}--artifacts"
env_prefix = "ARTIFACTS"
}

resource "aws_iam_user_policy" "artifacts_write" {
name = "artifacts-write"
user = module.artifacts_user.user_name

policy = local.s3_policy
}

resource "aws_s3_bucket_acl" "artifacts" {
bucket = aws_s3_bucket.artifacts.id
acl = "public-read"
}

# TODO: probably this should be imported
module "artifacts_cdn" {
source = "../static-website"

domain_name = var.artifacts_domain != null ? var.artifacts_domain : "${var.repo}-ci-artifacts.rust-lang.org"
origin_domain_name = aws_s3_bucket.artifacts.bucket_regional_domain_name
response_policy_id = aws_cloudfront_response_headers_policy.s3.id
}

data "aws_s3_bucket" "inventories" {
bucket = "rust-inventories"
}

resource "aws_s3_bucket_inventory" "artifacts" {
name = "all-objects-csv"
bucket = aws_s3_bucket.artifacts.id
enabled = true

included_object_versions = "Current"
optional_fields = ["ETag", "Size", "StorageClass", "IntelligentTieringAccessTier"]

schedule {
frequency = "Weekly"
}
destination {
bucket {
bucket_arn = data.aws_s3_bucket.inventories.arn
prefix = aws_s3_bucket.artifacts.id
format = "CSV"
}
}
}

resource "aws_iam_role" "try_builds" {
name = "${local.iam_prefix}--try-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "sts:AssumeRoleWithWebIdentity"
Principal = {
Federated = "arn:aws:iam::890664054962:oidc-provider/token.actions.githubusercontent.com"
}
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:sub" = "repo:rust-lang/${var.repo}:ref:refs/heads/automation/bors/try"
}
}
}
]
})
}

resource "aws_iam_role_policy" "try_builds" {
name = "put-objects"
role = aws_iam_role.try_builds.id
policy = local.s3_policy
}
Loading