예제 #1
0
def get_accounts():
    if not authenticated():
        log.error("Failed to authenticate")
        return []

    if (ArgumentParser.args.aws_assume_current
            and not ArgumentParser.args.aws_dont_scrape_current):
        log.warning(
            "You specified --aws-assume-current but not --aws-dont-scrape-current! "
            "This will result in the same account being scraped twice and is likely not what you want."
        )

    if ArgumentParser.args.aws_role and ArgumentParser.args.aws_scrape_org:
        accounts = [
            AWSAccount(aws_account_id, {}, role=ArgumentParser.args.aws_role)
            for aws_account_id in get_org_accounts(
                filter_current_account=not ArgumentParser.args.
                aws_assume_current) if aws_account_id not in
            ArgumentParser.args.aws_scrape_exclude_account
        ]
        if not ArgumentParser.args.aws_dont_scrape_current:
            accounts.append(AWSAccount(current_account_id(), {}))
    elif ArgumentParser.args.aws_role and ArgumentParser.args.aws_account:
        accounts = [
            AWSAccount(aws_account_id, {}, role=ArgumentParser.args.aws_role)
            for aws_account_id in ArgumentParser.args.aws_account
        ]
    else:
        accounts = [AWSAccount(current_account_id(), {})]

    return accounts
예제 #2
0
def authenticated() -> bool:
    try:
        _ = current_account_id()
    except botocore.exceptions.NoCredentialsError:
        log.error("No AWS credentials found")
        return False
    except botocore.exceptions.ClientError as e:
        if e.response["Error"]["Code"] == "AuthFailure":
            log.error(
                "AWS was unable to validate the provided access credentials")
        elif e.response["Error"]["Code"] == "InvalidClientTokenId":
            log.error("AWS was unable to validate the provided security token")
        elif e.response["Error"]["Code"] == "ExpiredToken":
            log.error("AWS security token included in the request is expired")
        else:
            raise
        return False
    return True
예제 #3
0
def main():
    if ArgumentParser.args.aws_role and ArgumentParser.args.aws_account:
        accounts = [
            AWSAccount(aws_account_id, {}, role=ArgumentParser.args.aws_role)
            for aws_account_id in ArgumentParser.args.aws_account
        ]
    else:
        accounts = [AWSAccount(current_account_id(), {})]

    if len(accounts) != 1:
        log.error("This tool only supports a single account at a time")
        sys.exit(1)

    account = accounts[0]
    session = aws_session(account.id, account.role)
    client = session.client("s3")
    bucket = ArgumentParser.args.aws_s3_bucket
    prefix = ArgumentParser.args.aws_s3_prefix

    mtime = (
        make_valid_timestamp(datetime.fromisoformat(ArgumentParser.args.aws_s3_mtime))
        if ArgumentParser.args.aws_s3_mtime
        else None
    )

    is_truncated = True
    max_keys = 500
    key_marker = None
    version_id_marker = None

    while is_truncated is True:
        if key_marker and version_id_marker:
            version_list = client.list_object_versions(
                Bucket=bucket,
                MaxKeys=max_keys,
                Prefix=prefix,
                KeyMarker=key_marker,
                VersionIdMarker=version_id_marker,
            )
        elif key_marker:
            version_list = client.list_object_versions(
                Bucket=bucket, MaxKeys=max_keys, Prefix=prefix, KeyMarker=key_marker
            )
        else:
            version_list = client.list_object_versions(
                Bucket=bucket, MaxKeys=max_keys, Prefix=prefix
            )
        is_truncated = version_list.get("IsTruncated", False)
        key_marker = version_list.get("NextKeyMarker")
        version_id_marker = version_list.get("NextVersionIdMarker")

        delete_objects = []
        versions = version_list.get("Versions", [])
        versions.extend(version_list.get("DeleteMarkers", []))
        for v in versions:
            object_version = v["VersionId"]
            object_key = v["Key"]
            # object_size = v["Size"]
            object_mtime = make_valid_timestamp(v["LastModified"])

            if mtime and object_mtime > mtime:
                log.debug(
                    f"Object {object_key} with mtime {object_mtime} newer than mtime {mtime}"
                )
                continue
            if (
                ArgumentParser.args.aws_s3_pattern
                and bool(re.search(ArgumentParser.args.aws_s3_pattern, str(object_key)))
                is False
            ):
                log.debug(
                    f"Object {object_key} does not match {ArgumentParser.args.aws_s3_pattern}"
                )
                continue
            log.info(
                (
                    f"Object {object_key} with version {object_version} and mtime"
                    f" {object_mtime} matches {ArgumentParser.args.aws_s3_pattern}"
                )
            )
            delete_objects.append({"VersionId": object_version, "Key": object_key})
        try:
            if len(delete_objects) > 0:
                str_delete_objects = "\n".join([do["Key"] for do in delete_objects])
                if ArgumentParser.args.aws_s3_yes is True:
                    confirm_delete = True
                else:
                    confirm_delete = button_dialog(
                        title=f"Delete {len(delete_objects)} S3 objects?",
                        text=f"Really delete these objects?\n{str_delete_objects}",
                        buttons=[("Yes", True), ("No", False), ("Abort", None)],
                    ).run()

                if confirm_delete is None:
                    sys.exit(0)
                elif confirm_delete is True:
                    response = client.delete_objects(
                        Bucket=bucket, Delete={"Objects": delete_objects}
                    )
                    log.info(f"Delete response {response}")
        except Exception:
            log.exception("Something went wrong trying to delete")