diff --git a/init-instance.sh b/init-instance.sh new file mode 100644 index 0000000..8dc35f7 --- /dev/null +++ b/init-instance.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# +# setup-student.sh +# +# Usage: +# curl -sL URL_TO_THIS_SCRIPT | bash -s -- GITHUB_USERNAME +# +# This script must be run as the 'rocky' user (with passwordless sudo). +# It takes one argument: the GitHub username of the student. +# It will: +# 1. Retrieve the student's public SSH keys from GitHub and install them +# so they can SSH in as 'rocky'. +# 2. Install cowsay, screen, and tmux. +# 3. Update /etc/motd to welcome the student via cowsay and point them +# at the tutorial repo. + +set -euo pipefail + +if [ "$#" -ne 1 ]; then + echo "Error: Missing GitHub username." + echo "Usage: $0 GITHUB_USERNAME" + exit 1 +fi + +GH_USER="$1" +SSH_DIR="/home/rocky/.ssh" +AUTHORIZED_KEYS="$SSH_DIR/authorized_keys" +MOTD_FILE="/etc/motd" +TUTORIAL_URL="https://github.com/OpenCHAMI/tutorial-2025" + +echo "→ Installing SSH keys for GitHub user '$GH_USER'..." + +# Create .ssh directory if needed +sudo mkdir -p "$SSH_DIR" +sudo chmod 700 "$SSH_DIR" + +# Fetch and install public keys +KEYS=$(curl -fsSL "https://github.com/${GH_USER}.keys") +if [ ! -z "${KEYS}" ]; then + echo "${KEYS}" | sudo tee "$AUTHORIZED_KEYS" >/dev/null + echo " ✓ Retrieved keys from https://github.com/${GH_USER}.keys" +else + echo " ✗ Could not find keys for user '$GH_USER'; please check the username and that authorization SSH keys are present." + exit 2 +fi + +sudo chmod 600 "$AUTHORIZED_KEYS" +sudo chown -R rocky:rocky "$SSH_DIR" + +echo "→ Installing packages: cowsay, screen, tmux..." +sudo dnf install -y cowsay screen tmux + +echo "→ Updating MOTD in $MOTD_FILE..." + +# Generate motd with cowsay greeting and tutorial link +sudo tee "$MOTD_FILE" >/dev/null < --script-url +# +# Example: +# +# ./setup-instances.py ./users.csv ./openchami.pem https://gist.githubusercontent.com/alexlovelltroy/96bfc8bb6f59c0845617a0dc659871de/raw +from fabric import Connection +from argparse import ArgumentParser +from csv import DictReader + +DEFAULT_SCRIPT_URL = "https://gist.githubusercontent.com/davidallendj/bb57c25adefb3e9921ccc3502e9ca13b/raw/2165263c07edc59c007b015c8d21f245f403c09d/setup-student.sh" + +def read_user_data(csv_path: str, ignore_header: bool) -> list: + data = [] + with open(csv_path, 'r') as file: + if ignore_header: + next(file) + reader = DictReader(file) + for row in reader: + data.append(row) + return data + + +def ssh_setup_instance( + remote_host: str, + username: str, + keyfile_path: str, + script_url: str = DEFAULT_SCRIPT_URL +) -> None: + # download the script on the remote host instance + conn = Connection( + host=f"rocky@{remote_host}", + connect_kwargs={"key_filename": keyfile_path} + ) + result = conn.run(f"curl -fssL {script_url} -o ./setup-student.sh && chmod 755 ./setup-student.sh && ./setup-student.sh {username}", hide=True) + print("{0.stdout}\n".format(result)) + + +def main() -> None: + # setup command-line arguments + parser = ArgumentParser( + prog='setup-instance', + description='Automates setting up an EC2 instance for the OpenCHAMI tutorial.', + epilog='./setup-instances.py ' + ) + parser.add_argument('csv-file', help="Path to CSV containing user information.", default="") + parser.add_argument('keyfile', help="Path to key file used to log into AWS EC2 instance. This is assumed to be shared between instances.") + parser.add_argument('--script-url', dest="script-url", help="URL pointing to setup script to initialize EC2 instance.", default=DEFAULT_SCRIPT_URL) + parser.add_argument('--ignore-header', dest="ignore-header", type=bool, help="Ignores the first line in CSV file.", default=False) + args = vars(parser.parse_args()) + + + # read contents from CSV file and load into dict + data: list = read_user_data(args["csv-file"], args["ignore-header"]) + if len(data) == 0: + print("no data found in CSV file") + exit() + + # run SSH commands to setup instance + for row in data: + print(f"{row}") + ip_addr: str = row["public_ip_address"] + username: str = row["github_username"] + if not ip_addr or not username: + continue + ssh_setup_instance(ip_addr, username, args["keyfile"], args["script-url"]) + + +if __name__ == "__main__": + main()