aws-samples / aws-cost-explorer-report

Python SAM Lambda module for generating an Excel cost report with graphs, including month on month cost changes. Uses the AWS Cost Explorer API for data.
MIT No Attribution
432 stars 166 forks source link

Prerequisites to run this tool #15

Closed minuki closed 6 years ago

minuki commented 6 years ago

Thank you for sharing this useful tool.

I tried this tool on my new account and works great. But I had 2 minor issues while running on lambda for the first time. So just for sharing. It would be great if it mentioned at 'prerequisite' section.

1) AWS organizations should be enabled. 2) Cost explorer should be enabled.

-- [ERROR] 2018-09-20T01:45:55.499Z Getting Account names failed Traceback (most recent call last): File "/var/task/lambda.py", line 89, in init self.accounts = self.getAccounts() File "/var/task/lambda.py", line 99, in getAccounts for response in response_iterator: File "/var/runtime/botocore/paginate.py", line 255, in iter response = self._make_request(current_kwargs) File "/var/runtime/botocore/paginate.py", line 332, in _make_request return self._method(current_kwargs) File "/var/runtime/botocore/client.py", line 314, in _api_call return self._make_api_call(operation_name, kwargs) File "/var/runtime/botocore/client.py", line 612, in _make_api_call raise error_class(parsed_response, operation_name) botocore.errorfactory.AWSOrganizationsNotInUseException: An error occurred (AWSOrganizationsNotInUseException) when calling the ListAccounts operation: Your account is not a member of an organization.**

An error occurred (AccessDeniedException) when calling the GetCostAndUsage operation: User not enabled for cost explorer access: ClientError Traceback (most recent call last): File "/var/task/lambda.py", line 394, in main_handler costexplorer.addReport(Name="Total", GroupBy=[],Style='Total',IncSupport=True) File "/var/task/lambda.py", line 272, in addReport Filter=Filter File "/var/runtime/botocore/client.py", line 314, in _api_call return self._make_api_call(operation_name, kwargs) File "/var/runtime/botocore/client.py", line 612, in _make_api_call raise error_class(parsed_response, operation_name) botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetCostAndUsage operation: User not enabled for cost explorer access

davfaulk commented 6 years ago

Thank you for the feedback. Organizations isn't technically required, as the report will run without (just log that exception and carry on), but GetCostAndUsage access is. Can I ask what was blocking access to GetCostAndUsage? Was it an IAM policy, or was it an option on enabling cost tools?

minuki commented 6 years ago

You're right. As you mentioned organization is not mandatory and help to display account label. Blocking access to GetCostAndUsage was just simple option on AWS console. (Maybe everyone enabled this option but I tested with new account with default setting.) screen shot 2018-09-21 at 9 13 50 am

davfaulk commented 6 years ago

Thank you - I had wondered abiut this, but have never tested a brand new account myself. Will update readme.

eKuG commented 3 years ago

Hey @davfaulk can you also tell me how to list all services by resource tags? I'm getting this error: botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetTagValues operation: User: arn:aws:sts::678258727640:assumed-role/aws-cost-explorer-report-CostExplorerReportLambdaI-129HLOI5OJI1V/CostExplorerReportLambda is not authorized to perform: tag:GetTagValuesTotal chart

Wrote this piece of code: `def getResourcetags(self): tags = {} restag = boto3.client('resourcegroupstaggingapi', region_name='ap-south-1') response = restag.get_tag_values( PaginationToken='string', Key='string' )

while 'PaginationToken' in response and response['PaginationToken']:

    #     token = response['PaginationToken']
    #     response = restag.get_resources(ResourcesPerPage=50, PaginationToken=token)
    for response in response_iterator:
        for res in response['tags']:
            tags[res['Values']] = res
    return tags`