Преглед изворни кода

Merge pull request #672 from mdr-engineering/feature/ftd_na_CredentialReportScript

Adds 'crendential-report.sh' and 'delete-iam-user.py' helper scripts
Frederick Damstra пре 3 година
родитељ
комит
34b0d36c3b
2 измењених фајлова са 190 додато и 0 уклоњено
  1. 77 0
      bin/credential-reports.sh
  2. 113 0
      bin/delete-iam-user.py

+ 77 - 0
bin/credential-reports.sh

@@ -0,0 +1,77 @@
+#!/bin/bash
+# Runs the same aws CLI command in "most" of the defined profiles
+# in $HOME/.aws/config
+#
+# You can pass in via an environment variable a "profile set"
+# of either "commercial", "govcloud", or "both".  Default is "both"
+#
+# Does an "aws sts get-caller-identity" to confirm that your AssumeRole
+# and other necessities are properly set up before attempting to call the
+# actual AWS command.
+#
+# PROFILE_SET=commercial aws-all.sh ec2 describe-instances
+#
+set -u -o pipefail # can't use -e since a pipe intentionally fails below
+
+AWS=${AWS:-/usr/local/bin/aws}
+PROFILE_SET=${PROFILE_SET:-both}
+
+ALL_PROFILES=$( egrep "\[profile" ~/.aws/config | 	\
+		awk '{ print $2 }' | 			\
+		sed "s/\]//" | 				\
+		egrep -v "default|commercial|govcloud" )
+
+COMMERCIAL_PROFILES=""
+GOVCLOUD_PROFILES=""
+
+export AWS_PAGER="" # Don't paginate output
+
+for i in $ALL_PROFILES; do
+	if [[ "$i" =~ -gov$ ]]; then
+		GOVCLOUD_PROFILES="$GOVCLOUD_PROFILES $i"
+	else
+		COMMERCIAL_PROFILES="$COMMERCIAL_PROFILES $i"
+	fi
+done
+
+case $PROFILE_SET in
+
+	both) 
+		PROFILES="$COMMERCIAL_PROFILES $GOVCLOUD_PROFILES"
+		;;
+	
+	govcloud) 
+		PROFILES="$GOVCLOUD_PROFILES"
+		;;
+
+	commercial) 
+		PROFILES="$COMMERCIAL_PROFILES"
+		;;
+esac
+
+for i in $PROFILES; do
+	echo "======================================================================================"
+	export AWS_PROFILE=$i 
+	
+	set +e
+	${AWS} sts get-caller-identity > /dev/null 2>&1
+	RC=$?
+	set -e
+
+	if [[ $RC -eq 0 ]]; then
+		echo "GetCallerIdentity (AssumeRole Test) for $i OK"
+		aws iam generate-credential-report --output=text
+    sleep 5
+    aws iam get-credential-report | jq -r .Content | base64 --decode | tee $i.tmp
+    echo "" >> $i.tmp
+	else
+		echo "GetCallerIdentity (AssumeRole Test) for $i FAILED"
+	fi
+done
+
+echo Combining
+(cat *.tmp | head -1; cat *.tmp | grep -v 'user,arn,user_creation_time' | sort -u) > combined.tmp2
+# Only the columsn we want. Since format is likely to change, this may be a bad idea
+echo cutting
+cut -d, -f1,2,5,6,9,10,11,14,15,16,19,20,21,22 combined.tmp2 > combined.csv
+rm -f *.tmp *.tmp2

+ 113 - 0
bin/delete-iam-user.py

@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+"""
+Delete an IAM User from an AWS Account.
+
+Copyright (c) 2019 TKalus <tkalus@users.noreply.github.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+SOURCE: https://gist.github.com/tkalus/e91c1d2d68bff68e9c6fa2b8ab2f5485
+"""
+
+import logging
+import sys
+
+import boto3.session
+import botocore.exceptions
+
+logger = logging.getLogger(__file__)
+
+
+def delete_iam_user(session: boto3.session.Session, user_name: str) -> None:
+    """For a given boto3.session.Session, delete the IAM User and all assoc'd resources."""
+    iam = session.resource("iam")
+    iam_client = session.client("iam")
+    user = iam.User(user_name)
+    try:
+        user.load()
+    except botocore.exceptions.ClientError as err:
+        # If load failed with NoSuchEntity, IAM User doesn't exist.
+        if err.response.get("Error", {}).get("Code", "") == "NoSuchEntity":
+            logger.error(f"User {user_name} does not exist")
+            return
+        raise err
+    logger.debug(f"Deleting IAM User: {user.arn}")
+    for group in user.groups.all():
+        logger.debug(f"Removing {user.arn} from Group {group.arn}")
+        user.remove_group(GroupName=group.name)
+    try:
+        login_profile = iam.LoginProfile(user.name)
+        login_profile.load()
+        logger.debug(f"Deleting Login Profile (I.E. Password) from {user.arn}")
+        login_profile.delete()
+    except botocore.exceptions.ClientError as err:
+        # If load failed with NoSuchEntity, No Login Profile
+        if err.response.get("Error", {}).get("Code", "") != "NoSuchEntity":
+            raise err
+    for device in user.mfa_devices.all():
+        logger.debug(f"Removing MFA Device from {user.arn}: {device.serial_number}")
+        device.disassociate()
+    for access_key in user.access_keys.all():
+        logger.debug(f"Deleting Access Key from {user.arn}: {access_key.access_key_id}")
+        access_key.delete()
+    for policy in user.policies.all():
+        logger.debug(f"Deleting Inline Policy from {user.arn}: {policy.name}")
+        policy.delete()
+    for policy in user.attached_policies.all():
+        logger.debug(f"Detatching Managed Policy from {user.arn}: {policy.arn}")
+        user.detach_policy(PolicyArn=policy.arn)
+    for cert in user.signing_certificates.all():
+        logger.debug(f"Deleting Signing Cert from {user.arn}: {cert.id}")
+        iam_client.delete_signing_certificate(UserName=user.name, CertificateId=cert.id)
+    for ssh_public_key_id in [
+        key.get("SSHPublicKeyId", "")
+        for key in iam_client.list_ssh_public_keys(UserName=user.name).get(
+            "SSHPublicKeys", []
+        )
+    ]:
+        logger.debug(f"Deleting SSH Public Key from {user.arn}: {ssh_public_key_id}")
+        iam_client.delete_ssh_public_key(
+            UserName=user.name, SSHPublicKeyId=ssh_public_key_id
+        )
+    for service_name, service_specific_credential_id in {
+        cred.get("ServiceName", ""): cred.get("ServiceSpecificCredentialId", "")
+        for cred in iam_client.list_service_specific_credentials(
+            UserName=user.name
+        ).get("ServiceSpecificCredentials", [])
+    }.items():
+        logger.debug(
+            f"Deleting Service Specific Cred from {user.arn}:"
+            f" {service_name}:{service_specific_credential_id}"
+        )
+        iam_client.delete_service_specific_credential(
+            UserName=user.name,
+            ServiceSpecificCredentialId=service_specific_credential_id,
+        )
+    logger.info(f"Deleted IAM user: {user.name}")
+    user.delete()
+
+
+if __name__ == "__main__":
+    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
+    logging.getLogger("boto3").setLevel(logging.ERROR)
+    logging.getLogger("botocore").setLevel(logging.ERROR)
+    logging.getLogger("urllib3").setLevel(logging.ERROR)
+    session = boto3.session.Session()
+    user_name = dict(enumerate(sys.argv)).get(1)
+    if user_name:
+        delete_iam_user(session, user_name)