diff --git a/.gitignore b/.gitignore index 900dcf70..1e5ff8f5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ .terratest/ vendor/ .test-data +.secret +kubeconfig/ +deploy/ .DS_Store .vscode examples/aws-iam/iam-provision/deploy diff --git a/examples/aws-iam/README.md b/examples/aws-iam/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/aws-iam/iam-provision/Makefile b/examples/aws-iam/iam-provision/Makefile deleted file mode 100644 index 73c08eb1..00000000 --- a/examples/aws-iam/iam-provision/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -SHELL += -eu - -export PKCS_KEY := "deploy/secrets/oidc-issuer.pub" -export POD_IDENTITY_SECRET_NAME := pod-identity-webhook -export POD_IDENTITY_SERVICE_NAMESPACE := kube-system - -default: init - -.PHONY: init -init: - @rm -rf deploy - @mkdir -p deploy/kubernetes - @mkdir -p deploy/secrets - @touch deploy/secrets/keys.json - @terraform init - @terraform apply -auto-approve - @rm deploy/secrets/keys.json - @go run ./main.go -key ${PKCS_KEY} | jq '.keys += [.keys[0]] | .keys[1].kid = ""' > ./deploy/secrets/keys.json - @terraform apply -auto-approve - -.PHONY: deploy -deploy: - @kubectl apply -f deploy/kubernetes/iam-auth.yaml - @sleep 5 - @kubectl apply -f deploy/kubernetes/iam-admin.yaml - @kubectl create secret generic ${POD_IDENTITY_SECRET_NAME} \ - --from-file=./deploy/secrets/tls.crt --from-file=./deploy/secrets/tls.key \ - --dry-run=client -o yaml | kubectl apply -f - - @kubectl apply -f deploy/kubernetes/irsa.yaml - @until kubectl get csr -o \ - jsonpath='{.items[?(@.spec.username=="system:serviceaccount:kube-system:pod-identity-webhook")].metadata.name}' | \ - grep -m 1 "csr-"; \ - do echo "Waiting for CSR to be created" && sleep 1 ; \ - done; - @kubectl certificate approve $$(kubectl get csr -o jsonpath='{.items[?(@.spec.username=="system:serviceaccount:kube-system:pod-identity-webhook")].metadata.name}') - -.PHONY: clean-k8s -clean-k8s: - @kubectl get csr -o jsonpath='{.items[?(@.spec.username=="system:serviceaccount:kube-system:pod-identity-webhook")].metadata.name}' | xargs kubectl delete csr - @kubectl delete -f deploy/kubernetes/irsa.yaml - @kubectl delete secrets ${POD_IDENTITY_SECRET_NAME} --namespace ${POD_IDENTITY_SERVICE_NAMESPACE} - @kubectl delete -f deploy/kubernetes/iam-auth.yaml - -.PHONY: clean-terraform -clean-terraform: - @terraform destroy -auto-approve - @rm -rf deploy - -.PHONY: clean -clean: clean-k8s clean-terraform - @echo "Clean all auth related k8s resource" \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/iam.tf b/examples/aws-iam/iam-provision/iam.tf deleted file mode 100644 index db6e5eb2..00000000 --- a/examples/aws-iam/iam-provision/iam.tf +++ /dev/null @@ -1,19 +0,0 @@ -data "aws_caller_identity" "current" {} - -data "aws_iam_policy_document" "k8s_assume_role" { - statement { - sid = "AssumeRole" - - actions = ["sts:AssumeRole"] - - principals { - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - } - } -} -resource "aws_iam_role" "k8s_admin" { - name = "${local.kubernetes_name}-admin" - path = "/" - assume_role_policy = data.aws_iam_policy_document.k8s_assume_role.json -} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/k8s.tf b/examples/aws-iam/iam-provision/k8s.tf deleted file mode 100644 index 6f117173..00000000 --- a/examples/aws-iam/iam-provision/k8s.tf +++ /dev/null @@ -1,85 +0,0 @@ -data "template_file" "iam_auth_yaml" { - template = file("${path.module}/resources/iam-auth.yaml") - - vars = { - image = var.aws_iam_authenticator_image - cluster_name = local.kubernetes_name - } -} - -data "template_file" "iam_admin_yaml" { - template = file("${path.module}/resources/iam-admin.yaml") - - vars = { - cluster_name = local.kubernetes_name - k8s_admin_iam_role = aws_iam_role.k8s_admin.arn - } -} - -resource "local_file" "iam_auth_yaml" { - content = data.template_file.iam_auth_yaml.rendered - filename = "./deploy/kubernetes/iam-auth.yaml" -} - -resource "local_file" "iam_admin_yaml" { - content = data.template_file.iam_admin_yaml.rendered - filename = "./deploy/kubernetes/iam-admin.yaml" -} - -data "template_file" "irsa_yaml" { - template = file("${path.module}/resources/irsa.yaml") - - vars = { - image = var.pod_identity_webhook_image - ca_bundle = base64encode(data.aws_s3_bucket_object.pod_identity_webhook_crt.body) - } -} - -resource "local_file" "irsa_yaml" { - content = data.template_file.irsa_yaml.rendered - filename = "./deploy/kubernetes/irsa.yaml" -} - -data "aws_s3_bucket_object" "kubeconfig" { - bucket = var.ignition_s3_bucket - key = var.kubeconfig_s3_key -} - -locals { - kubernetes_name = yamldecode(data.aws_s3_bucket_object.kubeconfig.body)["clusters"][0]["name"] - kubernetes_host = yamldecode(data.aws_s3_bucket_object.kubeconfig.body)["clusters"][0]["cluster"]["server"] - kubernetes_cluster_ca = yamldecode(data.aws_s3_bucket_object.kubeconfig.body)["clusters"][0]["cluster"]["certificate-authority-data"] -} - -data "template_file" "kubeconfig_iam" { - - template = file("${path.module}/resources/kubeconfig.iam") - - vars = { - api_server_endpoint = local.kubernetes_host - cluster_name = local.kubernetes_name - cluster_ca = local.kubernetes_cluster_ca - k8s_admin_iam_role = aws_iam_role.k8s_admin.arn - } -} - -resource "aws_s3_bucket_object" "kubeconfig_iam" { - bucket = var.ignition_s3_bucket - - key = "kubeconfig.iam" - content = data.template_file.kubeconfig_iam.rendered - acl = "private" - - server_side_encryption = "AES256" - content_type = "text/plain" - - tags = merge(module.label.tags, map( - "Name", "kubeconfig.iam", - "Role", "k8s-master" - )) -} - -resource "local_file" "kubeconfig_iam" { - content = data.template_file.kubeconfig_iam.rendered - filename = "./deploy/kubernetes/kubeconfig.iam" -} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/label.tf b/examples/aws-iam/iam-provision/label.tf deleted file mode 100644 index 9187a721..00000000 --- a/examples/aws-iam/iam-provision/label.tf +++ /dev/null @@ -1,11 +0,0 @@ -# --------------------------------------------------------------------------------------------------------------------- -# Naming and Tags -# --------------------------------------------------------------------------------------------------------------------- - -module "label" { - source = "../../../modules/aws/null-label" - environment = var.environment - project = var.project - name = var.name - service = var.service -} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/oidc.tf b/examples/aws-iam/iam-provision/oidc.tf deleted file mode 100644 index eeba5979..00000000 --- a/examples/aws-iam/iam-provision/oidc.tf +++ /dev/null @@ -1,61 +0,0 @@ -data "aws_region" "current" {} - -resource "null_resource" "oidc_thumbprint" { - provisioner "local-exec" { - command = "openssl s_client -connect s3-${data.aws_region.current.name}.amazonaws.com:443 -servername s3-${data.aws_region.current.name}.amazonaws.com -showcerts < /dev/null 2>/dev/null | openssl x509 -in /dev/stdin -sha1 -noout -fingerprint | cut -d '=' -f 2 | tr -d ':' > .terraform/oidc-thumbprint" - } -} - -data "local_file" "oidc_thumbprint" { - filename = ".terraform/oidc-thumbprint" - depends_on = [null_resource.oidc_thumbprint] -} - -resource "aws_iam_openid_connect_provider" "irsa" { - url = "https://s3-${data.aws_region.current.name}.amazonaws.com/${var.oidc_s3_bucket}" - - client_id_list = [var.oidc_api_audiences] - - thumbprint_list = [chomp(data.local_file.oidc_thumbprint.content)] -} - -data "template_file" "discovery_json" { - template = file("${path.module}/resources/discovery.json") - - vars = { - issuer_host = "https://s3-${data.aws_region.current.name}.amazonaws.com/${var.oidc_s3_bucket}" - } -} - -resource "aws_s3_bucket_object" "discovery_json" { - bucket = var.oidc_s3_bucket - - key = ".well-known/openid-configuration" - content = data.template_file.discovery_json.rendered - acl = "public-read" - content_type = "application/json" - - tags = merge(module.label.tags, map( - "Name", "discovery.json", - "Role", "k8s-master" - )) -} - -data "local_file" "keys_json" { - filename = "./deploy/secrets/keys.json" -} - -resource "aws_s3_bucket_object" "keys_json" { - bucket = var.oidc_s3_bucket - - key = "keys.json" - content = data.local_file.keys_json.content - acl = "public-read" - content_type = "application/json" - - - tags = merge(module.label.tags, map( - "Name", "keys.json", - "Role", "k8s-master" - )) -} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/outputs.tf b/examples/aws-iam/iam-provision/outputs.tf deleted file mode 100644 index bf075489..00000000 --- a/examples/aws-iam/iam-provision/outputs.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "oidc_issuer_endpoint" { - value = "https://s3-${data.aws_region.current.name}.amazonaws.com/${var.oidc_s3_bucket}" -} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/providers.tf b/examples/aws-iam/iam-provision/providers.tf deleted file mode 100644 index 02b813fa..00000000 --- a/examples/aws-iam/iam-provision/providers.tf +++ /dev/null @@ -1,32 +0,0 @@ -terraform { - required_version = ">= 0.12.0" -} - -provider "aws" { - region = var.aws_region - version = "2.65.0" -} - -provider "external" { - version = "1.2.0" -} - -provider "ignition" { - version = "1.2.0" -} - -provider "null" { - version = "2.1.2" -} - -provider "random" { - version = "2.2.0" -} - -provider "template" { - version = "2.1.2" -} - -provider "tls" { - version = "2.1.0" -} diff --git a/examples/aws-iam/iam-provision/resources/iam-auth.yaml b/examples/aws-iam/iam-provision/resources/iam-auth.yaml deleted file mode 100644 index 2cb34fe2..00000000 --- a/examples/aws-iam/iam-provision/resources/iam-auth.yaml +++ /dev/null @@ -1,165 +0,0 @@ ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: aws-iam-authenticator -rules: -- apiGroups: - - iamauthenticator.k8s.aws - resources: - - iamidentitymappings - verbs: - - get - - list - - watch -- apiGroups: - - iamauthenticator.k8s.aws - resources: - - iamidentitymappings/status - verbs: - - patch - - update -- apiGroups: - - "" - resources: - - events - verbs: - - create - - update - - patch - ---- ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: iamidentitymappings.iamauthenticator.k8s.aws -spec: - group: iamauthenticator.k8s.aws - version: v1alpha1 - scope: Cluster - names: - plural: iamidentitymappings - singular: iamidentitymapping - kind: IAMIdentityMapping - categories: - - all - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - required: - - arn - - username - properties: - arn: - type: string - username: - type: string - groups: - type: array - items: - type: string - ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: aws-iam-authenticator - namespace: kube-system - ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: aws-iam-authenticator -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: aws-iam-authenticator -subjects: -- kind: ServiceAccount - name: aws-iam-authenticator - namespace: kube-system - ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - namespace: kube-system - name: aws-iam-authenticator - labels: - k8s-app: aws-iam-authenticator -spec: - selector: - matchLabels: - k8s-app: aws-iam-authenticator - updateStrategy: - type: RollingUpdate - template: - metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: "" - labels: - k8s-app: aws-iam-authenticator - spec: - # use service account with access to - serviceAccountName: aws-iam-authenticator - - # run on the host network (don't depend on CNI) - hostNetwork: true - - # run on each master node - nodeSelector: - node-role.kubernetes.io/master: "" - tolerations: - - effect: NoSchedule - key: node-role.kubernetes.io/master - - key: CriticalAddonsOnly - operator: Exists - - # run `aws-iam-authenticator server` with three volumes - # - config (mounted from the ConfigMap at /etc/aws-iam-authenticator/config.yaml) - # - state (persisted TLS certificate and keys, mounted from the host) - # - output (output kubeconfig to plug into your apiserver configuration, mounted from the host) - containers: - - name: aws-iam-authenticator - image: ${image} - args: - - server - - --cluster-id=${cluster_name} - - --state-dir=/var/aws-iam-authenticator - - --kubeconfig-pregenerated=true - - --generate-kubeconfig=/etc/kubernetes/aws-iam-authenticator/kubeconfig - - --backend-mode=CRD - # uncomment if using the Kops Usage instructions https://sigs.k8s.io/aws-iam-authenticator#kops-usage - # the kubeconfig.yaml is pregenerated by the 'aws-iam-authenticator init' step - # - --kubeconfig-pregenerated=true - - resources: - requests: - memory: 20Mi - cpu: 10m - limits: - memory: 20Mi - cpu: 100m - - volumeMounts: - - name: state - mountPath: /var/aws-iam-authenticator/ - - name: output - mountPath: /etc/kubernetes/aws-iam-authenticator/ - - name: tmp - mountPath: /tmp - - volumes: - - name: output - hostPath: - path: /etc/kubernetes/aws-iam-authenticator/ - - name: state - hostPath: - path: /var/aws-iam-authenticator/ - - name: tmp - emptyDir: {} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/resources/irsa.yaml b/examples/aws-iam/iam-provision/resources/irsa.yaml deleted file mode 100644 index 3aeb5e55..00000000 --- a/examples/aws-iam/iam-provision/resources/irsa.yaml +++ /dev/null @@ -1,136 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: pod-identity-webhook - namespace: kube-system - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: pod-identity-webhook -rules: -- apiGroups: - - "" - resources: - - secrets - verbs: - - create -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - update - - patch - resourceNames: - - "pod-identity-webhook" -- apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - get - - watch - - list -- apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests - verbs: - - create - - get - - list - - watch - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: pod-identity-webhook -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: pod-identity-webhook -subjects: -- kind: ServiceAccount - name: pod-identity-webhook - namespace: kube-system - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: pod-identity-webhook - namespace: kube-system -spec: - replicas: 1 - selector: - matchLabels: - app: pod-identity-webhook - template: - metadata: - labels: - app: pod-identity-webhook - spec: - serviceAccountName: pod-identity-webhook - containers: - - name: pod-identity-webhook - image: ${image} - imagePullPolicy: Always - command: - - /webhook - - --in-cluster - - --namespace=kube-system - - --service-name=pod-identity-webhook - - --tls-secret=pod-identity-webhook - - --annotation-prefix=eks.amazonaws.com - - --token-audience=sts.amazonaws.com - - --logtostderr - volumeMounts: - - name: webhook-certs - mountPath: /var/run/app/certs - readOnly: false - volumes: - - name: webhook-certs - emptyDir: {} - ---- -apiVersion: v1 -kind: Service -metadata: - name: pod-identity-webhook - namespace: kube-system - annotations: - prometheus.io/port: "443" - prometheus.io/scheme: "https" - prometheus.io/scrape: "true" -spec: - ports: - - port: 443 - targetPort: 443 - selector: - app: pod-identity-webhook - ---- -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: pod-identity-webhook - namespace: kube-system -webhooks: -- name: pod-identity-webhook.amazonaws.com - failurePolicy: Ignore - clientConfig: - service: - name: pod-identity-webhook - namespace: kube-system - path: "/mutate" - caBundle: ${ca_bundle} - rules: - - operations: [ "CREATE" ] - apiGroups: [""] - apiVersions: ["v1"] - resources: ["pods"] \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/s3.tf b/examples/aws-iam/iam-provision/s3.tf deleted file mode 100644 index 4612ab55..00000000 --- a/examples/aws-iam/iam-provision/s3.tf +++ /dev/null @@ -1,29 +0,0 @@ -data "aws_s3_bucket_object" "pod_identity_webhook_crt" { - bucket = var.ignition_s3_bucket - key = "pod-identity-webhook.crt" -} - -resource "local_file" "pod_identity_webhook_crt" { - content = data.aws_s3_bucket_object.pod_identity_webhook_crt.body - filename = "deploy/secrets/tls.crt" -} - -data "aws_s3_bucket_object" "pod_identity_webhook_key" { - bucket = var.ignition_s3_bucket - key = "pod-identity-webhook.key" -} - -resource "local_file" "pod_identity_webhook_key" { - content = data.aws_s3_bucket_object.pod_identity_webhook_key.body - filename = "deploy/secrets/tls.key" -} - -data "aws_s3_bucket_object" "oidc_issuer_pub" { - bucket = var.ignition_s3_bucket - key = "oidc-issuer.pub" -} - -resource "local_file" "oidc_issuer_pub" { - content = data.aws_s3_bucket_object.oidc_issuer_pub.body - filename = "deploy/secrets/oidc-issuer.pub" -} \ No newline at end of file diff --git a/examples/aws-iam/kubernetes-cluster/main.tf b/examples/aws-iam/kubernetes-cluster/main.tf deleted file mode 100644 index e46a76f6..00000000 --- a/examples/aws-iam/kubernetes-cluster/main.tf +++ /dev/null @@ -1,111 +0,0 @@ -# --------------------------------------------------------------------------------------------------------------------- -# Naming and Tags -# --------------------------------------------------------------------------------------------------------------------- - -module "label" { - source = "../../../modules/aws/null-label" - environment = var.environment - project = var.project - name = var.name - service = var.service -} - -# --------------------------------------------------------------------------------------------------------------------- -# Network -# --------------------------------------------------------------------------------------------------------------------- - -module "network" { - source = "../../../modules/aws/network" - bastion_key_name = var.key_pair_name - name = module.label.id - extra_tags = module.label.tags -} - -module "latest_os_ami" { - source = "../../../modules/aws/latest-os-ami" - flavor = "flatcar" -} - -# --------------------------------------------------------------------------------------------------------------------- -# ElastiKube -# --------------------------------------------------------------------------------------------------------------------- - -module "master" { - source = "../../../modules/aws/elastikube" - - name = module.label.id - kube_service_network_cidr = var.service_cidr - kube_cluster_network_cidr = var.cluster_cidr - - enable_irsa = true - enable_iam_auth = true - - etcd_instance_config = { - count = "1" - image_id = module.latest_os_ami.image_id - ec2_type = "t3.medium" - root_volume_size = "40" - data_volume_size = "100" - data_device_name = "/dev/sdf" - data_device_rename = "/dev/nvme1n1" - data_path = "/etcd/data" - } - - master_instance_config = { - count = "1" - image_id = module.latest_os_ami.image_id - ec2_type_1 = "t3.medium" - ec2_type_2 = "t2.medium" - root_volume_iops = "100" - root_volume_size = "256" - root_volume_type = "gp2" - - on_demand_base_capacity = 0 - on_demand_percentage_above_base_capacity = 100 - spot_instance_pools = 1 - } - - hostzone = "${var.project}.cluster" - endpoint_public_access = var.endpoint_public_access - private_subnet_ids = module.network.private_subnet_ids - public_subnet_ids = module.network.public_subnet_ids - ssh_key = var.key_pair_name - reboot_strategy = "off" - - extra_tags = module.label.tags -} - -# --------------------------------------------------------------------------------------------------------------------- -# Worker Node (On Spot Instance) -# --------------------------------------------------------------------------------------------------------------------- - -module "worker_spot" { - source = "../../../modules/aws/kube-worker" - - name = module.label.id - service_network_cidr = var.service_cidr - network_plugin = var.network_plugin - - security_group_ids = module.master.worker_sg_ids - subnet_ids = module.network.private_subnet_ids - - instance_config = { - name = "spot" - image_id = module.latest_os_ami.image_id - count = "1" - ec2_type_1 = "m5.large" - ec2_type_2 = "m4.large" - root_volume_iops = "0" - root_volume_size = "40" - root_volume_type = "gp2" - - on_demand_base_capacity = 0 - on_demand_percentage_above_base_capacity = 0 - spot_instance_pools = 1 - } - - s3_bucket = module.master.ignition_s3_bucket - ssh_key = var.key_pair_name - - extra_tags = module.label.tags -} diff --git a/examples/aws-iam/kubernetes-cluster/outputs.tf b/examples/aws-iam/kubernetes-cluster/outputs.tf deleted file mode 100644 index 6ce5a97d..00000000 --- a/examples/aws-iam/kubernetes-cluster/outputs.tf +++ /dev/null @@ -1,11 +0,0 @@ -output "bastion_public_ip" { - value = module.network.bastion_public_ip -} - -output "ignition_s3_bucket" { - value = module.master.ignition_s3_bucket -} - -output "oidc_s3_bucket" { - value = module.master.oidc_s3_bucket -} \ No newline at end of file diff --git a/examples/iam-auth-and-irsa/example/iam-auth.tf b/examples/iam-auth-and-irsa/example/iam-auth.tf new file mode 100644 index 00000000..a0913e3b --- /dev/null +++ b/examples/iam-auth-and-irsa/example/iam-auth.tf @@ -0,0 +1,69 @@ +locals { + iam_kubeconfig_vars = { + api_server_endpoint = local.kubernetes_host + cluster_name = module.label.id + cluster_ca = local.kubernetes_cluster_ca + user = "kubernetes-admin" + context = "kubernetes-admin@kubernetes-iam" + k8s_admin_iam_role = aws_iam_role.k8s_admin.arn + } +} + +data "aws_iam_policy_document" "k8s_assume_role" { + statement { + sid = "AssumeRole" + + actions = ["sts:AssumeRole"] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } +} + +resource "aws_iam_role" "k8s_admin" { + name = "${local.kubernetes_name}-admin" + path = "/" + assume_role_policy = data.aws_iam_policy_document.k8s_assume_role.json +} + +resource "local_file" "iam_admin_yaml" { + filename = "./deploy/iam-admin.yaml" + content = templatefile("${path.module}/templates/iam-admin.yaml.tpl", { + user = "kubernetes-admin" + k8s_admin_iam_role = aws_iam_role.k8s_admin.arn + }) +} + +resource "null_resource" "apply_iam_admin_mapping" { + provisioner "local-exec" { + command = "kubectl apply -f ./deploy" + + environment = { + KUBECONFIG = "./.secret/kubeconfig" + } + } + depends_on = [local_file.iam_admin_yaml, local_file.kubeconfig] +} + +resource "aws_s3_bucket_object" "kubeconfig_iam" { + bucket = var.ignition_s3_bucket + + key = "kubeconfig-iam.conf" + content = templatefile("${path.module}/templates/kubeconfig.iam.tpl", local.iam_kubeconfig_vars) + + acl = "private" + server_side_encryption = "AES256" + content_type = "text/plain" + + tags = merge(module.label.tags, map( + "Name", "kubeconfig.iam", + "Role", "k8s-master" + )) +} + +resource "local_file" "kubeconfig_iam_local" { + filename = "./kubeconfig/kubeconfig-iam.conf" + content = templatefile("${path.module}/templates/kubeconfig.iam.tpl", local.iam_kubeconfig_vars) +} diff --git a/examples/iam-auth-and-irsa/example/irsa.tf b/examples/iam-auth-and-irsa/example/irsa.tf new file mode 100644 index 00000000..b79fe727 --- /dev/null +++ b/examples/iam-auth-and-irsa/example/irsa.tf @@ -0,0 +1,46 @@ +data "aws_iam_policy_document" "s3_echoer_policy" { + statement { + sid = "AssumeRole" + effect = "Allow" + actions = ["sts:AssumeRoleWithWebIdentity"] + + principals { + type = "Federated" + identifiers = ["${var.oidc_provider_arn}"] + } + + condition { + test = "StringEquals" + variable = "${var.oidc_issuer}:sub" + values = ["system:serviceaccount:default:s3-echoer"] + } + } +} + +resource "aws_iam_role" "s3_echoer" { + name = "s3-echoer" + path = "/" + assume_role_policy = data.aws_iam_policy_document.s3_echoer_policy.json +} + +resource "aws_iam_role_policy_attachment" "s3_echoer" { + role = aws_iam_role.s3_echoer.name + policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess" +} + +resource "local_file" "s3_echoer" { + filename = "./deploy/s3-echoer.yaml" + content = templatefile("${path.module}/templates/s3-echoer.yaml.tpl", { + account_id = data.aws_caller_identity.current.account_id + }) +} + +resource "null_resource" "apply_s3_echoer" { + provisioner "local-exec" { + command = "kubectl apply -f ./deploy" + environment = { + KUBECONFIG = "./.secret/kubeconfig" + } + } + depends_on = [local_file.s3_echoer, local_file.kubeconfig] +} diff --git a/examples/iam-auth-and-irsa/example/main.tf b/examples/iam-auth-and-irsa/example/main.tf new file mode 100644 index 00000000..d9083cd6 --- /dev/null +++ b/examples/iam-auth-and-irsa/example/main.tf @@ -0,0 +1,26 @@ +module "label" { + source = "../../../modules/aws/null-label" + environment = var.environment + project = var.project + name = var.name + service = var.service +} + +data "aws_caller_identity" "current" {} + +data "aws_s3_bucket_object" "kubeconfig" { + bucket = var.ignition_s3_bucket + key = var.kubeconfig_s3_key +} + +resource "local_file" "kubeconfig" { + filename = "./.secret/kubeconfig" + content = data.aws_s3_bucket_object.kubeconfig.body + depends_on = [data.aws_s3_bucket_object.kubeconfig] +} + +locals { + kubernetes_name = yamldecode(data.aws_s3_bucket_object.kubeconfig.body)["clusters"][0]["name"] + kubernetes_host = yamldecode(data.aws_s3_bucket_object.kubeconfig.body)["clusters"][0]["cluster"]["server"] + kubernetes_cluster_ca = yamldecode(data.aws_s3_bucket_object.kubeconfig.body)["clusters"][0]["cluster"]["certificate-authority-data"] +} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/resources/iam-admin.yaml b/examples/iam-auth-and-irsa/example/templates/iam-admin.yaml.tpl similarity index 52% rename from examples/aws-iam/iam-provision/resources/iam-admin.yaml rename to examples/iam-auth-and-irsa/example/templates/iam-admin.yaml.tpl index 790ba979..fa99cecc 100644 --- a/examples/aws-iam/iam-provision/resources/iam-admin.yaml +++ b/examples/iam-auth-and-irsa/example/templates/iam-admin.yaml.tpl @@ -1,11 +1,9 @@ ---- apiVersion: iamauthenticator.k8s.aws/v1alpha1 kind: IAMIdentityMapping metadata: - name: ${cluster_name}-admin + name: ${user} spec: arn: ${k8s_admin_iam_role} - username: ${cluster_name}-admin + username: ${user} groups: - - system:masters - \ No newline at end of file + - system:masters \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/resources/kubeconfig.iam b/examples/iam-auth-and-irsa/example/templates/kubeconfig.iam.tpl similarity index 78% rename from examples/aws-iam/iam-provision/resources/kubeconfig.iam rename to examples/iam-auth-and-irsa/example/templates/kubeconfig.iam.tpl index e9bcfe98..479ecea0 100644 --- a/examples/aws-iam/iam-provision/resources/kubeconfig.iam +++ b/examples/iam-auth-and-irsa/example/templates/kubeconfig.iam.tpl @@ -8,13 +8,13 @@ contexts: - context: cluster: ${cluster_name} namespace: default - user: ${cluster_name}-admin - name: ${cluster_name}-admin -current-context: ${cluster_name}-admin + user: ${user} + name: ${context} +current-context: ${context} kind: Config preferences: {} users: -- name: ${cluster_name}-admin +- name: ${user} user: exec: apiVersion: client.authentication.k8s.io/v1alpha1 diff --git a/examples/iam-auth-and-irsa/example/templates/s3-echoer.yaml.tpl b/examples/iam-auth-and-irsa/example/templates/s3-echoer.yaml.tpl new file mode 100644 index 00000000..ab7d5156 --- /dev/null +++ b/examples/iam-auth-and-irsa/example/templates/s3-echoer.yaml.tpl @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: s3-echoer + annotations: + k8s.amazonaws.com/role-arn: "arn:aws:iam::${account_id}:role/s3-echoer" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: s3-echoer +spec: + replicas: 1 + selector: + matchLabels: + app: s3-echoer + template: + metadata: + labels: + app: s3-echoer + spec: + serviceAccountName: s3-echoer + containers: + - name: ubuntu + image: ubuntu:20.04 + command: ["/bin/bash"] + args: ["-c", " + apt-get update && apt-get install -y curl zip; + curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip; + unzip awscliv2.zip; + ./aws/install; + rm -rf awscliv2.zip; + while :; do sleep 3600; done"] \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/variables.tf b/examples/iam-auth-and-irsa/example/variables.tf similarity index 61% rename from examples/aws-iam/iam-provision/variables.tf rename to examples/iam-auth-and-irsa/example/variables.tf index e67a95fc..c502813d 100644 --- a/examples/aws-iam/iam-provision/variables.tf +++ b/examples/iam-auth-and-irsa/example/variables.tf @@ -1,15 +1,3 @@ -variable "aws_region" { - description = "(Optional) The AWS region" - type = string - default = "us-west-2" -} - -variable "oidc_api_audiences" { - description = "the OIDC authenticator pre-introduction of API audiences" - type = string - default = "sts.amazonaws.com" -} - variable "ignition_s3_bucket" { description = "The Kubernetes ignition s3 bucket" type = string @@ -21,21 +9,10 @@ variable "kubeconfig_s3_key" { default = "admin.conf" } -variable "oidc_s3_bucket" { - description = "The oidc s3 bucket for IRSA" - type = string -} - -variable "aws_iam_authenticator_image" { - description = "The pod identity webhook image" - type = string - default = "quay.io/amis/aws-iam-authenticator:d7c0b2e" -} - -variable "pod_identity_webhook_image" { - description = "The pod identity webhook image" +variable "aws_region" { + description = "(Optional) The AWS region" type = string - default = "quay.io/amis/pod-identity-webhook:694444b" + default = "us-west-2" } variable "environment" { @@ -53,11 +30,21 @@ variable "project" { variable "name" { description = "(Optional) name, used to compose the resource name" type = string - default = "elastikube" + default = "k8s" } variable "service" { description = "(Optional) which service provide by this service" type = string default = "kubernetes" +} + +variable "oidc_provider_arn" { + description = "ARN of the OIDC provider for IRSA." + type = string +} + +variable "oidc_issuer" { + description = "Domain name of the S3 bucket (*.s3.amazonaws.com)." + type = string } \ No newline at end of file diff --git a/examples/iam-auth-and-irsa/example/version.tf b/examples/iam-auth-and-irsa/example/version.tf new file mode 100644 index 00000000..865a951a --- /dev/null +++ b/examples/iam-auth-and-irsa/example/version.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 0.12.29" +} + +provider "aws" { + region = var.aws_region + version = "~>2.65.0" +} + +provider "local" { + version = "1.4.0" +} + + diff --git a/examples/iam-auth-and-irsa/k8s-cluster/main.tf b/examples/iam-auth-and-irsa/k8s-cluster/main.tf new file mode 100644 index 00000000..cdc7ebae --- /dev/null +++ b/examples/iam-auth-and-irsa/k8s-cluster/main.tf @@ -0,0 +1,107 @@ +module "label" { + source = "../../../modules/aws/null-label" + environment = var.environment + project = var.project + name = var.name + service = var.service +} + +module "network" { + source = "../../../modules/aws/network" + bastion_key_name = var.key_pair_name + name = module.label.id + extra_tags = module.label.tags +} + +locals { + cluster_cidr = var.network_plugin == "amazon-vpc" ? module.network.vpc_cidr : var.cluster_cidr +} + +module "latest_os_ami" { + source = "../../../modules/aws/latest-os-ami" + flavor = "flatcar" +} + +module "service_account" { + source = "../../../modules/tls/private-key" +} + +module "irsa" { + source = "../../../modules/aws/irsa" + + name = module.label.id + oidc_s3_bucket = "oidc-${md5(module.label.id)}" + oidc_pub_key = module.service_account.public_key_pem +} + +module "iam_auth" { + source = "../../../modules/aws/iam-authenticator" + + name = module.label.id + extra_tags = module.label.tags +} + +module "master" { + source = "../../../modules/aws/elastikube" + + name = module.label.id + network_plugin = var.network_plugin + kube_service_network_cidr = var.service_cidr + kube_cluster_network_cidr = local.cluster_cidr + enable_iam_auth = true + enable_irsa = true + + service_account_content = { + pub_key = module.service_account.public_key_pem + pri_key = module.service_account.private_key_pem + } + + irsa_oidc_config = { + issuer = "https://${module.irsa.oidc_issuer}" + api_audiences = module.irsa.oidc_api_audiences + } + + auth_webhook_kubeconfig_path = module.iam_auth.webhook_kubeconfig_path + + etcd_instance_config = { + count = "1" + image_id = module.latest_os_ami.image_id + ec2_type = "t3.medium" + root_volume_size = "40" + data_volume_size = "100" + data_device_name = "/dev/sdf" + data_device_rename = "/dev/nvme1n1" + data_path = "/etcd/data" + } + + master_instance_config = { + count = "1" + image_id = module.latest_os_ami.image_id + ec2_type_1 = "t3.medium" + ec2_type_2 = "t2.medium" + root_volume_iops = "100" + root_volume_size = "256" + root_volume_type = "gp2" + + on_demand_base_capacity = 0 + on_demand_percentage_above_base_capacity = 0 + spot_instance_pools = 1 + } + + hostzone = "${var.project}.cluster" + endpoint_public_access = var.endpoint_public_access + private_subnet_ids = module.network.private_subnet_ids + public_subnet_ids = module.network.public_subnet_ids + ssh_key = var.key_pair_name + reboot_strategy = "off" + + extra_tags = module.label.tags + + extra_ignition_file_ids = concat( + module.irsa.ignitions_files, + module.iam_auth.ignitions_files, + ) +} + + + diff --git a/examples/iam-auth-and-irsa/k8s-cluster/outputs.tf b/examples/iam-auth-and-irsa/k8s-cluster/outputs.tf new file mode 100644 index 00000000..223f4088 --- /dev/null +++ b/examples/iam-auth-and-irsa/k8s-cluster/outputs.tf @@ -0,0 +1,21 @@ +output "bastion_public_ip" { + value = module.network.bastion_public_ip +} + +output "ignition_s3_bucket" { + value = module.master.ignition_s3_bucket +} + +output "oidc_s3_bucket" { + value = module.irsa.oidc_s3_bucket +} + +output "oidc_provider_arn" { + description = "ARN of the OIDC provider for IRSA." + value = module.irsa.oidc_provider_arn +} + +output "oidc_issuer" { + description = "Issuer of OIDC provider for IRSA." + value = module.irsa.oidc_issuer +} \ No newline at end of file diff --git a/examples/aws-iam/kubernetes-cluster/variables.tf b/examples/iam-auth-and-irsa/k8s-cluster/variables.tf similarity index 68% rename from examples/aws-iam/kubernetes-cluster/variables.tf rename to examples/iam-auth-and-irsa/k8s-cluster/variables.tf index 90505a7c..37967730 100644 --- a/examples/aws-iam/kubernetes-cluster/variables.tf +++ b/examples/iam-auth-and-irsa/k8s-cluster/variables.tf @@ -4,9 +4,10 @@ variable "aws_region" { default = "us-west-2" } -variable "key_pair_name" { - description = "The ssh key name for all instance, e.g. bastion, master, etcd, worker" +variable "name" { + description = "(Optional) name, used to compose the resource name" type = string + default = "k8s" } variable "environment" { @@ -21,56 +22,36 @@ variable "project" { default = "getamis" } -variable "name" { - description = "(Optional) name, used to compose the resource name" - type = string - default = "elastikube" -} - variable "service" { description = "(Optional) which service provide by this service" type = string default = "kubernetes" } -variable "endpoint_public_access" { - description = "(Optional) kubernetes apiserver endpoint" - type = bool - default = false -} - -variable "extra_tags" { - description = "Extra AWS tags to be applied to created resources." - type = map(string) - default = {} -} - -variable "network_plugin" { - description = "(Optional) Desired network plugin which is use for Kubernetes cluster. e.g. 'flannel', 'amazon-vpc'" - type = string - default = "amazon-vpc" -} - variable "service_cidr" { description = "(Optional) The Kubernetes service CIDR." type = string - default = "172.16.0.0/13" + default = "10.96.0.0/12" } variable "cluster_cidr" { description = "(Optional) The Kubernetes cluster CIDR." type = string - default = "172.24.0.0/13" + default = "10.244.0.0/16" +} + +variable "key_pair_name" { + description = "The ssh key name for all instance, e.g. bastion, master, etcd, worker" + type = string } -variable "certs_validity_period_hours" { - description = < ${path.root}/.secret/keys.json" + + environment = { + GO111MODULE = "on" + PKCS_KEY = "${path.root}/.secret/oidc-pkcs8.pub" + } + } + depends_on = [local_file.oidc_pub_key] +} + +resource "aws_s3_bucket" "oidc" { + bucket = var.oidc_s3_bucket + acl = "private" + + tags = merge( + map("Name", "${var.name}-oidc-${md5("${var.name}-oidc")}"), + var.extra_tags) +} + +resource "aws_s3_bucket_object" "discovery_json" { + bucket = aws_s3_bucket.oidc.id + + key = ".well-known/openid-configuration" + acl = "public-read" + content_type = "application/json" + + content = templatefile("${path.module}/templates/discovery.json.tpl", { + issuer_host = "https://s3-${data.aws_region.current.name}.amazonaws.com/${var.oidc_s3_bucket}" + }) + + tags = merge(map( + "Name", "discovery.json", + "Role", "k8s-master" + ), var.extra_tags) +} + +data "local_file" "keys_json" { + filename = "${path.root}/.secret/keys.json" + depends_on = [null_resource.generate_oidc_keys_json] +} + +resource "aws_s3_bucket_object" "keys_json" { + bucket = aws_s3_bucket.oidc.id + + key = "keys.json" + content = data.local_file.keys_json.content + acl = "public-read" + content_type = "application/json" + + tags = merge(map( + "Name", "keys.json", + "Role", "k8s-master" + ), var.extra_tags) +} diff --git a/modules/aws/irsa/outputs.tf b/modules/aws/irsa/outputs.tf new file mode 100644 index 00000000..2cc6b0c7 --- /dev/null +++ b/modules/aws/irsa/outputs.tf @@ -0,0 +1,21 @@ +output "oidc_s3_bucket" { + value = aws_s3_bucket.oidc.id +} + +output "oidc_api_audiences" { + value = var.oidc_api_audiences +} + +output "oidc_issuer" { + description = "Domain name of the S3 bucket (*.s3.amazonaws.com)." + value = "s3-${data.aws_region.current.name}.amazonaws.com/${var.oidc_s3_bucket}" +} + +output "oidc_provider_arn" { + description = "ARN of the OIDC provider for IRSA" + value = aws_iam_openid_connect_provider.irsa.arn +} + +output "ignitions_files" { + value = module.ignition_pod_idenity_webhook.files +} \ No newline at end of file diff --git a/examples/aws-iam/iam-provision/resources/discovery.json b/modules/aws/irsa/templates/discovery.json.tpl similarity index 100% rename from examples/aws-iam/iam-provision/resources/discovery.json rename to modules/aws/irsa/templates/discovery.json.tpl diff --git a/examples/aws-iam/iam-provision/go.mod b/modules/aws/irsa/tools/self-hosted/go.mod similarity index 100% rename from examples/aws-iam/iam-provision/go.mod rename to modules/aws/irsa/tools/self-hosted/go.mod diff --git a/examples/aws-iam/iam-provision/go.sum b/modules/aws/irsa/tools/self-hosted/go.sum similarity index 100% rename from examples/aws-iam/iam-provision/go.sum rename to modules/aws/irsa/tools/self-hosted/go.sum diff --git a/examples/aws-iam/iam-provision/main.go b/modules/aws/irsa/tools/self-hosted/main.go similarity index 100% rename from examples/aws-iam/iam-provision/main.go rename to modules/aws/irsa/tools/self-hosted/main.go diff --git a/modules/aws/irsa/tools/thumbprint.sh b/modules/aws/irsa/tools/thumbprint.sh new file mode 100755 index 00000000..252a2752 --- /dev/null +++ b/modules/aws/irsa/tools/thumbprint.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +THUMBPRINT=$(openssl s_client -connect s3-$1.amazonaws.com:443 -servername s3-$1.amazonaws.com -showcerts < /dev/null 2>/dev/null | openssl x509 -in /dev/stdin -sha1 -noout -fingerprint | cut -d '=' -f 2 | tr -d ':') +THUMBPRINT_JSON="{\"thumbprint\": \"${THUMBPRINT}\"}" +echo $THUMBPRINT_JSON \ No newline at end of file diff --git a/modules/aws/irsa/variables.tf b/modules/aws/irsa/variables.tf new file mode 100644 index 00000000..f11f5ea2 --- /dev/null +++ b/modules/aws/irsa/variables.tf @@ -0,0 +1,63 @@ +variable "name" { + description = "(Required) Name of the cluster." + type = string +} + +variable "container" { + description = "Desired container repo and tag." + type = map(string) + default = { + repo = "quay.io/amis/aws-pod-identity-webhook" + tag = "v0.2.0" + } +} + +variable "kube_addons_dir_path" { + description = "A path for installing addons." + type = string + default = "/etc/kubernetes/addons" +} + +variable "pki_dir_path" { + description = "A path for writting PKI." + type = string + default = "/etc/kubernetes/pki/pod-identity-webhook" +} + +variable "webhook_flags" { + description = "The flags of pod identity webhook. The variables need to follow https://github.com/aws/amazon-eks-pod-identity-webhook/blob/master/main.go. Do not use underline." + default = {} +} + +variable "certs_validity_period_hours" { + description = "Validity period of the self-signed certificates (in hours). Default is 10 years." + type = string + + // Default is provided only in this case + // bacause *some* of etcd internal certs are still self-generated and need + // this variable set + default = 87600 +} + +variable "oidc_s3_bucket" { + description = "Unique name under which the Amazon S3 bucket will be created. Bucket name must start with a lower case name and is limited to 63 characters." + type = string +} + +variable "oidc_api_audiences" { + description = "the OIDC authenticator pre-introduction of API audiences" + type = string + default = "sts.amazonaws.com" +} + +variable "oidc_pub_key" { + description = "The OIDC public key content" + type = string + default = "" +} + +variable "extra_tags" { + description = "Extra AWS tags to be applied to created resources." + type = map(string) + default = {} +} diff --git a/modules/aws/kube-etcd/ignition.tf b/modules/aws/kube-etcd/ignition.tf index 50627ba9..776125c5 100644 --- a/modules/aws/kube-etcd/ignition.tf +++ b/modules/aws/kube-etcd/ignition.tf @@ -16,7 +16,7 @@ module "ignition_node_exporter" { } module "ignition_etcd" { - source = "git::ssh://git@github.com/getamis/terraform-ignition-etcd?ref=v0.1.0" + source = "git::ssh://git@github.com/getamis/terraform-ignition-etcd" name = var.name containers = var.containers diff --git a/modules/aws/kube-iam-auth/certs.tf b/modules/aws/kube-iam-auth/certs.tf deleted file mode 100644 index b1a6555f..00000000 --- a/modules/aws/kube-iam-auth/certs.tf +++ /dev/null @@ -1,87 +0,0 @@ -module "webhook_ca" { - source = "../../tls/certificate-authority" - - cert_config = { - common_name = var.name - organization = var.name - validity_period_hours = var.certs_validity_period_hours - } - - rsa_bits = 2048 - self_signed = true -} - -module "webhook_cert" { - source = "../../tls/certificate" - - ca_config = { - algorithm = module.webhook_ca.algorithm - key_pem = module.webhook_ca.private_key_pem - cert_pem = module.webhook_ca.cert_pem - } - - cert_config = { - common_name = "pod-identity-webhook" - organization = var.name - validity_period_hours = var.certs_validity_period_hours - } - - cert_hostnames = ["${var.webhook_service_name}.${var.webhook_service_namespace}.svc"] - - cert_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - ] - - self_signed = true -} - -module "iam_auth_ca" { - source = "../../tls/certificate-authority" - - cert_config = { - common_name = var.name - organization = var.name - validity_period_hours = var.certs_validity_period_hours - } - - rsa_bits = 2048 - self_signed = true -} - -module "iam_auth_cert" { - source = "../../tls/certificate" - - ca_config = { - algorithm = module.iam_auth_ca.algorithm - key_pem = module.iam_auth_ca.private_key_pem - cert_pem = module.iam_auth_ca.cert_pem - } - - cert_config = { - common_name = "aws-iam-auth" - organization = var.name - validity_period_hours = var.certs_validity_period_hours - } - - cert_ip_addresses = compact(concat( - list( - "127.0.0.1" - ), - )) - - cert_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - "client_auth", - ] - - self_signed = true -} - -resource "tls_private_key" "oidc_issuer" { - algorithm = "RSA" - rsa_bits = 2048 -} \ No newline at end of file diff --git a/modules/aws/kube-iam-auth/ignition.tf b/modules/aws/kube-iam-auth/ignition.tf deleted file mode 100644 index 1f876f74..00000000 --- a/modules/aws/kube-iam-auth/ignition.tf +++ /dev/null @@ -1,8 +0,0 @@ -module "ignition_iam_auth" { - source = "../../ignitions/aws-iam-auth" - - auth_ca_cert = module.iam_auth_ca.cert_pem - auth_cert = module.iam_auth_cert.cert_pem - auth_cert_key = module.iam_auth_cert.private_key_pem - kubeconfig_dir_path = var.webhook_kubeconfig_dir_path -} diff --git a/modules/aws/kube-iam-auth/main.tf b/modules/aws/kube-iam-auth/main.tf deleted file mode 100644 index 5cf60726..00000000 --- a/modules/aws/kube-iam-auth/main.tf +++ /dev/null @@ -1,58 +0,0 @@ -data "aws_region" "current" {} - -resource "aws_s3_bucket" "oidc" { - bucket = var.oidc_s3_bucket - acl = "public-read" - - tags = merge(map( - "Name", "${var.name}-oidc-${md5("${var.name}-oidc")}"), var.extra_tags) -} - -resource "aws_s3_bucket_object" "pod_identity_webhook_crt" { - bucket = var.ignition_s3_bucket - - key = "pod-identity-webhook.crt" - content = module.webhook_cert.cert_pem - acl = "private" - - server_side_encryption = "AES256" - content_type = "text/plain" - - tags = merge(map( - "Name", "pod-identity-webhook.crt", - "kubernetes.io/cluster/${var.name}", "owned", - ), var.extra_tags) -} - -resource "aws_s3_bucket_object" "pod_identity_webhook_pri_key" { - bucket = var.ignition_s3_bucket - - key = "pod-identity-webhook.key" - content = module.webhook_cert.private_key_pem - acl = "private" - - server_side_encryption = "AES256" - content_type = "text/plain" - - tags = merge(map( - "Name", "pod-identity-webhook.key", - "kubernetes.io/cluster/${var.name}", "owned", - ), var.extra_tags) -} - -resource "aws_s3_bucket_object" "oidc_issuer_pub_key" { - bucket = var.ignition_s3_bucket - - key = "oidc-issuer.pub" - content = tls_private_key.oidc_issuer.public_key_pem - acl = "private" - - server_side_encryption = "AES256" - content_type = "text/plain" - - tags = merge(var.extra_tags, map( - "Name", "oidc-issuer.pub", - "kubernetes.io/cluster/${var.name}", "owned", - "Role", "k8s-master" - )) -} diff --git a/modules/aws/kube-iam-auth/outputs.tf b/modules/aws/kube-iam-auth/outputs.tf deleted file mode 100644 index cd354158..00000000 --- a/modules/aws/kube-iam-auth/outputs.tf +++ /dev/null @@ -1,35 +0,0 @@ -output "files" { - value = module.ignition_iam_auth.files -} - -output "webhook_kubeconfig_path" { - value = module.ignition_iam_auth.kubeconfig_path -} - -output "webhook_cert" { - sensitive = true - value = module.webhook_cert.cert_pem -} - -output "webhook_cert_key" { - sensitive = true - value = module.webhook_cert.private_key_pem -} - -output "oidc_issuer_pub_key" { - sensitive = true - value = tls_private_key.oidc_issuer.public_key_pem -} - -output "oidc_issuer_pri_key" { - sensitive = true - value = tls_private_key.oidc_issuer.private_key_pem -} - -output "oidc_s3_bucket" { - value = aws_s3_bucket.oidc.id -} - -output "oidc_issuer" { - value = "https://s3-${data.aws_region.current.name}.amazonaws.com/${aws_s3_bucket.oidc.id}" -} diff --git a/modules/aws/kube-master/ignition.tf b/modules/aws/kube-master/ignition.tf index cacae24b..12f00297 100644 --- a/modules/aws/kube-master/ignition.tf +++ b/modules/aws/kube-master/ignition.tf @@ -12,7 +12,7 @@ resource "random_password" "encryption_secret" { } module "ignition_kubernetes" { - source = "git::ssh://git@github.com/getamis/terraform-ignition-kubernetes?ref=v0.1.0" + source = "git::ssh://git@github.com/getamis/terraform-ignition-kubernetes" binaries = var.binaries containers = var.containers @@ -52,7 +52,7 @@ module "ignition_kubernetes" { audit_log_policy_content = var.audit_log_policy_content encryption_secret = random_password.encryption_secret.result enable_iam_auth = var.enable_iam_auth - auth_webhook_config_path = var.auth_webhook_config_path + auth_webhook_config_path = var.auth_webhook_kubeconfig_path enable_irsa = var.enable_irsa oidc_config = var.oidc_config @@ -77,8 +77,8 @@ module "ignition_kubernetes" { front_proxy_ca_key = module.front_proxy_ca.private_key_pem front_proxy_client_cert = module.front_proxy_client_cert.cert_pem front_proxy_client_key = module.front_proxy_client_cert.private_key_pem - sa_pub = module.service_account.public_key_pem - sa_key = module.service_account.private_key_pem + sa_pub = var.service_account_content.pub_key == "" ? module.service_account.public_key_pem : var.service_account_content.pub_key + sa_key = var.service_account_content.pri_key == "" ? module.service_account.private_key_pem : var.service_account_content.pri_key } kubelet_cert = { diff --git a/modules/aws/kube-master/outputs.tf b/modules/aws/kube-master/outputs.tf index c2cc2384..1e62eaac 100644 --- a/modules/aws/kube-master/outputs.tf +++ b/modules/aws/kube-master/outputs.tf @@ -17,7 +17,7 @@ output "kubernetes_ca_cert" { output "service_account_pub_key" { sensitive = true - value = module.service_account.public_key_pem + value = var.service_account_content.pub_key == "" ? module.service_account.public_key_pem : var.service_account_content.pub_key } output "tls_bootstrap_token_id" { diff --git a/modules/aws/kube-master/variables.tf b/modules/aws/kube-master/variables.tf index 04160444..b037a06c 100644 --- a/modules/aws/kube-master/variables.tf +++ b/modules/aws/kube-master/variables.tf @@ -102,8 +102,8 @@ variable "enable_iam_auth" { default = false } -variable "auth_webhook_config_path" { - description = "The path of webhook config for kube-apiserver." +variable "auth_webhook_kubeconfig_path" { + description = "The path of webhook kubeconfig for kube-apiserver." type = string default = "/etc/kubernetes/config/aws-iam-authenticator/kubeconfig" } @@ -146,6 +146,19 @@ variable "certs_validity_period_hours" { default = 87600 } +variable "service_account_content" { + description = "The service account keypair content for Kubernetes." + type = object({ + pub_key = string + pri_key = string + }) + + default = { + pub_key = "" + pri_key = "" + } +} + // ----------------------------------------- // AWS-related Variables // ----------------------------------------- diff --git a/modules/aws/kube-worker/ignition.tf b/modules/aws/kube-worker/ignition.tf index 3f202f56..15414d3c 100644 --- a/modules/aws/kube-worker/ignition.tf +++ b/modules/aws/kube-worker/ignition.tf @@ -21,7 +21,7 @@ data "aws_s3_bucket_object" "bootstrapping_kubeconfig" { } module "ignition_kubelet" { - source = "git::ssh://git@github.com/getamis/terraform-ignition-kubernetes//modules/kubelet?ref=v0.1.0" + source = "git::ssh://git@github.com/getamis/terraform-ignition-kubernetes//modules/kubelet" binaries = var.binaries containers = var.containers diff --git a/modules/ignitions/aws-iam-auth/main.tf b/modules/ignitions/aws-iam-auth/main.tf deleted file mode 100644 index 6866827c..00000000 --- a/modules/ignitions/aws-iam-auth/main.tf +++ /dev/null @@ -1,33 +0,0 @@ -data "ignition_file" "kubeconfig" { - filesystem = "root" - mode = 420 - path = "${pathexpand(var.kubeconfig_dir_path)}/kubeconfig" - - content { - content = templatefile("${path.module}/templates/kubeconfig.tpl", { - ca = base64encode(var.auth_ca_cert) - server_port = var.server_port - }) - } -} - -data "ignition_file" "iam_auth_cert" { - filesystem = "root" - mode = 420 - path = "${var.state_path}/cert.pem" - - content { - content = var.auth_cert - } -} - -data "ignition_file" "iam_auth_key" { - filesystem = "root" - mode = 420 - path = "${var.state_path}/key.pem" - - content { - content = var.auth_cert_key - } -} - diff --git a/modules/ignitions/aws-iam-auth/outputs.tf b/modules/ignitions/aws-iam-auth/outputs.tf deleted file mode 100644 index 1b8421e7..00000000 --- a/modules/ignitions/aws-iam-auth/outputs.tf +++ /dev/null @@ -1,11 +0,0 @@ -output "files" { - value = [ - data.ignition_file.iam_auth_cert.rendered, - data.ignition_file.iam_auth_key.rendered, - data.ignition_file.kubeconfig.rendered - ] -} - -output "kubeconfig_path" { - value = "${pathexpand(var.kubeconfig_dir_path)}/kubeconfig" -} diff --git a/modules/ignitions/aws-iam-auth/templates/kubeconfig.tpl b/modules/ignitions/aws-iam-auth/templates/kubeconfig.tpl deleted file mode 100644 index cb23c4e9..00000000 --- a/modules/ignitions/aws-iam-auth/templates/kubeconfig.tpl +++ /dev/null @@ -1,17 +0,0 @@ -# clusters refers to the remote service. -clusters: - - name: aws-iam-authenticator - cluster: - certificate-authority-data: ${ca} - server: https://127.0.0.1:${server_port}/authenticate -# users refers to the API Server's webhook configuration -# (we don't need to authenticate the API server). -users: - - name: apiserver -# kubeconfig files require a context. Provide one for the API Server. -current-context: webhook -contexts: -- name: webhook - context: - cluster: aws-iam-authenticator - user: apiserver diff --git a/modules/ignitions/aws-iam-auth/variables.tf b/modules/ignitions/aws-iam-auth/variables.tf deleted file mode 100644 index fdb68d25..00000000 --- a/modules/ignitions/aws-iam-auth/variables.tf +++ /dev/null @@ -1,32 +0,0 @@ -variable "state_path" { - description = "Persisted TLS certificate and keys." - type = string - default = "/var/aws-iam-authenticator" -} - -variable "server_port" { - description = "Localhost port where the server will serve the /authenticate endpoint" - type = number - default = 21362 -} - -variable "kubeconfig_dir_path" { - description = "A path for using iam aws authenticator to authenticate to a Kubernetes cluster." - type = string - default = "/etc/kubernetes/config/aws-iam-authenticator" -} - -variable "auth_ca_cert" { - description = "Certificate for verifying the AWS iam authenticator webhook" - type = string -} - -variable "auth_cert" { - description = "AWS iam authenticator webhook tls cert" - type = string -} - -variable "auth_cert_key" { - description = "AWS iam authenticator webhook tls cert key" - type = string -}