Revised and CIS introduced

This commit is contained in:
m8in
2025-02-15 18:33:27 +01:00
parent 3ea1ac0915
commit a0a9501c31
12 changed files with 318 additions and 120 deletions

10
.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
# Ignore the file '/domainOfHostOwner' because this is per host individually.
/domainOfHostOwner
# Ignore the subfolders only, because their content are other git repositories.
# But 'definitions and 'states' should be prepared by cloning this repository.
/definitions/*/
/states/*/
# Ignore environment files
.env

View File

@@ -1,5 +1,5 @@
Infrastructure System (ISS)
===========================
Core Infrastructure System (CIS)
================================
Setup a new host
----------------
@@ -52,20 +52,20 @@ We use the modern ed25519 keys, so the public key of root is stored at this loca
### Register public host key
This is an example for `example.net` as domain of the host owner.
1. Repository `iss`, allow __readonly__ access only.
2. Repository `iss-definition-example.net`, allow __readonly__ access only.
3. Repository `iss-state-example.net`, allow __writable__ access.
1. Repository `cis`, allow __readonly__ access only.
2. Repository `cis-definition-example.net`, allow __readonly__ access only.
3. Repository `cis-state-example.net`, allow __writable__ access.
### Clone the Infrastructure System (iss) repository
### Clone the Infrastructure System (cis) repository
After you registered the printed root's public key of this host you can clone the repository and execute the setup script:
```sh
# Note the tailing '/iss', because we want to clone the repository to that folder
git clone ssh://git@git.example.dev:22448/iss.git /iss
# Note the tailing '/cis', because we want to clone the repository to that folder
git clone ssh://git@git.example.dev:22448/cis.git /cis
# Execute the setup script
/iss/setupCoreOntoThisHost.sh
/cis/setupCoreOntoThisHost.sh
```
<br>
@@ -74,7 +74,7 @@ git clone ssh://git@git.example.dev:22448/iss.git /iss
How it works
------------
We add a webhook to each gitea repository that belongs to ISS:
We add a webhook to each gitea repository that belongs to CIS:
- __Taget URL:__ https://YOUR.JENKINS.DOMAIN/generic-webhook-trigger/invoke?token=YOUR_TOKEN
- __HTTP-Method:__ POST
- __Trigger On:__ Push Events
@@ -98,7 +98,7 @@ cat "${JENKINS_HOME}/.ssh/id_ed25519.pub" \
&& cat "${JENKINS_HOME}/.ssh/id_ed25519.pub")
# add your host here, note the tailing '&' to run it in parallel
ssh -o StrictHostKeyChecking=no jenkins@192.168.X.Y /iss/update_repositories.sh ( --scripts | --definitions | --states ) &
ssh -o StrictHostKeyChecking=no jenkins@192.168.X.Y /cis/update_repositories.sh ( --scripts | --definitions | --states ) &
#wait for all background processes to complete
wait

View File

