| #!/bin/bash |
| # |
| # module.sh - gerrit |
| # |
| # Copyright 2019 Luigi Santivetti <luigi.santivetti@gmail.com> |
| |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the "Software"), |
| # to deal in the Software without restriction, including without limitation |
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| # and/or sell copies of the Software, and to permit persons to whom the |
| # Software is furnished to do so, subject to the following conditions: |
| |
| # The above copyright notice and this permission notice (including the next |
| # paragraph) shall be included in all copies or substantial portions of the |
| # Software. |
| |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| # ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| declare -r module="gerrit" |
| source $common_sh |
| |
| module_enable $module |
| |
| declare -r etc_d="$mod_rootfs_d/etc" |
| declare -r logs_d="$mod_rootfs_d/var/log/gerrit" |
| declare -r hooks_d="$mod_rootfs_d/hooks" |
| declare -r hooks_mir="gerrit-hooks.git" |
| |
| declare -r keystore="$host_name.keystore" |
| declare -r keystore_pkcs12="$host_name.pkcs12.keystore" |
| declare -r keystore_f="$etc_d/$keystore_pkcs12" |
| declare -r config_f="$etc_d/gerrit.config" |
| declare -r secure_f="$etc_d/secure.config" |
| declare -r entrypoint="entrypoint.sh" |
| declare -r entrypoint_f="$mod_docker_d/$entrypoint" |
| declare -r dockerfile="Dockerfile" |
| declare -r dockerfile_f="$mod_docker_d/$dockerfile" |
| declare -r gerrit_cli_f="$mod_docker_d/gerrit-cli.sh" |
| |
| declare -r war_version="3.0.0" |
| declare -r war_mirror="https://gerrit-releases.storage.googleapis.com" |
| declare -r revision="1" |
| |
| declare -r rsa_id="${host_name}-con-gerrit.id_rsa" |
| declare -r rsa_id_f="$mod_rootfs_d/etc/$rsa_id" |
| |
| # Gerrit is always configured with a loopback on localhost. If the web server |
| # is configured to only utilise SSL encryption for all the public incoming |
| # and outgoing traffic, unencrypted requests and responses over simple http |
| # made to and from Gerrit (i.e. headers) are never exposed to the outside |
| # world. 'gerrit_has_https' allows to also encrypt looped back traffic that, |
| # as it stands, should be considered redundant. |
| declare -r gerrit_has_https=1 |
| if [ "$gerrit_has_https" -eq 1 ]; then |
| declare -r jar_sslib_mir1="https://gerrit-ci.gerritforge.com/job" |
| declare -r jar_sslib_mir2="plugin-secure-config-bazel-stable-3.0/lastSuccessfulBuild" |
| declare -r jar_sslib_mir3="artifact/bazel-bin/plugins/secure-config" |
| declare -r jar_sslib="secure-config" |
| declare -r jar_sslib_f="${mod_rootfs_d}/lib/${jar_sslib}.jar" |
| fi |
| |
| # Staged resources |
| declare -r war_f="$mod_staging_d/gerrit-$war_version.war" |
| |
| declare -ar mod_more_dirs=( $etc_d $logs_d $hooks_d ) |
| declare -ar mod_more_files=( $config_f $secure_f $entrypoint_f $dockerfile_f $gerrit_cli_f ) |
| declare -ar mod_more_trefs=( config_t secure_t entrypoint_bang_t dockerfile_t gerrit_cli_bang_t ) |
| |
| function tod_watch |
| { |
| __watch_module_common || return $s_err |
| } |
| |
| function tod_doins |
| { |
| __fetch_module_common || return $s_err |
| __gerrit_do_sitepath || return $s_err |
| |
| # Update $config_f after init is done |
| __doins_module_common || return $s_err |
| __gerrit_do_lock || return $s_err |
| } |
| |
| function tod_fetch |
| { |
| __fetch_module_common || return $s_err |
| } |
| |
| function tod_upins |
| { |
| __gerrit_do_unlock || return $s_err |
| __upins_module_common || return $s_err |
| __gerrit_do_lock || return $s_err |
| } |
| |
| function tod_clmod |
| { |
| __clmod_module_common || return $s_err |
| } |
| |
| function tod_clins |
| { |
| __clins_module_common || return $s_err |
| } |
| |
| function tod_doall |
| { |
| tod_doins || return $s_err |
| tod_upmod || return $s_err |
| } |
| |
| function tod_upall |
| { |
| tod_upins || return $s_err |
| tod_upmod || return $s_err |
| } |
| |
| function tod_upmod |
| { |
| __fetch_module_common || return $s_err |
| __gerrit_do_keystore || return $s_err |
| __gerrit_do_hooks || return $s_err |
| __gerrit_do_ssh_rsa_id || return $s_err |
| } |
| |
| function __gerrit_do_lock |
| { |
| set_mode "0644" "root" $config_f |
| set_mode "0644" "root" $secure_f |
| } |
| |
| function __gerrit_do_unlock |
| { |
| set_mode "0666" "1000" $config_f |
| set_mode "0666" "1000" $secure_f |
| } |
| |
| function __gerrit_do_sitepath |
| { |
| [ -f "$war_f" ] || { |
| lets -l -e "missing $(basename $war_f), is it in the MANIFEST?" |
| return $s_err |
| } |
| |
| # Make a bare skeleton of the essential rootfs tree |
| java -jar "$war_f" init --batch --skip-plugins --delete-caches --no-auto-start \ |
| --site-path "$mod_rootfs_d" 2>&1 | lets -l -x "java" |
| [ ${PIPESTATUS[0]} -eq 0 ] || { |
| lets -l -e "failed to init gerrit SITE_PATH" |
| return $s_err |
| } |
| |
| sleep 1 |
| |
| # Remove runtime files and directories |
| rm -f $mod_rootfs_d/etc/{ssh,secure}* |
| rm -Rf $mod_rootfs_d/{static,index,logs,data,index,cache,git,db,tmp}/* |
| |
| # Make sure gerrit.config is present before any real init is ever attempted |
| [ -f "$config_f" ] |
| } |
| |
| function __gerrit_do_sslib |
| { |
| # In order to use encrypted password, sslib needs to be available in /lib |
| cp $mod_staging_d/$jar_sslib.jar $jar_sslib_f |
| chmod 0664 $jar_sslib_f |
| |
| local gerrit_war |
| if [ -f "$mod_rootfs_d/bin/gerrit.war" ]; then |
| gerrit_war="$mod_rootfs_d/bin/gerrit.war" |
| elif [ -f "$mod_staging_d/gerrit-$war_version.war" ]; then |
| gerrit_war="$mod_staging_d/gerrit-$war_version.war" |
| else |
| lets -l -e "gerrit.war not found" |
| return $s_err |
| fi |
| |
| if [ -z "$PASSWD_F" ] || [ ! -f "$PASSWD_F" ]; then |
| lets -l -e "keystore needs PASSWD_F" |
| return $s_err |
| fi |
| |
| source $PASSWD_F |
| |
| [ -n "${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_}" ] || { |
| lets -l -e "_PASSWD_GERRIT_KEYSTORE_KEY_PASS_ not defined" |
| return $s_err |
| } |
| |
| __gerrit_do_unlock || return $s_err |
| java -jar $gerrit_war passwd -d "$mod_rootfs_d" \ |
| httpd.sslKeyPassword "${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_}" | lets -l -x "sslib" |
| java -jar $gerrit_war passwd -d "$mod_rootfs_d" \ |
| auth.registerEmailPrivateKey "${_PASSWD_GERRIT_EMAIL_PRIV_KEY_}" | lets -l -x "sslib" |
| |
| [ ${PIPESTATUS[0]} -eq 0 ] || return $s_err |
| __gerrit_do_lock |
| } |
| |
| function __gerrit_do_keystore |
| { |
| if [ "$gerrit_has_https" -ne 1 ]; then |
| lets -l -i "secure config not enabled" |
| return $s_ok |
| fi |
| |
| if [ ! -f "$mod_staging_d/$keystore" ] || \ |
| [ ! -f "$mod_staging_d/$keystore_pkcs12" ]; then |
| [ -n "$PASSWD_F" ] && [ -f "$PASSWD_F" ] || { |
| lets -l -e "keystore needs PASSWD_F" |
| return $s_err |
| } |
| |
| rm -f $mod_staging_d/$keystore |
| rm -f $mod_staging_d/$keystore_pkcs12 |
| |
| source $PASSWD_F |
| |
| # This isn't run as part of templates creation, make sure variables are |
| # defined |
| [ -n "${_PASSWD_GERRIT_KEYSTORE_STORE_PASS_}" ] && \ |
| [ -n "${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_}" ] || { |
| lets -l -e "keystore needs passwords" |
| return $s_err |
| } |
| |
| keytool -keystore $mod_staging_d/$keystore -v \ |
| -alias $module -genkey -keyalg RSA \ |
| -dname "cn=$host_name, ou=$host_name, o=$host_name, c=$host_name" \ |
| -storepass ${_PASSWD_GERRIT_KEYSTORE_STORE_PASS_} \ |
| -keypass ${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_} 2>&1 | \ |
| lets -l -x "keytool" |
| [ ${PIPESTATUS[0]} -eq 0 ] || { |
| lets -l -e "failed to create keystore: $mod_staging_d/$keystore" |
| return $s_err |
| } |
| |
| lets -l -i "converting to keystore to PKCS12 format ..." |
| |
| # Warning: Different store and key passwords not supported for PKCS12 KeyStores. |
| # So just use the same for both |
| keytool -importkeystore -deststoretype pkcs12 -noprompt -v \ |
| -deststorepass ${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_} \ |
| -destkeypass ${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_} \ |
| -destkeystore $mod_staging_d/$keystore_pkcs12 \ |
| -srcstorepass ${_PASSWD_GERRIT_KEYSTORE_STORE_PASS_} \ |
| -srckeypass ${_PASSWD_GERRIT_KEYSTORE_KEY_PASS_} \ |
| -srckeystore $mod_staging_d/$keystore -alias $module 2>&1 | \ |
| lets -l -x "keytool" |
| [ "${PIPESTATUS[0]}" -eq 0 ] || { |
| lets -l -e "failed to convert PKCS12 keystore: $mod_staging_d/$keystore" |
| return $s_err |
| } |
| |
| # Last bit, if we got this far, then we want to store the key password |
| # and gerrit requires it at start up. Do this using gerrit sslib |
| __gerrit_do_sslib || return $s_err |
| fi |
| |
| sudo cp $mod_staging_d/$keystore_pkcs12 $keystore_f || return $s_err |
| sudo chmod 0600 $keystore_f && sudo chown root:root $keystore_f |
| } |
| |
| function __gerrit_do_hooks |
| { |
| if [ ! -d "$mod_staging_d/$hooks_mir" ]; then |
| lets -l -w "$hooks_mir not found, not installing hooks" |
| return $s_ok |
| fi |
| |
| sudo cp -ar --preserve=all $mod_staging_d/$hooks_mir/* $hooks_d/ || { |
| lets -l -e "failed to install hooks" |
| return $s_err |
| } |
| } |
| |
| function __gerrit_do_ssh_rsa_id |
| { |
| if [ -f "$mod_staging_d/$rsa_id" ] && [ -f "$mod_staging_d/$rsa_id.pub" ]; then |
| lets -l -w "$rsa_id already exists" |
| else |
| sudo rm -f ${mod_staging_d}/${rsa_id} |
| sudo rm -f ${mod_staging_d}/${rsa_id}.pub |
| |
| ssh-keygen -b 2048 -t rsa -f $mod_staging_d/$rsa_id -C "con@drkc" -N "" 2>&1 | \ |
| lets -l -x "keygen" |
| if [ "${PIPESTATUS[0]}" -ne 0 ]; then |
| lets -l -e "failed to create new rsa_id" |
| return $s_err |
| fi |
| fi |
| |
| diff ${rsa_id_f}.pub $mod_staging_d/${rsa_id}.pub 2>&1 | lets -l -x "diff" |
| if [ "${PIPESTATUS[0]}" -ne 0 ]; then |
| sudo cp -a --preserve=all ${mod_staging_d}/${rsa_id} ${rsa_id_f} || { |
| lets -l -e "failed to copy new rsa_id" |
| return $s_err |
| } |
| sudo cp -a --preserve=all ${mod_staging_d}/${rsa_id}.pub ${rsa_id_f}.pub || { |
| lets -l -e "failed to copy new rsa_id.pub" |
| sudo rm -f ${rsa_id_f} |
| return $s_err |
| } |
| else |
| lets -l -i "no need to copy new rsa_id.pub" |
| fi |
| } |