]> WPIA git - infra.git/commitdiff
initial import
authorFelix <felix@dogcraft.de>
Tue, 1 Nov 2016 11:10:57 +0000 (12:10 +0100)
committerFelix Dörre <felix@dogcraft.de>
Thu, 16 Feb 2017 17:59:24 +0000 (18:59 +0100)
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

40 files changed:
.gitignore [new file with mode: 0644]
bootstrap [new file with mode: 0755]
bootstrap-user [new file with mode: 0644]
bootstrap_with_nre [new file with mode: 0755]
commands [new file with mode: 0755]
conf-puppet [new file with mode: 0644]
environments/production/.gitignore [new file with mode: 0644]
environments/production/manifests/gigi.pp [new file with mode: 0644]
environments/production/manifests/hop.pp [new file with mode: 0644]
environments/production/manifests/ip.pp [new file with mode: 0644]
environments/production/manifests/nginx.pp [new file with mode: 0644]
environments/production/manifests/postgres-primary.pp [new file with mode: 0644]
environments/production/manifests/quiz.pp [new file with mode: 0644]
environments/production/manifests/root.pp [new file with mode: 0644]
environments/production/manifests/site.pp [new file with mode: 0644]
modules/.gitignore [new file with mode: 0644]
modules/cassiopeia/.gitignore [new file with mode: 0644]
modules/cassiopeia/mkcassiopeia [new file with mode: 0755]
modules/cassiopeia/mkcassiopeia-openssl.cnf [new file with mode: 0644]
modules/container/manifests/init.pp [new file with mode: 0644]
modules/crl/templates/nginx.epp [new file with mode: 0644]
modules/gigi/files/.gitignore [new file with mode: 0644]
modules/gigi/files/cassiopeia-client.service [new file with mode: 0644]
modules/gigi/files/cassiopeia-signer.service [new file with mode: 0644]
modules/gigi/files/empty [new file with mode: 0644]
modules/gigi/templates/cassiopeia-client-conf.epp [new file with mode: 0644]
modules/gigi/templates/cassiopeia-client.epp [new file with mode: 0644]
modules/gigi/templates/gigi.properties.epp [new file with mode: 0644]
modules/gigi/templates/nginx.epp [new file with mode: 0644]
modules/gigi/templates/tcpserial.epp [new file with mode: 0644]
modules/hop/files/authorized_keys [new file with mode: 0644]
modules/hop/files/join [new file with mode: 0644]
modules/hop/templates/commands.epp [new file with mode: 0755]
modules/lxc/files/dogcraft.list [new file with mode: 0644]
modules/lxc/files/lxcbr0 [new file with mode: 0644]
modules/lxc/manifests/init.pp [new file with mode: 0644]
modules/quiz/files/000-default.conf [new file with mode: 0644]
modules/quiz/templates/config.php.epp [new file with mode: 0644]
modules/quiz/templates/nginx.epp [new file with mode: 0644]
modules/quiz/templates/sq_config.epp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..923abb6
--- /dev/null
@@ -0,0 +1,5 @@
+*~
+\#*\#
+
+#nre
+/nre
diff --git a/bootstrap b/bootstrap
new file mode 100755 (executable)
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 (file)
index 0000000..d25faf1
--- /dev/null
@@ -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 "<div class='alert alert-success'>"; 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 <<EOF
+INSERT INTO user_groups("user","permission","grantedby") VALUES((SELECT "id" FROM "users" WHERE "email"='$adminEmail'),'supporter',(SELECT "id" FROM "users" WHERE "email"='$adminEmail'));
+INSERT INTO user_groups("user","permission","grantedby") VALUES((SELECT "id" FROM "users" WHERE "email"='$adminEmail'),'orgassurer',(SELECT "id" FROM "users" WHERE "email"='$adminEmail'));
+INSERT INTO notary("from","to","points","location","when","date") VALUES((SELECT "id" FROM "users" WHERE "email"='$secondaryEmail'), (SELECT "preferredName" FROM "users" WHERE "email"='$adminEmail'), 100, 'initial', CURRENT_TIMESTAMP, '$(date +%Y-%m-%d)');
+INSERT INTO notary("from","to","points","location","when","date") VALUES((SELECT "id" FROM "users" WHERE "email"='$adminEmail'), (SELECT "preferredName" FROM "users" WHERE "email"='$secondaryEmail'), 100, 'initial', CURRENT_TIMESTAMP, '$(date +%Y-%m-%d)');
+INSERT INTO cats_passed("user_id", "variant_id") VALUES((SELECT "id" FROM "users" WHERE "email"='$adminEmail'),1);
+EOF
+sudo lxc-attach -n gigi -- systemctl stop gigi-proxy.service
+
+csrf=$(mcurl login -c $folder/cookie-jar | csrf)
+open-jar $folder/cookie-jar
+mcurl login -c $folder/cookie-jar --data-urlencode "username=$adminEmail" --data-urlencode "password=$adminPw" --data-urlencode "csrf=$csrf" &>/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 (executable)
index 0000000..57bebeb
--- /dev/null
@@ -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 <<EOF
+DOMAIN=$oldDomain
+EOF
+    read -rp "Years to issue your certificates for: (e.g. 1948 1950): " years
+    ./all root $years
+    cd ..
+    mkdir -p modules/nre/files
+    for i in nre/generated/gigi-*.tar.gz; do tar xvf $i -C modules/nre/files; done
+    mkdir -p modules/cassiopeia_signer/files
+    for i in nre/generated/signer-server-*.tar.gz; do tar xvf $i -C modules/cassiopeia_signer/files; done
+    mkdir -p modules/cassiopeia_client/files
+    for i in nre/generated/signer-client-*.tar.gz; do tar xvf $i -C modules/cassiopeia_client/files; done
+fi
+exec sudo ./bootstrap
diff --git a/commands b/commands
new file mode 100755 (executable)
index 0000000..269100b
--- /dev/null
+++ b/commands
@@ -0,0 +1,96 @@
+#!/bin/bash
+com="$SSH_ORIGINAL_COMMAND"
+if [[ "$UID" == 0 ]]; then
+    echo "Run script as non-root-user"
+    exit
+fi
+if [[ "$com" == "ask quiz certs" ]]; then
+    folder=$(mktemp -d)
+    # In argument 1 is the path of the certificates to update: $1.crt and $1.key
+    function update_cert {
+        name=$1
+        if [[ -f $name.crt ]] && openssl x509 -checkend $((365*24*60*60)) -in $name.crt > /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<len;i++)); do
+                    # read one certificate
+                    openssl x509 -out $folder/web1.crt
+                    cat $folder/web1.crt >> $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 (file)
index 0000000..4f807ca
--- /dev/null
@@ -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 (file)
index 0000000..9788325
--- /dev/null
@@ -0,0 +1 @@
+/modules
diff --git a/environments/production/manifests/gigi.pp b/environments/production/manifests/gigi.pp
new file mode 100644 (file)
index 0000000..00a6c5f
--- /dev/null
@@ -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 (file)
index 0000000..831bfda
--- /dev/null
@@ -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 (file)
index 0000000..3495a10
--- /dev/null
@@ -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 (file)
index 0000000..021c5d4
--- /dev/null
@@ -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 (file)
index 0000000..e90109f
--- /dev/null
@@ -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 (file)
index 0000000..1cae709
--- /dev/null
@@ -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 (file)
index 0000000..d51c17d
--- /dev/null
@@ -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 (file)
index 0000000..ad68ec3
--- /dev/null
@@ -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 (file)
index 0000000..5ce6f7e
--- /dev/null
@@ -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 (file)
index 0000000..52ee3c2
--- /dev/null
@@ -0,0 +1,5 @@
+#generated by mkcassiopeia
+
+/demoCA
+/files
+/.rnd
diff --git a/modules/cassiopeia/mkcassiopeia b/modules/cassiopeia/mkcassiopeia
new file mode 100755 (executable)
index 0000000..5e76f6f
--- /dev/null
@@ -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 (file)
index 0000000..459a7bb
--- /dev/null
@@ -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 (file)
index 0000000..d43e23b
--- /dev/null
@@ -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 (file)
index 0000000..5652d4d
--- /dev/null
@@ -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 (file)
index 0000000..8fee3c0
--- /dev/null
@@ -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 (file)
index 0000000..9e960ec
--- /dev/null
@@ -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 (file)
index 0000000..a567093
--- /dev/null
@@ -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 (file)
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 (file)
index 0000000..6b7a8a5
--- /dev/null
@@ -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 (file)
index 0000000..f867908
--- /dev/null
@@ -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 (file)
index 0000000..59853df
--- /dev/null
@@ -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 (file)
index 0000000..e6c8237
--- /dev/null
@@ -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 (file)
index 0000000..9b5501e
--- /dev/null
@@ -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 (file)
index 0000000..428b5e5
--- /dev/null
@@ -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 (file)
index 0000000..d2e521e
--- /dev/null
@@ -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 (executable)
index 0000000..cb1720f
--- /dev/null
@@ -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 (file)
index 0000000..5a9e6ed
--- /dev/null
@@ -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 (file)
index 0000000..e392d62
--- /dev/null
@@ -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 (file)
index 0000000..b0c64c4
--- /dev/null
@@ -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 (file)
index 0000000..d99c83a
--- /dev/null
@@ -0,0 +1,31 @@
+<VirtualHost *:80>
+       # 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
+</VirtualHost>
+
+# 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 (file)
index 0000000..e404a84
--- /dev/null
@@ -0,0 +1,574 @@
+<?php
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/*
+|--------------------------------------------------------------------------
+| Base Site URL
+|--------------------------------------------------------------------------
+|
+| URL to your CodeIgniter root. Typically this will be your base URL,
+| WITH a trailing slash:
+|
+|      http://example.com/
+|
+| WARNING: You MUST set this value!
+|
+| If it is not set, then CodeIgniter will try guess the protocol and path
+| your installation, but due to security concerns the hostname will be set
+| to $_SERVER['SERVER_ADDR'] if available, or localhost otherwise.
+| The auto-detection mechanism exists only for convenience during
+| development and MUST NOT be used in production!
+|
+| If you need to allow multiple domains, remember that this file is still
+| a PHP script and you can easily do that on your own.
+|
+*/
+$config['base_url'] = '//quiz.<%=$systemDomain%>';
+
+/*
+|--------------------------------------------------------------------------
+| 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('/^[<permitted_uri_chars>]+$/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 (file)
index 0000000..6f69a84
--- /dev/null
@@ -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 (file)
index 0000000..35b0aad
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+                $sq_base_url='//quiz.<%=$systemDomain%>/';
+                $sq_hostname='localhost';
+                $sq_dbname='quiz';
+                $sq_dbusername='quiz';
+                $sq_dbpassword='<%=$passwords[quiz-mysql][quiz]%>';