diff --git a/.circleci/config.yml b/.circleci/config.yml index 47d11b7..8875836 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ defaults: &defaults KUBERGRUNT_VERSION: v0.3.8 HELM_VERSION: v2.12.2 MODULE_CI_VERSION: v0.13.12 - TERRAFORM_VERSION: 0.11.11 + TERRAFORM_VERSION: 0.12.1 TERRAGRUNT_VERSION: NONE PACKER_VERSION: NONE GOLANG_VERSION: 1.11.2 diff --git a/README.md b/README.md index ef7eca6..444e80d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![Maintained by Gruntwork.io](https://img.shields.io/badge/maintained%20by-gruntwork.io-%235849a6.svg)](https://gruntwork.io/?ref=repo_terraform_kubernetes_helm) [![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gruntwork-io/terraform-kubernetes-helm.svg?label=latest)](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/latest) +![Terraform Version](https://img.shields.io/badge/tf-%3E%3D0.12.0-blue.svg) # Tiller Module diff --git a/examples/k8s-namespace-with-service-account/main.tf b/examples/k8s-namespace-with-service-account/main.tf index 5176645..f018470 100644 --- a/examples/k8s-namespace-with-service-account/main.tf +++ b/examples/k8s-namespace-with-service-account/main.tf @@ -4,14 +4,18 @@ # ServiceAccounts that are bound to each default role. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +terraform { + required_version = ">= 0.12" +} + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CONFIGURE OUR KUBERNETES CONNECTIONS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ provider "kubernetes" { version = "~> 1.5" - config_context = "${var.kubectl_config_context_name}" - config_path = "${var.kubectl_config_path}" + config_context = var.kubectl_config_context_name + config_path = var.kubectl_config_path } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -24,7 +28,7 @@ module "namespace" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-namespace?ref=v0.0.1" source = "../../modules/k8s-namespace" - name = "${var.name}" + name = var.name } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -38,13 +42,15 @@ module "service_account_access_all" { source = "../../modules/k8s-service-account" name = "${var.name}-admin" - namespace = "${module.namespace.name}" + namespace = module.namespace.name num_rbac_roles = 1 - rbac_roles = [{ - name = "${module.namespace.rbac_access_all_role}" - namespace = "${module.namespace.name}" - }] + rbac_roles = [ + { + name = module.namespace.rbac_access_all_role + namespace = module.namespace.name + }, + ] # How to tag the service account with a label labels = { @@ -59,13 +65,15 @@ module "service_account_access_read_only" { source = "../../modules/k8s-service-account" name = "${var.name}-read-only" - namespace = "${module.namespace.name}" + namespace = module.namespace.name num_rbac_roles = 1 - rbac_roles = [{ - name = "${module.namespace.rbac_access_read_only_role}" - namespace = "${module.namespace.name}" - }] + rbac_roles = [ + { + name = module.namespace.rbac_access_read_only_role + namespace = module.namespace.name + }, + ] # How to tag the service account with a label labels = { diff --git a/examples/k8s-namespace-with-service-account/outputs.tf b/examples/k8s-namespace-with-service-account/outputs.tf index 43000fc..71e367b 100644 --- a/examples/k8s-namespace-with-service-account/outputs.tf +++ b/examples/k8s-namespace-with-service-account/outputs.tf @@ -1,24 +1,24 @@ output "name" { description = "Name of the created namespace" - value = "${module.namespace.name}" + value = module.namespace.name } output "rbac_access_all_role" { description = "The name of the RBAC role that grants admin level permissions on the namespace." - value = "${module.namespace.rbac_access_all_role}" + value = module.namespace.rbac_access_all_role } output "rbac_access_read_only_role" { description = "The name of the RBAC role that grants read only permissions on the namespace." - value = "${module.namespace.rbac_access_read_only_role}" + value = module.namespace.rbac_access_read_only_role } output "service_account_access_all" { description = "The name of the ServiceAccount that has admin level permissions." - value = "${module.service_account_access_all.name}" + value = module.service_account_access_all.name } output "service_account_access_read_only" { description = "The name of the ServiceAccount that has read only level permissions." - value = "${module.service_account_access_read_only.name}" + value = module.service_account_access_read_only.name } diff --git a/examples/k8s-namespace-with-service-account/variables.tf b/examples/k8s-namespace-with-service-account/variables.tf index bb0bc45..7d7b1cf 100644 --- a/examples/k8s-namespace-with-service-account/variables.tf +++ b/examples/k8s-namespace-with-service-account/variables.tf @@ -5,14 +5,17 @@ variable "name" { description = "Name of the namespace to be created" + type = string } variable "kubectl_config_context_name" { description = "The config context to use when authenticating to the Kubernetes cluster. If empty, defaults to the current context specified in the kubeconfig file." + type = string default = "" } variable "kubectl_config_path" { description = "The path to the config file to use for kubectl. If empty, defaults to $HOME/.kube/config" + type = string default = "~/.kube/config" } diff --git a/examples/k8s-tiller-kubergrunt-minikube/main.tf b/examples/k8s-tiller-kubergrunt-minikube/main.tf index f4b9941..29b4a50 100644 --- a/examples/k8s-tiller-kubergrunt-minikube/main.tf +++ b/examples/k8s-tiller-kubergrunt-minikube/main.tf @@ -6,13 +6,17 @@ # - Using kubergrunt to deploy Tiller with TLS management # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +terraform { + required_version = ">= 0.12" +} + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CONFIGURE OUR KUBERNETES CONNECTIONS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ provider "kubernetes" { - config_context = "${var.kubectl_config_context_name}" - config_path = "${var.kubectl_config_path}" + config_context = var.kubectl_config_context_name + config_path = var.kubectl_config_path } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -25,7 +29,7 @@ module "tiller_namespace" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-namespace?ref=v0.3.0" source = "../../modules/k8s-namespace" - name = "${var.tiller_namespace}" + name = var.tiller_namespace } module "resource_namespace" { @@ -34,7 +38,7 @@ module "resource_namespace" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-namespace?ref=v0.3.0" source = "../../modules/k8s-namespace" - name = "${var.resource_namespace}" + name = var.resource_namespace } module "tiller_service_account" { @@ -43,18 +47,18 @@ module "tiller_service_account" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-service-account?ref=v0.3.0" source = "../../modules/k8s-service-account" - name = "${var.service_account_name}" - namespace = "${module.tiller_namespace.name}" + name = var.service_account_name + namespace = module.tiller_namespace.name num_rbac_roles = 2 rbac_roles = [ { - name = "${module.tiller_namespace.rbac_tiller_metadata_access_role}" - namespace = "${module.tiller_namespace.name}" + name = module.tiller_namespace.rbac_tiller_metadata_access_role + namespace = module.tiller_namespace.name }, { - name = "${module.resource_namespace.rbac_tiller_resource_access_role}" - namespace = "${module.resource_namespace.name}" + name = module.resource_namespace.rbac_tiller_resource_access_role + namespace = module.resource_namespace.name }, ] @@ -73,19 +77,19 @@ module "tiller" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-tiller?ref=v0.3.0" source = "../../modules/k8s-tiller" - tiller_service_account_name = "${module.tiller_service_account.name}" - tiller_service_account_token_secret_name = "${module.tiller_service_account.token_secret_name}" - namespace = "${module.tiller_namespace.name}" - tiller_image_version = "${var.tiller_version}" + tiller_service_account_name = module.tiller_service_account.name + tiller_service_account_token_secret_name = module.tiller_service_account.token_secret_name + namespace = module.tiller_namespace.name + tiller_image_version = var.tiller_version tiller_tls_gen_method = "kubergrunt" - tiller_tls_subject = "${var.tls_subject}" - private_key_algorithm = "${var.private_key_algorithm}" - private_key_ecdsa_curve = "${var.private_key_ecdsa_curve}" - private_key_rsa_bits = "${var.private_key_rsa_bits}" + tiller_tls_subject = var.tls_subject + private_key_algorithm = var.private_key_algorithm + private_key_ecdsa_curve = var.private_key_ecdsa_curve + private_key_rsa_bits = var.private_key_rsa_bits - kubectl_config_context_name = "${var.kubectl_config_context_name}" - kubectl_config_path = "${var.kubectl_config_path}" + kubectl_config_context_name = var.kubectl_config_context_name + kubectl_config_path = var.kubectl_config_path } # We use kubergrunt to wait for Tiller to be deployed. Any resources that depend on this can assume Tiller is @@ -93,11 +97,11 @@ module "tiller" { resource "null_resource" "wait_for_tiller" { provisioner "local-exec" { command = <<-EOF - ${lookup(module.require_executables.executables, "kubergrunt")} helm wait-for-tiller ${local.esc_newl} - --tiller-namespace ${module.tiller_namespace.name} ${local.esc_newl} - --tiller-deployment-name ${module.tiller.deployment_name} ${local.esc_newl} - --expected-tiller-version ${var.tiller_version} - EOF + ${module.require_executables.executables["kubergrunt"]} helm wait-for-tiller ${local.esc_newl} + --tiller-namespace ${module.tiller_namespace.name} ${local.esc_newl} + --tiller-deployment-name ${module.tiller.deployment_name} ${local.esc_newl} + --expected-tiller-version ${var.tiller_version} + EOF } } @@ -106,24 +110,24 @@ resource "null_resource" "wait_for_tiller" { # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ resource "null_resource" "grant_helm_access" { - count = "${var.configure_helm}" - depends_on = ["null_resource.wait_for_tiller"] + count = var.configure_helm ? 1 : 0 + depends_on = [null_resource.wait_for_tiller] provisioner "local-exec" { command = <<-EOF - ${lookup(module.require_executables.executables, "kubergrunt")} helm grant ${local.esc_newl} - --tiller-namespace ${module.tiller_namespace.name} ${local.esc_newl} - ${local.kubectl_config_options} ${local.esc_newl} - --tls-subject-json '${jsonencode(var.client_tls_subject)}' ${local.esc_newl} - ${local.configure_args} - - ${lookup(module.require_executables.executables, "kubergrunt")} helm configure ${local.esc_newl} - --helm-home ${local.helm_home_with_default} ${local.esc_newl} - --tiller-namespace ${module.tiller_namespace.name} ${local.esc_newl} - --resource-namespace ${module.resource_namespace.name} ${local.esc_newl} - ${local.kubectl_config_options} ${local.esc_newl} - ${local.configure_args} - EOF + ${module.require_executables.executables["kubergrunt"]} helm grant ${local.esc_newl} + --tiller-namespace ${module.tiller_namespace.name} ${local.esc_newl} + ${local.kubectl_config_options} ${local.esc_newl} + --tls-subject-json '${jsonencode(var.client_tls_subject)}' ${local.esc_newl} + ${local.configure_args} + + ${module.require_executables.executables["kubergrunt"]} helm configure ${local.esc_newl} + --helm-home ${local.helm_home_with_default} ${local.esc_newl} + --tiller-namespace ${module.tiller_namespace.name} ${local.esc_newl} + --resource-namespace ${module.resource_namespace.name} ${local.esc_newl} + ${local.kubectl_config_options} ${local.esc_newl} + ${local.configure_args} + EOF } } @@ -135,24 +139,19 @@ resource "null_resource" "grant_helm_access" { locals { kubectl_config_options = "${var.kubectl_config_context_name != "" ? "--kubectl-context-name ${var.kubectl_config_context_name}" : ""} ${var.kubectl_config_path != "" ? "--kubeconfig ${var.kubectl_config_path}" : ""}" - helm_home_with_default = "${var.helm_home == "" ? pathexpand("~/.helm") : var.helm_home}" + helm_home_with_default = var.helm_home == "" ? pathexpand("~/.helm") : var.helm_home - configure_args = "${ - var.helm_client_rbac_user != "" ? "--rbac-user ${var.helm_client_rbac_user}" - : var.helm_client_rbac_group != "" ? "--rbac-group ${var.helm_client_rbac_group}" - : var.helm_client_rbac_service_account != "" ? "--rbac-service-account ${var.helm_client_rbac_service_account}" - : "" - }" + configure_args = var.helm_client_rbac_user != "" ? "--rbac-user ${var.helm_client_rbac_user}" : var.helm_client_rbac_group != "" ? "--rbac-group ${var.helm_client_rbac_group}" : var.helm_client_rbac_service_account != "" ? "--rbac-service-account ${var.helm_client_rbac_service_account}" : "" - esc_newl = "${module.os.name == "Windows" ? "`" : "\\"}" + esc_newl = module.os.name == "Windows" ? "`" : "\\" } module "os" { - source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/operating-system?ref=v0.0.8" + source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/operating-system?ref=v0.1.0" } module "require_executables" { - source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/require-executable?ref=v0.0.8" + source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/require-executable?ref=v0.1.0" required_executables = ["kubergrunt"] error_message = "The __EXECUTABLE_NAME__ binary is not available in your PATH. Install the binary by following the instructions at https://github.com/gruntwork-io/terraform-kubernetes-helm/blob/master/examples/k8s-tiller-kubergrunt-minikube/README.md#installing-necessary-tools, or update your PATH variable to search where you installed __EXECUTABLE_NAME__." diff --git a/examples/k8s-tiller-kubergrunt-minikube/outputs.tf b/examples/k8s-tiller-kubergrunt-minikube/outputs.tf index 9837767..f839014 100644 --- a/examples/k8s-tiller-kubergrunt-minikube/outputs.tf +++ b/examples/k8s-tiller-kubergrunt-minikube/outputs.tf @@ -1,9 +1,9 @@ output "tiller_namespace" { description = "The name of the namespace that houses Tiller." - value = "${module.tiller_namespace.name}" + value = module.tiller_namespace.name } output "resource_namespace" { description = "The name of the namespace where Tiller will deploy resources into." - value = "${module.resource_namespace.name}" + value = module.resource_namespace.name } diff --git a/examples/k8s-tiller-kubergrunt-minikube/variables.tf b/examples/k8s-tiller-kubergrunt-minikube/variables.tf index 41459d1..3da8530 100644 --- a/examples/k8s-tiller-kubergrunt-minikube/variables.tf +++ b/examples/k8s-tiller-kubergrunt-minikube/variables.tf @@ -5,25 +5,27 @@ variable "tiller_namespace" { description = "The namespace to deploy Tiller into." + type = string } variable "resource_namespace" { description = "The namespace where the Helm chart resources will be deployed into by Tiller." + type = string } variable "service_account_name" { description = "The name of the service account to use for Tiller." + type = string } variable "tls_subject" { description = "The issuer information that contains the identifying information for the Tiller server. Used to generate the TLS certificate keypairs." - type = "map" + type = map(string) default = { common_name = "tiller" org = "Gruntwork" } - # Expects the following keys # - common_name # - org @@ -35,13 +37,12 @@ variable "tls_subject" { variable "client_tls_subject" { description = "The issuer information that contains the identifying information for the helm client of the operator. Used to generate the TLS certificate keypairs." - type = "map" + type = map(string) default = { common_name = "admin" org = "Gruntwork" } - # Expects the following keys # - common_name # - org @@ -60,6 +61,7 @@ variable "client_tls_subject" { variable "tiller_version" { description = "The version of Tiller to deploy." + type = string default = "v2.11.0" } @@ -67,28 +69,33 @@ variable "tiller_version" { variable "private_key_algorithm" { description = "The name of the algorithm to use for private keys. Must be one of: RSA or ECDSA." + type = string default = "ECDSA" } variable "private_key_ecdsa_curve" { description = "The name of the elliptic curve to use. Should only be used if var.private_key_algorithm is ECDSA. Must be one of P224, P256, P384 or P521." + type = string default = "P256" } variable "private_key_rsa_bits" { description = "The size of the generated RSA key in bits. Should only be used if var.private_key_algorithm is RSA." - default = "2048" + type = number + default = 2048 } # Kubectl options variable "kubectl_config_context_name" { description = "The config context to use when authenticating to the Kubernetes cluster. If empty, defaults to the current context specified in the kubeconfig file." + type = string default = "" } variable "kubectl_config_path" { description = "The path to the config file to use for kubectl. If empty, defaults to $HOME/.kube/config" + type = string default = "~/.kube/config" } @@ -96,25 +103,30 @@ variable "kubectl_config_path" { variable "configure_helm" { description = "Whether or not to configure the local helm client to authenticate to the deployed Tiller instance." + type = bool default = true } variable "helm_home" { description = "The path to the home directory for helm that you wish to use for this deployment." + type = string default = "" } variable "helm_client_rbac_user" { description = "If set, will setup the local helm client to authenticate using this RBAC user." + type = string default = "" } variable "helm_client_rbac_group" { description = "If set, will setup the local helm client to authenticate using this RBAC group." + type = string default = "" } variable "helm_client_rbac_service_account" { description = "If set, will setup the local helm client to authenticate using this ServiceAccount. The ServiceAccount should be encoded as NAMESPACE/NAME." + type = string default = "" } diff --git a/main.tf b/main.tf index 2b64546..506f789 100644 --- a/main.tf +++ b/main.tf @@ -6,13 +6,17 @@ # - Using kubergrunt to deploy Tiller with TLS management # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +terraform { + required_version = ">= 0.12" +} + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CONFIGURE OUR KUBERNETES CONNECTIONS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ provider "kubernetes" { - config_context = "${var.kubectl_config_context_name}" - config_path = "${var.kubectl_config_path}" + config_context = var.kubectl_config_context_name + config_path = var.kubectl_config_path } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -25,7 +29,7 @@ module "tiller_namespace" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-namespace?ref=v0.3.0" source = "./modules/k8s-namespace" - name = "${var.tiller_namespace}" + name = var.tiller_namespace } module "resource_namespace" { @@ -34,7 +38,7 @@ module "resource_namespace" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-namespace?ref=v0.3.0" source = "./modules/k8s-namespace" - name = "${var.resource_namespace}" + name = var.resource_namespace } module "tiller_service_account" { @@ -43,18 +47,18 @@ module "tiller_service_account" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-service-account?ref=v0.3.0" source = "./modules/k8s-service-account" - name = "${var.service_account_name}" - namespace = "${module.tiller_namespace.name}" + name = var.service_account_name + namespace = module.tiller_namespace.name num_rbac_roles = 2 rbac_roles = [ { - name = "${module.tiller_namespace.rbac_tiller_metadata_access_role}" - namespace = "${module.tiller_namespace.name}" + name = module.tiller_namespace.rbac_tiller_metadata_access_role + namespace = module.tiller_namespace.name }, { - name = "${module.resource_namespace.rbac_tiller_resource_access_role}" - namespace = "${module.resource_namespace.name}" + name = module.resource_namespace.rbac_tiller_resource_access_role + namespace = module.resource_namespace.name }, ] @@ -73,16 +77,16 @@ module "tiller" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-tiller?ref=v0.3.0" source = "./modules/k8s-tiller" - tiller_service_account_name = "${module.tiller_service_account.name}" - tiller_service_account_token_secret_name = "${module.tiller_service_account.token_secret_name}" - namespace = "${module.tiller_namespace.name}" - tiller_image_version = "${var.tiller_version}" + tiller_service_account_name = module.tiller_service_account.name + tiller_service_account_token_secret_name = module.tiller_service_account.token_secret_name + namespace = module.tiller_namespace.name + tiller_image_version = var.tiller_version tiller_tls_gen_method = "provider" - tiller_tls_subject = "${var.tls_subject}" - private_key_algorithm = "${var.private_key_algorithm}" - private_key_ecdsa_curve = "${var.private_key_ecdsa_curve}" - private_key_rsa_bits = "${var.private_key_rsa_bits}" + tiller_tls_subject = var.tls_subject + private_key_algorithm = var.private_key_algorithm + private_key_ecdsa_curve = var.private_key_ecdsa_curve + private_key_rsa_bits = var.private_key_rsa_bits } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -96,27 +100,22 @@ module "helm_client_tls_certs" { # source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-helm-client-tls-certs?ref=v0.3.1" source = "./modules/k8s-helm-client-tls-certs" - ca_tls_certificate_key_pair_secret_namespace = "${module.tiller.tiller_ca_tls_certificate_key_pair_secret_namespace}" - ca_tls_certificate_key_pair_secret_name = "${module.tiller.tiller_ca_tls_certificate_key_pair_secret_name}" + ca_tls_certificate_key_pair_secret_namespace = module.tiller.tiller_ca_tls_certificate_key_pair_secret_namespace + ca_tls_certificate_key_pair_secret_name = module.tiller.tiller_ca_tls_certificate_key_pair_secret_name - tls_subject = "${var.client_tls_subject}" - tls_certificate_key_pair_secret_namespace = "${module.tiller_namespace.name}" + tls_subject = var.client_tls_subject + tls_certificate_key_pair_secret_namespace = module.tiller_namespace.name # Kubergrunt expects client cert secrets to be stored under this name format tls_certificate_key_pair_secret_name = "tiller-client-${md5(local.rbac_entity_id)}-certs" tls_certificate_key_pair_secret_labels = { - "gruntwork.io/tiller-namespace" = "${module.tiller_namespace.name}" + "gruntwork.io/tiller-namespace" = module.tiller_namespace.name "gruntwork.io/tiller-credentials" = "true" "gruntwork.io/tiller-credentials-type" = "client" } } locals { - rbac_entity_id = "${ - var.grant_helm_client_rbac_user != "" ? var.grant_helm_client_rbac_user - : var.grant_helm_client_rbac_group != "" ? var.grant_helm_client_rbac_group - : var.grant_helm_client_rbac_service_account != "" ? var.grant_helm_client_rbac_service_account - : "" - }" + rbac_entity_id = var.grant_helm_client_rbac_user != "" ? var.grant_helm_client_rbac_user : var.grant_helm_client_rbac_group != "" ? var.grant_helm_client_rbac_group : var.grant_helm_client_rbac_service_account != "" ? var.grant_helm_client_rbac_service_account : "" } diff --git a/modules/k8s-helm-client-tls-certs/main.tf b/modules/k8s-helm-client-tls-certs/main.tf index 333922f..f972761 100644 --- a/modules/k8s-helm-client-tls-certs/main.tf +++ b/modules/k8s-helm-client-tls-certs/main.tf @@ -9,7 +9,7 @@ # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = "~> 0.9" + required_version = ">= 0.12" } # --------------------------------------------------------------------------------------------------------------------- @@ -17,42 +17,46 @@ terraform { # --------------------------------------------------------------------------------------------------------------------- resource "tls_private_key" "cert" { - algorithm = "${var.private_key_algorithm}" - ecdsa_curve = "${var.private_key_ecdsa_curve}" - rsa_bits = "${var.private_key_rsa_bits}" + algorithm = var.private_key_algorithm + ecdsa_curve = var.private_key_ecdsa_curve + rsa_bits = var.private_key_rsa_bits } resource "tls_cert_request" "cert" { - key_algorithm = "${tls_private_key.cert.algorithm}" - private_key_pem = "${tls_private_key.cert.private_key_pem}" + key_algorithm = tls_private_key.cert.algorithm + private_key_pem = tls_private_key.cert.private_key_pem + + dns_names = var.tls_certs_dns_names + ip_addresses = var.tls_certs_ip_addresses + + subject { + common_name = lookup(var.tls_subject, "common_name", null) + organization = lookup(var.tls_subject, "organization", null) + organizational_unit = lookup(var.tls_subject, "organizational_unit", null) + street_address = local.tls_subject_maybe_street_address != "" ? split("\n", local.tls_subject_maybe_street_address) : [] + locality = lookup(var.tls_subject, "locality", null) + province = lookup(var.tls_subject, "province", null) + country = lookup(var.tls_subject, "country", null) + postal_code = lookup(var.tls_subject, "postal_code", null) + serial_number = lookup(var.tls_subject, "serial_number", null) + } +} + +resource "tls_locally_signed_cert" "cert" { + cert_request_pem = tls_cert_request.cert.cert_request_pem - dns_names = ["${var.tls_certs_dns_names}"] - ip_addresses = ["${var.tls_certs_ip_addresses}"] + ca_key_algorithm = tls_private_key.cert.algorithm - subject = ["${var.tls_subject}"] + ca_private_key_pem = data.kubernetes_secret.ca_certs.data["${var.ca_tls_certificate_key_pair_secret_filename_base}.pem"] + + ca_cert_pem = data.kubernetes_secret.ca_certs.data["${var.ca_tls_certificate_key_pair_secret_filename_base}.crt"] + + validity_period_hours = var.validity_period_hours + allowed_uses = var.tls_certs_allowed_uses } -resource "tls_locally_signed_cert" "cert" { - cert_request_pem = "${tls_cert_request.cert.cert_request_pem}" - - ca_key_algorithm = "${tls_private_key.cert.algorithm}" - - ca_private_key_pem = "${ - lookup( - data.kubernetes_secret.ca_certs.data[var.ca_tls_certificate_key_pair_secret_filename_base], - "pem", - ) - }" - - ca_cert_pem = "${ - lookup( - data.kubernetes_secret.ca_certs.data[var.ca_tls_certificate_key_pair_secret_filename_base], - "crt", - ) - }" - - validity_period_hours = "${var.validity_period_hours}" - allowed_uses = ["${var.tls_certs_allowed_uses}"] +locals { + tls_subject_maybe_street_address = lookup(var.tls_subject, "street_address", "") } # --------------------------------------------------------------------------------------------------------------------- @@ -60,28 +64,21 @@ resource "tls_locally_signed_cert" "cert" { # --------------------------------------------------------------------------------------------------------------------- resource "kubernetes_secret" "signed_tls" { - count = "${var.store_in_kubernetes_secret ? 1 : 0}" + count = var.store_in_kubernetes_secret ? 1 : 0 metadata { - namespace = "${var.tls_certificate_key_pair_secret_namespace}" - name = "${var.tls_certificate_key_pair_secret_name}" - labels = "${var.tls_certificate_key_pair_secret_labels}" - annotations = "${var.tls_certificate_key_pair_secret_annotations}" + namespace = var.tls_certificate_key_pair_secret_namespace + name = var.tls_certificate_key_pair_secret_name + labels = var.tls_certificate_key_pair_secret_labels + annotations = var.tls_certificate_key_pair_secret_annotations } - data = "${ - map( - "${var.tls_certificate_key_pair_secret_filename_base}.pem", "${tls_private_key.cert.private_key_pem}", - "${var.tls_certificate_key_pair_secret_filename_base}.pub", "${tls_private_key.cert.public_key_pem}", - "${var.tls_certificate_key_pair_secret_filename_base}.crt", "${tls_locally_signed_cert.cert.cert_pem}", - "${var.ca_tls_certificate_key_pair_secret_filename_base}.crt", "${ - lookup( - data.kubernetes_secret.ca_certs.data[var.ca_tls_certificate_key_pair_secret_filename_base], - "crt", - ) - }", - ) - }" + data = { + "${var.tls_certificate_key_pair_secret_filename_base}.pem" = tls_private_key.cert.private_key_pem + "${var.tls_certificate_key_pair_secret_filename_base}.pub" = tls_private_key.cert.public_key_pem + "${var.tls_certificate_key_pair_secret_filename_base}.crt" = tls_locally_signed_cert.cert.cert_pem + "${var.ca_tls_certificate_key_pair_secret_filename_base}.crt" = data.kubernetes_secret.ca_certs.data["${var.ca_tls_certificate_key_pair_secret_filename_base}.crt"] + } } # --------------------------------------------------------------------------------------------------------------------- @@ -92,7 +89,7 @@ resource "kubernetes_secret" "signed_tls" { data "kubernetes_secret" "ca_certs" { metadata { - name = "${var.ca_tls_certificate_key_pair_secret_name}" - namespace = "${var.ca_tls_certificate_key_pair_secret_namespace}" + name = var.ca_tls_certificate_key_pair_secret_name + namespace = var.ca_tls_certificate_key_pair_secret_namespace } } diff --git a/modules/k8s-helm-client-tls-certs/outputs.tf b/modules/k8s-helm-client-tls-certs/outputs.tf index 3c6a7b0..5999451 100644 --- a/modules/k8s-helm-client-tls-certs/outputs.tf +++ b/modules/k8s-helm-client-tls-certs/outputs.tf @@ -1,40 +1,41 @@ output "tls_certificate_key_pair_private_key_pem" { description = "The private key of the generated TLS certs in PEM format." - value = "${tls_private_key.cert.private_key_pem}" + value = tls_private_key.cert.private_key_pem sensitive = true } output "tls_certificate_key_pair_public_key_pem" { description = "The public key of the generated TLS certs in PEM format." - value = "${tls_private_key.cert.public_key_pem}" + value = tls_private_key.cert.public_key_pem sensitive = true } output "tls_certificate_key_pair_certificate_pem" { description = "The public certificate of the generated TLS certs in PEM format." - value = "${tls_locally_signed_cert.cert.cert_pem}" + value = tls_locally_signed_cert.cert.cert_pem sensitive = true } output "ca_tls_certificate_key_pair_certificate_pem" { description = "The public certificate of the CA TLS certs in PEM format." - value = "${ - lookup( - data.kubernetes_secret.ca_certs.data[var.ca_tls_certificate_key_pair_secret_filename_base], - "crt", - ) - }" + value = data.kubernetes_secret.ca_certs.data["${var.ca_tls_certificate_key_pair_secret_filename_base}.crt"] sensitive = true } output "tls_certificate_key_pair_secret_namespace" { description = "Namespace where the signed TLS certificate key pair is stored." - value = "${element(concat(kubernetes_secret.signed_tls.*.metadata.0.namespace, list("")), 0)}" + value = element( + concat(kubernetes_secret.signed_tls.*.metadata.0.namespace, [""]), + 0, + ) } output "tls_certificate_key_pair_secret_name" { description = "Name of the Secret resource where the signed TLS certificate key pair is stored." - value = "${element(concat(kubernetes_secret.signed_tls.*.metadata.0.name, list("")), 0)}" + value = element( + concat(kubernetes_secret.signed_tls.*.metadata.0.name, [""]), + 0, + ) } diff --git a/modules/k8s-helm-client-tls-certs/variables.tf b/modules/k8s-helm-client-tls-certs/variables.tf index 8edff69..445e4da 100644 --- a/modules/k8s-helm-client-tls-certs/variables.tf +++ b/modules/k8s-helm-client-tls-certs/variables.tf @@ -6,26 +6,31 @@ # TLS certificate information variable "tls_subject" { - description = "The issuer information that contains the identifying information for the signed certificates. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys." - type = "map" + description = "The issuer information that contains the identifying information for the signed certificates. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys. Note that street_address must be a newline separated string as opposed to a list of strings." + # We use an string type here instead of directly specifying the object, to allow certain keys to be optional. + type = map(string) } # Kubernetes Secret information variable "ca_tls_certificate_key_pair_secret_namespace" { description = "Namespace where the CA certificate key pairs are stored." + type = string } variable "ca_tls_certificate_key_pair_secret_name" { description = "Name to use for the Secret resource that stores the CA certificate key pairs." + type = string } variable "tls_certificate_key_pair_secret_namespace" { description = "Namespace where the signed TLS certificate key pairs should be stored." + type = string } variable "tls_certificate_key_pair_secret_name" { description = "Name to use for the Secret resource that stores the signed TLS certificate key pairs." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -37,22 +42,25 @@ variable "tls_certificate_key_pair_secret_name" { variable "private_key_algorithm" { description = "The name of the algorithm to use for private keys. Must be one of: RSA or ECDSA." + type = string default = "ECDSA" } variable "private_key_ecdsa_curve" { description = "The name of the elliptic curve to use. Should only be used if var.private_key_algorithm is ECDSA. Must be one of P224, P256, P384 or P521." + type = string default = "P256" } variable "private_key_rsa_bits" { description = "The size of the generated RSA key in bits. Should only be used if var.private_key_algorithm is RSA." - default = "2048" + type = number + default = 2048 } variable "tls_certs_allowed_uses" { description = "List of keywords from RFC5280 describing a use that is permitted for the issued certificate. For more info and the list of keywords, see https://www.terraform.io/docs/providers/tls/r/self_signed_cert.html#allowed_uses." - type = "list" + type = list(string) default = [ "key_encipherment", @@ -63,18 +71,19 @@ variable "tls_certs_allowed_uses" { variable "tls_certs_dns_names" { description = "List of DNS names for which the certificate will be valid (e.g. tiller, foo.example.com)." - type = "list" + type = list(string) default = [] } variable "tls_certs_ip_addresses" { description = "List of IP addresses for which the certificate will be valid (e.g. 127.0.0.1)." - type = "list" + type = list(string) default = ["127.0.0.1"] } variable "validity_period_hours" { description = "The number of hours after initial issuing that the certificate will become invalid." + type = number # 10 years default = 87660 @@ -84,27 +93,30 @@ variable "validity_period_hours" { variable "store_in_kubernetes_secret" { description = "Whether or not to store the generated TLS certificate key pairs in Kubernetes Secret." + type = bool default = true } variable "ca_tls_certificate_key_pair_secret_filename_base" { description = "Basename used for the TLS certificate files stored in the Secret." + type = string default = "ca" } variable "tls_certificate_key_pair_secret_filename_base" { description = "Basename to use for the signed TLS certificate files stored in the Secret." + type = string default = "client" } variable "tls_certificate_key_pair_secret_labels" { description = "Labels to apply to the Secret resource that stores the signed TLS certificate key pairs." - type = "map" + type = map(string) default = {} } variable "tls_certificate_key_pair_secret_annotations" { description = "Annotations to apply to the Secret resource that stores the signed TLS certificate key pairs." - type = "map" + type = map(string) default = {} } diff --git a/modules/k8s-namespace-roles/main.tf b/modules/k8s-namespace-roles/main.tf index 1bc744d..f828193 100644 --- a/modules/k8s-namespace-roles/main.tf +++ b/modules/k8s-namespace-roles/main.tf @@ -8,7 +8,7 @@ # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = "~> 0.9" + required_version = ">= 0.12" } # --------------------------------------------------------------------------------------------------------------------- @@ -21,7 +21,7 @@ terraform { resource "null_resource" "dependency_getter" { triggers = { - instance = "${join(",", var.dependencies)}" + instance = join(",", var.dependencies) } } @@ -37,14 +37,14 @@ resource "null_resource" "dependency_getter" { # --------------------------------------------------------------------------------------------------------------------- resource "kubernetes_role" "rbac_role_access_all" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { name = "${var.namespace}-access-all" - namespace = "${var.namespace}" - labels = "${var.labels}" - annotations = "${var.annotations}" + namespace = var.namespace + labels = var.labels + annotations = var.annotations } rule { @@ -55,14 +55,14 @@ resource "kubernetes_role" "rbac_role_access_all" { } resource "kubernetes_role" "rbac_role_access_read_only" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { name = "${var.namespace}-access-read-only" - namespace = "${var.namespace}" - labels = "${var.labels}" - annotations = "${var.annotations}" + namespace = var.namespace + labels = var.labels + annotations = var.annotations } rule { @@ -77,14 +77,14 @@ resource "kubernetes_role" "rbac_role_access_read_only" { # See https://docs.helm.sh/using_helm/#example-deploy-tiller-in-a-namespace-restricted-to-deploying-resources-in-another-namespace resource "kubernetes_role" "rbac_tiller_metadata_access" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { name = "${var.namespace}-tiller-metadata-access" - namespace = "${var.namespace}" - labels = "${var.labels}" - annotations = "${var.annotations}" + namespace = var.namespace + labels = var.labels + annotations = var.annotations } rule { @@ -95,14 +95,14 @@ resource "kubernetes_role" "rbac_tiller_metadata_access" { } resource "kubernetes_role" "rbac_tiller_resource_access" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { name = "${var.namespace}-tiller-resource-access" - namespace = "${var.namespace}" - labels = "${var.labels}" - annotations = "${var.annotations}" + namespace = var.namespace + labels = var.labels + annotations = var.annotations } rule { diff --git a/modules/k8s-namespace-roles/outputs.tf b/modules/k8s-namespace-roles/outputs.tf index d036b42..ab91d72 100644 --- a/modules/k8s-namespace-roles/outputs.tf +++ b/modules/k8s-namespace-roles/outputs.tf @@ -1,19 +1,40 @@ output "rbac_access_all_role" { description = "The name of the RBAC role that grants admin level permissions on the namespace." - value = "${element(concat(kubernetes_role.rbac_role_access_all.*.metadata.0.name, list("")), 0)}" + value = element( + concat(kubernetes_role.rbac_role_access_all.*.metadata.0.name, [""]), + 0, + ) } output "rbac_access_read_only_role" { description = "The name of the RBAC role that grants read only permissions on the namespace." - value = "${element(concat(kubernetes_role.rbac_role_access_read_only.*.metadata.0.name, list("")), 0)}" + value = element( + concat( + kubernetes_role.rbac_role_access_read_only.*.metadata.0.name, + [""], + ), + 0, + ) } output "rbac_tiller_metadata_access_role" { description = "The name of the RBAC role that grants minimal permissions for Tiller to manage its metadata. Use this role if Tiller will be deployed into this namespace." - value = "${element(concat(kubernetes_role.rbac_tiller_metadata_access.*.metadata.0.name, list("")), 0)}" + value = element( + concat( + kubernetes_role.rbac_tiller_metadata_access.*.metadata.0.name, + [""], + ), + 0, + ) } output "rbac_tiller_resource_access_role" { description = "The name of the RBAC role that grants minimal permissions for Tiller to manage resources in this namespace." - value = "${element(concat(kubernetes_role.rbac_tiller_resource_access.*.metadata.0.name, list("")), 0)}" + value = element( + concat( + kubernetes_role.rbac_tiller_resource_access.*.metadata.0.name, + [""], + ), + 0, + ) } diff --git a/modules/k8s-namespace-roles/variables.tf b/modules/k8s-namespace-roles/variables.tf index e0af545..fed5310 100644 --- a/modules/k8s-namespace-roles/variables.tf +++ b/modules/k8s-namespace-roles/variables.tf @@ -5,6 +5,7 @@ variable "namespace" { description = "The name of the namespace where the roles should be created." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -14,18 +15,19 @@ variable "namespace" { variable "labels" { description = "Map of string key value pairs that can be used to organize and categorize the roles. See the Kubernetes Reference for more info (https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)." - type = "map" + type = map(string) default = {} } variable "annotations" { description = "Map of string key default pairs that can be used to store arbitrary metadata on the roles. See the Kubernetes Reference for more info (https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)." - type = "map" + type = map(string) default = {} } variable "create_resources" { description = "Set to false to have this module create no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the Namespace roles should be created or not." + type = bool default = true } @@ -43,6 +45,6 @@ variable "create_resources" { variable "dependencies" { description = "Create a dependency between the resources in this module to the interpolated values in this list (and thus the source resources). In other words, the resources in this module will now depend on the resources backing the values in this list such that those resources need to be created before the resources in this module, and the resources in this module need to be destroyed before the resources in the list." - type = "list" + type = list(string) default = [] } diff --git a/modules/k8s-namespace/main.tf b/modules/k8s-namespace/main.tf index 1e6602e..9b597ec 100644 --- a/modules/k8s-namespace/main.tf +++ b/modules/k8s-namespace/main.tf @@ -9,7 +9,7 @@ # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = "~> 0.9" + required_version = ">= 0.12" } # --------------------------------------------------------------------------------------------------------------------- @@ -22,7 +22,7 @@ terraform { resource "null_resource" "dependency_getter" { triggers = { - instance = "${join(",", var.dependencies)}" + instance = join(",", var.dependencies) } } @@ -31,13 +31,13 @@ resource "null_resource" "dependency_getter" { # --------------------------------------------------------------------------------------------------------------------- resource "kubernetes_namespace" "namespace" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { - name = "${var.name}" - labels = "${var.labels}" - annotations = "${var.annotations}" + name = var.name + labels = var.labels + annotations = var.annotations } } @@ -49,10 +49,10 @@ resource "kubernetes_namespace" "namespace" { module "namespace_roles" { source = "../k8s-namespace-roles" - namespace = "${kubernetes_namespace.namespace.id}" - labels = "${var.labels}" - annotations = "${var.annotations}" + namespace = kubernetes_namespace.namespace[0].id + labels = var.labels + annotations = var.annotations - create_resources = "${var.create_resources}" - dependencies = ["${var.dependencies}"] + create_resources = var.create_resources + dependencies = var.dependencies } diff --git a/modules/k8s-namespace/outputs.tf b/modules/k8s-namespace/outputs.tf index a5e9150..d8e2f96 100644 --- a/modules/k8s-namespace/outputs.tf +++ b/modules/k8s-namespace/outputs.tf @@ -1,24 +1,24 @@ output "name" { description = "The name of the created namespace." - value = "${element(concat(kubernetes_namespace.namespace.*.id, list("")), 0)}" + value = element(concat(kubernetes_namespace.namespace.*.id, [""]), 0) } output "rbac_access_all_role" { description = "The name of the RBAC role that grants admin level permissions on the namespace." - value = "${module.namespace_roles.rbac_access_all_role}" + value = module.namespace_roles.rbac_access_all_role } output "rbac_access_read_only_role" { description = "The name of the RBAC role that grants read only permissions on the namespace." - value = "${module.namespace_roles.rbac_access_read_only_role}" + value = module.namespace_roles.rbac_access_read_only_role } output "rbac_tiller_metadata_access_role" { description = "The name of the RBAC role that grants minimal permissions for Tiller to manage its metadata. Use this role if Tiller will be deployed into this namespace." - value = "${module.namespace_roles.rbac_tiller_metadata_access_role}" + value = module.namespace_roles.rbac_tiller_metadata_access_role } output "rbac_tiller_resource_access_role" { description = "The name of the RBAC role that grants minimal permissions for Tiller to manage resources in this namespace." - value = "${module.namespace_roles.rbac_tiller_resource_access_role}" + value = module.namespace_roles.rbac_tiller_resource_access_role } diff --git a/modules/k8s-namespace/variables.tf b/modules/k8s-namespace/variables.tf index 0f456fe..11e14e5 100644 --- a/modules/k8s-namespace/variables.tf +++ b/modules/k8s-namespace/variables.tf @@ -5,6 +5,7 @@ variable "name" { description = "The name of the namespace to be created." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -14,18 +15,19 @@ variable "name" { variable "labels" { description = "Map of string key value pairs that can be used to organize and categorize the namespace and roles. See the Kubernetes Reference for more info (https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)." - type = "map" + type = map(string) default = {} } variable "annotations" { description = "Map of string key default pairs that can be used to store arbitrary metadata on the namespace and roles. See the Kubernetes Reference for more info (https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)." - type = "map" + type = map(string) default = {} } variable "create_resources" { description = "Set to false to have this module create no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the Namespace should be created or not." + type = bool default = true } @@ -43,6 +45,6 @@ variable "create_resources" { variable "dependencies" { description = "Create a dependency between the resources in this module to the interpolated values in this list (and thus the source resources). In other words, the resources in this module will now depend on the resources backing the values in this list such that those resources need to be created before the resources in this module, and the resources in this module need to be destroyed before the resources in the list." - type = "list" + type = list(string) default = [] } diff --git a/modules/k8s-service-account/main.tf b/modules/k8s-service-account/main.tf index ab626e0..3c0802d 100644 --- a/modules/k8s-service-account/main.tf +++ b/modules/k8s-service-account/main.tf @@ -9,7 +9,7 @@ # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = "~> 0.9" + required_version = ">= 0.12" } # --------------------------------------------------------------------------------------------------------------------- @@ -22,7 +22,7 @@ terraform { resource "null_resource" "dependency_getter" { triggers = { - instance = "${join(",", var.dependencies)}" + instance = join(",", var.dependencies) } } @@ -32,17 +32,29 @@ resource "null_resource" "dependency_getter" { resource "kubernetes_service_account" "service_account" { metadata { - name = "${var.name}" - namespace = "${var.namespace}" - labels = "${var.labels}" - annotations = "${var.annotations}" + name = var.name + namespace = var.namespace + labels = var.labels + annotations = var.annotations } - image_pull_secret = "${var.secrets_for_pulling_images}" - secret = "${var.secrets_for_pods}" - automount_service_account_token = "${var.automount_service_account_token}" + dynamic "image_pull_secret" { + for_each = var.secrets_for_pulling_images + content { + name = image_pull_secret.value + } + } + + dynamic "secret" { + for_each = var.secrets_for_pods + content { + name = secret.value + } + } + + automount_service_account_token = var.automount_service_account_token - depends_on = ["null_resource.dependency_getter"] + depends_on = [null_resource.dependency_getter] } # --------------------------------------------------------------------------------------------------------------------- @@ -50,27 +62,27 @@ resource "kubernetes_service_account" "service_account" { # --------------------------------------------------------------------------------------------------------------------- resource "kubernetes_role_binding" "service_account_role_binding" { - count = "${var.num_rbac_roles}" + count = var.num_rbac_roles metadata { - name = "${var.name}-${lookup(var.rbac_roles[count.index], "name")}-role-binding" - namespace = "${lookup(var.rbac_roles[count.index], "namespace")}" - labels = "${var.labels}" - annotations = "${var.annotations}" + name = "${var.name}-${var.rbac_roles[count.index]["name"]}-role-binding" + namespace = var.rbac_roles[count.index]["namespace"] + labels = var.labels + annotations = var.annotations } role_ref { api_group = "rbac.authorization.k8s.io" kind = "Role" - name = "${lookup(var.rbac_roles[count.index], "name")}" + name = var.rbac_roles[count.index]["name"] } subject { api_group = "" kind = "ServiceAccount" - name = "${kubernetes_service_account.service_account.metadata.0.name}" - namespace = "${var.namespace}" + name = kubernetes_service_account.service_account.metadata[0].name + namespace = var.namespace } - depends_on = ["null_resource.dependency_getter"] + depends_on = [null_resource.dependency_getter] } diff --git a/modules/k8s-service-account/outputs.tf b/modules/k8s-service-account/outputs.tf index b46f7a5..9d747d9 100644 --- a/modules/k8s-service-account/outputs.tf +++ b/modules/k8s-service-account/outputs.tf @@ -1,13 +1,14 @@ output "name" { description = "The name of the created service account" - value = "${kubernetes_service_account.service_account.metadata.0.name}" + value = kubernetes_service_account.service_account.metadata[0].name - depends_on = ["kubernetes_role_binding.service_account_role_binding"] + depends_on = [kubernetes_role_binding.service_account_role_binding] } output "token_secret_name" { description = "The name of the secret that holds the default ServiceAccount token that can be used to authenticate to the Kubernetes API." - value = "${kubernetes_service_account.service_account.default_secret_name}" + value = kubernetes_service_account.service_account.default_secret_name - depends_on = ["kubernetes_role_binding.service_account_role_binding"] + depends_on = [kubernetes_role_binding.service_account_role_binding] } + diff --git a/modules/k8s-service-account/variables.tf b/modules/k8s-service-account/variables.tf index 04043c0..cb8bc58 100644 --- a/modules/k8s-service-account/variables.tf +++ b/modules/k8s-service-account/variables.tf @@ -5,10 +5,12 @@ variable "name" { description = "The name of the service account to be created." + type = string } variable "namespace" { description = "The namespace where the service account is created." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -20,12 +22,13 @@ variable "namespace" { # See: https://github.com/hashicorp/terraform/issues/17421 variable "num_rbac_roles" { description = "Number of RBAC roles to bind. This should match the number of items in the list passed to rbac_roles." + type = number default = 0 } variable "rbac_roles" { description = "List of maps representing RBAC roles that should be bound to the service account. If this list is non-empty, you must also pass in num_rbac_roles specifying the number of roles. This expects a list of maps, each with keys name and namespace." - type = "list" + type = list(map(string)) # Example: # rbac_roles = [{ @@ -37,30 +40,31 @@ variable "rbac_roles" { variable "labels" { description = "Map of string key default pairs that can be used to organize and categorize the service account. See the Kubernetes Reference for more info (https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)." - type = "map" + type = map(string) default = {} } variable "annotations" { description = "Map of string key default pairs that can be used to store arbitrary metadata on the service account. See the Kubernetes Reference for more info (https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)." - type = "map" + type = map(string) default = {} } variable "automount_service_account_token" { description = "Whether or not to automatically mount the service account token into the container. This defaults to true." + type = bool default = true } variable "secrets_for_pulling_images" { description = "A list of references to secrets in the same namespace to use for pulling any images in pods that reference this Service Account." - type = "list" + type = list(string) default = [] } variable "secrets_for_pods" { description = "A list of secrets allowed to be used by pods running using this Service Account." - type = "list" + type = list(string) default = [] } @@ -78,6 +82,6 @@ variable "secrets_for_pods" { variable "dependencies" { description = "Create a dependency between the resources in this module to the interpolated values in this list (and thus the source resources). In other words, the resources in this module will now depend on the resources backing the values in this list such that those resources need to be created before the resources in this module, and the resources in this module need to be destroyed before the resources in the list." - type = "list" + type = list(string) default = [] } diff --git a/modules/k8s-tiller-tls-certs/main.tf b/modules/k8s-tiller-tls-certs/main.tf index 30aff99..69d3adb 100644 --- a/modules/k8s-tiller-tls-certs/main.tf +++ b/modules/k8s-tiller-tls-certs/main.tf @@ -10,7 +10,7 @@ # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = "~> 0.9" + required_version = ">= 0.12" } # --------------------------------------------------------------------------------------------------------------------- @@ -23,7 +23,7 @@ terraform { resource "null_resource" "dependency_getter" { triggers = { - instance = "${join(",", var.dependencies)}" + instance = join(",", var.dependencies) } } @@ -32,26 +32,40 @@ resource "null_resource" "dependency_getter" { # --------------------------------------------------------------------------------------------------------------------- resource "tls_private_key" "ca" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] - algorithm = "${var.private_key_algorithm}" - ecdsa_curve = "${var.private_key_ecdsa_curve}" - rsa_bits = "${var.private_key_rsa_bits}" + algorithm = var.private_key_algorithm + ecdsa_curve = var.private_key_ecdsa_curve + rsa_bits = var.private_key_rsa_bits } resource "tls_self_signed_cert" "ca" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] - key_algorithm = "${element(concat(tls_private_key.ca.*.algorithm, list("")), 0)}" - private_key_pem = "${element(concat(tls_private_key.ca.*.private_key_pem, list("")), 0)}" + key_algorithm = element(concat(tls_private_key.ca.*.algorithm, [""]), 0) + private_key_pem = element(concat(tls_private_key.ca.*.private_key_pem, [""]), 0) is_ca_certificate = true - validity_period_hours = "${var.validity_period_hours}" - allowed_uses = ["${var.ca_tls_certs_allowed_uses}"] + validity_period_hours = var.validity_period_hours + allowed_uses = var.ca_tls_certs_allowed_uses + + subject { + common_name = lookup(var.ca_tls_subject, "common_name", null) + organization = lookup(var.ca_tls_subject, "organization", null) + organizational_unit = lookup(var.ca_tls_subject, "organizational_unit", null) + street_address = local.ca_tls_subject_maybe_street_address != "" ? split("\n", local.ca_tls_subject_maybe_street_address) : [] + locality = lookup(var.ca_tls_subject, "locality", null) + province = lookup(var.ca_tls_subject, "province", null) + country = lookup(var.ca_tls_subject, "country", null) + postal_code = lookup(var.ca_tls_subject, "postal_code", null) + serial_number = lookup(var.ca_tls_subject, "serial_number", null) + } +} - subject = ["${var.ca_tls_subject}"] +locals { + ca_tls_subject_maybe_street_address = lookup(var.ca_tls_subject, "street_address", "") } # --------------------------------------------------------------------------------------------------------------------- @@ -59,23 +73,21 @@ resource "tls_self_signed_cert" "ca" { # --------------------------------------------------------------------------------------------------------------------- resource "kubernetes_secret" "ca_secret" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { - namespace = "${var.ca_tls_certificate_key_pair_secret_namespace}" - name = "${var.ca_tls_certificate_key_pair_secret_name}" - labels = "${var.ca_tls_certificate_key_pair_secret_labels}" - annotations = "${var.ca_tls_certificate_key_pair_secret_annotations}" + namespace = var.ca_tls_certificate_key_pair_secret_namespace + name = var.ca_tls_certificate_key_pair_secret_name + labels = var.ca_tls_certificate_key_pair_secret_labels + annotations = var.ca_tls_certificate_key_pair_secret_annotations } - data = "${ - map( - "${var.ca_tls_certificate_key_pair_secret_filename_base}.pem", "${element(concat(tls_private_key.ca.*.private_key_pem, list("")), 0)}", - "${var.ca_tls_certificate_key_pair_secret_filename_base}.pub", "${element(concat(tls_private_key.ca.*.public_key_pem, list("")), 0)}", - "${var.ca_tls_certificate_key_pair_secret_filename_base}.crt", "${element(concat(tls_self_signed_cert.ca.*.cert_pem, list("")), 0)}", - ) - }" + data = { + "${var.ca_tls_certificate_key_pair_secret_filename_base}.pem" = element(concat(tls_private_key.ca.*.private_key_pem, [""]), 0) + "${var.ca_tls_certificate_key_pair_secret_filename_base}.pub" = element(concat(tls_private_key.ca.*.public_key_pem, [""]), 0) + "${var.ca_tls_certificate_key_pair_secret_filename_base}.crt" = element(concat(tls_self_signed_cert.ca.*.cert_pem, [""]), 0) + } } # --------------------------------------------------------------------------------------------------------------------- @@ -83,38 +95,52 @@ resource "kubernetes_secret" "ca_secret" { # --------------------------------------------------------------------------------------------------------------------- resource "tls_private_key" "cert" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] - algorithm = "${var.private_key_algorithm}" - ecdsa_curve = "${var.private_key_ecdsa_curve}" - rsa_bits = "${var.private_key_rsa_bits}" + algorithm = var.private_key_algorithm + ecdsa_curve = var.private_key_ecdsa_curve + rsa_bits = var.private_key_rsa_bits } resource "tls_cert_request" "cert" { - count = "${var.create_resources ? 1 : 0}" - - key_algorithm = "${element(concat(tls_private_key.cert.*.algorithm, list("")), 0)}" - private_key_pem = "${element(concat(tls_private_key.cert.*.private_key_pem, list("")), 0)}" - - dns_names = ["${var.signed_tls_certs_dns_names}"] - ip_addresses = ["${var.signed_tls_certs_ip_addresses}"] - - subject = ["${var.signed_tls_subject}"] + count = var.create_resources ? 1 : 0 + + key_algorithm = element(concat(tls_private_key.cert.*.algorithm, [""]), 0) + private_key_pem = element(concat(tls_private_key.cert.*.private_key_pem, [""]), 0) + + dns_names = var.signed_tls_certs_dns_names + ip_addresses = var.signed_tls_certs_ip_addresses + + subject { + common_name = lookup(var.signed_tls_subject, "common_name", null) + organization = lookup(var.signed_tls_subject, "organization", null) + organizational_unit = lookup(var.signed_tls_subject, "organizational_unit", null) + street_address = local.signed_tls_subject_maybe_street_address != "" ? split("\n", local.signed_tls_subject_maybe_street_address) : [] + locality = lookup(var.signed_tls_subject, "locality", null) + province = lookup(var.signed_tls_subject, "province", null) + country = lookup(var.signed_tls_subject, "country", null) + postal_code = lookup(var.signed_tls_subject, "postal_code", null) + serial_number = lookup(var.signed_tls_subject, "serial_number", null) + } } resource "tls_locally_signed_cert" "cert" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] - cert_request_pem = "${element(concat(tls_cert_request.cert.*.cert_request_pem, list("")), 0)}" + cert_request_pem = element(concat(tls_cert_request.cert.*.cert_request_pem, [""]), 0) - ca_key_algorithm = "${element(concat(tls_private_key.ca.*.algorithm, list("")), 0)}" - ca_private_key_pem = "${element(concat(tls_private_key.ca.*.private_key_pem, list("")), 0)}" - ca_cert_pem = "${element(concat(tls_self_signed_cert.ca.*.cert_pem, list("")), 0)}" + ca_key_algorithm = element(concat(tls_private_key.ca.*.algorithm, [""]), 0) + ca_private_key_pem = element(concat(tls_private_key.ca.*.private_key_pem, [""]), 0) + ca_cert_pem = element(concat(tls_self_signed_cert.ca.*.cert_pem, [""]), 0) - validity_period_hours = "${var.validity_period_hours}" - allowed_uses = ["${var.signed_tls_certs_allowed_uses}"] + validity_period_hours = var.validity_period_hours + allowed_uses = var.signed_tls_certs_allowed_uses +} + +locals { + signed_tls_subject_maybe_street_address = lookup(var.signed_tls_subject, "street_address", "") } # --------------------------------------------------------------------------------------------------------------------- @@ -122,22 +148,20 @@ resource "tls_locally_signed_cert" "cert" { # --------------------------------------------------------------------------------------------------------------------- resource "kubernetes_secret" "signed_tls" { - count = "${var.create_resources ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.create_resources ? 1 : 0 + depends_on = [null_resource.dependency_getter] metadata { - namespace = "${var.signed_tls_certificate_key_pair_secret_namespace}" - name = "${var.signed_tls_certificate_key_pair_secret_name}" - labels = "${var.signed_tls_certificate_key_pair_secret_labels}" - annotations = "${var.signed_tls_certificate_key_pair_secret_annotations}" + namespace = var.signed_tls_certificate_key_pair_secret_namespace + name = var.signed_tls_certificate_key_pair_secret_name + labels = var.signed_tls_certificate_key_pair_secret_labels + annotations = var.signed_tls_certificate_key_pair_secret_annotations } - data = "${ - map( - "${var.signed_tls_certificate_key_pair_secret_filename_base}.pem", "${element(concat(tls_private_key.cert.*.private_key_pem, list("")), 0)}", - "${var.signed_tls_certificate_key_pair_secret_filename_base}.pub", "${element(concat(tls_private_key.cert.*.public_key_pem, list("")), 0)}", - "${var.signed_tls_certificate_key_pair_secret_filename_base}.crt", "${element(concat(tls_locally_signed_cert.cert.*.cert_pem, list("")), 0)}", - "${var.ca_tls_certificate_key_pair_secret_filename_base}.crt", "${element(concat(tls_self_signed_cert.ca.*.cert_pem, list("")), 0)}", - ) - }" + data = { + "${var.signed_tls_certificate_key_pair_secret_filename_base}.pem" = element(concat(tls_private_key.cert.*.private_key_pem, [""]), 0) + "${var.signed_tls_certificate_key_pair_secret_filename_base}.pub" = element(concat(tls_private_key.cert.*.public_key_pem, [""]), 0) + "${var.signed_tls_certificate_key_pair_secret_filename_base}.crt" = element(concat(tls_locally_signed_cert.cert.*.cert_pem, [""]), 0) + "${var.ca_tls_certificate_key_pair_secret_filename_base}.crt" = element(concat(tls_self_signed_cert.ca.*.cert_pem, [""]), 0) + } } diff --git a/modules/k8s-tiller-tls-certs/outputs.tf b/modules/k8s-tiller-tls-certs/outputs.tf index ef60400..1a4038f 100644 --- a/modules/k8s-tiller-tls-certs/outputs.tf +++ b/modules/k8s-tiller-tls-certs/outputs.tf @@ -1,19 +1,32 @@ output "ca_tls_certificate_key_pair_secret_namespace" { description = "Namespace where the CA TLS certificate key pair is stored." - value = "${element(concat(kubernetes_secret.ca_secret.*.metadata.0.namespace, list("")), 0)}" + value = element( + concat(kubernetes_secret.ca_secret.*.metadata.0.namespace, [""]), + 0, + ) } output "ca_tls_certificate_key_pair_secret_name" { description = "Name of the Secret resource where the CA TLS certificate key pair is stored." - value = "${element(concat(kubernetes_secret.ca_secret.*.metadata.0.name, list("")), 0)}" + value = element( + concat(kubernetes_secret.ca_secret.*.metadata.0.name, [""]), + 0, + ) } output "signed_tls_certificate_key_pair_secret_namespace" { description = "Namespace where the signed TLS certificate key pair is stored." - value = "${element(concat(kubernetes_secret.signed_tls.*.metadata.0.namespace, list("")), 0)}" + value = element( + concat(kubernetes_secret.signed_tls.*.metadata.0.namespace, [""]), + 0, + ) } output "signed_tls_certificate_key_pair_secret_name" { description = "Name of the Secret resource where the signed TLS certificate key pair is stored." - value = "${element(concat(kubernetes_secret.signed_tls.*.metadata.0.name, list("")), 0)}" + value = element( + concat(kubernetes_secret.signed_tls.*.metadata.0.name, [""]), + 0, + ) } + diff --git a/modules/k8s-tiller-tls-certs/variables.tf b/modules/k8s-tiller-tls-certs/variables.tf index 353ded4..259ebea 100644 --- a/modules/k8s-tiller-tls-certs/variables.tf +++ b/modules/k8s-tiller-tls-certs/variables.tf @@ -6,31 +6,37 @@ # TLS certificate information variable "ca_tls_subject" { - description = "The issuer information that contains the identifying information for the CA certificates. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys." - type = "map" + description = "The issuer information that contains the identifying information for the CA certificates. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys. Note that street_address must be a newline separated string as opposed to a list of strings." + # We use an string type here instead of directly specifying the object, to allow certain keys to be optional. + type = map(string) } variable "signed_tls_subject" { - description = "The issuer information that contains the identifying information for the signed certificates. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys." - type = "map" + description = "The issuer information that contains the identifying information for the signed certificates. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys. Note that street_address must be a newline separated string as opposed to a list of strings." + # We use an string type here instead of directly specifying the object, to allow certain keys to be optional. + type = map(string) } # Kubernetes Secret information variable "ca_tls_certificate_key_pair_secret_namespace" { description = "Namespace where the CA certificate key pairs should be stored." + type = string } variable "ca_tls_certificate_key_pair_secret_name" { description = "Name to use for the Secret resource that stores the CA certificate key pairs." + type = string } variable "signed_tls_certificate_key_pair_secret_namespace" { description = "Namespace where the signed TLS certificate key pairs should be stored." + type = string } variable "signed_tls_certificate_key_pair_secret_name" { description = "Name to use for the Secret resource that stores the signed TLS certificate key pairs." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -42,22 +48,25 @@ variable "signed_tls_certificate_key_pair_secret_name" { variable "private_key_algorithm" { description = "The name of the algorithm to use for private keys. Must be one of: RSA or ECDSA." + type = string default = "ECDSA" } variable "private_key_ecdsa_curve" { description = "The name of the elliptic curve to use. Should only be used if var.private_key_algorithm is ECDSA. Must be one of P224, P256, P384 or P521." + type = string default = "P256" } variable "private_key_rsa_bits" { description = "The size of the generated RSA key in bits. Should only be used if var.private_key_algorithm is RSA." - default = "2048" + type = number + default = 2048 } variable "ca_tls_certs_allowed_uses" { description = "List of keywords from RFC5280 describing a use that is permitted for the CA certificate. For more info and the list of keywords, see https://www.terraform.io/docs/providers/tls/r/self_signed_cert.html#allowed_uses." - type = "list" + type = list(string) default = [ "cert_signing", @@ -70,7 +79,7 @@ variable "ca_tls_certs_allowed_uses" { variable "signed_tls_certs_allowed_uses" { description = "List of keywords from RFC5280 describing a use that is permitted for the issued certificate. For more info and the list of keywords, see https://www.terraform.io/docs/providers/tls/r/self_signed_cert.html#allowed_uses." - type = "list" + type = list(string) default = [ "key_encipherment", @@ -81,18 +90,19 @@ variable "signed_tls_certs_allowed_uses" { variable "signed_tls_certs_dns_names" { description = "List of DNS names for which the certificate will be valid (e.g. tiller, foo.example.com)." - type = "list" + type = list(string) default = [] } variable "signed_tls_certs_ip_addresses" { description = "List of IP addresses for which the certificate will be valid (e.g. 127.0.0.1)." - type = "list" + type = list(string) default = ["127.0.0.1"] } variable "validity_period_hours" { description = "The number of hours after initial issuing that the certificate will become invalid." + type = number # 10 years default = 87660 @@ -102,40 +112,43 @@ variable "validity_period_hours" { variable "ca_tls_certificate_key_pair_secret_filename_base" { description = "Basename to use for the TLS certificate files stored in the Secret." + type = string default = "ca" } variable "ca_tls_certificate_key_pair_secret_labels" { description = "Labels to apply to the Secret resource that stores the CA certificate key pairs." - type = "map" + type = map(string) default = {} } variable "ca_tls_certificate_key_pair_secret_annotations" { description = "Annotations to apply to the Secret resource that stores the CA certificate key pairs." - type = "map" + type = map(string) default = {} } variable "signed_tls_certificate_key_pair_secret_filename_base" { description = "Basename to use for the signed TLS certificate files stored in the Secret." + type = string default = "tls" } variable "signed_tls_certificate_key_pair_secret_labels" { description = "Labels to apply to the Secret resource that stores the signed TLS certificate key pairs." - type = "map" + type = map(string) default = {} } variable "signed_tls_certificate_key_pair_secret_annotations" { description = "Annotations to apply to the Secret resource that stores the signed TLS certificate key pairs." - type = "map" + type = map(string) default = {} } variable "create_resources" { description = "Set to false to have this module create no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the TLS certs should be created or not." + type = bool default = true } @@ -153,6 +166,6 @@ variable "create_resources" { variable "dependencies" { description = "Create a dependency between the resources in this module to the interpolated values in this list (and thus the source resources). In other words, the resources in this module will now depend on the resources backing the values in this list such that those resources need to be created before the resources in this module, and the resources in this module need to be destroyed before the resources in the list." - type = "list" + type = list(string) default = [] } diff --git a/modules/k8s-tiller/main.tf b/modules/k8s-tiller/main.tf index 4b09662..88966d0 100644 --- a/modules/k8s-tiller/main.tf +++ b/modules/k8s-tiller/main.tf @@ -12,7 +12,7 @@ # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = "~> 0.9" + required_version = ">= 0.12" } # --------------------------------------------------------------------------------------------------------------------- @@ -25,7 +25,7 @@ terraform { resource "null_resource" "dependency_getter" { triggers = { - instance = "${join(",", var.dependencies)}" + instance = join(",", var.dependencies) } } @@ -37,79 +37,72 @@ resource "null_resource" "dependency_getter" { # https://github.com/helm/helm/blob/master/cmd/helm/installer/install.go#L200 resource "kubernetes_deployment" "tiller" { depends_on = [ - "null_resource.dependency_getter", - "null_resource.tls_secret_generated", - "null_resource.tiller_tls_certs", + null_resource.dependency_getter, + null_resource.tls_secret_generated, + null_resource.tiller_tls_certs, ] metadata { - namespace = "${var.namespace}" - name = "${var.deployment_name}" - annotations = "${var.deployment_annotations}" + namespace = var.namespace + name = var.deployment_name + annotations = var.deployment_annotations # The labels app=helm and name=tiller need to be added for helm client to work. - labels = "${merge( - map( - "app", "helm", - "name", "tiller", - ), - var.deployment_labels - )}" + labels = merge( + { + "app" = "helm" + "name" = "tiller" + }, + var.deployment_labels, + ) } spec { - replicas = "${var.deployment_replicas}" + replicas = var.deployment_replicas # Only manage the Tiller pods deployed by this deployment selector { - match_labels { + match_labels = { app = "helm" name = "tiller" - deployment = "${var.deployment_name}" + deployment = var.deployment_name } } template { metadata { - labels { + labels = { app = "helm" name = "tiller" - deployment = "${var.deployment_name}" + deployment = var.deployment_name } } spec { - service_account_name = "${var.tiller_service_account_name}" + service_account_name = var.tiller_service_account_name container { name = "tiller" image = "${var.tiller_image}:${var.tiller_image_version}" - image_pull_policy = "${var.tiller_image_pull_policy}" + image_pull_policy = var.tiller_image_pull_policy command = ["/tiller"] args = [ - # Use Secrets for storing release info, which contain the values.yaml file info. "--storage=secret", - - # Set to only listen on localhost so that it is only available via port-forwarding. The helm client (and terraform - # helm provider) use port-forwarding to communicate with Tiller so this is a safer default. "--listen=localhost:44134", - - # Since the Secret for the TLS certs aren't created by helm init, allow user to override the file names. "--tls-key=${local.tls_certs_mount_path}/${var.tiller_tls_key_file_name}", - "--tls-cert=${local.tls_certs_mount_path}/${var.tiller_tls_cert_file_name}", "--tls-ca-cert=${local.tls_certs_mount_path}/${var.tiller_tls_cacert_file_name}", ] env { name = "TILLER_NAMESPACE" - value = "${var.namespace}" + value = var.namespace } env { name = "TILLER_HISTORY_MAX" - value = "${var.tiller_history_max}" + value = var.tiller_history_max } env { @@ -161,49 +154,44 @@ resource "kubernetes_deployment" "tiller" { # Make sure to mount the ServiceAccount token. volume_mount { - mount_path = "${local.service_account_token_mount_path}" - name = "${var.tiller_service_account_token_secret_name}" + mount_path = local.service_account_token_mount_path + name = var.tiller_service_account_token_secret_name read_only = true } # Mount the TLS certs into the location Tiller expects volume_mount { - mount_path = "${local.tls_certs_mount_path}" - name = "${local.tls_secret_volume_name}" + mount_path = local.tls_certs_mount_path + name = local.tls_secret_volume_name read_only = true } - # end container } # We have to mount the service account token so that Tiller can access the Kubernetes API as the attached # ServiceAccount. volume { - name = "${var.tiller_service_account_token_secret_name}" + name = var.tiller_service_account_token_secret_name secret { - secret_name = "${var.tiller_service_account_token_secret_name}" + secret_name = var.tiller_service_account_token_secret_name } } # Mount the volume for the TLS secrets volume { - name = "${local.tls_secret_volume_name}" + name = local.tls_secret_volume_name secret { - secret_name = "${local.generated_tls_secret_name}" + secret_name = local.generated_tls_secret_name } } - # end template spec } - # end template } - # end spec } - # end deployment } @@ -214,21 +202,21 @@ resource "kubernetes_deployment" "tiller" { # Adapted from Tiller installer in helm client. See: # https://github.com/helm/helm/blob/master/cmd/helm/installer/install.go#L332 resource "kubernetes_service" "tiller" { - depends_on = ["null_resource.dependency_getter"] + depends_on = [null_resource.dependency_getter] metadata { - namespace = "${var.namespace}" - name = "${var.service_name}" - annotations = "${var.service_annotations}" + namespace = var.namespace + name = var.service_name + annotations = var.service_annotations # The labels app=helm and name=tiller need to be added for helm client to work. - labels = "${merge( - map( - "app", "helm", - "name", "tiller", - ), - var.service_labels - )}" + labels = merge( + { + "app" = "helm" + "name" = "tiller" + }, + var.service_labels, + ) } spec { @@ -240,10 +228,10 @@ resource "kubernetes_service" "tiller" { target_port = "tiller" } - selector { + selector = { app = "helm" name = "tiller" - deployment = "${var.deployment_name}" + deployment = var.deployment_name } } } @@ -254,113 +242,116 @@ resource "kubernetes_service" "tiller" { # Generate CA TLS certs resource "null_resource" "tiller_tls_ca_certs" { - count = "${var.tiller_tls_gen_method == "kubergrunt" ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.tiller_tls_gen_method == "kubergrunt" ? 1 : 0 + depends_on = [null_resource.dependency_getter] provisioner "local-exec" { command = <<-EOF - ${lookup(module.require_executables.executables, "kubergrunt", "")} tls gen ${local.esc_newl} - ${local.kubergrunt_auth_params} ${local.esc_newl} - --ca ${local.esc_newl} - --namespace ${var.tiller_tls_ca_cert_secret_namespace} ${local.esc_newl} - --secret-name ${local.tiller_tls_ca_certs_secret_name} ${local.esc_newl} - --secret-label gruntwork.io/tiller-namespace=${var.namespace} ${local.esc_newl} - --secret-label gruntwork.io/tiller-credentials=true ${local.esc_newl} - --secret-label gruntwork.io/tiller-credentials-type=ca ${local.esc_newl} - --tls-subject-json '${jsonencode(local.tiller_tls_ca_certs_subject)}' ${local.esc_newl} - --tls-private-key-algorithm ${var.private_key_algorithm} ${local.esc_newl} - ${local.tls_algorithm_config} - EOF + ${lookup(module.require_executables.executables, "kubergrunt", "")} tls gen ${local.esc_newl} + ${local.kubergrunt_auth_params} ${local.esc_newl} + --ca ${local.esc_newl} + --namespace ${var.tiller_tls_ca_cert_secret_namespace} ${local.esc_newl} + --secret-name ${local.tiller_tls_ca_certs_secret_name} ${local.esc_newl} + --secret-label gruntwork.io/tiller-namespace=${var.namespace} ${local.esc_newl} + --secret-label gruntwork.io/tiller-credentials=true ${local.esc_newl} + --secret-label gruntwork.io/tiller-credentials-type=ca ${local.esc_newl} + --tls-subject-json '${jsonencode(local.tiller_tls_ca_certs_subject)}' ${local.esc_newl} + --tls-private-key-algorithm ${var.private_key_algorithm} ${local.esc_newl} + ${local.tls_algorithm_config} + EOF + # Use environment variables for Kubernetes credentials to avoid leaking into the logs environment = { - KUBECTL_SERVER_ENDPOINT = "${var.kubectl_server_endpoint}" - KUBECTL_CA_DATA = "${var.kubectl_ca_b64_data}" - KUBECTL_TOKEN = "${var.kubectl_token}" + KUBECTL_SERVER_ENDPOINT = var.kubectl_server_endpoint + KUBECTL_CA_DATA = var.kubectl_ca_b64_data + KUBECTL_TOKEN = var.kubectl_token } } provisioner "local-exec" { - when = "destroy" + when = destroy command = <<-EOF - ${var.kubectl_server_endpoint != "" ? "echo \"$KUBECTL_CA_DATA\" > ${path.module}/kubernetes_server_ca.pem" : ""} - ${lookup(module.require_executables.executables, "kubectl", "")} ${local.esc_newl} - ${local.kubectl_auth_params} ${local.esc_newl} - --namespace ${var.tiller_tls_ca_cert_secret_namespace} ${local.esc_newl} - delete secret ${local.tiller_tls_ca_certs_secret_name} - EOF + ${var.kubectl_server_endpoint != "" ? "echo \"$KUBECTL_CA_DATA\" > ${path.module}/kubernetes_server_ca.pem" : ""} + ${lookup(module.require_executables.executables, "kubectl", "")} ${local.esc_newl} + ${local.kubectl_auth_params} ${local.esc_newl} + --namespace ${var.tiller_tls_ca_cert_secret_namespace} ${local.esc_newl} + delete secret ${local.tiller_tls_ca_certs_secret_name} + EOF # Use environment variables for Kubernetes credentials to avoid leaking into the logs environment = { - KUBECTL_SERVER_ENDPOINT = "${var.kubectl_server_endpoint}" - KUBECTL_CA_DATA = "${base64decode(var.kubectl_ca_b64_data)}" - KUBECTL_TOKEN = "${var.kubectl_token}" + KUBECTL_SERVER_ENDPOINT = var.kubectl_server_endpoint + KUBECTL_CA_DATA = base64decode(var.kubectl_ca_b64_data) + KUBECTL_TOKEN = var.kubectl_token } } } # Use generated CA certs to create new certs for server resource "null_resource" "tiller_tls_certs" { - count = "${var.tiller_tls_gen_method == "kubergrunt" ? 1 : 0}" - depends_on = ["null_resource.dependency_getter"] + count = var.tiller_tls_gen_method == "kubergrunt" ? 1 : 0 + depends_on = [null_resource.dependency_getter] - triggers { - ca_cert_create_action = "${element(concat(null_resource.tiller_tls_ca_certs.*.id, list("")), 0)}" + triggers = { + ca_cert_create_action = element(concat(null_resource.tiller_tls_ca_certs.*.id, [""]), 0) } provisioner "local-exec" { command = <<-EOF - ${lookup(module.require_executables.executables, "kubergrunt", "")} tls gen ${local.esc_newl} - ${local.kubergrunt_auth_params} ${local.esc_newl} - --namespace ${var.namespace} ${local.esc_newl} - --ca-secret-name ${local.tiller_tls_ca_certs_secret_name} ${local.esc_newl} - --ca-namespace ${var.tiller_tls_ca_cert_secret_namespace} ${local.esc_newl} - --secret-name ${local.tiller_tls_certs_secret_name} ${local.esc_newl} - --secret-label gruntwork.io/tiller-namespace=${var.namespace} ${local.esc_newl} - --secret-label gruntwork.io/tiller-credentials=true ${local.esc_newl} - --secret-label gruntwork.io/tiller-credentials-type=server ${local.esc_newl} - --tls-subject-json '${jsonencode(var.tiller_tls_subject)}' ${local.esc_newl} - --tls-private-key-algorithm ${var.private_key_algorithm} ${local.esc_newl} - ${local.tls_algorithm_config} - EOF + ${lookup(module.require_executables.executables, "kubergrunt", "")} tls gen ${local.esc_newl} + ${local.kubergrunt_auth_params} ${local.esc_newl} + --namespace ${var.namespace} ${local.esc_newl} + --ca-secret-name ${local.tiller_tls_ca_certs_secret_name} ${local.esc_newl} + --ca-namespace ${var.tiller_tls_ca_cert_secret_namespace} ${local.esc_newl} + --secret-name ${local.tiller_tls_certs_secret_name} ${local.esc_newl} + --secret-label gruntwork.io/tiller-namespace=${var.namespace} ${local.esc_newl} + --secret-label gruntwork.io/tiller-credentials=true ${local.esc_newl} + --secret-label gruntwork.io/tiller-credentials-type=server ${local.esc_newl} + --tls-subject-json '${jsonencode(var.tiller_tls_subject)}' ${local.esc_newl} + --tls-private-key-algorithm ${var.private_key_algorithm} ${local.esc_newl} + ${local.tls_algorithm_config} + EOF + # Use environment variables for Kubernetes credentials to avoid leaking into the logs environment = { - KUBECTL_SERVER_ENDPOINT = "${var.kubectl_server_endpoint}" - KUBECTL_CA_DATA = "${var.kubectl_ca_b64_data}" - KUBECTL_TOKEN = "${var.kubectl_token}" + KUBECTL_SERVER_ENDPOINT = var.kubectl_server_endpoint + KUBECTL_CA_DATA = var.kubectl_ca_b64_data + KUBECTL_TOKEN = var.kubectl_token } } provisioner "local-exec" { - when = "destroy" + when = destroy command = <<-EOF - ${var.kubectl_server_endpoint != "" ? "echo \"$KUBECTL_CA_DATA\" > ${path.module}/kubernetes_server_ca.pem" : ""} - ${lookup(module.require_executables.executables, "kubectl", "")} ${local.esc_newl} - ${local.kubectl_auth_params} ${local.esc_newl} - --namespace ${var.namespace} ${local.esc_newl} - delete secret ${local.tiller_tls_certs_secret_name} - EOF + ${var.kubectl_server_endpoint != "" ? "echo \"$KUBECTL_CA_DATA\" > ${path.module}/kubernetes_server_ca.pem" : ""} + ${lookup(module.require_executables.executables, "kubectl", "")} ${local.esc_newl} + ${local.kubectl_auth_params} ${local.esc_newl} + --namespace ${var.namespace} ${local.esc_newl} + delete secret ${local.tiller_tls_certs_secret_name} + EOF + # Use environment variables for Kubernetes credentials to avoid leaking into the logs environment = { - KUBECTL_SERVER_ENDPOINT = "${var.kubectl_server_endpoint}" - KUBECTL_CA_DATA = "${base64decode(var.kubectl_ca_b64_data)}" - KUBECTL_TOKEN = "${var.kubectl_token}" + KUBECTL_SERVER_ENDPOINT = var.kubectl_server_endpoint + KUBECTL_CA_DATA = base64decode(var.kubectl_ca_b64_data) + KUBECTL_TOKEN = var.kubectl_token } } } module "require_executables" { - source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/require-executable?ref=v0.0.8" + source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/require-executable?ref=v0.1.0" # We have two items in the list here with conditionals, because terraform does not allow list values in conditionals. # TODO: revisit with TF 12 required_executables = [ - "${var.tiller_tls_gen_method == "kubergrunt" ? "kubergrunt" : ""}", - "${var.tiller_tls_gen_method == "kubergrunt" ? "kubectl" : ""}", + var.tiller_tls_gen_method == "kubergrunt" ? "kubergrunt" : "", + var.tiller_tls_gen_method == "kubergrunt" ? "kubectl" : "", ] error_message = "The __EXECUTABLE_NAME__ binary is not available in your PATH. Install the binary by following the instructions at https://github.com/gruntwork-io/terraform-kubernetes-helm/blob/master/modules/k8s-tiller/README.md#generating-with-kubergrunt, or update your PATH variable to search where you installed __EXECUTABLE_NAME__." @@ -373,40 +364,40 @@ module "require_executables" { module "tiller_tls_certs" { source = "../k8s-tiller-tls-certs" - ca_tls_subject = "${local.tiller_tls_ca_certs_subject}" + ca_tls_subject = local.tiller_tls_ca_certs_subject - ca_tls_certificate_key_pair_secret_namespace = "${var.tiller_tls_ca_cert_secret_namespace}" - ca_tls_certificate_key_pair_secret_name = "${local.tiller_tls_ca_certs_secret_name}" + ca_tls_certificate_key_pair_secret_namespace = var.tiller_tls_ca_cert_secret_namespace + ca_tls_certificate_key_pair_secret_name = local.tiller_tls_ca_certs_secret_name ca_tls_certificate_key_pair_secret_labels = { - "gruntwork.io/tiller-namespace" = "${var.namespace}" + "gruntwork.io/tiller-namespace" = var.namespace "gruntwork.io/tiller-credentials" = "true" "gruntwork.io/tiller-credentials-type" = "ca" } - signed_tls_subject = "${var.tiller_tls_subject}" - signed_tls_certificate_key_pair_secret_namespace = "${var.namespace}" - signed_tls_certificate_key_pair_secret_name = "${local.tiller_tls_certs_secret_name}" + signed_tls_subject = var.tiller_tls_subject + signed_tls_certificate_key_pair_secret_namespace = var.namespace + signed_tls_certificate_key_pair_secret_name = local.tiller_tls_certs_secret_name signed_tls_certificate_key_pair_secret_labels = { - "gruntwork.io/tiller-namespace" = "${var.namespace}" + "gruntwork.io/tiller-namespace" = var.namespace "gruntwork.io/tiller-credentials" = "true" "gruntwork.io/tiller-credentials-type" = "server" } - private_key_algorithm = "${var.private_key_algorithm}" - private_key_ecdsa_curve = "${var.private_key_ecdsa_curve}" - private_key_rsa_bits = "${var.private_key_rsa_bits}" + private_key_algorithm = var.private_key_algorithm + private_key_ecdsa_curve = var.private_key_ecdsa_curve + private_key_rsa_bits = var.private_key_rsa_bits - create_resources = "${var.tiller_tls_gen_method == "provider"}" - dependencies = ["${null_resource.dependency_getter.id}"] + create_resources = var.tiller_tls_gen_method == "provider" + dependencies = [null_resource.dependency_getter.id] } resource "null_resource" "tls_secret_generated" { - count = "${var.tiller_tls_gen_method == "provider" ? 1 : 0}" + count = var.tiller_tls_gen_method == "provider" ? 1 : 0 triggers = { - instance = "${module.tiller_tls_certs.signed_tls_certificate_key_pair_secret_name}" + instance = module.tiller_tls_certs.signed_tls_certificate_key_pair_secret_name } } @@ -427,64 +418,38 @@ locals { # --------------------------------------------------------------------------------------------------------------------- locals { - generated_tls_secret_name = "${ - var.tiller_tls_gen_method == "none" - ? var.tiller_tls_secret_name - : local.tiller_tls_certs_secret_name - }" - - tiller_tls_ca_certs_subject = "${ - merge( - var.tiller_tls_subject, - map("common_name", "${lookup(var.tiller_tls_subject, "common_name")} CA"), - ) - }" + generated_tls_secret_name = var.tiller_tls_gen_method == "none" ? var.tiller_tls_secret_name : local.tiller_tls_certs_secret_name + + tiller_tls_ca_certs_subject = merge( + var.tiller_tls_subject, + { + "common_name" = "${var.tiller_tls_subject["common_name"]} CA" + }, + ) tiller_tls_ca_certs_secret_name = "${var.namespace}-namespace-tiller-ca-certs" tiller_tls_certs_secret_name = "${var.namespace}-namespace-tiller-certs" - tls_algorithm_config = "${var.private_key_algorithm == "ECDSA" ? "--tls-private-key-ecdsa-curve ${var.private_key_ecdsa_curve}" : "--tls-private-key-rsa-bits ${var.private_key_rsa_bits}"}" + tls_algorithm_config = var.private_key_algorithm == "ECDSA" ? "--tls-private-key-ecdsa-curve ${var.private_key_ecdsa_curve}" : "--tls-private-key-rsa-bits ${var.private_key_rsa_bits}" kubergrunt_auth_params = <<-EOF - ${ - var.kubectl_server_endpoint != "" - ? "--kubectl-server-endpoint \"$KUBECTL_SERVER_ENDPOINT\" --kubectl-certificate-authority \"$KUBECTL_CA_DATA\" --kubectl-token \"$KUBECTL_TOKEN\"" - : "" - } ${local.esc_newl} - ${ - var.kubectl_config_path != "" - ? "--kubeconfig ${var.kubectl_config_path}" - : "" - } ${local.esc_newl} - ${ - var.kubectl_config_context_name != "" - ? "--kubectl-context-name ${var.kubectl_config_context_name}" - : "" - } ${local.esc_newl} - EOF + ${var.kubectl_server_endpoint != "" ? "--kubectl-server-endpoint \"$KUBECTL_SERVER_ENDPOINT\" --kubectl-certificate-authority \"$KUBECTL_CA_DATA\" --kubectl-token \"$KUBECTL_TOKEN\"" : ""} ${local.esc_newl} + ${var.kubectl_config_path != "" ? "--kubeconfig ${var.kubectl_config_path}" : ""} ${local.esc_newl} + ${var.kubectl_config_context_name != "" ? "--kubectl-context-name ${var.kubectl_config_context_name}" : ""} ${local.esc_newl} + EOF + kubectl_auth_params = <<-EOF - ${ - var.kubectl_server_endpoint != "" - ? "--server \"$KUBECTL_SERVER_ENDPOINT\" --certificate-authority \"${path.module}/kubernetes_server_ca.pem\" --token \"$KUBECTL_TOKEN\"" - : "" - } ${local.esc_newl} - ${ - var.kubectl_config_path != "" - ? "--kubeconfig ${var.kubectl_config_path}" - : "" - } ${local.esc_newl} - ${ - var.kubectl_config_context_name != "" - ? "--context ${var.kubectl_config_context_name}" - : "" - } ${local.esc_newl} - EOF - - esc_newl = "${module.os.name == "Windows" ? "`" : "\\"}" + ${var.kubectl_server_endpoint != "" ? "--server \"$KUBECTL_SERVER_ENDPOINT\" --certificate-authority \"${path.module}/kubernetes_server_ca.pem\" --token \"$KUBECTL_TOKEN\"" : ""} ${local.esc_newl} + ${var.kubectl_config_path != "" ? "--kubeconfig ${var.kubectl_config_path}" : ""} ${local.esc_newl} + ${var.kubectl_config_context_name != "" ? "--context ${var.kubectl_config_context_name}" : ""} ${local.esc_newl} + EOF + + + esc_newl = module.os.name == "Windows" ? "`" : "\\" } # Identify the operating system platform we are executing on module "os" { - source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/operating-system?ref=v0.0.8" + source = "git::https://github.com/gruntwork-io/package-terraform-utilities.git//modules/operating-system?ref=v0.1.0" } diff --git a/modules/k8s-tiller/outputs.tf b/modules/k8s-tiller/outputs.tf index 5ab3537..e23f872 100644 --- a/modules/k8s-tiller/outputs.tf +++ b/modules/k8s-tiller/outputs.tf @@ -1,65 +1,41 @@ output "deployment_name" { description = "The name of the Deployment resource that manages the Tiller Pods." - value = "${kubernetes_deployment.tiller.metadata.0.name}" + value = kubernetes_deployment.tiller.metadata[0].name } output "service_name" { description = "The name of the Service resource that fronts the Tiller Pods." - value = "${kubernetes_service.tiller.metadata.0.name}" + value = kubernetes_service.tiller.metadata[0].name } output "tiller_ca_tls_certificate_key_pair_secret_namespace" { description = "The Namespace where the Tiller TLS CA certs are stored. Set only if var.tiller_tls_gen_method is not \"none\"" - value = "${ - var.tiller_tls_gen_method == "provider" - ? module.tiller_tls_certs.ca_tls_certificate_key_pair_secret_namespace - : var.tiller_tls_gen_method == "kubergrunt" - ? var.tiller_tls_ca_cert_secret_namespace - : "" - }" + value = var.tiller_tls_gen_method == "provider" ? module.tiller_tls_certs.ca_tls_certificate_key_pair_secret_namespace : var.tiller_tls_gen_method == "kubergrunt" ? var.tiller_tls_ca_cert_secret_namespace : "" - depends_on = ["null_resource.tiller_tls_ca_certs"] + depends_on = [null_resource.tiller_tls_ca_certs] } output "tiller_ca_tls_certificate_key_pair_secret_name" { description = "The name of the Secret resource where the Tiller TLS CA certs are stored. Set only if var.tiller_tls_gen_method is not \"none\"" - value = "${ - var.tiller_tls_gen_method == "provider" - ? module.tiller_tls_certs.ca_tls_certificate_key_pair_secret_name - : var.tiller_tls_gen_method == "kubergrunt" - ? local.tiller_tls_ca_certs_secret_name - : "" - }" + value = var.tiller_tls_gen_method == "provider" ? module.tiller_tls_certs.ca_tls_certificate_key_pair_secret_name : var.tiller_tls_gen_method == "kubergrunt" ? local.tiller_tls_ca_certs_secret_name : "" - depends_on = ["null_resource.tiller_tls_ca_certs"] + depends_on = [null_resource.tiller_tls_ca_certs] } output "tiller_tls_certificate_key_pair_secret_namespace" { description = "The Namespace where the Tiller TLS certs are stored. Set only if var.tiller_tls_gen_method is not \"none\"" - value = "${ - var.tiller_tls_gen_method == "provider" - ? module.tiller_tls_certs.signed_tls_certificate_key_pair_secret_namespace - : var.tiller_tls_gen_method == "kubergrunt" - ? var.namespace - : "" - }" + value = var.tiller_tls_gen_method == "provider" ? module.tiller_tls_certs.signed_tls_certificate_key_pair_secret_namespace : var.tiller_tls_gen_method == "kubergrunt" ? var.namespace : "" - depends_on = ["null_resource.tiller_tls_certs"] + depends_on = [null_resource.tiller_tls_certs] } output "tiller_tls_certificate_key_pair_secret_name" { description = "The name of the Secret resource where the Tiller TLS certs are stored. Set only if var.tiller_tls_gen_method is not \"none\"" - value = "${ - var.tiller_tls_gen_method == "provider" - ? module.tiller_tls_certs.signed_tls_certificate_key_pair_secret_name - : var.tiller_tls_gen_method == "kubergrunt" - ? local.tiller_tls_certs_secret_name - : "" - }" + value = var.tiller_tls_gen_method == "provider" ? module.tiller_tls_certs.signed_tls_certificate_key_pair_secret_name : var.tiller_tls_gen_method == "kubergrunt" ? local.tiller_tls_certs_secret_name : "" - depends_on = ["null_resource.tiller_tls_certs"] + depends_on = [null_resource.tiller_tls_certs] } diff --git a/modules/k8s-tiller/variables.tf b/modules/k8s-tiller/variables.tf index 6c4fe12..35ca9d9 100644 --- a/modules/k8s-tiller/variables.tf +++ b/modules/k8s-tiller/variables.tf @@ -5,18 +5,22 @@ variable "namespace" { description = "The name of the Kubernetes Namespace where Tiller should be deployed into." + type = string } variable "tiller_service_account_name" { description = "The name of the Kubernetes ServiceAccount that Tiller should use when authenticating to the Kubernetes API." + type = string } variable "tiller_service_account_token_secret_name" { description = "The name of the Kubernetes Secret that holds the ServiceAccount token." + type = string } variable "tiller_tls_gen_method" { description = "The method in which the TLS certs for Tiller are generated. Must be one of `provider`, `kubergrunt`, or `none`." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -26,86 +30,97 @@ variable "tiller_tls_gen_method" { variable "deployment_name" { description = "The name to use for the Kubernetes Deployment resource. This should be unique to the Namespace if you plan on having multiple Tiller Deployments in a single Namespace." + type = string default = "tiller-deploy" } variable "deployment_labels" { description = "Any labels to attach to the Kubernetes Deployment resource." - type = "map" + type = map(string) default = {} } variable "deployment_annotations" { description = "Any annotations to attach to the Kubernetes Deployment resource." - type = "map" + type = map(string) default = {} } variable "deployment_replicas" { description = "The number of Pods to use for Tiller. 1 should be sufficient for most use cases." + type = number default = 1 } variable "service_name" { description = "The name to use for the Kubernetes Service resource. This should be unique to the Namespace if you plan on having multiple Tiller Deployments in a single Namespace." + type = string default = "tiller-deploy" } variable "service_labels" { description = "Any labels to attach to the Kubernetes Service resource." - type = "map" + type = map(string) default = {} } variable "service_annotations" { description = "Any annotations to attach to the Kubernetes Service resource." - type = "map" + type = map(string) default = {} } variable "tiller_image" { description = "The container image to use for the Tiller Pods." + type = string default = "gcr.io/kubernetes-helm/tiller" } variable "tiller_image_version" { description = "The version of the container image to use for the Tiller Pods." + type = string default = "v2.11.0" } variable "tiller_image_pull_policy" { description = "Policy for pulling the container image used for the Tiller Pods. Use `Always` if the image tag is mutable (e.g latest)" + type = string default = "IfNotPresent" } variable "tiller_history_max" { description = "The maximum number of revisions saved per release. Use 0 for no limit." + type = number default = 0 } variable "tiller_tls_key_file_name" { description = "The file name of the private key file for the server's TLS certificate key pair, as it is available in the Kubernetes Secret for the TLS certificates." + type = string default = "tls.pem" } variable "tiller_tls_cert_file_name" { description = "The file name of the public certificate file for the server's TLS certificate key pair, as it is available in the Kubernetes Secret for the TLS certificates." + type = string default = "tls.crt" } variable "tiller_tls_cacert_file_name" { description = "The file name of the CA certificate file that can be used to validate client side TLS certificates, as it is available in the Kubernetes Secret for the TLS certificates." + type = string default = "ca.crt" } variable "tiller_tls_secret_name" { description = "The name of the Kubernetes Secret that holds the TLS certificate key pair to use for Tiller. Needs to provide the TLS private key, public certificate, and CA certificate to use for verifying client TLS certificate key pairs. Used when var.tiller_tls_gen_method = none." - default = "" + type = string + default = null } variable "tiller_tls_subject" { description = "The issuer information that contains the identifying information for the Tiller server. Used to generate the TLS certificate keypairs. Used when var.tiller_tls_gen_method is not none. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys." - type = "map" + type = map(string) default = { common_name = "tiller" @@ -115,21 +130,25 @@ variable "tiller_tls_subject" { variable "private_key_algorithm" { description = "The name of the algorithm to use for private keys. Must be one of: RSA or ECDSA." + type = string default = "ECDSA" } variable "private_key_ecdsa_curve" { description = "The name of the elliptic curve to use. Should only be used if var.private_key_algorithm is ECDSA. Must be one of P224, P256, P384 or P521." + type = string default = "P256" } variable "private_key_rsa_bits" { description = "The size of the generated RSA key in bits. Should only be used if var.private_key_algorithm is RSA." - default = "2048" + type = number + default = 2048 } variable "tiller_tls_ca_cert_secret_namespace" { description = "The Kubernetes Namespace to use to store the CA certificate key pair." + type = string default = "kube-system" } @@ -137,26 +156,31 @@ variable "tiller_tls_ca_cert_secret_namespace" { variable "kubectl_config_context_name" { description = "The config context to use when authenticating to the Kubernetes cluster. If empty, defaults to the current context specified in the kubeconfig file. Used when var.tiller_tls_gen_method is kubergrunt." + type = string default = "" } variable "kubectl_config_path" { description = "The path to the config file to use for kubectl. If empty, defaults to $HOME/.kube/config. Used when var.tiller_tls_gen_method is kubergrunt." + type = string default = "~/.kube/config" } variable "kubectl_server_endpoint" { description = "The endpoint of the Kubernetes API to access when authenticating to the Kubernetes cluster. Use as an alternative to config and config context. When set, var.kubectl_ca_b64_data and var.kubectl_token must be provided. Used when var.tiller_tls_gen_method is kubergrunt." + type = string default = "" } variable "kubectl_ca_b64_data" { description = "The bas64 encoded certificate authority of the Kubernetes API when authenticating to the Kubernetes cluster. Use as an alternative to config and config context. Must be set when var.kubectl_server_endpoint is not empty. Used when var.tiller_tls_gen_method is kubergrunt." + type = string default = "" } variable "kubectl_token" { description = "The authentication token to use when authenticating to the Kubernetes cluster. Use as an alternative to config and config context. Must be set when var.kubectl_server_endpoint is not empty. Used when var.tiller_tls_gen_method is kubergrunt." + type = string default = "" } @@ -174,6 +198,6 @@ variable "kubectl_token" { variable "dependencies" { description = "Create a dependency between the resources in this module to the interpolated values in this list (and thus the source resources). In other words, the resources in this module will now depend on the resources backing the values in this list such that those resources need to be created before the resources in this module, and the resources in this module need to be destroyed before the resources in the list." - type = "list" + type = list(string) default = [] } diff --git a/outputs.tf b/outputs.tf index 69928e3..53fcf5f 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,27 +1,27 @@ output "tiller_namespace" { description = "The name of the namespace that houses Tiller." - value = "${module.tiller_namespace.name}" + value = module.tiller_namespace.name } output "resource_namespace" { description = "The name of the namespace where Tiller will deploy resources into." - value = "${module.resource_namespace.name}" + value = module.resource_namespace.name } output "helm_client_tls_private_key_pem" { description = "The private key of the TLS certificate key pair to use for the helm client." sensitive = true - value = "${module.helm_client_tls_certs.tls_certificate_key_pair_private_key_pem}" + value = module.helm_client_tls_certs.tls_certificate_key_pair_private_key_pem } output "helm_client_tls_public_cert_pem" { description = "The public certificate of the TLS certificate key pair to use for the helm client." sensitive = true - value = "${module.helm_client_tls_certs.tls_certificate_key_pair_private_key_pem}" + value = module.helm_client_tls_certs.tls_certificate_key_pair_private_key_pem } output "helm_client_tls_ca_cert_pem" { description = "The CA certificate of the TLS certificate key pair to use for the helm client." sensitive = true - value = "${module.helm_client_tls_certs.ca_tls_certificate_key_pair_certificate_pem}" + value = module.helm_client_tls_certs.ca_tls_certificate_key_pair_certificate_pem } diff --git a/test/Gopkg.lock b/test/Gopkg.lock index 2bf97d0..4adc48d 100644 --- a/test/Gopkg.lock +++ b/test/Gopkg.lock @@ -10,7 +10,7 @@ version = "v0.35.1" [[projects]] - digest = "1:17632b96c871d941111bfa7a41e9b18f189a9096f933f6e9058bde0df76f162f" + digest = "1:e18ff6188c07772d4d88beff47a1165ed5b5c1e1d0422a56db598b22d7148a15" name = "github.com/aws/aws-sdk-go" packages = [ "aws", @@ -24,6 +24,7 @@ "aws/credentials/endpointcreds", "aws/credentials/processcreds", "aws/credentials/stscreds", + "aws/crr", "aws/csm", "aws/defaults", "aws/ec2metadata", @@ -51,7 +52,9 @@ "service/acm", "service/autoscaling", "service/cloudwatchlogs", + "service/dynamodb", "service/ec2", + "service/ecs", "service/iam", "service/kms", "service/rds", @@ -60,6 +63,7 @@ "service/s3/s3manager", "service/sns", "service/sqs", + "service/ssm", "service/sts", ] pruneopts = "UT" @@ -86,6 +90,17 @@ revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" version = "v1.1.1" +[[projects]] + branch = "master" + digest = "1:ecdc8e0fe3bc7d549af1c9c36acf3820523b707d6c071b6d0c3860882c6f7b42" + name = "github.com/docker/spdystream" + packages = [ + ".", + "spdy", + ] + pruneopts = "UT" + revision = "6480d4af844c189cf5dd913db24ddd339d3a4f85" + [[projects]] digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda" name = "github.com/ghodss/yaml" @@ -199,8 +214,7 @@ version = "v0.4.2" [[projects]] - branch = "yori-k8s-test-service-account" - digest = "1:9fb55c620f53e7935db233e0b8c5cd75d85ed6fea5189371a5fb08174316e36e" + digest = "1:793635a4fbf9b85ccbde91f2426a8b4319ab13902b95cfb8268d455846110e0b" name = "github.com/gruntwork-io/terratest" packages = [ "modules/aws", @@ -219,7 +233,8 @@ "modules/test-structure", ] pruneopts = "UT" - revision = "4ec522074ed61b5573b0b18d9cdf7580b4c460cf" + revision = "f3916f7a5f58e3fedf603388d3e3e8052d6a47a3" + version = "v0.16.1" [[projects]] digest = "1:8eb1de8112c9924d59bf1d3e5c26f5eaa2bfc2a5fcbb92dc1c2e4546d695f277" @@ -229,6 +244,14 @@ revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4" version = "v0.3.6" +[[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + pruneopts = "UT" + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + [[projects]] digest = "1:bb81097a5b62634f3e9fec1014657855610c82d19b9a40c17612e32651e35dca" name = "github.com/jmespath/go-jmespath" @@ -304,6 +327,14 @@ revision = "be78767b3e392ce45ea73444451022a6fc32ad0d" version = "v1.1.0" +[[projects]] + digest = "1:22799aea8fe96dd5693abdd1eaa14b1b29e3eafbdc7733fa155b3cb556c8a7ae" + name = "github.com/spf13/cobra" + packages = ["."] + pruneopts = "UT" + revision = "67fc4837d267bc9bfd6e47f77783fcc3dffc68de" + version = "v0.0.4" + [[projects]] digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2" name = "github.com/spf13/pflag" @@ -498,7 +529,7 @@ [[projects]] branch = "release-1.12" - digest = "1:aa2ef0c7f4e3fac57a3781b20f2f9d1765aa77f55bbb0cac66188025ce9d61df" + digest = "1:f732c584e8a48a368d35289823fbb450987c5b242f1b96e1cae39774b2c1215c" name = "k8s.io/apimachinery" packages = [ "pkg/api/errors", @@ -524,6 +555,8 @@ "pkg/util/clock", "pkg/util/errors", "pkg/util/framer", + "pkg/util/httpstream", + "pkg/util/httpstream/spdy", "pkg/util/intstr", "pkg/util/json", "pkg/util/naming", @@ -535,6 +568,7 @@ "pkg/util/yaml", "pkg/version", "pkg/watch", + "third_party/forked/golang/netutil", "third_party/forked/golang/reflect", ] pruneopts = "UT" @@ -542,7 +576,7 @@ [[projects]] branch = "release-9.0" - digest = "1:fe891a0c96f0cb506f824b24b5516198b51a4f2a089931c82177a88501b6f709" + digest = "1:a92af87ab3cdd5289ba3b0b44c3e62051ba532ebb5b4ee3f6da7adf9e1a64169" name = "k8s.io/client-go" packages = [ "discovery", @@ -594,8 +628,10 @@ "tools/clientcmd/api/latest", "tools/clientcmd/api/v1", "tools/metrics", + "tools/portforward", "tools/reference", "transport", + "transport/spdy", "util/cert", "util/connrotation", "util/flowcontrol", @@ -606,6 +642,14 @@ pruneopts = "UT" revision = "832c4d89038dd351f988d3d6164617e96af47d00" +[[projects]] + digest = "1:7379e806daf6d6589f35f06200eecfe72abbb3c528e5a5900f92ed827c422e6b" + name = "k8s.io/kubernetes" + packages = ["pkg/kubectl/generate"] + pruneopts = "UT" + revision = "66049e3b21efe110454d67df4fa62b08ea79a19b" + version = "v1.14.2" + [solve-meta] analyzer-name = "dep" analyzer-version = 1 @@ -616,7 +660,6 @@ "github.com/gruntwork-io/terratest/modules/shell", "github.com/gruntwork-io/terratest/modules/terraform", "github.com/gruntwork-io/terratest/modules/test-structure", - "github.com/mitchellh/go-homedir", "github.com/stretchr/testify/assert", "github.com/stretchr/testify/require", "k8s.io/api/authorization/v1", diff --git a/test/Gopkg.toml b/test/Gopkg.toml index e2a77ad..fbf62f7 100644 --- a/test/Gopkg.toml +++ b/test/Gopkg.toml @@ -27,7 +27,7 @@ [[constraint]] name = "github.com/gruntwork-io/terratest" - version = "0.13.24" + version = "0.16.0" [prune] go-tests = true diff --git a/variables.tf b/variables.tf index 54453e5..7efc75a 100644 --- a/variables.tf +++ b/variables.tf @@ -5,19 +5,22 @@ variable "tiller_namespace" { description = "The namespace to deploy Tiller into." + type = string } variable "resource_namespace" { description = "The namespace where the Helm chart resources will be deployed into by Tiller." + type = string } variable "service_account_name" { description = "The name of the service account to use for Tiller." + type = string } variable "tls_subject" { description = "The issuer information that contains the identifying information for the Tiller server. Used to generate the TLS certificate keypairs. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys." - type = "map" + type = map(any) default = { common_name = "tiller" @@ -27,7 +30,7 @@ variable "tls_subject" { variable "client_tls_subject" { description = "The issuer information that contains the identifying information for the helm client of the operator. Used to generate the TLS certificate keypairs. See https://www.terraform.io/docs/providers/tls/r/cert_request.html#common_name for a list of expected keys." - type = "map" + type = map(any) default = { common_name = "admin" @@ -44,6 +47,7 @@ variable "client_tls_subject" { variable "tiller_version" { description = "The version of Tiller to deploy." + type = string default = "v2.11.0" } @@ -51,28 +55,33 @@ variable "tiller_version" { variable "private_key_algorithm" { description = "The name of the algorithm to use for private keys. Must be one of: RSA or ECDSA." + type = string default = "ECDSA" } variable "private_key_ecdsa_curve" { description = "The name of the elliptic curve to use. Should only be used if var.private_key_algorithm is ECDSA. Must be one of P224, P256, P384 or P521." + type = string default = "P256" } variable "private_key_rsa_bits" { description = "The size of the generated RSA key in bits. Should only be used if var.private_key_algorithm is RSA." - default = "2048" + type = number + default = 2048 } # Kubectl options variable "kubectl_config_context_name" { description = "The config context to use when authenticating to the Kubernetes cluster. If empty, defaults to the current context specified in the kubeconfig file." + type = string default = "" } variable "kubectl_config_path" { description = "The path to the config file to use for kubectl. If empty, defaults to $HOME/.kube/config" + type = string default = "~/.kube/config" } @@ -80,15 +89,18 @@ variable "kubectl_config_path" { variable "grant_helm_client_rbac_user" { description = "If set, will generate client side TLS certs for this RBAC user." + type = string default = "" } variable "grant_helm_client_rbac_group" { description = "If set, will generate client side TLS certs for this RBAC group." + type = string default = "" } variable "grant_helm_client_rbac_service_account" { description = "If set, will generate client side TLS certs for this ServiceAccount. The ServiceAccount should be encoded as NAMESPACE/NAME." + type = string default = "" }