Add terraform files

This commit is contained in:
Glenn Y. Rolland 2022-05-26 17:31:39 +02:00
commit ad77d0317a
27 changed files with 524 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.vagrant

28
README.md Normal file
View file

@ -0,0 +1,28 @@
## Web SSH terminal
* sshwifty (go)
* webssh (python)
https://hub.docker.com/r/snsyzb/webssh
* Guacamole
* Bastillion
https://github.com/bastillion-io/Bastillion
* SSHy
https://github.com/stuicey/SSHy
* ssh-web-console
https://github.com/genshen/ssh-web-console
* webssh2
https://github.com/billchurch/webssh2
* webssh
https://github.com/huashengdun/webssh
* https://github.com/gravitational/teleport
* https://github.com/roke22/PHP-SSH2-Web-Client
* https://www.shellvault.io/
* https://github.com/huashengdun/webssh
* https://github.com/xtermjs/xterm.js/
## Terraform + Ansible
https://www.digitalocean.com/community/tutorials/how-to-use-ansible-with-terraform-for-configuration-management

52
Vagrantfile vendored Normal file
View file

@ -0,0 +1,52 @@
# -*- mode: ruby -*-
# vi: set ft=ruby sw=2 st=2 et :
# frozen_string_literal: true
SERVERS_COUNT=3
Vagrant.configure('2') do |config|
# Common settings for virtual machines
config.vm.box = 'debian/bullseye64'
config.vm.box_check_update = false
##
## gateway: Guacamole proxy + entrypoint
##
config.vm.define 'gateway' do |machine|
machine.vm.hostname = 'gateway'
machine.vm.network 'private_network', ip: '192.168.50.250'
machine.vm.network 'forwarded_port', guest: 80, host: 1080
machine.vm.network 'forwarded_port', guest: 8080, host: 8080
machine.vm.provider 'virtualbox' do |vb|
vb.memory = '4000'
vb.gui = false
end
end
##
## serverX : host servers with mongo, etc
##
server_ip = ->(index) { "192.168.50.#{10 + index * 10}" }
SERVERS_COUNT.times do |index|
config.vm.define "server#{index}" do |machine|
machine.vm.hostname = "server#{index}"
machine.vm.network 'private_network', ip: server_ip.call(index)
machine.vm.provider 'virtualbox' do |vb|
vb.memory = '3000'
vb.gui = false
end
end
end
config.vm.provision 'ansible' do |ansible|
ansible.playbook = 'ansible/playbook.yml'
# ansible.verbose = true
ansible.config_file = 'ansible/ansible.cfg'
ansible.groups = {
'app_sshwifty' => ['gateway'],
'app_mongo' => SERVERS_COUNT.times.map { |i| "server#{i}" },
'all_groups:children' => ['app_mongo']
}
end
end

3
ansible/ansible.cfg Normal file
View file

@ -0,0 +1,3 @@
[ssh_connection]
ssh_args=-o ControlMaster=auto -o ControlPersist=7200s
pipelining=True

View file

@ -0,0 +1,2 @@
---
sshwifty_shared_key: admin

View file

@ -0,0 +1 @@
../../terraform/outputs/inventory

1
ansible/inventories/vagrant Symbolic link
View file

@ -0,0 +1 @@
../../.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory

26
ansible/playbook.yml Normal file
View file

@ -0,0 +1,26 @@
---
- hosts: app_sshwifty
become: true
tasks:
- include_tasks: tasks/setup_base.yml
- include_tasks: tasks/setup_docker.yml
- include_tasks: tasks/setup_sshwifty.yml
- include_tasks: tasks/setup_caddy.yml
- include_tasks: tasks/setup_sshaccess.yml
roles:
- role: caddy_ansible.caddy_ansible
caddy_setcap: 'yes'
caddy_systemd_network_dependency: false
caddy_systemd_capabilities_enabled: true
caddy_config: "{{ lookup('template', 'templates/Caddyfile.j2') }}"
- hosts: app_mongo
become: true
tasks:
- include_tasks: tasks/setup_base.yml
- include_tasks: tasks/setup_docker.yml
- include_tasks: tasks/setup_mongo.yml
- include_tasks: tasks/setup_sshaccess.yml
#

