From c3309581c2ac7077b9b50e306947a9ecf56b2aec 2022-06-08 21:48:04 From: x Date: 2022-06-08 21:48:04 Subject: [PATCH] Initial commit --- diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..360f540c1f007b28e37b2d8ae4e3c82e5e6ff3eb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "roles/initial/files"] + path = roles/initial/files + url = ssh://kallithea@projects.c3l.lu/ChaosStuff/cnc-host-keys diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..13290fc4bd0ae43582b24f244cc8cb113ebcebb3 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Command and Control +These scripts automate the Command and Control SBC installation as much as possible. + +Note that git submodules **must** be initalized, they contain crucial information such as +the SSH host keys and the public key of autom8. Special access is needed. + +## How to use +Flash the image on the eMMC using the flashEMMC.sh script (see section). +Then use ansible.sh to install and configure the installation. + +### Structure of submodule +``` +files +├── autom8_public_key +├── mcr-alpha +│   └── ssh_host_* +├── mcr-beta +│   └── ssh_host_* +├── mcr-delta +│   └── ssh_host_* +└── mcr-gamma + └── ssh_host_* +``` + +## Requirements +- Ansible (+ requirements.txt) +- expect +- sshpass +- OpenSSH tools (ssh-keygen, ssh-copy-id) + +## Scripts +There are various scripts, some of which are supposed to be used directly, while others are used by Ansible itself. + +### flashEMMC.sh +Usage: +`sudo ./flashEMMC.sh [block device name, e.g. sdb]` + +This script automates the installation of the ArchLinuxARM ODROID C2 image. (as shown on the [ALARM installation page](https://archlinuxarm.org/platforms/armv8/amlogic/odroid-c2#installation)) + +It shows the user information about the block device they indicated, asking if it is the right device. If it is, all mounts related to this block device are unmounted, a couple of blocks at the start are zero-ed out, the partition table is created, the single partition's FS is created, the ALARM image downloaded, hash verified, the parition is mounted, the tarball extracted, then the bootloader is installed. Finally, everything is `sync`-ed, and the directory unmounted. +### ansible.sh +Usage: +`sudo ./ansible.sh [playbook file, if none, site.yml]` + +It simply verifies that the ansible requirements.txt are met and runs through the specific playbook. diff --git a/alpha.yml b/alpha.yml new file mode 100644 index 0000000000000000000000000000000000000000..9ace87f3e6a9febdcd725a690b5325d0db79fa48 --- /dev/null +++ b/alpha.yml @@ -0,0 +1,32 @@ +--- +- name: Create local key and deploy it + hosts: mcr-alpha + remote_user: null + gather_facts: false + roles: + - localKey + +- name: Install python + hosts: mcr-alpha + remote_user: null + gather_facts: false + roles: + - python + +- name: Setup pi + hosts: mcr-alpha + remote_user: alarm + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - initial + +- name: Setup kiosk + hosts: mcr-alpha + remote_user: odroid + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - kiosk diff --git a/ansible.sh b/ansible.sh new file mode 100755 index 0000000000000000000000000000000000000000..46eb00d95df8cbdf28048dc0ea100fb63c29202e --- /dev/null +++ b/ansible.sh @@ -0,0 +1,12 @@ +ansible-galaxy install -r requirements.yml + +if [ -z ${1+x} ]; then + echo "var is unset"; + PLAYBOOK=site.yml +else + PLAYBOOK=$1 +fi + +# Agent running causes issues because SSH seems to prioritise those keys by default +SSH_AUTH_SOCK=/dev/null +ansible-playbook -v -i hosts.yml $PLAYBOOK diff --git a/beta.yml b/beta.yml new file mode 100644 index 0000000000000000000000000000000000000000..6fae2b0caa882d1250117cba098b8e1c34437bc6 --- /dev/null +++ b/beta.yml @@ -0,0 +1,32 @@ +--- +- name: Create local key and deploy it + hosts: mcr-beta + remote_user: null + gather_facts: false + roles: + - localKey + +- name: Install python + hosts: mcr-beta + remote_user: null + gather_facts: false + roles: + - python + +- name: Setup pi + hosts: mcr-beta + remote_user: alarm + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - initial + +- name: Setup kiosk + hosts: mcr-beta + remote_user: odroid + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - kiosk diff --git a/delta.yml b/delta.yml new file mode 100644 index 0000000000000000000000000000000000000000..af0b06a29461ffbd69d102e0bff28f6fbeb7e599 --- /dev/null +++ b/delta.yml @@ -0,0 +1,32 @@ +--- +- name: Create local key and deploy it + hosts: mcr-delta + remote_user: null + gather_facts: false + roles: + - localKey + +- name: Install python + hosts: mcr-delta + remote_user: null + gather_facts: false + roles: + - python + +- name: Setup pi + hosts: mcr-delta + remote_user: alarm + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - initial + +- name: Setup kiosk + hosts: mcr-delta + remote_user: odroid + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - kiosk diff --git a/flashEMMC.sh b/flashEMMC.sh new file mode 100755 index 0000000000000000000000000000000000000000..b3bd6dad654ca952e4d8b3323c1c759508ac3323 --- /dev/null +++ b/flashEMMC.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +DEV=$1 +IMAGE_NAME=ArchLinuxARM-odroid-c2-latest.tar.gz +# Fast mirror, but I'm not sure we can trust it... +DOWNLOAD_LINK=https://mirrors.dotsrc.org/archlinuxarm/os/ +HASH_LINK=https://de3.mirror.archlinuxarm.org/os/ + + +checkRoot() { + [ `id -u` -eq 0 ] || { echo "Run script (as root) or (with sudo)"; exit 1; } +} + +diskInfo() { + [[ -e /dev/$DEV ]] || { echo "ERROR: Drive doesn't exist" && exit 1; } + fdisk -l /dev/$DEV + echo +} + +verifyRightDrive() { + sleep 3 + read -n 1 -r -p "Is this the right drive? [y/N] " response + if [[ "$response" =~ ^([yY])$ ]] + then + return 0 + else + echo + exit 1 + fi +} + +umountInitially() { + BLKDEVS=$(find /dev/ -name ${DEV}*) + for LINE in $BLKDEVS; do + sudo umount $LINE + done +} + +zeroBeginning() { + dd if=/dev/zero of=/dev/$DEV bs=1M count=8 +} + +partitionEMMC() { +fdisk -W always /dev/$DEV << EOF +o +n +p +1 + + + +w +EOF +} + +createEXT4fs() { + mkfs.ext4 -O ^metadata_csum,^64bit /dev/${DEV}1 +} + +cdToScript() { + TMP=$(dirname "$0") + cd $TMP + mkdir flashEMMC + cd flashEMMC +} + +unmountFS() { + umount root +} + +panic() { + cdToScript + unmountFS + exit 1 +} + +downloadImage() { + rm ${IMAGE_NAME} + wget ${DOWNLOAD_LINK}${IMAGE_NAME} + wget ${HASH_LINK}${IMAGE_NAME}.md5 + md5sum -c ${IMAGE_NAME}.md5 || { echo "Hash of image is incorrect"; panic; } +} + +extractImage() { + bsdtar -xpf ArchLinuxARM-odroid-c2-latest.tar.gz -C root +} + +mountFS() { + mkdir root + mount /dev/${DEV}1 root + [ -e ${IMAGE_NAME}.md5 ] && md5sum -c ${IMAGE_NAME}.md5 || downloadImage && extractImage +} + +flashBootloader() { + cd root/boot + ./sd_fusing.sh /dev/${DEV} + cd ../.. +} + + +main() { + checkRoot + diskInfo + verifyRightDrive + umountInitially + zeroBeginning + partitionEMMC + createEXT4fs + cdToScript + mountFS + flashBootloader + unmountFS +} + +main diff --git a/gamma.yml b/gamma.yml new file mode 100644 index 0000000000000000000000000000000000000000..7ae8a12f43f6a0128a27f0413da99e1e78932557 --- /dev/null +++ b/gamma.yml @@ -0,0 +1,32 @@ +--- +- name: Create local key and deploy it + hosts: mcr-gamma + remote_user: null + gather_facts: false + roles: + - localKey + +- name: Install python + hosts: mcr-gamma + remote_user: null + gather_facts: false + roles: + - python + +- name: Setup pi + hosts: mcr-gamma + remote_user: alarm + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - initial + +- name: Setup kiosk + hosts: mcr-gamma + remote_user: odroid + vars: + ansible_host_key_checking: false + ansible_ssh_host_key_checking: false + roles: + - kiosk diff --git a/hosts.yml b/hosts.yml new file mode 100644 index 0000000000000000000000000000000000000000..5d8c3f651a0f2df8217893c56acda3484ba0ebab --- /dev/null +++ b/hosts.yml @@ -0,0 +1,27 @@ +all: + children: + cnc: + vars: + ansible_ssh_private_key_file: "{{inventory_dir}}/sshKey" + ansible_ssh_public_key_file: "{{inventory_dir}}/sshKey.pub" + ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' + children: + cncServer: + hosts: + mcr-alpha: + ansible_host: mcr-alpha.lan + barrierCommand: 'barriers --config /home/odroid/barrierConfiguration --name mcr-alpha --disable-crypto -f' + dashboardUrl: 'http://roonadan.lan/d/1i0gquEmz/turris?orgId=1&refresh=30s' + cncClient: + vars: + barrierCommand: 'barrierc --disable-crypto -f mcr-alpha' + hosts: + mcr-gamma: + ansible_host: mcr-gamma.lan + dashboardUrl: 'http://roonadan.lan/d/hfvfaCyik/mqtt?orgId=1&refresh=30s' + mcr-delta: + ansible_host: mcr-delta.lan + dashboardUrl: 'http://roonadan.lan/d/tI2qaTEiz/odroid?orgId=1&refresh=30s' + mcr-beta: + ansible_host: mcr-beta.lan + dashboardUrl: 'http://roonadan.lan/d/OsA71lsiz/spaceapi?orgId=1&refresh=30s' diff --git a/init.sh b/init.sh new file mode 100755 index 0000000000000000000000000000000000000000..72e7851dd6b7961164231904615fd4f947a063d0 --- /dev/null +++ b/init.sh @@ -0,0 +1,26 @@ +generateKey() { + touch sshKey + touch sshKey.pub + rm sshKey + rm sshKey.pub + ssh-keygen -t ed25519 -f ./sshKey -q -N "" -C "" +} + +deployKey() { + sshpass -p alarm ssh-copy-id -i ./sshKey.pub -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=false alarm@$1 +} + +# If keys are present, we just need to deploy it and destroy the SSH Agent +# Otherwise, we genrate a key and then deploy it +# The key can be present on the remote host multiple times, +# -> not a big issue, just not clean, but it works +[ -e sshKey ] && [ -e sshKey.pub ] || generateKey + + +for remoteHost in "$@" +do + echo "$remoteHost" + deployKey "$remoteHost" +done + +export SSH_AUTH_SOCK=/dev/null diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000000000000000000000000000000000000..052506bf2d302565009e8df15801b26a9dd5b795 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,2 @@ +collections: + - name: kewlfft.aur diff --git a/roles/initial/files b/roles/initial/files new file mode 160000 index 0000000000000000000000000000000000000000..845d64cadf0a414b2e2abd4147e2ee13a3105efb --- /dev/null +++ b/roles/initial/files @@ -0,0 +1 @@ +Subproject commit 845d64cadf0a414b2e2abd4147e2ee13a3105efb diff --git a/roles/initial/tasks/aur.yml b/roles/initial/tasks/aur.yml new file mode 100644 index 0000000000000000000000000000000000000000..099c94a116752c9d13234d327c930b9140538972 --- /dev/null +++ b/roles/initial/tasks/aur.yml @@ -0,0 +1,57 @@ +--- +# https://gist.github.com/cahna/45bb9eee92c5f1fce66f +- name: AUR | get metadata from AurJson api + connection: local + sudo: no + uri: > + url=https://aur.archlinux.org/rpc.php?type=info&arg={{ pkg_name | mandatory }} + return_content=yes + timeout=6 + register: api_info + +- assert: + that: + - api_info.status == 200 + - api_info.json is defined + - api_info.json.type == 'info' + - api_info.json.resultcount == 1 + - api_info.json.results is defined + +- name: AUR | {{ pkg_name }} | download tarball + sudo: no + connection: local + get_url: > + url='https://aur.archlinux.org{{ api_info.json.results.URLPath }}' + dest='/tmp/' + register: aur_tarball + +- name: AUR | {{ pkg_name }} | upload tarball to host and extract it + sudo: yes + sudo_user: "{{ makepkg_nonroot_user }}" + unarchive: > + src={{ aur_tarball.dest }} + dest=/tmp/ + register: extracted_pkg + +# This will break if run as root. Set user to use with makepkg with 'makepkg_user' var +- name: AUR | {{ pkg_name }} | build package, including missing dependencies + when: extracted_pkg | changed + sudo: yes + sudo_user: "{{ makepkg_nonroot_user }}" + command: > + makepkg --noconfirm --noprogressbar -mfs + chdir=/tmp/{{ pkg_name }} + register: aur_makepkg_result + +# Shameless variable declaration hack +- shell: ls -1 /tmp/{{ pkg_name | quote }} | grep pkg.tar + register: compiled_package_name + +- name: AUR | {{ pkg_name }} | install newly-built aur package with pacman + when: aur_makepkg_result | changed + sudo: yes + shell: > + pacman --noconfirm --noprogressbar --needed -U {{ compiled_package_name.stdout | quote }} + chdir=/tmp/{{ pkg_name }} + register: pacman_install_result + changed_when: pacman_install_result.stdout is defined and pacman_install_result.stdout.find('there is nothing to do') == -1 diff --git a/roles/initial/tasks/main.yml b/roles/initial/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..c2435937b9f5be524d76867284fa84200439e77f --- /dev/null +++ b/roles/initial/tasks/main.yml @@ -0,0 +1,24 @@ +# This role copies over the right SSH host keys, sets up some tools and creates the users +- name: Set up host ssh keys + import_tasks: ssh_host.yml +- name: Update system + become: yes + become_method: su + become_user: "root" + vars: + ansible_become_pass: root + community.general.pacman: + update_cache: yes + upgrade: yes +- name: Install basic tools (sudo, vim, etc.) + import_tasks: tools.yml +- name: Create users + import_tasks: users.yml +- name: Change hostname + become: yes + become_method: su + become_user: "root" + vars: + ansible_become_pass: root + ansible.builtin.hostname: + name: "{{ inventory_hostname }}" diff --git a/roles/initial/tasks/ssh_host.yml b/roles/initial/tasks/ssh_host.yml new file mode 100644 index 0000000000000000000000000000000000000000..b5d87c3da42f12b71f731393cf1ace7696855433 --- /dev/null +++ b/roles/initial/tasks/ssh_host.yml @@ -0,0 +1,45 @@ +# This task list copies over the right SSH host keys +# https://linuxdigest.com/howto/ansible-copy-multiple-files/ +# https://stackoverflow.com/questions/53102214/ansible-how-can-i-copy-files-to-hosts-depending-on-group-membership +# https://stackoverflow.com/questions/70378717/ansible-how-to-delete-files-starting-with-a-specific-name +--- +- name: Setup ssh keys as root + become: yes + become_method: su + become_user: "root" + vars: + ansible_become_pass: root + block: + - name: List existing host keys + ansible.builtin.find: + paths: /etc/ssh/ + patterns: "^ssh_host_.+$" + use_regex: true + register: ssh_host_keys + + - name: Delete existing host keys + ansible.builtin.file: + state: absent + path: "{{ item }}" + loop: "{{ ssh_host_keys.files|map(attribute='path')|list }}" + + - name: Copy SSH host keys + ansible.builtin.copy: + src: "{{ inventory_hostname }}/" + dest: /etc/ssh + owner: root + group: root + mode: '600' + + - name: List public host keys + ansible.builtin.find: + paths: /etc/ssh/ + patterns: "^ssh_host_.+_pub$" + use_regex: true + register: ssh_host_keys_pub + + - name: change visibility of host public keys + ansible.builtin.file: + path: "{{ item }}" + mode: '644' + loop: "{{ ssh_host_keys_pub.files|map(attribute='path')|list }}" diff --git a/roles/initial/tasks/tools.yml b/roles/initial/tasks/tools.yml new file mode 100644 index 0000000000000000000000000000000000000000..5523508a94c9575fe772eb1769d5468b74f17d2d --- /dev/null +++ b/roles/initial/tasks/tools.yml @@ -0,0 +1,63 @@ +# This task list sets up the basic tools +--- +- name: Install basic tools + become: yes + become_method: su + become_user: "root" + vars: + ansible_become_pass: root + block: + - name: Update pacman cache and update + community.general.pacman: + update_cache: no + upgrade: yes + + - name: Install tools + community.general.pacman: + state: installed + name: + - sudo + - vim + - htop + - base-devel + - git + + - name: Enable sudo for wheel + ansible.builtin.lineinfile: + path: /etc/sudoers + state: present + line: '%wheel ALL=(ALL:ALL) NOPASSWD: ALL' + validate: /usr/sbin/visudo -cf %s + + - name: Add default user to wheel group + ansible.builtin.user: + name: "{{ ansible_user }}" + append: yes + groups: wheel + +- name: Install paru + block: + - name: Gather package facts + ansible.builtin.package_facts: + manager: pacman + + - name: Install paru if not already installed + when: "'paru-bin' not in ansible_facts.packages" + block: + - name: Install necessary tools + become: yes + become_method: su + become_user: "root" + vars: + ansible_become_pass: root + community.general.pacman: + state: installed + name: + - base-devel + - git + + - name: Install paru + kewlfft.aur.aur: + name: paru-bin + use: makepkg + state: present diff --git a/roles/initial/tasks/users.yml b/roles/initial/tasks/users.yml new file mode 100644 index 0000000000000000000000000000000000000000..e391ed290495b723062acb3ed0bd950a89db107d --- /dev/null +++ b/roles/initial/tasks/users.yml @@ -0,0 +1,50 @@ +# This task list sets up the needed users +--- +- name: Create users + become: yes + become_method: su + become_user: "root" + vars: + ansible_become_pass: root + block: + - name: Standard user + vars: + username: odroid + block: + - name: Create user + ansible.builtin.user: + name: "{{ username }}" + create_home: yes + append: yes + groups: wheel, video + state: present + password: "{{ username | password_hash('sha512') }}" + shell: "/bin/bash" + - name: Add ssh key to odroid + ansible.posix.authorized_key: + user: "{{ username }}" + key: "{{ lookup('file', ansible_ssh_public_key_file) }}" + + - name: autom8 user + vars: + username: autom8 + block: + - name: Create user + ansible.builtin.user: + name: "{{ username }}" + create_home: yes + state: present + + - name: add SSH key + ansible.posix.authorized_key: + user: "{{ username }}" + state: present + key: "{{ lookup('file', 'autom8_public_key') }}" + manage_dir: yes + + - name: allow shutting down + ansible.builtin.lineinfile: + path: /etc/sudoers + state: present + line: 'ALL ALL=NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff, /sbin/shutdown now' + validate: /usr/sbin/visudo -cf %s diff --git a/roles/kiosk/files/agettyAutologin b/roles/kiosk/files/agettyAutologin new file mode 100644 index 0000000000000000000000000000000000000000..e7eaae5c547bfb274f7545f8f62d1f4bd8ad4147 --- /dev/null +++ b/roles/kiosk/files/agettyAutologin @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin odroid %I $TERM diff --git a/roles/kiosk/files/barrier/SSL/Barrier.pem b/roles/kiosk/files/barrier/SSL/Barrier.pem new file mode 100644 index 0000000000000000000000000000000000000000..ed5d1e264bf5cf14074403abd41009b0568f9928 --- /dev/null +++ b/roles/kiosk/files/barrier/SSL/Barrier.pem @@ -0,0 +1,47 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDH2UqcaAlEAZMV +3N2/jUd5tOkMTGqmqs9st9afk7b2EjNLffit3ck+M3dt6RfOU0tf54bAX7fXYcpG +tD4WyZ019u5qlfGnQCeJMFYNGdBSpX/mlp9mjC7yv18OIBOv87rCgA7YBjoXzkA9 +XCDxW/+4RGwJZVeDx4U45ECRupbzIaCmpJdPqnzkcPPwXi64F9RwfyuQENImRkMP +x/hrbWeYOCaTGHA9730MFoqz+xIgDJ0mHVAnGy/I0caFqhqW5lVzDh02Cw7DGF0o +1ZIA2f/n1h668+74npHngld3cD829kdDJAKHAJTrca0tGjlUjhrDS7WYc5X+mvKm +Xc2LbIYBAgMBAAECggEBAKgozaAn5kwD6yjFTQ2GKnNdZ4+CqWcOaTT4x65E0/ng +PKs0F1DtQw2EruSb8v0Yl17eaUNsBzxDO7ocpfX0tcUXv2uOOeValSnZsz6YzvML +8UAs03mtUT/PCYPQN+Cg/C/3IwZgzvcDBIjdAZc1q0n4wNNzI51uAEprvW0iDSwM +TgPgH+wYED60pTQtafzfIJ341ods2OWMZ/gMNqEqNnyijfQGqdFM7W7U85Gg/Ry4 +edpRcrRxG4eX2C1viQYPVARRVFBGK00o7VJ0/HZ86wDQ6qySHZmPeiOR5rR8zj3P +VVB2HffYL7V0o0pKyJmRkPEI+/QleAtTrya3MwZTkfUCgYEA4k+I9KYIL4cRZkWL +iGUQuNg9OYkARCb47ozlImOo+yWrA7xe7Q5pCWSTDVZqCCXObSL3kw+dSDjhLzdm +Ft3V0jEjsBUFpq7CxW8qh74r9OZlCQEEOrU6JnvxE5ijircApmQIoTgL5I68JbB7 +g04BdhJFvSCpUvfGMuNE1B6IuNsCgYEA4hEODY4swLaUkHZ3/BSQo3S/GYS669Nj +myyixOJxoTQOb36WbTa6Aq4nrUycOmcbX0peSCXesl9CQ6LZj0b0eQvKGoaPX4zL +534DV34I3OBS6rjs4E5q2cDwdE+cJdbCOAtm3w4EvUwaGfJ/QCkRnX0NlFGfrCOE +YkYCTEA99VMCgYEA4d5hoVMIfm7+9aTZY1MDQolHaeILavm+n0/t7MmswKRSr5LU +5yHnwWEoxzoE74bUJOauU49U+d0TGm3fLVlQa81xge8pSbfIWwbdWsd51Z4RHtBt +6S4xEHHJJTbFms+VDXxvhICMlhvDOpaOX3l+Sdpo0h8D//OdU/KyIkcrS9sCgYAq +G4EhlzzQvHFZoydgJbh3KbS6nRVv/ZTM/3hl8cO2ggq6S7rbJtlozGWJiv6Chlf7 +3M9I4vzi/olKLdgWLuI0dbS0UiH8ay5DtR4MOuaNtZ7cJ4u/j/upCZ4AHB/6kFDm +vYDwxRyu4bDu6lM3cS7dxcA0wytZldf/sgiViVXBDwKBgBOm/0PzyFloK8GZWZz8 +atqJ1GP9mlT5l65U1b4r1w6KQMYpEKup7CCj/iQEo0E2dqWK6yoFwR1dILimGL2N +q4V9y3kpCy1Oqm4+rxDZrhA5FP6cLHQah2QCWKjcZw/8LmOm5fbHIkHjckin2ER8 +7WI4cJz5v0yIUVFyJ0d2TV7f +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDBTCCAe2gAwIBAgIUbv1p7hiUSW3bC5kdaGnBNURuCTYwDQYJKoZIhvcNAQEL +BQAwEjEQMA4GA1UEAwwHQmFycmllcjAeFw0yMTA0MTAyMzM0MDFaFw0yMjA0MTAy +MzM0MDFaMBIxEDAOBgNVBAMMB0JhcnJpZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDH2UqcaAlEAZMV3N2/jUd5tOkMTGqmqs9st9afk7b2EjNLffit +3ck+M3dt6RfOU0tf54bAX7fXYcpGtD4WyZ019u5qlfGnQCeJMFYNGdBSpX/mlp9m +jC7yv18OIBOv87rCgA7YBjoXzkA9XCDxW/+4RGwJZVeDx4U45ECRupbzIaCmpJdP +qnzkcPPwXi64F9RwfyuQENImRkMPx/hrbWeYOCaTGHA9730MFoqz+xIgDJ0mHVAn +Gy/I0caFqhqW5lVzDh02Cw7DGF0o1ZIA2f/n1h668+74npHngld3cD829kdDJAKH +AJTrca0tGjlUjhrDS7WYc5X+mvKmXc2LbIYBAgMBAAGjUzBRMB0GA1UdDgQWBBRH +wq5ukNTrKKFWezWE+P6anuoJLzAfBgNVHSMEGDAWgBRHwq5ukNTrKKFWezWE+P6a +nuoJLzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB9KCubbKSa +Pfyb1p4lZb/cReGazhXHObK4wvZh1EVD4jM4c8dwqbE7kNZjbr4vunSyemo8G8Wz +3yuht8eAxKrskIjwaE8zMFEo0VDeZnwNH6yVr5T0Mg3W5aQur57kDIhsvDXEsv1X +jNRv6jF0/1/HiX6MUXD7Vwcykr6iQ/GUMjqcJjI3XqZ4HGQpao3WpFjhhAhpMKNG +Y4jI/dHjd6N4KpdSjSUmx8d5uzKDmcH2FGUQUGoAxBUbwNiVOQbaUaCOqNZlr3A7 +hUOc1m+B6brCEvl7H5k2HDtiW9fzfmaoQ9qdiUIHVzsXVmoqiVcEP1uiK54EFTeQ +PZnULIlz5zfx +-----END CERTIFICATE----- diff --git a/roles/kiosk/files/barrier/SSL/Fingerprints/Local.txt b/roles/kiosk/files/barrier/SSL/Fingerprints/Local.txt new file mode 100644 index 0000000000000000000000000000000000000000..25c86967048e8c7c37b2fc4eebd62b7b84c1a795 --- /dev/null +++ b/roles/kiosk/files/barrier/SSL/Fingerprints/Local.txt @@ -0,0 +1 @@ +EB:13:D0:9B:B1:4A:CB:FB:34:6E:03:8C:A3:34:C8:64:6A:E9:20:41 diff --git a/roles/kiosk/files/barrier/SSL/Fingerprints/TrustedServers.txt b/roles/kiosk/files/barrier/SSL/Fingerprints/TrustedServers.txt new file mode 100644 index 0000000000000000000000000000000000000000..25c86967048e8c7c37b2fc4eebd62b7b84c1a795 --- /dev/null +++ b/roles/kiosk/files/barrier/SSL/Fingerprints/TrustedServers.txt @@ -0,0 +1 @@ +EB:13:D0:9B:B1:4A:CB:FB:34:6E:03:8C:A3:34:C8:64:6A:E9:20:41 diff --git a/roles/kiosk/files/barrierConfiguration b/roles/kiosk/files/barrierConfiguration new file mode 100644 index 0000000000000000000000000000000000000000..70eb7b4989ef95112a4479337c1ed1809bb7b162 --- /dev/null +++ b/roles/kiosk/files/barrierConfiguration @@ -0,0 +1,61 @@ +section: screens + mcr-alpha: + halfDuplexCapsLock = false + halfDuplexNumLock = false + halfDuplexScrollLock = false + xtestIsXineramaUnaware = false + preserveFocus = false + switchCorners = none + switchCornerSize = 0 + mcr-beta: + halfDuplexCapsLock = false + halfDuplexNumLock = false + halfDuplexScrollLock = false + xtestIsXineramaUnaware = false + preserveFocus = false + switchCorners = none + switchCornerSize = 0 + mcr-gamma: + halfDuplexCapsLock = false + halfDuplexNumLock = false + halfDuplexScrollLock = false + xtestIsXineramaUnaware = false + preserveFocus = false + switchCorners = none + switchCornerSize = 0 + mcr-delta: + halfDuplexCapsLock = false + halfDuplexNumLock = false + halfDuplexScrollLock = false + xtestIsXineramaUnaware = false + preserveFocus = false + switchCorners = none + switchCornerSize = 0 +end + +section: aliases +end + +section: links + mcr-alpha: + right = mcr-beta + down = mcr-gamma + mcr-beta: + left = mcr-alpha + down = mcr-delta + mcr-gamma: + right = mcr-delta + up = mcr-alpha + mcr-delta: + left = mcr-gamma + up = mcr-beta +end + +section: options + relativeMouseMoves = false + screenSaverSync = true + win32KeepForeground = false + clipboardSharing = true + switchCorners = none + switchCornerSize = 0 +end diff --git a/roles/kiosk/tasks/barrier.yml b/roles/kiosk/tasks/barrier.yml new file mode 100644 index 0000000000000000000000000000000000000000..ce6c77c325c061fc7e29d9e723cff98690413987 --- /dev/null +++ b/roles/kiosk/tasks/barrier.yml @@ -0,0 +1,20 @@ +# This task list sets up barrier +--- +- name: Copy barrier config + ansible.builtin.copy: + dest: ~/barrierConfiguration + src: barrierConfiguration + mode: 0644 + +- name: Copy barrier SSL files + ansible.builtin.copy: + dest: ~/.local/share/barrier/SSL/Fingerprints/ + src: barrier/SSL/Fingerprints/ + mode: 0644 + directory_mode: 0755 + +- name: Make key read only to user + ansible.builtin.copy: + mode: '0600' + src: barrier/SSL/Barrier.pem + dest: '~/.local/share/barrier/SSL/Barrier.pem' diff --git a/roles/kiosk/tasks/main.yml b/roles/kiosk/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..7dad9ffe6041f842426e61530b5c91b5503e2024 --- /dev/null +++ b/roles/kiosk/tasks/main.yml @@ -0,0 +1,12 @@ +# This role sets up a kiosk +- name: Install software (browser, KVM) + import_tasks: software.yml +- name: Setup barrier + import_tasks: barrier.yml +- name: Setup window manager + import_tasks: wm.yml +- name: Reboot + become: yes + become_user: root + ansible.builtin.reboot: + msg: "Rebooting kiosk after setup..." diff --git a/roles/kiosk/tasks/software.yml b/roles/kiosk/tasks/software.yml new file mode 100644 index 0000000000000000000000000000000000000000..c4c1f1e30a400263f0fe851ae378f5c0acd5b3e1 --- /dev/null +++ b/roles/kiosk/tasks/software.yml @@ -0,0 +1,21 @@ +# This task list sets up the basic tools +--- +- name: Install browser + become: yes + community.general.pacman: + name: firefox + state: present +- name: Install Xorg & wm & tools + become: yes + community.general.pacman: + name: + - xorg-xinit + - xorg-server + - xorg-xset + - xorg-setxkbmap + - unclutter + - openbox + - xf86-video-odroid-c2 + - ttf-liberation + - barrier-headless + state: present diff --git a/roles/kiosk/tasks/wm.yml b/roles/kiosk/tasks/wm.yml new file mode 100644 index 0000000000000000000000000000000000000000..eb35f77f79782d0a67a954c09f63c441ff650f96 --- /dev/null +++ b/roles/kiosk/tasks/wm.yml @@ -0,0 +1,46 @@ +# This task list sets up the window manager +--- +- name: Create autologin directory + become: yes + become_user: root + ansible.builtin.file: + state: directory + path: '/etc/systemd/system/getty@tty1.service.d/' + mode: '0755' + owner: root + group: root + +- name: Autologin + become: yes + become_user: root + ansible.builtin.copy: + src: agettyAutologin + dest: '/etc/systemd/system/getty@tty1.service.d/override.conf' + owner: root + group: root + mode: '0644' + +- name: xinitrc + ansible.builtin.copy: + dest: ~/.xinitrc + content: 'exec openbox-session' + mode: 0644 + +- name: Create autologin directory + ansible.builtin.file: + state: directory + path: '~/.config/openbox' + mode: '0755' + +- name: Setup openbox autostart + ansible.builtin.template: + src: openboxAutocomplete.j2 + dest: ~/.config/openbox/autostart + mode: 0644 + +- name: Autostart X on tty1 on odroid + ansible.builtin.lineinfile: + path: '~/.bashrc' + state: present + line: '[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && xinit' + mode: 0644 diff --git a/roles/kiosk/templates/openboxAutocomplete.j2 b/roles/kiosk/templates/openboxAutocomplete.j2 new file mode 100644 index 0000000000000000000000000000000000000000..a63fa2492074a828236f5251dd4ca2484d9b3efd --- /dev/null +++ b/roles/kiosk/templates/openboxAutocomplete.j2 @@ -0,0 +1,8 @@ +(sleep 1s && xset s off) & +(sleep 1s && xset s noblank) & +(sleep 1s && xset -dpms) & +(sleep 1s && setxkbmap -option terminate:ctrl_alt_bksp) & +(sleep 1s && unclutter) & +(sleep 1s && firefox --kiosk {{ dashboardUrl }}) & +(sleep 1s && {{ barrierCommand }}) + diff --git a/roles/localKey/tasks/main.yml b/roles/localKey/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..02f35497022b2ab10845c0f51ec69da0b79af375 --- /dev/null +++ b/roles/localKey/tasks/main.yml @@ -0,0 +1,8 @@ +- name: Local SSH keypair and remote deployment + delegate_to: localhost + throttle: 1 + ansible.builtin.script: + chdir: "{{ inventory_dir }}" + cmd: init.sh "{{ ansible_host }}" + register: cmd_reg +- debug: msg="{{ cmd_reg.stdout }}" diff --git a/roles/python/tasks/3.yml b/roles/python/tasks/3.yml new file mode 100644 index 0000000000000000000000000000000000000000..cc2f70e1f2008191b034f763539b19275d6d5212 --- /dev/null +++ b/roles/python/tasks/3.yml @@ -0,0 +1,21 @@ +- name: Pacman keyring + Python installation + delegate_to: localhost + ansible.builtin.shell: | + expect <