From ed3e6a4a54abec2c98ec51620431edc0048a1ca8 Mon Sep 17 00:00:00 2001 From: Justin Travis Date: Mon, 16 Aug 2021 21:13:49 -0400 Subject: [PATCH] KASM-1827 OCI Terraform projects --- README.md | 6 +- oci/single_server/README.md | 55 ++++++ oci/single_server/authorized_keys | 1 + oci/single_server/deployment.tf | 30 ++++ oci/single_server/kasm_ssl.crt | 1 + oci/single_server/kasm_ssl.key | 1 + oci/single_server/module/dns.tf | 12 ++ oci/single_server/module/instance.tf | 49 ++++++ oci/single_server/module/main.tf | 8 + oci/single_server/module/security_list.tf | 42 +++++ .../module/userdata/bootstrap.sh | 25 +++ oci/single_server/module/variables.tf | 94 +++++++++++ oci/single_server/module/vcn.tf | 43 +++++ oci/single_server/oci-private-key.pem | 1 + oci/standard/README.md | 55 ++++++ oci/standard/authorized_keys | 1 + oci/standard/deployment.tf | 29 ++++ oci/standard/kasm_ssl.crt | 1 + oci/standard/kasm_ssl.key | 1 + oci/standard/module/agent.tf | 44 +++++ oci/standard/module/db.tf | 48 ++++++ oci/standard/module/dns.tf | 12 ++ oci/standard/module/load_balancer.tf | 66 ++++++++ oci/standard/module/main.tf | 8 + oci/standard/module/security_lists.tf | 101 ++++++++++++ oci/standard/module/subnet.tf | 48 ++++++ .../module/userdata/agent_bootstrap.sh | 21 +++ oci/standard/module/userdata/db_bootstrap.sh | 21 +++ .../module/userdata/webapp_bootstrap.sh | 30 ++++ oci/standard/module/variables.tf | 156 ++++++++++++++++++ oci/standard/module/vcn.tf | 38 +++++ oci/standard/module/webapp.tf | 48 ++++++ oci/standard/oci-private-key.pem | 1 + 33 files changed, 1096 insertions(+), 1 deletion(-) create mode 100644 oci/single_server/README.md create mode 100644 oci/single_server/authorized_keys create mode 100644 oci/single_server/deployment.tf create mode 100644 oci/single_server/kasm_ssl.crt create mode 100644 oci/single_server/kasm_ssl.key create mode 100644 oci/single_server/module/dns.tf create mode 100644 oci/single_server/module/instance.tf create mode 100644 oci/single_server/module/main.tf create mode 100644 oci/single_server/module/security_list.tf create mode 100644 oci/single_server/module/userdata/bootstrap.sh create mode 100644 oci/single_server/module/variables.tf create mode 100644 oci/single_server/module/vcn.tf create mode 100644 oci/single_server/oci-private-key.pem create mode 100644 oci/standard/README.md create mode 100644 oci/standard/authorized_keys create mode 100644 oci/standard/deployment.tf create mode 100644 oci/standard/kasm_ssl.crt create mode 100644 oci/standard/kasm_ssl.key create mode 100644 oci/standard/module/agent.tf create mode 100644 oci/standard/module/db.tf create mode 100644 oci/standard/module/dns.tf create mode 100644 oci/standard/module/load_balancer.tf create mode 100644 oci/standard/module/main.tf create mode 100644 oci/standard/module/security_lists.tf create mode 100644 oci/standard/module/subnet.tf create mode 100644 oci/standard/module/userdata/agent_bootstrap.sh create mode 100644 oci/standard/module/userdata/db_bootstrap.sh create mode 100644 oci/standard/module/userdata/webapp_bootstrap.sh create mode 100644 oci/standard/module/variables.tf create mode 100644 oci/standard/module/vcn.tf create mode 100644 oci/standard/module/webapp.tf create mode 100644 oci/standard/oci-private-key.pem diff --git a/README.md b/README.md index 5a0c823..0593fa6 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,8 @@ Administators should review the projects and add additional customizations and s # AWS - [Multi-Server Single Region](aws/standard/README.md) -- [Multi-Region](aws/multi_region/README.md) \ No newline at end of file +- [Multi-Region](aws/multi_region/README.md) + +# Oracle Cloud +- [Single Server](oci/single_server/README.md) +- [Multi-Server Single Region](oci/standard/README.md) diff --git a/oci/single_server/README.md b/oci/single_server/README.md new file mode 100644 index 0000000..5470b33 --- /dev/null +++ b/oci/single_server/README.md @@ -0,0 +1,55 @@ +# OPC Single Server +This project will deploy Kasm Workspaces in a single-server deployment in OCI. + + +![Diagram][Image_Diagram] + +[Image_Diagram]: https://f.hubspotusercontent30.net/hubfs/5856039/terraform/diagrams/oci-single-server.png "Diagram" + + + + +# Pre-Configuration +Consider creating a new Compartment for the Kasm Workspaces deployment. + +### DNS Zone +In OCI create a public DNS zone that matches the desired domain name for the deployment. e.g `kasm.contoso.com`. + +### API Keys +Create an administative user the OCI console that will be used for the terraform deployment. Add the user to the +**Administrators** Group. Generate an API Key for the user. The API Key Fingerprint will be used as a variable +in the deployment configuration. Save the private key to the local directory replacing `oci-private-key.pem`. + +### SSH Authorized Keys +The project will install an SSH key(s) inside the OCI compute instance(s). Update `authorized_keys` in this directory +with the desired SSH public keys. + +### SSL Certificate +Create an SSL certificate that matches the desired domain for the deployment. e.g (kasm.contoso.com). Place the pem encoded +cert and key in this directory overwriting `kasm_ssl.crt` and `kasm_ssl.key`. + + + +# Terraform Configuration + +1. Initialize the project + + terraform init + +2. Open `deployment.tf` and update the variables. The variable definitions and descriptions +can be found in `module/variables.tf` + + +3. Verify the configuration + + terraform plan + +4. Deploy + + terraform deploy + + +5. Login to the Deployment as an Admin via the domain defined e.g `https://kasm.contoso.com` . Single server installs +download all workspaces images during the install process so it may take ~15 minutes for the server to fully come online. + + diff --git a/oci/single_server/authorized_keys b/oci/single_server/authorized_keys new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/single_server/authorized_keys @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/single_server/deployment.tf b/oci/single_server/deployment.tf new file mode 100644 index 0000000..c3440a4 --- /dev/null +++ b/oci/single_server/deployment.tf @@ -0,0 +1,30 @@ +module "kasm" { + source = "./module" + + oci_domain_name = "kasm.contoso.com" + project_name = "contoso" + + tenancy_ocid = "" + user_ocid = "" + compartment_ocid = "" + + fingerprint = "" + private_key_path = "./oci-private-key.pem" + + ssh_authorized_keys = "./authorized_keys" + kasm_ssl_crt_path = "./kasm_ssl.crt" + kasm_ssl_key_path = "./kasm_ssl.key" + + region = "us-ashburn-1" + instance_image_ocid = "ocid1.image.oc1.iad.aaaaaaaafg6lg7dejwjebjqontwzyvutgf6qs5awyze6fgoiqepyj5qkvcuq" + instance_shape = "VM.Standard.E4.Flex" + instance_ocpus = 2 + shape_memory_in_gb = 4 + instance_boot_size_gb = 60 + + kasm_build_url = "https://kasm-static-content.s3.amazonaws.com/kasm_release_1.9.0.077388.tar.gz" + user_password = "changeme" + admin_password = "changeme" + allow_ssh_cidr = "0.0.0.0/0" + allow_web_cidr = "0.0.0.0/0" +} \ No newline at end of file diff --git a/oci/single_server/kasm_ssl.crt b/oci/single_server/kasm_ssl.crt new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/single_server/kasm_ssl.crt @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/single_server/kasm_ssl.key b/oci/single_server/kasm_ssl.key new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/single_server/kasm_ssl.key @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/single_server/module/dns.tf b/oci/single_server/module/dns.tf new file mode 100644 index 0000000..f49066f --- /dev/null +++ b/oci/single_server/module/dns.tf @@ -0,0 +1,12 @@ +resource "oci_dns_rrset" "kasm_a_record" { + domain = var.oci_domain_name + rtype = "A" + zone_name_or_id = var.oci_domain_name + compartment_id = var.compartment_ocid + items { + domain = var.oci_domain_name + rdata = oci_core_instance.kasm_instance.public_ip + rtype = "A" + ttl = 300 + } +} \ No newline at end of file diff --git a/oci/single_server/module/instance.tf b/oci/single_server/module/instance.tf new file mode 100644 index 0000000..23c5d08 --- /dev/null +++ b/oci/single_server/module/instance.tf @@ -0,0 +1,49 @@ +data "template_file" "user_data" { + template = "${file("${path.module}/userdata/bootstrap.sh")}" + vars = { + kasm_build_url = "${var.kasm_build_url}" + user_password = "${var.user_password}" + admin_password = "${var.admin_password}" + swap_size = "${var.swap_size}" + nginx_cert_in = file("${var.kasm_ssl_crt_path}") + nginx_key_in = file("${var.kasm_ssl_key_path}") + } +} + +resource "oci_core_instance" "kasm_instance" { + availability_domain = data.oci_identity_availability_domain.ad.name + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-Kasm-Workspaces" + shape = var.instance_shape + + shape_config { + ocpus = var.instance_ocpus + memory_in_gbs = var.shape_memory_in_gb + } + + create_vnic_details { + subnet_id = oci_core_subnet.kasm_subnet.id + display_name = "${var.project_name}-Primaryvnic" + assign_public_ip = true + assign_private_dns_record = true + hostname_label = "${var.project_name}-Kasm-Workspaces" + } + + source_details { + source_type = "image" + source_id = var.instance_image_ocid + boot_volume_size_in_gbs = var.instance_boot_size_gb + } + + + metadata = { + ssh_authorized_keys = file("${var.ssh_authorized_keys}") + user_data = base64encode("${data.template_file.user_data.rendered}") + } + +} + + + + + diff --git a/oci/single_server/module/main.tf b/oci/single_server/module/main.tf new file mode 100644 index 0000000..586a8cb --- /dev/null +++ b/oci/single_server/module/main.tf @@ -0,0 +1,8 @@ +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + diff --git a/oci/single_server/module/security_list.tf b/oci/single_server/module/security_list.tf new file mode 100644 index 0000000..3fae3cb --- /dev/null +++ b/oci/single_server/module/security_list.tf @@ -0,0 +1,42 @@ + +resource "oci_core_security_list" "allow_web" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + display_name = "allow_web" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + stateless = "false" + } + + ingress_security_rules { + protocol = "6" + source = "${var.allow_web_cidr}" + tcp_options { + max = "443" + min = "443" + } + } +} + +resource "oci_core_security_list" "allow_ssh" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + display_name = "allow_ssh" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + stateless = "false" + } + + ingress_security_rules { + protocol = "6" + source = "${var.allow_ssh_cidr}" + tcp_options { + max = "22" + min = "22" + } + } +} diff --git a/oci/single_server/module/userdata/bootstrap.sh b/oci/single_server/module/userdata/bootstrap.sh new file mode 100644 index 0000000..dfe4da9 --- /dev/null +++ b/oci/single_server/module/userdata/bootstrap.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -ex +echo "Starting Kasm Workspaces Install" + +/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=${swap_size} +/sbin/mkswap /var/swap.1 +chmod 600 /var/swap.1 +/sbin/swapon /var/swap.1 + +cd /tmp + +PRIVATE_IP=(`hostname -I | cut -d ' ' -f1 | tr -d '\\n'`) + +wget ${kasm_build_url} -O kasm_workspaces.tar.gz +tar -xf kasm_workspaces.tar.gz +bash kasm_release/install.sh -e -U ${user_password} -P ${admin_password} -p $PRIVATE_IP -m $PRIVATE_IP + +echo -e "${nginx_cert_in}" > /opt/kasm/current/certs/kasm_nginx.crt + +echo -e "${nginx_key_in}" > /opt/kasm/current/certs/kasm_nginx.key + +docker exec kasm_proxy nginx -s reload + +echo "Done" + diff --git a/oci/single_server/module/variables.tf b/oci/single_server/module/variables.tf new file mode 100644 index 0000000..29fb5f5 --- /dev/null +++ b/oci/single_server/module/variables.tf @@ -0,0 +1,94 @@ +variable "project_name" { + description = "The name of the deployment (e.g dev, staging). A short single word" +} + +variable "oci_domain_name" { + description = "The public Zone used for the dns entries. This must already exist in the OCI account. (e.g kasm.contoso.com). The deployment will be accessed via this zone name via https" +} + +variable kasm_build_url { + description = "The URL for the Kasm Workspaces build" +} + +variable swap_size { + description = "The amount of swap (in MB) to configure inside the compute instances" + default = 2048 +} + +variable "tenancy_ocid" { + description = "The Tenancy OCID." +} + +variable "user_ocid" { + description = "The User OCID." +} + +variable "compartment_ocid" { + description = "The Compartment OCID" +} + +variable "region" { + description = "The OCI Region eg: (us-ashburn-1)" +} + +variable "fingerprint" { + description = "API Key Fingerprint" +} + +variable "private_key_path" { + description = "The path to the API Key PEM encoded Private Key" +} + +variable "ssh_authorized_keys" { + description = "The file path to the authorized_keys file that contains SSH public keys to be installed on the OCI compute instance" +} + +variable "instance_image_ocid" { + description = "The OCID for the instance image , such as ubuntu 18.04, to use." + default = "ocid1.image.oc1.iad.aaaaaaaafg6lg7dejwjebjqontwzyvutgf6qs5awyze6fgoiqepyj5qkvcuq" +} + +variable "instance_boot_size_gb" { + description = "The size, in GB, of the instance drive" + default = 60 +} + +variable "instance_shape" { + description = "The instance shape to use. Should be a Flex type." + default = "VM.Standard.E3.Flex" +} + +variable "instance_ocpus" { + description = "The number of CPUs to configure for the instance" + default = 2 +} + +variable "shape_memory_in_gb" { + description = "The amount of memory, in GB, to configure for the instance" + default = 4 +} + +variable "allow_ssh_cidr" { + description = "The CIDR notation to allow SSH access to the systems." + default = "0.0.0.0/0" +} + +variable "allow_web_cidr" { + description = "The CIDR notation to allow HTTPS access to the systems." + default = "0.0.0.0/0" +} + +variable "kasm_ssl_crt_path" { + description = "The file path to the PEM encoded SSL Certificate" +} + +variable "kasm_ssl_key_path" { + description = "The file path to the PEM encoded SSL Certificate Key" +} + +variable "user_password" { + description = "The password for the database. No special characters" +} +variable "admin_password" { + description = "The password for the database. No special characters" +} \ No newline at end of file diff --git a/oci/single_server/module/vcn.tf b/oci/single_server/module/vcn.tf new file mode 100644 index 0000000..a068830 --- /dev/null +++ b/oci/single_server/module/vcn.tf @@ -0,0 +1,43 @@ + +resource "oci_core_vcn" "kasm_vcn" { + cidr_block = "10.0.0.0/16" + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-VCN" + dns_label = "${var.project_name}vcn" +} + + +resource "oci_core_internet_gateway" "kasm_internet_gateway" { + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-Gateway" + vcn_id = oci_core_vcn.kasm_vcn.id +} + +resource "oci_core_default_route_table" "default_route_table" { + manage_default_resource_id = oci_core_vcn.kasm_vcn.default_route_table_id + display_name = "DefaultRouteTable" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.kasm_internet_gateway.id + } +} + +resource "oci_core_subnet" "kasm_subnet" { + availability_domain = data.oci_identity_availability_domain.ad.name + cidr_block = "10.0.10.0/24" + display_name = "${var.project_name}-Subnet" + dns_label = "${var.project_name}subnet" + security_list_ids = [oci_core_security_list.allow_web.id, oci_core_security_list.allow_ssh.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + route_table_id = oci_core_vcn.kasm_vcn.default_route_table_id + dhcp_options_id = oci_core_vcn.kasm_vcn.default_dhcp_options_id +} + + +data "oci_identity_availability_domain" "ad" { + compartment_id = var.tenancy_ocid + ad_number = 1 +} diff --git a/oci/single_server/oci-private-key.pem b/oci/single_server/oci-private-key.pem new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/single_server/oci-private-key.pem @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/standard/README.md b/oci/standard/README.md new file mode 100644 index 0000000..e5c7428 --- /dev/null +++ b/oci/standard/README.md @@ -0,0 +1,55 @@ +# OPC Single Server +This project will deploy Kasm Workspaces in a multi-server deployment in OCI. + + +![Diagram][Image_Diagram] + +[Image_Diagram]: https://f.hubspotusercontent30.net/hubfs/5856039/terraform/diagrams/oci-multi-server.png "Diagram" + + + + +# Pre-Configuration +Consider creating a new Compartment for the Kasm Workspaces deployment. + +### DNS Zone +In OCI create a public DNS zone that matches the desired domain name for the deployment. e.g `kasm.contoso.com`. + +### API Keys +Create an administative user the OCI console that will be used for the terraform deployment. Add the user to the +**Administrators** Group. Generate an API Key for the user. The API Key Fingerprint will be used as a variable +in the deployment configuration. Save the private key to the local directory replacing `oci-private-key.pem`. + +### SSH Authorized Keys +The project will install an SSH key(s) inside the OCI compute instance(s). Update `authorized_keys` in this directory +with the desired SSH public keys. + +### SSL Certificate +Create an SSL certificate that matches the desired domain for the deployment. e.g (kasm.contoso.com). Place the pem encoded +cert and key in this directory overwriting `kasm_ssl.crt` and `kasm_ssl.key`. + + + +# Terraform Configuration + +1. Initialize the project + + terraform init + +2. Open `deployment.tf` and update the variables. The variable definitions and descriptions +can be found in `module/variables.tf` + + +3. Verify the configuration + + terraform plan + +4. Deploy + + terraform deploy + + +5. Login to the Deployment as an Admin via the domain defined e.g `https://kasm.contoso.com`. It may take several minutes +for the deployment to fully come online. + + diff --git a/oci/standard/authorized_keys b/oci/standard/authorized_keys new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/standard/authorized_keys @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/standard/deployment.tf b/oci/standard/deployment.tf new file mode 100644 index 0000000..6d770d8 --- /dev/null +++ b/oci/standard/deployment.tf @@ -0,0 +1,29 @@ +module "kasm" { + source = "./module" + oci_domain_name = "kasm.contoso.com" + project_name = "contoso" + + tenancy_ocid = "" + user_ocid = "" + compartment_ocid = "" + + fingerprint = "" + private_key_path = "./oci-private-key.pem" + ssh_authorized_keys = "./authorized_keys" + kasm_ssl_crt_path = "./kasm_ssl.crt" + kasm_ssl_key_path = "./kasm_ssl.key" + + region = "us-ashburn-1" + instance_image_ocid = "ocid1.image.oc1.iad.aaaaaaaafg6lg7dejwjebjqontwzyvutgf6qs5awyze6fgoiqepyj5qkvcuq" + num_agents = "2" + num_webapps = "2" + + kasm_build_url = "https://kasm-static-content.s3.amazonaws.com/kasm_release_1.9.0.077388.tar.gz" + allow_ssh_cidr = "0.0.0.0/0" + allow_web_cidr = "0.0.0.0/0" + manager_token = "changeme" + admin_password = "changeme" + user_password = "changeme" + redis_password = "changeme" + database_password = "changeme" +} \ No newline at end of file diff --git a/oci/standard/kasm_ssl.crt b/oci/standard/kasm_ssl.crt new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/standard/kasm_ssl.crt @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/standard/kasm_ssl.key b/oci/standard/kasm_ssl.key new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/standard/kasm_ssl.key @@ -0,0 +1 @@ +replaceme \ No newline at end of file diff --git a/oci/standard/module/agent.tf b/oci/standard/module/agent.tf new file mode 100644 index 0000000..90cd524 --- /dev/null +++ b/oci/standard/module/agent.tf @@ -0,0 +1,44 @@ +data "template_file" "agent_user_data" { + template = "${file("${path.module}/userdata/agent_bootstrap.sh")}" + vars = { + kasm_build_url = var.kasm_build_url + swap_size = var.swap_size + manager_address = var.oci_domain_name + manager_token = var.manager_token + } +} + +resource "oci_core_instance" "kasm_agent_instance" { + count = var.num_agents + availability_domain = data.oci_identity_availability_domain.ad.name + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-Kasm-Agent-${count.index}" + shape = var.instance_shape + + shape_config { + ocpus = var.agent_ocpus + memory_in_gbs = var.agent_memory_in_gb + } + + create_vnic_details { + subnet_id = oci_core_subnet.kasm-agent-subnet.id + display_name = "${var.project_name}-Primaryvnic" + assign_public_ip = true + assign_private_dns_record = true + hostname_label = "${var.project_name}-Kasm-Agent-${count.index}" + } + + source_details { + source_type = "image" + source_id = var.instance_image_ocid + boot_volume_size_in_gbs = var.agent_boot_size_gb + } + + + metadata = { + ssh_authorized_keys = file("${var.ssh_authorized_keys}") + user_data = base64encode("${data.template_file.agent_user_data.rendered}") + } + +} + diff --git a/oci/standard/module/db.tf b/oci/standard/module/db.tf new file mode 100644 index 0000000..fb21f6f --- /dev/null +++ b/oci/standard/module/db.tf @@ -0,0 +1,48 @@ +data "template_file" "db_user_data" { + template = "${file("${path.module}/userdata/db_bootstrap.sh")}" + vars = { + kasm_build_url = var.kasm_build_url + user_password = var.user_password + admin_password = var.admin_password + redis_password = var.redis_password + database_password = var.database_password + manager_token = var.manager_token + swap_size = var.swap_size + + } +} + +resource "oci_core_instance" "kasm_db_instance" { + availability_domain = data.oci_identity_availability_domain.ad.name + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-Kasm-DB" + shape = var.instance_shape + + shape_config { + ocpus = var.db_ocpus + memory_in_gbs = var.db_memory_in_gb + } + + create_vnic_details { + subnet_id = oci_core_subnet.kasm-db-subnet.id + display_name = "${var.project_name}-Primaryvnic" + assign_public_ip = true + assign_private_dns_record = true + hostname_label = "${var.project_name}-Kasm-DB" + } + + source_details { + source_type = "image" + source_id = var.instance_image_ocid + boot_volume_size_in_gbs = var.db_boot_size_gb + } + + + metadata = { + ssh_authorized_keys = file("${var.ssh_authorized_keys}") + user_data = base64encode("${data.template_file.db_user_data.rendered}") + } + +} + + diff --git a/oci/standard/module/dns.tf b/oci/standard/module/dns.tf new file mode 100644 index 0000000..daaa765 --- /dev/null +++ b/oci/standard/module/dns.tf @@ -0,0 +1,12 @@ +resource "oci_dns_rrset" "kasm_a_record" { + domain = var.oci_domain_name + rtype = "A" + zone_name_or_id = var.oci_domain_name + compartment_id = var.compartment_ocid + items { + domain = var.oci_domain_name + rdata = oci_load_balancer_load_balancer.kasm_load_balancer.ip_addresses[0] + rtype = "A" + ttl = 300 + } +} \ No newline at end of file diff --git a/oci/standard/module/load_balancer.tf b/oci/standard/module/load_balancer.tf new file mode 100644 index 0000000..1daa13d --- /dev/null +++ b/oci/standard/module/load_balancer.tf @@ -0,0 +1,66 @@ +resource "oci_load_balancer_load_balancer" "kasm_load_balancer" { + compartment_id = var.compartment_ocid + display_name = "Kasm-${var.project_name}-lb" + shape = "100Mbps" + subnet_ids = [oci_core_subnet.kasm-webapp-subnet.id, oci_core_subnet.kasm-webapp-subnet-2.id] + is_private = false +} + +resource "oci_load_balancer_certificate" "kasm_lb_certificate" { + certificate_name = "${var.project_name}-kasm-cert-2" + load_balancer_id = oci_load_balancer_load_balancer.kasm_load_balancer.id + + ca_certificate = file(var.kasm_ssl_crt_path) + public_certificate = file(var.kasm_ssl_crt_path) + private_key = file(var.kasm_ssl_key_path) + + lifecycle { + create_before_destroy = true + } +} + +resource "oci_load_balancer_backend_set" "kasm-webapps-backend-set" { + health_checker { + interval_ms = "10000" + port = "443" + protocol = "HTTP" + response_body_regex = "" + retries = "3" + return_code = "200" + timeout_in_millis = "3000" + url_path = "/api/__healthcheck" + } + ssl_configuration { + certificate_name = oci_load_balancer_certificate.kasm_lb_certificate.certificate_name + verify_peer_certificate = false + } + + load_balancer_id = oci_load_balancer_load_balancer.kasm_load_balancer.id + name = "kasm-webapps-lb-backend-set" + policy = "ROUND_ROBIN" +} + +resource "oci_load_balancer_backend" "webapp-ld-backed" { + count = var.num_webapps + backendset_name = oci_load_balancer_backend_set.kasm-webapps-backend-set.name + backup = "false" + drain = "false" + load_balancer_id = oci_load_balancer_load_balancer.kasm_load_balancer.id + ip_address = oci_core_instance.kasm_webapp_instance[count.index].private_ip + offline = "false" + port = "443" + weight = "1" +} + +resource "oci_load_balancer_listener" "kasm_https_ssl_listener" { + load_balancer_id = oci_load_balancer_load_balancer.kasm_load_balancer.id + name = "${var.project_name}-https-ssl-listener" + default_backend_set_name = oci_load_balancer_backend_set.kasm-webapps-backend-set.name + port = "443" + protocol = "HTTP" + + ssl_configuration { + certificate_name = oci_load_balancer_certificate.kasm_lb_certificate.certificate_name + verify_peer_certificate = false + } +} diff --git a/oci/standard/module/main.tf b/oci/standard/module/main.tf new file mode 100644 index 0000000..586a8cb --- /dev/null +++ b/oci/standard/module/main.tf @@ -0,0 +1,8 @@ +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + diff --git a/oci/standard/module/security_lists.tf b/oci/standard/module/security_lists.tf new file mode 100644 index 0000000..5499bb3 --- /dev/null +++ b/oci/standard/module/security_lists.tf @@ -0,0 +1,101 @@ +resource "oci_core_security_list" "allow_web" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + display_name = "allow_web" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + stateless = "false" + } + + ingress_security_rules { + protocol = "6" + source = var.allow_web_cidr + tcp_options { + max = "443" + min = "443" + } + } +} + +resource "oci_core_security_list" "allow_ssh" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + display_name = "allow_ssh" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + stateless = "false" + } + + ingress_security_rules { + protocol = "6" + source = var.allow_ssh_cidr + tcp_options { + max = "22" + min = "22" + } + } +} + + +resource "oci_core_security_list" "allow_db_redis" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + display_name = "allow_db_redis" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + stateless = "false" + } + + ingress_security_rules { + protocol = "6" + source = oci_core_subnet.kasm-webapp-subnet.cidr_block + tcp_options { + max = "5432" + min = "5432" + } + } + ingress_security_rules { + protocol = "6" + source = oci_core_subnet.kasm-webapp-subnet.cidr_block + tcp_options { + max = "6379" + min = "6379" + } + } +} + + +resource "oci_core_security_list" "allow_web_from_webapp" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + display_name = "allow_web_from_webapp" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + stateless = "false" + } + + ingress_security_rules { + protocol = "6" + source = var.webapp_cidr_1 + tcp_options { + max = "443" + min = "443" + } + } + ingress_security_rules { + protocol = "6" + source = var.webapp_cidr_2 + tcp_options { + max = "443" + min = "443" + } + } +} diff --git a/oci/standard/module/subnet.tf b/oci/standard/module/subnet.tf new file mode 100644 index 0000000..371cb4b --- /dev/null +++ b/oci/standard/module/subnet.tf @@ -0,0 +1,48 @@ +resource "oci_core_subnet" "kasm-db-subnet" { + availability_domain = data.oci_identity_availability_domain.ad.name + cidr_block = "10.0.10.0/24" + display_name = "${var.project_name}-kasm-db-subnet" + dns_label = "${var.project_name}db" + security_list_ids = [oci_core_security_list.allow_db_redis.id, oci_core_security_list.allow_ssh.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + route_table_id = oci_core_vcn.kasm_vcn.default_route_table_id + dhcp_options_id = oci_core_vcn.kasm_vcn.default_dhcp_options_id +} + +resource "oci_core_subnet" "kasm-webapp-subnet" { + availability_domain = data.oci_identity_availability_domain.ad.name + cidr_block = var.webapp_cidr_1 + display_name = "${var.project_name}-kasm-webapp-subnet" + dns_label = "${var.project_name}webapp" + security_list_ids = [oci_core_security_list.allow_web.id, oci_core_security_list.allow_ssh.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + route_table_id = oci_core_vcn.kasm_vcn.default_route_table_id + dhcp_options_id = oci_core_vcn.kasm_vcn.default_dhcp_options_id +} + +resource "oci_core_subnet" "kasm-webapp-subnet-2" { + availability_domain = data.oci_identity_availability_domain.ad2.name + cidr_block = var.webapp_cidr_2 + display_name = "${var.project_name}-kasm-webapp-subnet-2" + dns_label = "${var.project_name}webapp2" + security_list_ids = [oci_core_security_list.allow_web.id, oci_core_security_list.allow_ssh.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + route_table_id = oci_core_vcn.kasm_vcn.default_route_table_id + dhcp_options_id = oci_core_vcn.kasm_vcn.default_dhcp_options_id +} + + +resource "oci_core_subnet" "kasm-agent-subnet" { + availability_domain = data.oci_identity_availability_domain.ad.name + cidr_block = "10.0.30.0/24" + display_name = "${var.project_name}-kasm-agent-subnet" + dns_label = "${var.project_name}agent" + security_list_ids = [oci_core_security_list.allow_web_from_webapp.id, oci_core_security_list.allow_ssh.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.kasm_vcn.id + route_table_id = oci_core_vcn.kasm_vcn.default_route_table_id + dhcp_options_id = oci_core_vcn.kasm_vcn.default_dhcp_options_id +} \ No newline at end of file diff --git a/oci/standard/module/userdata/agent_bootstrap.sh b/oci/standard/module/userdata/agent_bootstrap.sh new file mode 100644 index 0000000..58ebf1b --- /dev/null +++ b/oci/standard/module/userdata/agent_bootstrap.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -ex +echo "Starting Kasm Workspaces Agent Install" + +/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=${swap_size} +/sbin/mkswap /var/swap.1 +chmod 600 /var/swap.1 +/sbin/swapon /var/swap.1 + +echo '/var/swap.1 swap swap defaults 0 0' | tee -a /etc/fstab + +cd /tmp + +PRIVATE_IP=(`hostname -I | cut -d ' ' -f1 | tr -d '\\n'`) + +wget ${kasm_build_url} -O kasm_workspaces.tar.gz +tar -xf kasm_workspaces.tar.gz +bash kasm_release/install.sh -S agent -e -p $PRIVATE_IP -m ${manager_address} -M ${manager_token} + +echo "Done" + diff --git a/oci/standard/module/userdata/db_bootstrap.sh b/oci/standard/module/userdata/db_bootstrap.sh new file mode 100644 index 0000000..76b1efb --- /dev/null +++ b/oci/standard/module/userdata/db_bootstrap.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -ex +echo "Starting Kasm Workspaces Install" + +/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=${swap_size} +/sbin/mkswap /var/swap.1 +chmod 600 /var/swap.1 +/sbin/swapon /var/swap.1 + +echo '/var/swap.1 swap swap defaults 0 0' | tee -a /etc/fstab + +cd /tmp + +PRIVATE_IP=(`hostname -I | cut -d ' ' -f1 | tr -d '\\n'`) + +wget ${kasm_build_url} -O kasm_workspaces.tar.gz +tar -xf kasm_workspaces.tar.gz +bash kasm_release/install.sh -S db -e -Q ${database_password} -R ${redis_password} -U ${user_password} -P ${admin_password} -M ${manager_token} + +echo "Done" + diff --git a/oci/standard/module/userdata/webapp_bootstrap.sh b/oci/standard/module/userdata/webapp_bootstrap.sh new file mode 100644 index 0000000..dfd0b23 --- /dev/null +++ b/oci/standard/module/userdata/webapp_bootstrap.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -ex +echo "Starting Kasm Workspaces Install" + +/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=${swap_size} +/sbin/mkswap /var/swap.1 +chmod 600 /var/swap.1 +/sbin/swapon /var/swap.1 + +echo '/var/swap.1 swap swap defaults 0 0' | tee -a /etc/fstab + +cd /tmp + +PRIVATE_IP=(`hostname -I | cut -d ' ' -f1 | tr -d '\\n'`) + +wget ${kasm_build_url} -O kasm_workspaces.tar.gz +tar -xf kasm_workspaces.tar.gz + +echo "Checking for Kasm DB..." +apt-get update && apt-get install -y netcat +while ! nc -w 1 -z ${db_ip} 5432; do + echo "Not Ready..." + sleep 5 +done +echo "DB is alive" + +bash kasm_release/install.sh -S app -e -z ${zone_name} -q "${db_ip}" -Q ${database_password} -R ${redis_password} + +echo "Done" + diff --git a/oci/standard/module/variables.tf b/oci/standard/module/variables.tf new file mode 100644 index 0000000..f621f6a --- /dev/null +++ b/oci/standard/module/variables.tf @@ -0,0 +1,156 @@ +variable "project_name" { + description = "The name of the deployment (e.g dev, staging). A short single word" +} + +variable "oci_domain_name" { + description = "The public Zone used for the dns entries. This must already exist in the OCI account. (e.g kasm.contoso.com). The deployment will be accessed via this zone name via https" +} + +variable kasm_build_url { + description = "The URL for the Kasm Workspaces build" +} + + +variable swap_size { + description = "The amount of swap (in MB) to configure inside the compute instances" + default = 2048 +} + + +variable "tenancy_ocid" { + description = "The Tenancy OCID." +} + +variable "user_ocid" { + description = "The User OCID." +} + +variable "compartment_ocid" { + description = "The Compartment OCID" +} + +variable "region" { + description = "The OCI Region eg: (us-ashburn-1)" +} + +variable "fingerprint" { + description = "API Key Fingerprint" +} + +variable "private_key_path" { + description = "The path to the API Key PEM encoded Private Key" +} + +variable "ssh_authorized_keys" { + description = "The file path to the authorized_keys file that contains SSH public keys to be installed on the OCI compute instance" +} + +variable "instance_image_ocid" { + description = "The OCID for the instance image , such as ubuntu 18.04, to use." + default = "ocid1.image.oc1.iad.aaaaaaaafg6lg7dejwjebjqontwzyvutgf6qs5awyze6fgoiqepyj5qkvcuq" +} + + +variable "allow_ssh_cidr" { + description = "The CIDR notation to allow SSH access to the systems." + default = "0.0.0.0/0" +} + +variable "allow_web_cidr" { + description = "The CIDR notation to allow HTTPS access to the systems." + default = "0.0.0.0/0" +} + +variable "kasm_ssl_crt_path" { + description = "The file path to the PEM encoded SSL Certificate" +} + +variable "kasm_ssl_key_path" { + description = "The file path to the PEM encoded SSL Certificate Key" +} + + +variable "instance_shape" { + description = "The instance shape to use. Should be a Flex type." + default = "VM.Standard.E3.Flex" +} + +variable "db_boot_size_gb" { + description = "The size, in GB, of the DB instance drive" + default = 50 +} + +variable "webapp_boot_size_gb" { + description = "The size, in GB, of the Webapp instance drives" + default = 50 +} + +variable "agent_boot_size_gb" { + description = "The size, in GB, of the Agemt instance drives" + default = 60 +} + + +variable "num_agents" { + default = "2" + description = "The number of Agent Role Servers to create in the deployment" +} + + +variable "num_webapps" { + default = "2" + description = "The number of WebApp role servers to create in the deployment" +} + + +variable "agent_ocpus" { + description = "The number of CPUs to configure for the Agent instances" + default = 2 +} + +variable "db_ocpus" { + description = "The number of CPUs to configure for the DB instance" + default = 1 +} + +variable "webapp_ocpus" { + description = "The number of CPUs to configure for the Webapp instances" + default = 1 +} + +variable "agent_memory_in_gb" { + description = "The amount of memory, in GB, to configure for the Agent instances" + default = 4 +} + +variable "webapp_memory_in_gb" { + description = "The amount of memory, in GB, to configure for the Webapp instances" + default = 2 +} + +variable "db_memory_in_gb" { + description = "The amount of memory, in GB, to configure for the DB instance" + default = 2 +} + +variable "manager_token" { + description = "The password for the database. No special characters" +} +variable "database_password" { + description = "The password for the database. No special characters" +} +variable "redis_password" { + description = "The password for the database. No special characters" +} +variable "user_password" { + description = "The password for the database. No special characters" +} +variable "admin_password" { + description = "The password for the database. No special characters" +} +variable "webapp_cidr_1" { + default = "10.0.20.0/24" +} +variable "webapp_cidr_2" { + default = "10.0.25.0/24" +} \ No newline at end of file diff --git a/oci/standard/module/vcn.tf b/oci/standard/module/vcn.tf new file mode 100644 index 0000000..23a7605 --- /dev/null +++ b/oci/standard/module/vcn.tf @@ -0,0 +1,38 @@ + +resource "oci_core_vcn" "kasm_vcn" { + cidr_block = "10.0.0.0/16" + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-VCN" + dns_label = "${var.project_name}vcn" +} + + + +resource "oci_core_internet_gateway" "kasm_internet_gateway" { + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-Gateway" + vcn_id = oci_core_vcn.kasm_vcn.id +} + +resource "oci_core_default_route_table" "default_route_table" { + manage_default_resource_id = oci_core_vcn.kasm_vcn.default_route_table_id + display_name = "DefaultRouteTable" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.kasm_internet_gateway.id + } +} + + + +data "oci_identity_availability_domain" "ad" { + compartment_id = var.tenancy_ocid + ad_number = 1 +} + +data "oci_identity_availability_domain" "ad2" { + compartment_id = var.tenancy_ocid + ad_number = 2 +} diff --git a/oci/standard/module/webapp.tf b/oci/standard/module/webapp.tf new file mode 100644 index 0000000..e227c31 --- /dev/null +++ b/oci/standard/module/webapp.tf @@ -0,0 +1,48 @@ +data "template_file" "webapp_user_data" { + template = "${file("${path.module}/userdata/webapp_bootstrap.sh")}" + vars = { + kasm_build_url = var.kasm_build_url + db_ip = oci_core_instance.kasm_db_instance.private_ip + database_password = var.database_password + redis_password = var.redis_password + swap_size = var.swap_size + zone_name = "default" + } +} + +resource "oci_core_instance" "kasm_webapp_instance" { + count = var.num_webapps + availability_domain = data.oci_identity_availability_domain.ad.name + compartment_id = var.compartment_ocid + display_name = "${var.project_name}-Kasm-Webapp-${count.index}" + shape = var.instance_shape + + shape_config { + ocpus = var.webapp_ocpus + memory_in_gbs = var.webapp_memory_in_gb + } + + create_vnic_details { + subnet_id = oci_core_subnet.kasm-webapp-subnet.id + display_name = "${var.project_name}-Primaryvnic" + assign_public_ip = true + assign_private_dns_record = true + hostname_label = "${var.project_name}-Kasm-Webapp-${count.index}" + } + + source_details { + source_type = "image" + source_id = var.instance_image_ocid + boot_volume_size_in_gbs = var.webapp_boot_size_gb + } + + + metadata = { + ssh_authorized_keys = file("${var.ssh_authorized_keys}") + user_data = base64encode("${data.template_file.webapp_user_data.rendered}") + } + +} + + + diff --git a/oci/standard/oci-private-key.pem b/oci/standard/oci-private-key.pem new file mode 100644 index 0000000..5d6af95 --- /dev/null +++ b/oci/standard/oci-private-key.pem @@ -0,0 +1 @@ +replaceme \ No newline at end of file