initial commit

Signed-off-by: Max Brenner <xamrennerb@gmail.com>
This commit is contained in:
Max Brenner
2021-04-23 11:06:52 +02:00
commit 2febf65b69
12 changed files with 532 additions and 0 deletions

36
aws-cloudsdk/.gitignore vendored Normal file
View File

@@ -0,0 +1,36 @@
# Created by https://www.toptal.com/developers/gitignore/api/terraform
# Edit at https://www.toptal.com/developers/gitignore?templates=terraform
### Terraform ###
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Include override files you do wish to add to version control using negated pattern
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
# End of https://www.toptal.com/developers/gitignore/api/terraform

29
aws-cloudsdk/acm.tf Normal file
View File

@@ -0,0 +1,29 @@
resource "aws_acm_certificate" "cloudsdk" {
domain_name = local.domain
subject_alternative_names = ["*.${local.domain}"]
validation_method = "DNS"
tags = var.tags
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "cloudsdk_ssl_validation" {
for_each = {
for dvo in aws_acm_certificate.cloudsdk.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
zone_id = data.aws_route53_zone.cloudsdk.zone_id
name = each.value.name
type = each.value.type
ttl = 600
allow_overwrite = true
records = [
each.value.record
]
}

View File

@@ -0,0 +1,259 @@
module "alb_ingress_iam_role" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-assumable-role-with-oidc?ref=v3.7.0"
role_name = "${module.eks.cluster_id}-alb-ingress"
provider_url = local.oidc_provider_url
role_policy_arns = [
aws_iam_policy.alb_ingress_iam_policy.arn,
]
create_role = true
tags = var.tags
}
resource "aws_iam_policy" "alb_ingress_iam_policy" {
name_prefix = "alb-ingress-iam-policy-"
description = "ALB ingress policy for cluster ${var.name}"
policy = data.aws_iam_policy_document.alb_ingress_iam_policy.json
}
data "aws_iam_policy_document" "alb_ingress_iam_policy" {
statement {
actions = [
"iam:CreateServiceLinkedRole",
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeInternetGateways",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DescribeListenerCertificates",
"elasticloadbalancing:DescribeSSLPolicies",
"elasticloadbalancing:DescribeRules",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetGroupAttributes",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTags"
]
effect = "Allow"
resources = ["*"]
}
statement {
actions = [
"cognito-idp:DescribeUserPoolClient",
"acm:ListCertificates",
"acm:DescribeCertificate",
"iam:ListServerCertificates",
"iam:GetServerCertificate",
"waf-regional:GetWebACL",
"waf-regional:GetWebACLForResource",
"waf-regional:AssociateWebACL",
"waf-regional:DisassociateWebACL",
"wafv2:GetWebACL",
"wafv2:GetWebACLForResource",
"wafv2:AssociateWebACL",
"wafv2:DisassociateWebACL",
"shield:GetSubscriptionState",
"shield:DescribeProtection",
"shield:CreateProtection",
"shield:DeleteProtection"
]
effect = "Allow"
resources = ["*"]
}
statement {
actions = [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress"
]
effect = "Allow"
resources = ["*"]
}
statement {
actions = [
"ec2:CreateSecurityGroup"
]
effect = "Allow"
resources = ["*"]
}
statement {
actions = [
"ec2:CreateTags"
]
effect = "Allow"
resources = ["arn:aws:ec2:*:*:security-group/*"]
condition {
test = "StringEquals"
values = ["CreateSecurityGroup"]
variable = "ec2:CreateAction"
}
condition {
test = "Null"
values = ["false"]
variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
}
}
statement {
actions = [
"ec2:CreateTags",
"ec2:DeleteTags"
]
effect = "Allow"
resources = ["arn:aws:ec2:*:*:security-group/*"]
condition {
test = "Null"
values = ["true"]
variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
}
condition {
test = "Null"
values = ["false"]
variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
}
}
statement {
actions = [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:DeleteSecurityGroup"
]
effect = "Allow"
resources = ["arn:aws:ec2:*:*:security-group/*"]
condition {
test = "Null"
values = ["false"]
variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
}
}
statement {
actions = [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateTargetGroup"
]
effect = "Allow"
resources = ["*"]
condition {
test = "Null"
values = ["false"]
variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
}
}
statement {
actions = [
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:CreateRule",
"elasticloadbalancing:DeleteRule"
]
effect = "Allow"
resources = ["*"]
}
statement {
actions = [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags"
]
effect = "Allow"
resources = [
"arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"
]
condition {
test = "Null"
values = ["true"]
variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
}
condition {
test = "Null"
values = ["false"]
variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
}
}
statement {
actions = [
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:SetIpAddressType",
"elasticloadbalancing:SetSecurityGroups",
"elasticloadbalancing:SetSubnets",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:ModifyTargetGroupAttributes",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DeleteTargetGroup"
]
effect = "Allow"
resources = ["*"]
condition {
test = "Null"
values = ["false"]
variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
}
}
statement {
actions = [
"elasticloadbalancing:SetWebAcl",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:AddListenerCertificates",
"elasticloadbalancing:RemoveListenerCertificates",
"elasticloadbalancing:ModifyRule"
]
effect = "Allow"
resources = ["*"]
}
}
resource "helm_release" "aws-load-balancer-controller" {
name = "aws-load-balancer-controller"
repository = "https://aws.github.io/eks-charts"
chart = "aws-load-balancer-controller"
version = "1.1.2"
namespace = "kube-system"
set {
name = "clusterName"
value = var.name
}
set {
name = "enableShield"
value = "false"
}
set {
name = "enableWaf"
value = "false"
}
set {
name = "enableWafv2"
value = "false"
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.alb_ingress_iam_role.this_iam_role_arn
}
}

3
aws-cloudsdk/aws.tf Normal file
View File

@@ -0,0 +1,3 @@
provider "aws" {
region = "eu-central-1"
}

49
aws-cloudsdk/eks.tf Normal file
View File

@@ -0,0 +1,49 @@
data "aws_eks_cluster" "cluster" {
name = module.eks.cluster_id
}
data "aws_eks_cluster_auth" "cluster" {
name = module.eks.cluster_id
}
provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
token = data.aws_eks_cluster_auth.cluster.token
load_config_file = false
version = "~> 1.9"
}
provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
token = data.aws_eks_cluster_auth.cluster.token
}
}
module "eks" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-eks?ref=v13.2.1"
cluster_name = var.name
subnets = module.vpc.private_subnets
vpc_id = module.vpc.vpc_id
tags = var.tags
#workers_group_defaults = {
# kubelet_extra_args = "--kube-reserved cpu=500m,memory=500Mi,ephemeral-storage=1Gi --system-reserved cpu=250m,memory=500Mi,ephemeral-storage=1Gi --eviction-hard memory.available<500Mi,nodefs.available<10%"
#}
worker_groups = [
{
name = "worker-group-1"
asg_desired_capacity = 3
asg_max_size = 3
asg_min_size = 1
instance_type = "m4.large"
}
]
enable_irsa = true
cluster_version = var.eks_cluster_version
write_kubeconfig = false
}

