Created
January 26, 2018 23:02
-
-
Save gmanfunky/5efb09c02cdbef3479bd0ca9b20acbd2 to your computer and use it in GitHub Desktop.
aws inspector install script - robust BASH
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#By installing the Amazon Inspector Agent, you agree that your use is | |
# subject to the terms of your existing AWS Customer Agreement or other | |
# agreement with Amazon Web Services, Inc. or its affiliates governing your | |
# use of AWS services. You may not install and use the | |
# Amazon Inspector Agent unless you have an account in good standing with AWS. | |
# Copyright 2016 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. | |
# Licensed under the terms of your existing AWS Customer Agreement | |
# <https://aws.amazon.com/agreement/> or other agreement with Amazon Web Services, Inc. | |
# or its affiliates governing your use of AWS services. | |
# | |
# Inspector Agent installer script to get the proper package installed. | |
# Version: 1.0.1668.0 | |
# For debugging, uncomment this line: | |
#set -eux | |
###GET_INSTALL_FUNCTIONS### | |
#!/bin/bash | |
#functions | |
function in_array() { | |
local haystack=${1}[@] | |
local needle=${2} | |
for i in ${!haystack}; do | |
if [[ ${i} == ${needle} ]]; then | |
return 0 | |
fi | |
done | |
return 1 | |
} | |
function exit_run_once { | |
local pidfile=${1} | |
local exitcode=${2} | |
rm -f $pidfile | |
exit $exitcode | |
} | |
function init_run_once { | |
local pidfile=${1} | |
local pid_creation_code=1 | |
if [[ -f $pidfile ]]; then | |
local pid=$(cat $pidfile) | |
ps -p $pid > /dev/null 2>&1 | |
if [[ $? -eq 0 ]]; then | |
echo "AWS Agent is already installing or updating with pid ${pid}. Exiting..." | |
exit 0 | |
else # assume stale pidfile | |
echo $$ > $pidfile | |
pid_creation_code=$? | |
fi | |
else # There a theoretical race condition right here, but our cron does not spawn twice within a fractional second or even a minute, ever. | |
echo $$ > $pidfile | |
pid_creation_code=$? | |
fi | |
if [[ $pid_creation_code -ne 0 ]]; then | |
echo "Could not create PID file: $pidfile." | |
exit 1 | |
fi | |
} | |
#This function expects at least 2 arguments: | |
# $1 - must be 'report_only' or 'report_and_exit', | |
# if this argument equals to 'report_only' then this function will only report status | |
# if this argument equals to 'report_and_exit' then it will it report status and exit | |
# otherwise scrip will exit with error code 129 | |
# $2 - status code | |
# $3 - (optional) args | |
function report_status_and_exit_if_requested() { | |
local action="nil" | |
if [[ $# -le 1 ]]; then | |
echo "no arguments has been passed... When expected at least two" | |
exit 129 | |
fi | |
if [[ $1 != "report_only" && $1 != "report_and_exit" ]]; then | |
echo "invalid first argument (action): '${1}', when expecting 'report_only' or 'report_and_exit'" | |
exit 129 | |
fi | |
action=$1 | |
local result_param="nil" | |
local result="nil" | |
if [[ $# > 2 ]]; then | |
result_param=$3 | |
fi | |
result=$2 | |
#if inventory url is defined then start publishing | |
if [[ ! -z ${AGENT_METRICS_URL} ]]; then | |
${CURL} --head "${AGENT_METRICS_URL}&x-op=${OP}&x-result=${result}&x-result-param=${result_param}" | |
else | |
echo "AWS Agent Inventory URL is not yet defined." | |
fi | |
echo "Script exited with status code ${result} ${result_param}" | |
if [[ "${action}" = "report_and_exit" ]]; then | |
if [[ "${result}" = "SUCCESS" ]]; then | |
exit 0 | |
else | |
exit 1 | |
fi | |
fi | |
} | |
function report_status() { | |
report_status_and_exit_if_requested "report_only" "$@" | |
} | |
function handle_status() { | |
report_status_and_exit_if_requested "report_and_exit" "$@" | |
} | |
function download_and_verify_sig() { | |
local download_url=$1 | |
local download_file_name=$2 | |
if [[ -z "${PUBKEY_FILE}" || -z "${SECURE_TMP_DIR}" || ! -d "${SECURE_TMP_DIR}" ]]; then | |
handle_status "SANITY_CHECK_FAILURE" "SECURE_TMP_DIR" | |
fi | |
echo "PUBKEY_FILE: ${SECURE_TMP_DIR}/${PUBKEY_FILE}" | |
if [[ -z "${SECURE_TMP_DIR}/${PUBKEY_FILE}" || ! -s "${SECURE_TMP_DIR}/${PUBKEY_FILE}" ]]; then | |
handle_status "SANITY_CHECK_FAILURE" "PUBKEY_FILE" | |
fi | |
#get the awsagent inventory file | |
${CURL} -o "${SECURE_TMP_DIR}/${download_file_name}" "${download_url}" | |
if [[ $? -ne 0 ]]; then | |
echo "Failed to download the ${download_file_name} from ${download_url}" | |
handle_status "FILE_DOWNLOAD_ERROR" "${download_file_name}" | |
fi | |
#get the awsagent inventory signature | |
${CURL} -o "${SECURE_TMP_DIR}/${download_file_name}.sig" "${download_url}.sig" | |
if [[ $? -ne 0 ]]; then | |
echo "Failed to download the ${download_file_name} signature from ${download_url}.sig" | |
handle_status "FILE_DOWNLOAD_ERROR" "${download_file_name}.sig" | |
fi | |
gpg_results=$( gpg -q --no-default-keyring --keyring "${SECURE_TMP_DIR}/${PUBKEY_FILE}" --verify "${SECURE_TMP_DIR}/${download_file_name}.sig" "${SECURE_TMP_DIR}/${download_file_name}" 2>&1 ) | |
if [[ $? -eq 0 ]]; then | |
echo "Validated ${download_file_name} signature with: $(echo "${gpg_results}" | grep -i fingerprint)" | |
else | |
echo "Error validating signature of ${download_file_name}, terminating. Please contact AWS Support." | |
echo ${gpg_results} | |
handle_status "SIGNATURE_MISMATCH" "${download_file_name}" | |
fi | |
} | |
function get_signature_timestamp() { | |
local download_file_name=$1 | |
SIGNATURE_TIMESTAMP="$(gpg --list-packets "${SECURE_TMP_DIR}/${download_file_name}.sig" 2>/dev/null | egrep 'version .* created' | head -n 1 | sed -e 's/.* created \([0-9]\{10\}\), .*/\1/')" | |
} | |
function verify_signature_timestamp() { | |
local previous_timestamp=$1 | |
local signature_timestamp=$2 | |
# SANITY CHECKS | |
# date --date='@1470000000' ==> Sun Jul 31 21:20:00 UTC 2016 | |
# date --date='@2000000000' ==> Wed May 18 03:33:20 UTC 2033 | |
if [[ -z "${previous_timestamp}" || -z "${signature_timestamp}" ]]; then | |
echo "Missing timestamp." | |
return 2 | |
fi | |
if [[ "${previous_timestamp}" -lt 1470000000 || "${previous_timestamp}" -gt 2000000000 ]]; then | |
echo "Invalid previous timestamp." | |
return 3 | |
fi | |
if [[ "${signature_timestamp}" -lt 1470000000 || "${signature_timestamp}" -gt 2000000000 ]]; then | |
echo "Invalid signature timestamp." | |
return 4 | |
fi | |
# We have two valid timestamps -- the new one should excede the old | |
if [[ "${signature_timestamp}" -ge "${previous_timestamp}" ]]; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
function package_install() { | |
local package_path=$1 | |
local new_version=$2 | |
local existing_version=$3 | |
local rv=0 | |
if [[ -z ${package_path} || -z ${new_version} || -z ${existing_version} ]]; then | |
handle_status "SANITY_CHECK_FAILURE" "PACKAGE_INSTALLATION" | |
fi | |
local package_name=$(basename ${package_path}) | |
#calculate version strings | |
local new_version_str=$(printf "%06d%06d%06d%06d" $(echo ${new_version} | sed 's/\./ /g')) | |
local existing_version_str=$(printf "%06d%06d%06d%06d" $(echo ${existing_version} | sed 's/\./ /g')) | |
if [[ "${package_name}" =~ \.deb$ ]] && which apt-get 2>/dev/null; then | |
echo "Installing with dpkg..." | |
apt-get update | |
dpkg --force-overwrite -i "${package_path}" | |
apt-get --fix-broken -y install --no-remove | |
rv="$?" | |
elif [[ "${package_name}" =~ \.rpm$ ]] && which yum 2>/dev/null; then | |
echo "Installing with yum..." | |
if [[ ${new_version_str} == ${existing_version_str} ]]; then | |
yum reinstall -y "${package_path}" | |
elif [[ ${new_version_str} > ${existing_version_str} ]]; then | |
yum install -y "${package_path}" | |
elif [[ ${new_version_str} < ${existing_version_str} ]]; then | |
yum downgrade -y "${package_path}" | |
else | |
handle_status "SANITY_CHECK_FAILURE" "PACKAGE_VERSION_RPM" | |
fi | |
#rpm -fUvh --force --oldpackage "${package_path}" | |
rv="$?" | |
else | |
echo "No supported package managers are installed." | |
handle_status "MISSING_PACKAGE_MANAGER" "${DIST_TYPE}_${package_name}" | |
fi | |
if [[ ${rv} -ne 0 ]]; then | |
handle_status "PACKAGE_INSTALLATION_ERROR" "${package_name}" | |
fi | |
} | |
function verify_hash_package() { | |
local checked_package=$1 | |
local expected_package_hash=$2 | |
if [[ ! -s ${checked_package} || -z ${expected_package_hash} ]]; then | |
handle_status "SANITY_CHECK_FAILURE" "HASH_VERIFICATION_ERROR" | |
fi | |
# Check the hash of the package downloaded vs. the hash of the package in the index | |
local actual_package_hash=$( sha256sum ${checked_package} | cut -f1 -d' ') | |
if [[ "${actual_package_hash}" != "${expected_package_hash}" ]]; then | |
echo "Package sha256 hash does not match expected package hash from package inventory." | |
handle_status "HASH_MISMATCH" "${checked_package}" | |
else | |
echo "Validated agent package sha256 hash matches expected value." | |
fi | |
} | |
function download_and_install_kernel_module_package() { | |
local km_version_detail=$1 | |
local new_km_version="${NEW_KM_VERSION}" | |
local existing_km_version="${EXISTING_KM_VERSION}" | |
if [[ -z "${new_km_version}" || -z "${km_version_detail}" || -z "${existing_km_version}" ]]; then | |
echo "New Kernel module Version: ${new_km_version} Existing Kernel module version: ${existing_km_version} & Kernel Version Detail: ${km_version_detail} is invalid" | |
handle_status "SANITY_CHECK_FAILURE" "INSTALL_KM_PACKAGE" | |
fi | |
local km_package_url=$( echo "${km_version_detail}" | cut -f5 -d'|' ) | |
local km_package_hash=$(echo "${km_version_detail}" | cut -f4 -d'|' ) | |
local km_package_name=$( echo "${km_version_detail}" | cut -f3 -d'|' ) | |
if [[ -z "${km_package_url}" || -z "{km_package_name}" || -z "{km_package_hash}" ]]; then | |
echo "Kernel Package URL: ${km_package_url} , Kernel Package Hash: ${km_package_hash} & Kernel package name: ${km_package_name} is invalid." | |
handle_status "PARSE_ERROR" "KERNEL_MODULE_PACKAGE_${UNIQ_OS_ID}" | |
fi | |
${CURL} -o "${SECURE_TMP_DIR}/${km_package_name}" "${km_package_url}" | |
if [[ $? -ne 0 ]]; then | |
echo "Failed to download the kernel package from ${km_package_url}" | |
handle_status "FILE_DOWNLOAD_ERROR" "${km_package_name}" | |
fi | |
# Check the hash of the package downloaded vs. the hash of the package in the index | |
verify_hash_package "${SECURE_TMP_DIR}/${km_package_name}" "${km_package_hash}" | |
package_install "${SECURE_TMP_DIR}/${km_package_name}" "${new_km_version}" "${existing_km_version}" | |
} | |
function download_and_install_agent_package() { | |
local agent_package_name=$1 | |
local agent_package_url=$2 | |
local expected_agent_package_hash=$3 | |
local new_agent_version="${NEW_AGENT_VERSION}" | |
local existing_agent_version="${EXISTING_AGENT_VERSION}" | |
if [[ -z "${new_agent_version}" || -z "${existing_agent_version}" || -z "${expected_agent_package_hash}" ]]; then | |
handle_status "SANITY_CHECK_FAILURE" "INSTALL_AGENT_PACKAGE" | |
fi | |
if [[ -z "${agent_package_url}" || -z "${agent_package_name}" || -z "${expected_agent_package_hash}" ]]; then | |
echo "Agent package URL: ${agent_package_url} or Agent Package Hash: ${expected_agent_package_hash} or Agent package name : ${agent_package_name} is invalid." | |
handle_status "PARSE_ERROR" "AGENT_INSTALL_PACKAGE_${UNIQ_OS_ID}" | |
fi | |
# Download the package for the proper version. | |
${CURL} -o ${SECURE_TMP_DIR}/${agent_package_name} ${agent_package_url} | |
if [[ ! -s ${SECURE_TMP_DIR}/${agent_package_name} ]]; then | |
echo "Failed to download package from the path ${agent_package_url}." | |
handle_status "FILE_DOWNLOAD_ERROR" "${agent_package_name}" | |
fi | |
# Check the hash of the package downloaded vs. the hash of the package in the index | |
verify_hash_package "${SECURE_TMP_DIR}/${agent_package_name}" "${expected_agent_package_hash}" | |
package_install "${SECURE_TMP_DIR}/${agent_package_name}" "${new_agent_version}" "${existing_agent_version}" | |
} | |
function lowercase(){ | |
echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/" | |
} | |
function uppercase(){ | |
echo "$1" | sed "y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/" | |
} | |
function get_os_info () { | |
OS=`lowercase \`uname\`` | |
KERNEL=`callUname -r` | |
MACH=`uname -m` | |
KERNEL_GROUP=$(echo $KERNEL | cut -f1-2 -d'.') | |
if [ "${OS}" = "linux" ] ; then | |
# Figure out which OS we are running on | |
if [ -f /etc/os-release ]; then | |
source /etc/os-release | |
DIST_TYPE=$ID | |
DIST=$NAME | |
REV=$VERSION_ID | |
elif [ -f /usr/lib/os-release ]; then | |
source /usr/lib/os-release | |
DIST_TYPE=$ID | |
DIST=$NAME | |
REV=$VERSION_ID | |
elif [ -f /etc/centos-release ]; then | |
DIST_TYPE='CentOS' | |
DIST=`cat /etc/centos-release |sed s/\ release.*//` | |
REV=`cat /etc/centos-release | sed s/.*release\ // | sed s/\ .*//` | |
elif [ -f /etc/redhat-release ]; then | |
DIST_TYPE='RedHat' | |
DIST=`cat /etc/redhat-release |sed s/\ release.*//` | |
REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//` | |
elif [ -f /etc/system-release ]; then | |
if grep "Amazon Linux AMI" /etc/system-release; then | |
DIST_TYPE='amzn' | |
fi | |
DIST=`cat /etc/system-release |sed s/\ release.*//` | |
REV=`cat /etc/system-release | sed s/.*release\ // | sed s/\ .*//` | |
elif [ -f /etc/SuSE-release ] ; then | |
DIST_TYPE='SuSe' | |
REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //` | |
elif [ -f /etc/mandrake-release ] ; then | |
DIST_TYPE='Mandrake' | |
REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//` | |
elif [ -f /etc/debian_version ] ; then | |
DIST_TYPE='Debian' | |
DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F= '{ print $2 }'` | |
REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F= '{ print $2 }'` | |
fi | |
if [ -f /etc/UnitedLinux-release ] ; then | |
DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]" | |
fi | |
fi | |
if [ "${OS}" == "darwin" ]; then | |
OS=mac | |
fi | |
DIST_TYPE=`lowercase $DIST_TYPE` | |
UNIQ_OS_ID="${DIST_TYPE}-${KERNEL}-${MACH}" | |
UNIQ_PLATFORM_ID="${DIST_TYPE}-${KERNEL_GROUP}." | |
OS_FULL_REVISION="${REV}" | |
OS_MAIN_REVISION=$(echo "${DIST_TYPE}.${REV}" | cut -f1-2 -d'.') | |
if [[ -z "${DIST}" || -z "${DIST_TYPE}" ]]; then | |
echo "Unsupported distribution: ${DIST} and distribution type: ${DIST_TYPE}" | |
exit 1 | |
fi | |
} | |
function callUname () { | |
local args=("$@") | |
echo "$(uname ${args})" | |
} | |
function executeEnvironmentCleanup() { | |
echo "Installation script completed successfully." | |
} | |
function getAgentStatus() { | |
local agent_status=$( ${AGENT_EXEC} status ) | |
echo "Agent status completed with code:$?" | |
echo "${agent_status}" | |
} | |
function usage() { | |
executing_script=$(basename "${BASH_SOURCE[0]}") | |
echo "Usage sudo ${executing_script}< options > " | |
echo "Options:" | |
echo "-u [ true | false ] Automatically update Aws Agent when versions become available. Applicable only during first installation." | |
} | |
# customer may have somehow disabled agent. | |
# an update shouldn't override that decision | |
function check_awsagent_condition() { | |
if [[ $(basename "${BASH_SOURCE[0]}" ) = "update" ]]; then # otherwise this is a fresh install | |
if [[ ! -f /var/run/awsagent.pid ]]; then | |
echo "/var/run/awsagent.pid not found. Updater only runs when agent is expected to be running." | |
handle_status "SUCCESS" "AGENT_NOT_RUNNING_NO_UPDATE" | |
fi | |
fi | |
} | |
# | |
#Search AgentManifest file or version file | |
# - Search agent manifest file by ${DIST_TYPE}.${OS_FULL_REVISION} | |
# - If not found then search agent manifest by ${DIST_TYPE}.${OS_MAIN_REVISION} | |
# - If not found then search agent version by ${UNIQ_PLATFORM_ID} | |
#Load row_value and parsing out following global variables: | |
# - AGENT_PACKAGE_URL | |
# - EXPECTED_AGENT_PACKAGE_HASH | |
# - NEW_AGENT_VERSION | |
function searchAgentManifest() { | |
#first check the full version... | |
local os_search_key="${DIST_TYPE}.${OS_FULL_REVISION}" | |
local path_to_agent_manifest=$1 | |
local path_to_agent_version=$2 | |
local row_value=$( grep -m 1 -i "${os_search_key}" "${path_to_agent_manifest}" ) | |
AGENT_PACKAGE_URL=$( echo "${row_value}" | cut -f3 -d' ' ) | |
EXPECTED_AGENT_PACKAGE_HASH=$( echo "${row_value}" | cut -f2 -d' ') | |
NEW_AGENT_VERSION=$( echo "${row_value}" | cut -f7 -d'/' ) | |
if [[ -z "${row_value}" ]]; then | |
# there is no entry for full version... searching for MainVersion: | |
os_search_key="${DIST_TYPE}.${OS_MAIN_REVISION}" | |
row_value=$( grep -m 1 -i "${os_search_key}" "${path_to_agent_manifest}" ) | |
AGENT_PACKAGE_URL=$( echo "${row_value}" | cut -f3 -d' ' ) | |
EXPECTED_AGENT_PACKAGE_HASH=$( echo "${row_value}" | cut -f2 -d' ' ) | |
NEW_AGENT_VERSION=$( echo "${row_value}" | cut -f7 -d'/' ) | |
if [[ -z "${row_value}" ]]; then | |
echo "using legacy VERSION file" | |
row_value=$( grep -m 1 -i "${UNIQ_PLATFORM_ID}" "${path_to_agent_version}" ) | |
AGENT_PACKAGE_URL=$( echo "${row_value}" | cut -f4 -d' ' ) | |
EXPECTED_AGENT_PACKAGE_HASH=$( echo "${row_value}" | cut -f3 -d' ' ) | |
NEW_AGENT_VERSION=$( echo "${row_value}" | cut -f7 -d'/' ) | |
if [[ -z "${row_value}" ]]; then | |
echo "Failed to find an inspector agent package for this OS:${UNIQ_PLATFORM_ID}." | |
handle_status "MISSING_AGENT_PLATFORM" "$os_search_key" | |
fi | |
fi | |
fi | |
} | |
if [[ $(whoami) != "root" ]]; then | |
echo "Script is run as $(whoami). Please run as root" | |
exit 1 | |
fi | |
PIDFILE="/var/run/awsagent_install_or_update.PID" | |
init_run_once $PIDFILE | |
#Create a Secure temp directory where we get all files and then use them. | |
SECURE_TMP_DIR=$(mktemp -d /tmp/awsagent.XXXXXXXX) | |
# Perform Cleanup upon exit | |
trap "EXIT_CODE=$?; rm -f ${SECURE_TMP_DIR}/*; rmdir ${SECURE_TMP_DIR}; exit_run_once $PIDFILE $EXIT_CODE" EXIT | |
#define constants | |
declare -a SUPPORTED_REGIONS=("us-east-1" "us-west-1" "us-west-2" "ap-northeast-1" "eu-west-1" "ap-northeast-2" "ap-southeast-2" "ap-south-1" "eu-central-1" "us-east-2") | |
ROOTDIRECTORY="$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )" | |
AGENT_INVENTORY_FILE="AWS_AGENT_INVENTORY" | |
AGENT_MANIFEST_FILE="AGENT_MANIFEST" | |
AGENT_VERSION_FILE="VERSION" | |
AGENT_CFG_KEY="agent.cfg" | |
PUBKEY_FILE="inspector.gpg" | |
CRON_UPDATE_AGENT=true | |
OP=install | |
CURL="curl -s --fail --retry 5 --max-time 30 " | |
#define inspector constants | |
AGENT_CONFIG_FILE=/opt/aws/awsagent/etc/agent.cfg | |
AGENT_EXEC=/opt/aws/awsagent/bin/awsagent | |
AGENT_KMOD=/opt/aws/awsagent/kmods/amznmon64.ko | |
AGENT_KMOD_DIR=/opt/aws/awsagent/kmods | |
AGENT_KMOD_NAME=amznmon64.ko | |
AGENT_INIT_SCRIPT="/etc/init.d/awsagent" | |
AGENT_ENV_CONFIG="/etc/init.d/awsagent.env" | |
INSTALL_CONFIG_FILE=/opt/aws/awsagent/etc/install.cfg | |
#Domain specific configuration | |
INSTALLER_EXT="" | |
BUCKET="aws-agent.us-west-2" | |
#check if environment environment file exists and if so source it | |
if [[ -f "${AGENT_ENV_CONFIG}" ]]; then | |
source "${AGENT_ENV_CONFIG}" | |
fi | |
#check if environment override file exists and if so source it | |
if [[ -f "${ROOTDIRECTORY}/environmentOverride" ]]; then | |
source "${ROOTDIRECTORY}/environmentOverride" | |
fi | |
#handle installer options | |
while getopts ":u:" opt; do | |
case $opt in | |
u) | |
echo "Forced update specified as argument is : $OPTARG" | |
if [[ $(basename "${BASH_SOURCE[0]}" ) = "install" ]]; then | |
CRON_UPDATE_AGENT=$OPTARG | |
fi | |
;; | |
\?) | |
echo "Invalid option: -$OPTARG" | |
usage | |
exit 1 | |
;; | |
:) | |
echo "Option -$OPTARG requires an argument." | |
usage | |
exit 1 | |
;; | |
esac | |
done | |
#call the os info function to get details | |
get_os_info | |
check_awsagent_condition | |
KERNEL_VERSION=`callUname -r` | |
if [[ -z "${KERNEL_VERSION}" ]]; then | |
handle_status "NO_KERNEL_VERSION" | |
fi | |
KERNEL_GROUP=$(echo "${KERNEL_VERSION}" | cut -f 1-2 -d'.') | |
KERNEL_VERSION_WO_ARCH=$(basename ${KERNEL_VERSION} .x86_64) | |
echo "Distribution of the machine is ${DIST}." | |
echo "Distribution type of the machine is ${DIST_TYPE}." | |
echo "Revision of the distro is ${REV}." | |
echo "Kernel version of the machine is ${KERNEL_VERSION}." | |
#gather all meta data information | |
METADATA_AZ=$( ${CURL} http://169.254.169.254/latest/meta-data/placement/availability-zone) | |
METADATA_INSTANCE_TYPE=$( ${CURL} http://169.254.169.254/latest/meta-data/instance-type) | |
METADATA_REGION=$( echo $METADATA_AZ | sed -e 's/[a-z]*$//' ) | |
if [[ -n "${METADATA_REGION}" ]]; then | |
REGION=${METADATA_REGION} | |
else | |
echo "No region information was obtained." | |
handle_status "NO_REGION_INFO" | |
fi | |
#check if the obtained region is supported by inspector | |
if in_array SUPPORTED_REGIONS "${REGION}"; then | |
echo "$(hostname -f) is an EC2 instance reporting region as ${REGION}." | |
else | |
echo "Aws Agent is only supported in ${SUPPORTED_REGIONS[@]}" | |
handle_status "UNSUPPORTED_REGION" ${REGION} | |
fi | |
#Base url formation | |
if [[ -z "${INSTALLER_EXT}" ]]; then | |
BUCKET="aws-agent.${REGION}" | |
fi | |
BASE_URL="https://s3.dualstack.${REGION}.amazonaws.com/${BUCKET}" | |
#check existing agent status to get the version information of the running agent | |
if [[ "${DIST_TYPE}" = "ubuntu" ]]; then | |
EXISTING_AGENT_VERSION=$(dpkg-query -W -f='${VERSION}' "awsagent" | cut -f1 -d'-') | |
rv=${PIPESTATUS[0]} | |
else | |
EXISTING_AGENT_VERSION=$(rpm -qa "AwsAgent" --queryformat '%{VERSION}') | |
rv=$? | |
fi | |
echo "Check for existing AwsAgent completed with error code:${rv}" | |
if [[ -z "${EXISTING_AGENT_VERSION}" ]]; then | |
EXISTING_AGENT_VERSION="0.0.0.0" | |
fi | |
echo "Existing version of agent installed is ${EXISTING_AGENT_VERSION}." | |
#get existing kernel module version based on kernel version in machine | |
if [[ "${DIST_TYPE}" = "ubuntu" ]]; then | |
EXISTING_KM_VERSION=$(dpkg-query -W -f='${VERSION}' "awsagentkernelmodule-${KERNEL_VERSION_WO_ARCH}" | cut -f1 -d'-') | |
rv=${PIPESTATUS[0]} | |
else | |
EXISTING_KM_VERSION=$(rpm -qa "AwsAgentKernelModule__${DIST_TYPE}__${KERNEL_VERSION_WO_ARCH}" --queryformat '%{VERSION}') | |
rv=$? | |
fi | |
echo "Check for existing AwsAgentKernelModule completed with error code:${rv}" | |
if [[ -z "${EXISTING_KM_VERSION}" ]]; then | |
EXISTING_KM_VERSION="0.0.0.0" | |
fi | |
echo "Existing version of kernel module installed is ${EXISTING_KM_VERSION}." | |
#Agent and Kernel Param | |
AGENT_ID_PARAM="x-installer-version=1.0.1668.0&x-existing-version=${EXISTING_AGENT_VERSION}&x-uniq-os-id=${UNIQ_OS_ID}&x-instance-type=${METADATA_INSTANCE_TYPE}" | |
KERNEL_ID_PARAM="x-existing-km-version=${EXISTING_KM_VERSION}" | |
AGENT_INVENTORY_URL="${BASE_URL}/linux/latest/${AGENT_INVENTORY_FILE}" | |
AGENT_METRICS_URL="${AGENT_INVENTORY_URL}?${AGENT_ID_PARAM}&${KERNEL_ID_PARAM}" | |
if [[ -n "${BASH_SOURCE[0]}" && $(basename "${BASH_SOURCE[0]}" ) = "update" ]]; then | |
OP=update | |
if [[ ! -f "${AGENT_EXEC}" ]]; then | |
echo "Attempting update, but binary does not exist. Please run 'install' instead." | |
handle_status "WRONG_EXEC_MODE" "update" | |
fi | |
if [[ -s "${INSTALL_CONFIG_FILE}" ]]; then | |
echo "Detected running as updater script, loading saved configuration from ${INSTALL_CONFIG_FILE}..." | |
source ${INSTALL_CONFIG_FILE} | |
fi | |
COLLECT="$( getAgentStatus | grep -Ei "Collecting\s*:" | sed -re 's/Collecting\s*:\s*//i' )" | |
if [[ "${COLLECT}" = "true" ]]; then | |
echo "Agent is actively colecting at this time, cannot update agent while it is collecting data!" | |
handle_status "AGENT_RUNNING_ASSESSMENT" | |
elif [[ "${CRON_UPDATE_AGENT}" = "false" ]]; then | |
echo "Update is not permitted according to configuration parameter mentioned as argument." | |
handle_status "CRON_UPDATE_AGENT_DISABLED" | |
else | |
echo "Agent is inactive, continuing to update..." | |
fi | |
fi | |
# Check that the dir exists and is owned by our euid (root) | |
if [[ ! -O "${SECURE_TMP_DIR}" ]]; then | |
echo "Unable to create secure temporary directory ${SECURE_TMP_DIR}." | |
handle_status "TMP_DIR_ERROR" | |
fi | |
chmod 700 "${SECURE_TMP_DIR}" | |
#get the public key | |
${CURL} -o "${SECURE_TMP_DIR}/${PUBKEY_FILE}" "${BASE_URL}/linux/latest/${PUBKEY_FILE}" | |
if [[ $? != 0 ]]; then | |
echo "Failed to download public key from the path ${BASE_URL}/linux/latest/${PUBKEY_FILE}" | |
handle_status "FILE_DOWNLOAD_ERROR" "${PUBKEY_FILE}" | |
fi | |
#get the awsagent inventory file | |
download_and_verify_sig "${AGENT_INVENTORY_URL}" "${AGENT_INVENTORY_FILE}" | |
#send start agent census metric | |
${CURL} --head "${AGENT_METRICS_URL}&x-op=${OP}&x-result=begin" | |
AGENT_MANIFEST_URL="$(grep "${AGENT_MANIFEST_FILE}" "${SECURE_TMP_DIR}/${AGENT_INVENTORY_FILE}" | grep -v "${AGENT_MANIFEST_FILE}.sig" | cut -f2 -d' ')" | |
AGENT_VERSION_URL="$(grep "${AGENT_VERSION_FILE}" "${SECURE_TMP_DIR}/${AGENT_INVENTORY_FILE}" | grep -v "${AGENT_VERSION_FILE}.sig" | cut -f2 -d' ')" | |
if [[ -z "${AGENT_MANIFEST_URL}" && -z "${AGENT_VERSION_URL}" ]]; then | |
echo "Agent manifest file URL was not obtained. Please contact AWS support." | |
handle_status "PARSE_ERROR" "${AGENT_MANIFEST_FILE} and ${AGENT_VERSION_FILE} are both empty" | |
fi | |
echo "AGENT_MANIFEST_URL: ${AGENT_MANIFEST_URL}" | |
echo "AGENT_VERSION_URL: ${AGENT_VERSION_URL}" | |
download_and_verify_sig "${AGENT_MANIFEST_URL}" "${AGENT_MANIFEST_FILE}" | |
download_and_verify_sig "${AGENT_VERSION_URL}" "${AGENT_VERSION_FILE}" | |
searchAgentManifest "${SECURE_TMP_DIR}/${AGENT_MANIFEST_FILE}" "${SECURE_TMP_DIR}/${AGENT_VERSION_FILE}" | |
echo "AGENT_PACKAGE_URL: ${AGENT_PACKAGE_URL}" | |
echo "EXPECTED_AGENT_PACKAGE_HASH: ${EXPECTED_AGENT_PACKAGE_HASH}" | |
echo "NEW_AGENT_VERSION:${NEW_AGENT_VERSION}" | |
if [[ -z "${NEW_AGENT_VERSION}" ]]; then | |
handle_status "SANITY_CHECK_FAILURE" "NEW_AGENT_VERSION" | |
fi | |
DIST_TYPE_UPPERCASE=`uppercase "${DIST_TYPE}"` | |
# | |
# Check if we need to install agent | |
# | |
need_install_agent=true | |
if [[ $(basename "${BASH_SOURCE[0]}" ) == "update" ]]; then | |
if [[ "${EXISTING_AGENT_VERSION}" == "${NEW_AGENT_VERSION}" ]]; then | |
need_install_agent=false | |
fi | |
fi | |
# | |
# Check if we need to install kernel module | |
# | |
need_install_kernel="true" | |
is_kernel_missing="false" | |
KERNEL_MANIFEST_VERSION="$(grep "km_version" "${SECURE_TMP_DIR}/${AGENT_INVENTORY_FILE}" | cut -f2 -d' ')" | |
if [[ -z "${KERNEL_MANIFEST_VERSION}" ]]; then | |
echo "Warning: No supported kernel module is available in this installation package for ${UNIQ_OS_ID}" | |
echo "Inspector rules packages that require the kernel module cannot be used for assessments. " | |
echo "Agent installation will continue without support for kernel module." | |
need_install_kernel="false" | |
is_kernel_missing="true" | |
report_status "PARSE_ERROR" "KERNEL_MANIFEST_VERSION" | |
else | |
KERNEL_MANIFEST_VERSION_3DIGITS=$(echo "${KERNEL_MANIFEST_VERSION}" | cut -f 1-3 -d".") | |
KERNEL_MANIFEST_FILE_NAME="KM_MANIFEST_${DIST_TYPE_UPPERCASE}_${KERNEL_GROUP}_${KERNEL_MANIFEST_VERSION_3DIGITS}.txt" | |
KERNEL_MANIFEST_URL="${BASE_URL}/kernel-modules/${KERNEL_MANIFEST_FILE_NAME}" | |
download_and_verify_sig "${KERNEL_MANIFEST_URL}" "${KERNEL_MANIFEST_FILE_NAME}" | |
KERNEL_MODULE_VERSION_DETAIL=$( grep -i "${KERNEL_VERSION_WO_ARCH}" "${SECURE_TMP_DIR}/${KERNEL_MANIFEST_FILE_NAME}" | tail -n -1 ) | |
if [[ -z "${KERNEL_MODULE_VERSION_DETAIL}" ]]; then | |
echo "Warning: Kernel module failed to install or failed to find an inspector kernel module package for this OS: ${UNIQ_OS_ID}" | |
echo "Inspector rules packages that require the kernel module cannot be used for assessments. Agent installation will continue without support for kernel module" | |
need_install_kernel="false" | |
is_kernel_missing="true" | |
report_status "MISSING_KERNEL_VERSION" "${UNIQ_OS_ID}" | |
fi | |
NEW_KM_VERSION=$( echo "${KERNEL_MODULE_VERSION_DETAIL}" | cut -f2 -d'|' ) | |
if [[ -z "${NEW_KM_VERSION}" ]]; then | |
need_install_kernel="false" | |
is_kernel_missing="true" | |
echo "Warning: No supported kernel module is available in this installation package for ${UNIQ_OS_ID}" | |
echo "Inspector rules packages that require the kernel module cannot be used for assessments. Agent installation will continue without support for kernel module." | |
report_status "PARSE_ERROR" "NEW_KM_VERSION" | |
fi | |
# | |
# We will not install kernel version only if | |
# kernel avaiable to install and kernel version didn't changed and no need to install agent | |
# | |
if [[ "${EXISTING_KM_VERSION}" == "${NEW_KM_VERSION}" && "${need_install_agent}" == "false" ]]; then | |
need_install_kernel="false" | |
is_kernel_missing="false" | |
fi | |
fi | |
if [[ "${need_install_kernel}" == "true" ]]; then | |
download_and_install_kernel_module_package "${KERNEL_MODULE_VERSION_DETAIL}" | |
fi | |
if [[ "${need_install_agent}" == "true" ]]; then | |
if [[ "${DIST_TYPE}" = "ubuntu" ]]; then | |
AGENT_PACKAGE_NAME="awsagent.deb" | |
else | |
AGENT_PACKAGE_NAME="AWSAgent.rpm" | |
fi | |
echo "AGENT_PACKAGE_NAME:${AGENT_PACKAGE_NAME}" | |
download_and_install_agent_package ${AGENT_PACKAGE_NAME} ${AGENT_PACKAGE_URL} ${EXPECTED_AGENT_PACKAGE_HASH} | |
umask 077 | |
# Save the config so we can update with the same parameters | |
[[ -f ${INSTALL_CONFIG_FILE} ]] && mv -f ${INSTALL_CONFIG_FILE} ${INSTALL_CONFIG_FILE}.old | |
echo "AGENT_CFG_KEY=${AGENT_CFG_KEY}" >> ${INSTALL_CONFIG_FILE} | |
echo "CRON_UPDATE_AGENT=${CRON_UPDATE_AGENT}" >> ${INSTALL_CONFIG_FILE} | |
fi | |
if [[ "${need_install_kernel}" == "true" ]]; then | |
AGENT_KMOD_KERNEL_SPECIFIC="${AGENT_KMOD_DIR}/${NEW_KM_VERSION}/${AGENT_KMOD_NAME}.${KERNEL_VERSION}" | |
if [[ -f "${AGENT_KMOD_KERNEL_SPECIFIC}" ]]; then | |
cp -f "${AGENT_KMOD_KERNEL_SPECIFIC}" "${AGENT_KMOD}" | |
else | |
echo "Warning: No supported kernel module is available in this installation package for ${UNIQ_OS_ID}" | |
echo "Inspector rules packages that require the kernel module cannot be used for assessments. Agent installation will continue without support for kernel" | |
is_kernel_missing="true" | |
report_status "MISSING_KM_FILE" "${NEW_KM_VERSION}__${UNIQ_OS_ID}" | |
fi | |
fi | |
if [[ ! -f ${AGENT_CONFIG_FILE} && -f ${AGENT_CONFIG_FILE}.orig ]]; then | |
cp ${AGENT_CONFIG_FILE}.orig ${AGENT_CONFIG_FILE} | |
fi | |
RUNNING_VERSION=$( getAgentStatus | grep -Ei "Agent\s*version" | sed -re 's/Agent\s*version\s*:\s*//i' ) | |
ARSENAL_ENDPOINT=$( getAgentStatus | grep -Ei "Endpoint" | sed -re 's/Endpoint\s*:\s*//i' ) | |
#send installer end metric | |
${CURL} --head "${AGENT_METRICS_URL}&x-op=${OP}&x-result=SUCCESS&x-running-agent-version=${RUNNING_VERSION}" | |
executeEnvironmentCleanup | |
echo | |
echo "Notice:" | |
echo "By installing the Amazon Inspector Agent, you agree that your use is subject to the terms of your existing " | |
echo "AWS Customer Agreement or other agreement with Amazon Web Services, Inc. or its affiliates governing your " | |
echo "use of AWS services. You may not install and use the Amazon Inspector Agent unless you have an account in " | |
echo "good standing with AWS." | |
echo "* * *" | |
echo "Current running agent reports to arsenal endpoint: $ARSENAL_ENDPOINT" | |
echo "Current running agent reports version as: $RUNNING_VERSION" | |
echo "This install script was created to install agent version:1.0.1668.0" | |
echo "In most cases, these version numbers should be the same." | |
if [[ "${is_kernel_missing}" == "true" ]]; then | |
echo "Warning: No supported kernel module is available in this installation or kernel module failed to install" | |
echo "Inspector rules packages that require the kernel module cannot be used for assessments." | |
fi | |
echo | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment