mirror of
https://github.com/m8tin/cis.git
synced 2025-12-06 07:48:26 +01:00
Revised and CIS introduced
This commit is contained in:
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal 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
|
||||
22
README.md
22
README.md
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
83
prepareDefinitionsRepository.sh
Normal file
83
prepareDefinitionsRepository.sh
Normal 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
|
||||
49
prepareStatesRepository.sh
Normal file
49
prepareStatesRepository.sh
Normal 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
|
||||
46
preparationBeforeCloning.sh → prepareThisHostBeforeCloning.sh
Executable file → Normal file
46
preparationBeforeCloning.sh → prepareThisHostBeforeCloning.sh
Executable file → Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user