diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81e6bae --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/.terraform +**/*.tfstate \ No newline at end of file diff --git a/step0-tfstate/output.tf b/step0-tfstate/output.tf new file mode 100644 index 0000000..6ac5944 --- /dev/null +++ b/step0-tfstate/output.tf @@ -0,0 +1,13 @@ +output "storage_account_name" { + value = "${azurerm_storage_account.stg.name}" +} + +output "container" { + value = "${azurerm_storage_container.tfstate.name}" +} + +output "access_key" { + sensitive = true + value = "${azurerm_storage_account.stg.primary_access_key}" +} + diff --git a/step0-tfstate/storage.tf b/step0-tfstate/storage.tf new file mode 100644 index 0000000..199704d --- /dev/null +++ b/step0-tfstate/storage.tf @@ -0,0 +1,37 @@ +resource "azurerm_resource_group" "rg" { + name = "AKS-TFSTATE-DEV" + location = "southeastasia" +} + +resource "random_string" "stg" { + length = 17 + upper = false + special = false +} + + +locals { + + # must start with a letter + stg_name = "tfstate${random_string.stg.result}" +} + + +resource "azurerm_storage_account" "stg" { + name = "${local.stg_name}" + resource_group_name = "${azurerm_resource_group.rg.name}" + location = "${azurerm_resource_group.rg.location}" + account_tier = "Standard" + account_replication_type = "RAGRS" + + tags = { + environment = "DEV" + } +} + +resource "azurerm_storage_container" "tfstate" { + name = "tfstate" + resource_group_name = "${azurerm_resource_group.rg.name}" + storage_account_name = "${azurerm_storage_account.stg.name}" + container_access_type = "private" +} \ No newline at end of file diff --git a/step1-aks/deploy.sh b/step1-aks/deploy.sh new file mode 100755 index 0000000..06e337d --- /dev/null +++ b/step1-aks/deploy.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# To run the deployment: +# ./deploy.sh ../step0-tfstate/terraform.tfstate [plan|apply] + +# capture the current path +current_path=$(pwd) +tfstate_path=$1 +tf_command=$2 + +cd "${tfstate_path}" +storage_account_name=$(terraform output storage_account_name) +echo ${storage_account_name} +access_key=$(terraform output access_key) +container=$(terraform output container) +tf_name="aks.tfstate" + +cd "${current_path}" +pwd + +terraform init \ + -backend=true \ + -lock=false \ + -backend-config storage_account_name=${storage_account_name} \ + -backend-config container_name=${container} \ + -backend-config access_key=${access_key} \ + -backend-config key=${tf_name} + +terraform ${tf_command} \ No newline at end of file diff --git a/step1-aks/dev.auto.tfvars b/step1-aks/dev.auto.tfvars new file mode 100644 index 0000000..9baed83 --- /dev/null +++ b/step1-aks/dev.auto.tfvars @@ -0,0 +1,129 @@ + +aks_service_principal { + primary { + user_msi = "msi-clusterdev01pri" # Max 24 char including prefix (prefix 4 + 1) + name = "aks-clusterdev01pri" + end_date = "2020-01-01T01:02:03Z" # To be refactored to Date + Duration + } + secondary { + user_msi = "msi-clusterdev01sec" # Max 24 char including prefix (prefix 4 + 1) + name = "aks-clusterdev01sec" + end_date = "2020-01-01T01:02:03Z" # To be refactored to Date + Duration + } +} + +location_map { + "primary" = "southeastasia" + "secondary" = "eastasia" +} + +# Key is lexically sorted - adding after a deployment can cause the deployed resources to be deleted and recreated +resource_groups { + "networking" = "AKS-CLUSTER1-NETWORKING" + "identity" = "AKS-CLUSTER1-IDENTITY" + "aks" = "AKS-CLUSTER1-AKS" + "appgateway" = "AKS-CLUSTER1-APPGW" + "bastion" = "AKS-CLUSTER1-BASTION" +} + +waf_configuration_map { + primary { + gateway_name = "app-gw01-sg" + sku_name = "WAF_V2" + sku_tier = "WAF_V2" + capacity_sku = 1 + pip_sku = "Standard" + pip_allocation = "Static" + firewall_mode = "Prevention" + rule_set_type = "OWASP" + rule_set_version = "3.0" + waf_enabled = true + frontend_port = 80 + backend_port = 80 + backend_protocol = "Http" + request_timeout = 5 # in seconds + cookie_based_affinity = "Enabled" + request_routing_rule_rule_type = "Basic" + } + secondary { + gateway_name = "app-gw01-hk" + sku_name = "WAF_Medium" + sku_tier = "WAF" + capacity_sku = 1 + pip_sku = "Basic" + pip_allocation = "Dynamic" + firewall_mode = "Prevention" + rule_set_type = "OWASP" + rule_set_version = "3.0" + waf_enabled = true + frontend_port = 80 + backend_port = 80 + backend_protocol = "Http" + request_timeout = 5 # in seconds + cookie_based_affinity = "Enabled" + request_routing_rule_rule_type = "Basic" + } +} + +aks_map { + primary { + aks_name = "aks-cluster1-sg" + aks_version = "1.12.7" + vm_user_name = "aks-king" + aks_agent_count = "1" + aks_agent_vm_size = "Standard_DS4_v2" + aks_agent_os_disk_size = "32" + aks_dns_service_ip = "10.30.0.132" + aks_docker_bridge_cidr = "172.17.0.1/16" + aks_service_cidr = "10.30.0.128/25" + } + secondary { + aks_name = "aks-cluster1-hk" + aks_version = "1.12.7" + vm_user_name = "aks-king" + aks_agent_count = "1" + aks_agent_vm_size = "Standard_DS4_v2" + aks_agent_os_disk_size = "32" + aks_dns_service_ip = "10.31.0.132" + aks_docker_bridge_cidr = "172.17.0.1/16" + aks_service_cidr = "10.31.0.128/25" + } +} + +subnets { + primary { + "0_kubernetes" = "aks-cluster1" + "1_applicationGateway" = "appgw-aks-cluster1" + "2_bastion" = "bastion1" + } + secondary { + "0_kubernetes" = "aks-cluster1" + "1_applicationGateway" = "appgw-aks-cluster1" + "2_bastion" = "bastion1" + } + +} + +vnet { + primary { + name = "vnet-aks" + address_space = "10.30.0.0/16" + aks-cluster1 = "10.30.0.0/25" + appgw-aks-cluster1 = "10.30.254.0/24" + bastion1 = "10.30.253.0/24" + } + secondary { + name = "vnet-aks-hk" + address_space = "10.31.0.0/16" + aks-cluster1 = "10.31.0.0/25" + appgw-aks-cluster1 = "10.31.254.0/24" + bastion1 = "10.31.253.0/24" + } +} + +dns_zone { + name = "thedemo.biz" + zone_type = "Public" +} + +analytics_workspace_name = "aks" \ No newline at end of file diff --git a/step1-aks/ingress.yaml b/step1-aks/ingress.yaml new file mode 100644 index 0000000..9b39886 --- /dev/null +++ b/step1-aks/ingress.yaml @@ -0,0 +1,15 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: helloworld + annotations: + kubernetes.io/ingress.class: nginx +spec: + rules: + - host: helloworld.alw6e85l6k816dme7oawdycsud7uyca5.internal + http: + paths: + - path: / + backend: + serviceName: hello-world + servicePort: 80 \ No newline at end of file diff --git a/step1-aks/init.tf b/step1-aks/init.tf new file mode 100644 index 0000000..8f59f6d --- /dev/null +++ b/step1-aks/init.tf @@ -0,0 +1,17 @@ + +provider "azurerm" { + version = "~>1.25" +} + +terraform { + backend "azurerm" {} +} + + +# Used to make sure delete / re-create generate brand new names and reduce risk of being throttled during dev activities +resource "random_string" "prefix" { + length = 4 + special = false + upper = false + number = false +} \ No newline at end of file diff --git a/step1-aks/main.tf b/step1-aks/main.tf new file mode 100644 index 0000000..267a4d8 --- /dev/null +++ b/step1-aks/main.tf @@ -0,0 +1,57 @@ +# Create the resource groups to host the blueprint +module "resource_group" { + source = "modules/resource_group" + + prefix = "${random_string.prefix.result}" + resource_groups = "${var.resource_groups}" + location = "${var.location_map["primary"]}" +} + +# Create the Azure Monitor workspace +module "monitoring_workspace" { + source = "modules/log_analytics" + + prefix = "${random_string.prefix.result}" + name = "${var.analytics_workspace_name}" + resource_group_name = "${module.resource_group.names["aks"]}" +} + +# Register the Azure dns service to an existing domain name +module "azure_dns" { + source = "modules/azure_dns" + + resource_group_name = "${module.resource_group.names["networking"]}" + dns_zone = "${var.dns_zone}" +} + +module "aks_primary" { + source = "modules/blueprint_aks" + + prefix = "${random_string.prefix.result}" + suffix = "sg" + resource_group_names = "${module.resource_group.names}" + log_analytics_workspace_id = "${module.monitoring_workspace.id}" + aks_map = "${var.aks_map["primary"]}" + dns_zone = "${var.dns_zone}" # to be replaced by output variable + location = "${var.location_map["primary"]}" + vnet = "${var.vnet["primary"]}" + subnets = "${var.subnets["primary"]}" + waf_configuration_map = "${var.waf_configuration_map["primary"]}" + aks_service_principal = "${var.aks_service_principal["primary"]}" +} + +module "aks_secondary" { + source = "modules/blueprint_aks" + + prefix = "${random_string.prefix.result}" + suffix = "hk" + resource_group_names = "${module.resource_group.names}" + log_analytics_workspace_id = "${module.monitoring_workspace.id}" + aks_map = "${var.aks_map["secondary"]}" + dns_zone = "${var.dns_zone}" # to be replaced by output variable + location = "${var.location_map["secondary"]}" + vnet = "${var.vnet["secondary"]}" + subnets = "${var.subnets["secondary"]}" + waf_configuration_map = "${var.waf_configuration_map["secondary"]}" + aks_service_principal = "${var.aks_service_principal["secondary"]}" +} \ No newline at end of file diff --git a/step1-aks/modules/aks/cluster.tf b/step1-aks/modules/aks/cluster.tf new file mode 100644 index 0000000..eebbb94 --- /dev/null +++ b/step1-aks/modules/aks/cluster.tf @@ -0,0 +1,67 @@ +resource "random_string" "dns_prefix" { + length = 44 + upper = false + special = true + override_special = "-" +} + +locals { + dns_prefix = "a${random_string.dns_prefix.result}" +} + + +resource "azurerm_kubernetes_cluster" "k8s" { + + depends_on = [ + "azurerm_role_assignment.ra1", + "azurerm_role_assignment.ra2" + ] + + name = "${var.prefix}-${var.aks_map["aks_name"]}" + resource_group_name = "${data.azurerm_resource_group.rg.name}" + location = "${var.location}" + dns_prefix = "${local.dns_prefix}" + kubernetes_version = "${var.aks_map["aks_version"]}" + + linux_profile { + admin_username = "${var.aks_map["vm_user_name"]}" + + ssh_key { + key_data = "${var.public_ssh_key_openssh}" + } + } + + addon_profile { + http_application_routing { + enabled = false + } + + oms_agent { + enabled = true + log_analytics_workspace_id = "${var.log_analytics_workspace_id}" + } + } + + agent_pool_profile { + name = "agentpool" + count = "${var.aks_map["aks_agent_count"]}" + vm_size = "${var.aks_map["aks_agent_vm_size"]}" + os_type = "Linux" + os_disk_size_gb = "${var.aks_map["aks_agent_os_disk_size"]}" + vnet_subnet_id = "${var.subnets_map["${var.aks_subnet_name}"]}" + + } + + service_principal { + client_id = "${var.service_principal_map["app_id"]}" + client_secret = "${var.service_principal_map["client_secret"]}" + } + + network_profile { + network_plugin = "azure" + dns_service_ip = "${var.aks_map["aks_dns_service_ip"]}" + docker_bridge_cidr = "${var.aks_map["aks_docker_bridge_cidr"]}" + service_cidr = "${var.aks_map["aks_service_cidr"]}" + } + +} \ No newline at end of file diff --git a/step1-aks/modules/aks/hello_world.tf b/step1-aks/modules/aks/hello_world.tf new file mode 100644 index 0000000..8ac5cf8 --- /dev/null +++ b/step1-aks/modules/aks/hello_world.tf @@ -0,0 +1,43 @@ +# # https://medium.com/devopslinks/creating-an-azure-kubernetes-service-cluster-with-custom-vnet-helm-and-https-ingress-controller-400d0a3c101 +# # https://github.com/Azure/application-gateway-kubernetes-ingress +# # https://github.com/fbeltrao/aks-letsencrypt/blob/master/install-nginx-ingress.md + +# data "helm_repository" "azure_samples" { +# depends_on = ["azurerm_kubernetes_cluster.k8s"] + +# name = "azure-samples" +# url = "https://azure-samples.github.io/helm-charts/" +# } + +# resource "helm_release" "hello_world" { +# name = "hello-world" +# chart = "azure-samples/aks-helloworld" +# force_update = true + +# set { +# name = "serviceName" +# value = "hello-world" +# } + +# values = [<> ~/.ssh/config&&echo \" IdentityFile ~/.ssh/${azurerm_public_ip.bastion_pip.fqdn}.private\n\" >> ~/.ssh/config&&echo \" StrictHostKeyChecking no\n\" >> ~/.ssh/config" +} \ No newline at end of file diff --git a/step1-aks/modules/blueprint_aks/blueprint_aks.tf b/step1-aks/modules/blueprint_aks/blueprint_aks.tf new file mode 100644 index 0000000..1767021 --- /dev/null +++ b/step1-aks/modules/blueprint_aks/blueprint_aks.tf @@ -0,0 +1,88 @@ +## Blueprint: AKS with Application Gateway as ingress controller +# reference: https://github.com/Azure/application-gateway-kubernetes-ingress + + + + + +# Create service principal for the AKS cluster +module "aks_service_principal" { + source = "../service_principal" + + prefix = "${var.prefix}" + name = "${var.aks_service_principal["name"]}" + end_date = "${var.aks_service_principal["end_date"]}" +} + +# Create the user assigned identity +module "user_msi" { + source = "../user_identity" + + prefix = "${var.prefix}" + resource_group_name = "${var.resource_group_names["identity"]}" + name = "${var.aks_service_principal["user_msi"]}" +} + +# Generate the ssh keys +module "aks_ssh_keys" { + source = "../ssh_key" +} + +# Create the network environment +module "vnet_and_subnets" { + source = "../networking" + + location = "${var.location}" + resource_group_name = "${var.resource_group_names["networking"]}" + prefix = "${var.prefix}" + vnet = "${var.vnet}" + subnets = "${var.subnets}" + +} + + + +module "application_gateway" { + source = "../application_gateway" + + prefix = "${var.prefix}" + resource_group_name = "${var.resource_group_names["appgateway"]}" + location = "${var.location}" + vnet_id = "${module.vnet_and_subnets.vnet_id}" + subnet_name = "${var.subnets["1_applicationGateway"]}" + waf_configuration_map = "${var.waf_configuration_map}" + internal_ip_ingress = "${module.aks_cluster.nginx-ingress_loadbalancer_ip}" +} + + +# Managed Kubernetes Cluster +module "aks_cluster" { + source = "../aks" + + prefix = "${var.prefix}" + location = "${var.location}" + resource_group_name = "${var.resource_group_names["aks"]}" + vnet_resource_group_name = "${var.resource_group_names["networking"]}" + public_ssh_key_openssh = "${module.aks_ssh_keys.public_key_openssh}" + service_principal_map = "${module.aks_service_principal.service_principal_map}" + user_msi_map = "${module.user_msi.map}" + virtual_network_name = "${var.vnet["name"]}" + subnets_map = "${module.vnet_and_subnets.subnet_map}" + aks_subnet_name = "${var.subnets["0_kubernetes"]}" + appgw_subnet_name = "${var.subnets["1_applicationGateway"]}" + aks_map = "${var.aks_map}" + log_analytics_workspace_id = "${var.log_analytics_workspace_id}" + default_dns_name = "${var.dns_zone["name"]}" +} + +module "bastion" { + source = "../bastion" + + prefix = "${var.prefix}" + default_location = "${var.location}" + computer_name = "bastion-${var.suffix}" + vm_size = "Standard_F2s_v2" + subnets_map = "${module.vnet_and_subnets.subnet_map}" + subnet_name = "${var.subnets["2_bastion"]}" + resource_group_name = "${var.resource_group_names["bastion"]}" +} \ No newline at end of file diff --git a/step1-aks/modules/blueprint_aks/save_ssh.tf b/step1-aks/modules/blueprint_aks/save_ssh.tf new file mode 100755 index 0000000..59ff840 --- /dev/null +++ b/step1-aks/modules/blueprint_aks/save_ssh.tf @@ -0,0 +1,32 @@ +# resource "null_resource" "save_ssh_key" { + +# provisioner "local-exec" { +# command = "${local.arg_save_ssh_key}" +# } + +# triggers = { +# content = "${module.arg_save_ssh_key.private_key_pem}" +# arg = "${local.arg_save_ssh_key}" +# } +# } + +# locals { +# arg_save_ssh_key = "cat > ~/.ssh/${azurerm_public_ip.bastion_pip.fqdn}.private <> ~/.ssh/config&&echo \" IdentityFile ~/.ssh/${azurerm_public_ip.bastion_pip.fqdn}.private\n\" >> ~/.ssh/config&&echo \" StrictHostKeyChecking no\n\" >> ~/.ssh/config" +# } \ No newline at end of file diff --git a/step1-aks/modules/blueprint_aks/variables.tf b/step1-aks/modules/blueprint_aks/variables.tf new file mode 100644 index 0000000..e2c8e8b --- /dev/null +++ b/step1-aks/modules/blueprint_aks/variables.tf @@ -0,0 +1,46 @@ +variable "aks_service_principal" { + description = "Map of name and end_date of the azure AD application" + type = "map" +} + +variable "location" { + description = "Location to create the resources" +} + +variable "subnets" { + type = "map" +} + +variable "vnet" { + type = "map" +} + +variable "resource_group_names" { + type = "map" +} + +variable "waf_configuration_map" { + description = "Map of the waf configuration" + type = "map" +} + +variable "aks_map" { + type = "map" +} + +variable "dns_zone" { + type = "map" +} + +variable "log_analytics_workspace_id" { + +} + +variable "prefix" { + +} + +variable "suffix" { + +} + diff --git a/step1-aks/modules/log_analytics/main.tf b/step1-aks/modules/log_analytics/main.tf new file mode 100644 index 0000000..9ecf175 --- /dev/null +++ b/step1-aks/modules/log_analytics/main.tf @@ -0,0 +1,23 @@ +data "azurerm_resource_group" "rg" { + name = "${var.resource_group_name}" +} + +resource "azurerm_log_analytics_workspace" "log" { + name = "${var.prefix}-${var.name}" + location = "${data.azurerm_resource_group.rg.location}" + resource_group_name = "${var.resource_group_name}" + sku = "PerGB2018" +} + +resource "azurerm_log_analytics_solution" "container_insights" { + solution_name = "ContainerInsights" + location = "${data.azurerm_resource_group.rg.location}" + resource_group_name = "${var.resource_group_name}" + workspace_resource_id = "${azurerm_log_analytics_workspace.log.id}" + workspace_name = "${azurerm_log_analytics_workspace.log.name}" + + plan { + publisher = "Microsoft" + product = "OMSGallery/ContainerInsights" + } +} \ No newline at end of file diff --git a/step1-aks/modules/log_analytics/output.tf b/step1-aks/modules/log_analytics/output.tf new file mode 100644 index 0000000..c8139e4 --- /dev/null +++ b/step1-aks/modules/log_analytics/output.tf @@ -0,0 +1,3 @@ +output "id" { + value = "${azurerm_log_analytics_workspace.log.id}" +} diff --git a/step1-aks/modules/log_analytics/variables.tf b/step1-aks/modules/log_analytics/variables.tf new file mode 100644 index 0000000..3fd106a --- /dev/null +++ b/step1-aks/modules/log_analytics/variables.tf @@ -0,0 +1,13 @@ +variable "resource_group_name" { + +} + +variable "prefix" { + +} + +variable "name" { + +} + + diff --git a/step1-aks/modules/networking/main.tf b/step1-aks/modules/networking/main.tf new file mode 100644 index 0000000..fd2c3b1 --- /dev/null +++ b/step1-aks/modules/networking/main.tf @@ -0,0 +1,3 @@ +data "azurerm_resource_group" "rg" { + name = "${var.resource_group_name}" +} \ No newline at end of file diff --git a/step1-aks/modules/networking/networking.tf b/step1-aks/modules/networking/networking.tf new file mode 100644 index 0000000..e25f00b --- /dev/null +++ b/step1-aks/modules/networking/networking.tf @@ -0,0 +1,22 @@ + + + +resource "azurerm_virtual_network" "vnet" { + name = "${var.vnet["name"]}" + resource_group_name = "${data.azurerm_resource_group.rg.name}" + location = "${var.location}" + address_space = ["${var.vnet["address_space"]}"] +} + +locals { + subnet_list = "${keys(var.subnets)}" +} + +resource "azurerm_subnet" "subnets" { + count = "${length(var.subnets)}" + name = "${var.subnets[element(local.subnet_list, count.index)]}" + resource_group_name = "${data.azurerm_resource_group.rg.name}" + virtual_network_name = "${azurerm_virtual_network.vnet.name}" + address_prefix = "${lookup(var.vnet, var.subnets[element(local.subnet_list, count.index)])}" +} + diff --git a/step1-aks/modules/networking/output.tf b/step1-aks/modules/networking/output.tf new file mode 100644 index 0000000..5174108 --- /dev/null +++ b/step1-aks/modules/networking/output.tf @@ -0,0 +1,10 @@ + +output "subnet_map" { + value = "${ + "${zipmap(azurerm_subnet.subnets.*.name,azurerm_subnet.subnets.*.id)}" + }" +} + +output "vnet_id" { + value = "${azurerm_virtual_network.vnet.id}" +} \ No newline at end of file diff --git a/step1-aks/modules/networking/variables.tf b/step1-aks/modules/networking/variables.tf new file mode 100644 index 0000000..9a72756 --- /dev/null +++ b/step1-aks/modules/networking/variables.tf @@ -0,0 +1,21 @@ + +variable "prefix" { + +} + +variable "resource_group_name" { + +} + + +variable "subnets" { + type = "map" +} + +variable "vnet" { + type = "map" +} + +variable "location" { + +} diff --git a/step1-aks/modules/resource_group/main.tf b/step1-aks/modules/resource_group/main.tf new file mode 100644 index 0000000..bc2603e --- /dev/null +++ b/step1-aks/modules/resource_group/main.tf @@ -0,0 +1,12 @@ +locals { + rg_list = "${keys(var.resource_groups)}" +} + + + +resource "azurerm_resource_group" "rg" { + count = "${length(local.rg_list)}" + + name = "${var.prefix}-${var.resource_groups[element(local.rg_list, count.index)]}" + location = "${var.location}" +} diff --git a/step1-aks/modules/resource_group/output.tf b/step1-aks/modules/resource_group/output.tf new file mode 100644 index 0000000..702ad5f --- /dev/null +++ b/step1-aks/modules/resource_group/output.tf @@ -0,0 +1,7 @@ +output "names" { + depends_on = ["azurerm_resource_group.rg.*"] + + value = "${ + "${zipmap(local.rg_list,azurerm_resource_group.rg.*.name)}" + }" +} diff --git a/step1-aks/modules/resource_group/variables.tf b/step1-aks/modules/resource_group/variables.tf new file mode 100644 index 0000000..5108756 --- /dev/null +++ b/step1-aks/modules/resource_group/variables.tf @@ -0,0 +1,11 @@ +variable "resource_groups" { + type = "map" +} + +variable "location" { + +} + +variable "prefix" { + +} diff --git a/step1-aks/modules/service_principal/main.tf b/step1-aks/modules/service_principal/main.tf new file mode 100644 index 0000000..a566d56 --- /dev/null +++ b/step1-aks/modules/service_principal/main.tf @@ -0,0 +1,19 @@ +resource "azuread_application" "app" { + name = "${var.prefix}-${var.name}" +} + +resource "azuread_service_principal" "sp" { + application_id = "${azuread_application.app.application_id}" +} + +resource "random_string" "pwd" { + length = 70 + upper = true + special = true +} + +resource "azuread_service_principal_password" "pwd" { + service_principal_id = "${azuread_service_principal.sp.id}" + value = "${random_string.pwd.result}" + end_date = "${var.end_date}" +} \ No newline at end of file diff --git a/step1-aks/modules/service_principal/output.tf b/step1-aks/modules/service_principal/output.tf new file mode 100644 index 0000000..7b7ea03 --- /dev/null +++ b/step1-aks/modules/service_principal/output.tf @@ -0,0 +1,9 @@ +output "service_principal_map" { + value = "${ + map( + "app_id", "${azuread_application.app.application_id}", + "object_id", "${azuread_service_principal.sp.id}", + "client_secret", "${random_string.pwd.result}" + ) + }" +} diff --git a/step1-aks/modules/service_principal/variables.tf b/step1-aks/modules/service_principal/variables.tf new file mode 100644 index 0000000..87869e5 --- /dev/null +++ b/step1-aks/modules/service_principal/variables.tf @@ -0,0 +1,11 @@ +variable "end_date" { + description = "Define the end date time in the format '2020-01-01T01:02:03Z' " +} + +variable "name" { + description = "Name of the Azure AD Application name" +} + +variable "prefix" { + +} \ No newline at end of file diff --git a/step1-aks/modules/ssh_key/main.tf b/step1-aks/modules/ssh_key/main.tf new file mode 100644 index 0000000..17707ef --- /dev/null +++ b/step1-aks/modules/ssh_key/main.tf @@ -0,0 +1,6 @@ +resource "tls_private_key" "ssh" { + algorithm = "RSA" + rsa_bits = 4096 +} + + diff --git a/step1-aks/modules/ssh_key/output.tf b/step1-aks/modules/ssh_key/output.tf new file mode 100644 index 0000000..e9abb90 --- /dev/null +++ b/step1-aks/modules/ssh_key/output.tf @@ -0,0 +1,12 @@ +output "public_key_openssh" { + value = "${tls_private_key.ssh.public_key_openssh}" +} + +output "public_key_pem" { + value = "${tls_private_key.ssh.public_key_pem}" +} + + +output "private_key_pem" { + value = "${tls_private_key.ssh.private_key_pem}" +} diff --git a/step1-aks/modules/user_identity/main.tf b/step1-aks/modules/user_identity/main.tf new file mode 100644 index 0000000..d978a05 --- /dev/null +++ b/step1-aks/modules/user_identity/main.tf @@ -0,0 +1,10 @@ +data "azurerm_resource_group" "rg" { + name = "${var.resource_group_name}" +} + +resource "azurerm_user_assigned_identity" "msi" { + resource_group_name = "${data.azurerm_resource_group.rg.name}" + location = "${data.azurerm_resource_group.rg.location}" + + name = "${var.prefix}-${var.name}" +} \ No newline at end of file diff --git a/step1-aks/modules/user_identity/output.tf b/step1-aks/modules/user_identity/output.tf new file mode 100644 index 0000000..77724ca --- /dev/null +++ b/step1-aks/modules/user_identity/output.tf @@ -0,0 +1,9 @@ +output "map" { + value = "${ + map( + "id", "${azurerm_user_assigned_identity.msi.id}", + "principal_id", "${azurerm_user_assigned_identity.msi.principal_id}", + "client_id", "${azurerm_user_assigned_identity.msi.client_id}" + ) + }" +} diff --git a/step1-aks/modules/user_identity/variables.tf b/step1-aks/modules/user_identity/variables.tf new file mode 100644 index 0000000..3b8173f --- /dev/null +++ b/step1-aks/modules/user_identity/variables.tf @@ -0,0 +1,12 @@ + +variable "prefix" { + +} + +variable "resource_group_name" { + +} + +variable "name" { + +} diff --git a/step1-aks/variables.tf b/step1-aks/variables.tf new file mode 100644 index 0000000..794ffad --- /dev/null +++ b/step1-aks/variables.tf @@ -0,0 +1,42 @@ +variable "aks_service_principal" { + description = "Map of name and end_date of the azure AD application" + type = "map" +} + +variable "location_map" { + description = "Default location to create the resources" + type = "map" + default = { + primary = "southeastasia" + secondary = "eastasia" + } +} + +variable "subnets" { + type = "map" +} + +variable "vnet" { + type = "map" +} + +variable "resource_groups" { + type = "map" +} + +variable "waf_configuration_map" { + description = "Map of the waf configuration" + type = "map" +} + +variable "aks_map" { + type = "map" +} + +variable "dns_zone" { + type = "map" +} + +variable "analytics_workspace_name" { + +} diff --git a/step2-app/demo-app.tf b/step2-app/demo-app.tf new file mode 100755 index 0000000..e69de29 diff --git a/step2-app/demo.yaml b/step2-app/demo.yaml new file mode 100644 index 0000000..c3e81c3 --- /dev/null +++ b/step2-app/demo.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - image: nginx:1.15.5 + name: mypod + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 250m + memory: 256Mi + volumeMounts: + - name: azure + mountPath: /mnt/azure + volumes: + - name: azure + azureFile: + secretName: azure-secret + shareName: aks + readOnly: false +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: azurefile +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteMany + azureFile: + secretName: azure-secret + shareName: azurefile + readOnly: false + mountOptions: + - dir_mode=0755 + - file_mode=0755 + - uid=1000 + - gid=1000 diff --git a/step2-app/deploy.sh b/step2-app/deploy.sh new file mode 100755 index 0000000..5e125ae --- /dev/null +++ b/step2-app/deploy.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# To run the deployment: +# ./deploy.sh ../step0-tfstate/terraform.tfstate [plan|apply] + +# capture the current path +current_path=$(pwd) +tfstate_path=$1 +tf_command=$2 + +cd "${tfstate_path}" +storage_account_name=$(terraform output storage_account_name) +echo ${storage_account_name} +access_key=$(terraform output access_key) +container=$(terraform output container) +tf_name="aks.tfstate" + +cd "${current_path}" +pwd + +terraform init \ + -backend=true \ + -lock=false \ + -backend-config storage_account_name=${storage_account_name} \ + -backend-config container_name=${container} \ + -backend-config access_key=${access_key} \ + -backend-config key=${tf_name} + +terraform ${tf_command} -refresh=true \ No newline at end of file