def lambda_handler(event, context): my_event = { "Id": "826839167791", "IamResourceType": "Group", "IamResourceName": "teste" } # Declares global variables used by other functions global resource_key resource_key = my_event["IamResourceType"] global resource_name resource_name = my_event["IamResourceName"] global iam_client iam_client = get_creds("iam", Id=my_event["Id"]) global dynamodb_client dynamodb_client = get_creds("dynamodb") # Get data about desired IAM Resource item = dynamodb_client.get_item(TableName=environ["iam_resource_table"], Key={ "ResourceName": { "S": resource_name }, "ResourceType": { "S": resource_key } }, ReturnConsumedCapacity="TOTAL", ConsistentRead=True) my_logging("Details about {} {}: {}".format(resource_key, resource_name, item)) # Enforces resource creation on account resource = create_iam_resource(**item["Item"]) my_logging("Enforce Resource: {}".format(resource)) # Enforces policies on resource policies = apply_policies(**item["Item"]) my_logging("Enforce Policies: {}".format(policies)) # Sends message to queue of the microservice that attaches User to Groups if resource_key == "User" and "Groups" in item["Item"]: my_message = send_sqs({ "Id": my_event["Id"], "User": item["Item"] }, environ["attach_user_to_groups_queue"]) my_logging( "Message to Attach User {} to Groups on account {} sent: {}". format(resource_name, my_event["Id"], my_message))
def create_account(payer_id, role, email, name, payer_role): try: orgs_client = get_creds("organizations", Id=payer_id, role=role) new_account = orgs_client.create_account( Email=email, AccountName=name, RoleName=payer_role, IamUserAccessToBilling="ALLOW") my_logging("New Account {} creation: {}".format(email, new_account)) return new_account except botocore.exceptions.ClientError as e: my_logging("Could not create account: {}".format(e), "error") return e # ============================================================================# # CALLS FUNCTION ON ROOT ACCOUNT TO CREATE CROSSACCOUNTROLE ON LINKED ACCOUNT # # ============================================================================# # ============================================================================# # ASSUMES NEW CROSS ACCOUNT ROLE AND DELETES OLD CROSS ROLE FROM ROOT ACCOUNT # # ============================================================================# # ============================================================================# # SENDS MESSAGE TO THE ACCOUNT SETUP CONTROLLER QUEUE # # ============================================================================# # ============================================================================# # MAIN FUNCTION # # ============================================================================#
def send_to_s3(bucket_name, file_name, file): try: client = get_creds("s3") return client.put_object(Body=file, Bucket=bucket_name, Key=file_name) except botocore.exceptions.ClientError as e: my_logging("Could not put object on s3: {}".format(e), "error") return e
def lambda_handler(event, context): for account in event['accounts']: account_id = account['Id'] alias = account['Alias'] iam_client = get_creds("iam",Id=account_id) try: #getting the currently account alias account_alias = iam_client.list_account_aliases()['AccountAliases'][0] print("Currently account alias: '{}'. Deleting to update".format(account_alias)) #deleting response = iam_client.delete_account_alias(AccountAlias=account_alias) print("Deleting response: ",response['ResponseMetadata']['HTTPStatusCode']) except IndexError as e: pass finally: #creating account alias response = iam_client.create_account_alias(AccountAlias=alias) try: print("Added account alias in {}. ({})".format(account_id, response['ResponseMetadata']['HTTPStatusCode'])) except Exception as e: print("Error in adding account alias. ERROR:",e)
def list_aws_regions(): try: client = get_creds("ec2") return client.describe_regions()["Regions"] except botocore.exceptions.ClientError as e: my_logging("Could not list regions: {}".format(e), "error") return e
def get_sg_details(acc_Id, Region): try: client = get_creds("ec2", Id=acc_Id, region=Region) return list_resources(client, "SecurityGroups", "describe_security_groups", "NextToken") except botocore.exceptions.ClientError as e: my_logging("Could not get security groups: {}".format(e), "error") return e
def describe_resources(service, acc_Id, Region, resp_item, action, token): my_logging("Describing {} on region {}".format(service, Region)) try: client = get_creds(service, Id=acc_Id, region=Region) return list_resources(client, resp_item, action, token) except botocore.exceptions.ClientError as e: my_logging("Could not list resources: {}".format(e), "error") return e
def update_item(Id, expression, values): try: client = get_creds("dynamodb") response = client.update_item(TableName=environ["accounts_table"], Key={"Id": { "S": Id }}, ReturnValues="ALL_NEW", ReturnConsumedCapacity="TOTAL", ReturnItemCollectionMetrics="SIZE", UpdateExpression=expression, ExpressionAttributeValues={":v": values}) my_logging("Items recorded: {}".format(response)) return response except botocore.exceptions.ClientError as e: my_logging("Could not record items: {}".format(e), "error") return e
def lambda_handler(event, context): account_id = event['Id'] iam_client = get_creds('iam', Id=account_id) response = iam_client.update_account_password_policy( MinimumPasswordLength=14, RequireSymbols=True, RequireNumbers=True, RequireUppercaseCharacters=True, RequireLowercaseCharacters=True, AllowUsersToChangePassword=True, MaxPasswordAge=60, PasswordReusePrevention=24) try: print("Password policy updated. ({})".format( response['ResponseMetadata']['HTTPStatusCode'])) except Exception as e: print("Error in updating password policy. ERROR:", e)
def create_trail(): #creating cloudtrail in the new account cloudtrail_client = octopus.get_creds('cloudtrail') try: #creating trail cloudtrail_response = cloudtrail_client.create_trail( Name=name_trail, S3BucketName=bucket_cloudtrail, IsMultiRegionTrail=True) print("Success: ", cloudtrail_response['TrailARN']) try: #after created, we need to call another function to start logging the trail cloudtrail_client.start_logging(Name=cloudtrail_response['Name']) except Exception as e: print("Error in start to logging. ERROR:", e) except Exception as e: print("Error in creating. ERROR:", e)
def lambda_handler(event,context): # Event Sample # {"saml_xml":"", "bucket_name":"", "Id":"", "idp_name":""} # Gets credentials for IAM Client global iam_client iam_client = get_creds("iam",Id=event["Id"]) # Name of SAML file generated by ADFS saml_xml = event["saml_xml"] # Gets SAML xml Document from S3 saml_doc = get_file_from_s3( event["bucket_name"], "files/{}".format(saml_xml) ) # Tryes to create idp on account idp = create_idp(event["idp_name"],saml_doc) # If IDP already exists, updates it if isinstance(idp,botocore.exceptions.ClientError) and \ idp.response["Error"]["Code"] == "EntityAlreadyExists": update_idp(event["Id"],event["idp_name"],saml_doc)
def verify_account_exist(payer_id, role): orgs_client = get_creds("organizations", Id=payer_id, role=role)
def update_policy_bucket(acc_id_new): #assume role in cloudtrail account s3_client_sts = octopus.get_creds("s3", Id=acc_id_trail) bucket_empty = False try: #getting the bucket policy bucket_policy = s3_client_sts.get_bucket_policy( Bucket=bucket_cloudtrail) account_arns = loads( bucket_policy['Policy'])['Statement'][1]['Resource'] except botocore.exceptions.ClientError as e: if "NoSuchBucketPolicy" in str(e): #there is no policy in the bucket, we need to create then bucket_empty = True account_arn = 'arn:aws:s3:::%s/AWSLogs/%s/*' % (bucket_cloudtrail, acc_id_new) if bucket_empty: account_arns = account_arn if bucket_empty or account_arn not in account_arns: if not bucket_empty: #if the bucket policy is not empty, we add in the list and sort it try: account_arns.append(account_arn) except AttributeError: #when occur this error is because there is only one element in the resource and it is classified as str #so we need to convert to list to add multiples accounts account_arns = account_arns.split() account_arns.append(account_arn) account_arns = sorted(account_arns, reverse=True) #print(account_arns) #we neeed to use the policy from bucket to update with the new account added new_bucket_policy = { "Version": "2012-10-17", "Statement": [{ "Sid": "AWSCloudTrailAclCheck20150319", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::" + bucket_cloudtrail }, { "Sid": "AWSCloudTrailWrite20150319", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "s3:PutObject", "Resource": account_arns, "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } }] } s3_client_sts.put_bucket_policy(Bucket=bucket_cloudtrail, Policy=dumps(new_bucket_policy))
def main_function(event): # Variables resource = literal_eval(record["body"])["resource"] resource_name_tag = literal_eval(record["body"])["resource_name_tag"] token_name = literal_eval(record["body"])["token_name"] account = literal_eval(record["body"])["account"] my_logging("MessageId {} for account {}".format(record["messageId"], account["Id"])) # Assumes linked account role with IAM service my_logging("Setting up IAM Service...") iam_client = get_creds("iam", Id=account["Id"]) # List Selected Resource on account resource_list = list_resources( iam_client, resource, literal_eval(record["body"])["action_list_resource"], token_name) create_dynamo_structure_iam(resource, account["Id"]) # Iterates through resource listing policies my_logging("Analysing %s one by one..." % resource) for item in resource_list: my_logging(item) item["Policies"] = [] try: # Dict with parameters to list resource's inline policies parameters = {resource_name_tag: item[resource_name_tag]} inline_policies = list_resources( iam_client, "PolicyNames", literal_eval(record["body"])["action_list_resource_policies"], token_name, **parameters) except Exception as e: my_logging( "Could not list inline policies for %s %s: %s" % (str(resource_name_tag), str(item[resource_name_tag]), str(e)), "error") for policy in inline_policies: try: # Creates dict with parameters used to get policy parameters = { resource_name_tag: item[resource_name_tag], "PolicyName": policy } inline_doc = list_resources( iam_client, "PolicyDocument", literal_eval(record["body"])["action_get_resource_policy"], token_name, **parameters) item["Policies"].extend({ "PolicyName": policy, "PolicyDocument": inline_doc }) except Exception as e: my_logging( "Could not retrieve details for policy %s: %s" % (str(policy), str(e)), "error") try: # Dict with parameters to list resource"s attached policies parameters = {resource_name_tag: item[resource_name_tag]} attached_polices = list_resources( iam_client, "AttachedPolicies", literal_eval(record["body"])["action_list_attached_policies"], token_name, **parameters) except Exception as e: my_logging( "Could not list attached policies for %s %s: %s " % (str(resource_name_tag), str(item[resource_name_tag]), str(e)), "error") for i in attached_polices: try: # Creates dict with parameters used to get policy versions policy_details = list_resources(iam_client, "Versions", "list_policy_versions", token_name, PolicyArn=i["PolicyArn"]) except Exception as e: my_logging( 'Could not list versions of policy for %s %s: %s' % (str(resource_name_tag), str( item[resource_name_tag]), str(e)), "error") try: # Select default policy and save the data about it for sub in policy_details: if sub["IsDefaultVersion"]: document = iam_client.get_policy_version( PolicyArn=i["PolicyArn"], VersionId=sub["VersionId"]) item["Policies"].append({ "PolicyName": i["PolicyName"], "PolicyDocument": document["PolicyVersion"]["Document"], "DocumentVersion": sub["VersionId"] }) except Exception as e: my_logging( "Could not get document policy for %s %s: %s" % (str(resource_name_tag), str( item[resource_name_tag]), str(e)), "error") try: for policy in item["Policies"]: # Finds AdministratorAccess Policy if policy["PolicyName"] == "AdministratorAccess": try: msg = { "Alert": "Policy AdministratorAccess found attached", "Id": account["Id"], "Email": account["Email"], resource_name_tag: item[resource_name_tag], "Policy": policy } my_logging( send_sqs( msg, environ["sqs_url_AdministratorAccess"])) my_logging( send_sns( "Alert - AdministratorAccess Policy Found", msg, environ["sns_topic_administratorAccess"])) except Exception as e: my_logging(e, "error") # Iterates through policies and finds those with full access permissions for statement in policy["PolicyDocument"]["Statement"]: if isinstance(statement["Action"], str): is_full_access(statement["Action"], account["Id"], account["Email"], resource_name_tag, item[resource_name_tag], policy, environ["sqs_url_fullaccess"]) else: for action in statement["Action"]: is_full_access(action, account["Id"], account["Email"], resource_name_tag, item[resource_name_tag], policy, environ["sqs_url_fullaccess"]) except Exception as e: my_logging( "Could not verify if policies are too permissive. %s %s: %s" % (str(resource_name_tag), str( item[resource_name_tag]), str(e)), "error") item["CreateDate"] = str(item["CreateDate"]) if "PasswordLastUsed" in item: item["PasswordLastUsed"] = str(item["PasswordLastUsed"]) print( update_item( account["Id"], "SET Services.IAM.{}_list = list_append(Services.IAM.{}_list,:v)" .format(resource, resource), {"L": [{ "S": str(item) }]})) print("List of {} extracted: {}".format(resource, resource_list)) return my_logging("Execution finished")
# # # ============================================================================# # ============================================================================# # # # ============================================================================# # ============================================================================# # # # ============================================================================# # ============================================================================# # # # ============================================================================# client = get_creds("iam", Id=acc_id) # ============================================================================# # RECORDS ITEMS ON DYNAMODB TABLE # # ============================================================================# def update_item(Id, expression, values): try: client = get_creds("dynamodb") response = client.update_item(TableName=environ["accounts_table"], Key={"Id": { "S": Id }}, ReturnValues="ALL_NEW", ReturnConsumedCapacity="TOTAL",
from octopus import get_creds, query_items, send_sqs from json import dumps, loads from os import environ import botocore lambda_client = get_creds("lambda") sqs_client = get_creds("sqs") # Main function def lambda_handler(event, context): # Verifies what resource is in execution and sets variables according if event["resource"] == "iam": resources = ["Roles", "Users", "Groups"] sqs_url = environ["iam_queue"] elif event["resource"] == "instances": resources = ["ec2", "rds"] sqs_url = environ["instances_queue"] payer_accounts = query_items(environ["dynamo_table"], environ["index"], "Id,Email,#s", "#key = :v", { "#key": "IsLinked", "#s": "Status" }, {":v": { "S": "False" }}) accounts = [] for account in payer_accounts: get_accounts = loads(