# Copyright (c) 2018 SIOS Technology Corp. # # Confirm the setting of AWS IAM role # # LifeKeeper Linux Change history: # CR7309 05/Jan/18 ysa initial submit # CR7397 06/Feb/18 old sed support # CR7519 Need to get the EIP that the instance can get to, not all of them # exit 0 set -o pipefail DEFAULT_FILE=/etc/default/LifeKeeper if [ -z "$LKROOT" ] then PATH= . $DEFAULT_FILE LKROOT=${LKROOT:=/opt/LifeKeeper} PATH=${PATH:=$LKROOT/bin:/usr/bin:/usr/sbin:/bin:/sbin} export LKROOT PATH fi # extend log output log=${VERBOSE_AWS_ROLE_CHECK:-/dev/null} role_error () { echo "This instance does not have $1 role." exit 1 } _aws () { echo -e "---\naws $@" >> $log aws $@ 2>&1 |tee -a $log } # Note # Since aws - cli now checks the role first, there is no problem # even if the argument is incomplete. # It is necessary to fix it when the order of checking in the future changes. # EC2 ARK role check # required role # - DescribeAddress # - DescribeRouteTable # - AssociateAddress # - DisassociateAddress # - ReplaceRoute get_metadata () { local URL="http://169.254.169.254/latest/meta-data/$1" $LKROOT/bin/curl -s $URL } check_ec2 () { local region if [ -z "$1" ]; then region=`get_metadata placement/availability-zone|sed -e s/.$//` else region=$1 fi echo "region=$region" > $log local instance=`get_metadata instance-id` echo "instance=$instance" >> $log local esa=`ip link show|grep "link/ether"|head -1|sed -r "s/.*link\/ether\s(\S+)(\s.*|$)/\1/"` local vpcid=`get_metadata network/interfaces/macs/$esa/vpc-id` if [ -z "$vpcid" ]; then echo "Can't get VPC id." return 1 fi echo "vpcid=$vpcid" >> $log local meta_eni=`get_metadata network/interfaces/macs/$esa/interface-id` echo "network-interface-id (metadata)=$meta_eni" >> $log local eip _aws ec2 --region=$region --output=text describe-addresses > /dev/null 2>&1 [ $? -ne 0 ] && role_error ec2:DescribeAddresses #bug7519 - It is possible that the instance may not have an EIP eip=`aws ec2 --region=$region --output=text describe-addresses --filters Name=instance-id,Values=$instance|grep eipassoc-|head -1` _aws ec2 describe-route-tables --output=text --region=$region --filters Name=vpc-id,Values=$vpcid|grep ROUTETABLES > /dev/null 2>&1 [ $? -ne 0 ] && role_error ec2:DescribeRouteTables local rtb_id rtb_id=`aws ec2 describe-route-tables --output=text --region=$region --filters Name=vpc-id,Values=$vpcid|grep ROUTETABLES|cut -f2|head -1` echo "rtb-id=$rtb_id" >> $log local out if [ -n "$eip" ]; then # found associated address local alloc=`echo $eip|cut -d' ' -f2` local associate=`echo $eip|cut -d' ' -f3` local eni=`echo $eip|cut -d' ' -f6` echo "allocation-id=$alloc" >> $log echo "association-id=$associate" >> $log echo "network-interface-id=$eni" >> $log out=`_aws ec2 associate-address --output=text --region=$region --allocation-id $alloc --network-interface-id $eni --dry-run` echo $out|grep -q DryRunOperation || role_error ec2:AssociateAddress out=`_aws ec2 disassociate-address --output=text --region=$region --association-id $associate --dry-run` echo $out|grep -q DryRunOperation || role_error ec2:DisassociateAddress else # no associate case #bug7519 Make sure to get the instance specific Eip eip=`aws ec2 --region=$region --output=text describe-addresses --filters Name=instance-id,Values=$instance|head -1` if [ -n "$eip" ]; then local alloc=`echo $eip|cut -d' ' -f2` out=`_aws ec2 associate-address --output=text --region=$region --allocation-id $alloc --network-interface-id $meta_eni` [ $? -ne 0 ] && role_error ec2:AssociateAddress _aws ec2 disassociate-address --output=text --region=$region --association-id $out > /dev/null 2>&1 [ $? -ne 0 ] && role_error ec2:DisassociateAddress fi fi if [ -n "$rtb_id" -a -n "$meta_eni" ]; then out=`_aws ec2 replace-route --output=text --region=$region --route-table-id=$rtb_id --destination-cidr-block=0.0.0.0/32 --network-interface-id $meta_eni --dry-run` echo $out|grep -q DryRunOperation || role_error ec2:ReplaceRoute fi exit 0 } # Route53 role check # # Required role # - ListHostedZones # - ListResourceRecordSets # - ChangeResourceRecrodSets # - GetChange # # This test create lifekeeper-iam-test.[hostedzone] record. change_batch_json () { cat < $log _aws route53 --output=text list-hosted-zones > /dev/null [ $? -ne 0 ] && role_error route53:ListHostedZones local zone=`_aws route53 --output=text list-hosted-zones --query='HostedZones[*].{Id:Id,Name:Name}'` if [ -n "$1" ]; then zone=`echo "$zone"|grep $1` else zone=`echo "$zone"|head -1` fi echo "zone=$zone" >> $log if [ -z "$zone" ]; then echo "Hosted zone not found. Please add a zone." exit 1 fi local zoneid=`echo "$zone"|cut -f1` local zonename=`echo "$zone"|cut -f2` _aws route53 --output=text list-resource-record-sets --hosted-zone-id=$zoneid > /dev/null [ $? -ne 0 ] && role_error route53:ListResourceRecordSets local try for ((try=1; try <= 100; try++)); do local json=`change_batch_json "CREATE" $zonename $try` echo -e "CREATE json\n$json" >> $log echo "aws route53 --output text change-resource-record-sets --hosted-zone-id $zoneid --change-batch \"$json\"" >> $log local change=`aws route53 --output text change-resource-record-sets --hosted-zone-id $zoneid --change-batch "$json" 2>&1` local ret=$? echo $change >> $log echo $change|grep -q "CHANGEINFO" || ret=1 if [ $ret -ne 0 ]; then echo $change|grep -q "AccessDenied" && role_error route53:ChangeResourceRecordSets else break fi done if [ $ret -ne 0 ]; then echo -e "route53:ChangeResourceRecordSets check failed.\nPlase check $zonename" exit 1 fi change=`echo "$change"|cut -f3` _aws route53 get-change --id=$change >> $log if [ $? -ne 0 ]; then echo "This instance don't have route53:GetChange role." result=1 fi json=`change_batch_json "DELETE" $zonename $try` echo -e "DELETE json\n$json" >> $log aws route53 --output text change-resource-record-sets --hosted-zone-id $zoneid --change-batch "$json" >> $log exit $result } # Main # aws-cli install check which aws &> /dev/null if [ $? -ne 0 ]; then echo -e "\"aws\" command not found.\nPlease install aws-cli utility." exit 1 fi if [ $# -lt 1 ]; then echo "`basename $0` service [options...]" exit 1 fi # role check service=$1 shift case "$service" in "ec2") check_ec2 $@;; "route53") check_r53 $@;; esac echo "Unknown service" exit 1