#!/bin/bash
# Плугин проверяет политики настройки контейнеризации на сервере
export TEXTDOMAINDIR='/usr/share/locale'
export TEXTDOMAIN='podsec-inotify'

set +o noglob

export LANG=C
export MAILTO=''

export PROGNAME=$(basename $0)

if [ $EUID -ne 0 ]
then
  echo "POLICY Unknown $(gettext 'plugin must be run as root user')"
  exit 3
fi

. podsec-policy-functions
. podsec-inotify-functions

# setTraps

# Проанализировать описание уровня интервалов во входных парамаетрах
if [ $# -eq 0 ]
then
  JOURNALPLUGINPARS[c]=100
  NAGIIOSPLUGINPARS[c]=100
  VERBOSELEVEL=2
else
  parseIntervalParameters $*
fi

checkUsersConfig=$(checkUsersConfig)

summaryMetric=0
messages=
nagiosHeads=
users=
export prefix
export metricWeight

# Число пользователей входящий в группу podman но не входящих в группу podman_dev
nOnlyPodmanUsers=$(echo $checkUsersConfig | jq '[.[] | select(.groups | any(index("podman"))) | select(.groups | any(index("podman_dev")) | not)] | length')

# JSON пользователей имеющих образы, но не входящих в группу podman (исключая root)
notPodmanUsersJSON=$(echo $checkUsersConfig | jq '.[] | select(.groups | any(index("podman")) | not) | select(.user!="root")')
if [ -n "$notPodmanUsersJSON" ]
then
  # Получение списка пользователей
  notPodmanUsers=$(echo $notPodmanUsersJSON | jq .user | tr "\n" ' ')
#   echo "notPodmanUsers=$notPodmanUsers"
  metricWeight=101
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$notPodmanUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'outside the podman group'),"
    message="$prefix($metricWeight): $(gettext 'Users') $notPodmanUsers $(gettext 'have images but are not in the podman group')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# JSON пользователей имеющих defaultPolicy !=reject, но не входящих в группу podman_dev
incorrectPolicyUsersJSON=$(echo $checkUsersConfig | jq '.[] | select(.defaultPolicy!="reject") |  select(.groups | any(index("podman_dev")) | not)')
# echo "incorrectPolicyUsersJSON=$incorrectPolicyUsersJSON"
if [ -n "$incorrectPolicyUsersJSON" ]
then
  # Получение списка пользователей
  incorrectPolicyUsers=$(echo $incorrectPolicyUsersJSON | jq .user | tr "\n" ' ')
#   echo "incorrectPolicyUsers=$incorrectPolicyUsers"
  metricWeight=102
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$incorrectPolicyUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'capable of receiving any image')"
    message="$prefix($metricWeight): $(gettext 'Users') $incorrectPolicyUsers $(gettext 'have defaultPolicy!=reject in policy.json but are not in the podman_dev group')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# JSON пользователей не имеющих не имеющих registry.local в списке регистраторов для которых проверяется наличие электронной подписи образов
nonRegistryLocalUsersJSON=$(echo $checkUsersConfig | jq '.[] |  select(.signedRegistries | any(index("registry.local"))|not)')
# echo "nonRegistryLocalUsersJSON=$nonRegistryLocalUsersJSON"
if [ -n "$nonRegistryLocalUsersJSON" ]
then
  # Получение списка пользователей
  nonRegistryLocalUsers=$(echo $nonRegistryLocalUsersJSON | jq .user | tr "\n" ' ')
#    echo "nonRegistryLocalUsers=$nonRegistryLocalUsers"
  metricWeight=103
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$nonRegistryLocalUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'capable of getting a local image without a signature')"
    message="$prefix($metricWeight): $(gettext 'Users') $nonRegistryLocalUsers $(gettext 'do not have registry.local in the list of registries for which the presence of digital image signature is checked')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# JSON пользователей имеющих в политике регистраторы для которых не проверяется наличие электронной подписи образов
notSignedRegistriesUsersJSON=$(echo $checkUsersConfig | jq '.[] | select(.notSignedRegistries | length >0)')
if [ -n "$notSignedRegistriesUsersJSON" ]
then
  # Получение списка пользователей
  notSignedRegistriesUsers=$(echo $notSignedRegistriesUsersJSON | jq .user | tr "\n" ' ')
  metricWeight=104
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$notSignedRegistriesUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'capable of receiving any image without a signature')"
    message="$prefix($metricWeight): $(gettext 'Users') $notSignedRegistriesUsers $(gettext 'have registries in the policy for which the presence of an electronic image signature is not checked')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# JSON пользователей имеющих в списке поддерживаемых транспортов транспорты отличные от docker (получение образов с регистратора)
forbiddenTransportsUsersJSON=$(echo $checkUsersConfig | jq '.[] | select(.forbiddenTransports | length >0)')
# echo "forbiddenTransportsUsersJSON=$forbiddenTransportsUsersJSON"
if [ -n "$forbiddenTransportsUsersJSON" ]
then
  # Получение списка пользователей
  forbiddenTransportsUsers=$(echo $forbiddenTransportsUsersJSON | jq .user | tr "\n" ' ')
  metricWeight=105
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$forbiddenTransportsUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}способные получать любой образ через запрещенный транспорт
    nagiosHeads+="\n$(gettext 'capable of receiving any image via prohibited transport')"
    message="$prefix($metricWeight): $(gettext 'Users') $forbiddenTransportsUsers $(gettext 'have transports other than docker in the list of supported transports')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# JSON пользователей не использующих хранилище подписей  http://sigstore.local:81/sigstore/ как хранилище подписей по умолчанию
