#!/bin/sh

#################################################################################
#
#   Lynis
# ------------------
#
# Copyright (c) Michael Boelen, CISOfy, and many contributors.
#
# Website  : https://cisofy.com/
# Blog     : https://linux-audit.com/
# GitHub   : https://github.com/CISOfy/lynis
#
# Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
# welcome to redistribute it under the terms of the GNU General Public License.
# See LICENSE file for usage of this software.
#
#################################################################################

if [ $# -eq 0 ]; then
    Display --indent 2 --text "${RED}Error: ${WHITE}Provide a file${NORMAL}"
    Display --text " "; Display --text " "
    ExitFatal
else
    FILE=$(echo $1 | grep -E "^http|https")
    if HasData "${FILE}"; then
        echo "Provide a file (not a URL)"
        ExitFatal
    else
        if [ -f $1 ]; then
            AUDIT_FILE="$1"
        else
            Display --indent 2 --text "File $1 does not exist"
            ExitFatal
        fi
    fi
    Display --indent 2 --text "File to audit = ${AUDIT_FILE}"
fi

#####################################################

#
##################################################################################################
#

    InsertSection "${SECTION_IMAGE}"

    PKGMGR=""
    FIND=$(grep "^FROM" ${AUDIT_FILE} | sed 's/ /:space:/g')
    for I in ${FIND}; do
        IMAGE=$(echo ${I} | sed 's/:space:/ /g' | awk '{ if ($1=="FROM") { print $2 }}')
        TAG=$(echo ${IMAGE} | cut -d':' -f2)
        Display --indent 2 --text "Found image:" --result "${IMAGE}"

        IS_DEBIAN=$(echo ${IMAGE} | grep -i debian)
        IS_FEDORA=$(echo ${IMAGE} | grep -i fedora)
        IS_UBUNTU=$(echo ${IMAGE} | grep -i ubuntu)
        IS_ALPINE=$(echo ${IMAGE} | grep -i alpine)
        IS_LATEST=$(echo ${TAG} | grep -i latest)

        if [ -n "${IS_DEBIAN}" ]; then IMAGE="debian"; fi
        if [ -n "${IS_FEDORA}" ]; then IMAGE="fedora"; fi
        if [ -n "${IS_UBUNTU}" ]; then IMAGE="ubuntu"; fi
        if [ -n "${IS_ALPINE}" ]; then IMAGE="alpine"; fi
        if [ -n "${IS_LATEST}" ]; then
            ReportWarning "dockerfile" "latest TAG used. Specifying a targeted OS image and version is better for reproducible results."
        fi

        case ${IMAGE} in
            "debian")
                LogText "Image = Debian based"
                PKGMGR="apt"
                ;;
            "fedora*")
                LogText "  Image = Fedora based"
                PKGMGR="yum"
                ;;
            "ubuntu")
                LogText "  Image = Ubuntu based"
                PKGMGR="apt"
                ;;
            "alpine")
                LogText "  Image = Alpine based"
                PKGMGR="apk"
                ;;
            *)
                Display --indent 2 --text "Unknown image" --result "" --color YELLOW
                ;;
        esac
    done

#
##################################################################################################
#
    InsertSection "${SECTION_BASICS}"

    MAINTAINER=$(grep -E -i "*MAINTAINER" ${AUDIT_FILE} | sed 's/=/ /g' | cut -d'"' -f 2)
    if [ -z "${MAINTAINER}" ]; then
        ReportWarning "dockerfile" "No maintainer found. Unclear who created this file."
    else
        Display --indent 2 --text "Maintainer" --result "${MAINTAINER}"
    fi

    ENTRYPOINT=$(grep "^ENTRYPOINT" ${AUDIT_FILE} | cut -d' ' -f2 )
    if [ -z "${ENTRYPOINT}" ]; then
        ReportWarning "dockerfile" "No ENTRYPOINT defined in Dockerfile."
    else
        Display --indent 2 --text "ENTRYPOINT" --result "${ENTRYPOINT}"
    fi

    FIND=$(grep "^CMD" ${AUDIT_FILE} | cut -d' ' -f2 )
    if [ -z "${FIND}" ]; then
        ReportWarning "dockerfile" "No CMD defines in Dockerfile."
    else
        CMD=$(echo ${FIND})
        Display --indent 2 --text "CMD" --result "${CMD}"
    fi

    FIND=$(grep "^USER" ${AUDIT_FILE} | cut -d' ' -f2 )
    if [ -z "${FIND}" ]; then
        ReportWarning "dockerfile" "No user declared in Dockerfile. Container will execute command as root"
    else
        USER=$(echo ${FIND})
        Display --indent 2 --text "User" --result "${USER}"
    fi