@@ -73,7 +73,7 @@ function cloneOrPull {
function addAndCheckGitRepository() {
local _FOLDER _REPOSITORY
_FOLDER="${1:?"Missing first parameter FOLDER"}"
_REPOSITORY="${2:?"Missing second parameter REPOSITORY: e.g. ssh://git@your.domain.com/iss.git "}"
_REPOSITORY="${2:?"Missing second parameter REPOSITORY: e.g. ssh://git@your.domain.com/cis.git "}"
_RIGHTS="${3:?"Missing third parameter RIGHTS: (readonly, writable) "}"
readonly _FOLDER _REPOSITORY
@@ -98,4 +98,6 @@ addAndCheckGitRepository \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
"$(echo ${2} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
"$(echo ${3} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
&& exit 0
exit 1

View File

@@ -34,6 +34,7 @@ function addNormalUser() {
}
# sanitizes all parameters
addNormalUser \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
addNormalUser "$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0
exit 1

View File

@@ -8,11 +8,11 @@
# Note that an unprivileged user can use this script successfully,
# if no user has to be added to the host because it already exists.
function addToCrontabEveryHour() {
local _ROOT _MINUTE_VALUE _STRING
_ROOT="${0%%/core/*}/" #Removes longest matching pattern '/core/*' from the end
local _CIS_ROOT _MINUTE_VALUE _STRING
_CIS_ROOT="${0%%/core/*}/" #Removes longest matching pattern '/core/*' from the end
! [ -z "${2##*[!0-9]*}" ] && _MINUTE_VALUE=$((${2}%60)) # if second parameter is integer then (minute-value % 60) as safe guard
_STRING="${_MINUTE_VALUE:?"Missing MINUTE_VALUE"} * * * * ${1:?"Missing first parameter COMMAND"} > /dev/null 2>&1"
readonly _ROOT _MINUTE_VALUE _STRING
readonly _CIS_ROOT _MINUTE_VALUE _STRING
[ "$(id -u)" == "0" ] \
&& crontab -l | grep -qF "${_STRING:?"Missing CRON_STRING"}" \
@@ -21,11 +21,11 @@ function addToCrontabEveryHour() {
&& return 0
[ "$(id -u)" == "0" ] \
&& echo "${_ROOT:?"Missing ROOT"}" | grep "home" &> /dev/null \
&& echo "${_CIS_ROOT:?"Missing CIS_ROOT"}" | grep "home" &> /dev/null \
&& echo "SUCCESS: Although the entry will be skipped: ("$(readlink -f ${0})")" \
&& echo " - '${_STRING}'" \
&& echo " that is because the current environment is:" \
&& echo " - ${_ROOT}" \
&& echo " - ${_CIS_ROOT}" \
&& return 0
[ "$(id -u)" == "0" ] \
@@ -47,4 +47,6 @@ function addToCrontabEveryHour() {
addToCrontabEveryHour \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
"$(echo ${2} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
&& exit 0
exit 1

View File

@@ -51,17 +51,17 @@ function prepareFolder() {
}
function defineAuthorizedKeysOfUser() {
local _ROOT _CORE_SCRIPTS _DOMAIN _DEFINITIONS _USER
local _CIS_ROOT _CORE_SCRIPTS _DOMAIN _DEFINITIONS _USER
_DEFINITIONS="$(realpath -s "${1:?"Missing first parameter DEFINITIONS: 'ROOT/definitions/DOMAIN'"}")"
_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_CIS_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_DOMAIN="${_DEFINITIONS##*/definitions/}" #Removes longest matching pattern '*/definitions/' from the begin
_DOMAIN="${_DOMAIN%/}" #Removes shortest matching pattern '/' from the end
#Build from components for safety
_DEFINITIONS="${_ROOT:?"Missing ROOT"}definitions/${_DOMAIN:?"Missing DOMAIN"}"
_DEFINITIONS="${_CIS_ROOT:?"Missing ROOT"}definitions/${_DOMAIN:?"Missing DOMAIN"}"
_USER="${2:?"Missing second parameter USER"}"
_CORE_SCRIPTS="${_ROOT:?"Missing ROOT"}core/"
readonly _ROOT _CORE_SCRIPTS _DOMAIN _DEFINITIONS _USER
_CORE_SCRIPTS="${_CIS_ROOT:?"Missing ROOT"}core/"
readonly _CIS_ROOT _CORE_SCRIPTS _DOMAIN _DEFINITIONS _USER
case "${_USER:?"Missing USER"}" in
root)
@@ -83,4 +83,6 @@ function defineAuthorizedKeysOfUser() {
defineAuthorizedKeysOfUser \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
"$(echo ${2} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
&& exit 0
exit 1

View File

@@ -24,6 +24,28 @@ function isCoreDefinition() {
return 1
}
function filterInvalidAuthorizedKeysFilesOfRoot() {
local _FILE_DEFINED
_FILE_DEFINED="${1:?"Missing DEFINITION FILE"}"
readonly _FILE_DEFINED
#If the full filename contains 'root/.ssh/authorized_keys' then check the content.
#Skip lines starting with '#' and if at least one remaining line contains 'ssh' and '@' then print the filename.
echo "${_FILE_DEFINED}" | grep -F 'root/.ssh/authorized_keys' &> /dev/null \
&& grep -vE '^[[:blank:]]*#' "${_FILE_DEFINED}" | grep -F 'ssh' | grep -F '@' &> /dev/null \
&& echo "${_FILE_DEFINED}" \
&& return 0
#If the full filename contains 'root/.ssh/authorized_keys' print nothing because the file has to be invalid.
echo "${_FILE_DEFINED}" | grep -F 'root/.ssh/authorized_keys' &> /dev/null \
&& echo \
&& return 0
#Print the full filename because it does not contain 'root/.ssh/authorized_keys'
echo "${_FILE_DEFINED}"
return 0
}
function printSelectedDefinition() {
local _CORE_FILE_DEFINED_ALL_HOSTS _CORE_FILE_DEFINED_THIS_HOST _FILE_DEFINED_ALL_HOSTS _FILE_DEFINED_THIS_HOST
_CORE_FILE_DEFINED_ALL_HOSTS="${1:?"Missing DEFINITIONS"}/core/all${2:?"Missing CURRENT_FULLFILE"}"
@@ -36,13 +58,13 @@ function printSelectedDefinition() {
#Try this host first because it should be priorized.
isCoreDefinition "${2:?"Missing CURRENT_FULLFILE"}" \
&& [ -s "${_CORE_FILE_DEFINED_THIS_HOST}" ] \
&& echo "${_CORE_FILE_DEFINED_THIS_HOST}" \
&& filterInvalidAuthorizedKeysFiles "${_CORE_FILE_DEFINED_THIS_HOST}" \
&& return 0
#The following are special definitions that affect the core functionality.
isCoreDefinition "${2:?"Missing CURRENT_FULLFILE"}" \
&& [ -s "${_CORE_FILE_DEFINED_ALL_HOSTS}" ] \
&& echo "${_CORE_FILE_DEFINED_ALL_HOSTS}" \
&& filterInvalidAuthorizedKeysFiles "${_CORE_FILE_DEFINED_ALL_HOSTS}" \
&& return 0
#Try this host first because it should be priorized.
@@ -71,11 +93,6 @@ function createSymlinkToDefinition() {
&& [ "$(sha256sum "${_DEFINED_FULLFILE}" | cut -d' ' -f1)" == "$(sha256sum "${_CURRENT_FULLFILE}" | cut -d' ' -f1)" ] \
&& echo "The content of the current file already matches the definition, but it will be replaced by a symlink..."
[ -f "${_CURRENT_FULLFILE}" ] \
&& [ "$(sha256sum "${_DEFINED_FULLFILE}" | cut -d' ' -f1)" == "$(sha256sum "${_CURRENT_FULLFILE}" | cut -d' ' -f1)" ] \
&& echo "The content of the current file already matches the definition, but it will be replaced by a symlink..."
[ -f "${_CURRENT_FULLFILE}" ] \
&& mv "${_CURRENT_FULLFILE:?"Missing CURRENT_FULLFILE"}" "${_SAVED_FULLFILE:?"Missing SAVED_FULLFILE"}" \
&& echo "Current file has been backed up to: '${_SAVED_FULLFILE}'"
@@ -92,13 +109,13 @@ function createSymlinkToDefinition() {
}
function ensureUsageOfDefinitions() {
local _ROOT _CURRENT_FILE _CURRENT_FOLDER _CURRENT_FULLFILE _DEFINITIONS _DOMAIN _DEFINED_FULLFILE _NOW _SAVED_FULLFILE
local _CIS_ROOT _CURRENT_FILE _CURRENT_FOLDER _CURRENT_FULLFILE _DEFINITIONS _DOMAIN _DEFINED_FULLFILE _NOW _SAVED_FULLFILE
_DEFINITIONS="$(realpath -s "${1:?"Missing first parameter DEFINITIONS: 'ROOT/definitions/DOMAIN'"}")"
_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_CIS_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_DOMAIN="${_DEFINITIONS##*/definitions/}" #Removes longest matching pattern '*/definitions/' from the begin
_DOMAIN="${_DOMAIN%/}" #Removes shortest matching pattern '/' from the end
#Build from components for safety
_DEFINITIONS="$(printIfEqual "${_DEFINITIONS}" "${_ROOT:?"Missing ROOT"}definitions/${_DOMAIN:?"Missing DOMAIN"}")"
_DEFINITIONS="$(printIfEqual "${_DEFINITIONS}" "${_CIS_ROOT:?"Missing ROOT"}definitions/${_DOMAIN:?"Missing DOMAIN"}")"
_CURRENT_FOLDER="$(dirname "${2:?"Missing second parameter CURRENT_FULLFILE"}")"
@@ -121,7 +138,13 @@ function ensureUsageOfDefinitions() {
_DEFINED_FULLFILE="$(printSelectedDefinition "${_DEFINITIONS}" "${_CURRENT_FULLFILE}")"
_NOW="$(date +%Y%m%d_%H%M)"
_SAVED_FULLFILE="${_CURRENT_FULLFILE}-backup@${_NOW:?"Missing NOW"}"
readonly _ROOT _CURRENT_FILE _CURRENT_FOLDER _CURRENT_FULLFILE _DEFINITIONS _DOMAIN _DEFINED_FULLFILE _NOW _SAVED_FULLFILE
readonly _CIS_ROOT _CURRENT_FILE _CURRENT_FOLDER _CURRENT_FULLFILE _DEFINITIONS _DOMAIN _DEFINED_FULLFILE _NOW _SAVED_FULLFILE
[ -z "${_DEFINED_FULLFILE}" ] \
&& echo \
&& echo "URGENT WARNING: If an 'authorized_keys' file of root is replaced by an invalid version," \
&& echo " you may lose access to this host!" \
&& echo
! [ -f "${_DEFINED_FULLFILE}" ] \
&& echo "FAIL: No definition available for this file: ("$(readlink -f ${0})")" \
@@ -138,11 +161,11 @@ function ensureUsageOfDefinitions() {
&& echo " - '${_DEFINED_FULLFILE}'" \
&& return 0
echo "${_ROOT:?"Missing ROOT"}" | grep "home" &> /dev/null \
echo "${_CIS_ROOT:?"Missing CIS_ROOT"}" | grep "home" &> /dev/null \
&& echo "SUCCESS: Although this definition will be skipped: ("$(readlink -f ${0})")" \
&& echo " - '${_DEFINED_FULLFILE}'" \
&& echo " that is because the current environment is:" \
&& echo " - ${_ROOT}" \
&& echo " - ${_CIS_ROOT}" \
&& echo " following file is in use:" \
&& echo " - $(readlink -f "${_CURRENT_FULLFILE}")" \
&& return 0
@@ -174,4 +197,6 @@ function ensureUsageOfDefinitions() {
ensureUsageOfDefinitions \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
"$(echo ${2} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
&& exit 0
exit 1

View File

@@ -0,0 +1,83 @@
#!/bin/bash
[ "$(id -u)" == "0" ] \
&& echo "This script prepares the content of the repository for the definitions." \
&& echo "You have run it as root, please run it with a user who has write access to the Git server." \
&& echo \
&& echo "Do not use the SSH key of root for this." \
&& echo \
&& exit 1
_BOOT_HOSTNAME="$(hostname -b)"
_BOOT_DOMAIN="${_BOOT_HOSTNAME#*.}" #Removes shortest matching pattern '*.' from the begin to get the domain
[ -z "${_BOOT_DOMAIN}" ] \
&& echo "It was impossible to find out the domain of this host, please prepare this host first." \
&& exit 1
_REOPSITORY_NAME="cis-definition-${_BOOT_DOMAIN}"
#Generate file 'README.md'
mkdir -p /tmp/skeleton/definition
cat << EOF > /tmp/skeleton/definition/README.md
#$_REOPSITORY_NAME
Central Infrastructure System's definition of domain $_BOOT_DOMAIN
EOF
#Generate sudoers file 'allow-jenkins-updateRepositories'
mkdir -p /tmp/skeleton/definition/core/all/etc/sudoers.d
cat << EOF > /tmp/skeleton/definition/core/all/etc/sudoers.d/allow-jenkins-updateRepositories
Cmnd_Alias C_JENKINS = \\
/cis/updateRepositories.sh --core, \\
/cis/updateRepositories.sh --scripts, \\
/cis/updateRepositories.sh --definitions, \\
/cis/updateRepositories.sh --states
jenkins ALL = (root) NOPASSWD: C_JENKINS
EOF
#Generate file 'authorized_keys' for user jenkins
mkdir -p /tmp/skeleton/definition/core/all/home/jenkins/.ssh
cat << EOF > /tmp/skeleton/definition/core/all/home/jenkins/.ssh/authorized_keys
#------------------------------------------------------
# Enter the public ssh key of your jenkins server here.
#------------------------------------------------------
EOF
#Use current file 'authorized_keys' of root as definition
mkdir -p /tmp/skeleton/definition/core/all/root/.ssh
cp /root/.ssh/authorized_keys /tmp/skeleton/definition/core/all/root/.ssh/authorized_keys
cat << EOF
The first content for your repository for the definitions of the '$_BOOT_DOMAIN' domain has been created.
Please create a definition repository.
To follow the naming convention name it '$_REOPSITORY_NAME'
Go to folder '/tmp/skeleton/definition' and check the content of all 'authorized_keys' files,
correct them if required to prevent losing access to your hosts.
The public ssh key of your jenkins server has to be added.
Only now follow the instructions as our git server shows.
For example:
git init
git checkout -b main
git add .
git commit -m "first core definitions"
git remote add origin ssh://git@git.example.dev:22448/$_REOPSITORY_NAME.git
git push -u origin main
EOF

View File

@@ -0,0 +1,49 @@
#!/bin/bash
[ "$(id -u)" == "0" ] \
&& echo "This script prepares the content of the repository for the definitions." \
&& echo "You have run it as root, please run it with a user who has write access to the Git server." \
&& echo \
&& echo "Do not use the SSH key of root for this." \
&& echo \
&& exit 1
_BOOT_HOSTNAME="$(hostname -b)"
_BOOT_DOMAIN="${_BOOT_HOSTNAME#*.}" #Removes shortest matching pattern '*.' from the begin to get the domain
[ -z "${_BOOT_DOMAIN}" ] \
&& echo "It was impossible to find out the domain of this host, please prepare this host first." \
&& exit 1
_REOPSITORY_NAME="cis-state-${_BOOT_DOMAIN}"
#Generate README.md
mkdir -p /tmp/skeleton/state
cat << EOF > /tmp/skeleton/state/README.md
#$_REOPSITORY_NAME
Central Infrastructure System's state of domain $_BOOT_DOMAIN
EOF
cat << EOF
The first content for your repository for the state of the '$_BOOT_DOMAIN' domain has been created.
Please create a states repository.
To follow the naming convention name it '$_REOPSITORY_NAME'
Then go to folder '/tmp/skeleton/state' and follow the instructions as your git server shows.
For example:
git init
git checkout -b main
git add .
git commit -m "first state"
git remote add origin ssh://git@git.example.dev:22448/$_REOPSITORY_NAME.git
git push -u origin main
EOF

View File

@@ -12,42 +12,62 @@ function setNeededHostnameOrExit() {
&& hostnamectl set-hostname "${_FQDN}" \
&& return 0
echo "FAILED: setting full qualified domain name, given value was:"
echo " - ${_FQDN}"
echo "FAILED: setting full qualified domain name does not contain a domain,"
echo " given value was: ${_FQDN}"
exit 1
}
function prepare() {
function prepareThisHost() {
git --version > /dev/null || (apt update; apt upgrade -y; apt install git)
echo
echo "Public SSH-Key for root@$(hostname -b):"
cat "/root/.ssh/id_ed25519.pub" \
&& return 0
# -t type of the key pair
# -f defines the filenames (we use the standard for the selected type here)
# -q quiet, no output or interaction
# -N "" means the private key will not be secured by a passphrase
# -C defines a comment
cat "/root/.ssh/id_ed25519.pub" \
|| (ssh-keygen \
ssh-keygen \
-t ed25519 \
-f "/root/.ssh/id_ed25519" -q -N "" \
-C "$(date +%Y%m%d)-root@$(hostname -b)" \
&& cat "/root/.ssh/id_ed25519.pub")
-C "$(date +%Y%m%d):root@$(hostname -b)"
cat "/root/.ssh/id_ed25519.pub" \
&& return 0
echo
echo "Now you have to register the public ssh-key from above into your git-server to grant these access rights:"
echo "FAILED: somthing went wrong during the generation the ssh keys."
echo " These keys are mandantory. You can try to restart this script."
echo
}
function showFurtherSteps() {}
echo
echo "IMPORTANT: It is assumed that repositories for definitions and states already exist"
echo " and comply with the naming convention."
echo " Otherwise, these repositories must be created first!"
echo
echo "To grant the correct access rights, you have to register the above-mentioned ssh key,"
echo "as deploy key in these repositories of the Git server:"
echo " - scripts repository (allow readonly access only),"
echo " - definitions repository (allow readonly access only),"
echo " - states repository (allow writable access)."
echo
echo "After all access rights are granted you can clone the Infrastructure System:"
echo " e.g.: git clone ssh://git@git.example.dev:22448/iss.git /iss"
echo "After all access rights are granted you can clone the Core Infrastructure System:"
echo " e.g.: git clone ssh://git@git.example.dev:22448/cis.git /cis"
echo
echo "Finally call 'setupCoreOntoThisHost.sh' from the root directory of the repository:"
echo " e.g.: /iss/setupCoreOntoThisHost.sh"
echo "Finally call 'setupCoreOntoThisHost.sh' from the root directory:"
echo " e.g.: /cis/setupCoreOntoThisHost.sh"
echo
}
# sanitizes all parameters
setNeededHostnameOrExit "$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& prepare
&& prepareThisHost \
&& showFurtherSteps \
&& exit 0
exit 1

View File

@@ -31,10 +31,10 @@ function checkGitIsAvailable() {
}
function checkPreconditions() {
local _ROOT _DOMAIN
_ROOT="${1:?"Missing parameter ROOT"}"
local _CIS_ROOT _DOMAIN
_CIS_ROOT="${1:?"Missing parameter CIS_ROOT"}"
_DOMAIN="${2}" # Optional parameter DOMAIN
readonly _ROOT _DOMAIN
readonly _CIS_ROOT _DOMAIN
! [ -z "${_DOMAIN}" ] \
&& [ "$(hostname -d)" != "${_DOMAIN}" ] \
@@ -46,7 +46,7 @@ function checkPreconditions() {
! [ -z "${_DOMAIN}" ] \
&& checkPathsAreAvaiable \
&& checkGitIsAvailable \
&& git -C "${_ROOT}" pull &> /dev/null \
&& git -C "${_CIS_ROOT}" pull &> /dev/null \
&& return 0
echo
@@ -69,11 +69,11 @@ function checkPreconditions() {
}
function getOrSetDomain() {
local _ROOT _DOMAIN_FILE _GIVEN_DOMAIN
_ROOT="${1:?"Missing parameter ROOT"}"
_DOMAIN_FILE="${_ROOT:?"Missing ROOT"}domainOfHostOwner"
local _CIS_ROOT _DOMAIN_FILE _GIVEN_DOMAIN
_CIS_ROOT="${1:?"Missing parameter CIS_ROOT"}"
_DOMAIN_FILE="${_CIS_ROOT:?"Missing CIS_ROOT"}domainOfHostOwner"
_GIVEN_DOMAIN="${2}" # Optional parameter DOMAIN
readonly _ROOT _DOMAIN_FILE _GIVEN_DOMAIN
readonly _CIS_ROOT _DOMAIN_FILE _GIVEN_DOMAIN
# Wenn DOMAIN_FILE enhält lesbare Daten
grep '[^[:space:]]' "${_DOMAIN_FILE:?"Missing DOMAIN_FILE"}" &> /dev/null \
@@ -99,11 +99,11 @@ function getOrSetDomain() {
}
function getRemoteRepositoryPath() {
local _ROOT
_ROOT="${1:?"Missing parameter ROOT"}"
readonly _ROOT
local _CIS_ROOT
_CIS_ROOT="${1:?"Missing parameter CIS_ROOT"}"
readonly _CIS_ROOT
_RESULT="$(git -C "${_ROOT:?"Missing ROOT"}" remote show origin | grep -i 'fetch' | xargs -n 1 | grep -i 'ssh://')"
_RESULT="$(git -C "${_CIS_ROOT:?"Missing CIS_ROOT"}" remote show origin | grep -i 'fetch' | xargs -n 1 | grep -i 'ssh://')"
_RESULT="${_RESULT%/*}" #Removes shortest matching pattern '/*' from the end
! [ -z "${_RESULT}" ] \
&& echo "${_RESULT}" \
@@ -113,12 +113,12 @@ function getRemoteRepositoryPath() {
}
function addDefinition(){
local _ROOT _CORE_SCRIPTS _DEFINITIONS _REPOSITORY
local _CIS_ROOT _CORE_SCRIPTS _DEFINITIONS _REPOSITORY
_DEFINITIONS="${1:?"Missing parameter DEFINITIONS"}"
_REPOSITORY="${2:?"Missing parameter REPOSITORY"}"
_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_CORE_SCRIPTS="${_ROOT:?"Missing ROOT"}core/"
readonly _ROOT _CORE_SCRIPTS _DEFINITIONS _REPOSITORY
_CIS_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_CORE_SCRIPTS="${_CIS_ROOT:?"Missing CIS_ROOT"}core/"
readonly _CIS_ROOT _CORE_SCRIPTS _DEFINITIONS _REPOSITORY
[ "$(id -u)" == "0" ] \
&& "${_CORE_SCRIPTS:?"Missing CORE_SCRIPTS"}addAndCheckGitRepository.sh" "${_DEFINITIONS}" "${_REPOSITORY}" readonly \
&& echo " - definitions are usable for this host." \
@@ -133,12 +133,12 @@ function addDefinition(){
}
function addState() {
local _ROOT _CORE_SCRIPTS _STATES _REPOSITORY
local _CIS_ROOT _CORE_SCRIPTS _STATES _REPOSITORY
_STATES="${1:?"Missing parameter STATES"}"
_REPOSITORY="${2:?"Missing parameter REPOSITORY"}"
_ROOT="${_STATES%%/states/*}/" #Removes longest matching pattern '/states/*' from the end
_CORE_SCRIPTS="${_ROOT:?"Missing ROOT"}core/"
readonly _ROOT _CORE_SCRIPTS _STATES _REPOSITORY
_CIS_ROOT="${_STATES%%/states/*}/" #Removes longest matching pattern '/states/*' from the end
_CORE_SCRIPTS="${_CIS_ROOT:?"Missing CIS_ROOT"}core/"
readonly _CIS_ROOT _CORE_SCRIPTS _STATES _REPOSITORY
[ "$(id -u)" == "0" ] \
&& "${_CORE_SCRIPTS:?"Missing CORE_SCRIPTS"}addAndCheckGitRepository.sh" "${_STATES}" "${_REPOSITORY}" writable \
@@ -154,13 +154,13 @@ function addState() {
}
function setupCoreFunctionality() {
local _ROOT _CORE_SCRIPTS _DEFINITIONS _MINUTE_FROM_OWN_IP _SETUP
local _CIS_ROOT _CORE_SCRIPTS _DEFINITIONS _MINUTE_FROM_OWN_IP _SETUP
_DEFINITIONS="${1:?"Missing DEFINITIONS: 'ROOT/definitions/DOMAIN'"}"
_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_CORE_SCRIPTS="${_ROOT:?"Missing ROOT"}core/"
_CIS_ROOT="${_DEFINITIONS%%/definitions/*}/" #Removes longest matching pattern '/definitions/*' from the end
_CORE_SCRIPTS="${_CIS_ROOT:?"Missing CIS_ROOT"}core/"
_MINUTE_FROM_OWN_IP="$(hostname -I | xargs -n 1 | grep -F . | head -n 1 | cut -d. -f4 || echo 0)" #uses last value from first own ipv4 or 0 as minute value
_SETUP="${2:?"Missing SETUP"}"
readonly _ROOT _CORE_SCRIPTS _DEFINITIONS _MINUTE_FROM_OWN_IP _SETUP
readonly _CIS_ROOT _CORE_SCRIPTS _DEFINITIONS _MINUTE_FROM_OWN_IP _SETUP
[ "$(id -u)" != "0" ] \
&& echo "Configuration of host skipped because of insufficient rights." \
@@ -183,20 +183,20 @@ function setupCoreFunctionality() {
}
function setup() {
local _ROOT _DEFINITIONS _DEFINITIONS_REPOSITORY _DOMAIN _REPOSITORY_PATH _SETUP _STATES _STATES_REPOSITORY
local _CIS_ROOT _DEFINITIONS _DEFINITIONS_REPOSITORY _DOMAIN _REPOSITORY_PATH _SETUP _STATES _STATES_REPOSITORY
_SETUP="$(readlink -f "${0}" 2> /dev/null)"
_ROOT="$(dirname ${_SETUP:?"Missing SETUP"} 2> /dev/null || echo "/iss")/"
_DOMAIN="$(getOrSetDomain "${_ROOT:?"Missing ROOT"}" "${1}")"
_REPOSITORY_PATH="$(getRemoteRepositoryPath "${_ROOT:?"Missing ROOT"}")"
_CIS_ROOT="$(dirname ${_SETUP:?"Missing SETUP"} 2> /dev/null || echo "/cis")/"
_DOMAIN="$(getOrSetDomain "${_CIS_ROOT:?"Missing CIS_ROOT"}" "${1}")"
_REPOSITORY_PATH="$(getRemoteRepositoryPath "${_CIS_ROOT:?"Missing CIS_ROOT"}")"
! checkPreconditions "${_ROOT:?"Missing ROOT"}" "${_DOMAIN}" \
! checkPreconditions "${_CIS_ROOT:?"Missing CIS_ROOT"}" "${_DOMAIN}" \
&& return 1
_DEFINITIONS="${_ROOT:?"Missing ROOT"}definitions/${_DOMAIN:?"Missing DOMAIN"}"
_DEFINITIONS_REPOSITORY="${_REPOSITORY_PATH:?"Missing REPOSITORY_PATH"}/iss-definition-${_DOMAIN:?"Missing DOMAIN"}.git"
_STATES="${_ROOT:?"Missing ROOT"}states/${_DOMAIN:?"Missing DOMAIN"}"
_STATES_REPOSITORY="${_REPOSITORY_PATH:?"Missing REPOSITORY_PATH"}/iss-state-${_DOMAIN:?"Missing DOMAIN"}.git"
readonly _ROOT _DEFINITIONS _DEFINITIONS_REPOSITORY _DOMAIN _REPOSITORY_PATH _SETUP _STATES _STATES_REPOSITORY
_DEFINITIONS="${_CIS_ROOT:?"Missing CIS_ROOT"}definitions/${_DOMAIN:?"Missing DOMAIN"}"
_DEFINITIONS_REPOSITORY="${_REPOSITORY_PATH:?"Missing REPOSITORY_PATH"}/cis-definition-${_DOMAIN:?"Missing DOMAIN"}.git"
_STATES="${_CIS_ROOT:?"Missing CIS_ROOT"}states/${_DOMAIN:?"Missing DOMAIN"}"
_STATES_REPOSITORY="${_REPOSITORY_PATH:?"Missing REPOSITORY_PATH"}/cis-state-${_DOMAIN:?"Missing DOMAIN"}.git"
readonly _CIS_ROOT _DEFINITIONS _DEFINITIONS_REPOSITORY _DOMAIN _REPOSITORY_PATH _SETUP _STATES _STATES_REPOSITORY
echo \
&& echo "Running setup using repositories of: '${_REPOSITORY_PATH:?"Missing REPOSITORY_PATH"}' ..." \
@@ -215,6 +215,7 @@ function setup() {
}
# sanitizes all parameters
setup \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
setup "$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0
exit 1

View File

@@ -20,32 +20,32 @@
function update_repositories() {
local _ROOT _DEFINITIONS _DOMAIN _MODE _STATES _UPDATE_REPOSITORIES
local _CIS_ROOT _DEFINITIONS _DOMAIN _MODE _STATES _UPDATE_REPOSITORIES
_UPDATE_REPOSITORIES="$(readlink -f "${0}" 2> /dev/null)"
_MODE="${1:-"all"}"
_ROOT="$(dirname ${_UPDATE_REPOSITORIES:?"Missing UPDATE_REPOSITORIES"} 2> /dev/null || echo "/iss")/"
_DOMAIN="$(cat ${_ROOT:?"Missing ROOT"}domainOfHostOwner)"
_DEFINITIONS="${_ROOT}definitions/${_DOMAIN:?"Missing DOMAIN from file: ${_ROOT}domainOfHostOwner"}/"
_STATES="${_ROOT}states/${_DOMAIN:?"Missing DOMAIN from file: ${_ROOT}domainOfHostOwner"}/"
readonly _ROOT _DEFINITIONS _DOMAIN _MODE _STATES _UPDATE_REPOSITORIES
_MODE="${1:-"--core"}"
_CIS_ROOT="$(dirname ${_UPDATE_REPOSITORIES:?"Missing UPDATE_REPOSITORIES"} 2> /dev/null || echo "/cis")/"
_DOMAIN="$(cat ${_CIS_ROOT:?"Missing CIS_ROOT"}domainOfHostOwner)"
_DEFINITIONS="${_CIS_ROOT}definitions/${_DOMAIN:?"Missing DOMAIN from file: ${_CIS_ROOT}domainOfHostOwner"}/"
_STATES="${_CIS_ROOT}states/${_DOMAIN:?"Missing DOMAIN from file: ${_CIS_ROOT}domainOfHostOwner"}/"
readonly _CIS_ROOT _DEFINITIONS _DOMAIN _MODE _STATES _UPDATE_REPOSITORIES
[ "${_MODE}" == "--repair" ] \
&& (git -C "${_ROOT}" reset --hard origin/master; \
git -C "${_DEFINITIONS}" reset --hard origin/master; \
git -C "${_STATES}" reset --hard origin/master; \
&& (git -C "${_CIS_ROOT}" reset --hard origin/main; \
git -C "${_DEFINITIONS}" reset --hard origin/main; \
git -C "${_STATES}" reset --hard origin/main; \
echo "Run repairs") \
&& return 0
[ "${_MODE}" == "--test" ] \
&& git -C "${_ROOT}" pull \
&& git -C "${_CIS_ROOT}" pull \
&& git -C "${_DEFINITIONS}" pull \
&& git -C "${_STATES}" pull \
&& echo "Run in testMode successfully." \
&& return 0
[ "${_MODE}" == "--scripts" ] \
&& echo "Host $HOSTNAME updating scripts: ${_ROOT} ..." \
&& (git -C "${_ROOT}" pull &> /dev/null &) \
&& echo "Host $HOSTNAME updating scripts: ${_CIS_ROOT} ..." \
&& (git -C "${_CIS_ROOT}" pull &> /dev/null &) \
&& return 0
[ "${_MODE}" == "--definitions" ] \
@@ -58,16 +58,19 @@ function update_repositories() {
&& (git -C "${_STATES}" pull &> /dev/null &) \
&& return 0
echo "Host ${HOSTNAME} updating ${_MODE}:" \
&& echo " - ${_ROOT}" \
&& echo " - ${_DEFINITIONS}" \
&& echo " - ${_STATES}"
git -C "${_ROOT}" pull &> /dev/null
git -C "${_DEFINITIONS}" pull &> /dev/null
git -C "${_STATES}" pull &> /dev/null
[ "${_MODE}" == "--core" ] \
&& echo "Host ${HOSTNAME} updating core including scripts, definitions and states: ${_STATES} ..." \
&& (git -C "${_CIS_ROOT}" pull &> /dev/null &) \
&& (git -C "${_DEFINITIONS}" pull &> /dev/null &) \
&& (git -C "${_STATES}" pull &> /dev/null &) \
&& return 0
echo "FAILED: an error occurred during an update."
return 1
}
# sanitizes all parameters
update_repositories \
"$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0 || exit 1
update_repositories "$(echo ${1} | sed -E 's|[^a-zA-Z0-9/:@._-]*||g')" \
&& exit 0
exit 1