From 197ac5d0ef87bd6fbaaa30ad8f40973e380d60e9 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Wed, 9 Feb 2022 21:46:01 -0500 Subject: [PATCH] Day three: enhance SSH security in two separate phases. Closes #3 --- day3_geninventory_phase1.sh | 39 ++++++++++++++++++++++++++++++++ day3_geninventory_phase2.sh | 44 ++++++++++++++++++++++++++++++++++++ phase1user.yml | 45 +++++++++++++++++++++++++++++++++++++ phase2user.yml | 38 +++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100755 day3_geninventory_phase1.sh create mode 100755 day3_geninventory_phase2.sh create mode 100644 phase1user.yml create mode 100644 phase2user.yml diff --git a/day3_geninventory_phase1.sh b/day3_geninventory_phase1.sh new file mode 100755 index 0000000..e65b7a9 --- /dev/null +++ b/day3_geninventory_phase1.sh @@ -0,0 +1,39 @@ +# +# Day 3 - Generate Inventory (Phase 1: tachyon user) +# Requires linode-cli to be installed (`pip3 install linode-cli`) +# The hosts file generated requires ansible (`pip3 install ansible`) +# This will crush any ansible.cfg and hosts files in the current directory. + +# Default ansible group and linode label +if [ -z "$CATEGORY" ] +then + CATEGORY="UpskillChallengeNode" +fi + +if [ -z "$ADMINUSER" ] +then + ADMINUSER="tachyon" +fi + +# fetch IP address from Linode. Assumes one device (TODO: handle a swarm of them). +NODEIP=$(linode-cli linodes list --format 'ipv4' --label "$CATEGORY" --text | tail -n 1) + +# create or clobber hosts file +cat > hosts << EOF +[$CATEGORY] +$NODEIP ansible_user=$ADMINUSER + +[$CATEGORY:vars] +ansible_ssh_user=$ADMINUSER +ansible_become=yes +ansible_become_user=root +ansible_become_method=sudo +EOF + +# create or clobber hosts file +cat > ansible.cfg << EOF +[defaults] +inventory = $(pwd)/hosts +EOF + +ansible "$CATEGORY" -m ping diff --git a/day3_geninventory_phase2.sh b/day3_geninventory_phase2.sh new file mode 100755 index 0000000..f83820f --- /dev/null +++ b/day3_geninventory_phase2.sh @@ -0,0 +1,44 @@ +# +# Day 3 - Generate Inventory (Phase 2: tachyon user on obscure port) +# Requires linode-cli to be installed (`pip3 install linode-cli`) +# The hosts file generated requires ansible (`pip3 install ansible`) +# This will crush any ansible.cfg and hosts files in the current directory. + +# Default ansible group and linode label +if [ -z "$CATEGORY" ] +then + CATEGORY="UpskillChallengeNode" +fi + +if [ -z "$ADMINUSER" ] +then + ADMINUSER="tachyon" +fi + +if [ -z "$NODESSHPORT" ] +then + NODESSHPORT=22022 +fi + +# fetch IP address from Linode. Assumes one device (TODO: handle a swarm of them). +NODEIP=$(linode-cli linodes list --format 'ipv4' --label "$CATEGORY" --text | tail -n 1) + +# create or clobber hosts file +cat > hosts << EOF +[$CATEGORY] +$NODEIP:$NODESSHPORT ansible_user=$ADMINUSER + +[$CATEGORY:vars] +ansible_ssh_user=$ADMINUSER +ansible_become=yes +ansible_become_user=root +ansible_become_method=sudo +EOF + +# create or clobber hosts file +cat > ansible.cfg << EOF +[defaults] +inventory = $(pwd)/hosts +EOF + +ansible "$CATEGORY" -m ping diff --git a/phase1user.yml b/phase1user.yml new file mode 100644 index 0000000..9068922 --- /dev/null +++ b/phase1user.yml @@ -0,0 +1,45 @@ +--- +- name: Create admin user + hosts: UpskillChallengeNode + + vars: + newusername: "tachyon" + + vars_prompt: + - name: "passhash" + prompt: "Password for the user account" + private: yes + encrypt: "sha512_crypt" + confirm: yes + + tasks: + - name: install sudo + ansible.builtin.apt: + package: sudo + state: present + + - name: create user + ansible.builtin.user: + name: "{{ newusername }}" + password: "{{ passhash }}" + groups: + - sudo + state: present + shell: /bin/bash + createhome: yes + + - name: set public key authentication + ansible.posix.authorized_key: + user: "{{ newusername }}" + key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDjO4ZEQxOZk0IZ1JgRP0AsO6/mIxSB8lojjq+dX2oIH8VTS2UxnwsrKx0DMn+qomUWk4HuYwRwPpWjP68+C+t3hqehhXpdM83YE+favA/VEtbTJnLVf0dq3RPzxuvtYsfpaiYF8/ctEaLAiXIgcpIAf0jOv7FTNADUBLhsV1KbpWneJqKquqroE1e6lCPoU968yWeZkzxCx8VpQ7uBDktJTosLNsm7wEtiKmlSdVE0cYUrNS+/VIoNE2Fr5xjqOlZHFhM5BBlUqqiVxWSpGizr+CGq+xhuOByGtqLgnmvju8oG2KkYhN/5LTMCRtpTwgRmjdU6oA7a8psFyu16iMpupmhPTc0aT3F7X5fiCWOiYDF0VvYNLVYRXzqm9UOy5OI3fCFnvERaheiNEm484OgWm/kUqHQWqlN30Tk9POY022QsDAVKPMCG3kSsAeM1LFsZE1fsleG31g5yicLqgQbw/v2fqGvklT0z5D2uXXuUEqM0aBNSysLWYvChGTfUZtk= john@arecibo + + + - name: grant {{ newusername }} passwordless sudo access + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: '^%sudo' + line: "%sudo ALL=(ALL:ALL) NOPASSWD: ALL" + validate: 'visudo -cf %s' + + + diff --git a/phase2user.yml b/phase2user.yml new file mode 100644 index 0000000..27df0b8 --- /dev/null +++ b/phase2user.yml @@ -0,0 +1,38 @@ +--- +- name: Lock down root & SSH on the server + hosts: UpskillChallengeNode + + tasks: + - name: Disable root login over ssh + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^PermitRootLogin' + line: 'PermitRootLogin no' + + - name: Disable all users' password login + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^PasswordAuthentication' + line: 'PasswordAuthentication no' + + - name: Change SSH port + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^#?Port ' + line: 'Port 22022' + + - name: update and upgrade packages + ansible.builtin.apt: + update_cache: yes + upgrade: yes + + - name: install fail2ban + ansible.builtin.apt: + package: fail2ban + state: present + + - name: restart ssh + service: + name: ssh + state: restarted +