diff --git a/.gitignore b/.gitignore index 495a14520fa696299e5533ed0ae8d49e8b2646e4..19c581c1fa99fcee6d54fab3a369d63b90139a80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,8 @@ terraform/.terraform.lock.hcl terraform/.terraform.tfstate.lock.info terraform/terraform.tfstate* -terraform/variables-local.tf -terraform/variables-local.tfvars terraform/.terraform/* terraform/tfplan .idea - +terraform/variables-local.tfvars +terraform/variables-local.tf diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a2c734ddadfe54edf449fd93d0ac22571dbd34ac..6eac3126d001fb0019814be4f6cf60e18e010ce1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,18 +9,13 @@ variables: 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_USER_PASSWORD=${TF_VAR_USER_PASSWORD} + - export TF_VAR_LETSENCRYPT_EMAIL=${TF_VAR_LETSENCRYPT_EMAIL} - 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 diff --git a/README.md b/README.md index edebda764526963c6b44c3c7caeaaf42e1c86626..bd2f9256e2e390e559e1e9cdeffe77c186d01a9e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,45 @@ # Alpha Project Manager +An Infrastructure as Code manager to deploy lab infrastructure and configure instances. Working with Atrium, Gitlab CI, Terraform, Cloud-init and Scaleway. + +### How does it work ? + +The FORGE (Gitlab) manage the Infrastructure with Terraform at any state, plan, creation, modification and destruction with the CI. The FORGE store and will provide the configuration information +such as credentials to Terraform only during the running state to improve security. Then, informations are destroyed with the Gitlab Agent container. + +On run state, Terraform will create, modify and destroy infrastructure resources in Scaleway to match the configuration described in the configuration files. + +Resources deployed : + +| resource-type | plan | inbound port | +|----------------------------------|--------|--------------| +| scaleway_instance_ip | | | +| scaleway_domain_record | | | +| scaleway_domain_record | | | +| scaleway_instance_security_group | | 22, 443, 80 | +| scaleway_instance_server | DEV1-L | | + +After the resources provisionned with Terraform, Cloud-init will configure the instances by running bash scripts, creating files... And 3 services will be running for each instance : +- Atrium (Reverse proxy, TLS encryption and HTTPS to the others hosted services) +- Code-server +- Webtop + +After deployment, each resource can be accessed though HTTPS depending their count number : +- https://desktop-0.rust-0.daag.alpha.grandlyon.com/ +- https://code-0.rust-0.daag.alpha.grandlyon.com/ + +- https://desktop-1.rust-1.daag.alpha.grandlyon.com/ +- https://code-1.rust-1.daag.alpha.grandlyon.com/ + +User : +- Username: abc +- Password: <Gitlab Stored> + ## Setup Terraform Locally -### File Creation - variables-local.tf +First, you must setup 2 local files for your variables : + +### variables-local.tf Create a file **variables-local.tf** containing the following code : ```hcl @@ -27,7 +64,7 @@ variable "FORGE_ACCESS_TOKEN" { sensitive = true } ``` -### File Creation - variables-local.tfvars +### variables-local.tfvars Now, you can create a file for your variables information called **variables-local.tfvars** containing the following code : ```hcl @@ -36,8 +73,6 @@ Now, you can create a file for your variables information called **variables-loc SCW_PROJECT_ID = "" SCW_ACCESS_KEY = "" SCW_SECRET_KEY = "" -SCW_SSH_PUB_KEY = "" -SCW_SSH_PRIVATE_KEY = "" INSTANCES_COUNT = "2" ENVIRONMENT = "devrust" ``` diff --git a/create_lab.sh b/create_lab.sh deleted file mode 100755 index 42d181771c11debe6651cc850594b443a7aa9f08..0000000000000000000000000000000000000000 --- a/create_lab.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/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 deleted file mode 100755 index 47aaecf4d10489acb191b15b1b8aade0372d01bc..0000000000000000000000000000000000000000 --- a/delete_lab.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -export $(cat .env | xargs) -terraform destroy diff --git a/instance-scripts/cloud-init.yml b/instance-scripts/cloud-init.yml new file mode 100644 index 0000000000000000000000000000000000000000..3bfb36f5d9986f24d0451e86a3c05f99d984a652 --- /dev/null +++ b/instance-scripts/cloud-init.yml @@ -0,0 +1,89 @@ +#cloud-config + +# System update +package_update: true +package_upgrade: true + +# Install Packages +packages: + - curl + - git + +write_files: +# +# Atrium config file +# + - content: | + hostname: %atrium_hostname%.daag.alpha.grandlyon.com + debug_mode: false + letsencrypt_email: %atrium_letsencrypt_email% + tls_mode: Auto + apps: # optional : applications served by atrium + - id: 1 + name: Code %atrium_count_index% + icon: web_asset + color: 4292030255 + is_proxy: true + host: code-%atrium_count_index% + target: localhost:8080 + - id: 2 + name: Desktop %atrium_count_index% + icon: web_asset + color: 4292030255 + is_proxy: true + host: desktop-%atrium_count_index% + target: localhost:8081 + path: /root/atrium.yaml +# +# Code-server config file +# + - content: | + bind-addr: 0.0.0.0:8080 + auth: password + password: %user_password% + cert: false + path: /root/config.yaml + +runcmd: +# +# Install Rust +# + - "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" + - "source \"$HOME/.cargo/env\"" +# +# Install Docker +# + - "curl -fsSL https://get.docker.com -o get-docker.sh" + - "sh get-docker.sh" +# +# Install Atrium +# + - "mkdir -p /root/atrium/data && mkdir -p /root/atrium/letsencrypt_cache" + - 'sed -i "s/%atrium_hostname%/$(scw-userdata atrium_hostname)/g" /root/atrium.yaml' + - 'sed -i "s/%atrium_letsencrypt_email%/$(scw-userdata atrium_letsencrypt_email)/g" /root/atrium.yaml' + - 'sed -i "s/%atrium_count_index%/$(scw-userdata atrium_count_index)/g" /root/atrium.yaml' + - "mv /root/atrium.yaml /root/atrium/atrium.yaml" + - "chown -Rf 1000:1000 /root/atrium" +# +# Run Atrium Container +# + - "docker run -d --name atrium --restart unless-stopped --net=host -v /root/atrium/atrium.yaml:/app/atrium.yaml -v /root/atrium/letsencrypt_cache:/app/letsencrypt_cache -v /root/atrium/data:/app/data nicolaspernoud/atrium:latest" +# +# Install And Run Code Server +# + - "export HOME=/root" + - "export USER=root" + - "mkdir -p /root/.config/code-server/" + - 'sed -i "s/%user_password%/$(scw-userdata user_password)/g" /root/config.yaml' + - "mv /root/config.yaml /root/.config/code-server/config.yaml" + - "curl -fsSL https://code-server.dev/install.sh | sh" + - "sudo systemctl enable --now code-server@$USER" +# +# Run Webtop Container +# + - "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 8081:3000 -v /root/webtop:/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" + - 'echo "$(scw-userdata user_password)\n$(scw-userdata user_password)" | docker exec -i webtop passwd abc' +# +# Install Repository +# + - "git clone https://github.com/NathanRodet/rust-axum-demo /root/rust-axum-demo" \ No newline at end of file diff --git a/instance-scripts/confs/atrium.yaml b/instance-scripts/confs/atrium.yaml new file mode 100644 index 0000000000000000000000000000000000000000..56c601f19834015ecac6c53e177e9ceb93d87e45 --- /dev/null +++ b/instance-scripts/confs/atrium.yaml @@ -0,0 +1,20 @@ +# The content of this file is recreated by cloud init. +hostname: %atrium_hostname%.daag.alpha.grandlyon.com +debug_mode: false +letsencrypt_email: %atrium_letsencrypt_email% +tls_mode: Auto +apps: # optional : applications served by atrium + - id: 1 + name: Code %atrium_count_index% + icon: web_asset + color: 4292030255 + is_proxy: true + host: code-%atrium_count_index% + target: localhost:8080 + - id: 2 + name: Desktop %atrium_count_index% + icon: web_asset + color: 4292030255 + is_proxy: true + host: desktop-%atrium_count_index% + target: localhost:8081 \ No newline at end of file diff --git a/instance-scripts/confs/config.yaml b/instance-scripts/confs/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f212ef59ce13e4a0428648bb1c1722762124bc20 --- /dev/null +++ b/instance-scripts/confs/config.yaml @@ -0,0 +1,5 @@ +# The content of this file is recreated by cloud init. +bind-addr: 0.0.0.0:8080 +auth: password +password: %user_password% +cert: false \ No newline at end of file diff --git a/instance_scripts/atrium_scripts/atrium.yaml b/instance_scripts/atrium_scripts/atrium.yaml deleted file mode 100644 index badb1c51084f904337285db8875e8291e05e2786..0000000000000000000000000000000000000000 --- a/instance_scripts/atrium_scripts/atrium.yaml +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index b947e39a17dbac0bae9f544c29be22edaf3c7f4e..0000000000000000000000000000000000000000 --- a/instance_scripts/atrium_scripts/deploy.sh +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100755 index 9650b16760d6e85b07c37c3e7ba6fadd0cc8e9fe..0000000000000000000000000000000000000000 --- a/instance_scripts/start_webtop.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/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 index 26561465b58c0c207d9c50f14f6fa1f8fe4530c9..70d8fdf6ba28f55ec1953353419dbcc09118148e 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -1,12 +1,3 @@ -############ -# Terraform SSH key -############ - -resource "scaleway_account_ssh_key" "ssh_key" { - name = "FORGE alpha_project_manager" - public_key = var.SCW_SSH_PUB_KEY -} - ############ # Public IP ############ @@ -23,7 +14,7 @@ resource "scaleway_instance_ip" "public_ip" { resource "scaleway_domain_record" "subdomain_record" { count = var.INSTANCES_COUNT dns_zone = "daag.alpha.grandlyon.com" - name = "lab-${count.index}-daag-${var.ENVIRONMENT}" + name = "${var.ENVIRONMENT}-${count.index}" type = "A" data = scaleway_instance_ip.public_ip[count.index].address ttl = 3600 @@ -32,7 +23,7 @@ resource "scaleway_domain_record" "subdomain_record" { resource "scaleway_domain_record" "host_subdomain_record" { count = var.INSTANCES_COUNT dns_zone = "daag.alpha.grandlyon.com" - name = "*.lab-${count.index}-daag-${var.ENVIRONMENT}" + name = "*.${var.ENVIRONMENT}-${count.index}" type = "A" data = scaleway_instance_ip.public_ip[count.index].address ttl = 3600 @@ -44,29 +35,20 @@ resource "scaleway_domain_record" "host_subdomain_record" { resource "scaleway_instance_security_group" "www" { project_id = var.SCW_PROJECT_ID - name = "security-group-daag-lab-${var.ENVIRONMENT}" + name = "security-group-${var.ENVIRONMENT}" inbound_default_policy = "drop" outbound_default_policy = "accept" inbound_rule { action = "accept" - port = "22" - } - - inbound_rule { - action = "accept" - port = "80" + port = "443" } inbound_rule { action = "accept" - port = "8080" + port = "22" } - inbound_rule { - action = "accept" - port = "443" - } } ############################## @@ -76,48 +58,24 @@ resource "scaleway_instance_security_group" "www" { 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}" + name = "instance${count.index}-${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 - ] -} + user_data = { + atrium_count_index = count.index + atrium_hostname = scaleway_domain_record.subdomain_record[count.index].name + atrium_letsencrypt_email = var.LETSENCRYPT_EMAIL + user_password = var.USER_PASSWORD + cloud-init = file("../instance-scripts/cloud-init.yml") + } -resource "null_resource" "provisioner" { - count = var.INSTANCES_COUNT depends_on = [ - scaleway_instance_server.user_instance_server + scaleway_instance_ip.public_ip, + scaleway_instance_security_group.www, + scaleway_domain_record.host_subdomain_record, + scaleway_domain_record.subdomain_record ] - - 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 index 62ee373c49d70cad84fd21fef9798cf3cec78f41..8779f0eaafa009f524e50ffd2284339db2eb5010 100644 --- a/terraform/output.tf +++ b/terraform/output.tf @@ -4,5 +4,5 @@ output "public_ip_address" { value = scaleway_instance_ip.public_ip[*].address - sensitive = false + sensitive = true } \ No newline at end of file diff --git a/terraform/variables-gitlab.tf b/terraform/variables-gitlab.tf index 5648602b9abf3899469de3818f4b354e31a3c51f..f324f2306af0a3ef5639d2efdecc7618a462e6ec 100644 --- a/terraform/variables-gitlab.tf +++ b/terraform/variables-gitlab.tf @@ -18,16 +18,16 @@ variable "SCW_SECRET_KEY" { description = "Scaleway secret key" } -variable "SCW_SSH_PUB_KEY" { +variable "LETSENCRYPT_EMAIL" { type = string sensitive = true - description = "SSH public key from Gitlab agent installed on scaleway" + description = "User password for accessing services" } -variable "SCW_SSH_PRIVATE_KEY" { +variable "USER_PASSWORD" { type = string sensitive = true - description = "SSH private key from Gitlab agent for remote-exec" + description = "User password for accessing services" } variable "INSTANCES_COUNT" {