From 93b720ac90b1d9ab45ef5088b71fb8b6ba9deea8 Mon Sep 17 00:00:00 2001 From: Nathan Rodet <nrodet@grandlyon.com> Date: Tue, 20 Dec 2022 16:42:26 +0100 Subject: [PATCH] Initial commit --- .gitignore | 9 ++ .gitlab-ci.yml | 76 ++++++++++++ create_lab.sh | 35 ++++++ delete_lab.sh | 3 + instance_scripts/atrium_scripts/atrium.yaml | 19 +++ instance_scripts/atrium_scripts/deploy.sh | 21 ++++ instance_scripts/start_webtop.sh | 21 ++++ terraform/main.tf | 123 ++++++++++++++++++++ terraform/output.tf | 8 ++ terraform/provider.tf | 19 +++ terraform/variables-gitlab.tf | 41 +++++++ terraform/variables-local.tf | 19 +++ terraform/variables-local.tfvars | 14 +++ 13 files changed, 408 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100755 create_lab.sh create mode 100755 delete_lab.sh create mode 100644 instance_scripts/atrium_scripts/atrium.yaml create mode 100644 instance_scripts/atrium_scripts/deploy.sh create mode 100755 instance_scripts/start_webtop.sh create mode 100644 terraform/main.tf create mode 100644 terraform/output.tf create mode 100644 terraform/provider.tf create mode 100644 terraform/variables-gitlab.tf create mode 100644 terraform/variables-local.tf create mode 100644 terraform/variables-local.tfvars diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..596881b --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +./terraform/.terraform.lock.hcl +./terraform/.terraform.tfstate.lock.info +./terraform/terraform.tfstate* +./terraform/.terraform/* +./terraform/variables-local.tf +./terraform/variables-local.tfvars +./terraform/tfplan +.env +.idea \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..a2c734d --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,76 @@ +default: + image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest + +variables: + TF_ROOT: ${CI_PROJECT_DIR}/terraform + TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME} + TF_STATE_NAME: ${ENVIRONMENT} + TF_CACHE_KEY: default + +before_script: + - cd ${TF_ROOT} + - which ssh-agent || ( apt-get install -qq openssh-client ) + - ssh-keygen -b 2048 -t rsa -f ./tf.rsa -q -N "" -C "FORGE alpha-project-manager" + - export TF_VAR_SCW_ACCESS_KEY=${TF_VAR_SCW_ACCESS_KEY} + - export TF_VAR_SCW_SECRET_KEY=${TF_VAR_SCW_SECRET_KEY} + - export TF_VAR_SCW_PROJECT_ID=${TF_VAR_SCW_PROJECT_ID} + - export TF_VAR_INSTANCES_COUNT=${TF_VAR_INSTANCES_COUNT} + - export TF_VAR_ENVIRONMENT=${ENVIRONMENT} + - export TF_VAR_SCW_SSH_PUB_KEY=$(cat tf.rsa.pub) + - export TF_VAR_SCW_SSH_PRIVATE_KEY=$(cat tf.rsa) + - echo ${TF_VAR_SCW_SSH_PUB_KEY} + - echo ${TF_VAR_SCW_SSH_PRIVATE_KEY} + - echo $(ssh-keygen -E md5 -lf ./tf.rsa.pub) + +stages: + - prepare + - validate + - build + - deploy + - destroy + +init: + stage: prepare + script: + - gitlab-terraform init + +validate: + stage: validate + script: + - gitlab-terraform validate + +plan: + stage: build + script: + - gitlab-terraform plan + - gitlab-terraform plan-json + artifacts: + name: plan + paths: + - ${TF_ROOT}/plan.cache + reports: + terraform: ${TF_ROOT}/plan.json + +apply: + stage: deploy + environment: + name: ${ENVIRONMENT} + script: + - gitlab-terraform apply + dependencies: + - plan + when: manual + only: + - develop + - main + +destroy: + stage: destroy + environment: + name: ${ENVIRONMENT} + script: + - gitlab-terraform destroy + when: manual + only: + - develop + - main \ No newline at end of file diff --git a/create_lab.sh b/create_lab.sh new file mode 100755 index 0000000..42d1817 --- /dev/null +++ b/create_lab.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +echo "|------------------------|" +echo "| INITIALISATION DU LABO |" +echo "|------------------------|" + +if [ ! -f ".env" ]; then + echo "Créez un fichier .env de la forme suivante :" + echo "SCW_ACCESS_KEY=" + echo "SCW_SECRET_KEY=" + echo "TF_VAR_PROJECT_ID=" + echo "TF_VAR_INSTANCES_COUNT=2" + exit 1 +fi + +export $(cat .env | xargs) +# Move to Terraform directory +cd ./terraform +# Initialize a Terraform working directory +terraform init +# Generate and show the execution plan +terraform plan +# Build the infrastructure +terraform apply +# Echo Terraform outputs +terraform output +# Move to default directory +cd .. + +echo "|--------------|" +echo "| LABO DÉMARRÉ |" +echo "|--------------|" + +echo "Se connecter sur les IPs, avec le port 80 pour webtop, et 8080 pour code-server." +echo "Le mot de passe des instances est yfB4W23G." diff --git a/delete_lab.sh b/delete_lab.sh new file mode 100755 index 0000000..47aaecf --- /dev/null +++ b/delete_lab.sh @@ -0,0 +1,3 @@ +#!/bin/bash +export $(cat .env | xargs) +terraform destroy diff --git a/instance_scripts/atrium_scripts/atrium.yaml b/instance_scripts/atrium_scripts/atrium.yaml new file mode 100644 index 0000000..badb1c5 --- /dev/null +++ b/instance_scripts/atrium_scripts/atrium.yaml @@ -0,0 +1,19 @@ +hostname: labo.alpha.grandlyon.com +debug_mode: false +letsencrypt_email: nrodet@alpha.grandlyon.com +apps: # optional : applications served by atrium + - id: $COUNT + name: Code + icon: web_asset + color: 4292030255 + is_proxy: true + host: instance$COUNT-code + target: $PRIVATE_IP:8080 +apps: # optional : applications served by atrium + - id: $COUNT + name: Desktop + icon: web_asset + color: 4292030255 + is_proxy: true + host: instance$COUNT-desktop + target: $PRIVATE_IP:8081 \ No newline at end of file diff --git a/instance_scripts/atrium_scripts/deploy.sh b/instance_scripts/atrium_scripts/deploy.sh new file mode 100644 index 0000000..b947e39 --- /dev/null +++ b/instance_scripts/atrium_scripts/deploy.sh @@ -0,0 +1,21 @@ +cat<<EOF >> ./atrium.yaml +hostname: labo.alpha.grandlyon.com +debug_mode: false +letsencrypt_email: nrodet@alpha.grandlyon.com +apps: # optional : applications served by atrium + - id: "$COUNT" + name: Code + icon: web_asset + color: 4292030255 + is_proxy: true + host: machine$COUNT-code + target: $PRIVATE_IP:8080 +apps: # optional : applications served by atrium + - id: "$COUNT" + name: Desktop + icon: web_asset + color: 4292030255 + is_proxy: true + host: machine$COUNT-desktop + target: $PRIVATE_IP:8081 +EOF diff --git a/instance_scripts/start_webtop.sh b/instance_scripts/start_webtop.sh new file mode 100755 index 0000000..9650b16 --- /dev/null +++ b/instance_scripts/start_webtop.sh @@ -0,0 +1,21 @@ +#!/bin/bash +docker stop webtop +docker rm webtop +docker run -d \ + --name=webtop \ + --security-opt seccomp=unconfined \ + -e PUID=0 \ + -e PGID=0 \ + -e TZ=Europe/Paris \ + -e SUBFOLDER=/ \ + -e KEYBOARD=fr-fr-azerty \ + -e AUTO_LOGIN=false \ + -p 80:3000 \ + -v /root/webtop_data/:/config \ + -v /var/run/docker.sock:/var/run/docker.sock \ + --shm-size="8gb" \ + --cap-add=NET_ADMIN \ + --privileged \ + --restart unless-stopped \ + --sysctl net.ipv6.conf.all.disable_ipv6=0 \ + lscr.io/linuxserver/webtop:ubuntu-xfce diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..2656146 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,123 @@ +############ +# Terraform SSH key +############ + +resource "scaleway_account_ssh_key" "ssh_key" { + name = "FORGE alpha_project_manager" + public_key = var.SCW_SSH_PUB_KEY +} + +############ +# Public IP +############ + +resource "scaleway_instance_ip" "public_ip" { + count = var.INSTANCES_COUNT + project_id = var.SCW_PROJECT_ID +} + +################ +# DOMAIN RECORD +################ + +resource "scaleway_domain_record" "subdomain_record" { + count = var.INSTANCES_COUNT + dns_zone = "daag.alpha.grandlyon.com" + name = "lab-${count.index}-daag-${var.ENVIRONMENT}" + type = "A" + data = scaleway_instance_ip.public_ip[count.index].address + ttl = 3600 +} + +resource "scaleway_domain_record" "host_subdomain_record" { + count = var.INSTANCES_COUNT + dns_zone = "daag.alpha.grandlyon.com" + name = "*.lab-${count.index}-daag-${var.ENVIRONMENT}" + type = "A" + data = scaleway_instance_ip.public_ip[count.index].address + ttl = 3600 +} + +################################## +## Security group - Allowed ports +################################## + +resource "scaleway_instance_security_group" "www" { + project_id = var.SCW_PROJECT_ID + name = "security-group-daag-lab-${var.ENVIRONMENT}" + inbound_default_policy = "drop" + outbound_default_policy = "accept" + + inbound_rule { + action = "accept" + port = "22" + } + + inbound_rule { + action = "accept" + port = "80" + } + + inbound_rule { + action = "accept" + port = "8080" + } + + inbound_rule { + action = "accept" + port = "443" + } +} + +############################## +## VM Instance - User Machine +############################## + +resource "scaleway_instance_server" "user_instance_server" { + count = var.INSTANCES_COUNT + project_id = var.SCW_PROJECT_ID + name = "instance-${count.index}-daag-lab-${var.ENVIRONMENT}" + type = "DEV1-L" + image = "ubuntu_jammy" + ip_id = scaleway_instance_ip.public_ip[count.index].id + security_group_id = scaleway_instance_security_group.www.id + + depends_on = [ + scaleway_account_ssh_key.ssh_key, + scaleway_instance_security_group.www + ] +} + +resource "null_resource" "provisioner" { + count = var.INSTANCES_COUNT + depends_on = [ + scaleway_instance_server.user_instance_server + ] + + connection { + host = element(scaleway_instance_ip.public_ip.*.address, count.index) + type = "ssh" + user = "root" + private_key = var.SCW_SSH_PRIVATE_KEY + timeout = "2m" + } + + // Install Rust + provisioner "remote-exec" { + inline = [ + "apt-get update -y'", + "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y'", + "source \"$HOME/.cargo/env\"", + ] + } + + // Install Code-server + provisioner "remote-exec" { + inline = [ + "curl -fsSL https://code-server.dev/install.sh | sh", + "mkdir -p /root/.config/code-server/", + "echo 'bind-addr: 0.0.0.0:8080\nauth: password\npassword: yfB4W23G\ncert: false\n' > /root/.config/code-server/config.yaml", + "systemctl enable --now code-server@$USER" + ] + } +} \ No newline at end of file diff --git a/terraform/output.tf b/terraform/output.tf new file mode 100644 index 0000000..62ee373 --- /dev/null +++ b/terraform/output.tf @@ -0,0 +1,8 @@ +################# +# Public IP List +################# + +output "public_ip_address" { + value = scaleway_instance_ip.public_ip[*].address + sensitive = false +} \ No newline at end of file diff --git a/terraform/provider.tf b/terraform/provider.tf new file mode 100644 index 0000000..e6337d7 --- /dev/null +++ b/terraform/provider.tf @@ -0,0 +1,19 @@ +terraform { + required_providers { + scaleway = { + source = "scaleway/scaleway" + } + } + + backend "http" {} + + required_version = ">= 0.13" +} + +provider "scaleway" { + zone = "fr-par-1" + region = "fr-par" + access_key = var.SCW_ACCESS_KEY + secret_key = var.SCW_SECRET_KEY + project_id = var.SCW_PROJECT_ID +} \ No newline at end of file diff --git a/terraform/variables-gitlab.tf b/terraform/variables-gitlab.tf new file mode 100644 index 0000000..5648602 --- /dev/null +++ b/terraform/variables-gitlab.tf @@ -0,0 +1,41 @@ +### Gitlab CI variables + +variable "SCW_PROJECT_ID" { + type = string + sensitive = true + description = "Project ID from a scaleway project" +} + +variable "SCW_ACCESS_KEY" { + type = string + sensitive = true + description = "Scaleway access key" +} + +variable "SCW_SECRET_KEY" { + type = string + sensitive = true + description = "Scaleway secret key" +} + +variable "SCW_SSH_PUB_KEY" { + type = string + sensitive = true + description = "SSH public key from Gitlab agent installed on scaleway" +} + +variable "SCW_SSH_PRIVATE_KEY" { + type = string + sensitive = true + description = "SSH private key from Gitlab agent for remote-exec" +} + +variable "INSTANCES_COUNT" { + type = number + description = "Number of instances to create" +} + +variable "ENVIRONMENT" { + type = string + description = "The type of lab to create, ex: devrust, pentest..." +} diff --git a/terraform/variables-local.tf b/terraform/variables-local.tf new file mode 100644 index 0000000..f322a9e --- /dev/null +++ b/terraform/variables-local.tf @@ -0,0 +1,19 @@ +## Terraform local execution + +variable "FORGE_PROJECT_ID" { + type = string + description = "Forge Project ID" + sensitive = true +} + +variable "FORGE_USERNAME" { + type = string + description = "Forge Username" + sensitive = true +} + +variable "FORGE_ACCESS_TOKEN" { + type = string + description = "Forge Access Token" + sensitive = true +} diff --git a/terraform/variables-local.tfvars b/terraform/variables-local.tfvars new file mode 100644 index 0000000..8a4a791 --- /dev/null +++ b/terraform/variables-local.tfvars @@ -0,0 +1,14 @@ +### SCW variables + +SCW_PROJECT_ID = "c260d8c4-3ab6-41c2-ae56-c72bfa13b5f8" +SCW_ACCESS_KEY = "SCWEHMDTK4QSVBQRM5HJ" +SCW_SECRET_KEY = "5850fa82-d42a-469c-88a4-76c176760d5a" +SCW_SSH_PUB_KEY = "" +SCW_SSH_PRIVATE_KEY = "" +INSTANCES_COUNT = "2" +ENVIRONMENT = "devrust" + +### FORGE variables +FORGE_PROJECT_ID = "875" +FORGE_USERNAME="[\"Nathan Rodet\"]" +FORGE_ACCESS_TOKEN = "R00tR00t" \ No newline at end of file -- GitLab