tools/jenkins-slave-creation-unix/infrastructure.tf (245 lines of code) (raw):

# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. variable "key_name" { type = "string" } variable "key_path" { type = "string" } variable "instance_type" { type = "string" } variable "secret_manager_docker_hub_arn" { type = "string" } variable "s3_config_bucket" { type = "string" } variable "s3_config_filename" { type = "string" } variable "slave_install_script" { type = "string" } variable "shell_variables_file" { type = "string" } # ftp://64.50.236.216/pub/ubuntu-cloud-images/query/xenial/server/released.txt # https://cloud-images.ubuntu.com/locator/ec2/ variable "ami" { type = "string" } variable "instance_name" { type = "string" } variable "aws_region" { type = "string" } # Input variables (done by script) variable "slave_config_tar_path" { type = "string" } provider "aws" { region = "${var.aws_region}" } # Store terraform state in S3 instead of local. terraform { backend "s3" { encrypt = true key = "terraform.tfstate" # Remaining config is defined in $CONFIG_DIR/infrastructure_backend.tfvars # See https://www.terraform.io/docs/backends/config.html for more details } } data "template_cloudinit_config" "user_data" { base64_encode = true # Important: This part has to be in first place as it gets mapped to # /var/lib/cloud/instance/scripts/part-001 # This is a hack, but there's no other way to reference other scripts part { content_type = "text/x-shellscript" content = "${file("${var.shell_variables_file}")}" } part { content_type = "text/x-shellscript" content = "${file("${var.slave_install_script}")}" } } resource "aws_iam_role" "jenkins_slave_role" { name = "jenkins_slave_role" assume_role_policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "ec2.amazonaws.com" }, "Effect": "Allow", "Sid": "" } ] } POLICY } resource "aws_iam_role" "jenkins_restricted_slave_role" { name = "jenkins_restricted_slave_role" assume_role_policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "ec2.amazonaws.com" }, "Effect": "Allow", "Sid": "" } ] } POLICY } resource "aws_iam_policy" "jenkins_slave_s3_read_policy" { name = "jenkins_slave_s3_read_policy" description = "Policy to grant Jenkins Slave S3 read-access to the associated bucket" policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], "Resource": "arn:aws:s3:::*" }, { "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::${var.s3_config_bucket}" ] }, { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::${var.s3_config_bucket}/*" ] }, { "Effect": "Allow", "Action": [ "ec2:CreateTags" ], "Resource": [ "arn:aws:s3:::instance/*" ] } ] } POLICY } resource "aws_iam_policy_attachment" "jenkins_slave_s3_read_policy_attach" { name = "jenkins_slave_s3_read_policy_attach" roles = [ "${aws_iam_role.jenkins_slave_role.name}", "${aws_iam_role.jenkins_restricted_slave_role.name}" ] policy_arn = "${aws_iam_policy.jenkins_slave_s3_read_policy.arn}" } resource "aws_iam_policy" "jenkins_slave_ec2_create_tags" { name = "jenkins_slave_ec2_create_tags" description = "Policy to grant Jenkins Slave permission to create tags in order to rename an instance" policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:CreateTags" ], "Resource": [ "arn:aws:ec2:*:*:instance/*" ] } ] } POLICY } resource "aws_iam_policy_attachment" "jenkins_slave_ec2_create_tags_attach" { name = "jenkins_slave_ec2_create_tags_attach" roles = [ "${aws_iam_role.jenkins_slave_role.name}", "${aws_iam_role.jenkins_restricted_slave_role.name}" ] policy_arn = "${aws_iam_policy.jenkins_slave_ec2_create_tags.arn}" } resource "aws_iam_policy" "jenkins_restricted_slave_secrets_docker_cache" { name = "jenkins_restricted_slave_secrets_docker_cache" description = "Policy to grant restricted Jenkins Slave permission to the Secret Manager to do Docker Hub credential retrieval for distributed Docker cache" policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:DescribeSecret", "secretsmanager:List*" ], "Resource": "*" }, { "Effect": "Allow", "Action": "secretsmanager:*", "Resource": [ "${var.secret_manager_docker_hub_arn}" ] } ] } POLICY } # Only apply this permission to restricted slaves!!! resource "aws_iam_policy_attachment" "jenkins_restricted_slave_secrets_docker_cache_attach" { name = "jenkins_restricted_slave_secrets_docker_cache_attach" roles = ["${aws_iam_role.jenkins_restricted_slave_role.name}"] policy_arn = "${aws_iam_policy.jenkins_restricted_slave_secrets_docker_cache.arn}" } resource "aws_iam_instance_profile" "jenkins_slave_profile" { name = "jenkins_slave_profile" role = "${aws_iam_role.jenkins_slave_role.name}" } resource "aws_iam_instance_profile" "jenkins_restricted_slave_profile" { name = "jenkins_restricted_slave_profile" role = "${aws_iam_role.jenkins_restricted_slave_role.name}" } resource "aws_instance" "mxnet-slave" { instance_type = "${var.instance_type}" ami = "${var.ami}" iam_instance_profile = "${aws_iam_instance_profile.jenkins_slave_profile.name}" # The name of our SSH keypair you've created and downloaded # from the AWS console. # # https://console.aws.amazon.com/ec2/v2/home?region=us-west-2#KeyPairs: # key_name = "${var.key_name}" vpc_security_group_ids = [ "REDACTED", "REDACTED" ] user_data = "${data.template_cloudinit_config.user_data.rendered}" tags = { "Name" = "${var.instance_name}" } root_block_device { volume_type = "gp2" volume_size = 350 delete_on_termination = true } # Wait for S3 bucket as it's needed during startup depends_on = [ "aws_s3_bucket_object.slave_config_s3" ] } resource "aws_s3_bucket" "slave_config_bucket" { bucket = "${var.s3_config_bucket}" acl = "private" } resource "aws_s3_bucket_object" "slave_config_s3" { bucket = "${aws_s3_bucket.slave_config_bucket.id}" key = "${var.s3_config_filename}" source = "${var.slave_config_tar_path}" etag = "${filemd5(var.slave_config_tar_path)}" }