6
ansible/requirements.yml Normal file
View file

@ -0,0 +1,6 @@
---
roles:
- name: caddy_ansible.caddy_ansible
src: https://github.com/caddy-ansible/caddy-ansible
type: git
version: master

View file

@ -0,0 +1,20 @@
---
- name: Sync time
ansible.builtin.shell:
cmd: ntpdate 0.debian.pool.ntp.org
ignore_errors: yes
- name: Install required system packages
ansible.builtin.apt:
name:
- vim
- ntpdate
state: latest
update_cache: true
- name: Sync time
ansible.builtin.command:
cmd: ntpdate 0.debian.pool.ntp.org
#

View file

View file

@ -0,0 +1,59 @@
---
- name: Install required system packages
ansible.builtin.apt:
name:
- apt-transport-https
- ca-certificates
- curl
- software-properties-common
- python3-pip
- virtualenv
- python3-setuptools
state: latest
update_cache: true
- name: Create keyring directory
ansible.builtin.file:
dest: /etc/apt/keyrings
state: directory
- name: Add signing key
ansible.builtin.get_url:
url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg"
dest: /etc/apt/keyrings/docker.gpg_armored
- name: De-Armor Docker GPG key
shell: >
gpg --dearmor
< /etc/apt/keyrings/docker.gpg_armored
> /etc/apt/keyrings/docker.gpg
# no_log: true
args:
creates: /etc/apt/keyrings/docker.gpg
- name: Get DEB architecture
shell: dpkg --print-architecture
register: deb_architecture
- name: Add repository into sources list
ansible.builtin.apt_repository:
repo: "deb [arch={{ deb_architecture.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
state: present
filename: docker
- name: Install Docker
ansible.builtin.apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
- docker-compose
state: latest
update_cache: true
- name: Install Docker Module for Python
pip:
name: docker
#

View file

View file

@ -0,0 +1,12 @@
---
# Password needs to be encrypted. Use the following command to change password
# python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'
- name: Add the user 'debian'
ansible.builtin.user:
name: debian
password: '$6$7SKND.wc64QSchcm$eGS36vIXypLHSd.PQM0gIq6ILx9QiRQxWNej3Gb32sKk2MuLrRlceXCJmidYATNZeJTbBXNf3c5qTmm7BB.EA1'
shell: /bin/bash
state: present
update_password: always
#

View file

@ -0,0 +1,30 @@
---
- name: Install required system packages
ansible.builtin.apt:
name:
- vim
state: latest
update_cache: true
- name: Deploy SSHwifty configuration
template:
src: templates/sshwifty.conf.j2
dest: /etc/sshwifty.conf
- name: Create SSHwifty directory
file:
path: /var/lib/sshwifty
state: directory
- name: Deploy SSHwifty configuration
template:
src: templates/docker-compose.yml.j2
dest: /var/lib/sshwifty/docker-compose.yml
- name: Run SSHwifty
community.docker.docker_compose:
project_src: /var/lib/sshwifty
recreate: smart
state: present
#

View file

@ -0,0 +1,11 @@
http://0.0.0.0:80 {
log
reverse_proxy http://localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
}
}

View file

@ -0,0 +1,21 @@
---
# vim: set ts=2 sw=2 et ft=yaml :
version: "3.4"
services:
sshwifty:
image: niruix/sshwifty:latest
restart: always
ports:
- 8080:8182
environment:
SSHWIFTY_SHAREDKEY: admin
SSHWIFTY_CONFIG: /etc/sshwifty.conf
volumes:
- /etc/sshwifty.conf:/etc/sshwifty.conf
volumes: {}
networks: {}
#

View file