#
##################################################################################################
#
    InsertSection "${SECTION_SOFTWARE}"

    case $PKGMGR in
    "apt")
        FIND=$(grep -E "apt-get(.*) install" ${AUDIT_FILE})
        if [ ! "${FIND}" = "" ]; then
            LogText "Found installation via apt-get"
        else
            LogText "No installations found via apt-get"
        fi
        ;;
     "apk")
        FIND=$(grep -E "apk(.*) add" ${AUDIT_FILE})
        if [ ! "${FIND}" = "" ]; then
            LogText "Found installation via apk"
        else
            LogText "No installations found via apk"
        fi
        ;;
    *)
        LogText "Unknown package manager"
    ;;
    esac

    FIND=$(grep -E " (gcc|libc6-dev|make)" ${AUDIT_FILE} | grep -v "^#")
    if [ ! "${FIND}" = "" ]; then
        ReportWarning "dockerfile" "Possible development utilities found, which is not advised for production environment"
        LogText "Details: ${FIND}"
    fi

    # SSH
    FIND_OPENSSH=$(grep openssh ${AUDIT_FILE})
    if [ ! "${FIND_OPENSSH}" = "" ]; then
        Display --indent 2 --text "OpenSSH" --result "FOUND" --color RED
        ReportSuggestion "dockerfile" "Don't use OpenSSH in container, use 'docker exec' instead"
    fi
#
##################################################################################################
#
    InsertSection "${SECTION_DOWNLOADS}"

    FILE_DOWNLOAD=0

    LogText "Checking usage of cURL"
    FIND_CURL=$(grep curl ${AUDIT_FILE})
    if [ ! "${FIND_CURL}" = "" ]; then
        Display --indent 4 --text "Download tool" --result "curl"
        FILE_DOWNLOAD=1
    fi

    LogText "Checking usage of wget"
    FIND_WGET=$(grep wget ${AUDIT_FILE})
    if HasData "${FIND_WGET}"; then
        Display --indent 4 --text "Download tool" --result "wget"
        FILE_DOWNLOAD=1
    fi


    FIND=$(grep "^ADD http" ${AUDIT_FILE})
    if HasData "${FIND}"; then
        FILE_DOWNLOAD=1
        ReportWarning "dockerfile" "Found download of file via ADD. Unclear if the integrity of this file is checked, or file is signed"
        LogText "Details: ${FIND}"
    fi

    if [ ${FILE_DOWNLOAD} -eq 1 ]; then

        SSL_USED_FIND=$(grep -E "(https)" ${AUDIT_FILE})

        if HasData "${SSL_USED_FIND}"; then
            SSL_USED="YES"
            COLOR="GREEN"
        else
            SSL_USED="NO"
            COLOR="RED"
            ReportSuggestion "Use SSL downloads when possible to increase security (DNSSEC, HTTPS, validation of domain, avoid MitM)"
        fi
        Display --indent 2 --text "Integrity testing performed" --result "${SSL_USED}" --color ${COLOR}
        HASHING_USED=$(grep -E "(sha1sum|sha256sum|sha512sum)" ${AUDIT_FILE})
        Display --indent 2 --text "Hashing" --result "${HASHING_USED}"
        KEYS_USED=$(grep -E "(apt-key adv)" ${AUDIT_FILE}| sed 's/RUN apt-key adv//g'| sed 's/--keyserver/Key Server:/g' | sed 's/--recv/Key Value:/g')
        Display --indent 2 --text "Signing keys used" --result "${KEYS_USED}"
        Display --indent 2 --text "All downloads properly checked" --result "?"
    else
        Display --indent 2 --text "No files seems to be downloaded in this Dockerfile"

    fi
#
##################################################################################################
#
    InsertSection "${SECTION_PERMISSIONS}"

    FIND=$(grep -i "chmod 777" ${AUDIT_FILE})
    if HasData "${FIND}"; then
        ReportWarning "dockerfile" "Warning: chmod 777 found"
    fi
#
##################################################################################################
#

    # Removing temp file
    LogText "Action: Removing temporary file ${TMP_FILE}"
    if [ -f ${TMP_FILE} ]; then
        rm -f ${TMP_FILE}
    fi

# EOF
