From: Felix Date: Tue, 1 Nov 2016 11:10:57 +0000 (+0100) Subject: initial import X-Git-Url: https://code.wpia.club/?p=infra.git;a=commitdiff_plain;h=417ce970216bcb6221d2e7335e89c65083cdecc5 initial import Current features include: - setup of gigi, cassiopeia-client, quiz-system, minimalist exim, nginx - setup of gigi-database from scratch (including validation of own domain and issuing own certificates - optional cassiopeia-signer in own container with communication via tcpserial - hop container for administrators connecting to the system Change-Id: Id8fe05c78c8ec0a93ed444daea0ab2399e3a5717 --- 417ce970216bcb6221d2e7335e89c65083cdecc5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..923abb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*~ +\#*\# + +#nre +/nre diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000..47a2257 --- /dev/null +++ b/bootstrap @@ -0,0 +1,42 @@ +#!/bin/bash +#sudo apt-get install sudo git +#sudo apt-get install emacs-nox tmux +#git clone ... +if ((UID != 0)); then + printf >&2 '%s: must be run as root\n' "$0" + exit 1 +fi +. conf-puppet + +if ! [[ -x /usr/bin/puppet ]]; then + apt-get update + apt-get install -y puppet puppet-master +fi + +if ! [[ -h /etc/puppet/code/modules ]]; then + ln -s $PWD/modules /etc/puppet/code/modules + ln -s $PWD/environments /etc/puppet/code/environments +fi +if grep -q "^search\|^domain" /etc/resolv.conf; then + echo "Removing domain from resolv.conf" + sed -i "/^search\|^domain/d" /etc/resolv.conf + systemctl restart puppet-master +fi + +if ! grep -q host01 /etc/hosts; then + echo "Changing hostname" + hostnamectl set-hostname host01 + echo "127.0.0.1 host01" >> /etc/hosts + systemctl restart puppet-master + echo "Please open a new shell (hostname) and restart bootstrap" + exit +fi + + +puppet module install puppetlabs-firewall +puppet module install puppetlabs-stdlib +puppet module install puppetlabs-apt +puppet module install puppetlabs-postgresql +puppet module install puppetlabs-mysql + +puppet apply /etc/puppet/code/environments/production/manifests --debug diff --git a/bootstrap-user b/bootstrap-user new file mode 100644 index 0000000..d25faf1 --- /dev/null +++ b/bootstrap-user @@ -0,0 +1,223 @@ +#!/bin/bash +#Get domain-name and gigi-ip from the puppet config to know how to communicate with gigi +hostname=$(sed -n "/\$systemDomain/ { s/\$systemDomain = '\([^']*\)'/\1/; p }" environments/production/manifests/ip.pp) +ip=$(grep -A10 -F '$ips' environments/production/manifests/ip.pp | grep -F 'gigi =>' | head -n 1 | sed "s/.*'\([^']*\)'.*/\1/") + +folder=.bootstrap-user-data +mkdir -p $folder + +# Curl gigi using correct host-header, faking https-access and using the cookies in "cookie-jar" +function mcurl { + local url="$1" + shift + curl -s --header "X-Real-Proto: https" --header "Host: www.$hostname" -b $folder/cookie-jar "http://$ip/$url" "$@" +} + +# get the csrf out of a webpage (arguments 1 and 2 can be used to select the correct csrf-token) +function csrf { + grep csrf | ${1:-cat} | ${2:-cat} | sed "s/.*value='\([^']*\)'.*/\\1/" +} + +# update the cookie-jar so that cookies received with https-only property are also sent over our fake-https-connection +function open-jar { + sed -i 's/TRUE/FALSE/g' "$1" # also use the cookie over insecure connection +} +function silent_read { + prompt="$1" + shift + read -rsp "$prompt" "$@" + printf '\n' +} +#execute a registration in gigi. If "$1" == "nopass" a password is not asked for but chosen at random. +function register { + csrf=$(mcurl register -c $folder/cookie-jar | csrf) + open-jar $folder/cookie-jar + silent_read "First Name: " fname + silent_read "Last Name: " lname + silent_read "Year of birth: " year + silent_read "Month of birth: " month + silent_read "Day of birth: " day + silent_read "Email address: " email + while [[ "$email" == *"'"* || "$email" == *"\\"* ]]; do + silent_read "Email address was not valid, try again: " email + done + if [[ "$1" == "nopass" ]]; then + pw1="$(head -c 15 /dev/urandom | base64)" + pw2="$pw1" + else + silent_read "Password: " pw1 + silent_read "Password (repeat): " pw2 + while [[ "$pw1" != "$pw2" ]]; do + silent_read "Password: " pw1 + silent_read "Password (repeat): " pw2 + done + fi + mcurl register --data-urlencode "name-type=western" \ + --data-urlencode "fname=$fname" \ + --data-urlencode "lname=$lname" \ + --data-urlencode "suffix" \ + --data-urlencode "name" \ + --data-urlencode "year=$year" \ + --data-urlencode "month=$month" \ + --data-urlencode "day=$day" \ + --data-urlencode "residenceCountry=invalid" \ + --data-urlencode "email=$email" \ + --data-urlencode "pword1=$pw1" \ + --data-urlencode "pword2=$pw2" \ + --data-urlencode "general=1" \ + --data-urlencode "country=1" \ + --data-urlencode "regional=1" \ + --data-urlencode "radius=1" \ + --data-urlencode "tos_agree=1" \ + --data-urlencode "process=Weiter" \ + --data-urlencode "csrf=$csrf" > /dev/null +} +if ! type curl > /dev/null; then + echo "requires curl" >&2 + exit 1 +fi +if ! [[ "$(sudo lxc-attach -n postgres-primary -- su -c "psql -At gigi" postgres <<< "\dt")" == "No relations found." ]]; then + echo "gigi already has a database" >&2 + exit 1 +fi +# Manually managing gigi + nginx for now +sudo lxc-attach -n front-nginx systemctl stop puppet.service +sudo lxc-attach -n gigi systemctl stop puppet.service + +#Stopping nginx so no-one external can interfere with our init procedure +sudo lxc-attach -n front-nginx systemctl stop nginx.service +sudo lxc-attach -n gigi systemctl stop gigi-proxy.{socket,service} +sudo lxc-attach -n gigi systemctl stop cassiopeia-client.service +sudo lxc-attach -n gigi gigi reset-database +sudo lxc-attach -n gigi systemctl start cassiopeia-client.service +sudo lxc-attach -n gigi systemctl start gigi-proxy.socket + +rm -f $folder/cookie-jar +echo "So... preliminary things done. Let's start with the setup" +echo "We need a first administrative user, this user will be one of the bootstrappers for the WoT and seed for support." +register +adminEmail=$email +adminPw=$pw1 +echo "Ok, let's define the second bootstrapper" +register nopass +secondaryEmail=$email +echo "You should now have been sent an activation link to the email you entered previously" +read -rp "The activation link: " link +params=${link##*\?} +csrf=$(mcurl "verify?$params" -c $folder/cookie-jar | csrf) +open-jar $folder/cookie-jar +echo "doing verification with $params" +if ! mcurl verify -d "$params&csrf=$csrf" | grep -qF "
"; then + echo "Your e-mail address did not verify." >&2 + exit 1 +fi + +echo "granting initial bootstrapping-rights" +sudo lxc-attach -n postgres-primary -- su -c "psql -d gigi" postgres </dev/null +open-jar $folder/cookie-jar + +echo "Creating organisation" +csrf=$(mcurl "orga/new" | csrf) +mgmOid=$(mcurl "orga/new" -v -d "O=SomeCA&L=town&ST=state&C=AT&contact=ce%40email.org&comments=&action=new&csrf=$csrf" 2>&1 | grep "< Location: " | sed "s_.*/\([0-9]*\)[^0-9]*_\1_") +if ! grep -q '^[0-9]\+$' <<< $mgmOid; then + echo "Got an Organisation ID that is not a number: $mgmOid." >&2 + exit 1 +fi +printf "Management Organisation id is \"%s\"\n" "$mgmOid" + +echo "add self as orgadmin for organisation" +csrf=$(mcurl orga/$mgmOid | csrf "head -n 2" "tail -n 1") +mcurl orga/$mgmOid --data-urlencode "email=$adminEmail" --data-urlencode "master=y" --data-urlencode "do_affiliate=Add" --data-urlencode "csrf=$csrf" &>/dev/null +echo "adding org-domain" +csrf=$(mcurl orga/$mgmOid | csrf "head -n 4" "tail -n 1") +domainName="$hostname" +mcurl orga/$mgmOid -d "domain=$domainName&addDomain=action&csrf=$csrf" &> /dev/null + +csrf=$(mcurl account/details | csrf "tail -1") +mcurl account/details -d "orgaForm=orga&org%3A$mgmOid&csrf=$csrf" &> /dev/null + +echo "Configuring pings for the domain" +domain=$(mcurl "account/domains" | grep "/account/domains/" | sed "s_.*/\([0-9]\+\)'.*_\1_") +if ! grep -q '^[0-9]\+$' <<< $domain; then + echo "Got a Domain ID that is not a number: $domain." >&2 + exit 1 +fi + +csrf=$(mcurl "account/domains/$domain" | tee $folder/domain | csrf "tail -n 1") + +token=$(grep pre $folder/domain | tail -n 1 | sed "s_.*>\([a-zA-Z0-9]*\)<.*_\1_") +name=$(grep "content available under" $folder/domain | sed "s_.*/cacert-\([a-zA-Z0-9]*\)\\.txt.*_\1_") + +sudo mkdir -p /data/nginx/challenge +printf "%s" "$token" | sudo tee /data/nginx/challenge/cacert-$name.txt > /dev/null + +openssl req -newkey rsa:4096 -subj "/CN=$domainName/OU=$token" -nodes -out $folder/self-req -keyout $folder/self-priv +openssl x509 -req -in $folder/self-req -signkey $folder/self-priv -out $folder/self-cert -extfile <(printf "extendedKeyUsage = clientAuth, serverAuth\n") + +cp $folder/self-cert modules/gigi/files/gigi.crt +setfacl -m user:puppet:r $folder/self-priv +cp --preserve=all $folder/self-priv modules/gigi/files/gigi.key +sudo lxc-attach -n front-nginx -- puppet agent --test --verbose + +mcurl "account/domains/$domain" -d "HTTPType=y&SSLType=y&ssl-type-0=direct&ssl-port-0=443&ssl-type-1=direct&ssl-port-1=&ssl-type-2=direct&ssl-port-2=&ssl-type-3=direct&ssl-port-3=&csrf=$csrf" > /dev/null + +echo "Pings configured... waiting" +sleep 5 +mcurl "account/domains/$domain" > $folder/domainStatus + +echo "Issuing certificate for web" + +function issue { + options=$1 + csrf=$(mcurl "account/certs/new" | csrf "head -n 1") + + openssl req -newkey rsa:4096 -subj "/CN=blabla" -nodes -out $folder/req -keyout $folder/priv + encoded=$(tr '\n' '?' < $folder/req | sed "s/=/%3D/g;s/+/%2B/g;s/\?/%0A/g") + + mcurl account/certs/new -d "CSR=$encoded&process=Next&csrf=$csrf" > /dev/null + + serial=$(mcurl account/certs/new -d "$options&OU=&hash_alg=SHA256&validFrom=now&validity=2y&login=1&description=&process=Issue+Certificate&csrf=$csrf" -v 2>&1 | tee $folder/certlog | grep "< Location: " | sed "s_.*/\([a-f0-9]*\)[^0-9]*_\1_") + echo "Certificate: $serial" + if [[ $serial != "" ]]; then + echo "installing" + mcurl "account/certs/$serial.crt?chain&noAnchor" > $folder/cert.crt + return 0; + else + return 1; + fi +} +if issue "profile=server-orga&CN=&SANs=dns%3Awww.$domainName%2Cdns%3Astatic.$domainName%2Cdns%3Aapi.$domainName%2Cdns%3Asecure.$domainName"; then + cp $folder/cert.crt modules/gigi/files/gigi.crt + setfacl -m user:puppet:r $folder/priv + cp --preserve=all $folder/priv modules/gigi/files/gigi.key + echo "reloading cert" + sudo lxc-attach -n front-nginx -- puppet agent --test --verbose +else + echo "refusing to update" +fi + +if issue "profile=mail-orga&CN=Gigi+System&SANs=email%3Agigi@$domainName"; then + echo "great!" + keystorepw=$(head -c 15 /dev/urandom | base64) + openssl pkcs12 -export -name "mail" -in $folder/cert.crt -inkey $folder/priv -CAfile modules/nre/files/config/ca/root.crt -password file:<(printf '%s' "$keystorepw") | sudo tee modules/gigi/files/keystore.pkcs12 > /dev/null + printf '%s' "$keystorepw" | sudo tee modules/gigi/files/keystorepw > /dev/null +else + echo "refusing to update" +fi +echo "marking gigi ready" +echo yes | sudo lxc-attach -n gigi tee /gigi-ready > /dev/null +sudo lxc-attach -n gigi -- puppet agent --test --verbose + +sudo lxc-attach -n front-nginx systemctl start puppet.service +sudo lxc-attach -n gigi systemctl start puppet.service diff --git a/bootstrap_with_nre b/bootstrap_with_nre new file mode 100755 index 0000000..57bebeb --- /dev/null +++ b/bootstrap_with_nre @@ -0,0 +1,25 @@ +#!/bin/bash +sudo apt-get install libfaketime +if ! [[ -d nre ]]; then + read -rp "URL to NRE git repo: " nre + git clone "$nre" nre + cd nre + read -rp "Update your Organisation name..." tmp + for command in "$VISUAL" "$EDITOR" emacs nano vim vi ex ed; do + "$command" commonFunctions.bash &>/dev/null && break + done + . conf-puppet + cat >> config < /dev/null; then + echo "SKIP $name" + else + echo "ISSUE $name" + openssl req -newkey rsa:4096 -subj "/CN=will-be-ignored" -nodes -out $folder/web.req -keyout $folder/web.key 2>/dev/null + cat $folder/web.req + read -r response + if [[ "$response" == "SUCCESS" ]]; then + # read certificate count + read -r len + printf '' > $folder/web.crt + for ((i=0;i> $folder/web.crt + done + rm $folder/web1.crt + crt=$(openssl x509 -in $folder/web.crt -noout -modulus) + key=$(openssl rsa -in $folder/web.key -noout -modulus) + if [[ $crt == $key ]]; then + echo "SUCCESS: $len"; + cp $folder/web.crt $name.crt + chmod +r $folder/web.key + cp $folder/web.key $name.key + else + echo "MISMATCH"; + fi + else + printf "%s\n" "$response" + fi + fi + } + update_cert "modules/quiz/files/web" + update_cert "modules/quiz/files/client" + update_cert "modules/gigi/files/gigi" + update_cert "modules/gigi/files/client" + echo "DONE" + [[ -f $folder/web.crt ]] && rm $folder/web.crt + [[ -f $folder/web.req ]] && rm $folder/web.req + [[ -f $folder/web.key ]] && rm $folder/web.key + rmdir $folder +elif [[ "$com" == "reload quiz certs" ]]; then + sudo puppet apply /etc/puppet/code/environments/production/manifests --verbose + sudo lxc-attach -n front-nginx -- puppet agent --verbose --test + sudo lxc-attach -n quiz -- puppet agent --verbose --test + sudo lxc-attach -n gigi -- puppet agent --verbose --test +elif [[ "$com" == "update crls" ]]; then + if ! tar xv -C /data/crl; then + echo "requiring tar" + exit; + fi + echo "Updating crls" + mkdir -p /data/crl/htdocs/g2 + for i in /data/crl/*.crl; do + if ! [[ -h /data/crl/htdocs/g2/${i#/data/crl/} ]]; then + ln -vs /data-crl/${i#/data/crl/} /data/crl/htdocs/g2/${i#/data/crl/} + fi + done + + for i in /data/gigi-crl/*/ca.crl; do + j=$(echo $i | sed "s#^/data/gigi-crl/\([a-zA-Z]*\)_\([0-9]*\)_\([0-9]\)/ca.crl#\2/\1-\3.crl#") + mkdir -p /data/crl/htdocs/g2/$(dirname $j) + if ! [[ -h /data/crl/htdocs/g2/$j ]]; then + ln -vs /data-crl-gigi/${i#/data/gigi-crl/} /data/crl/htdocs/g2/$j + fi + done + + mkdir -p /data/crl/crt-htdocs/g2 + for i in modules/nre/files/config/ca/*; do + [[ $i == *_* ]] && continue + if ! [[ -f /data/crl/crt-htdocs/g2/$(basename $i) ]]; then + cp -v $i /data/crl/crt-htdocs/g2/$(basename $i) + fi + done + for i in /data/gigi-crl/*/ca.crt; do + j=$(echo $i | sed "s#^/data/gigi-crl/\([a-zA-Z]*\)_\([0-9]*\)_\([0-9]\)/ca.crt#\2/\1-\3.crt#") + mkdir -p /data/crl/crt-htdocs/g2/$(dirname $j) + if ! [[ -h /data/crl/crt-htdocs/g2/$j ]]; then + ln -vs /data-crl-gigi/${i#/data/gigi-crl/} /data/crl/crt-htdocs/g2/$j + fi + done + +else + printf "%s\n" $com +fi diff --git a/conf-puppet b/conf-puppet new file mode 100644 index 0000000..4f807ca --- /dev/null +++ b/conf-puppet @@ -0,0 +1,24 @@ +#!/bin/bash +force=false +if [[ "$1" == "--force" ]]; then + force=true +fi +oldDomain=$(sed -n "/\$systemDomain/ { s/\$systemDomain = '\([^']*\)'/\1/; p }" environments/production/manifests/ip.pp) +if $force || [[ "$oldDomain" == "unknown" ]]; then + read -rp "Your Domain: " domain + sed -i "s/\$systemDomain = '[^']*'/\$systemDomain = '$domain'/" environments/production/manifests/ip.pp + oldDomain="$systemDomain" +fi + +if $force || grep -q "gigi_translation.*unknown" environments/production/manifests/ip.pp; then + read -rp "Your Path To Gigi Translation: " gigi + sed -i "s!\$gigi_translation = '[^']*'!\$gigi_translation = '$gigi'!" environments/production/manifests/ip.pp +fi + +if $force || grep -q "internet_iface.*unknown" environments/production/manifests/ip.pp; then + ip a + read -rp "Your Interface to the Internet: " iface + sed -i "s/\$internet_iface = '[^']*'/\$internet_iface = '$iface'/" environments/production/manifests/ip.pp +fi + +sed -i "s/\$administrativeUser = '[^']*'/\$administrativeUser = '${SUDO_USER:-$USER}'/" environments/production/manifests/ip.pp diff --git a/environments/production/.gitignore b/environments/production/.gitignore new file mode 100644 index 0000000..9788325 --- /dev/null +++ b/environments/production/.gitignore @@ -0,0 +1 @@ +/modules diff --git a/environments/production/manifests/gigi.pp b/environments/production/manifests/gigi.pp new file mode 100644 index 0000000..00a6c5f --- /dev/null +++ b/environments/production/manifests/gigi.pp @@ -0,0 +1,198 @@ +node gigi { + include container::contained; + include container::no_ssh; + + file { "${::puppet_vardir}/debconf/": + ensure => 'directory' + } + file { "${::puppet_vardir}/debconf/gigi-lang.debconf": + ensure => 'present', + content => "wpia-gigi-testing wpia-gigi-testing/fetch-locales-command string gigi fetch-locales $gigi_translation" + } -> + exec { 'debconf-gigi-testing': + path => "/usr/bin", + command => "/usr/bin/debconf-set-selections < ${::puppet_vardir}/debconf/gigi-lang.debconf", + unless => "/usr/bin/debconf-get-selections | /bin/grep -F '$gigi_translation'" + } + + class{'apt':} + apt_key{ 'E643C483A426BB5311D26520A631B6AF9FD3DF94': + source => 'http://deb.dogcraft.de/signer.gpg', + ensure => 'present' + } -> + file { '/etc/apt/sources.list.d/dogcraft.list': + source => 'puppet:///modules/lxc/dogcraft.list', + ensure => 'present', + notify => Exec['apt_update'] + } + package { 'wpia-gigi-testing': + require => [Exec['debconf-gigi-testing'],Exec['apt_update']], + ensure => 'installed', + } + $gigi_pg_ip = $ips[postgres]; + $gigi_pg_password = $passwords[postgres][gigi]; + file { '/var/lib/wpia-gigi': + ensure => 'directory' + } + file { '/var/lib/wpia-gigi/config': + ensure => 'directory' + } + file {'/var/lib/wpia-gigi/config/gigi.properties': + ensure => 'file', + content => epp('gigi/gigi.properties') + } + file {'/var/lib/wpia-gigi/config/ca': + ensure => 'directory', + source => 'puppet:///modules/nre/config/ca', + recurse => true, + purge => true, + notify => Exec['keytool for /var/lib/wpia-gigi/config/cacerts.jks'] + } + file {'/var/lib/wpia-gigi/config/profiles': + ensure => 'directory', + source => 'puppet:///modules/nre/config/profiles', + recurse => true, + purge => true, + } + exec {'keytool for /var/lib/wpia-gigi/config/cacerts.jks': + cwd => '/var/lib/wpia-gigi/config/ca', + refreshonly => true, + require => Package['wpia-gigi-testing'], + command => '/bin/rm -f ../cacerts.jks && /usr/bin/keytool -importcert -keystore ../cacerts.jks -noprompt -storepass changeit -file root.crt -alias root && for i in assured.crt codesign.crt env.crt orga.crt orgaSign.crt unassured.crt *_*.crt; do /usr/bin/keytool -importcert -keystore ../cacerts.jks -storepass changeit -file "$i" -alias "${i%.crt}"; done', + } + file {'/var/lib/wpia-gigi/config/truststorepw': + ensure => 'file', + content => 'changeit', + } + file {['/etc/wpia','/etc/wpia/gigi']: + ensure => 'directory' + } + file {'/var/lib/wpia-gigi/config/keystore.pkcs12': + source => ['puppet:///modules/gigi/keystore.pkcs12', 'puppet:///modules/gigi/empty'], + notify => Exec['tar for gigi-conf'] + }-> + file {'/var/lib/wpia-gigi/config/keystorepw': + source => ['puppet:///modules/gigi/keystorepw', 'puppet:///modules/gigi/empty'], + show_diff => 'no', + notify => Exec['tar for gigi-conf'] + } + exec{'tar for gigi-conf': + command => 'if /usr/bin/[ -s /var/lib/wpia-gigi/config/keystore.pkcs12 ]; then /bin/tar cf /etc/wpia/gigi/conf.tar gigi.properties truststorepw cacerts.jks keystorepw keystore.pkcs12; else /bin/tar cf /etc/wpia/gigi/conf.tar gigi.properties truststorepw cacerts.jks; fi', + provider => 'shell', + path => '', + cwd => '/var/lib/wpia-gigi/config', + unless => '/usr/bin/[ /var/lib/wpia-gigi/keys/keystore.pkcs12 -ot /etc/wpia/gigi/conf.tar ] && /usr/bin/[ /var/lib/wpia-gigi/config/cacerts.jks -ot /etc/wpia/gigi/conf.tar ]', + subscribe => [File['/var/lib/wpia-gigi/config/truststorepw'],Exec['keytool for /var/lib/wpia-gigi/config/cacerts.jks'],File['/var/lib/wpia-gigi/config/gigi.properties']], + require => File['/etc/wpia/gigi'] + } + file {'/var/lib/wpia-gigi/keys/crt': + ensure => 'directory', + owner => 'gigi', + require => Package['wpia-gigi-testing'] + } + file {'/var/lib/wpia-gigi/keys/csr': + ensure => 'directory', + owner => 'gigi', + require => Package['wpia-gigi-testing'] + } + exec {'/gigi-ready': + creates => '/gigi-ready', + command =>'/bin/false' + } + exec{'alexa': + command => '/usr/bin/gigi fetch-alexa /var/lib/wpia-gigi/blacklist.dat 100', + creates => '/var/lib/wpia-gigi/blacklist.dat', + require => [File['/var/lib/wpia-gigi'],Package['wpia-gigi-testing']] + } -> service{'gigi-proxy.socket': + ensure => 'running', + provider => 'systemd', + subscribe => [Exec['tar for gigi-conf'],File['/var/lib/wpia-gigi/config/profiles']], + require => [Package['wpia-gigi-testing'], File['/var/lib/wpia-gigi/keys/crt'], File['/var/lib/wpia-gigi/keys/csr'], Exec['/gigi-ready']] + } + package{'cacert-cassiopeia': + ensure => 'installed', + require => Exec['apt_update'] + } +if $signerLocation == 'self' { + package { 'tcpserial': + ensure => 'installed', + require => Exec['apt_update'] + } + $cass_ip = $ips[cassiopeia] + file {'/etc/systemd/system/tcpserial.service': + ensure => 'file', + content => epp('gigi/tcpserial'), + require => Package['tcpserial'] + }-> + service{'tcpserial.service': + ensure => 'running', + provider => 'systemd', + before => Service['cassiopeia-client.service'] + } +} elsif $signerLocation == '/dev/ttyS0' { + exec {'/bin/mknod /dev/ttyS0 c 4 64': + creates => "/dev/ttyS0", + before => Service['cassiopeia-client.service'] + } +} + + file {'/var/lib/cassiopeia/': + ensure => 'directory', + require => Package['cacert-cassiopeia'] + } + file {'/var/lib/cassiopeia/config.txt': + ensure => 'file', + content => epp('gigi/cassiopeia-client-conf') + } + + file {'/var/lib/cassiopeia/logs': + ensure => 'directory', + } + + file {'/var/lib/cassiopeia/profiles': + ensure => 'directory', + source => 'puppet:///modules/cassiopeia_client/profiles', + recurse => true, + purge => true + } + file {'/var/lib/cassiopeia/ca': + ensure => 'directory', + source => 'puppet:///modules/cassiopeia_client/ca', + recurse => true, + } + + file {'/var/lib/cassiopeia/keys': + ensure => 'directory', + require => File['/var/lib/cassiopeia/'] + } + file {'/var/lib/cassiopeia/keys/ca.crt': + ensure => 'file', + source => 'puppet:///modules/cassiopeia/ca.crt' + } + file {'/var/lib/cassiopeia/keys/signer_client.crt': + ensure => 'file', + source => 'puppet:///modules/cassiopeia/signer_client.crt' + } + file {'/var/lib/cassiopeia/keys/signer_client.key': + ensure => 'file', + source => 'puppet:///modules/cassiopeia/signer_client.key' + } + + file { '/etc/systemd/system/cassiopeia-client.service': + source => 'puppet:///modules/gigi/cassiopeia-client.service', + ensure => 'present' + } -> + service{'cassiopeia-client.service': + provider => 'systemd', + require => [File['/var/lib/cassiopeia/config.txt'], + File['/var/lib/cassiopeia/ca'], + File['/var/lib/cassiopeia/logs'], + File['/var/lib/cassiopeia/profiles'], + File['/var/lib/cassiopeia/keys/ca.crt'], + File['/var/lib/cassiopeia/keys/signer_client.crt'], + File['/var/lib/cassiopeia/keys/signer_client.key'], + Exec['/gigi-ready']], + ensure => 'running' + } + +} diff --git a/environments/production/manifests/hop.pp b/environments/production/manifests/hop.pp new file mode 100644 index 0000000..831bfda --- /dev/null +++ b/environments/production/manifests/hop.pp @@ -0,0 +1,40 @@ +node hop{ + include container::contained + + package { 'tmux': + ensure => 'installed'; + } + package { 'emacs-nox': + ensure => 'installed'; + } + user { 'admin': + ensure => 'present', + shell => '/bin/bash' + } + file { '/home/admin': + require => User['admin'], + ensure => 'directory', + owner => 'admin' + } + file { '/home/admin/join': + ensure => 'present', + source => 'puppet:///modules/hop/join', + mode => 'a+x', + owner => 'root' + } + file { '/home/admin/commands': + ensure => 'present', + content => epp('hop/commands'), + mode => 'a+x', + owner => 'root' + } + file { '/home/admin/.ssh': + ensure => 'directory', + owner => 'admin' + } + file { '/home/admin/.ssh/authorized_keys': + ensure => 'present', + source => 'puppet:///modules/hop/authorized_keys', + owner => 'root' + } +} diff --git a/environments/production/manifests/ip.pp b/environments/production/manifests/ip.pp new file mode 100644 index 0000000..3495a10 --- /dev/null +++ b/environments/production/manifests/ip.pp @@ -0,0 +1,25 @@ +$ips = { + front-nginx => '10.0.3.13', + gigi => '10.0.3.15', + cassiopeia => '10.0.3.16', + exim => '10.0.3.17', + hop => '10.0.3.18', + quiz => '10.0.3.19', + postgres => '10.0.3.14'} + +$passwords = { + postgres => { + gigi => 'gigi' + }, + quiz-mysql => { + root => 'root', + quiz => 'quiz' + } +} + +$internet_iface = 'unknown' +$systemDomain = 'unknown' +$gigi_translation = 'unknown' +$signerLocation = 'self' +$protected='no' +$administrativeUser = 'admin' diff --git a/environments/production/manifests/nginx.pp b/environments/production/manifests/nginx.pp new file mode 100644 index 0000000..021c5d4 --- /dev/null +++ b/environments/production/manifests/nginx.pp @@ -0,0 +1,68 @@ +define front_vhost($source, $crt = undefined){ + if $crt { + file{"/etc/ssl/private/$name.crt": + ensure => 'file', + source => ["puppet:///modules/$crt.crt", 'puppet:///modules/gigi/gigi.crt'], + show_diff => 'no', + notify => Service['nginx'], + before => File["/etc/nginx/sites-available/$name.conf"] + } + file{"/etc/ssl/private/$name.key": + ensure => 'file', + source => ["puppet:///modules/$crt.key", 'puppet:///modules/gigi/gigi.key'], + show_diff => 'no', + before => File["/etc/nginx/sites-available/$name.conf"] + } + } + file {"/etc/nginx/sites-available/$name.conf": + ensure => 'file', + content => epp($source), + require => Package['nginx-light'], + }-> + file {"/etc/nginx/sites-enabled/$name.conf": + ensure => 'link', + target => "/etc/nginx/sites-available/$name.conf", + require => Package['nginx-light'], + notify => Service['nginx'] + } +} + +node front-nginx { + include container::contained; + include container::no_ssh; + package{ 'nginx-light': + ensure => 'installed' + } + $gigi_ip = $ips[gigi]; + front_vhost{'gigi': + source => 'gigi/nginx', + crt => 'gigi/gigi', + notify => Service['nginx'] + } + front_vhost{'crl': + source => 'crl/nginx', + notify => Service['nginx'] + } + if($protected != 'no') { + file{'/etc/nginx/access.txt': + content => $protected, + require => Package['nginx-light'], + before => Service['nginx'] + } + } + file{'/etc/ssl/root.crt': + ensure => 'file', + source => ['puppet:///modules/nre/config/ca/root.crt'], + show_diff => 'no', + notify => Service['nginx'], + before => Front_vhost['quiz'] + } + front_vhost{'quiz': + source => 'quiz/nginx', + crt => 'quiz/web', + notify => Service['nginx'] + } + service {'nginx': + ensure => 'running' + } +} diff --git a/environments/production/manifests/postgres-primary.pp b/environments/production/manifests/postgres-primary.pp new file mode 100644 index 0000000..e90109f --- /dev/null +++ b/environments/production/manifests/postgres-primary.pp @@ -0,0 +1,31 @@ +node postgres-primary { + include container::contained + include container::no_ssh + + package{ 'postgresql': + ensure => 'installed', + install_options => ['--no-install-recommends'], + } + + class { 'postgresql::globals': + version => '9.6', + }-> + class { 'postgresql::server': + listen_addresses => '*', + } -> + postgresql::server::db { 'gigi': + require => Package['postgresql'], + user => 'gigi', + password => postgresql_password('gigi', $passwords[postgres][gigi]), + } + $gigi_ip = $ips[gigi]; + postgresql::server::pg_hba_rule { 'allow gigi to access its database': + require => Package['postgresql'], + description => "Open up PostgreSQL for access from gigi to its database", + type => 'host', + database => 'gigi', + user => 'gigi', + address => "$gigi_ip/32", + auth_method => 'md5', + } +} diff --git a/environments/production/manifests/quiz.pp b/environments/production/manifests/quiz.pp new file mode 100644 index 0000000..1cae709 --- /dev/null +++ b/environments/production/manifests/quiz.pp @@ -0,0 +1,81 @@ +define teracara_quiz (){ + class{'apt':} + apt_key{ 'E643C483A426BB5311D26520A631B6AF9FD3DF94': + source => 'http://deb.dogcraft.de/signer.gpg', + ensure => 'present' + } -> + file { '/etc/apt/sources.list.d/dogcraft.list': + source => 'puppet:///modules/lxc/dogcraft.list', + ensure => 'present', + notify => Exec['apt_update'] + } + package { 'teracara-quiz': + require => Exec['apt_update'], + ensure => 'installed', + } + package { 'apache2': + ensure => 'installed', + } + file {'/etc/apache2/sites-available/000-default.conf': + require => Package['apache2'], + ensure => 'file', + source => 'puppet:///modules/quiz/000-default.conf', + notify => Service['apache2'], + } + file {'/etc/teracara-quiz/config.php': + require => Package['teracara-quiz'], + ensure => 'file', + content => epp('quiz/config.php'), + } + file {'/etc/teracara-quiz/client.crt': + require => Package['teracara-quiz'], + ensure => 'file', + show_diff => 'false', + source => 'puppet:///modules/quiz/client.crt', + } + file {'/etc/teracara-quiz/client.key': + require => Package['teracara-quiz'], + ensure => 'file', + show_diff => 'false', + source => 'puppet:///modules/quiz/client.key', + } + file {'/etc/teracara-quiz/sq_config.php': + require => Package['teracara-quiz'], + ensure => 'file', + content => epp('quiz/sq_config'), + } + file{'/etc/teracara-quiz/root.crt': + require => Package['teracara-quiz'], + ensure => 'file', + source => ['puppet:///modules/nre/config/ca/root.crt'], + show_diff => 'no' + } + class {'::mysql::client': + package_name => 'mariadb-client' + } + class { '::mysql::server': + package_name => 'mariadb-server', + root_password => $passwords[quiz-mysql][root] + } + mysql::db { 'quiz': + require => Package['teracara-quiz'], + user => 'quiz', + password => $passwords[quiz-mysql][quiz], + host => 'localhost', + grant => ['SELECT', 'INSERT', 'UPDATE', 'DELETE'], + sql => '/usr/share/teracara-quiz/sql/db.sql', + import_timeout => 900, + } +} +node quiz{ + include container::contained; + include container::no_ssh; + + teracara_quiz{ 'quiz': } + service {'apache2': + require => Teracara_quiz['quiz'], + ensure => 'running', + } + +} + diff --git a/environments/production/manifests/root.pp b/environments/production/manifests/root.pp new file mode 100644 index 0000000..d51c17d --- /dev/null +++ b/environments/production/manifests/root.pp @@ -0,0 +1,182 @@ +class my_fw::post { + package { 'iptables-persistent': + ensure => 'installed' + } + resources { 'firewall': + purge => true, + } + Package['iptables-persistent'] -> + firewall { '80 dnat': + proto => 'tcp', + dport => '80', + jump => 'DNAT', + todest => "${$ips[front-nginx]}:80", + iniface => $internet_iface, + table => 'nat', + chain => 'PREROUTING', + } -> + firewall { '80 dnat-https': + proto => 'tcp', + dport => '443', + jump => 'DNAT', + todest => "${$ips[front-nginx]}:443", + iniface => $internet_iface, + table => 'nat', + chain => 'PREROUTING', + } -> + firewall { '80 dnat-htop-ssh': + proto => 'tcp', + dport => '2222', + jump => 'DNAT', + todest => "${$ips[hop]}:22", + iniface => $internet_iface, + table => 'nat', + chain => 'PREROUTING', + } -> + firewall { '80 MASQ': + chain => 'POSTROUTING', + table => 'nat', + jump => 'MASQUERADE', + proto => 'all', + outiface => $internet_iface, + source => '10.0.3.0/24', + } +} + + +node host01 { + include my_fw::post + include lxc + package {'bridge-utils': + ensure => 'installed' + } -> file {'/etc/network/interfaces.d/lxcbr0': + source => 'puppet:///modules/lxc/lxcbr0' + } -> exec {'ifup lxcbr0': + command => '/sbin/ifdown lxcbr0; /sbin/ifup lxcbr0', + refreshonly => true, + subscribe => File['/etc/network/interfaces.d/lxcbr0'] + } -> exec { "enable forwarding on $hostname": + user => "root", + command => "/bin/echo 1 > /proc/sys/net/ipv4/ip_forward", + unless => "/bin/grep -q 1 /proc/sys/net/ipv4/ip_forward"; + }-> + file_line {"root-resolv1": + path => "/etc/resolv.conf", + ensure => 'absent', + match_for_absence => "true", + match => '^domain ', + line => '' + }-> + file_line {"root-resolv2": + path => "/etc/resolv.conf", + ensure => 'absent', + match_for_absence => "true", + match => '^search ', + line => '' + } +if $signerLocation == 'self' { + exec {"create cassiopeia-comm-keys": + command => '/etc/puppet/code/modules/cassiopeia/mkcassiopeia', + creates => '/etc/puppet/code/modules/cassiopeia/files/signer_client.crt' + } +} else { + exec {"create cassiopeia-comm-keys": + command => '/bin/false', + creates => '/etc/puppet/code/modules/cassiopeia/files/signer_client.crt' + } +} + exec {"gigi keystore.pkcs12": + command => '/bin/bash -c \'keystorepw=$(/usr/bin/head -c 15 /dev/urandom | base64); /usr/bin/openssl pkcs12 -export -name "mail" -in /etc/puppet/code/modules/gigi/files/client.crt -inkey /etc/puppet/code/modules/gigi/client.key -CAfile /etc/puppet/codemodules/nre/files/config/ca/root.crt -password file:<(echo $keystorepw) > /etc/puppet/code/modules/gigi/files/keystore.pkcs12; /usr/bin/printf "%s" "$keystorepw" > /etc/puppet/code/modules/gigi/files/keystorepw\'', + unless => '/usr/bin/[ /etc/puppet/code/modules/gigi/files/keystore.pkcs12 -nt /etc/puppet/code/modules/gigi/files/client.crt ] || ! /usr/bin/[ -f /etc/puppet/code/modules/gigi/files/client.crt ]' + } + lxc::container { 'front-nginx': + contname => 'front-nginx', + ip => $ips[front-nginx], + dir => ["/data", "/data-crl", '/data-crl-gigi'], + bind => { + "/data/nginx" => {target => "data", option => ",ro"}, + "/data/crl" => {target => "data-crl", option => ",ro"}, + "/data/gigi-crl" => {target => "data-crl-gigi", option => ",ro"} + }, + require => File['/data/nginx', '/data/crl/htdocs', '/data/gigi-crl'] + } + file { '/data': + ensure => 'directory', + } + file { '/data/nginx': + ensure => 'directory', + } + file { '/data/crl': + ensure => 'directory', + owner => $administrativeUser + } + file { '/data/gigi-crl': + ensure => 'directory', + owner => $administrativeUser + } + file { '/data/crl/htdocs': + ensure => 'directory', + owner => $administrativeUser + } + file { '/data/postgres/conf': + ensure => 'directory', + } + file { '/data/postgres/data': + ensure => 'directory', + } + file { '/data/postgres': + ensure => 'directory', + } + file { '/data/gigi': + ensure => 'directory', + } + lxc::container { 'postgres-primary': + contname => 'postgres-primary', + ip => $ips[postgres], + dir => ["/var/lib/postgresql", "/etc/postgresql"], + bind => { + "/data/postgres/data" => { target => "var/lib/postgresql"}, + "/data/postgres/conf" => { target => "etc/postgresql"} + }, + require => File['/data/postgres'] + } + $gigi_serial_conf= $signerLocation ? { + 'self' => [], + '/dev/ttyS0' => ["lxc.cgroup.devices.allow = c 4:64 rwm"] + } + + lxc::container { 'gigi': + contname => 'gigi', + ip => $ips[gigi], + dir => ["/var/lib/wpia-gigi", "/var/lib/wpia-gigi/keys", '/var/lib/cassiopeia', '/var/lib/cassiopeia/ca'], + bind => { + "/data/gigi" => { target => "var/lib/wpia-gigi/keys"}, + "/data/gigi-crl" => { target => "var/lib/cassiopeia/ca"} + }, + confline => $gigi_serial_conf, + require => File['/data/gigi', '/data/gigi-crl'] + } + if $signerLocation == 'self' { + lxc::container { 'cassiopeia': + contname => 'cassiopeia', + ip => $ips[cassiopeia] + } + } + lxc::container { 'exim': + contname => 'exim', + ip => $ips[exim] + } + lxc::container { 'hop': + contname => 'hop', + ip => $ips[hop] + } + lxc::container { 'quiz': + contname => 'quiz', + ip => $ips[quiz] + } + # Required for bootstrap-user + package {'acl': + ensure => 'installed' + } +} + diff --git a/environments/production/manifests/site.pp b/environments/production/manifests/site.pp new file mode 100644 index 0000000..ad68ec3 --- /dev/null +++ b/environments/production/manifests/site.pp @@ -0,0 +1,123 @@ +node cassiopeia { + include container::contained +if $signerLocation == 'self' { + include container::no_ssh +} else { + include container::ssh +} + class{'apt':} + apt_key{ 'E643C483A426BB5311D26520A631B6AF9FD3DF94': + source => 'http://deb.dogcraft.de/signer.gpg', + ensure => 'present' + } -> + file { '/etc/apt/sources.list.d/dogcraft.list': + source => 'puppet:///modules/lxc/dogcraft.list', + ensure => 'present', + notify => Exec['apt_update'] + } -> + package { 'cacert-cassiopeia-signer': + ensure => 'installed', + require => Exec['apt_update'] + } +if $signerLocation == 'self' { + package { 'tcpserial': + ensure => 'installed', + require => Exec['apt_update'] + } + $cass_ip=''; + file {'/etc/systemd/system/tcpserial.service': + ensure => 'file', + content => epp('gigi/tcpserial'), + require => Package['tcpserial'] + }-> + service{'tcpserial.service': + ensure => 'running', + provider => 'systemd', + before => Service['cassiopeia-signer.service'] + } +} elsif $signerLocation == '/dev/ttyS0' { + exec {'/bin/mknod /dev/ttyS0 c 4 64': + creates => "/dev/ttyS0", + before => Service['cassiopeia-signer.service'] + } +} else { + fail("unknown signerLocation") +} + file {'/var/lib/cassiopeia/': + ensure => 'directory', + }-> + exec {'/usr/bin/openssl dhparam -out dh_param.pem 2048': + timeout => '0', + creates => '/var/lib/cassiopeia/dh_param.pem', + cwd => '/var/lib/cassiopeia/', + require => File['/var/lib/cassiopeia/'] + } # TODO: make this unneded and fix cassiopeia dh-param-generation + + file {'/var/lib/cassiopeia/logs': + ensure => 'directory', + } + + file {'/var/lib/cassiopeia/profiles': + ensure => 'directory', + source => 'puppet:///modules/cassiopeia_signer/profiles', + recurse => true, + purge => true + } + file {'/var/lib/cassiopeia/ca': + ensure => 'directory', + source => 'puppet:///modules/cassiopeia_signer/ca', + recurse => true, + } + + file {'/var/lib/cassiopeia/keys': + ensure => 'directory', + require => File['/var/lib/cassiopeia/'] + } + file {'/var/lib/cassiopeia/keys/ca.crt': + ensure => 'file', + source => 'puppet:///modules/cassiopeia/ca.crt', + } + file {'/var/lib/cassiopeia/keys/signer_server.crt': + ensure => 'file', + source => 'puppet:///modules/cassiopeia/signer_server.crt', + } + file {'/var/lib/cassiopeia/keys/signer_server.key': + ensure => 'file', + source => 'puppet:///modules/cassiopeia/signer_server.key', + } + $gigi_pg_ip="" + $gigi_pg_password="" + file {'/var/lib/cassiopeia/config.txt': + ensure => 'file', + content => epp('gigi/cassiopeia-client-conf'), + } + + file {'/etc/systemd/system/cassiopeia-signer.service': + ensure => 'file', + source => 'puppet:///modules/gigi/cassiopeia-signer.service', + }-> + service{'cassiopeia-signer.service': + ensure => 'running', + provider => 'systemd', + require => [Exec['/usr/bin/openssl dhparam -out dh_param.pem 2048'], + Package['cacert-cassiopeia-signer'], + File['/var/lib/cassiopeia/logs'], + File['/var/lib/cassiopeia/profiles'], + File['/var/lib/cassiopeia/ca'], + File['/var/lib/cassiopeia/config.txt'], + File['/var/lib/cassiopeia/keys/ca.crt'], + File['/var/lib/cassiopeia/keys/signer_server.crt'], + File['/var/lib/cassiopeia/keys/signer_server.key']] + } + +} + + +node exim{ + include container::contained; + include container::no_ssh; + + package{ 'exim4-daemon-light': + ensure => 'installed' + } +} diff --git a/modules/.gitignore b/modules/.gitignore new file mode 100644 index 0000000..5ce6f7e --- /dev/null +++ b/modules/.gitignore @@ -0,0 +1,11 @@ +/apache +/concat +/firewall +/stdlib + +# generated by nre +/nre +/cassiopeia_signer +/cassiopeia_client +/*/files/*.crt +/*/files/*.key diff --git a/modules/cassiopeia/.gitignore b/modules/cassiopeia/.gitignore new file mode 100644 index 0000000..52ee3c2 --- /dev/null +++ b/modules/cassiopeia/.gitignore @@ -0,0 +1,5 @@ +#generated by mkcassiopeia + +/demoCA +/files +/.rnd diff --git a/modules/cassiopeia/mkcassiopeia b/modules/cassiopeia/mkcassiopeia new file mode 100755 index 0000000..5e76f6f --- /dev/null +++ b/modules/cassiopeia/mkcassiopeia @@ -0,0 +1,31 @@ +#!/bin/bash +cd -- "$(dirname -- "$0")" +function genCA { + [[ -d demoCA ]] && return + mkdir demoCA + openssl req -new -newkey rsa:4096 -nodes -keyout demoCA/ca.key -out demoCA/ca.csr -subj "/CN=signerCA" + mkdir demoCA/newcerts + touch demoCA/index.txt + echo 01 > demoCA/serial + echo "unique_subject = no" > demoCA/index.txt.attr + openssl ca -config mkcassiopeia-openssl.cnf -create_serial -out demoCA/ca.crt -days 700 -batch -keyfile demoCA/ca.key \ + -selfsign -policy policy_anything -extensions v3_ca -infiles demoCA/ca.csr +} +function genKey { + local name="$1" + local eku="$2" + local keyName="$3" + [[ -f "$keyName.crt" ]] && return + openssl req -new -newkey rsa:4096 -nodes -subj "/CN=$name" -keyout "$keyName.key" -out "$keyName.csr" + chmod +r "$keyName.key" + openssl ca -config mkcassiopeia-openssl.cnf -days 700 \ + -batch -extfile <(printf "basicConstraints=critical, CA:FALSE\nkeyUsage=critical, digitalSignature, keyEncipherment, keyAgreement\nextendedKeyUsage=$eku\n") \ + -policy policy_anything -out "$keyName.crt" -keyfile demoCA/ca.key -cert demoCA/ca.crt -infiles "$keyName.csr" + + +} +genCA +mkdir -p files +cp -v demoCA/ca.crt files/ca.crt +genKey signer-server serverAuth files/signer_server +genKey signer-client clientAuth files/signer_client diff --git a/modules/cassiopeia/mkcassiopeia-openssl.cnf b/modules/cassiopeia/mkcassiopeia-openssl.cnf new file mode 100644 index 0000000..459a7bb --- /dev/null +++ b/modules/cassiopeia/mkcassiopeia-openssl.cnf @@ -0,0 +1,44 @@ +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +database = $dir/index.txt # database index file. +unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +RANDFILE = $dir/private/.rand # private random number file + +# Extension copying option: use with caution. +# copy_extensions = copy + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + + + +[ v3_ca ] +# Extensions for a typical CA +# PKIX recommendation. + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer +basicConstraints = critical,CA:true diff --git a/modules/container/manifests/init.pp b/modules/container/manifests/init.pp new file mode 100644 index 0000000..d43e23b --- /dev/null +++ b/modules/container/manifests/init.pp @@ -0,0 +1,21 @@ +class container::no_ssh { + package { [ 'openssh-client', 'openssh-server']: + ensure => purged + } +} +class container::contained { + package { 'puppet': + ensure => installed + } + service { 'puppet': + ensure => 'running' + } + file {'/certified': + content => '' + } +} +class container::ssh { + package { [ 'openssh-client', 'openssh-server']: + ensure => installed + } +} \ No newline at end of file diff --git a/modules/crl/templates/nginx.epp b/modules/crl/templates/nginx.epp new file mode 100644 index 0000000..5652d4d --- /dev/null +++ b/modules/crl/templates/nginx.epp @@ -0,0 +1,23 @@ +server { + listen 0.0.0.0:80; + listen 0.0.0.0:443 ssl; + server_name g2.crl.<%=$systemDomain%>; + ssl_certificate /etc/ssl/private/gigi.crt; + ssl_certificate_key /etc/ssl/private/gigi.key; + + location / { + root /data-crl/htdocs; + } +} + +server { + listen 0.0.0.0:80; + listen 0.0.0.0:443 ssl; + server_name g2.crt.<%=$systemDomain%>; + ssl_certificate /etc/ssl/private/gigi.crt; + ssl_certificate_key /etc/ssl/private/gigi.key; + + location / { + root /data-crl/crt-htdocs; + } +} diff --git a/modules/gigi/files/.gitignore b/modules/gigi/files/.gitignore new file mode 100644 index 0000000..8fee3c0 --- /dev/null +++ b/modules/gigi/files/.gitignore @@ -0,0 +1,2 @@ +/keystorepw +/keystore.pkcs12 diff --git a/modules/gigi/files/cassiopeia-client.service b/modules/gigi/files/cassiopeia-client.service new file mode 100644 index 0000000..9e960ec --- /dev/null +++ b/modules/gigi/files/cassiopeia-client.service @@ -0,0 +1,6 @@ +[Unit] +Description=cassiopeia client + +[Service] +ExecStart=/usr/bin/cassiopeia +WorkingDirectory=/var/lib/cassiopeia/ diff --git a/modules/gigi/files/cassiopeia-signer.service b/modules/gigi/files/cassiopeia-signer.service new file mode 100644 index 0000000..a567093 --- /dev/null +++ b/modules/gigi/files/cassiopeia-signer.service @@ -0,0 +1,6 @@ +[Unit] +Description=cassiopeia signer + +[Service] +ExecStart=/usr/bin/cassiopeia-signer +WorkingDirectory=/var/lib/cassiopeia/ diff --git a/modules/gigi/files/empty b/modules/gigi/files/empty new file mode 100644 index 0000000..e69de29 diff --git a/modules/gigi/templates/cassiopeia-client-conf.epp b/modules/gigi/templates/cassiopeia-client-conf.epp new file mode 100644 index 0000000..6b7a8a5 --- /dev/null +++ b/modules/gigi/templates/cassiopeia-client-conf.epp @@ -0,0 +1,13 @@ +<% if ($signerLocation == 'self') { %> +serialPath=/var/lib/cassiopeia/serial +<% } else { %> +serialPath=<%=$signerLocation%> +<% } %> +sql.host=<%=$gigi_pg_ip%> +sql.user=gigi +sql.password=<%=$gigi_pg_password%> +sql.database=gigi +key.directory=/var/lib/wpia-gigi/keys + +crlPrefix=http://g2.crl.<%=$systemDomain%> +crtPrefix=http://g2.crt.<%=$systemDomain%> diff --git a/modules/gigi/templates/cassiopeia-client.epp b/modules/gigi/templates/cassiopeia-client.epp new file mode 100644 index 0000000..f867908 --- /dev/null +++ b/modules/gigi/templates/cassiopeia-client.epp @@ -0,0 +1,7 @@ +[Unit] +Description=cassiopeia client +Conflicts=gigi-simple-signer.service + +[Service] +ExecStart=/usr/bin/cassiopeia +WorkingDirectory=/var/lib/cassiopeia diff --git a/modules/gigi/templates/gigi.properties.epp b/modules/gigi/templates/gigi.properties.epp new file mode 100644 index 0000000..59853df --- /dev/null +++ b/modules/gigi/templates/gigi.properties.epp @@ -0,0 +1,24 @@ +name.static=static.<%=$systemDomain%> +name.secure=secure.<%=$systemDomain%> +name.www=www.<%=$systemDomain%> +name.api=api.<%=$systemDomain%> + +gigi.uid=-1 +gigi.gid=-1 + +sql.driver=org.postgresql.Driver +sql.url=jdbc:postgresql://<%=$gigi_pg_ip%>/gigi +sql.user=gigi +sql.password=<%=$gigi_pg_password%> + +https.port=443 +http.port=80 +http.bindPort=stdin + +proxy=true + +emailProvider=club.wpia.gigi.email.SendMail +emailProvider.smtpHost=<%=$ips[exim]%> +emailProvider.smtpPort=25 + +highFinancialValue=blacklist.dat diff --git a/modules/gigi/templates/nginx.epp b/modules/gigi/templates/nginx.epp new file mode 100644 index 0000000..e6c8237 --- /dev/null +++ b/modules/gigi/templates/nginx.epp @@ -0,0 +1,63 @@ +server { + listen 0.0.0.0:443 ssl; + server_name api.<%=$systemDomain%>; + server_name secure.<%=$systemDomain%>; + ssl_certificate /etc/ssl/private/gigi.crt; + ssl_certificate_key /etc/ssl/private/gigi.key; + + ssl_client_certificate /etc/ssl/root.crt; + ssl_verify_client on; + ssl_verify_depth 4; + + location / { + proxy_pass http://<%=$gigi_ip%>; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-Proto https; + proxy_set_header X-Client-Cert $ssl_client_cert; + } +} + +server { + listen 0.0.0.0:443 ssl; + server_name *.<%=$systemDomain%>; + server_name <%=$systemDomain%>; + ssl_certificate /etc/ssl/private/gigi.crt; + ssl_certificate_key /etc/ssl/private/gigi.key; + + location / { + proxy_pass http://<%=$gigi_ip%>; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-Proto https; + proxy_set_header X-Client-Cert $ssl_client_cert; + <% if($protected != 'no') { %> + auth_basic "closed site"; + auth_basic_user_file /etc/nginx/access.txt; + <% } %> + } + location ~* /cacert-.* { + root /data/challenge; + } +} + +server { + listen 0.0.0.0:80; + server_name *.<%=$systemDomain%>; + server_name <%=$systemDomain%>; + + location / { + proxy_pass http://<%=$gigi_ip%>; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-Proto http; + proxy_set_header X-Client-Cert ""; + <% if($protected != 'no') { %> + auth_basic "closed site"; + auth_basic_user_file /etc/nginx/access.txt; + <% } %> + } + location ~* /cacert-.* { + root /data/challenge; + } +} diff --git a/modules/gigi/templates/tcpserial.epp b/modules/gigi/templates/tcpserial.epp new file mode 100644 index 0000000..9b5501e --- /dev/null +++ b/modules/gigi/templates/tcpserial.epp @@ -0,0 +1,6 @@ +[Unit] +Description=tcpserial for cassiopeia signer + +[Service] +Type=notify +ExecStart=/usr/bin/tcpserial /var/lib/cassiopeia/serial 8000 <%=$cass_ip%> diff --git a/modules/hop/files/authorized_keys b/modules/hop/files/authorized_keys new file mode 100644 index 0000000..428b5e5 --- /dev/null +++ b/modules/hop/files/authorized_keys @@ -0,0 +1,3 @@ +command="/home/admin/join lucas",no-port-forwarding,no-x11-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGT7rQdjhH3nfFcAciyLLhR9yoVKw/V7Yo2SwiGpYl9C lucas@pippin +command="/home/admin/join felix",no-port-forwarding,no-x11-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII9rX4mF7we1dwTX5/6FCI2zIjOOLZVxeVzz9i58uSO7 Felix@Schneeeule +command="/home/admin/join felix2",no-port-forwarding,no-x11-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHOETXyx/4HYYbU+VG14SLswXQfWDbf+wBqFoKF711U/ Felix2@Schneeeule diff --git a/modules/hop/files/join b/modules/hop/files/join new file mode 100644 index 0000000..d2e521e --- /dev/null +++ b/modules/hop/files/join @@ -0,0 +1,109 @@ +#!/bin/bash + +mkdir -p .join/ + +if ! [[ -z "$TMUX" ]]; then + printf >&2 'Already in tmux, unset TMUX to force nesting\n' + exit 1 +fi + +name="$1" +if [[ $name == "" ]]; then + printf >&2 'Usage: %s NAME\n' "$0" + exit 1 +fi + +set -o noclobber + +# duplicate stderr to fd 3 +exec 3>&2 +# kill stderr to hide noclobber errors +exec 2>/dev/null + +function sessionname { + if (($# != 2)); then + printf >&3 'sessionname requires exactly two arguments\n' + exit 1 + fi + if [[ "$1" < "$2" ]]; then + printf '%s\n' "$1-$2" + else + printf '%s\n' "$2-$1" + fi +} + +if printf '%s\n' "$name" > .join/join1; then + # we're the first + name1=$name + trap 'rm -f .join/join1' EXIT + # wait for second + printf 'Waiting for second client...\n' + while ! [[ -f .join/join2 ]]; do + sleep 1 + done + read -r name2 < .join/join2 + trap "echo false >| .join/$name1-$name2; rm -f .join/join1" EXIT + read -p "Do you want to collaborate with $name2? [Y/n] " -r response 2>&3 + if [[ "$response" =~ ^[Nn] ]]; then + echo false >| .join/"$name1-$name2" + exit 1 + else + # set up session + if ! tmux has-session -t "$(sessionname "$name1" "$name2")" &> /dev/null; then + tmux new-session -s "$(sessionname "$name1" "$name2")" -d + tmux set-hook -t "$(sessionname "$name1" "$name2")" client-detached "run 'tmux detach-client -s $(sessionname "$name1" "$name2"); true'" + fi + echo true >| .join/"$name1-$name2" + fi + rm -f .join/join1 .join/join2 + # ready +else + read -r name1 < .join/join1 + read -p "Do you want to collaborate with $name1? [Y/n] " -r response 2>&3 + if [[ "$response" =~ ^[Nn] ]]; then + exit 1 + fi + if printf '%s\n' "$name" > .join/join2; then + # we're the second + trap 'rm -f .join/join2' EXIT + read -r name1 < .join/join1 + name2=$name + if [[ "$name1" == "$name2" ]]; then + printf >&3 'same client twice not allowed, exiting\n' + exit 1 + fi + # wait for first to acknowledge collaboration + while ! [[ -f .join/"$name1-$name2" ]]; do + if ! read -r name1_ < .join/join1 || ! [[ "$name1_" == "$name1" ]]; then + printf >&3 '%s has aborted collaboration.\n' "$name1" + exit 1 + fi + sleep 1 + done + read -r ack < ".join/$name1-$name2" + rm -f ".join/$name1-$name2" + if [[ $ack != true ]]; then + printf >&3 '%s does not want to collaborate with you\n' "$name1" + exit 1 + fi + else + # we're the third one, nope + printf >&3 'two clients already connected, exiting\n' + exit 1 + fi +fi +if [[ "$name1" == "$name2" ]]; then + printf >&3 'same client twice not allowed, exiting\n' + exit 1 +fi +( + while tmux has-session -t "$(sessionname "$name1" "$name2")"; do + sleep 5 + [[ -f .join/"$name1-$name2" ]] && rm -f ".join/$name1-$name2" + if (($(tmux list-clients -t "$(sessionname "$name1" "$name2")" | wc -l)!=2)); then + tmux detach-client -s "$(sessionname "$name1" "$name2")" + break + fi + done +) & +exec tmux attach -t "$(sessionname "$name1" "$name2")" diff --git a/modules/hop/templates/commands.epp b/modules/hop/templates/commands.epp new file mode 100755 index 0000000..cb1720f --- /dev/null +++ b/modules/hop/templates/commands.epp @@ -0,0 +1,14 @@ +#!/bin/bash + +com="$SSH_ORIGINAL_COMMAND" +if [[ "$com" == "ask quiz certs" ]]; then + exec ssh <%=$administrativeUser%>@10.0.3.1 "ask quiz certs" +elif [[ "$com" == "reload quiz certs" ]]; then + # requires sudo --> requires terminal + exec ssh -t <%=$administrativeUser%>@10.0.3.1 "reload quiz certs" +elif [[ "$com" == "update crls" ]]; then + exec ssh <%=$administrativeUser%>@10.0.3.1 "update crls" +else + echo $com +fi + diff --git a/modules/lxc/files/dogcraft.list b/modules/lxc/files/dogcraft.list new file mode 100644 index 0000000..5a9e6ed --- /dev/null +++ b/modules/lxc/files/dogcraft.list @@ -0,0 +1 @@ +deb http://deb2.dogcraft.de/ stretch main diff --git a/modules/lxc/files/lxcbr0 b/modules/lxc/files/lxcbr0 new file mode 100644 index 0000000..e392d62 --- /dev/null +++ b/modules/lxc/files/lxcbr0 @@ -0,0 +1,7 @@ +auto lxcbr0 +iface lxcbr0 inet static + bridge_ports none + bridge_fd 0 + bridge_maxwait 0 + address 10.0.3.1 + netmask 255.255.255.0 diff --git a/modules/lxc/manifests/init.pp b/modules/lxc/manifests/init.pp new file mode 100644 index 0000000..b0c64c4 --- /dev/null +++ b/modules/lxc/manifests/init.pp @@ -0,0 +1,154 @@ +class lxc { + file {"/data/log": + ensure => 'directory' + } + package{ 'lxc': + ensure => 'installed' + } + define container ($contname, $ip, $dir = [], $bind = {}, $confline = []) { + exec {"lxc-$contname-issue-cert": + command => "/usr/bin/puppet ca destroy \"$contname\";/usr/bin/puppet ca generate \"$contname\"", + unless => "/usr/bin/[ -f /var/lib/puppet/ssl/private_keys/$contname.pem ] && /usr/bin/[ -f /var/lib/puppet/ssl/certs/$contname.pem ]", + before => Exec["lxc-$contname-started"] + } + + exec{ "lxc-$contname-created": + logoutput => on_failure, + command => "/usr/bin/lxc-create -n $contname -t debian -- -r stretch --packages=gnupg2", ## requires gnupg for puppet seed + unless => "/usr/bin/test -d /var/lib/lxc/$contname", + timeout => '0', + require => Package['lxc'], + } -> file_line {"lxc-$contname-conf1": + path => "/var/lib/lxc/$contname/config", + line => 'lxc.network.type = veth', + notify => Exec["lxc-$contname-started"], + } -> file_line {"lxc-$contname-conf2": + path => "/var/lib/lxc/$contname/config", + line => 'lxc.network.link = lxcbr0', + notify => Exec["lxc-$contname-started"], + } -> file_line {"lxc-$contname-conf3": + path => "/var/lib/lxc/$contname/config", + line => 'lxc.network.flags = up', + notify => Exec["lxc-$contname-started"], + } -> file_line {"lxc-$contname-conf4": + path => "/var/lib/lxc/$contname/config", + line => "lxc.network.ipv4 = $ip/24", + notify => Exec["lxc-$contname-started"], + } -> file_line {"lxc-$contname-conf5": + path => "/var/lib/lxc/$contname/config", + line => 'lxc.network.ipv4.gateway = 10.0.3.1', + notify => Exec["lxc-$contname-started"], + } -> file_line {"lxc-$contname-network": + path => "/var/lib/lxc/$contname/rootfs/etc/network/interfaces", + line => 'iface eth0 inet manual', + match => '^iface eth0 inet', + notify => Exec["lxc-$contname-started"], + } -> exec {"lxc-$contname-started": + path => '/usr/bin', + refreshonly => true, + refresh => "/usr/bin/lxc-stop -n $contname ; /usr/bin/lxc-start -dn $contname", + }-> exec {"lxc-$contname-started1": + command => "/usr/bin/lxc-start -dn $contname", + unless => "/usr/bin/[ \"\$(lxc-info -Hsn $contname)\" != \"STOPPED\" ]", + } + $dir.each |String $in| { + file { "/var/lib/lxc/$contname/rootfs/$in": + ensure => 'directory', + notify => Exec["lxc-$contname-started"], + require => File_line["lxc-$contname-conf5"] + } + } + $bind.each |String $out, Struct[{target=>String, Optional[option]=>String}] $in| { + file_line { "lxc-$contname-mount-$out": + path => "/var/lib/lxc/$contname/config", + line => "lxc.mount.entry = $out ${in[target]} none bind${in[option]} 0 0", + require=> File_line["lxc-$contname-conf5"], + notify => Exec["lxc-$contname-started"], + } + } + file {"/data/log/$contname": + ensure => 'directory' + }-> + file_line { "lxc-$contname-mount-journal": + path => "/var/lib/lxc/$contname/config", + line => "lxc.mount.entry = /data/log/$contname var/log/journal none bind 0 0", + require=> File_line["lxc-$contname-conf5"], + notify => Exec["lxc-$contname-started"], + } + file {"/var/lib/lxc/$contname/rootfs/var/log/journal": + ensure => 'directory', + notify => Exec["lxc-$contname-started"], + require => File_line["lxc-$contname-conf5"] + } + $confline.each |Integer $idx, String $in| { + file_line { "lxc-$contname-confline-extra-$idx": + path => "/var/lib/lxc/$contname/config", + line => "$in", + require=> File_line["lxc-$contname-conf5"], + notify => Exec["lxc-$contname-started"], + } + } + file {"/var/lib/lxc/$contname/rootfs/var/lib/puppet": + ensure => 'directory', + require => Exec["lxc-$contname-created"] + } + file {"/var/lib/lxc/$contname/rootfs/var/lib/puppet/ssl": + ensure => 'directory' + } + file {"/var/lib/lxc/$contname/rootfs/var/lib/puppet/ssl/private_keys/": + ensure => 'directory' + } + file {"/var/lib/lxc/$contname/rootfs/var/lib/puppet/ssl/certs/": + ensure => 'directory' + } + Exec["lxc-$contname-started1"] -> + file_line {"lxc-$contname-hosts": + path => "/var/lib/lxc/$contname/rootfs/etc/hosts", + line => '10.0.3.1 puppet puppet.lan host01'; + }-> + file_line {"lxc-$contname-hosts-local": + path => "/var/lib/lxc/$contname/rootfs/etc/hosts", + line => "127.0.0.1 $contname" + }-> + file_line {"lxc-$contname-resolv1": + path => "/var/lib/lxc/$contname/rootfs/etc/resolv.conf", + ensure => 'absent', + match_for_absence => "true", + match => '^domain ', + line => '' + }-> + file_line {"lxc-$contname-resolv2": + path => "/var/lib/lxc/$contname/rootfs/etc/resolv.conf", + ensure => 'absent', + match_for_absence => "true", + match => '^search ', + line => '' + } -> + exec {"lxc-$contname-install-puppet": + command => "/usr/bin/lxc-attach -n \"$contname\" -- apt-get update && /usr/bin/lxc-attach -n \"$contname\" -- apt-get install -y puppet", + timeout => '0', + creates => "/var/lib/lxc/$contname/rootfs/usr/bin/puppet" + } -> + file {"/var/lib/lxc/$contname/rootfs/var/lib/puppet/ssl/private_keys/$contname.pem": + source => "file:///var/lib/puppet/ssl/private_keys/$contname.pem", + notify => Exec["lxc-$contname-puppet-restart"], + } -> + file {"/var/lib/lxc/$contname/rootfs/var/lib/puppet/ssl/certs/$contname.pem": + source => "file:///var/lib/puppet/ssl/certs/$contname.pem", + notify => Exec["lxc-$contname-puppet-restart"], + } -> + exec {"lxc-$contname-puppet-restart": + command => "/usr/bin/lxc-attach -n $contname -- systemctl restart puppet", + timeout => '0', + refreshonly => 'true' + } -> + exec {"lxc-$contname-refresh": + command => "/usr/bin/lxc-attach -n $contname -- puppet agent --onetime --no-daemonize --verbose", + timeout => '0', + # TODO figure out a way to verify puppet launches + creates => "/var/lib/lxc/$contname/rootfs/certified" + ##creates => "/var/lib/lxc/$contname/rootfs/lib/systemd/system/puppet.service" + } + } + +} diff --git a/modules/quiz/files/000-default.conf b/modules/quiz/files/000-default.conf new file mode 100644 index 0000000..d99c83a --- /dev/null +++ b/modules/quiz/files/000-default.conf @@ -0,0 +1,31 @@ + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + #ServerName www.example.com + + ServerAdmin webmaster@localhost + DocumentRoot /usr/share/teracara-quiz/www/ + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/modules/quiz/templates/config.php.epp b/modules/quiz/templates/config.php.epp new file mode 100644 index 0000000..e404a84 --- /dev/null +++ b/modules/quiz/templates/config.php.epp @@ -0,0 +1,574 @@ +'; + +/* +|-------------------------------------------------------------------------- +| Index File +|-------------------------------------------------------------------------- +| +| Typically this will be your index.php file, unless you've renamed it to +| something else. If you are using mod_rewrite to remove the page set this +| variable so that it is blank. +| +*/ +$config['index_page'] = 'index.php'; + +/* +|-------------------------------------------------------------------------- +| URI PROTOCOL +|-------------------------------------------------------------------------- +| +| This item determines which server global should be used to retrieve the +| URI string. The default setting of 'REQUEST_URI' works for most servers. +| If your links do not seem to work, try one of the other delicious flavors: +| +| 'REQUEST_URI' Uses $_SERVER['REQUEST_URI'] +| 'QUERY_STRING' Uses $_SERVER['QUERY_STRING'] +| 'PATH_INFO' Uses $_SERVER['PATH_INFO'] +| +| WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! +*/ +$config['uri_protocol'] = 'REQUEST_URI'; + +/* +|-------------------------------------------------------------------------- +| URL suffix +|-------------------------------------------------------------------------- +| +| This option allows you to add a suffix to all URLs generated by CodeIgniter. +| For more information please see the user guide: +| +| https://codeigniter.com/user_guide/general/urls.html +*/ +$config['url_suffix'] = ''; + +/* +|-------------------------------------------------------------------------- +| Default Language +|-------------------------------------------------------------------------- +| +| This determines which set of language files should be used. Make sure +| there is an available translation if you intend to use something other +| than english. +| +*/ +$config['language'] = 'english'; + +/* +|-------------------------------------------------------------------------- +| Default Character Set +|-------------------------------------------------------------------------- +| +| This determines which character set is used by default in various methods +| that require a character set to be provided. +| +| See http://php.net/htmlspecialchars for a list of supported charsets. +| +*/ +$config['charset'] = 'UTF-8'; + +/* +|-------------------------------------------------------------------------- +| Enable/Disable System Hooks +|-------------------------------------------------------------------------- +| +| If you would like to use the 'hooks' feature you must enable it by +| setting this variable to TRUE (boolean). See the user guide for details. +| +*/ +$config['enable_hooks'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Class Extension Prefix +|-------------------------------------------------------------------------- +| +| This item allows you to set the filename/classname prefix when extending +| native libraries. For more information please see the user guide: +| +| https://codeigniter.com/user_guide/general/core_classes.html +| https://codeigniter.com/user_guide/general/creating_libraries.html +| +*/ +$config['subclass_prefix'] = 'MY_'; + +/* +|-------------------------------------------------------------------------- +| Composer auto-loading +|-------------------------------------------------------------------------- +| +| Enabling this setting will tell CodeIgniter to look for a Composer +| package auto-loader script in application/vendor/autoload.php. +| +| $config['composer_autoload'] = TRUE; +| +| Or if you have your vendor/ directory located somewhere else, you +| can opt to set a specific path as well: +| +| $config['composer_autoload'] = '/path/to/vendor/autoload.php'; +| +| For more information about Composer, please visit http://getcomposer.org/ +| +| Note: This will NOT disable or override the CodeIgniter-specific +| autoloading (application/config/autoload.php) +*/ +$config['composer_autoload'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Allowed URL Characters +|-------------------------------------------------------------------------- +| +| This lets you specify which characters are permitted within your URLs. +| When someone tries to submit a URL with disallowed characters they will +| get a warning message. +| +| As a security measure you are STRONGLY encouraged to restrict URLs to +| as few characters as possible. By default only these are allowed: a-z 0-9~%.:_- +| +| Leave blank to allow all characters -- but only if you are insane. +| +| The configured value is actually a regular expression character group +| and it will be executed as: ! preg_match('/^[]+$/i +| +| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! +| +*/ +$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; + +/* +|-------------------------------------------------------------------------- +| Enable Query Strings +|-------------------------------------------------------------------------- +| +| By default CodeIgniter uses search-engine friendly segment based URLs: +| example.com/who/what/where/ +| +| By default CodeIgniter enables access to the $_GET array. If for some +| reason you would like to disable it, set 'allow_get_array' to FALSE. +| +| You can optionally enable standard query string based URLs: +| example.com?who=me&what=something&where=here +| +| Options are: TRUE or FALSE (boolean) +| +| The other items let you set the query string 'words' that will +| invoke your controllers and its functions: +| example.com/index.php?c=controller&m=function +| +| Please note that some of the helpers won't work as expected when +| this feature is enabled, since CodeIgniter is designed primarily to +| use segment based URLs. +| +*/ +$config['allow_get_array'] = TRUE; +$config['enable_query_strings'] = FALSE; +$config['controller_trigger'] = 'c'; +$config['function_trigger'] = 'm'; +$config['directory_trigger'] = 'd'; + +/* +|-------------------------------------------------------------------------- +| Error Logging Threshold +|-------------------------------------------------------------------------- +| +| You can enable error logging by setting a threshold over zero. The +| threshold determines what gets logged. Threshold options are: +| +| 0 = Disables logging, Error logging TURNED OFF +| 1 = Error Messages (including PHP errors) +| 2 = Debug Messages +| 3 = Informational Messages +| 4 = All Messages +| +| You can also pass an array with threshold levels to show individual error types +| +| array(2) = Debug Messages, without Error Messages +| +| For a live site you'll usually only enable Errors (1) to be logged otherwise +| your log files will fill up very fast. +| +*/ +$config['log_threshold'] = 0; + +/* +|-------------------------------------------------------------------------- +| Error Logging Directory Path +|-------------------------------------------------------------------------- +| +| Leave this BLANK unless you would like to set something other than the default +| application/logs/ directory. Use a full server path with trailing slash. +| +*/ +$config['log_path'] = ''; + +/* +|-------------------------------------------------------------------------- +| Log File Extension +|-------------------------------------------------------------------------- +| +| The default filename extension for log files. The default 'php' allows for +| protecting the log files via basic scripting, when they are to be stored +| under a publicly accessible directory. +| +| Note: Leaving it blank will default to 'php'. +| +*/ +$config['log_file_extension'] = ''; + +/* +|-------------------------------------------------------------------------- +| Log File Permissions +|-------------------------------------------------------------------------- +| +| The file system permissions to be applied on newly created log files. +| +| IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal +| integer notation (i.e. 0700, 0644, etc.) +*/ +$config['log_file_permissions'] = 0644; + +/* +|-------------------------------------------------------------------------- +| Date Format for Logs +|-------------------------------------------------------------------------- +| +| Each item that is logged has an associated date. You can use PHP date +| codes to set your own date formatting +| +*/ +$config['log_date_format'] = 'Y-m-d H:i:s'; + +/* +|-------------------------------------------------------------------------- +| Error Views Directory Path +|-------------------------------------------------------------------------- +| +| Leave this BLANK unless you would like to set something other than the default +| application/views/errors/ directory. Use a full server path with trailing slash. +| +*/ +$config['error_views_path'] = ''; + +/* +|-------------------------------------------------------------------------- +| Cache Directory Path +|-------------------------------------------------------------------------- +| +| Leave this BLANK unless you would like to set something other than the default +| application/cache/ directory. Use a full server path with trailing slash. +| +*/ +$config['cache_path'] = ''; + +/* +|-------------------------------------------------------------------------- +| Cache Include Query String +|-------------------------------------------------------------------------- +| +| Whether to take the URL query string into consideration when generating +| output cache files. Valid options are: +| +| FALSE = Disabled +| TRUE = Enabled, take all query parameters into account. +| Please be aware that this may result in numerous cache +| files generated for the same page over and over again. +| array('q') = Enabled, but only take into account the specified list +| of query parameters. +| +*/ +$config['cache_query_string'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Encryption Key +|-------------------------------------------------------------------------- +| +| If you use the Encryption class, you must set an encryption key. +| See the user guide for more info. +| +| https://codeigniter.com/user_guide/libraries/encryption.html +| +*/ +$config['encryption_key'] = ''; + +/* +|-------------------------------------------------------------------------- +| Session Variables +|-------------------------------------------------------------------------- +| +| 'sess_driver' +| +| The storage driver to use: files, database, redis, memcached +| +| 'sess_cookie_name' +| +| The session cookie name, must contain only [0-9a-z_-] characters +| +| 'sess_expiration' +| +| The number of SECONDS you want the session to last. +| Setting to 0 (zero) means expire when the browser is closed. +| +| 'sess_save_path' +| +| The location to save sessions to, driver dependent. +| +| For the 'files' driver, it's a path to a writable directory. +| WARNING: Only absolute paths are supported! +| +| For the 'database' driver, it's a table name. +| Please read up the manual for the format with other session drivers. +| +| IMPORTANT: You are REQUIRED to set a valid save path! +| +| 'sess_match_ip' +| +| Whether to match the user's IP address when reading the session data. +| +| WARNING: If you're using the database driver, don't forget to update +| your session table's PRIMARY KEY when changing this setting. +| +| 'sess_time_to_update' +| +| How many seconds between CI regenerating the session ID. +| +| 'sess_regenerate_destroy' +| +| Whether to destroy session data associated with the old session ID +| when auto-regenerating the session ID. When set to FALSE, the data +| will be later deleted by the garbage collector. +| +| Other session cookie settings are shared with the rest of the application, +| except for 'cookie_prefix' and 'cookie_httponly', which are ignored here. +| +*/ +$config['sess_driver'] = 'files'; +$config['sess_cookie_name'] = 'ci_session'; +$config['sess_expiration'] = 7200; +$config['sess_save_path'] = NULL; +$config['sess_match_ip'] = FALSE; +$config['sess_time_to_update'] = 300; +$config['sess_regenerate_destroy'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Cookie Related Variables +|-------------------------------------------------------------------------- +| +| 'cookie_prefix' = Set a cookie name prefix if you need to avoid collisions +| 'cookie_domain' = Set to .your-domain.com for site-wide cookies +| 'cookie_path' = Typically will be a forward slash +| 'cookie_secure' = Cookie will only be set if a secure HTTPS connection exists. +| 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript) +| +| Note: These settings (with the exception of 'cookie_prefix' and +| 'cookie_httponly') will also affect sessions. +| +*/ +$config['cookie_prefix'] = ''; +$config['cookie_domain'] = ''; +$config['cookie_path'] = '/'; +$config['cookie_secure'] = FALSE; +$config['cookie_httponly'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Standardize newlines +|-------------------------------------------------------------------------- +| +| Determines whether to standardize newline characters in input data, +| meaning to replace \r\n, \r, \n occurrences with the PHP_EOL value. +| +| This is particularly useful for portability between UNIX-based OSes, +| (usually \n) and Windows (\r\n). +| +*/ +$config['standardize_newlines'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Global XSS Filtering +|-------------------------------------------------------------------------- +| +| Determines whether the XSS filter is always active when GET, POST or +| COOKIE data is encountered +| +| WARNING: This feature is DEPRECATED and currently available only +| for backwards compatibility purposes! +| +*/ +$config['global_xss_filtering'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Cross Site Request Forgery +|-------------------------------------------------------------------------- +| Enables a CSRF cookie token to be set. When set to TRUE, token will be +| checked on a submitted form. If you are accepting user data, it is strongly +| recommended CSRF protection be enabled. +| +| 'csrf_token_name' = The token name +| 'csrf_cookie_name' = The cookie name +| 'csrf_expire' = The number in seconds the token should expire. +| 'csrf_regenerate' = Regenerate token on every submission +| 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks +*/ +$config['csrf_protection'] = FALSE; +$config['csrf_token_name'] = 'csrf_test_name'; +$config['csrf_cookie_name'] = 'csrf_cookie_name'; +$config['csrf_expire'] = 7200; +$config['csrf_regenerate'] = TRUE; +$config['csrf_exclude_uris'] = array(); + +/* +|-------------------------------------------------------------------------- +| Output Compression +|-------------------------------------------------------------------------- +| +| Enables Gzip output compression for faster page loads. When enabled, +| the output class will test whether your server supports Gzip. +| Even if it does, however, not all browsers support compression +| so enable only if you are reasonably sure your visitors can handle it. +| +| Only used if zlib.output_compression is turned off in your php.ini. +| Please do not use it together with httpd-level output compression. +| +| VERY IMPORTANT: If you are getting a blank page when compression is enabled it +| means you are prematurely outputting something to your browser. It could +| even be a line of whitespace at the end of one of your scripts. For +| compression to work, nothing can be sent before the output buffer is called +| by the output class. Do not 'echo' any values with compression enabled. +| +*/ +$config['compress_output'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Master Time Reference +|-------------------------------------------------------------------------- +| +| Options are 'local' or any PHP supported timezone. This preference tells +| the system whether to use your server's local time as the master 'now' +| reference, or convert it to the configured one timezone. See the 'date +| helper' page of the user guide for information regarding date handling. +| +*/ +$config['time_reference'] = 'local'; + +/* +|-------------------------------------------------------------------------- +| Rewrite PHP Short Tags +|-------------------------------------------------------------------------- +| +| If your PHP installation does not have short tag support enabled CI +| can rewrite the tags on-the-fly, enabling you to utilize that syntax +| in your view files. Options are TRUE or FALSE (boolean) +| +| Note: You need to have eval() enabled for this to work. +| +*/ +$config['rewrite_short_tags'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Reverse Proxy IPs +|-------------------------------------------------------------------------- +| +| If your server is behind a reverse proxy, you must whitelist the proxy +| IP addresses from which CodeIgniter should trust headers such as +| HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify +| the visitor's IP address. +| +| You can use both an array or a comma-separated list of proxy addresses, +| as well as specifying whole subnets. Here are a few examples: +| +| Comma-separated: '10.0.1.200,192.168.5.0/24' +| Array: array('10.0.1.200', '192.168.5.0/24') +*/ +$config['proxy_ips'] = ''; + +/* + |-------------------------------------------------------------------------- + | Number of rows + |-------------------------------------------------------------------------- + | + | Sets the number of rows displayed for lists + */ +$config['number_of_rows'] = '30'; + +/* + |-------------------------------------------------------------------------- + | display chart + |-------------------------------------------------------------------------- + | + | Sets if charts are visible + */ +$config['display_chart'] = TRUE; + +/* + |-------------------------------------------------------------------------- + | display names in chart + |-------------------------------------------------------------------------- + | + | Sets if charts names are displayed in charts + */ +$config['chart_anonym'] = TRUE; + +/* + |-------------------------------------------------------------------------- + | cert login + |-------------------------------------------------------------------------- + | + | cert_login = enables certificate login if configured on the web server + | issuer_check = enables check if certificate is issued by a specifc issuer + | issuer_list = list of allowed issuer e.g. array('issuer1', 'issuer2') + | api_verification = enables api check + | api_keyfile = private key file for the api call, just the file name + | api_certfile = public key file for the api call, just the file name + | api_key_password = password private key (can be empty) + | api_cafile = file containing the certificate chain, just the file name + | api_url = url for the api call to gigi + */ +$config['cert_login'] = TRUE; +$config['issuer_check'] = FALSE; +$config['issuer_list'] = array(); +$config['api_verification'] = TRUE; +$config['api_keyfile'] = '/etc/teracara-quiz/client.key'; +$config['api_certfile'] = '/etc/teracara-quiz/client.crt'; +$config['api_key_password'] = ''; +$config['api_cafile'] = '/etc/teracara-quiz/root.crt'; +$config['api_url'] = 'https://api.<%=$systemDomain%>/cats'; + +/* + |-------------------------------------------------------------------------- + | domain name for clock settings + |-------------------------------------------------------------------------- + | + | Sets the domain name use for the clock setting in cookies during quiz + */ +$config['domain'] = 'quiz.<%=$systemDomain%>'; diff --git a/modules/quiz/templates/nginx.epp b/modules/quiz/templates/nginx.epp new file mode 100644 index 0000000..6f69a84 --- /dev/null +++ b/modules/quiz/templates/nginx.epp @@ -0,0 +1,20 @@ +server { + listen 0.0.0.0:443 ssl; + server_name quiz.<%=$systemDomain%>; + + ssl_certificate /etc/ssl/private/quiz.crt; + ssl_certificate_key /etc/ssl/private/quiz.key; + + ssl_client_certificate /etc/ssl/root.crt; + ssl_verify_client on; + ssl_verify_depth 4; + + location / { + proxy_pass http://<%=$ips[quiz]%>; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-Proto https; + proxy_set_header X-Client-Serial "$ssl_client_serial"; + } +} + diff --git a/modules/quiz/templates/sq_config.epp b/modules/quiz/templates/sq_config.epp new file mode 100644 index 0000000..35b0aad --- /dev/null +++ b/modules/quiz/templates/sq_config.epp @@ -0,0 +1,6 @@ +/'; + $sq_hostname='localhost'; + $sq_dbname='quiz'; + $sq_dbusername='quiz'; + $sq_dbpassword='<%=$passwords[quiz-mysql][quiz]%>';