Skip to main content

A decorator to allow running a function against all AWS accounts in an organization

Project description

Botocove

Run a function against a selection of AWS accounts, or all AWS accounts in an organization, concurrently. By default, opinionated to work with the standard AWS Organization master/member configuration from an organization master account.

  • Fast
  • Easy
  • Dolphin Themed 🐬

A simple decorator for functions to remove time and complexity burden. Uses ThreadPoolExecutor to run boto3 sessions against one to all of your AWS accounts at (nearly!) the same speed as running against one.

Wrap a function in @cove and inject an assumed role session into every account required, gathering all results into a dictionary.

Warning: this tool gives you the potential to make dangerous changes at scale. Test carefully and make idempotent changes! Please read available arguments to understand safe experimentation with this package.

Requirements

An IAM user with sts:assumerole privilege, and accounts that have a trust relationship to the IAM user's account.

By default, the IAM user is expected to be in an AWS Organization Master account

Default (customisable if unsuitable) expectations are:

In the organization master account:

  • IAM permissions sts:assumerole, sts:get-caller-identity and organizations:list-accounts

In the organization accounts:

  • An AccountOrganizationAccessRole role

See the Arguments section for how to change these defaults to work with any accounts.

Quickstart

A function written to interact with a boto3 session can now be called with a session from every account required in your AWS organization, assuming a role in each account.

For example:

A standard approach: this function takes a boto3 session and gets all IAM users from a single AWS account

import boto3


def get_iam_users(session):
    iam = session.client("iam", region_name="eu-west-1")
    all_users = iam.get_paginator("list_users").paginate().build_full_result()
    return all_users

def main():
    session = boto3.session.Session(profile_name="my_dev_account")
    users = get_iam_users(session)
    print(users) # A single account's IAM users

Now with @cove: a session for every account in the organization is injected by the decorator. A safe example to run as a test!

import boto3
from botocove import cove

@cove()
def get_iam_users(session):
    iam = session.client("iam", region_name="eu-west-1")
    all_users = iam.get_paginator("list_users").paginate().build_full_result()
    return all_users

def main():
    # No session passed as the decorator injects it
    all_results = get_iam_users() 
    # Now returns a Dict with keys Results, Exceptions and FailedAssumeRole
    
    # A list of dictionaries for each account, with account details included.
    # Each account's get_iam_users return is in a "Result" key.
    print(all_results["Results"]) 
    
    # A list of dictionaries for each account that raised an exception
    print(all_results["Exceptions"])

    # A list of dictionaries for each account that could not be assumed into
    print(all_results["FailedAssumeRole"])

Arguments

Cove

@cove():

Uses boto3 credential chain to get every AWS account within the organization, assume the OrganizationAccountAccessRole in it and run the wrapped function with that role.

Equivalent to: @cove(target_ids=None, ignore_ids=None, rolename=None, role_session_name=rolename, policy=None, policy_arns=None, assuming_session=None, raise_exception=False, org_master=True)

target_ids: Optional[List[str]]

A list of AWS accounts as strings to attempt to assume role in to. When unset, default attempts to use every available account ID in an AWS organization.

ignore_ids: Optional[List[str]]

A list of AWS account ID's that will not attempt assumption in to. Allows IDs to be ignored.

rolename: Optional[str]

An IAM role name that will be attempted to assume in all target accounts. Defaults to the AWS Organization default, OrganizationAccountAccessRole.

role_session_name: Optional[str]

An IAM role session name that will be passed to each Cove session's sts.assume_role() call. Defaults to the name of the role being used if unset.

policy: Optional[str]

A policy document that will be used as a session policy in each Cove session's sts.assume_role() call. Unless the value is None, it is passed through via the Policy parameter.

policy_arns: Optional[List[str]]

A list of managed policy ARNs that will be used as a session policy in each Cove session's sts.assume_role() call. Unless the value is None, it is passed through via the PolicyArns parameter.

assuming_session: Optional[Session]

A Boto3 boto3.session.Session() object that will be used to call sts:assumerole. If not provided, cove will instantiate one which will use the standard boto3 credential chain.

raise_exception: bool

Defaults to False. Default behaviour is that exceptions are not raised from decorated function. This is due to cove running asynchronously and preferring to resolve all tasks and report their results instead of exiting early.

raise_exception=True will allow a full stack trace to escape on the first exception seen; but will not gracefully or consistently interrupt running tasks. It is vital to run interruptible, idempotent code with this argument as True.

org_master: bool

Defaults to True. When True, will leverage the Boto3 Organizations API to list all accounts in the organization, and enrich each CoveSession with information available (Id, Arn, Name).

org_master=False means target_ids must be provided (as no list of accounts can be created for you), as well as likely rolename. Only Id will be available to CoveSession.

CoveSession

Cove supplies an enriched Boto3 session to each function called. Account details are available with the session_information attribute.

Otherwise, it functions exactly as calling boto3 would.

@cove()
def do_nothing(session: CoveSession):
    print(session.session_information) # Outputs a dict of known information
    # This function runs no boto3-specific API, but does test that a role
    # can be assumed

Return values

Wrapped functions return a dictionary. Each value contains List[Dict[str, Any]]:

{
    "Results": results: 
    "Exceptions": exceptions,
    "FailedAssumeRole": invalid_sessions,
}

An example of cove_output["Results"]:

[ # A list of dictionaries per account called
    {
    'Id': '123456789010',
    'Email': 'email@address.com',
    'Name': 'account-name',
    'Status': 'ACTIVE',
    'AssumeRoleSuccess': True,
    'Result': wrapped_function_return_value # Result of wrapped func
    } 
] 

botocove?

It turns out that the Amazon's Boto dolphins are solitary or small-group animals, unlike the large pods of dolphins in the oceans. This killed my "large group of boto" idea, so the next best idea was where might they all shelter together... a cove!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

botocove-1.4.1.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

botocove-1.4.1-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

Details for the file botocove-1.4.1.tar.gz.

File metadata

  • Download URL: botocove-1.4.1.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.12 CPython/3.8.12 Linux/5.4.0-1065-azure

File hashes

Hashes for botocove-1.4.1.tar.gz
Algorithm Hash digest
SHA256 e506f9ab69a4a4232ddfa52d4bfa05f8196884d31dac3e8182e5ae158bcefcbe
MD5 47bda434768afc27cb6d5d1cf46f6934
BLAKE2b-256 951a1e95725a24979678020d5ca7db7ea4297c458546853e6ac37f7b04db1600

See more details on using hashes here.

File details

Details for the file botocove-1.4.1-py3-none-any.whl.

File metadata

  • Download URL: botocove-1.4.1-py3-none-any.whl
  • Upload date:
  • Size: 12.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.12 CPython/3.8.12 Linux/5.4.0-1065-azure

File hashes

Hashes for botocove-1.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2864598beea0de50032f21fdc7a4b7dbe78f7e2b18861c70996422ad2eba80c9
MD5 16a32967a1eb45267b34abcccebc33ed
BLAKE2b-256 70f331d2b5eeb37cee04d2a605565bef96c7b09df17af79ab5031bf4b58eb189

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page