View File

@@ -0,0 +1,83 @@
module "external_dns_cluster_role" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-iam.git//modules/iam-assumable-role-with-oidc?ref=v3.7.0"
role_name = "${module.eks.cluster_id}-external-dns"
provider_url = local.oidc_provider_url
role_policy_arns = [aws_iam_policy.external_dns.arn]
create_role = true
tags = var.tags
}
resource "aws_iam_policy" "external_dns" {
name_prefix = "external-dns"
description = "EKS external-dns policy for cluster ${var.name}"
policy = data.aws_iam_policy_document.external_dns.json
}
data "aws_iam_policy_document" "external_dns" {
statement {
sid = "GrantModifyAccessToDomains"
actions = [
"route53:ChangeResourceRecordSets",
]
effect = "Allow"
resources = [
"arn:aws:route53:::hostedzone/${data.aws_route53_zone.cloudsdk.zone_id}",
]
}
statement {
sid = "GrantListAccessToDomains"
actions = [
"route53:ListHostedZones",
"route53:ListResourceRecordSets",
]
effect = "Allow"
resources = ["*"]
}
}
data "aws_region" "current" {}
resource "helm_release" "external-dns" {
name = "external-dns"
repository = "https://charts.bitnami.com/bitnami"
chart = "external-dns"
version = "4.5.5"
namespace = "kube-system"
set {
name = "podAnnotations.iam\\.amazonaws\\.com/role"
value = module.external_dns_cluster_role.this_iam_role_arn
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.external_dns_cluster_role.this_iam_role_arn
}
set {
name = "aws.region"
value = data.aws_region.current.name
}
set {
name = "txtOwnerId"
value = "/hostedzone/${data.aws_route53_zone.cloudsdk.zone_id}"
}
set {
name = "domainFilters"
value = "{${var.route53_zone_name}}"
}
set {
name = "policy"
value = "sync"
}
}

