-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for AWS Support Subscriptions
Removing .idea folder Fixing linter errors Ignoring Pycharm files Implementing Code Review Comments Removing references to enterprise support, making the process a bit more generic going forward. Making it run on every execution rather than just on account creation, adding on some logic for detecting desired support type and when to do ticket creation. Also updated logging throughout to be a bit more verbose to assist debugging future issues. Changed Support Subscription to run on account creation Updating documentation Adding in the exact usecase, with emphasis
- Loading branch information
stewartwallace
committed
Apr 10, 2020
1 parent
19b3a28
commit 471929e
Showing
6 changed files
with
159 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,13 +18,15 @@ The OU name is the name of the direct parent of the account. If you want to move | |
- Create and update account alias. | ||
- Account tagging. | ||
- Allow the account access to view its own billing. | ||
- Set up support subscriptions during account provisioning | ||
|
||
### Currently not supported | ||
|
||
- Updating account names | ||
- Updating account email addresses | ||
- Removing accounts | ||
- Handling root account credentials and MFA | ||
- Changing the support subscription of an account. | ||
|
||
### Configuration Parameters | ||
|
||
|
@@ -33,6 +35,9 @@ The OU name is the name of the direct parent of the account. If you want to move | |
- `email`: Email associated by the account, must be valid otherwise it is not possible to access as root user when needed | ||
- `delete_default_vpc`: `True|False` if Default VPCs need to be delete from all AWS Regions. | ||
- `allow_billing`: `True|False` if the account see its own costs within the organization. | ||
- `support_level`: `basic|enterprise` ADF will raise a ticket to add the account to an existing AWS support subscription when an account is created. Currently only supports basic or enterprise. | ||
**NB: This is for activating enterprise support on account creation only. As a prerequisite your organization master account must already have enterprise support activated** | ||
|
||
- `alias`: AWS account alias. Must be unique globally otherwise cannot be created. Check [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/console_account-alias.html) for further details. If the account alias is not created or already exists, in the Federation login page, no alias will be presented | ||
- `tags`: list of tags associate to the account. | ||
|
||
|
@@ -47,6 +52,7 @@ accounts: | |
email: [email protected] | ||
allow_billing: False | ||
delete_default_vpc: True | ||
support_level: enterprise | ||
alias: prod-company-1 | ||
tags: | ||
- created_by: adf | ||
|
@@ -62,6 +68,7 @@ accounts: | |
email: [email protected] | ||
allow_billing: True | ||
delete_default_vpc: False | ||
support_level: basic | ||
alias: test-company-11 | ||
tags: | ||
- created_by: adf | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/provisioner/src/support.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
"""Support module used throughout the ADF | ||
""" | ||
from enum import Enum | ||
from botocore.config import Config | ||
from botocore.exceptions import ClientError, BotoCoreError | ||
from logger import configure_logger | ||
from .account import Account | ||
|
||
|
||
LOGGER = configure_logger(__name__) | ||
|
||
|
||
class SupportLevel(Enum): | ||
BASIC = "basic" | ||
DEVELOPER = "developer" | ||
BUSINESS = "business" | ||
ENTERPRISE = "enterprise" | ||
|
||
|
||
class Support: # pylint: disable=R0904 | ||
"""Class used for accessing AWS Support API | ||
""" | ||
_config = Config(retries=dict(max_attempts=30)) | ||
|
||
def __init__(self, role): | ||
self.client = role.client("support", region_name='us-east-1', config=Support._config) | ||
|
||
def get_support_level(self) -> SupportLevel: | ||
""" | ||
Gets the AWS Support Level of the current Account | ||
based on the Role passed in during the init of the Support class. | ||
:returns: | ||
SupportLevels Enum defining the level of AWS support. | ||
:raises: | ||
ClientError | ||
BotoCoreError | ||
""" | ||
try: | ||
severity_levels = self.client.get_severity_levels()['severityLevels'] | ||
available_support_codes = [level['code'] for level in severity_levels] | ||
|
||
# See: https://aws.amazon.com/premiumsupport/plans/ for insights into the interpretation of | ||
# the available support codes. | ||
|
||
if 'critical' in available_support_codes: # Business Critical System Down Severity | ||
return SupportLevel.ENTERPRISE | ||
if 'urgent' in available_support_codes: # Production System Down Severity | ||
return SupportLevel.BUSINESS | ||
if 'low' in available_support_codes: # System Impaired Severity | ||
return SupportLevel.DEVELOPER | ||
|
||
return SupportLevel.BASIC | ||
|
||
except (ClientError, BotoCoreError) as e: | ||
if e.response["Error"]["Code"] == "SubscriptionRequiredException": | ||
LOGGER.info('Enterprise Support is not enabled') | ||
return SupportLevel.BASIC | ||
raise | ||
|
||
def set_support_level_for_account(self, account: Account, account_id: str, current_level: SupportLevel = SupportLevel.BASIC): | ||
""" | ||
Sets the support level for the account. If the current_value is the same as the value in the instance | ||
of the account Class it will not create a new ticket. | ||
Currently only supports "basic|enterprise" tiers. | ||
:param account: Instance of Account class | ||
:param account_id: AWS Account ID of the account that will have support configured for it. | ||
:param current_level: SupportLevel value that represents the current support tier of the account (Default: Basic) | ||
:return: Void | ||
:raises: ValueError if account.support_level is not a valid/supported SupportLevel. | ||
""" | ||
desired_level = SupportLevel(account.support_level) | ||
|
||
if desired_level is current_level: | ||
LOGGER.info(f'Account {account.full_name} ({account_id}) already has {desired_level.value} support enabled.') | ||
|
||
elif desired_level is SupportLevel.ENTERPRISE: | ||
LOGGER.info(f'Enabling {desired_level.value} for Account {account.full_name} ({account_id})') | ||
self._enable_support_for_account(account, account_id, desired_level) | ||
|
||
else: | ||
LOGGER.error(f'Invalid support tier configured: {desired_level.value}. ' | ||
f'Currently only "{SupportLevel.BASIC.value}" or "{SupportLevel.ENTERPRISE.value}" ' | ||
'are accepted.', exc_info=True) | ||
raise ValueError(f'Invalid Support Tier Value: {desired_level.value}') | ||
|
||
def _enable_support_for_account(self, account: Account, account_id, desired_level: SupportLevel): | ||
""" | ||
Raises a support ticket in the organization root account, enabling support for the account specified | ||
by account_id. | ||
:param account: Instance of Account class | ||
:param account_id: AWS Account ID, of the account that will have support configured | ||
:param desired_level: Desired Support Level | ||
:return: Void | ||
:raises: ClientError, BotoCoreError. | ||
""" | ||
try: | ||
cc_email = account.email | ||
subject = f'[ADF] Enable {desired_level.value} Support for account: {account_id}' | ||
body = ( | ||
f'Hello, \n' | ||
f'Can {desired_level.value} support be enabled on Account: {account_id} ({account.email}) \n' | ||
'Thank you!\n' | ||
'(This ticket was raised automatically via ADF)' | ||
|
||
) | ||
LOGGER.info(f'Creating AWS Support ticket. {desired_level.value} Support for Account ' | ||
f'{account.full_name}({account_id})') | ||
|
||
response = self.client.create_case( | ||
subject=subject, | ||
serviceCode='account-management', | ||
severityCode='low', | ||
categoryCode='billing', | ||
communicationBody=body, | ||
ccEmailAddresses=[ | ||
cc_email, | ||
], | ||
language='en', | ||
) | ||
|
||
LOGGER.info(f'AWS Support ticket: {response["caseId"]} ' | ||
f'has been created. {desired_level.value} Support has ' | ||
f'been requested on Account {account.full_name} ({account_id}). ' | ||
f'{account.email} has been CCd') | ||
|
||
except (ClientError, BotoCoreError): | ||
LOGGER.error(f'Failed to enable {desired_level.value} support for account: ' | ||
f'{account.full_name} ({account.alias}): {account_id}', exc_info=True) | ||
raise |