diff --git a/README.md b/README.md index 2f10481..2aa523d 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ spec: options: networkPath: "//server/share" mountOptions: "dir_mode=0755,file_mode=0644,noperm" + selinuxEnabled: "true" ``` Start the pod: diff --git a/cifs b/cifs index 040674e..67cfba7 100755 --- a/cifs +++ b/cifs @@ -2,6 +2,10 @@ set -u +DEBUG=1 +LOGFILE=/var/log/cifs.log +MAXLOGFILESIZE=100 # In megabytes + # ==================================================================== # Example configuration: # ==================================================================== @@ -49,127 +53,401 @@ set -u # mountOptions: "dir_mode=0755,file_mode=0644,noperm" # -------------------------------------------------------------------- + +log() { + level=$1 + shift + message=$@ + shift + if [ ${DEBUG} -ne 0 ] + then + echo "$(date +%Y%m%d-%H:%M:%S):::${level}:::${message}" >>${LOGFILE} + fi +} + +manageSize(){ + [ ! -f ${LOGFILE} ] && log "info" "log initialized" && return + [ $(du -sm ${LOGFILE}|cut -f1) -gt ${MAXLOGFILESIZE} ] && mv ${LOGFILE} ${LOGFILE}.1 && log "info" "log initialized" + +} + +checkMount() { + log "debug" "verifying running processes..." + runningprocesses="$(fuser -m $1)" + [ -n "${runningprocesses}" ] && log "info" "Running Processes: ${runningprocesses}" + +} + +init() { + assertBinaryInstalled mount.cifs cifs-utils + assertBinaryInstalled jq jq + assertBinaryInstalled mountpoint util-linux + assertBinaryInstalled base64 coreutils + echo '{ "status": "Success", "message": "The fstab/cifs flexvolume plugin was initialized successfully", "capabilities": { "attach": false } }' + log "debug" "The fstab/cifs flexvolume plugin was initialized successfully" + exit 0 +} + +assertBinaryInstalled() { + binary="$1" + package="$2" + if ! which "$binary" > /dev/null ; then + errorExit "Failed to initialize the fstab/cifs flexvolume plugin. $binary command not found. Please install the $package package." + fi +} + +errorExit() { + if [[ $# -ne 1 ]] ; then + echo '{ "status": "Failure", "message": "Unknown error in the fstab/cifs flexvolume plugin." }' + log "error" "Unknown error in the fstab/cifs flexvolume plugin.." + else + jq -Mcn --arg message "$1" '{ "status": "Failure", "message": $message }' + log "error" "$1" + fi + exit 1 +} + +doMount() { + if [[ -z ${1:-} || -z ${2:-} ]] ; then + errorExit "cifs mount: syntax error. usage: cifs mount " + fi + mountPoint="$1" + shift + json=$(printf '%s ' "${@}") + if ! jq -e . > /dev/null 2>&1 <<< "$json" ; then + errorExit "cifs mount: syntax error. invalid json: '$json'" + fi + networkPath="$(jq --raw-output -e '.networkPath' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: option networkPath missing in flexvolume configuration." + fi + mountOptions="$(jq --raw-output -e '.mountOptions' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: option mountOptions missing in flexvolume configuration." + fi + + selinuxOptions="" + selinuxEnabled="$(jq --raw-output -e '.selinuxEnabled' <<< "$json" 2>/dev/null)" + if [[ "$(echo $selinuxEnabled|tr '[A-Z]' '[a-z]')" == "true" ]] ; then + selinuxOptions=",context=system_u:object_r:container_file_t:s0" + fi + cifsUsernameBase64="$(jq --raw-output -e '.["kubernetes.io/secret/username"]' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: username not found. the flexVolume definition must contain a secretRef to a secret with username and password." + fi + cifsPasswordBase64="$(jq --raw-output -e '.["kubernetes.io/secret/password"]' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: password not found. the flexVolume definition must contain a secretRef to a secret with username and password." + fi + cifsUsername="$(base64 --decode <<< "$cifsUsernameBase64" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: username secret is not base64 encoded." + fi + cifsPassword="$(base64 --decode <<< "$cifsPasswordBase64" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: password secret is not base64 encoded." + fi + if ! mkdir -p "$mountPoint" > /dev/null 2>&1 ; then + errorExit "cifs mount: failed to create mount directory: '$mountPoint'" + fi + if [[ $(mountpoint "$mountPoint") = *"is a mountpoint"* ]] ; then + errorExit "cifs mount: there is already a filesystem mounted under the mount directory: '$mountPoint'" + fi + if [[ ! -z $(ls -A "$mountPoint" 2>/dev/null) ]] ; then + errorExit "cifs mount: mount directory is not an empty directory: '$mountPoint'" + fi + + export PASSWD="$cifsPassword" + + log "debug" "mount -t cifs $networkPath $mountPoint -o username=$cifsUsername,$mountOptions$selinuxOptions" + + result=$(mount -t cifs "$networkPath" "$mountPoint" -o "username=$cifsUsername,$mountOptions$selinuxOptions" 2>&1) + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: failed to mount the network path: $result" + fi + echo '{ "status": "Success" }' + log "info" "success mount" + exit 0 +} + +doUnmount() { + #log "info" "umount action - '$2'" + if [[ -z ${1:-} ]] ; then + errorExit "cifs unmount: syntax error. usage: cifs unmount " + fi + mountPoint="$1" + if [[ $(mountpoint "$mountPoint") != *"is a mountpoint"* ]] ; then + errorExit "cifs unmount: no filesystem mounted under directory: '$mountPoint'" + fi + + checkMount "$mountPoint" + + result=$(umount "$mountPoint" 2>&1) + if [[ $? -ne 0 ]] ; then + errorExit "cifs unmount: failed to unmount the network path: $result" + fi + echo '{ "status": "Success" }' + log "info" "success umount" + exit 0 +} + +not_supported() { + echo '{ "status": "Not supported" }' + log "info" "action not supported - ${@}" + exit 1 +} + # Uncomment the following lines to see how this plugin is called: -# echo >> /tmp/cifs.log -# date >> /tmp/cifs.log -# echo "$@" >> /tmp/cifs.log +#echo >> /tmp/ci0fs_.log +manageSize +log "debug" "RAWDATA $@" + +command=${1:-} +if [[ -n $command ]]; then + shift +fi + +case "$command" in + init) + init "$@" + ;; + mount) + log "debug" "mount action - '$@'" + doMount "$@" + ;; + unmount) + log "debug" "unmount action - '$@'" + doUnmount "$@" + ;; + *) + not_supported "$@" + ;; +esac +root@atlhqmphsrncd4:~# vi /var/lib/kubelet/volumeplugins/fstab~cifs/cifs +root@atlhqmphsrncd4:~# cat /var/lib/kubelet/volumeplugins/fstab~cifs/cifs +#!/bin/bash + +set -u + +DEBUG=1 +LOGFILE=/var/log/cifs.log +MAXLOGFILESIZE=100 # In megabytes + +# ==================================================================== +# Example configuration: +# ==================================================================== +# -------------------------------------------------------------------- +# secret.yml: +# -------------------------------------------------------------------- +# apiVersion: v1 +# kind: Secret +# metadata: +# name: cifs-secret +# namespace: default +# type: fstab/cifs +# data: +# username: 'ZXhhbXBsZQo=' +# password: 'c2VjcmV0Cg==' +# +# -------------------------------------------------------------------- +# pod.yml: +# -------------------------------------------------------------------- +# apiVersion: v1 +# kind: Pod +# metadata: +# name: busybox +# namespace: default +# spec: +# containers: +# - name: busybox +# image: busybox +# command: +# - sleep +# - "3600" +# imagePullPolicy: IfNotPresent +# volumeMounts: +# - name: test +# mountPath: /data +# volumes: +# - name: test +# flexVolume: +# driver: "fstab/cifs" +# fsType: "cifs" +# secretRef: +# name: "cifs-secret" +# options: +# networkPath: "//example-server/backup" +# mountOptions: "dir_mode=0755,file_mode=0644,noperm" +# -------------------------------------------------------------------- + + +log() { + level=$1 + shift + message=$@ + shift + if [ ${DEBUG} -ne 0 ] + then + echo "$(date +%Y%m%d-%H:%M:%S):::${level}:::${message}" >>${LOGFILE} + fi +} + +manageSize(){ + [ ! -f ${LOGFILE} ] && log "info" "log initialized" && return + [ $(du -sm ${LOGFILE}|cut -f1) -gt ${MAXLOGFILESIZE} ] && mv ${LOGFILE} ${LOGFILE}.1 && log "info" "log initialized" + +} + +checkMount() { + log "debug" "verifying running processes..." + runningprocesses="$(fuser -m $1)" + [ -n "${runningprocesses}" ] && log "info" "Running Processes: ${runningprocesses}" + +} init() { - assertBinaryInstalled mount.cifs cifs-utils - assertBinaryInstalled jq jq - assertBinaryInstalled mountpoint util-linux - assertBinaryInstalled base64 coreutils - echo '{ "status": "Success", "message": "The fstab/cifs flexvolume plugin was initialized successfully", "capabilities": { "attach": false } }' - exit 0 + assertBinaryInstalled mount.cifs cifs-utils + assertBinaryInstalled jq jq + assertBinaryInstalled mountpoint util-linux + assertBinaryInstalled base64 coreutils + echo '{ "status": "Success", "message": "The fstab/cifs flexvolume plugin was initialized successfully", "capabilities": { "attach": false } }' + log "debug" "The fstab/cifs flexvolume plugin was initialized successfully" + exit 0 } assertBinaryInstalled() { - binary="$1" - package="$2" - if ! which "$binary" > /dev/null ; then - errorExit "Failed to initialize the fstab/cifs flexvolume plugin. $binary command not found. Please install the $package package." - fi + binary="$1" + package="$2" + if ! which "$binary" > /dev/null ; then + errorExit "Failed to initialize the fstab/cifs flexvolume plugin. $binary command not found. Please install the $package package." + fi } errorExit() { - if [[ $# -ne 1 ]] ; then - echo '{ "status": "Failure", "message": "Unknown error in the fstab/cifs flexvolume plugin." }' - else - jq -Mcn --arg message "$1" '{ "status": "Failure", "message": $message }' - fi - exit 1 + if [[ $# -ne 1 ]] ; then + echo '{ "status": "Failure", "message": "Unknown error in the fstab/cifs flexvolume plugin." }' + log "error" "Unknown error in the fstab/cifs flexvolume plugin.." + else + jq -Mcn --arg message "$1" '{ "status": "Failure", "message": $message }' + log "error" "$1" + fi + exit 1 } doMount() { - if [[ -z ${1:-} || -z ${2:-} ]] ; then - errorExit "cifs mount: syntax error. usage: cifs mount " - fi - mountPoint="$1" - shift - json=$(printf '%s ' "${@}") - if ! jq -e . > /dev/null 2>&1 <<< "$json" ; then - errorExit "cifs mount: syntax error. invalid json: '$json'" - fi - networkPath="$(jq --raw-output -e '.networkPath' <<< "$json" 2>/dev/null)" - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: option networkPath missing in flexvolume configuration." - fi - mountOptions="$(jq --raw-output -e '.mountOptions' <<< "$json" 2>/dev/null)" - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: option mountOptions missing in flexvolume configuration." - fi - cifsUsernameBase64="$(jq --raw-output -e '.["kubernetes.io/secret/username"]' <<< "$json" 2>/dev/null)" - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: username not found. the flexVolume definition must contain a secretRef to a secret with username and password." - fi - cifsPasswordBase64="$(jq --raw-output -e '.["kubernetes.io/secret/password"]' <<< "$json" 2>/dev/null)" - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: password not found. the flexVolume definition must contain a secretRef to a secret with username and password." - fi - cifsUsername="$(base64 --decode <<< "$cifsUsernameBase64" 2>/dev/null)" - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: username secret is not base64 encoded." - fi - cifsPassword="$(base64 --decode <<< "$cifsPasswordBase64" 2>/dev/null)" - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: password secret is not base64 encoded." - fi - if ! mkdir -p "$mountPoint" > /dev/null 2>&1 ; then - errorExit "cifs mount: failed to create mount directory: '$mountPoint'" - fi - if [[ $(mountpoint "$mountPoint") = *"is a mountpoint"* ]] ; then - errorExit "cifs mount: there is already a filesystem mounted under the mount directory: '$mountPoint'" - fi - if [[ ! -z $(ls -A "$mountPoint" 2>/dev/null) ]] ; then - errorExit "cifs mount: mount directory is not an empty directory: '$mountPoint'" - fi - - export PASSWD="$cifsPassword" - result=$(mount -t cifs "$networkPath" "$mountPoint" -o "username=$cifsUsername,$mountOptions" 2>&1) - if [[ $? -ne 0 ]] ; then - errorExit "cifs mount: failed to mount the network path: $result" - fi - echo '{ "status": "Success" }' - exit 0 + if [[ -z ${1:-} || -z ${2:-} ]] ; then + errorExit "cifs mount: syntax error. usage: cifs mount " + fi + mountPoint="$1" + shift + json=$(printf '%s ' "${@}") + if ! jq -e . > /dev/null 2>&1 <<< "$json" ; then + errorExit "cifs mount: syntax error. invalid json: '$json'" + fi + networkPath="$(jq --raw-output -e '.networkPath' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: option networkPath missing in flexvolume configuration." + fi + mountOptions="$(jq --raw-output -e '.mountOptions' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: option mountOptions missing in flexvolume configuration." + fi + + selinuxOptions="" + selinuxEnabled="$(jq --raw-output -e '.selinuxEnabled' <<< "$json" 2>/dev/null)" + if [[ "$(echo $selinuxEnabled|tr '[A-Z]' '[a-z]')" == "true" ]] ; then + selinuxOptions=",context=system_u:object_r:container_file_t:s0" + fi + cifsUsernameBase64="$(jq --raw-output -e '.["kubernetes.io/secret/username"]' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: username not found. the flexVolume definition must contain a secretRef to a secret with username and password." + fi + cifsPasswordBase64="$(jq --raw-output -e '.["kubernetes.io/secret/password"]' <<< "$json" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: password not found. the flexVolume definition must contain a secretRef to a secret with username and password." + fi + cifsUsername="$(base64 --decode <<< "$cifsUsernameBase64" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: username secret is not base64 encoded." + fi + cifsPassword="$(base64 --decode <<< "$cifsPasswordBase64" 2>/dev/null)" + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: password secret is not base64 encoded." + fi + if ! mkdir -p "$mountPoint" > /dev/null 2>&1 ; then + errorExit "cifs mount: failed to create mount directory: '$mountPoint'" + fi + if [[ $(mountpoint "$mountPoint") = *"is a mountpoint"* ]] ; then + errorExit "cifs mount: there is already a filesystem mounted under the mount directory: '$mountPoint'" + fi + if [[ ! -z $(ls -A "$mountPoint" 2>/dev/null) ]] ; then + errorExit "cifs mount: mount directory is not an empty directory: '$mountPoint'" + fi + + export PASSWD="$cifsPassword" + + log "debug" "executed mount -t cifs $networkPath $mountPoint -o username=$cifsUsername,$mountOptions$selinuxOptions" + + result=$(mount -t cifs "$networkPath" "$mountPoint" -o "username=$cifsUsername,$mountOptions$selinuxOptions" 2>&1) + if [[ $? -ne 0 ]] ; then + errorExit "cifs mount: failed to mount the network path: $result" + fi + echo '{ "status": "Success" }' + log "info" "success mount" + exit 0 } doUnmount() { - if [[ -z ${1:-} ]] ; then - errorExit "cifs unmount: syntax error. usage: cifs unmount " - fi - mountPoint="$1" - if [[ $(mountpoint "$mountPoint") != *"is a mountpoint"* ]] ; then - errorExit "cifs unmount: no filesystem mounted under directory: '$mountPoint'" - fi - result=$(umount "$mountPoint" 2>&1) - if [[ $? -ne 0 ]] ; then - errorExit "cifs unmount: failed to unmount the network path: $result" - fi - echo '{ "status": "Success" }' - exit 0 + #log "info" "umount action - '$2'" + if [[ -z ${1:-} ]] ; then + errorExit "cifs unmount: syntax error. usage: cifs unmount " + fi + mountPoint="$1" + if [[ $(mountpoint "$mountPoint") != *"is a mountpoint"* ]] ; then + errorExit "cifs unmount: no filesystem mounted under directory: '$mountPoint'" + fi + + checkMount "$mountPoint" + + log "debug" "executed umount $mountPoint" + result=$(umount "$mountPoint" 2>&1|tr '\n' ' ') + if [[ $? -ne 0 ]] ; then + errorExit "cifs unmount: failed to unmount the network path: $result" + fi + echo '{ "status": "Success" }' + log "info" "success umount" + exit 0 } not_supported() { - echo '{ "status": "Not supported" }' - exit 1 + echo '{ "status": "Not supported" }' + log "info" "action not supported - ${@}" + exit 1 } +# Uncomment the following lines to see how this plugin is called: +#echo >> /tmp/ci0fs_.log +manageSize +log "debug" "RAWDATA $@" + command=${1:-} if [[ -n $command ]]; then - shift + shift fi case "$command" in - init) - init "$@" - ;; - mount) - doMount "$@" - ;; - unmount) - doUnmount "$@" - ;; - *) - not_supported "$@" - ;; + init) + init "$@" + ;; + mount) + log "debug" "mount action - '$@'" + doMount "$@" + ;; + unmount) + log "debug" "unmount action - '$@'" + doUnmount "$@" + ;; + *) + not_supported "$@" + ;; esac