diff --git a/divingbell/templates/bin/_perm.sh.tpl b/divingbell/templates/bin/_perm.sh.tpl new file mode 100644 index 0000000..6aac03e --- /dev/null +++ b/divingbell/templates/bin/_perm.sh.tpl @@ -0,0 +1,135 @@ +#!/bin/bash + +{{/* +# Copyright 2018 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/}} + +set -e + +cat <<'EOF' > {{ .Values.conf.chroot_mnt_path | quote }}/tmp/perm_host.sh +{{ include "divingbell.shcommon" . }} + +backup_path='/var/divingbell/perm' + +[ ! -d "${backup_path}" ] && mkdir -p "${backup_path}" + +write_test "${backup_path}" + +add_perm(){ +# accepts $path, $owner, $group, $permissions + local path="${1}" + + for i in ${path}; do + add_single_perm $i ${2} ${3} ${4} + done +} + +add_single_perm(){ +# accepts $path, $owner, $group, $permissions + local path="${1}" + local owner="${2}" + local group="${3}" + local permissions="${4}" + + # check if file exists + [ -e $path ] || return 1 + # if set -e is set the entire script will exit + + # construct backup name + local file_name=$(systemd-escape $path) + local backup_file="${backup_path}/${file_name}" + # check if backup exists + if [ ! -e ${backup_file} ]; then + # Try reading the current permissions and owner + local o_owner="$(stat -c %U ${path})" + local o_group="$(stat -c %G ${path})" + local o_permissions="$(stat -c %a ${path})" + + # write restore script/data + # design decision: + # we could write complete script to restore originals + # but for security reasons write only data + # otherwise we would execute _any_ script from backup dir + + # chmod o_permissions path + echo "$o_permissions $path"> ${backup_file} + # chown o_owner:o_group path + echo "$o_owner:$o_group $path">> ${backup_file} + + log.DEBUG ${backup_file} + fi + + # apply permissions + chmod ${permissions} ${path} + # apply owner and group + chown ${owner}:${group} ${path} + + # notice applied perm + applied_perm="${applied_perm}${file_name}"$'\n' + # ("${file_name}"$'\n') + +} + +{{- range $perm := .Values.conf.perm }} +add_perm {{ $perm.path | squote }} {{ $perm.owner | squote }} {{ $perm.group | squote }} {{ $perm.permissions | squote }} +{{- end }} + +log.INFO "Applied: ${applied_perm}" + +# Revert +prev_files="$(find "${backup_path}" -type f)" +if [ -n "${prev_files}" ]; then + basename -a ${prev_files} | sort > /tmp/prev_perm + echo "${applied_perm}" | sort > /tmp/curr_perm + log.DEBUG /tmp/prev_perm + log.DEBUG /tmp/curr_perm + revert_list="$(comm -23 /tmp/prev_perm /tmp/curr_perm)" + IFS=$'\n' + for o_perm in ${revert_list}; do + first=1 + while IFS=' ' read -r a1 a2; do + if [ "$first" -eq 1 ]; then + $(chmod $a1 $a2) + first=0 + else + $(chown $a1 $a2) + fi + done < "${backup_path}/${o_perm}" + + rm "${backup_path}/${o_perm}" + log.INFO "Reverted permissions and owner: ${backup_path}/${o_perm}" + done +fi + +if [ -n "${curr_settings}" ]; then + log.INFO 'All permissions successfully applied on this node.' +else + log.WARN 'No permissions overrides defined for this node.' +fi + +exit 0 +EOF + +chmod 755 {{ .Values.conf.chroot_mnt_path | quote }}/tmp/perm_host.sh +chroot {{ .Values.conf.chroot_mnt_path | quote }} /tmp/perm_host.sh + +sleep 1 +echo 'INFO Putting the daemon to sleep.' + +while [ 1 ]; do + sleep 300 +done + +exit 0 diff --git a/divingbell/templates/daemonset-perm.yaml b/divingbell/templates/daemonset-perm.yaml new file mode 100644 index 0000000..6c31c71 --- /dev/null +++ b/divingbell/templates/daemonset-perm.yaml @@ -0,0 +1,71 @@ +{{/* +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/}} + +{{- define "divingbell.daemonset.perm" }} + {{- $daemonset := index . 0 }} + {{- $secretName := index . 1 }} + {{- $envAll := index . 2 }} + {{- with $envAll }} +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: {{ $daemonset }} + annotations: + {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }} +spec: +{{ tuple $envAll $daemonset | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }} + template: + metadata: + labels: +{{ list $envAll .Chart.Name $daemonset | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }} + spec: + hostNetwork: true + hostPID: true + hostIPC: true + containers: + - name: {{ $daemonset }} + image: {{ .Values.images.divingbell }} + imagePullPolicy: {{ .Values.images.pull_policy }} +{{ tuple $envAll $envAll.Values.pod.resources.perm | include "helm-toolkit.snippets.kubernetes_resources" | indent 8 }} + command: + - /tmp/{{ $daemonset }}.sh + volumeMounts: + - name: rootfs-{{ $daemonset }} + mountPath: {{ .Values.conf.chroot_mnt_path }} + - name: {{ $secretName }} + mountPath: /tmp/{{ $daemonset }}.sh + subPath: {{ $daemonset }} + readOnly: true + securityContext: + privileged: true + volumes: + - name: rootfs-{{ $daemonset }} + hostPath: + path: / + - name: {{ $secretName }} + secret: + secretName: {{ $secretName }} + defaultMode: 0555 + {{- end }} +{{- end }} +{{- if .Values.manifests.daemonset_perm }} +{{- $daemonset := "perm" }} +{{- $secretName := "divingbell-perm" }} +{{- $daemonset_yaml := list $daemonset $secretName . | include "divingbell.daemonset.perm" | toString | fromYaml }} +{{- $secret_include := "divingbell.secret.perm" }} +{{- list $daemonset $daemonset_yaml $secret_include $secretName . | include "helm-toolkit.utils.daemonset_overrides" }} +{{- end }} diff --git a/divingbell/templates/secret-perm.yaml b/divingbell/templates/secret-perm.yaml new file mode 100644 index 0000000..e1edbfa --- /dev/null +++ b/divingbell/templates/secret-perm.yaml @@ -0,0 +1,29 @@ +{{/* +Copyright 2018 The Openstack-Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/}} + +{{- define "divingbell.secret.perm" }} +{{- $secretName := index . 0 }} +{{- $envAll := index . 1 }} +{{- with $envAll }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} +data: + perm: {{ tuple "bin/_perm.sh.tpl" . | include "helm-toolkit.utils.template" | b64enc }} +{{- end }} +{{- end }} diff --git a/divingbell/values.yaml b/divingbell/values.yaml index eab75d4..d8351f5 100644 --- a/divingbell/values.yaml +++ b/divingbell/values.yaml @@ -31,6 +31,47 @@ conf: - telnetd-ssl - nis - ntpdate +# perm: +# - +# path: '/boot/System.map-*' +# owner: 'root' +# group: 'root' +# permissions: '0640' +# - +# path: '/etc/shadow' +# owner: 'root' +# group: 'shadow' +# permissions: '0640' +# - +# path: '/etc/gshadow' +# owner: 'root' +# group: 'shadow' +# permissions: '0640' +# - +# path: '/etc/passwd' +# owner: 'root' +# group: 'root' +# permissions: '0644' +# - +# path: '/etc/group' +# owner: 'root' +# group: 'root' +# permissions: '0644' +# - +# path: '/var/log/kern.log' +# owner: 'syslog' +# group: 'adm' +# permissions: '0640' +# - +# path: '/var/log/auth.log' +# owner: 'syslog' +# group: 'adm' +# permissions: '0640' +# - +# path: '/var/log/syslog' +# owner: 'syslog' +# group: 'adm' +# permissions: '0640' ## data.values.conf.sysctl # sysctl: @@ -76,6 +117,10 @@ pod: enabled: true min_ready_seconds: 0 max_unavailable: 100% + perm: + enabled: true + min_ready_seconds: 0 + max_unavailable: 100% resources: enabled: false ethtool: @@ -113,6 +158,13 @@ pod: requests: memory: "128Mi" cpu: "100m" + perm: + limits: + memory: "128Mi" + cpu: "100m" + requests: + memory: "128Mi" + cpu: "100m" apt: limits: memory: "128Mi" @@ -128,3 +180,4 @@ manifests: daemonset_sysctl: true daemonset_limits: true daemonset_apt: true + daemonset_perm: true diff --git a/tools/gate/scripts/020-test-divingbell.sh b/tools/gate/scripts/020-test-divingbell.sh index b4cf74d..d766108 100755 --- a/tools/gate/scripts/020-test-divingbell.sh +++ b/tools/gate/scripts/020-test-divingbell.sh @@ -353,6 +353,88 @@ test_limits(){ echo "[SUCCESS] test range loop for limits passed successfully" >> "${TEST_RESULTS}" } +_test_perm_value(){ + local file=${1} + local owner=${2} + local group=${3} + local perm=${4} + local r_owner="$(stat -c %U ${file})" + local r_group="$(stat -c %G ${file})" + local r_perm="$(stat -c %a ${file})" + [ "${perm}"=="${r_perm}" ] && echo "+" || (echo "File ${file} permissions ${r_perm} but expected ${perm}"; exit 1) + [ "${owner}"=="${r_owner}" ] && echo "+" || (echo "File ${file} owner ${r_owner} but expected ${owner}"; exit 1) + [ "${group}"=="${r_group}" ] && echo "+" || (echo "File ${file} group ${r_group} but expected ${group}"; exit 1) +} + +_perm_init_one(){ + local file=${1} + local user=${file##*.} + useradd ${user} -U + chmod 777 ${file} + chown ${user}:${user} ${file} + echo ${file} +} + +_make_p_temp(){ + echo $(mktemp "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") +} + +_perm_init(){ + # global vars! + p_test_file1=$(_perm_init_one $(_make_p_temp)) + p_test_file2=$(_perm_init_one $(_make_p_temp)) +} + +_perm_teardown_one(){ + local file=${1} + local user=${file##*.} + deluser ${user} -q + rm -f ${file} +} + +_perm_teardown(){ + # global vars! + _perm_teardown_one ${p_test_file1} + unset p_test_file1 + _perm_teardown_one ${p_test_file2} + unset p_test_file2 +} + +test_perm(){ + _perm_init + local overrides_yaml=${LOGS_SUBDIR}/${FUNCNAME}.yaml + echo "conf: + perm: + - + path: ${p_test_file1} + owner: 'root' + group: 'shadow' + permissions: '0640' + - + path: ${p_test_file2} + owner: 'root' + group: 'shadow' + permissions: '0640'" > "${overrides_yaml}" + install_base "--values=${overrides_yaml}" + get_container_status perm + _test_perm_value ${p_test_file1} root shadow 640 + _test_perm_value ${p_test_file2} root shadow 640 + echo "[SUCCESS] Positive test for perm passed successfully" >> "${TEST_RESULTS}" + echo "conf: + perm: + - + path: ${p_test_file1} + owner: 'root' + group: 'shadow' + permissions: '0640'" > "${overrides_yaml}" + install_base "--values=${overrides_yaml}" + get_container_status perm + _test_perm_value ${p_test_file1} root shadow 640 + _test_perm_value ${p_test_file2} ${p_test_file2##*.} ${p_test_file2##*.} 777 + echo "[SUCCESS] Backup test for perm passed successfully" >> "${TEST_RESULTS}" + _perm_teardown +} + _test_if_mounted_positive(){ mountpoint "${1}" || (echo "Expect ${1} to be mounted, but was not"; exit 1) df -h | grep "${1}" | grep "${2}" || @@ -971,9 +1053,9 @@ test_overrides(){ # Compare against expected number of generated daemonsets daemonset_count="$(echo "${tc_output}" | grep 'kind: DaemonSet' | wc -l)" - if [ "${daemonset_count}" != "14" ]; then + if [ "${daemonset_count}" != "15" ]; then echo '[FAILURE] overrides test 1 failed' >> "${TEST_RESULTS}" - echo "Expected 14 daemonsets; got '${daemonset_count}'" >> "${TEST_RESULTS}" + echo "Expected 15 daemonsets; got '${daemonset_count}'" >> "${TEST_RESULTS}" exit 1 else echo '[SUCCESS] overrides test 1 passed successfully' >> "${TEST_RESULTS}" @@ -1153,6 +1235,7 @@ if [[ -z $SKIP_BASE_TESTS ]]; then install_base test_sysctl test_limits + test_perm test_mounts test_ethtool test_uamlite