diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..596881b22652099c232d55eda336f3431a1f977a --- /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 0000000000000000000000000000000000000000..a2c734ddadfe54edf449fd93d0ac22571dbd34ac --- /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 0000000000000000000000000000000000000000..42d181771c11debe6651cc850594b443a7aa9f08 --- /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 0000000000000000000000000000000000000000..47aaecf4d10489acb191b15b1b8aade0372d01bc --- /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 0000000000000000000000000000000000000000..badb1c51084f904337285db8875e8291e05e2786 --- /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 0000000000000000000000000000000000000000..b947e39a17dbac0bae9f544c29be22edaf3c7f4e --- /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 0000000000000000000000000000000000000000..9650b16760d6e85b07c37c3e7ba6fadd0cc8e9fe --- /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 0000000000000000000000000000000000000000..26561465b58c0c207d9c50f14f6fa1f8fe4530c9 --- /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 0000000000000000000000000000000000000000..62ee373c49d70cad84fd21fef9798cf3cec78f41 --- /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 0000000000000000000000000000000000000000..e6337d76cda3f78b354b4401fdb56c7828a7aef1 --- /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 0000000000000000000000000000000000000000..5648602b9abf3899469de3818f4b354e31a3c51f --- /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 0000000000000000000000000000000000000000..f322a9e71df20fe0364a1ec7002ea3ee46bf2414 --- /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 0000000000000000000000000000000000000000..8a4a791a092cc862df4cc9dd787da0e617ce3b4b --- /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