4
aws-cloudsdk/locals.tf Normal file
View File

@@ -0,0 +1,4 @@
locals {
oidc_provider_url = split("https://", module.eks.cluster_oidc_issuer_url)[1]
domain = "${var.subdomain}.${var.route53_zone_name}"
}

3
aws-cloudsdk/outputs.tf Normal file
View File

@@ -0,0 +1,3 @@
output "acm_arn" {
value = aws_acm_certificate.cloudsdk.arn
}

3
aws-cloudsdk/route53.tf Normal file
View File

@@ -0,0 +1,3 @@
data "aws_route53_zone" "cloudsdk" {
name = "${var.route53_zone_name}."
}

View File

@@ -0,0 +1,4 @@
name = "cloudsdk"
cidr = "10.0.0.0/16"
route53_zone_name = "my.domain"
subdomain = "cloudsdk"

33
aws-cloudsdk/variables.tf Normal file
View File

@@ -0,0 +1,33 @@
variable "name" {
description = "Name to use on all resources created"
type = string
default = "cloudsdk"
}
variable "tags" {
description = "A map of tags to apply on all resources"
type = map(string)
default = {}
}
variable "cidr" {
description = "The CIDR block for the VPC which will be created"
type = string
}
variable "eks_cluster_version" {
description = "Version for EKS cluster"
type = string
default = "1.18"
}
variable "route53_zone_name" {
description = "Name of existing Route53 zone that will be used for creating DNS entries and validating certificates"
type = string
}
variable "subdomain" {
description = "Subdomain that all CloudSDK componenents will be created under"
type = string
}

26
aws-cloudsdk/vpc.tf Normal file
View File

@@ -0,0 +1,26 @@
data "aws_availability_zones" "available" {}
module "vpc" {
source = "github.com/terraform-aws-modules/terraform-aws-vpc?ref=v2.66.0"
name = var.name
cidr = var.cidr
azs = data.aws_availability_zones.available.names
private_subnets = [for az in data.aws_availability_zones.available.names : cidrsubnet(var.cidr, 8, index(data.aws_availability_zones.available.names, az))]
public_subnets = [for az in data.aws_availability_zones.available.names : cidrsubnet(var.cidr, 8, index(data.aws_availability_zones.available.names, az) + length(data.aws_availability_zones.available.names))]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
public_subnet_tags = {
"kubernetes.io/cluster/${var.name}" = "shared"
"kubernetes.io/role/elb" = "1"
}
private_subnet_tags = {
"kubernetes.io/cluster/${var.name}" = "shared"
"kubernetes.io/role/internal-elb" = "1"
}
tags = var.tags
}