diff --git a/.vscode/settings.json b/.vscode/settings.json index 1b31698..9a5337b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,9 @@ "/unittests/**/*.yaml" ] }, - "yaml.schemaStore.enable": true + "yaml.schemaStore.enable": true, + "[shellscript]": { + "files.eol": "\n", + "editor.tabSize": 2 + } } diff --git a/scripts/token.sh b/scripts/act_runner/token.sh similarity index 100% rename from scripts/token.sh rename to scripts/act_runner/token.sh diff --git a/scripts/init-containers/config/config_environment.sh b/scripts/init-containers/config/config_environment.sh new file mode 100644 index 0000000..fc6a7a6 --- /dev/null +++ b/scripts/init-containers/config/config_environment.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +set -euo pipefail + +function env2ini::log() { + printf "${1}\n" +} + +function env2ini::read_config_to_env() { + local section="${1}" + local line="${2}" + + if [[ -z "${line}" ]]; then + # skip empty line + return + fi + + # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line + local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" + + if [[ -z "${setting}" ]]; then + env2ini::log ' ! invalid setting' + exit 1 + fi + + local value='' + local regex="^${setting}(\s*)=(\s*)(.*)" + if [[ $line =~ $regex ]]; then + value="${BASH_REMATCH[3]}" + else + env2ini::log ' ! invalid setting' + exit 1 + fi + + env2ini::log " + '${setting}'" + + if [[ -z "${section}" ]]; then + export "GITEA____${setting^^}=${value}" # '^^' makes the variable content uppercase + return + fi + + local masked_section="${section//./_0X2E_}" # '//' instructs to replace all matches + masked_section="${masked_section//-/_0X2D_}" + + export "GITEA__${masked_section^^}__${setting^^}=${value}" # '^^' makes the variable content uppercase +} + +function env2ini::reload_preset_envs() { + env2ini::log "Reloading preset envs..." + + while read -r line; do + if [[ -z "${line}" ]]; then + # skip empty line + return + fi + + # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line + local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" + + if [[ -z "${setting}" ]]; then + env2ini::log ' ! invalid setting' + exit 1 + fi + + local value='' + local regex="^${setting}(\s*)=(\s*)(.*)" + if [[ $line =~ $regex ]]; then + value="${BASH_REMATCH[3]}" + else + env2ini::log ' ! invalid setting' + exit 1 + fi + + env2ini::log " + '${setting}'" + + export "${setting^^}=${value}" # '^^' makes the variable content uppercase + done < "/tmp/existing-envs" + + rm /tmp/existing-envs +} + + +function env2ini::process_config_file() { + local config_file="${1}" + local section="$(basename "${config_file}")" + + if [[ $section == '_generals_' ]]; then + env2ini::log " [ini root]" + section='' + else + env2ini::log " ${section}" + fi + + while read -r line; do + env2ini::read_config_to_env "${section}" "${line}" + done < <(awk 1 "${config_file}") # Helm .toYaml trims the trailing new line which breaks line processing; awk 1 ... adds it back while reading +} + +function env2ini::load_config_sources() { + local path="${1}" + + if [[ -d "${path}" ]]; then + env2ini::log "Processing $(basename "${path}")..." + + while read -d '' configFile; do + env2ini::process_config_file "${configFile}" + done < <(find "${path}" -type l -not -name '..data' -print0) + + env2ini::log "\n" + fi +} + +function env2ini::generate_initial_secrets() { + # These environment variables will either be + # - overwritten with user defined values, + # - initially used to set up Gitea + # Anyway, they won't harm existing app.ini files + + export GITEA__SECURITY__INTERNAL_TOKEN=$(gitea generate secret INTERNAL_TOKEN) + export GITEA__SECURITY__SECRET_KEY=$(gitea generate secret SECRET_KEY) + export GITEA__OAUTH2__JWT_SECRET=$(gitea generate secret JWT_SECRET) + export GITEA__SERVER__LFS_JWT_SECRET=$(gitea generate secret LFS_JWT_SECRET) + + env2ini::log "...Initial secrets generated\n" +} + +# save existing envs prior to script execution. Necessary to keep order of preexisting and custom envs +env | (grep -e '^GITEA__' || [[ $? == 1 ]]) > /tmp/existing-envs + +# MUST BE CALLED BEFORE OTHER CONFIGURATION +env2ini::generate_initial_secrets + +env2ini::load_config_sources '/env-to-ini-mounts/inlines/' +env2ini::load_config_sources '/env-to-ini-mounts/additionals/' + +# load existing envs to override auto generated envs +env2ini::reload_preset_envs + +env2ini::log "=== All configuration sources loaded ===\n" + +# safety to prevent rewrite of secret keys if an app.ini already exists +if [ -f ${GITEA_APP_INI} ]; then + env2ini::log 'An app.ini file already exists. To prevent overwriting secret keys, these settings are dropped and remain unchanged:' + env2ini::log ' - security.INTERNAL_TOKEN' + env2ini::log ' - security.SECRET_KEY' + env2ini::log ' - oauth2.JWT_SECRET' + env2ini::log ' - server.LFS_JWT_SECRET' + + unset GITEA__SECURITY__INTERNAL_TOKEN + unset GITEA__SECURITY__SECRET_KEY + unset GITEA__OAUTH2__JWT_SECRET + unset GITEA__SERVER__LFS_JWT_SECRET +fi + +environment-to-ini -o $GITEA_APP_INI diff --git a/scripts/init-containers/init/configure_gpg_environment.sh b/scripts/init-containers/init/configure_gpg_environment.sh new file mode 100644 index 0000000..686a318 --- /dev/null +++ b/scripts/init-containers/init/configure_gpg_environment.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu + +gpg --batch --import /raw/private.asc diff --git a/templates/gitea/act_runner/config-scripts.yaml b/templates/gitea/act_runner/config-scripts.yaml index 31b926e..5c47763 100644 --- a/templates/gitea/act_runner/config-scripts.yaml +++ b/templates/gitea/act_runner/config-scripts.yaml @@ -9,6 +9,6 @@ metadata: labels: {{- include "gitea.labels" . | nindent 4 }} data: -{{ (.Files.Glob "scripts/*.sh").AsConfig | indent 2 }} +{{ (.Files.Glob "scripts/act_runner/*.sh").AsConfig | indent 2 }} {{- end }} {{- end }} diff --git a/templates/gitea/config.yaml b/templates/gitea/config.yaml index 897c8c9..1ef5b61 100644 --- a/templates/gitea/config.yaml +++ b/templates/gitea/config.yaml @@ -18,6 +18,7 @@ metadata: {{- include "gitea.labels" . | nindent 4 }} type: Opaque stringData: +{{ (.Files.Glob "scripts/init-containers/config/*.sh").AsConfig | indent 2 }} assertions: | {{- /*assert that only one PG dep is enabled */ -}} @@ -54,158 +55,3 @@ stringData: {{- end }} {{- end }} - config_environment.sh: |- - #!/usr/bin/env bash - set -euo pipefail - - function env2ini::log() { - printf "${1}\n" - } - - function env2ini::read_config_to_env() { - local section="${1}" - local line="${2}" - - if [[ -z "${line}" ]]; then - # skip empty line - return - fi - - # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line - local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" - - if [[ -z "${setting}" ]]; then - env2ini::log ' ! invalid setting' - exit 1 - fi - - local value='' - local regex="^${setting}(\s*)=(\s*)(.*)" - if [[ $line =~ $regex ]]; then - value="${BASH_REMATCH[3]}" - else - env2ini::log ' ! invalid setting' - exit 1 - fi - - env2ini::log " + '${setting}'" - - if [[ -z "${section}" ]]; then - export "GITEA____${setting^^}=${value}" # '^^' makes the variable content uppercase - return - fi - - local masked_section="${section//./_0X2E_}" # '//' instructs to replace all matches - masked_section="${masked_section//-/_0X2D_}" - - export "GITEA__${masked_section^^}__${setting^^}=${value}" # '^^' makes the variable content uppercase - } - - function env2ini::reload_preset_envs() { - env2ini::log "Reloading preset envs..." - - while read -r line; do - if [[ -z "${line}" ]]; then - # skip empty line - return - fi - - # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line - local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" - - if [[ -z "${setting}" ]]; then - env2ini::log ' ! invalid setting' - exit 1 - fi - - local value='' - local regex="^${setting}(\s*)=(\s*)(.*)" - if [[ $line =~ $regex ]]; then - value="${BASH_REMATCH[3]}" - else - env2ini::log ' ! invalid setting' - exit 1 - fi - - env2ini::log " + '${setting}'" - - export "${setting^^}=${value}" # '^^' makes the variable content uppercase - done < "/tmp/existing-envs" - - rm /tmp/existing-envs - } - - - function env2ini::process_config_file() { - local config_file="${1}" - local section="$(basename "${config_file}")" - - if [[ $section == '_generals_' ]]; then - env2ini::log " [ini root]" - section='' - else - env2ini::log " ${section}" - fi - - while read -r line; do - env2ini::read_config_to_env "${section}" "${line}" - done < <(awk 1 "${config_file}") # Helm .toYaml trims the trailing new line which breaks line processing; awk 1 ... adds it back while reading - } - - function env2ini::load_config_sources() { - local path="${1}" - - if [[ -d "${path}" ]]; then - env2ini::log "Processing $(basename "${path}")..." - - while read -d '' configFile; do - env2ini::process_config_file "${configFile}" - done < <(find "${path}" -type l -not -name '..data' -print0) - - env2ini::log "\n" - fi - } - - function env2ini::generate_initial_secrets() { - # These environment variables will either be - # - overwritten with user defined values, - # - initially used to set up Gitea - # Anyway, they won't harm existing app.ini files - - export GITEA__SECURITY__INTERNAL_TOKEN=$(gitea generate secret INTERNAL_TOKEN) - export GITEA__SECURITY__SECRET_KEY=$(gitea generate secret SECRET_KEY) - export GITEA__OAUTH2__JWT_SECRET=$(gitea generate secret JWT_SECRET) - export GITEA__SERVER__LFS_JWT_SECRET=$(gitea generate secret LFS_JWT_SECRET) - - env2ini::log "...Initial secrets generated\n" - } - - # save existing envs prior to script execution. Necessary to keep order of preexisting and custom envs - env | (grep -e '^GITEA__' || [[ $? == 1 ]]) > /tmp/existing-envs - - # MUST BE CALLED BEFORE OTHER CONFIGURATION - env2ini::generate_initial_secrets - - env2ini::load_config_sources '/env-to-ini-mounts/inlines/' - env2ini::load_config_sources '/env-to-ini-mounts/additionals/' - - # load existing envs to override auto generated envs - env2ini::reload_preset_envs - - env2ini::log "=== All configuration sources loaded ===\n" - - # safety to prevent rewrite of secret keys if an app.ini already exists - if [ -f ${GITEA_APP_INI} ]; then - env2ini::log 'An app.ini file already exists. To prevent overwriting secret keys, these settings are dropped and remain unchanged:' - env2ini::log ' - security.INTERNAL_TOKEN' - env2ini::log ' - security.SECRET_KEY' - env2ini::log ' - oauth2.JWT_SECRET' - env2ini::log ' - server.LFS_JWT_SECRET' - - unset GITEA__SECURITY__INTERNAL_TOKEN - unset GITEA__SECURITY__SECRET_KEY - unset GITEA__OAUTH2__JWT_SECRET - unset GITEA__SERVER__LFS_JWT_SECRET - fi - - environment-to-ini -o $GITEA_APP_INI diff --git a/templates/gitea/init.yaml b/templates/gitea/init.yaml index 5adc9a3..8470a55 100644 --- a/templates/gitea/init.yaml +++ b/templates/gitea/init.yaml @@ -7,11 +7,7 @@ metadata: {{- include "gitea.labels" . | nindent 4 }} type: Opaque stringData: - configure_gpg_environment.sh: |- - #!/usr/bin/env bash - set -eu - - gpg --batch --import /raw/private.asc +{{ (.Files.Glob "scripts/init-containers/init/*.sh").AsConfig | indent 2 }} init_directory_structure.sh: |- #!/usr/bin/env bash diff --git a/unittests/helm/init/init_directory_structure.sh-rootless.yaml b/unittests/helm/init/init_directory_structure.sh-rootless.yaml index e41ca4d..63a244e 100644 --- a/unittests/helm/init/init_directory_structure.sh-rootless.yaml +++ b/unittests/helm/init/init_directory_structure.sh-rootless.yaml @@ -15,7 +15,7 @@ tests: asserts: - equal: path: stringData["configure_gpg_environment.sh"] - value: |- + value: | #!/usr/bin/env bash set -eu diff --git a/unittests/helm/init/init_directory_structure.sh.yaml b/unittests/helm/init/init_directory_structure.sh.yaml index 7327265..56b7402 100644 --- a/unittests/helm/init/init_directory_structure.sh.yaml +++ b/unittests/helm/init/init_directory_structure.sh.yaml @@ -16,7 +16,7 @@ tests: asserts: - equal: path: stringData["configure_gpg_environment.sh"] - value: |- + value: | #!/usr/bin/env bash set -eu