예제 #1
0
def get_role_names_policy_attached_to(policy_name,
                                      iam_client=None,
                                      logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    policy = get_policy_arn_default_version(policy_name, iam_client)
    if policy['arn'] is not None:
        attached_to_roles = []
        response = iam_client.list_roles()
        for role in response['Roles']:
            role_policies = iam_client.list_attached_role_policies(
                RoleName=role['RoleName'])
            if any(d['PolicyName'] == policy['policy_name']
                   for d in role_policies['AttachedPolicies']):
                attached_to_roles.append(role['RoleName'])
        if len(attached_to_roles) < 1:
            logger.debug("Policy %s is not attached to any roles" %
                         policy_name)
            return None
        else:
            return attached_to_roles
    else:
        logger.debug("No policy with name % found" % policy_name)
        return None
예제 #2
0
def roleback_policy(policy_name, iam_client=None, logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    policy = get_policy_arn_default_version(policy_name)
    if policy is not None:
        arn = policy['arn']
    else:
        error_response = {
            "Error": {
                "Code": "404",
                "Message": "No policy with name %s found" % policy_name
            }
        }
        raise boto_exceptions.ClientError(error_response, "roleback_policy")
    response = iam_client.list_policy_versions(PolicyArn=arn)
    non_default_versions = [
        version for version in response['Versions']
        if version['IsDefaultVersion'] is not True
    ]
    non_default_versions_sorted = sorted(non_default_versions,
                                         key=lambda v: v['VersionId'],
                                         reverse=True)
    newest_non_default_version_id = non_default_versions_sorted[0]['VersionId']
    logger.info("Rolling back policy %s to newest previous version %s" %
                (policy_name, newest_non_default_version_id))
    iam_client.set_default_policy_version(
        PolicyArn=arn, VersionId=newest_non_default_version_id)
예제 #3
0
def delete_ami_and_snapshots(image_id, ec2_client=None, logger=None):
    if ec2_client is None:
        ec2_client = boto3.client("ec2")
    if logger is None:
        logger = core.set_logger()
    decribe_image_response = ec2_client.describe_images(DryRun=False, Owners=["self"], ImageIds=[image_id])
    delete_ami_and_snapshots_from_describe_image_response(decribe_image_response, ec2_client, logger)
예제 #4
0
def delete_ami_and_snapshots_from_describe_image_response(decribe_image_response, ec2_client=None, logger=None):
    if ec2_client is None:
        ec2_client = boto3.client("ec2")
    if logger is None:
        logger = core.set_logger()
    if "Images" in decribe_image_response:
        if len(decribe_image_response["Images"]) > 0:
            for image_json in decribe_image_response["Images"]:
                try:
                    logger.info("Deregsitering image %s" % image_json["ImageId"])
                    ec2_client.deregister_image(DryRun=False, ImageId=image_json["ImageId"])
                except botocore.exceptions.ClientError as e:
                    if e.response["Error"]["Code"] == "InvalidAMIID.Unavailable":
                        logger.info("AMI %s no longer present" % image_json["ImageId"])
                    else:
                        raise Exception("Unexpected error: %s" % e)
                for block_device_mapping in image_json["BlockDeviceMappings"]:
                    logger.info(
                        "Removing associated block device snapshot %s" % block_device_mapping["Ebs"]["SnapshotId"]
                    )
                    ec2_client.delete_snapshot(DryRun=False, SnapshotId=block_device_mapping["Ebs"]["SnapshotId"])
        else:
            logger.warn("Could not find image(s) to remove")
    else:
        logger.warn("Could not find image(s) to remove")
예제 #5
0
def delete_ami_and_snapshots_from_describe_image_response(decribe_image_response, ec2_client=None, logger=None):
    if ec2_client is None:
        ec2_client = boto3.client('ec2')
    if logger is None:
        logger = core.set_logger()
    if 'Images' in decribe_image_response:
        if len(decribe_image_response['Images']) > 0:
            for image_json in decribe_image_response['Images']:
                try:
                    logger.info("Deregsitering image %s" % image_json['ImageId'])
                    ec2_client.deregister_image(
                        DryRun=False,
                        ImageId=image_json['ImageId']
                    )
                except botocore.exceptions.ClientError as e:
                    if e.response['Error']['Code'] == 'InvalidAMIID.Unavailable':
                        logger.info("AMI %s no longer present" % image_json['ImageId'])
                    else:
                        raise Exception("Unexpected error: %s" % e)
                for block_device_mapping in image_json['BlockDeviceMappings']:
                    logger.info(
                        "Removing associated block device snapshot %s" % block_device_mapping['Ebs']['SnapshotId'])
                    ec2_client.delete_snapshot(
                        DryRun=False,
                        SnapshotId=block_device_mapping['Ebs']['SnapshotId']
                    )
        else:
            logger.warn("Could not find image(s) to remove")
    else:
        logger.warn("Could not find image(s) to remove")
예제 #6
0
def delete_ami_and_snapshots(image_id, ec2_client=None, logger=None):
    if ec2_client is None:
        ec2_client = boto3.client('ec2')
    if logger is None:
        logger = core.set_logger()
    decribe_image_response = ec2_client.describe_images(
        DryRun=False,
        Owners=[
            'self'
        ],
        ImageIds=[
            image_id,
        ]
    )
    delete_ami_and_snapshots_from_describe_image_response(decribe_image_response, ec2_client, logger)
예제 #7
0
def delete_non_default_policy_versions(policy_arn,
                                       iam_client=None,
                                       logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    logger.info("Deleting non-default policy versions of policy %s" %
                policy_arn)
    # Delete old policy versions to maintain within the 5 limit
    policy_versions = iam_client.list_policy_versions(PolicyArn=policy_arn)
    for policy_version in policy_versions['Versions']:
        if not policy_version['IsDefaultVersion']:
            logger.debug("Deleting policy version %s of policy %s" %
                         (policy_version['VersionId'], policy_arn))
            iam_client.delete_policy_version(
                PolicyArn=policy_arn, VersionId=policy_version['VersionId'])
예제 #8
0
def delete_all_versions_of_policy(policy_name, iam_client=None, logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    logger.info("Completely deleting poilcy %s and all its versions" %
                policy_name)
    policy = get_policy_arn_default_version(policy_name, iam_client)
    if policy['arn'] is not None:
        attached_to_roles = get_role_names_policy_attached_to(
            policy_name, iam_client)
        if attached_to_roles is not None:
            for role_name in attached_to_roles:
                logger.debug("Detatching policy %s from role %s" %
                             (policy_name, role_name))
                iam_client.detach_role_policy(RoleName=role_name,
                                              PolicyArn=policy['arn'])
        # Remove old versions
        response = iam_client.list_policy_versions(PolicyArn=policy['arn'])
        for version in response['Versions']:
            if version['IsDefaultVersion'] is not True:
                # TODO error handling needed around this call
                logger.debug("Deleting version %s of policy %s" %
                             (version['VersionId'], policy_name))
                iam_client.delete_policy_version(
                    PolicyArn=policy['arn'], VersionId=version['VersionId'])
        # Delete policy as should now only have one version
        logger.debug(
            "Deleting policy %s now all its versions have been deleted" %
            policy_name)
        iam_client.delete_policy(PolicyArn=policy['arn'])
    else:
        error_response = {
            "Error": {
                "Code": "404",
                "Message": "No policy with name %s found" % policy_name
            }
        }
        raise boto_exceptions.ClientError(error_response,
                                          "delete_all_versions_of_policy")
예제 #9
0
def delete_role_and_attached_policies(role_name,
                                      force=False,
                                      iam_client=None,
                                      logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    logger.info("Deleting role %s and all its attached polices" % role_name)
    response = iam_client.list_attached_role_policies(RoleName=role_name)
    for attachment in response['AttachedPolicies']:
        policy = iam_client.get_policy(PolicyArn=attachment['PolicyArn'])
        # Should not delete the policy if it is attached to something else unless force is set to true.
        if policy['Policy']['AttachmentCount'] <= 1 or force is True:
            logger.info(
                "Deleting policy %s and all its versions. It is either only attached to role %s or the force options has been set"
                % (policy['Policy']['PolicyName'], role_name))
            delete_all_versions_of_policy(policy['Policy']['PolicyName'],
                                          iam_client)
    response = iam_client.list_role_policies(RoleName=role_name)
    for inline_policy in response['PolicyName']:
        iam_client.delete_role_policy(RoleName=role_name,
                                      PolicyName=inline_policy)
    iam_client.delete_role(RoleName=role_name)
예제 #10
0
def find_policy_by_name_regex(policy_name_regex, iam_client=None, logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    matching_policies = []
    policies = iam_client.list_policies(
        Scope='Local',
        OnlyAttached=False,
    )
    if policies is not None:
        policy_name_regex = re.compile(policy_name_regex)
        for policy in policies['Policies']:
            if policy_name_regex.match(policy['PolicyName']):
                policy_dict = {
                    'policy_name': policy['PolicyName'],
                    'arn': policy['Arn'],
                    'default_version': policy['DefaultVersionId']
                }
                matching_policies.append(policy_dict)
    if len(matching_policies) < 1:
        logger.debug("No policies found whose name matched regex: %s" %
                     policy_name_regex)
        return None
예제 #11
0
def update_policy_array(policy_arn,
                        policy_default_version,
                        sid,
                        array_key,
                        item,
                        to_contain=False,
                        iam_client=None,
                        logger=None):
    if iam_client is None:
        iam_client = boto3.client('iam')
    if logger is None:
        logger = core.set_logger()
    # Delete old policy versions to maintain within the 5 limit
    delete_non_default_policy_versions(logger, policy_arn)
    # Get the current default policy content
    policy_content = iam_client.get_policy_version(
        PolicyArn=policy_arn, VersionId=policy_default_version)
    policy_doc = policy_content['PolicyVersion']['Document']
    statement = get_policy_statement_by_sid(logger, policy_doc, sid)
    if statement is not None:
        if array_key in statement:
            if not isinstance(statement[array_key], list):
                raise TypeError("Not an array at key %s" % array_key)
            needs_update = False
            if to_contain:
                if item not in statement[array_key]:
                    statement[array_key].append(item)
                    needs_update = True
                else:
                    logger.debug(
                        "Item %s already defined in policy statement %s array key %s. Nothing to do."
                        % (item, sid, array_key))
                    return policy_default_version
            else:
                if item in statement[array_key]:
                    statement[array_key].remove(item)
                    needs_update = True
                else:
                    logger.debug(
                        "Item %s not found in policy statement %s array key %s. Nothing to do."
                        % (item, sid, array_key))
                    return policy_default_version
            if needs_update:
                logger.debug(
                    "Updating policy at statement id %s array key %s" %
                    (sid, array_key))
                logger.debug("New policy document: %s" %
                             json.dumps(policy_doc))
                update = iam_client.create_policy_version(
                    PolicyArn=policy_arn,
                    PolicyDocument=json.dumps(policy_doc),
                    SetAsDefault=True)
                logger.info("IAM policy updated, new policy version: %s" %
                            update['PolicyVersion']['VersionId'])
                return update['PolicyVersion']['VersionId']
        else:
            logger.error("Array not found in statement %s at key %s" %
                         (sid, array_key))
    else:
        logger.error(
            "Statement with Sid %s not found in policy %s version %s" %
            (sid, policy_arn, policy_default_version))
    return None