commit e319adc501d6ecfc64747a6ba57af30b4a68a9fd Author: lhahn Date: Sun Aug 20 11:13:01 2023 +0200 Git initial commit diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..2071b23 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..5b96b7b --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# cloud-basis + +Ansible role to setup basic cloud configuration for a cloud node. +E.g.: mount volumes, setup user, install basic software and so on. \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100755 index 0000000..1153c25 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,113 @@ +--- +## BASIC CONFIG +cloud_update: false +cloud_name: cloud +cloud_home: "/opt/{{ cloud_name }}" +cloud_type: "cloud" +cloud_env: production +cloud_env_path: "{{ cloud_home }}/{{ cloud_env }}" +cloud_host_group: server +cloud_control_version: 1.0.0 +cloud_control_name: cloud-control +cloud_git_branch_main: main +cloud_stage: prod + +cloud_tzdata: Europe/Berlin + +cloud_apps: /opt +cloud_storage: /srv +cloud_python_envs: "{{ cloud_apps }}/pyenv" + +cloud_internal_dns: 1.1.1.1 + +basis_apps: + - passwd + - vim + - unzip + - resolvconf + + +## HARDWARE +mount_points: [] +# - path: /some/path +# dev: /dev/sdb +# fstype: ext4 +# opts: noatime +# state: mounted + + +swap_on: true +swap_file: /swapfile +#block size * block count = swap size (Bytes) +swap_block_size: 1024 +swap_block_count: 1048576 + + +## USER + GROUPS +shared_group: "{{ cloud_name }}" +default_groups: + - "ssh" + - "users" + - "cdrom" + - "{{ cloud_shared_group }}" +users: + - name: username + displayname: User Name + shell: /bin/bash + groups: + - sudo + - username + state: present + ssh_key: "ssh-rsa ABCDEF" + +## SSH +ssh_port: 22 +ssh_configs: + - Protocol 2 + - "Port {{ cloud_ssh_port }}" + - PermitRootLogin no + - PubkeyAuthentication yes + - PasswordAuthentication no + - PermitEmptyPasswords no + +## FAIL2BAN +fail2ban_bantime: 1h +fail2ban_maxretry: 3 +fail2ban_nginx_selfmade_filter: + - nginx-noscript + - nginx-nohome + - nginx-noproxy +fail2ban_nginx_default_filter: + - nginx-limit-req + - nginx-botsearch +fail2ban_activate_modules: + - sshd + - nginx + +## WIREGUARD +wireguard_enabled: True +wireguard_is_gateway: False +wireguard_allow_adjacent_client_traffic: False +wireguard_keepalive: 25 + +wireguard_gateway_interface: eth0 +wireguard_gateway_host: my-wireguard-server.tld +wireguard_gateway_port: 51820 +wireguard_gateway_net_prefix: 10.10.10 +wireguard_gateway_net_cidr: 28 +wireguard_gateway_public_key: your-public-key +wireguard_gateway_private_key: your-privat-key + +wireguard_gateway_forward: [] +# - server_port: 22 +# client_port: "{{ ssh_port }}" +# client_index: 0 + + +wireguard_client_host: my-wireguard-client +wireguard_clients: +# my-wireguard-client: +# index: 0 +# public_key: my-public-key +# private_key: my-private-key + diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100755 index 0000000..ab7b1e7 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,19 @@ +--- +- name: restart sshd service + service: + name: sshd + state: restarted + enabled: yes + +- name: restart fail2ban service + service: + name: fail2ban + state: restarted + enabled: yes + +- name: restart wireguard service + service: + name: wg-quick@{{ cloud_name }} + state: restarted + enabled: yes + when: wireguard_installed is defined and not wireguard_installed.changed \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100755 index 0000000..3c78dbc --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: + role_name: basis + namespace: hahn-cloud + author: Lars Hahn + company: OpenDevChain + license: MIT + description: Basis role to setup a basic system with ansible; e.g. Users, Fail2Ban, SSHD + min_ansible_version: 2.7 + platforms: + - name: Debian + versions: + - 10 + galaxy_tags: + - basis +dependencies: [] diff --git a/tasks/cloud_control.yml b/tasks/cloud_control.yml new file mode 100755 index 0000000..8bd2795 --- /dev/null +++ b/tasks/cloud_control.yml @@ -0,0 +1,8 @@ +--- +- name: setup Cloud Control script + template: + src: "templates{{ cloud_control_path }}/cloud-control.j2" + dest: "{{ cloud_control_path }}/{{ cloud_control_name }}" + owner: root + group: root + mode: 0754 diff --git a/tasks/fail2ban.yml b/tasks/fail2ban.yml new file mode 100755 index 0000000..21955ff --- /dev/null +++ b/tasks/fail2ban.yml @@ -0,0 +1,30 @@ +--- +- name: install fail2ban service + apt: + update_cache: yes + state: "{% if cloud_update | bool %}latest{% else %}present{% endif %}" + install_recommends: yes + pkg: fail2ban + +- name: setup fail2ban config jail.local + template: + backup: yes + src: "templates{{ fail2ban_jail_conf }}.j2" + dest: "{{ fail2ban_jail_conf }}" + owner: root + group: root + mode: 0644 + notify: restart fail2ban service + +- name: Install fail2ban filter plugins nginx + template: + src: "templates{{ fail2ban_path }}/filter.d/{{ filter }}.local.j2" + dest: "{{ fail2ban_path }}/filter.d/{{ filter }}.local" + owner: root + group: root + mode: 0644 + loop: "{{ fail2ban_nginx_filter }}" + loop_control: + label: "{{ filter }}" + loop_var: filter + notify: restart fail2ban service diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100755 index 0000000..858e182 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,64 @@ +--- +- name: Limit access to cloude home only for root + file: + state: directory + path: "{{ cloud_home }}" + owner: root + group: root + mode: 0700 + recurse: yes + +- name: Install basic apps via apt + apt: + update_cache: yes + autoclean: yes + autoremove: yes + state: latest + install_recommends: yes + pkg: "{{ basis_apps }}" + +- name: set timezone + timezone: + name: "{{ cloud_tzdata }}" + +- name: Setup hahn-cloud users + import_tasks: users.yml + +- name: Setup and configure sshd service + import_tasks: sshd.yml + +- name: Setup and configure fail2ban service + import_tasks: fail2ban.yml + +- name: Setup and configure cloud control script + import_tasks: cloud_control.yml + +- name: Setup mount points + import_tasks: mount.yml + +- name: Setup swap + import_tasks: swap.yml + when: swap_on + +- name: Setup basic cloud folders for apps and storage + file: + state: directory + path: "{{ item }}" + mode: 0755 + owner: root + group: "{{ shared_group }}" + loop: + - "{{ cloud_apps }}" + - "{{ cloud_storage }}" + +- name: Setup shared python environment for all cloud users + file: + state: directory + path: "{{ cloud_python_envs }}" + mode: 0755 + owner: root + group: "{{ shared_group }}" + +- name: Setup wireguard vpn + import_tasks: wireguard.yml + when: wireguard_enabled diff --git a/tasks/mount.yml b/tasks/mount.yml new file mode 100755 index 0000000..dd28f6a --- /dev/null +++ b/tasks/mount.yml @@ -0,0 +1,20 @@ +- name: generate filesystem on mounts if not defined + filesystem: + fstype: "{{ mnt.fstype | default('ext4') }}" + dev: "{{ mnt.dev }}" + loop: "{{ mount_points }}" + loop_control: + loop_var: mnt + label: "{{ mnt.dev }}: {{ mnt.fstype | default('ext4') }}" + +- name: mount required points + mount: + path: "{{ mnt.path }}" + src: "{{ mnt.dev }}" + state: "{{ mnt.state | default('mounted') }}" + fstype: "{{ mnt.fstype | default('ext4') }}" + opts: "{{ mnt.opts | default('defaults') }}" + loop: "{{ mount_points }}" + loop_control: + loop_var: mnt + label: "{{ mnt.dev }}: {{ mnt.path }}" \ No newline at end of file diff --git a/tasks/sshd.yml b/tasks/sshd.yml new file mode 100755 index 0000000..027f716 --- /dev/null +++ b/tasks/sshd.yml @@ -0,0 +1,21 @@ +--- +- name: install OpenSSH server + apt: + update_cache: yes + state: "{% if cloud_update | bool %}latest{% else %}present{% endif %}" + install_recommends: yes + pkg: openssh-server + +- name: setup sshd_config + lineinfile: + path: "{{ sshd_conf }}" + regexp: '^#?{{ configline.split(" ")[0] }}{% if configline.split(" ") | length > 1 %} {% endif %}' + line: "{{ configline }}" + owner: root + group: root + mode: 0644 + loop: "{{ ssh_configs }}" + loop_control: + loop_var: configline + label: "{{ configline }}" + notify: restart sshd service diff --git a/tasks/swap.yml b/tasks/swap.yml new file mode 100755 index 0000000..dd98ad0 --- /dev/null +++ b/tasks/swap.yml @@ -0,0 +1,35 @@ +--- +- name: generate file for swapping + command: + cmd: "dd if=/dev/zero of={{ swap_file }} bs={{ swap_block_size }} count={{ swap_block_count }}" + chdir: "/" + creates: "{{ swap_file }}" + register: swapfile_setup + +- name: prepare swap file + command: + cmd: "mkswap {{ swap_file }}" + chdir: "/" + when: swapfile_setup.changed + register: swapfile_creation + +- name: set swap permission + file: + path: "{{ swap_file }}" + mode: 0600 + +- name: activate swap + command: + cmd: "swapon {{ swap_file }}" + chdir: "/" + when: swapfile_creation.changed + +- name: mount swap on boot + mount: + path: none + src: "{{ swap_file }}" + fstype: swap + opts: sw + passno: 0 + dump: 0 + state: present diff --git a/tasks/users.yml b/tasks/users.yml new file mode 100755 index 0000000..85c776d --- /dev/null +++ b/tasks/users.yml @@ -0,0 +1,47 @@ +--- +- name: list active users + shell: cat /etc/passwd | grep -v "nologin" | cut -f 1 -d ":" + changed_when: false + register: active_users + +- name: Setup required groups of users + group: + name: "{{ group }}" + state: present + loop: "{{ ((users | json_query('[*].groups') | flatten) + default_groups) | unique }}" + loop_control: + loop_var: group + label: "{{ group }}" + +- name: Setup users + user: + name: "{{ user.name }}" + state: "{{ user.state }}" + comment: "{{ user.displayname }}" + group: "{{ user.name }}" + groups: "{{ default_groups | default([]) + user.groups }}" + append: yes + shell: "{{ user.shell }}" + loop: "{{ users }}" + loop_control: + loop_var: user + label: "{{ user.name }}" + register: new_user_setup + +- name: Setup User ssh_key + authorized_key: + user: "{{ user.name }}" + state: "{{ user.state | default('present') }}" + key: "{{ user.ssh_key }}" + loop: "{{ users | selectattr('ssh_key', 'defined') | list }}" + loop_control: + label: "{{ user.name }}" + loop_var: user + +- name: Activate password setup for newly created users + shell: " set -e pipefail; passwd -d {{ user }}; chage -d0 {{ user }}" + loop: "{{ new_user_setup | json_query('results[?changed==`true`].name') | difference(active_users.stdout_lines) }}" + loop_control: + label: "{{ user }}" + loop_var: user + when: new_user_setup.changed diff --git a/tasks/wireguard.yml b/tasks/wireguard.yml new file mode 100644 index 0000000..677b2b1 --- /dev/null +++ b/tasks/wireguard.yml @@ -0,0 +1,34 @@ +--- +- name: install fail2ban service + apt: + update_cache: yes + state: "{% if cloud_update | bool %}latest{% else %}present{% endif %}" + install_recommends: yes + pkg: wireguard + register: wireguard_installed + +- name: setup key files + template: + src: "etc/wireguard/{{ item }}.j2" + dest: "/etc/wireguard/{{ item }}" + owner: root + mode: 0600 + loop: + - private.key + - public.key + notify: restart wireguard service + +- name: setup wireguard config + template: + src: "etc/wireguard/wireguard-{% if wireguard_is_gateway %}server{% else %}client{% endif %}.conf.j2" + dest: "/etc/wireguard/{{ cloud_name }}.conf" + owner: root + mode: 0600 + notify: restart wireguard service + +- name: enable wireguard systemd unit + systemd: + name: wg-quick@{{ cloud_name }} + enabled: yes + daemon_reload: yes + state: started diff --git a/templates/etc/fail2ban/filter.d/nginx-nohome.local.j2 b/templates/etc/fail2ban/filter.d/nginx-nohome.local.j2 new file mode 100755 index 0000000..9a6994e --- /dev/null +++ b/templates/etc/fail2ban/filter.d/nginx-nohome.local.j2 @@ -0,0 +1,5 @@ +[Definition] + +failregex = ^ -.*GET .*/~.* + +ignoreregex = \ No newline at end of file diff --git a/templates/etc/fail2ban/filter.d/nginx-noproxy.local.j2 b/templates/etc/fail2ban/filter.d/nginx-noproxy.local.j2 new file mode 100755 index 0000000..e6742db --- /dev/null +++ b/templates/etc/fail2ban/filter.d/nginx-noproxy.local.j2 @@ -0,0 +1,5 @@ +[Definition] + +failregex = ^ -.*GET http.* + +ignoreregex = \ No newline at end of file diff --git a/templates/etc/fail2ban/filter.d/nginx-noscript.local.j2 b/templates/etc/fail2ban/filter.d/nginx-noscript.local.j2 new file mode 100755 index 0000000..900d07f --- /dev/null +++ b/templates/etc/fail2ban/filter.d/nginx-noscript.local.j2 @@ -0,0 +1,5 @@ +[Definition] + +failregex = ^ -.*GET.*(\.asp|\.exe|\.pl|\.cgi|\.scgi) + +ignoreregex = diff --git a/templates/etc/fail2ban/jail.local.j2 b/templates/etc/fail2ban/jail.local.j2 new file mode 100755 index 0000000..61f8e54 --- /dev/null +++ b/templates/etc/fail2ban/jail.local.j2 @@ -0,0 +1,34 @@ +[DEFAULT] +bantime = {{ fail2ban_bantime }} +findtime = {{ fail2ban_bantime }} +maxretry = {{ fail2ban_maxretry }} + +[sshd] +enabled = true +port = 22,{{ ssh_port }},ssh + +[nginx-http-auth] +enabled = {{ 'nginx' in fail2ban_activate_modules }} +port = http,https +filter = nginx-noscript +logpath = %(nginx_error_log)s +maxretry = 6 + +{% for filter in fail2ban_nginx_default_filter %} +[{{ filter }}] +enabled = {{ 'nginx' in fail2ban_activate_modules }} +port = http,https +filter = {{ filter }} +logpath = %(nginx_access_log)s +maxretry = 2 + +{% endfor %} +{% for filter in fail2ban_nginx_selfmade_filter %} +[{{ filter }}] +enabled = {{ 'nginx' in fail2ban_activate_modules }} +port = http,https +filter = {{ filter }} +logpath = %(nginx_access_log)s +maxretry = 2 + +{% endfor %} diff --git a/templates/etc/ssh/sshd_config.j2 b/templates/etc/ssh/sshd_config.j2 new file mode 100755 index 0000000..dd0a119 --- /dev/null +++ b/templates/etc/ssh/sshd_config.j2 @@ -0,0 +1,121 @@ +# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ + +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options override the +# default value. +Protocol {{ ssh_protocol_version }} +Port {{ ssh_port }} +#AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +#HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_ecdsa_key +#HostKey /etc/ssh/ssh_host_ed25519_key + +# Ciphers and keying +#RekeyLimit default none + +# Logging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 10m +PermitRootLogin {{ ssh_login_root }} +#StrictModes yes +#MaxAuthTries 6 +#MaxSessions 10 + +PubkeyAuthentication {{ ssh_use_key }} + +# Expect .ssh/authorized_keys2 to be disregarded by default in future. +#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 + +#AuthorizedPrincipalsFile none + +#AuthorizedKeysCommand none +#AuthorizedKeysCommandUser nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication {{ ssh_use_password }} +PermitEmptyPasswords no + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication no + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM yes + +#AllowAgentForwarding yes +#AllowTcpForwarding yes +#GatewayPorts no +X11Forwarding no +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes +PrintMotd no +#PrintLastLog yes +#TCPKeepAlive yes +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS no +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +# override default of no subsystems +Subsystem sftp /usr/lib/openssh/sftp-server + +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# PermitTTY no +# ForceCommand cvs server diff --git a/templates/etc/wireguard/private.key.j2 b/templates/etc/wireguard/private.key.j2 new file mode 100644 index 0000000..b1b6e56 --- /dev/null +++ b/templates/etc/wireguard/private.key.j2 @@ -0,0 +1 @@ +{% if not wireguard_is_gateway %}{{ wireguard_clients[wireguard_client_host].private_key }}{% else %}{{ wireguard_gateway_private_key }}{% endif %} \ No newline at end of file diff --git a/templates/etc/wireguard/public.key.j2 b/templates/etc/wireguard/public.key.j2 new file mode 100644 index 0000000..7817ebc --- /dev/null +++ b/templates/etc/wireguard/public.key.j2 @@ -0,0 +1 @@ +{% if not wireguard_is_gateway %}{{ wireguard_clients[wireguard_client_host].public_key }}{% else %}{{ wireguard_gateway_public_key }}{% endif %} \ No newline at end of file diff --git a/templates/etc/wireguard/wireguard-client.conf.j2 b/templates/etc/wireguard/wireguard-client.conf.j2 new file mode 100644 index 0000000..f5a6e3e --- /dev/null +++ b/templates/etc/wireguard/wireguard-client.conf.j2 @@ -0,0 +1,11 @@ +[Interface] +Address = {{ wireguard_gateway_net_prefix }}.{{ wireguard_clients[wireguard_client_host].index }}/32 +PrivateKey = {{ wireguard_clients[wireguard_client_host].private_key }} +DNS = {{ cloud_internal_dns }} + +[Peer] +PublicKey = {{ wireguard_gateway_public_key }} +Endpoint = {{ wireguard_gateway_host }}:{{ wireguard_gateway_port }} +AllowedIPs = {{ wireguard_gateway_net_prefix }}.1/{% if wireguard_allow_adjacent_client_traffic %}{{ wireguard_gateway_net_cidr }}{% else %}32{% endif %} + +PersistentKeepalive = {{ wireguard_keepalive }} diff --git a/templates/etc/wireguard/wireguard-server.conf.j2 b/templates/etc/wireguard/wireguard-server.conf.j2 new file mode 100644 index 0000000..419e54a --- /dev/null +++ b/templates/etc/wireguard/wireguard-server.conf.j2 @@ -0,0 +1,25 @@ +[Interface] +Address = {{ wireguard_gateway_net_prefix }}.1/{{ wireguard_gateway_net_cidr }} +ListenPort = {{ wireguard_gateway_port }} +PrivateKey = {{ wireguard_gateway_private_key }} + +{% if wireguard_gateway_forward is defined and wireguard_gateway_forward | length > 0 %} +PreUp = sysctl -w net.ipv4.ip_forward=1 +PreUp = sysctl -w net.ipv6.conf.all.forwarding=1 + +{% for config in wireguard_gateway_forward %} +PreUp = iptables -t nat -A PREROUTING -i {{ wireguard_gateway_interface }} -p tcp --dport {{ config.server_port }} -j DNAT --to-destination {{ wireguard_gateway_net_prefix }}.{{ config.client_index }}:{{ config.client_port }} +PostDown = iptables -t nat -D PREROUTING -i {{ wireguard_gateway_interface }} -p tcp --dport {{ config.server_port }} -j DNAT --to-destination {{ wireguard_gateway_net_prefix }}.{{ config.client_index }}:{{ config.client_port }} + +{% endfor %} +PreUp = iptables -t nat -A POSTROUTING -o {{ cloud_name }} -j MASQUERADE +PostDown = iptables -t nat -D POSTROUTING -o {{ cloud_name }} -j MASQUERADE +{% endif %} + +{% for client in wireguard_clients %} +## Wireguard {{ cloud_name }} - {{ client }} ## +[Peer] +PublicKey = {{ wireguard_clients[client].public_key }} +AllowedIPs = {{ wireguard_gateway_net_prefix }}.{{ wireguard_clients[client].index }}/32 + +{% endfor %} \ No newline at end of file diff --git a/templates/usr/local/bin/cloud-control.j2 b/templates/usr/local/bin/cloud-control.j2 new file mode 100755 index 0000000..6179181 --- /dev/null +++ b/templates/usr/local/bin/cloud-control.j2 @@ -0,0 +1,155 @@ +#!/bin/bash +set -e + + +### VARIABLE ################################################################### +environment_folder={{ cloud_env_path }} +environment="{{ cloud_env }}" +host_type="{{ cloud_host_group }}" +script_name=$(basename $0) +cloud_name="{{ cloud_name }}" +cloud_type="{{ cloud_type }}" +version="{{ cloud_control_version }}" +branch_main="{{ cloud_git_branch_main }}" +################################################################################ + + + +### FUNCTION ################################################################### +to_working_directory() { + if [ ! -d $environment_folder/.git ] || [ ! -d $environment_folder ]; then + echo "Environment '$environment' in '$environment_folder' not available or folder not a git repository! Abort." + exit 1 + fi + cd $environment_folder/$environment +} + +help() { + echo "$script_name, version $version by L.Hahn" + echo "" + echo " $cloud_name script for cloud control" + echo " You can checkout environment (branches), rollout configurations," + echo " run ansible and restore entire configurations." + echo "" + echo "Usage: $script_name [command] [options]" + echo "" + echo "commands:" + echo " - help print this help" + echo " - maintenance setup local server into maintenance mode; no automatic ansible call" + echo " - environment" + echo " download checkout from remote repository" + echo " update load latest remote changes for current branch" + echo " reset stash changes and reset current branch from remote repository with latest changes" + echo " restore checkout latest $branch_main branch from remote repository" + echo " - update get latest roles according to environment requirements.yml" + echo " - play play current loaded ansible playbooks" + echo " - reset perform 1. environment restore, 2. update, 3. execute" + echo "" + echo "" + echo "example:" + echo "~# $script_name environment update" + echo " this will download changes from the currently active remote branch" +} + +environment() { + to_working_directory + current_branch=$(git branch | grep "^\*" | cut -d " " -f 2) + current_upstream=$(git rev-parse $current_branch@{upstream}) + + env_option=$1 + case $env_option in + "update") + echo "### Updating branch '$current_branch' in $environment_folder ###" + git pull + ;; + "reset") + echo "### Resetting branch '$current_branch' in $environment_folder ###" + git reset --hard $current_branch + git pull + ;; + "restore") + echo "### Restoring branch '$branch_main' in $environment_folder ###" + git reset --hard HEAD + git clean -f + git checkout $branch_main + git pull + ;; + "download") + if [ $# -lt 2 ]; then + echo "Missing branch name for environment downloading" + exit 1 + fi + echo "### Stashing branch '$current_branch' & downloading branch '$2' in $environment_folder ###" + git stash + git checkout -b $2 origin/$2 + git pull + ;; + *) + echo "Unknown environments option '$env_option', abort!" + exit 1 + ;; + esac +} + +maintenance() { + to_working_directory + echo "maint" +} + +update() { + to_working_directory + ansible-galaxy install -f -p roles/ -r requirements.yml +} + +play() { + to_working_directory + ansible-playbook $cloud_type"-"$host_type".yml" +} +################################################################################ + + +### MAIN ####################################################################### +if [ $# -eq 0 ]; then + help + exit 1 +fi +script_command=$1 + +case $script_command in + "help") + help + ;; + "maintenance") + maintenance + ;; + "environment") + if [ $# -lt 2 ]; then + echo "ERROR! environment command needs options! None provided." + echo "Call '~# $script_name help' for more information." + exit 1 + fi + environment $2 $3 + ;; + "update") + update + ;; + "play") + play + ;; + "reset") + echo "#=== restore environment ===#" + environment restore + echo "" + echo "#=== update roles ===#" + update + echo "" + echo "#=== play playbook ===#" + play + echo "" + ;; + *) + echo "Unknown command '$script_command', abort!" + echo "Call '~# $script_name help' for more information." + ;; +esac +################################################################################ \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml new file mode 100755 index 0000000..9598da3 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,7 @@ +--- +sshd_path: "/etc/ssh" +sshd_conf: "{{ sshd_path }}/sshd_config" +fail2ban_path: "/etc/fail2ban" +fail2ban_jail_conf: "{{ fail2ban_path }}/jail.local" + +cloud_control_path: "/usr/local/bin"