Compare commits

..

5 Commits

12 changed files with 1735 additions and 0 deletions

View File

@ -23,6 +23,10 @@ EOF
cat > ansible.cfg << EOF
[defaults]
inventory = $(pwd)/hosts
[ssh_connection]
ssh_args = "-o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey"
pipelining = true
EOF
ansible "$CATEGORY" -m ping

31
day2_exitcodeprompt.sh Normal file
View File

@ -0,0 +1,31 @@
#!/bin/bash
#
# Day 2 - Exit Code PS1 prompt
# "Pimp my prompt" with the return value of the last command.
# source this from ~/.bashrc or similar to modify PS1 to show the return value of previous command.
# Use the "demojify" command to restore your previous prompt after sourcing.
PS1OLD=$PS1
exitprompt ()
{
ERROR="$?"
if [ "$ERROR" -eq 0 ]
then
COLORCODE=32 # foreground green
EMOJI="🙂"
else
COLORCODE=31 # foreground red
EMOJI="🙁"
fi
echo -e "\e[${COLORCODE}m${ERROR} ${EMOJI} \e[0m"
}
demojify ()
{
PS1=$PS1OLD
}
PS1="\$(exitprompt)\n$PS1"

43
day3_geninventory_phase1.sh Executable file
View File

@ -0,0 +1,43 @@
#
# 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
[ssh_connection]
ssh_args = "-o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey"
pipelining = true
EOF
ansible "$CATEGORY" -m ping

48
day3_geninventory_phase2.sh Executable file
View File

@ -0,0 +1,48 @@
#
# 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
[ssh_connection]
ssh_args = "-o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey"
pipelining = true
EOF
ansible "$CATEGORY" -m ping

11
jupyterhub.service Normal file
View File

@ -0,0 +1,11 @@
[Unit]
Description=Jupyterhub
[Service]
Type=simple
ExecStart=jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
Restart=on-failure
PIDFile=/var/run/jupyterhub.pid
[Install]
WantedBy=multi-user.target

1385
jupyterhub_config.py Normal file

File diff suppressed because it is too large Load Diff

78
jupyterhubsrv.yml Normal file
View File

@ -0,0 +1,78 @@
---
- name: Install Jupyterhub
hosts: UpskillChallengeNode
gather_facts: no
tasks:
- name: Create NodeJS directory
ansible.builtin.file:
path: /opt/nodesource
state: directory
mode: 0755
- name: Create Jupyterhub config directory
ansible.builtin.file:
path: /etc/jupyterhub
state: directory
mode: 0755
- name: Download NodeJS apt configuration
ansible.builtin.get_url:
url: "https://deb.nodesource.com/setup_14.x"
dest: /opt/nodesource
checksum: "sha512:a0451fa9a2d679fb43a1e703eb1ae0e0ad62da3eac73ff5a25abc71cbe908eb463ee478c1f2f7687532b56106956634afb72129572db347334bd1b7fbf99dcdc"
mode: 0755
- name: run NodeJS configuration script
ansible.builtin.shell: /opt/nodesource/setup_14.x
args:
chdir: /opt/nodesource
creates: /etc/apt/sources.list.d/nodesource.list
- name: update and upgrade packages
ansible.builtin.apt:
update_cache: yes
- name: install prerequisites [apt]
ansible.builtin.apt:
package:
- sudo
- python3
- python3-pip
- gcc
- g++
- make
- build-essential
- nodejs
- nginx
- certbot
- python3-certbot-nginx
state: present
- name: install prerequisites [pip]
ansible.builtin.pip:
name:
- jupyterhub
- notebook
- virtualenv
- name: install prerequisites [npm]
community.general.npm:
global: yes
name: configurable-http-proxy
- name: copy Jupyterhub service file
ansible.builtin.copy:
src: jupyterhub.service
dest: /etc/systemd/system/
- name: copy Jupyterhub config file
ansible.builtin.copy:
src: jupyterhub_config.py
dest: /etc/jupyterhub
- name: daemon-reload
ansible.builtin.systemd:
name: jupyterhub
state: restarted
daemon_reload: yes

21
omniconfig.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
d ()
{
date '+%F %T'
}
echo $(d): Starting server
ROOT_PASS="Swordfish4321!" ./day0_create.sh
./wait_ready.sh
./day1_geninventory.sh
echo $(d): Creating user account
ansible-playbook phase1user.yml > .phase1.log
./day3_geninventory_phase1.sh
echo $(d): Securing SSH access
ansible-playbook phase2user.yml > .phase2.log
./day3_geninventory_phase2.sh
echo $(d): configuring jupyterhub
ansible-playbook jupyterhubsrv.yml > .jupyterhub.log
echo $(d): ready

46
phase1user.yml Normal file
View File

@ -0,0 +1,46 @@
---
- name: Create admin user
hosts: UpskillChallengeNode
gather_facts: no
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'

39
phase2user.yml Normal file
View File

@ -0,0 +1,39 @@
---
- name: Lock down root & SSH on the server
hosts: UpskillChallengeNode
gather_facts: no
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

6
test_error.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
# Returns a non-zero exit code on purpose to test the day 2 error prompt.
exit 42

23
wait_ready.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
if [ -z ""]
then
LABEL="UpskillChallengeNode"
fi
NODESTATE="indeterminate"
while [ "$NODESTATE" != "running" ]
do
OLDSTATE=$NODESTATE
NODESTATE=$(linode-cli linodes list --format 'status' --label "$LABEL" --text | tail -n 1)
if [ "$NODESTATE" = "status" ]
then
echo "No node detected."
exit 1
fi
if [ "$NODESTATE" != "$OLDSTATE" ]
then
echo "$(date '+%F %T'): $NODESTATE"
fi
done