@ -0,0 +1,48 @@
{
{# "HostName": "localhost", #}
"SharedKey": "{{ sshwifty_shared_key }}",
"DialTimeout": 10,
"Servers": [
{
"ListenInterface": "0.0.0.0",
"ListenPort": 8182,
"InitialTimeout": 3,
"ReadTimeout": 60,
"WriteTimeout": 60,
"HeartbeatTimeout": 20,
"ReadDelay": 10,
"WriteDelay": 10 {# , #}
{# "TLSCertificateFile": "", #}
{# "TLSCertificateKeyFile": "" #}
}
],
"Presets": [
{
"Title": "Gateway",
"Type": "SSH",
"Host": "{{ansible_facts.all_ipv4_addresses | ansible.netcommon.ipaddr('192.168.50.0/24') | first }}:22",
"Meta": {
"User": "debian",
"Encoding": "utf-8",
"Password": "debian",
"Authentication": "Password" {# , #}
{# "Private Key": "file:///home/user/.ssh/private_key", #}
{# "Fingerprint": "SHA256:bgO...." #}
}
},
{
"Title": "SDF.org Unix Shell",
"Type": "SSH",
"Host": "sdf.org:22",
"Meta": {
"User": "debian",
"Encoding": "utf-8",
"Password": "debian",
"Authentication": "Password" {# , #}
{# "Private Key": "file:///home/user/.ssh/private_key", #}
{# "Fingerprint": "SHA256:bgO...." #}
}
}
],
"OnlyAllowPresetRemotes": true
}

4
terraform/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.terraform
.terraform.lock.hcl
outputs/*
*.tfstate*

18
terraform/domains.tf Normal file
View file

@ -0,0 +1,18 @@
resource "gandi_livedns_record" "gateways_exploreko_org" {
count = var.mongo_groups_count
zone = var.domain_name
name = "gateway${count.index}.teaching"
type = "A"
ttl = 3600
values = [openstack_compute_instance_v2.mongo_gateway[count.index].access_ip_v4]
}
resource "gandi_livedns_record" "mongos_exploreko_org" {
count = var.mongo_replicas_count * var.mongo_groups_count
zone = var.domain_name
name = "mongo${count.index}.teaching"
type = "A"
ttl = 3600
values = [openstack_compute_instance_v2.mongo_servers[count.index].access_ip_v4]
}

68
terraform/instances.tf Normal file
View file

@ -0,0 +1,68 @@
# Création d'une ressource de paire de clés SSH
resource "openstack_compute_keypair_v2" "provision_keypair" {
provider = openstack.ovh
name = "provision_keypair"
public_key = file(var.ssh_public_key)
}
resource "openstack_compute_instance_v2" "mongo_gateway" {
count = var.mongo_groups_count
name = "prod-gateway${count.index}" # Nom de l'instance
provider = openstack.ovh # Nom du fournisseur
image_name = "Debian 11" # Nom de l'image
flavor_name = "s1-2" # Nom du type d'instance
# flavor_name = "s1-8" # Nom du type d'instance
# flavor_name = "d2-8" # Nom du type d'instance
# Nom de la ressource openstack_compute_keypair_v2 nommée test_keypair
key_pair = openstack_compute_keypair_v2.provision_keypair.name
metadata = {
ansible-group = "gateways"
mongo-group-id = count.index
}
# Ajoute le composant réseau pour atteindre votre instance
network {
name = "Ext-Net"
}
# provisioner "local-exec" {
# command = "ansible-playbook -i inventories/terraform --private-key ${var.ssh_private_key} -e 'pub_key=${var.ssh_public_key}' playbook.yml --limit ${self.name}"
# working_dir = "../ansible"
# environment = {
# ANSIBLE_HOST_KEY_CHECKING = "False"
# }
# }
}
# Création d'une instance
resource "openstack_compute_instance_v2" "mongo_servers" {
count = var.mongo_replicas_count * var.mongo_groups_count
name = "prod-server${count.index}" # Nom de l'instance
provider = openstack.ovh # Nom du fournisseur
image_name = "Debian 11" # Nom de l'image
flavor_name = "s1-2" # Nom du type d'instance
# flavor_name = "s1-8" # Nom du type d'instance
# flavor_name = "d2-8" # Nom du type d'instance
# Nom de la ressource openstack_compute_keypair_v2 nommée test_keypair
key_pair = openstack_compute_keypair_v2.provision_keypair.name
metadata = {
ansible-group = "mongos"
mongo-group-id = floor(count.index / var.mongo_replicas_count)
mongo-group-index = count.index % var.mongo_replicas_count
}
# Ajoute le composant réseau pour atteindre votre instance
network {
name = "Ext-Net"
}
# provisioner "local-exec" {
# command = "cd ../ansible && ansible-playbook -i inventories/terraform --private-key ${var.ssh_private_key} -e 'pub_key=${var.ssh_public_key}' playbook.yml --limit ${self.name}"
# environment = {
# ANSIBLE_HOST_KEY_CHECKING = "False"
# }
# }
}

12
terraform/output.tf Normal file
View file

@ -0,0 +1,12 @@
resource "local_file" "ansible_inventory" {
content = templatefile("templates/inventory.tmpl",
{
mongo_gateways = openstack_compute_instance_v2.mongo_gateway.*
mongo_servers = openstack_compute_instance_v2.mongo_servers.*
mongo_groups_count = var.mongo_groups_count
mongo_replicas_count = var.mongo_replicas_count
}
)
filename = "outputs/inventory"
file_permission = "0644"
}

0
terraform/outputs/.empty Normal file
View file

37
terraform/provider.tf Normal file
View file

@ -0,0 +1,37 @@
terraform {
required_version = ">= 0.14.0" # Prend en compte les versions de terraform à partir de la 0.14.0
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 1.42.0"
}
ovh = {
source = "ovh/ovh"
version = ">= 0.13.0"
}
gandi = {
source = "go-gandi/gandi"
version = "~> 2.0.1"
}
}
}
provider "gandi" {
key = "${var.gandi_key}"
}
provider "openstack" {
auth_url = "https://auth.cloud.ovh.net/v3/" # URL d'authentification
domain_name = "default" # Toujours à "default" pour OVHcloud
alias = "ovh" # Un alias
region = "GRA5"
}
provider "ovh" {
endpoint = "ovh-eu" # Provider entry point
alias = "ovh" # Provider alias
}

View file

@ -0,0 +1,4 @@
# provisioner "local-exec" {
# command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i outputs/inventory --private-key ${var.private_key} -e 'pub_key=${var.pub_key}' playbook.yml"
# }

View file

@ -0,0 +1,40 @@
%{ for index, instance in mongo_gateways ~}
${ instance.name } ansible_user=debian ansible_host=${instance.network[0].fixed_ip_v4}
%{ endfor ~}
%{ for index, instance in mongo_servers ~}
${ instance.name } ansible_user=debian ansible_host=${instance.network[0].fixed_ip_v4}
%{ endfor ~}
[stage_development]
[stage_testing]
[stage_production]
%{ for index, instance in mongo_gateways ~}
${ instance.name }
%{ endfor ~}
%{ for index, instance in mongo_servers ~}
${ instance.name }
%{ endfor ~}
[role_gateway]
%{ for index, instance in mongo_gateways ~}
${ instance.name }
%{ endfor ~}
[role_mongo]
%{ for index, instance in mongo_servers ~}
${ instance.name }
%{ endfor ~}
[all_groups:children]
role_gateway
role_mongo
stage_development
stage_testing
stage_production
[all:vars]
mongo_groups_count = ${ mongo_groups_count }
mongo_replicas_count = ${ mongo_replicas_count }

20
terraform/variables.tf Normal file
View file

@ -0,0 +1,20 @@
variable "mongo_groups_count" {
default = "1"
description = "How many replicas per mongo"
}
variable "mongo_replicas_count" {
default = "2"
description = "How many replicas per mongo group"
}
variable "ssh_private_key" {}
variable "ssh_public_key" {}
variable "gandi_key" {}
variable "domain_name" {}