def RemoveTermProtection(fProfile, fAllInstances): for i in range(len(fAllInstances)): logging.warning("Profile: %s | Region: %s | ChildAccount: %s" % (fProfile, fAllInstances[i]['ChildRegion'], fAllInstances[i]['ChildAccount'])) session_cfn = Inventory_Modules.get_child_access( fProfile, fAllInstances[i]['ChildRegion'], fAllInstances[i]['ChildAccount']) client_cfn = session_cfn.client('cloudformation') try: response = client_cfn.update_termination_protection( EnableTerminationProtection=False, StackName=fAllInstances[i]['StackName']) except Exception as e: if e.response['Error']['Code'] == 'ValidationError': logging.info( "Caught exception 'ValidationError', ignoring the exception..." ) print() pass logging.info( "Stack %s had termination protection removed from it in Account %s in Region %s" % (fAllInstances[i]['StackName'], fAllInstances[i]['ChildAccount'], fAllInstances[i]['ChildRegion'])) return (True)
def find_all_accounts(fRootProfiles): AllChildAccounts = [] for profile in fRootProfiles: logging.error("Finding all accounts under Management Profile: %s" % (profile)) ChildAccounts = Inventory_Modules.find_child_accounts2(profile) AllChildAccounts.extend(ChildAccounts) logging.warning("Found %s accounts" % (len(AllChildAccounts))) return (AllChildAccounts)
def get_root_profiles(): RootProfiles = [] AllProfiles = Inventory_Modules.get_profiles2() try: for profile in AllProfiles: print(ERASE_LINE, "Checking profile {} to see if it's an Org Root profile". format(profile), end="\r") response = Inventory_Modules.find_if_org_root(profile) if response == 'Root': RootProfiles.append(profile) except ClientError as my_Error: if str(my_Error).find("AuthFailure") > 0: print("Authorization Failure for profile {}".format(profile)) print(my_Error) elif str(my_Error).find("AccessDenied") > 0: print("Access Denied Failure for profile {}".format(profile)) print(my_Error) else: print("Other kind of failure for profile {}".format(profile)) print(my_Error) return (RootProfiles)
else: print( "You asked me to find (and delete) stacksets that match the following:" ) print(" In the ROOT profile {} and all children".format(pProfile)) print(" In these regions: {}".format(pRegion)) print(" For stacksets that contain these fragments: {}".format(pStackfrag)) print(" Specifically to find this account number: {}".format(pAccountRemove)) if pCheckAccount: print( " We'll also display those accounts in the stacksets that are no longer part of the organization" ) print() # Get the StackSet names from the Master Profile StackSetNames = Inventory_Modules.find_stacksets(pProfile, pRegion, pStackfrag) ProfileAccountNumber = Inventory_Modules.find_account_number(pProfile) logging.error("Found %s StackSetNames that matched your fragment" % (len(StackSetNames))) # Now go through those stacksets and determine the instances, made up of accounts and regions for i in range(len(StackSetNames)): print(ERASE_LINE, "Looking for stacksets with '{}' string in account {} in region {}". format(pStackfrag, ProfileAccountNumber, pRegion), end='\r') StackInstances = Inventory_Modules.find_stack_instances( pProfile, pRegion, StackSetNames[i]['StackSetName']) # pprint.pprint(StackInstances) # sys.exit(99) logging.warning("Found %s Stack Instances within the StackSet %s" %
4. They provided both the pProfile AND pProfiles parameters. * argparse will stop the user from doing that! """ logging.info("Profile: %s",pProfile) logging.info("Profiles: %s",str(pProfiles)) if pProfile == "all" and pProfiles == []: # Use case #1 from above logging.info("Use Case #1") logging.warning("Profile is set to all") ShowEverything=True elif not pProfile == "all": # Use case #2 from above logging.info("Use Case #2") logging.warning("Profile is set to %s",pProfile) AcctNum = Inventory_Modules.find_account_number(pProfile) AcctAttr = Inventory_Modules.find_org_attr(pProfile) MasterAcct = AcctAttr['MasterAccountId'] OrgId = AcctAttr['Id'] if AcctNum==MasterAcct: logging.warning("This is a root account - showing info only for %s",pProfile) RootAcct=True ShowEverything=False else: print() print(Fore.RED + "If you're going to provide a profile, it's supposed to be a Master Billing Account profile!!" + Fore.RESET) print("Continuing to run the script - but for all profiles.") ShowEverything=True else: # Use case #3 from above logging.info("Use Case #3") logging.warning("Multiple profiles have been provided: %s. Going through one at a time...",str(pProfiles))
AccountsToSkip = args.pSkipAccounts verbose = args.loglevel DeletionRun = args.DeletionRun logging.basicConfig( level=args.loglevel, format= "[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)30s() ] %(message)s") ########################## ERASE_LINE = '\x1b[2K' print() fmt = '%-20s %-15s %-15s' print(fmt % ("Account", "pRegion", "IDP Name")) print(fmt % ("-------", "------", "--------")) ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) ChildAccounts = Inventory_Modules.RemoveCoreAccounts(ChildAccounts, AccountsToSkip) NumofAccounts = len(ChildAccounts) IdpsFound = [] for account in ChildAccounts: try: account_credentials, role_arn = Inventory_Modules.get_child_access2( pProfile, account['AccountId']) logging.info("Role ARN: %s" % role_arn) account_credentials['AccountNumber'] = account['AccountId'] except ClientError as my_Error: if str(my_Error).find("AuthFailure") > 0: print(pProfile + ": Authorization Failure for account {}".format( account['AccountId']))
pProfile=args.pProfile pRegion=args.pRegion AccountsToSkip=args.pSkipAccounts verbose=args.loglevel DeletionRun=args.DeletionRun logging.basicConfig(level=args.loglevel, format="[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)30s() ] %(message)s") ########################## ERASE_LINE = '\x1b[2K' print() fmt='%-20s %-15s %-15s' print(fmt % ("Account","pRegion","IDP Name")) print(fmt % ("-------","------","--------")) # pRegionList=Inventory_Modules.get_ec2_pRegions(ppRegionList) ChildAccounts=Inventory_Modules.find_child_accounts2(pProfile) ChildAccounts=Inventory_Modules.RemoveCoreAccounts(ChildAccounts,AccountsToSkip) # pprint.pprint(AccountsToSkip) # pprint.pprint(ChildAccounts) # sys.exit(1) NumofAccounts=len(ChildAccounts) IdpsFound=[] aws_session = boto3.Session(profile_name=pProfile) sts_client = aws_session.client('sts') for account in ChildAccounts: role_arn = "arn:aws:iam::{}:role/AWSCloudFormationStackSetExecutionRole".format(account['AccountId']) logging.info("Role ARN: %s" % role_arn) try: account_credentials = sts_client.assume_role( RoleArn=role_arn, RoleSessionName="Find-Stacks")['Credentials']
else: print("You asked me to find (and delete) stacksets that match the following:") print(" In the ROOT profile {} and all children".format(pProfile)) print(" In these regions: {}".format(pRegion)) print(" For stacksets that contain these fragments: {}".format(pStackfrag)) # print(" For stack instances that match this status: {}".format(pstatus)) if pAccountRemove == "NotProvided": pass else: print(" Specifically to find this account number: {}".format(pAccountRemove)) if pCheckAccount: print(" We'll also display those accounts in the stacksets that are no longer part of the organization") print() # Get the StackSet names from the Master Profile StackSetNames=Inventory_Modules.find_stacksets(pProfile, pRegion, pStackfrag) ProfileAccountNumber=Inventory_Modules.find_account_number(pProfile) logging.error("Found %s StackSetNames that matched your fragment" % (len(StackSetNames))) # Now go through those stacksets and determine the instances, made up of accounts and regions for i in range(len(StackSetNames)): print(ERASE_LINE, "Looking for stacksets with {} string in account {} in region {}".format(pStackfrag, ProfileAccountNumber, pRegion), end='\r') StackInstances=Inventory_Modules.find_stack_instances(pProfile, pRegion, StackSetNames[i]['StackSetName']) # pprint.pprint(StackInstances) # sys.exit(99) logging.warning("Found %s Stack Instances within the StackSet %s" % (len(StackInstances), StackSetNames[i]['StackSetName'])) for j in range(len(StackInstances)): if 'StackId' not in StackInstances[j].keys(): logging.info("The stack instance found doesn't have a stackid associated. Which means it's never been deployed and probably OUTDATED") pass if pAccountRemove=='NotProvided':
action="store_const", default=logging.CRITICAL, # args.loglevel = 50 dest="loglevel", const=logging.DEBUG) # args.loglevel = 20 args = parser.parse_args() pProfile=args.pProfile pTargetRole=args.pTargetRole pAccessRole=args.pAccessRole pLock=args.pLock pSafety=args.pSafety pFix=args.pFix verbose=args.loglevel logging.basicConfig(level=args.loglevel, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s") ParentAcctNum=Inventory_Modules.find_account_number(pProfile) ChildAccounts=Inventory_Modules.find_child_accounts2(pProfile) if len(ChildAccounts) == 0: print() print("The profile {} does not represent an Org".format(pProfile)) print("This script only works with org accounts.") print() sys.exit(1) ########################## ERASE_LINE = '\x1b[2K' ########################## print("We're using the {} role to gain access to the child accounts".format(pAccessRole)) print("We're targeting the {} role to change its Trust Policy".format(pTargetRole)) '''
print( " If it has been, it needs to be deleted before we can adopt this new account" ) print(" into the Org's Automated Landing Zone.") print(Fore.BLUE + " 5." + Fore.RESET + " This child account " + Fore.RED + "must exist" + Fore.RESET + " within the Parent Organization.") print(" If it doesn't - then you must move it into this Org") print(" (this script can't do that for you).") print() print( "Since this script is fairly new - All comments or suggestions are enthusiastically encouraged" ) print() try: account_credentials, role = Inventory_Modules.get_child_access2( pProfile, pChildAccountId) if role.find("failed") > 0: print( Fore.RED, "We weren't able to connect to the Child Account from this Master Account. Please check the role Trust Policy and re-run this script.", Fore.RESET) print( "The following list of roles were tried, but none were allowed access to account {} using the {} profile" .format(pChildAccountId, pProfile)) print(Fore.RED, account_credentials, Fore.RESET) ProcessStatus['Step0']['Success'] = False sys.exit("Exiting due to cross-account Auth Failure") except ClientError as my_Error: if str(my_Error).find("AuthFailure") > 0: print("{}: Authorization Failure for account {}".format( pProfile, pChildAccountId))
print( " If it has been, it needs to be deleted before we can adopt this new account" ) print(" into the Org's Automated Landing Zone.") print(Fore.BLUE + " 5." + Fore.RESET + " This child account " + Fore.RED + "must exist" + Fore.RESET + " within the Parent Organization.") print(" If it doesn't - then you must move it into this Org") print(" (this script can't do that for you).") print() print( "Since this script is fairly new - All comments or suggestions are enthusiastically encouraged" ) print() try: account_credentials, role = Inventory_Modules.get_child_access2( pProfile, pChildAccountId) # account_credentials = client_sts.assume_role( # RoleArn=role_arn, # RoleSessionName="ALZ_CheckAccount")['Credentials'] account_credentials['AccountNumber'] = pChildAccountId # pprint.pprint(account_credentials) if role.find("failed") > 0: print( Fore.RED, "We weren't able to connect to the Child Account from this Master Account. Please check the role Trust Policy and re-run this script.", Fore.RESET) sys.exit("Exiting due to cross-account Auth Failure") except ClientError as my_Error: if str(my_Error).find("AuthFailure") > 0: print("{}: Authorization Failure for account {}".format( pProfile, pChildAccountId))
# If plevel # 1: credentials file only # 2: config file only # 3: credentials and config files pProfile = args.pProfile verbose = args.loglevel logging.basicConfig(level=args.loglevel) # RegionList=[] # SkipProfiles=["default"] SkipProfiles = ["default", "Shared-Fid"] ########################## ERASE_LINE = '\x1b[2K' ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) NumUsersFound = 0 print() fmt = '%-15s %-20s' print(fmt % ("Account Number", "User Name")) print(fmt % ("--------------", "---------")) sts_session = boto3.Session(profile_name=pProfile) sts_client = sts_session.client('sts') for account in ChildAccounts: role_arn = "arn:aws:iam::{}:role/AWSCloudFormationStackSetExecutionRole".format( account['AccountId']) logging.info("Role ARN: %s" % role_arn) try: account_credentials = sts_client.assume_role(
logging.basicConfig(level=args.loglevel) SkipProfiles = ["default", "Shared-Fid"] ########################## ERASE_LINE = '\x1b[2K' NumLBsFound = 0 NumRegions = 0 print() fmt = '%-20s %-10s %-20s %-10s %-50s' print(fmt % ("Profile", "Region", "Load Balancer Name", "LB Status", "Load Balancer DNS Name")) print(fmt % ("-------", "------", "------------------", "---------", "----------------------")) RegionList = Inventory_Modules.get_ec2_regions(pRegionList) ProfileList = Inventory_Modules.get_profiles(SkipProfiles, pProfiles) for pregion in RegionList: NumRegions += 1 NumProfilesInvestigated = 0 # I only care about the last run - so I don't get profiles * regions. for profile in ProfileList: NumProfilesInvestigated += 1 try: LoadBalancers = Inventory_Modules.find_load_balancers( profile, pregion, pstackfrag, pstatus) LBNum = len(LoadBalancers) logging.info( "Profile: %-15s | Region: %-15s | Found %2d Load Balancers", profile, pregion, LBNum) print(ERASE_LINE,
level=args.loglevel, format= "[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)30s() ] %(message)s") SkipProfiles = ["default", "Shared-Fid"] ########################## ERASE_LINE = '\x1b[2K' NumVpcsFound = 0 NumRegions = 0 print() fmt = '%-20s %-10s %-21s %-20s %-12s %-10s' print(fmt % ("Profile", "Region", "Vpc ID", "CIDR", "Is Default?", "Vpc Name")) print(fmt % ("-------", "------", "------", "----", "-----------", "--------")) RegionList = Inventory_Modules.get_ec2_regions(pRegionList) ProfileList = Inventory_Modules.get_profiles(SkipProfiles, pProfiles) logging.info("# of Regions: %s" % len(RegionList)) logging.info("# of Profiles: %s" % len(ProfileList)) for region in RegionList: NumRegions += 1 NumProfilesInvestigated = 0 # I only care about the last run - so I don't get profiles * regions. for profile in ProfileList: NumProfilesInvestigated += 1 try: Vpcs = Inventory_Modules.find_profile_vpcs(profile, region, pDefaultOnly) logging.info("Info - Profile %s | Region %s | Found %s vpcs", profile, region, len(Vpcs))
# StackSetNames2=[] print() if pdryrun: print("You asked me to find (but not delete) stacksets that match the following:") else: print("You asked me to find (and delete) stacksets that match the following:") print(" In the ROOT profile {} and all children".format(pProfile)) print(" In these regions: {}".format(pRegion)) print(" For stacksets that contain these fragments: {}".format(pStackfrag)) print(" Specifically to find this account number: {}".format(pRemove)) print() # Get the StackSet names from the Master Profile StackSetNames=Inventory_Modules.find_stacksets(pProfile,pRegion,pStackfrag) ProfileAccountNumber=Inventory_Modules.find_account_number(pProfile) logging.info("Found %s StackSetNames that matched your fragment" % (len(StackSetNames))) # for i in range(len(StackSetNames)): # if 'AWSControlTower' in StackSetNames[i]['StackSetName']: # continue # else: # StackSetNames2.append(StackSetNames[i]) # StackSetNames=StackSetNames2 for i in range(len(StackSetNames)): print(ERASE_LINE,"Looking for stacksets with '{}' string in account {} in region {}".format(StackSetNames[i]['StackSetName'],ProfileAccountNumber,pRegion),end='\r') StackInstances=Inventory_Modules.find_stack_instances(pProfile,pRegion,StackSetNames[i]['StackSetName']) # pprint.pprint(StackInstances) logging.warning("Found %s Stack Instances within the StackSet %s" % (len(StackInstances),StackSetNames[i]['StackSetName'])) for j in range(len(StackInstances)): AllInstances.append({
const=logging.DEBUG, # args.loglevel = 20 default=logging.CRITICAL) # args.loglevel = 50 args = parser.parse_args() pProfile = args.pProfile pAccount = args.pAccount pRoleNameToAdd = args.pRoleNameToAdd pRoleNameToRemove = args.pRoleNameToRemove pRoleNameToCheck = args.pRoleNameToCheck pAccessRole = args.pAccessRole verbose = args.loglevel logging.basicConfig(level=args.loglevel, format="[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)20s() ] %(message)s") if pAccount is None: ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) if len(ChildAccounts) == 0: print() print("The profile {} does not represent an Org".format(pProfile)) print("This script only works with org accounts. Sorry.") print() sys.exit(1) elif not len(pAccount) == 12: print("The provided Account number must be 12 digits") sys.exit(2) else: ChildAccounts = [{'ParentProfile': pProfile, 'AccountId': pAccount, 'AccountEmail': 'Not Provided', 'AccountStatus': 'Unknown' }]
########################## def sort_by_email(elem): return(elem('AccountEmail')) ########################## ERASE_LINE = '\x1b[2K' print() SCP2Stacks=[] SCProducts=[] ErroredSCPExists=False session_cfn=boto3.Session(profile_name=pProfile,region_name=pRegion) client_cfn=session_cfn.client('cloudformation') try: # SCProducts=Inventory_Modules.find_sc_products(pProfile,pRegion,"ERROR") SCresponse=Inventory_Modules.find_sc_products(pProfile,pRegion,"All") logging.warning("A list of the SC Products found:") for i in range(len(SCresponse)): logging.warning("SC Product Name %s | SC Product Status %s", SCresponse[i]['Name'], SCresponse[i]['Status']) SCProducts.append({ 'SCPName':SCresponse[i]['Name'], 'SCPId':SCresponse[i]['Id'], 'SCPStatus':SCresponse[i]['Status'] }) if SCresponse[i]['Status'] == 'ERROR' or SCresponse[i]['Status'] == 'TAINTED': ErroredSCPExists=True for i in range(len(SCProducts)): print(ERASE_LINE,Fore.RED+"Checking {} of {} products".format(i+1,len(SCProducts))+Fore.RESET,end='\r') # CFNresponse=Inventory_Modules.find_stacks(pProfile,pRegion,SCProducts[i]['SCPId'],"all") CFNresponse=Inventory_Modules.find_stacks(pProfile,pRegion,SCProducts[i]['SCPId']) logging.error("There are %s matches for SC Provisioned Product Name %s", len(CFNresponse),SCProducts[i]['SCPName'])
NumInstancesFound = 0 print() if ProfileSupplied: fmt = '%-12s %-15s %-10s %-15s %-25s %-20s %-42s %-12s' print(fmt % ("Profile", "Account #", "Region", "InstanceType", "Name", "Instance ID", "Public DNS Name", "State")) print(fmt % ("-------", "---------", "------", "------------", "----", "-----------", "---------------", "-----")) elif not ProfileSupplied: fmt = '%-15s %-10s %-15s %-25s %-20s %-42s %-12s' print(fmt % ("Account #", "Region", "InstanceType", "Name", "Instance ID", "Public DNS Name", "State")) print(fmt % ("---------", "------", "------------", "----", "-----------", "---------------", "-----")) RegionList = Inventory_Modules.get_regions(pRegionList) AllChildAccounts = [] SoughtAllProfiles = False ProfileIsRoot = Inventory_Modules.find_if_org_root(pProfile) if ProfileIsRoot == 'Root': logging.info("Profile %s is a Root account", pProfile) Creds = Inventory_Modules.find_calling_identity(pProfile) AllChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) elif ProfileIsRoot == 'StandAlone': logging.info("Profile %s is a Standalone account", pProfile) Creds = Inventory_Modules.find_calling_identity(pProfile) AllChildAccounts = [{ 'ParentProfile': pProfile, 'AccountId': Creds['AccountId'],
const=logging.ERROR, # args.loglevel = 40 default=logging.CRITICAL) # args.loglevel = 50 args = parser.parse_args() pProfile = args.pProfile AccountsToSkip = args.pSkipAccounts logging.basicConfig(level=args.loglevel, format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S') ########################## ERASE_LINE = '\x1b[2K' NumObjectsFound = 0 NumAccountsInvestigated = 0 ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) ChildAccounts = Inventory_Modules.RemoveCoreAccounts(ChildAccounts, AccountsToSkip) cross_account_role = "AWSCloudFormationStackSetExecutionRole" print() fmt = '%-15s %-42s' print(fmt % ("Account Number", "Role Name")) print(fmt % ("--------------", "---------")) sts_session = boto3.Session(profile_name=pProfile) sts_client = sts_session.client('sts') for account in ChildAccounts: role_arn = "arn:aws:iam::{}:role/{}".format(account['AccountId'], cross_account_role) logging.info("Role ARN: %s" % role_arn)
logging.basicConfig( level=args.loglevel, format= "[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)30s() ] %(message)s") ########################## ERASE_LINE = '\x1b[2K' SkipProfiles = ["default"] NumVpcsFound = 0 NumRegions = 0 print() fmt = '%-20s %-10s %-21s %-20s %-12s %-10s' print(fmt % ("Profile", "Region", "Vpc ID", "CIDR", "Is Default?", "Vpc Name")) print(fmt % ("-------", "------", "------", "----", "-----------", "--------")) RegionList = Inventory_Modules.get_ec2_regions(pRegionList) SoughtAllProfiles = False AllChildAccounts = [] AdminRole = "AWSCloudFormationStackSetExecutionRole" if pDefault: vpctype = "default" else: vpctype = "" if pProfile in ['all', 'ALL', 'All']: # print(Fore.RED+"Doesn't yet work to specify 'all' profiles, since it takes a long time to go through and find only those profiles that either Org Masters, or stand-alone accounts",Fore.RESET) # sys.exit(1) SoughtAllProfiles = True logging.info("Profiles sent to function get_profiles3: %s", pProfile) print( "Since you specified 'all' profiles, we going to look through ALL of your profiles. Then we go through and determine which profiles represent the Master of an Organization and which are stand-alone accounts. This will enable us to go through all accounts you have access to for inventorying."
pProfile=args.pProfile adminrolename=args.pAdminRoleName DeletionRun=args.flagDelete ForceDelete=args.ForceDelete AccountsToSkip=args.pSkipAccounts pRegions=args.pRegions logging.basicConfig(level=args.loglevel, format="[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)30s() ] %(message)s") ########################## ERASE_LINE = '\x1b[2K' NumObjectsFound = 0 NumAccountsInvestigated = 0 adminrolename='AWSCloudFormationStackSetExecutionRole' ChildAccounts=Inventory_Modules.find_child_accounts2(pProfile) ChildAccounts=Inventory_Modules.RemoveCoreAccounts(ChildAccounts,AccountsToSkip) # pprint.pprint(ChildAccounts) # sys.exit(99) cfg_regions=Inventory_Modules.get_service_regions('config',pRegions) all_config_resources=[] all_config_resources=[] print("Searching {} accounts and {} regions".format(len(ChildAccounts),len(cfg_regions))) sts_session = boto3.Session(profile_name=pProfile) sts_client = sts_session.client('sts') for account in ChildAccounts: role_arn = "arn:aws:iam::{}:role/{}".format(account['AccountId'],adminrolename) logging.info("Role ARN: %s" % role_arn)
action="store_const", dest="loglevel", const=logging.DEBUG, # args.loglevel = 10 default=logging.CRITICAL) # args.loglevel = 50 args = parser.parse_args() pProfile = args.pProfile logging.basicConfig( level=args.loglevel, format="[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)20s() ] %(" "message)s") ########################## ERASE_LINE = '\x1b[2K' ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) print() fmt = '%-15s %-42s' print(fmt % ("Account Number", "Role Name")) print(fmt % ("--------------", "---------")) RoleNum = 0 for account in ChildAccounts: try: account_credentials, role_arn = Inventory_Modules.get_child_access2( pProfile, account['AccountId']) logging.info("Connecting to %s with %s role", account['AccountId'], role_arn) logging.info("Role ARN: %s" % role_arn) except ClientError as my_Error: if str(my_Error).find("AuthFailure") > 0:
** TODO: This list should hold *all* stacks and then we could find stacks for accounts that no longer exist. 'AccountHistogram' holds the list of accounts (the account numbers are the keys in this dict) and the number of SC products that are created for this account is the value of that key. ''' ERASE_LINE = '\x1b[2K' print() SCP2Stacks = [] SCProducts = [] ErroredSCPExists = False session_aws = boto3.Session(profile_name=pProfile, region_name=pRegion) client_org = session_aws.client('organizations') client_cfn = session_aws.client('cloudformation') AcctList = Inventory_Modules.find_child_accounts2(pProfile) AccountHistogram = {} SuspendedAccounts = [] for account in AcctList: AccountHistogram[account['AccountId']] = account['AccountStatus'] if account['AccountStatus'] == 'SUSPENDED': SuspendedAccounts.append(account['AccountId']) try: SCresponse = Inventory_Modules.find_sc_products(pProfile, pRegion, "All", 10) logging.warning("A list of the SC Products found:") for i in range(len(SCresponse)): logging.warning("SC Product Name %s | SC Product Status %s", SCresponse[i]['Name'], SCresponse[i]['Status']) SCProducts.append({
ERASE_LINE = '\x1b[2K' ALZRegex = '/\w{8,8}-\w{4,4}-\w{4,4}-\w{4,4}-\w{12,12}/\w{3,3}' print() fmt = '%-15s %-20s' print(fmt % ("Parameter Name", "Last Modified Date")) print(fmt % ("--------------", "------------------")) session_ssm = boto3.Session(profile_name=pProfile) client_ssm = session_ssm.client('ssm') Parameters = [] ParamsToDelete = [] ALZParams = 0 try: # Since there could be 10,000 parameters stored in the Parameter Store - this function COULD take a long time Parameters = Inventory_Modules.find_ssm_parameters(pProfile, pRegion) logging.error("Profile: %s found a total of %s parameters", pProfile, len(Parameters)) # print(ERASE_LINE,"Account:",account['AccountId'],"Found",len(Users),"users",end='\r') except ClientError as my_Error: if str(my_Error).find("AuthFailure") > 0: print("{}: Authorization Failure".format(pProfile)) if ALZParam: today = datetime.datetime.now(tz=datetime.timezone.utc) for y in range(len(Parameters)): # If the parameter matches the string regex of "/2ac07efd-153d-4069-b7ad-0d18cc398b11/105" - then it should be a candidate for deletion # With Regex - I'm looking for "/\w{8,8}-\w{4,4}-\w{4,4}-\w{4,4}-\w{12,12}/\w{3,3}" ParameterDate = Parameters[y]['LastModifiedDate'] mydelta = today - ParameterDate # this is a "timedelta" object p = re.compile(ALZRegex) # Sets the regex to look for
def _delete_stack_instances(fProfile, fRegion, fAccountList, fAccountRemove, fAccountsToSkip, fRegionList, fStackSet, fForce=True): session_cfn=boto3.Session(profile_name=pProfile, region_name=pRegion) logging.warning("Removing instances from %s StackSet" % (fStackSet['StackSetName'])) try: StackSetOpId='Delete-'+randomString(5) response=Inventory_Modules.delete_stack_instances(fProfile, [fRegion], fAccountList, fRegionList, fStackSet['StackSetName'], fForce, StackSetOpId) # pprint.pprint(response) except Exception as e: if e.response['Error']['Code'] == 'StackSetNotFoundException': logging.info("Caught exception 'StackSetNotFoundException', ignoring the exception...") else: print("Error: ", e) return("Failed-Other") StackOperationsRunning=True client_cfn=session_cfn.client('cloudformation') timer=10 while StackOperationsRunning: InstancesToSkip = 0 SpecificInstancesLeft = 0 logging.debug("Got into the While Loop") logging.warning(fStackSet['StackSetName']) try: time.sleep(3) Status=client_cfn.list_stack_set_operations(StackSetName=fStackSet['StackSetName']) # pprint.pprint(Status) logging.info("StackSet Operation state is %s" % Status['Summaries'][0]['Status']) if Status['Summaries'][0]['Status'] in ['CANCELLED', 'FAILED']: time.sleep(2) Reason=client_cfn.list_stack_set_operation_results(StackSetName=fStackSet['StackSetName'], OperationId=StackSetOpId) for k in range(len(Reason)): logging.info("Reason: %s", Reason['Summaries'][k]['StatusReason']) if Reason['Summaries'][k]['Status']=='FAILED' and Reason['Summaries'][k]['StatusReason'].find("role with trust relationship to Role") > 0: logging.info("StackSet Operation status reason is: %s" % Reason['Summaries'][k]['StatusReason']) print("Error removing account {} from the StackSet {}. We should try to delete the stack instance with '--retain-stacks' enabled...".format(pAccountRemove, fStackSet['StackSetName'])) return("Failed-ForceIt") response2=client_cfn.list_stack_instances(StackSetName=fStackSet['StackSetName'])['Summaries'] for j in range(len(response2)): if response2[j]['Account'] in fAccountsToSkip: InstancesToSkip+=1 elif response2[j]['Account'] == fAccountRemove: SpecificInstancesLeft+=1 # elif response2[j]['Region'] == fRegionRemove: # SpecificInstancesLeft+=1 # if fAccountRemove=='NotProvided' and fRegionRemove=='NotProvided': # InstancesLeft=len(response2)-InstancesToSkip # logging.info("There are still %s instances left in the stackset" % InstancesLeft) if fAccountRemove=='NotProvided': InstancesLeft=len(response2)-InstancesToSkip logging.info("There are still %s instances left in the stackset" % InstancesLeft) else: # A specific account was provided to remove from all stacksets InstancesLeft=SpecificInstancesLeft logging.info("There are still %s instances of account %s left in the stackset", SpecificInstancesLeft, fAccountRemove) StackOperationsRunning=(Status['Summaries'][0]['Status'] in ['RUNNING', 'PENDING']) logging.info("StackOperationsRunning is %s" % StackOperationsRunning) if StackOperationsRunning: print(ERASE_LINE+"Waiting {} seconds for {} to be fully deleted. There's still {} instances left.".format(timer, fStackSet['StackSetName'], InstancesLeft), end='\r') time.sleep(10) timer+=10 elif Status['Summaries'][0]['Status'] == 'SUCCEEDED': # pprint.pprint(Status['Summaries']) logging.info("Successfully removed %s from %s", fAccountRemove, fStackSet['StackSetName']) return("Success") else: logging.info("Something else failed") return("Failed-Other") except Exception as e: # if e.response['Error']['Code'] == 'StackSetNotFoundException': # logging.info("Caught exception 'StackSetNotFoundException', ignoring the exception...") # StackOperationsRunning=True # pass # else: print("Error: ", e) break
return s[-amount:] def mid(s, offset, amount): return s[offset - 1:offset + amount - 1] ########################## ERASE_LINE = '\x1b[2K' NumInstancesFound = 0 NumRegions = 0 print() fmt = '%-20s %-10s %-40s %-12s %-35s' print(fmt % ("Profile", "Region", "Function Name", "Runtime", "Role")) print(fmt % ("-------", "------", "-------------", "-------", "----")) RegionList = Inventory_Modules.get_ec2_regions(pRegionList) ProfileList = Inventory_Modules.get_profiles(SkipProfiles, pProfiles) # pprint.pprint(RegionList) for pregion in RegionList: NumRegions += 1 NumProfilesInvestigated = 0 # I only care about the last run - so I don't get profiles * regions. for profile in ProfileList: NumProfilesInvestigated += 1 try: Functions = Inventory_Modules.find_profile_functions( profile, pregion) FunctionNum = len(Functions['Functions']) print(ERASE_LINE + "Profile:", profile, "Region:", pregion,
SkipProfiles = ["default"] ########################## ERASE_LINE = '\x1b[2K' NumPHZsFound = 0 NumRegions = 0 print() fmt = '%-20s %-10s %-25s %-20s %-25s' print( fmt % ("Profile", "Region", "Hosted Zone Name", "Number of Records", "Zone ID")) print( fmt % ("-------", "------", "----------------", "-----------------", "-------")) RegionList = Inventory_Modules.get_ec2_regions(pRegionList) ProfileList = Inventory_Modules.get_profiles(SkipProfiles, pProfiles) for pregion in RegionList: NumRegions += 1 NumProfilesInvestigated = 0 # I only care about the last run - so I don't get profiles * regions. for profile in ProfileList: NumProfilesInvestigated += 1 try: HostedZones = Inventory_Modules.find_private_hosted_zones( profile, pregion)['HostedZones'] PHZNum = len(HostedZones) logging.info( "Profile: %-15s | Region: %-15s | Found %2d Hosted Zones", profile, pregion, PHZNum) print(ERASE_LINE,
########################## ERASE_LINE = '\x1b[2K' print(args.loglevel) print() if args.loglevel < 21: # INFO level fmt='%-20s %-15s %-15s %-50s %-50s' print(fmt % ("Account","Region","Stack Status","Stack Name","Stack ID")) print(fmt % ("-------","------","------------","----------","--------")) else: fmt='%-20s %-15s %-15s %-50s' print(fmt % ("Account","Region","Stack Status","Stack Name")) print(fmt % ("-------","------","------------","----------")) # RegionList=Inventory_Modules.get_ec2_regions(pRegionList) RegionList=Inventory_Modules.get_service_regions('cloudformation',pRegionList) ChildAccounts=Inventory_Modules.find_child_accounts2(pProfile) ChildAccounts=Inventory_Modules.RemoveCoreAccounts(ChildAccounts,AccountsToSkip) # pprint.pprint(AccountsToSkip) # pprint.pprint(ChildAccounts) # sys.exit(1) StacksFound=[] aws_session = boto3.Session(profile_name=pProfile) sts_client = aws_session.client('sts') for account in ChildAccounts: role_arn = "arn:aws:iam::{}:role/AWSCloudFormationStackSetExecutionRole".format(account['AccountId']) logging.info("Role ARN: %s" % role_arn) try: account_credentials = sts_client.assume_role( RoleArn=role_arn, RoleSessionName="Find-Stacks")['Credentials']
const=logging.DEBUG, # args.loglevel = 10 default=logging.CRITICAL) # args.loglevel = 50 args = parser.parse_args() pProfile = args.pProfile pRegionList = args.pregion pstackfrag = args.pstackfrag pstatus = args.pstatus verbose = args.loglevel logging.basicConfig( level=args.loglevel, format= "[%(filename)s:%(lineno)s:%(levelname)s - %(funcName)20s() ] %(message)s") SkipProfiles = ["default"] ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) NumStacksFound = 0 ########################## ERASE_LINE = '\x1b[2K' print() fmt = '%-20s %-15s %-15s %-50s' print(fmt % ("Account", "Region", "Status", "StackSet Name")) print(fmt % ("-------", "------", "------", "-------------")) RegionList = Inventory_Modules.get_ec2_regions(pRegionList) sts_session = boto3.Session(profile_name=pProfile) sts_client = sts_session.client('sts') for account in ChildAccounts: role_arn = "arn:aws:iam::{}:role/AWSCloudFormationStackSetExecutionRole".format(
action="store_const", dest="loglevel", const=logging.ERROR) # args.loglevel = 40 parser.add_argument('-vv', help="Be MORE verbose", action="store_const", dest="loglevel", const=logging.WARNING) # args.loglevel = 30 args = parser.parse_args() pProfile = args.pProfile pForcedReg = args.pForcedReg verbose = args.loglevel logging.basicConfig(level=args.loglevel) ChildAccounts = Inventory_Modules.find_child_accounts2(pProfile) if len(ChildAccounts) == 0: print() print("The profile {} seems to not represent an Org".format(pProfile)) print("This script only works with org accounts. Sorry.") print() sys.exit(1) ########################## ERASE_LINE = '\x1b[2K' print() fmt = '%-15s %-25s %-15s %-24s' print(fmt % ("Account", "Email", "AccessKey", "Secret Access Key")) print(fmt % ("-------", "-----", "---------", "-----------------")) sts_session = boto3.Session(profile_name=pProfile)