# -*- coding: utf-8 -*-
from setuptools import setup

modules = \
['aws_org_inventory']
install_requires = \
['boto-collator-client>=0.1.1,<0.2.0',
 'boto3>=1.18.52,<2.0.0',
 'botocove>=1.3.1,<2.0.0',
 'pandas>=1.3.3,<2.0.0']

entry_points = \
{'console_scripts': ['aws-org-inventory = aws_org_inventory:main']}

setup_kwargs = {
    'name': 'aws-org-inventory',
    'version': '0.5.2.post1',
    'description': " Dumps to CSV all the resources in an organization's member accounts",
    'long_description': '# AWS Org Inventory\n\nDumps to CSV all the resources in an organization\'s member accounts.\n\nSet your environment\'s AWS_PROFILE and AWS_DEFAULT_REGION variables.\n\nThe AWS_PROFILE should be configured to use a role in the organization management account that can assume OrganizationAccountAccessRole in the member accounts.\n\nRedirect the dumper\'s output to save the file.\n\nThe dumper uses Botocove to query each member account.\n\n## Why?\n\nThis tool fills in the gaps in AWS Config\'s inventory.\n\nSadly [AWS Config](https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html) supports only a subset of all the resource types you may have.\n\nAWS Config\'s organization aggregators are great, but they may not update instantly with new resources.\n\n## Installation\n\nThe package is published to PyPy as aws-org-inventory, so you can install it with pip or anything equivalent.\n\n```\npip install aws-org-inventory\n```\n\n## Basic example\n\nConfigure environment:\n\n```bash\nexport AWS_PROFILE=OrgMgmtRole\nexport AWS_DEFAULT_REGION=eu-west-1\n```\n\nDump inventory of CloudWatch log groups:\n\n```bash\naws-org-inventory logs describe_log_groups logGroups\n```\n\nDump inventory of support cases:\n\n```bash\naws-org-inventory support describe_cases cases\n```\n\nDump inventory of EC2 key pairs:\n\n```bash\naws-org-inventory ec2 describe_key_pairs KeyPairs\n```\n\nDump inventory of account alises:\n\n```bash\naws-org-inventory iam list_account_alises AccountAliases\n```\n\nTry doing those with AWS Config!\n\nThe successful command outputs a CSV file to standard out. (TODO: show example of columns from each of the example commands)\n\n## Advanced example\n\nSay you need to collect inventory about AWS Config itself. You want to know which config recorders exist and how the delivery streams are configured. You want to do this across multiple regions and multiple organizations.\n\naws-org-inventory doesn\'t yet support multiple API calls, multiple regions, or multiple organizations in a single invocation. So one way or another you\'ll need to perform multiple invocations.\n\n[GNU Parallel](https://www.gnu.org/software/parallel/) offers a neat way to do this. First you export a bash function that takes a profile and a region as parameters and saves the results of all the invocations of aws-org-inventory. Then you invoke the function via parallel passing the a list of profiles and a list of regions. parallel iterates over the cartesian product of the parameters to collect all the data.\n\nYou can use a script like this to drive the whole process.\n\n```bash\ncd "$(mktemp --dir)"\n\ncollect() {\n    profile="${1}"\n    region="${2}"\n\n    AWS_PROFILE="${profile}" \\\n    AWS_DEFAULT_REGION="${region}" \\\n    aws-org-inventory config describe_configuration_recorders ConfigurationRecorders \\\n    > "configuration_recorders__${profile}__${region}.csv"\n\n    AWS_PROFILE="${profile}" \\\n    AWS_DEFAULT_REGION="${region}" \\\n    aws-org-inventory config describe_delivery_channels DeliveryChannels \\\n    > "delivery_channels__${profile}__${region}.csv"\n}\n\nexport -f collect\n\ntime parallel --max-procs 1 collect \\\n::: org_A org_B \\\n::: us-east-1 eu-west-1\n```\n\nWith some patience you will end up with a result like this.\n\n```text\n$ tree\n.\n├── configuration_recorders__org_A__eu-west-1.csv\n├── configuration_recorders__org_A__us-east-1.csv\n├── configuration_recorders__org_B__eu-west-1.csv\n├── configuration_recorders__org_B__us-east-1.csv\n├── delivery_channels__org_A__eu-west-1.csv\n├── delivery_channels__org_A__us-east-1.csv\n├── delivery_channels__org_B__eu-west-1.csv\n├── delivery_channels__org_B__us-east-1.csv\n```\n\nPatience is needed because this is a really inefficient way to collect from multiple APIs and multiple regions. This can definitely be improved in aws-org-inventory itself. I\'ll be working on that whenver I have the time and the notion.\n\nBut isn\'t the whole point of parallel to run things in ... parallel? Why is max-procs set to 1? \n\nOne reason is to avoid failures from API rate limiting. For example, a single AWS account can handle only a certain frequency of DescribeAccount calls per second.\n\nAnother reason is to avoid memory exhaustion which may cause the tool to crash. It needs an amount of memory proportial to the number of accounts in the organization.\n\nI think both of these problems can be fixed in the tools itself such that in the future using GNU Parallel may no longer be necessary. See [aws_recon](https://github.com/darkbitio/aws-recon) for inspiration.\n\n## General use\n\nTo derive arguments for other use cases, check the boto service documentation.\n\nThe value passed to the boto3.client method that would instantiate a client for the service is parameter 1.\n\nFind the method of that client that `list`s or `describe`s the resource type that you want to dump.\n\nThe name of the method is parameter 2.\n\nFind in the method\'s response syntax the top-level key for the list of objects.\n\nThe name of the key is parameter 3.\n\n## Error output\n\nOn stderr you will always see a summary of the botocove result and any exceptions. These exceptions may reveal problems such as an incorrect command invocation, a misconfigured AWS account, or a bug in the program (feel free to report those!)\n\n```text\n{\'Results\': 237, \'Exceptions\': 11, \'FailedAssumeRole\': 0}\n```\n\nIf Botocove fails to get a session for an account, That account\'s resources will not be included in the main output. Botocove will output the account ID to stderr like this:\n\n```text\nInvalid session Account IDs as list: [\'111111111111\']\n```\n\n\nIf the AWS API raises an exception, its error output will printed to standard error and the account\'s details will not be included in the main output.\n\nFor example, if you try to get the enabled standards in an account not enabled for Security Hub:\n\n```text\n[{\'Id\': \'111111111111\', \'Email\': \'111111111111@example.com\', \'Name\': \'Account 1\', \'Status\': \'ACTIVE\', \'AssumeRoleSuccess\': True, \'ExceptionDetails\': [InvalidAccessException(\'An error occurred (InvalidAccessException) when calling the GetEnabledStandards operation: Account 111111111111 is not subscribed to AWS Security Hub\'), ...]}\n```\n\n## Development\n\nA GitHub Actions workflow contains the continuous integration (CI) tests. You can run it locally using [act](https://github.com/nektos/act).\n\n```bash\nact\n```\n\nAnother GitHub Actions workflow publishes to the\n[Python Package Index (PyPI)](https://pypi.org/project/aws-org-inventory/). Run the workflow locally like this (the final publish step will probably fail):\n\n```\nact release\n```\n\n## TODO\n\nTODO: query multiple regions (see aws-boto-multiregion-client for example)\n\nTODO: export to JSON by default to simplify the output format (tabularization is tricky)\n\nTODO: ensure that org management account is included in results\n\nTODO: give example of how to use AwsOrgInventory class in other applications\n\nTODO: improve CLI (monkey patch awscli.clidriver.CLIOperationCaller._make_client_call)\n\nTODO: Use boto\'s service model to automate the parameters given a resource type\n\nTODO: improve error handling\n',
    'author': 'Iain Samuel McLean Elder',
    'author_email': 'iain@isme.es',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/iainelder/aws-org-inventory',
    'py_modules': modules,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