incorrectDefaultDockerUsersJSON=$(echo $checkUsersConfig | jq '.[] | select(.joinedSigStories."default-docker".lookaside!="http://sigstore.local:81/sigstore/")')
# echo "incorrectDefaultDockerUsersJSON=$incorrectDefaultDockerUsersJSON"
if [ -n "$incorrectDefaultDockerUsersJSON" ]
then
  # Получение списка пользователей
  incorrectDefaultDockerUsers=$(echo $incorrectDefaultDockerUsersJSON | jq .user | tr "\n" ' ')
  metricWeight=106
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$incorrectDefaultDockerUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'not using a local signature store')"
    message="$prefix($metricWeight): $(gettext 'Users') $incorrectDefaultDockerUsers $(gettext 'do not use the signature store http://sigstore.local:81/sigstore/ as the default signature store')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# Определить список пользователей группы podman (за исключением входящих в группу podman_dev):
# имеющих каталог .config/containers/ открытым на запись и изменения
# не имеющих файла конфигурации .config/containers/storage.conf
# входящих в группу wheel
notConfigUsers='' editableConfigUsers='' podmanWheelUsers=''
for dir in /home/*
do
  user=$(basename $dir)
  if ! group=$(id -g -n $user 2>/dev/null); then continue; fi
  groups=$(id -G -n $user)
  if echo " $group $groups " | grep -q ' podman_dev '; then continue; fi
  if echo " $group $groups " | grep -q ' podman '
  then
    if echo " $group $groups " | grep -q ' wheel '
    then
      podmanWheelUsers+=" \"$user\""
    fi
  else
    continue;
  fi
  # Только группа podman без podman_dev
  if [ ! -f "/home/$user/.config/containers/storage.conf" ]
  then
    notConfigUsers+=" \"$user\""
    continue
  fi
  if echo 2>/dev/null > /home/$user/.config/containers/.test 2>/dev/null
  then
    editableConfigUsers+=" \"$user\""
  fi
done

# echo "podmanWheelUsers=$podmanWheelUsers"
if [ -n "$podmanWheelUsers" ]
then
  metricWeight=107
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$podmanWheelUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosheads+="\n$(gettext 'included in the wheel group')"
    message="$prefix($metricweight): $(gettext 'the') $podmanwheelusers $(gettext 'users are members of the podman and wheel groups')"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# echo "notConfigUsers=$notConfigUsers"
if [ -n "$notConfigUsers" ]
then
  users+=$notConfigUsers
  set -- $notConfigUsers
  let metricWeight="(90*$#)/$nOnlyPodmanUsers"
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'without a config file')"
    message="$prefix($metricWeight): $notConfigUsers $(gettext 'users do not have config file') .config/containers/storage.conf"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

# echo "editableConfigUsers=$editableConfigUsers"
if [ -n "$editableConfigUsers" ]
then
  set -- $editableConfigUsers
  let metricWeight="(90*$#)/$nOnlyPodmanUsers"
  key=$(getJournalKeyByMetric $metricWeight);
  if [ -n "$key" ]
  then
    users+=$editableConfigUsers
    prefix=${LEVELSNAMES[$key]};
    priority=${JOURNALPRIORITY[$key]}
    nagiosHeads+="\n$(gettext 'able to change configuration')"
    message="$prefix($metricWeight): $editableConfigUsers $(gettext 'users have writable configuration directory') .config/containers"
    logger -p $priority -t "${PROGNAME}" "$prefix: $message"
    messages+="\n$message"
  fi
  let summaryMetric+=$metricWeight
fi

key=$(getNagiosKeyByMetric $summaryMetric)
if [ -n "$key" ]
then
  users=$(echo "$users" | tr ' ' "\n" | sort -u | tr "\n" ' ')
  prefix=${LEVELSNAMES[$key]}
  priority=${NAGIOSPRIORITY[$key]}
  outMessage=
  export subject
  case $VERBOSELEVEL in
    0)
      subject="POLICY $prefix($metricWeight): $(gettext 'Violation of user containerization policies') $users"
      outMessage=$subject
      ;;
    1|2|3)
      subject="POLICY $prefix($metricWeight): $(gettext 'Violation of user containerization policies') $users"
      outMessage="$subject | $(gettext 'There are users'):"
      outMessage+="$nagiosHeads"
      if [ $VERBOSELEVEL -gt 1 ]
      then
        outMessage+=" | $messages"
      fi
      ;;
  esac
  outMessage+="\n"
  if [ -n "$MAILTO" ]
    then
      echo -ne $outMessage | mail -s "$subject" $MAILTO
  fi
  exit 0
fi
  echo "POLICY OK: $(gettext 'Containerization policies are not violated')"
exit 0

