Companies looking for an acquisition or a successful exit through a merger, undergo a technical assessment as part of the due diligence process. While being a profitable business by itself can attract interest, running a disciplined IT department within your organization can make the acquisition more valuable. As an entity operating cloud workloads on AWS, you can use the AWS Well-Architected Framework. This will demonstrate that your workloads are architected with industry best practices in mind. The Well-Architected Framework explains the pros and cons of decisions you make while building systems on AWS. It consistently measures architectures against best practices observed in customer workloads across several industries. These workloads have achieved continued success on AWS through architectures that are secure, high-performing, resilient, scalable, and efficient. The Well-Architected Framework evaluates your cloud workloads based on five pillars:
Operational Excellence: The ability to support development and run workloads effectively, gain insights into your operations, and continuously improve supporting processes and procedures to deliver business value.
Security: The ability to protect data, systems, and assets to take advantage of cloud technologies to improve your security.
Reliability: The ability of the workload to perform its intended function correctly and consistently. This includes the ability to operate and test the workload through its complete lifecycle.
Performance Efficiency: The ability to use computing resources efficiently to meet system requirements, and to maintain that efficiency as demand changes and technologies evolve.
Cost Optimization: The ability to run cost-aware workloads that achieve business outcomes while minimizing costs.
The Well-Architected Framework Value Proposition in Mergers & Acquisitions (M&A)
Continuously assess the pre-M&A state of cloud workloads – The Well-Architected state for a workload must be treated as a moving target. New cloud patterns and best practices emerge every day. The Well-Architected Framework constantly evolves to incorporate them. Your workloads can continuously grow, shrink, become more complex, or simpler. Mergers and acquisitions can be a long, drawn-out process, which can take can take months to complete. Well-Architected reviews are recommended for workloads every 6 months to 1 year, or with every major development milestone. This helps guard against IT inertia and allows emerging best practices to be accounted for in your continuously evolving workload architecture. The technical currency can be maintained throughout the M&A process by continuously assessing your workloads against the Well-Architected Framework. The accompanying AWS Well-Architected Tool (AWS WA Tool) helps you track milestones as you make improvements to and measure your progress.
Standardize through a common framework – One of the biggest challenges in M&As is the standardization of the Enterprise IT post-merger. The IT departments of organizations can operate differently, and have vastly different IT assets, skill sets, and processes. According to a McKinsey article on the Strategic Value of IT in M&A, more than half the synergies available in a merger are related to IT. If the acquirer is also an AWS customer, this can enable the significant synergies in M&As. The Well-Architected Framework can be a foundation on which the two IT departments can find common ground. Even if the acquirer does not have a cloud-based environment like AWS, inheriting a Well-Architected AWS setup can help the post-merger IT landscape evolve.
Integrate seamlessly through Well-Architected landing zones –AWS Control Tower service or AWS Landing Zone solution are options that can provision Well-Architected multi-account AWS environments. Together with AWS Organizations, this makes the IT integration a lot smoother for the AWS environments across enterprises. AWS accounts can detach from one AWS Organization and attach to another seamlessly. The latter can enroll with an existing Control Tower setup to benefit from the security and governance guardrails. In a Well-Architected landing zone, your management account will not have any workloads. As shown in the following diagram, you may move member accounts from your AWS Organization to your acquirer’s AWS Organization under the right Organizational Unit (OU). You can later decommission your AWS Organization and close your management AWS account.
Benefit from faster migration to AWS – using the Well-Architected Framework, you can achieve faster migration to AWS. Workload risks can be mitigated beforehand by using best practices from AWS before the migration. Post migration, the workloads benefit from AWS offerings that already have many of the Well-Architected best practices built into them. The improvement plans from the Well-Architected tool include the recommended AWS services that can address identified risks. Physical IT assets are heavily depreciated during an acquisition and do not fetch valuations close to their original purchase price. AWS workloads that are Well-Architected should be evaluated by the actual business value they provide. By consolidating your IT needs on AWS, you are also decreasing the overhead of vendor consolidation for the acquirer. This can be challenging when multiple active contracts must transfer hands.
Overcome the innovation barrier – At the onset of an M&A, companies may be focusing too much on keeping the lights on through the process. Businesses that do not move forward may fall behind on continuous innovation. Not only can innovation open more business opportunities, but it can also influence the acquisition valuation. Well-Architected reviews can optimize costs. This can result in diverse benefits such as better agility and an increased use of advanced technologies. This can facilitate rapid innovation. Improvements gained in the security posture, reliability, and performance of the workload make it more valuable to the acquirer.
Demonstrate depth in your area of expertise –Well-Architected lenses help evaluate workloads for specific technology or business domains. Lenses dive deeper into the domain-specific best practices for the workload. If your business specializes in a domain for which a Well-Architected lens is available, doing a review with the specific lens will provide more value for your workload. Today, AWS has lenses for serverless, SaaS, High Performance Computing (HPC), the financial services industry, machine learning, IoT workloads and more. We recently announced a new Management and Governance Lens.
Build workloads using AWS vetted constructs –AWS Solutions Library provides you a repository of Well-Architected solutions across a range of technologies and industry verticals. The library includes reference architectures, implementations of reusable patterns, and fully baked end-to-end solution implementations. Use these building blocks to assemble your workloads. Include the AWS recommended best practices into them, and create an attractive proposition to an acquirer.
Conclusion
You can start taking advantage of the Well-Architected Framework today to improve your technical readiness for an acquisition. The Well-Architected Tool in the AWS Management Console allows you to review your workload at no cost. Engage with your AWS account team early, and we can provide the right guidance for your specific M&A, and plan your Well-Architected technical readiness. Using the Well-Architected Framework as the cornerstone, the AWS Solutions Architects and APN partners have guided thousands of customers through this journey. We are looking forward to helping you succeed.
With AWS SSO, you can centrally manage access and user permissions to all of your accounts in AWS Organizations. You can assign user permissions based on common job functions, customize them to meet your specific security requirements, and assign the permissions to users or groups in the specific accounts where they need access. You can create, read, update, and delete permission sets in one place to have consistent role policies across your entire organization. You can then provide access by assigning permission sets to multiple users and groups in multiple accounts all in a single operation.
AWS SSO recently added new account assignment APIs and AWS CloudFormation support to automate access assignment across AWS Organizations accounts. This release addressed feedback from our customers with multi-account environments who wanted to adopt AWS SSO, but faced challenges related to managing AWS account permissions. To automate the previously manual process and save your administration time, you can now use the new AWS SSO account assignment APIs, or AWS CloudFormation templates, to programmatically manage AWS account permission sets in multi-account environments.
With AWS SSO account assignment APIs, you can now build your automation that will assign access for your users and groups to AWS accounts. You can also gain insights into who has access to which permission sets in which accounts across your entire AWS Organizations structure. With the account assignment APIs, your automation system can programmatically retrieve permission sets for audit and governance purposes, as shown in Figure 1.
Figure 1: Automating multi-account access with the AWS SSO API and AWS CloudFormation
Overview
In this walkthrough, we’ll illustrate how to create permission sets, assign permission sets to users and groups in AWS SSO, and grant access for users and groups to multiple AWS accounts by using the AWS Command Line Interface (AWS CLI) and AWS CloudFormation.
To grant user permissions to AWS resources with AWS SSO, you use permission sets. A permission set is a collection of AWS Identity and Access Management (IAM) policies. Permission sets can contain up to 10 AWS managed policies and a single custom policy stored in AWS SSO.
A policy is an object that defines a user’s permissions. Policies contain statements that represent individual access controls (allow or deny) for various tasks. This determines what tasks users can or cannot perform within the AWS account. AWS evaluates these policies when an IAM principal (a user or role) makes a request.
When you provision a permission set in the AWS account, AWS SSO creates a corresponding IAM role on that account, with a trust policy that allows users to assume the role through AWS SSO. With AWS SSO, you can assign more than one permission set to a user in the specific AWS account. Users who have multiple permission sets must choose one when they sign in through the user portal or the AWS CLI. Users will see these as IAM roles.
Assume you have a company, Example.com, which has three AWS accounts: an organization management account (ExampleOrgMaster), a development account (ExampleOrgDev), and a test account (ExampleOrgTest). Example.com uses AWS Organizations to manage these accounts and has already enabled AWS SSO.
Example.com has the IT security lead, Frank Infosec, who needs PowerUserAccess to the test account (ExampleOrgTest) and SecurityAudit access to the development account (ExampleOrgDev). Alice Developer, the developer, needs full access to Amazon Elastic Compute Cloud (Amazon EC2) and Amazon Simple Storage Service (Amazon S3) through the development account (ExampleOrgDev). We’ll show you how to assign and audit the access for Alice and Frank centrally with AWS SSO, using the AWS CLI.
The flow includes the following steps:
Create three permission sets:
PowerUserAccess, with the PowerUserAccess policy attached.
AuditAccess, with the SecurityAudit policy attached.
EC2-S3-FullAccess, with the AmazonEC2FullAccess and AmazonS3FullAccess policies attached.
Assign permission sets to the AWS account and AWS SSO users:
Assign the PowerUserAccess and AuditAccess permission sets to Frank Infosec, to provide the required access to the ExampleOrgDev and ExampleOrgTest accounts.
Assign the EC2-S3-FullAccess permission set to Alice Developer, to provide the required permissions to the ExampleOrgDev account.
Retrieve the assigned permissions by using Account Entitlement APIs for audit and governance purposes.
Figure 2: AWS Organizations accounts access for Alice and Frank
To help simplify administration of access permissions, we recommend that you assign access directly to groups rather than to individual users. With groups, you can grant or deny permissions to groups of users, rather than having to apply those permissions to each individual. For simplicity, in this blog you’ll assign permissions directly to the users.
Prerequisites
Before you start this walkthrough, complete these steps:
Sign in to the AWS Organizations management account AWS Management Console with AWS SSO administrator credentials. To learn more about AWS Organizations and the management account, see AWS Organizations FAQs.
In order to call the AWS SSO account assignment API by using the AWS CLI, you need to install and configure AWS CLI v2. For more information about AWS CLI installation and configuration, see Installing the AWS CLI and Configuring the AWS CLI.
Step 1: Create permission sets
In this step, you learn how to create EC2-S3FullAccess, AuditAccess, and PowerUserAccess permission sets in AWS SSO from the AWS CLI.
Before you create the permission sets, run the following command to get the Amazon Resource Name (ARN) of the AWS SSO instance and the Identity Store ID, which you will need later in the process when you create and assign permission sets to AWS accounts and users or groups.
aws sso-admin list-instances
Figure 3 shows the results of running the command.
Figure 3: AWS SSO list instances
Next, create the permission set for the security team (Frank) and dev team (Alice), as follows.
Permission set for Alice Developer (EC2-S3-FullAccess)
Run the following command to create the EC2-S3-FullAccess permission set for Alice, as shown in Figure 4.
aws sso-admin create-permission-set --instance-arn '<Instance ARN>' --name 'EC2-S3-FullAccess' --description 'EC2 and S3 access for developers'
Figure 4: Creating the permission set EC2-S3-FullAccess
Permission set for Frank Infosec (AuditAccess)
Run the following command to create the AuditAccess permission set for Frank, as shown in Figure 5.
aws sso-admin create-permission-set --instance-arn '<Instance ARN>' --name 'AuditAccess' --description 'Audit Access for security team on ExampleOrgDev account'
Figure 5: Creating the permission set AuditAccess
Permission set for Frank Infosec (PowerUserAccess)
Run the following command to create the PowerUserAccess permission set for Frank, as shown in Figure 6.
aws sso-admin create-permission-set --instance-arn '<Instance ARN>' --name 'PowerUserAccess' --description 'Power User Access for security team on ExampleOrgDev account'
Figure 6: Creating the permission set PowerUserAccess
Copy the permission set ARN from these responses, which you will need when you attach the managed policies.
Step 2: Assign policies to permission sets
In this step, you learn how to assign managed policies to the permission sets that you created in step 1.
Attach policies to the EC2-S3-FullAccess permission set
Run the following command to attach the amazonec2fullacess AWS managed policy to the EC2-S3-FullAccess permission set, as shown in Figure 7.
Figure 9: Attaching the AWS managed policy SecurityAudit to the AuditAccess permission set
Attach a policy to the PowerUserAccess permission set
The following command is similar to the previous command; it attaches the PowerUserAccess managed policy to the PowerUserAccess permission set, as shown in Figure 10.
Figure 10: Attaching AWS managed policy PowerUserAccess to the PowerUserAccess permission set
In the next step, you assign users (Frank Infosec and Alice Developer) to their respective permission sets and assign permission sets to accounts.
Step 3: Assign permission sets to users and groups and grant access to AWS accounts
In this step, you assign the AWS SSO permission sets you created to users and groups and AWS accounts, to grant the required access for these users and groups on respective AWS accounts.
To assign access to an AWS account for a user or group, using a permission set you already created, you need the following:
The principal ID (the ID for the user or group)
The AWS account ID to which you need to assign this permission set
To obtain a user’s or group’s principal ID (UserID or GroupID), you need to use the AWS SSO Identity Store API. The AWS SSO Identity Store service enables you to retrieve all of your identities (users and groups) from AWS SSO. See AWS SSO Identity Store API for more details.
Use the first two commands shown here to get the principal ID for the two users, Alice (Alice’s user name is [email protected]) and Frank (Frank’s user name is [email protected]).
Alice’s user ID
Run the following command to get Alice’s user ID, as shown in Figure 11.
aws identitystore list-users --identity-store-id '<Identity Store ID>' --filter AttributePath='UserName',AttributeValue='[email protected]'
Figure 11: Retrieving Alice’s user ID
Frank’s user ID
Run the following command to get Frank’s user ID, as shown in Figure 12.
aws identitystore list-users --identity-store-id '<Identity Store ID>'--filter AttributePath='UserName',AttributeValue='[email protected]'
Figure 12: Retrieving Frank’s user ID
Note: To get the principal ID for a group, use the following command.
aws identitystore list-groups --identity-store-id '<Identity Store ID>' --filter AttributePath='DisplayName',AttributeValue='<Group Name>'
Assign the EC2-S3-FullAccess permission set to Alice in the ExampleOrgDev account
Run the following command to assign Alice access to the ExampleOrgDev account using the EC2-S3-FullAccess permission set. This will give Alice full access to Amazon EC2 and S3 services in the ExampleOrgDev account.
Note: When you call the CreateAccountAssignment API, AWS SSO automatically provisions the specified permission set on the account in the form of an IAM policy attached to the AWS SSO–created IAM role. This role is immutable: it’s fully managed by the AWS SSO, and it cannot be deleted or changed by the user even if the user has full administrative rights on the account. If the permission set is subsequently updated, the corresponding IAM policies attached to roles in your accounts won’t be updated automatically. In this case, you will need to call ProvisionPermissionSet to propagate these updates.
Figure 16: View the permission sets (AuditAccess and EC2-S3-FullAccess) assigned to the ExampleOrgDev account
To review the created resources in the AWS Management Console, navigate to the AWS SSO console. In the list of permission sets on the AWS accounts tab, choose the EC2-S3-FullAccess permission set. Under AWS managed policies, the policies attached to the permission set are listed, as shown in Figure 17.
Figure 17: Review the permission set in the AWS SSO console
To see the AWS accounts, where the EC2-S3-FullAccess permission set is currently provisioned, navigate to the AWS accounts tab, as shown in Figure 18.
Figure 18: Review permission set account assignment in the AWS SSO console
Step 4: Audit access
In this step, you learn how to audit access assigned to your users and group by using the AWS SSO account assignment API. In this example, you’ll start from a permission set, review the permissions (AWS-managed policies or a custom policy) attached to the permission set, get the users and groups associated with the permission set, and see which AWS accounts the permission set is provisioned to.
List the IAM managed policies for the permission set
Run the following command to list the IAM managed policies that are attached to a specified permission set, as shown in Figure 19.
aws sso-admin list-managed-policies-in-permission-set --instance-arn '<Instance ARN>' --permission-set-arn '<Permission Set ARN>'
Figure 19: View the managed policies attached to the permission set
List the assignee of the AWS account with the permission set
Run the following command to list the assignee (the user or group with the respective principal ID) of the specified AWS account with the specified permission set, as shown in Figure 20.
Figure 20: View the permission set and the user or group attached to the AWS account
List the accounts to which the permission set is provisioned
Run the following command to list the accounts that are associated with a specific permission set, as shown in Figure 21.
aws sso-admin list-accounts-for-provisioned-permission-set --instance-arn '<Instance ARN>' --permission-set-arn '<Permission Set ARN>'
Figure 21: View AWS accounts to which the permission set is provisioned
In this section of the post, we’ve illustrated how to create a permission set, assign a managed policy to the permission set, and grant access for AWS SSO users or groups to AWS accounts by using this permission set. In the next section, we’ll show you how to do the same using AWS CloudFormation.
Use the AWS SSO API through AWS CloudFormation
In this section, you learn how to use CloudFormation templates to automate the creation of permission sets, attach managed policies, and use permission sets to assign access for a particular user or group to AWS accounts.
Sign in to your AWS Management Console and create a CloudFormation stack by using the following CloudFormation template. For more information on how to create a CloudFormation stack, see Creating a stack on the AWS CloudFormation console.
//start of Template//
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation template to automate multi-account access with AWS Single Sign-On (Entitlement APIs): Create permission sets, assign access for AWS SSO users and groups to AWS accounts using permission sets. Before you use this template, we assume you have enabled AWS SSO for your AWS Organization, added the AWS accounts to which you want to grant AWS SSO access to your organization, signed in to the AWS Management Console with your AWS Organizations management account credentials, and have the required permissions to use the AWS SSO console.",
"Parameters": {
"InstanceARN" : {
"Type" : "String",
"AllowedPattern": "arn:aws:sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}",
"Description" : "Enter AWS SSO InstanceARN. Ex: arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx",
"ConstraintDescription": "must be the name of an existing AWS SSO InstanceARN associated with the management account."
},
"ExampleOrgDevAccountId" : {
"Type" : "String",
"AllowedPattern": "\\d{12}",
"Description" : "Enter 12-digit Developer AWS Account ID. Ex: 123456789012"
},
"ExampleOrgTestAccountId" : {
"Type" : "String",
"AllowedPattern": "\\d{12}",
"Description" : "Enter 12-digit AWS Account ID. Ex: 123456789012"
},
"AliceDeveloperUserId" : {
"Type" : "String",
"AllowedPattern": "^([0-9a-f]{10}-|)[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$",
"Description" : "Enter Developer UserId. Ex: 926703446b-f10fac16-ab5b-45c3-86c1-xxxxxxxxxxxx"
},
"FrankInfosecUserId" : {
"Type" : "String",
"AllowedPattern": "^([0-9a-f]{10}-|)[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$",
"Description" : "Enter Test UserId. Ex: 926703446b-f10fac16-ab5b-45c3-86c1-xxxxxxxxxxxx"
}
},
"Resources": {
"EC2S3Access": {
"Type" : "AWS::SSO::PermissionSet",
"Properties" : {
"Description" : "EC2 and S3 access for developers",
"InstanceArn" : {
"Ref": "InstanceARN"
},
"ManagedPolicies" : ["arn:aws:iam::aws:policy/amazonec2fullaccess","arn:aws:iam::aws:policy/amazons3fullaccess"],
"Name" : "EC2-S3-FullAccess",
"Tags" : [ {
"Key": "Name",
"Value": "EC2S3Access"
} ]
}
},
"SecurityAuditAccess": {
"Type" : "AWS::SSO::PermissionSet",
"Properties" : {
"Description" : "Audit Access for Infosec team",
"InstanceArn" : {
"Ref": "InstanceARN"
},
"ManagedPolicies" : [ "arn:aws:iam::aws:policy/SecurityAudit" ],
"Name" : "AuditAccess",
"Tags" : [ {
"Key": "Name",
"Value": "SecurityAuditAccess"
} ]
}
},
"PowerUserAccess": {
"Type" : "AWS::SSO::PermissionSet",
"Properties" : {
"Description" : "Power User Access for Infosec team",
"InstanceArn" : {
"Ref": "InstanceARN"
},
"ManagedPolicies" : [ "arn:aws:iam::aws:policy/PowerUserAccess"],
"Name" : "PowerUserAccess",
"Tags" : [ {
"Key": "Name",
"Value": "PowerUserAccess"
} ]
}
},
"EC2S3userAssignment": {
"Type" : "AWS::SSO::Assignment",
"Properties" : {
"InstanceArn" : {
"Ref": "InstanceARN"
},
"PermissionSetArn" : {
"Fn::GetAtt": [
"EC2S3Access",
"PermissionSetArn"
]
},
"PrincipalId" : {
"Ref": "AliceDeveloperUserId"
},
"PrincipalType" : "USER",
"TargetId" : {
"Ref": "ExampleOrgDevAccountId"
},
"TargetType" : "AWS_ACCOUNT"
}
},
"SecurityAudituserAssignment": {
"Type" : "AWS::SSO::Assignment",
"Properties" : {
"InstanceArn" : {
"Ref": "InstanceARN"
},
"PermissionSetArn" : {
"Fn::GetAtt": [
"SecurityAuditAccess",
"PermissionSetArn"
]
},
"PrincipalId" : {
"Ref": "FrankInfosecUserId"
},
"PrincipalType" : "USER",
"TargetId" : {
"Ref": "ExampleOrgDevAccountId"
},
"TargetType" : "AWS_ACCOUNT"
}
},
"PowerUserAssignment": {
"Type" : "AWS::SSO::Assignment",
"Properties" : {
"InstanceArn" : {
"Ref": "InstanceARN"
},
"PermissionSetArn" : {
"Fn::GetAtt": [
"PowerUserAccess",
"PermissionSetArn"
]
},
"PrincipalId" : {
"Ref": "FrankInfosecUserId"
},
"PrincipalType" : "USER",
"TargetId" : {
"Ref": "ExampleOrgTestAccountId"
},
"TargetType" : "AWS_ACCOUNT"
}
}
}
}
//End of Template//
When you create the stack, provide the following information for setting the example permission sets for Frank Infosec and Alice Developer, as shown in Figure 22:
The Alice Developer and Frank Infosec user IDs
The ExampleOrgDev and ExampleOrgTest account IDs
The AWS SSO instance ARN
Then launch the CloudFormation stack.
Figure 22: User inputs to launch the CloudFormation template
AWS CloudFormation creates the resources that are shown in Figure 23.
Figure 23: Resources created from the CloudFormation stack
Cleanup
To delete the resources you created by using the AWS CLI, use these commands.
Run the following command to delete the account assignment.
To delete the resource that you created by using the CloudFormation template, go to the AWS CloudFormation console. Select the appropriate stack you created, and then choose delete. Deleting the CloudFormation stack cleans up the resources that were created.
Summary
In this blog post, we showed how to use the AWS SSO account assignment API to automate the deployment of permission sets, how to add managed policies to permission sets, and how to assign access for AWS users and groups to AWS accounts by using specified permission sets.
If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, start a new thread on the AWS SSO forum or contact AWS Support.
Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.
Amazon Web Services (AWS) customers who establish shared infrastructure services in a multi-account environment through AWS Organizations and AWS Resource Access Manager (RAM) may find that the default permissions assigned to the management account are too broad. This may allow organizational accounts to share virtual private clouds (VPCs) with other accounts that shouldn’t have access. Many AWS customers, such as those in regulated industries or who handle sensitive data, may need tighter control of which AWS accounts can share VPCs and which accounts can access shared VPCs.
This blog post describes a mechanism for using service control policies (SCPs) to provide that granular control when you create VPC subnet resource shares within AWS Organizations. These organization policies create a preventative guardrail for controlling which accounts in AWS Organizations can share VPC resources, and with whom. The approach outlined here helps to ensure that your AWS accounts comply with your organization’s access control guidelines for VPC sharing.
A VPC sharing scenario in a multi-account environment
When you set up a multi-account environment in AWS, you can create a good foundation to support your cloud projects by incorporating AWS best practices. AWS Control Tower can automate the implementation of best practices and help your organization achieve its centralized governance and business agility goals. One AWS best practice is to create a shared service network account to consolidate networking components, such as subnets, that can be used by the rest of the organization without duplication of resources and costs. AWS RAM provides the ability to share VPC subnets across accounts. This helps to leverage the implicit routing within a VPC for applications that require a high degree of interconnectivity. VPC subnet sharing across accounts allows individual teams to co-locate their microservice application stacks in a single VPC, and provides several advantages:
Easier administration and management of VPCs in a central network account.
Separation of duties—in other words, network admins retain control over management of VPCs, network access control lists (network ACLs), and security groups, while application teams have permissions to deploy resources and workloads in those VPCs.
High density of Classless Inter-Domain Routing (CIDR) block usage for VPC subnets and avoidance of the problem of CIDR overlap that is encountered with multiple VPCs.
Reuse of network address translation (NAT) gateways, VPC interface endpoints, and avoidance of inter-VPC connectivity costs.
In order to allow for VPC subnets to be shared, you must turn on resource sharing from the management account for your AWS Organizations structure. See Shared VPC prerequisites for more information. This allows sharing of VPC subnets across any accounts within AWS Organizations. However, RAM resource sharing does not provide granular control over VPC shared access.
Let’s consider a customer organization that has set up a multi-account environment with AWS Organizations. The organization consists of segmented accounts and organization units (OUs). The following diagram shows such a multi-OU multi-account environment for a customer who has several teams using the AWS environment for their applications and initiatives.
Figure 1: VPC sharing in a customer’s multi-account AWS environment
The AWS environment is structured as follows:
The Infrastructure OU consists of AWS accounts that contain shared resources for the organization. This OU contains a central network account that contains all the networking resources to be shared with other AWS Organization accounts. Network administrators create a VPC in the networking account with a public and private subnet. This VPC is created for the purpose of sharing the subnets with other teams that need access for their workloads.
The Applications OU consists of AWS accounts that are used by several application teams. These are external and internal application stacks that require a VPC-based infrastructure.
The Data Science OU consists of AWS accounts that are used by teams working on data analytics applications and business intelligence (BI) tools. These applications use serverless data analytics tools for Extract-Transform-Load (ETL) pipelines and big data processing workloads. They have third-party BI tools that need to be hosted in AWS and used by the BI team of the organization for reporting.
Cloud administrators turn on resource sharing in AWS RAM from the management account for their organization. The network administrators operating within the network account create a resource share for the two subnets by using AWS RAM, and share them with the Applications OU so that the application teams can use the shared subnets.
However, this approach opens the door to sharing AWS VPC subnets from any AWS account to any other AWS account as long as the admin users of individual accounts have access to AWS RAM. An example of such unintended or unwanted sharing is when the Application OU account could share a resource with the Data Science OU account, bypassing the centralized network account to satisfy one-off project requests or Proof of Concepts (POCs) that violate the centralized VPC sharing policy.
As a security best practice, cloud administrators should follow the principle of least privilege and use granular controls for VPC sharing. The cloud administrator in this example wants to limit AWS Identity and Access Management (IAM) users with policies that restrict users’ access to AWS RAM to create resource shares. However, this setup can be cumbersome to manage when there are several OUs and numerous AWS accounts. For a more efficient way to have granular control over VPC sharing, you can enable security guardrails by using service control policies (SCPs), as described in the next section. We will walk you through example SCP policies that restrict VPC sharing within AWS Organizations.
Use service control policies to control VPC sharing
In the scenario we described earlier, cloud admins want to allow VPC sharing with the following constraints:
Allow only VPC subnet shares created from a network account
Allow VPC subnet shares to be shared only with certain OUs or AWS accounts
You can achieve these constraints by using the following service control policies.
Both of these service control policies are attached at the root of AWS Organizations, so they are applied to all underlying OUs and accounts. When a network administrator who has logged into the network account tries to create a VPC subnet resource share and associate it with the Application OU, the resource share is successfully created and available to both the Internalapp and Externalapp AWS accounts. However, when the network admin tries to associate the resource share with the DataAnalytics account (which lies outside of the permitted Application OU), the RAMControl2 SCP prevents that action, based on the first condition in the policy statement. The second condition on the RAMControl2 SCP prevents action for specific AWS accounts. In that case, you will see the following error.
Figure 2 Resource share creation is blocked by the SCP
Likewise, when an AWS account administrator of the Externalapp account creates a VPC in that account and tries to share it with the Internalapp account, an error is displayed and the SCP prevents that action. The RAMControl1 SCP prevents the action because it allows only the network account to create and associate resource shares.
Considerations
When you use service control policies within a multi-account structure, it’s important to keep in mind the following considerations:
Customers apply SCPs for several governance and guardrail requirements. The SCPs mentioned here will be evaluated in conjunction with all other SCPs applied at that level in the hierarchy or inherited from above in the hierarchy. See How to use SCPs in AWS Organizations for more information.
AWS strongly recommends that you don’t attach SCPs to the root of your organization without thoroughly testing to ensure that you don’t inadvertently lock users out of key services thereby impacting AWS production environments.
While the example here specifies applying SCPs at the root level, you can take a similar approach if you want to control VPC sharing within a specific OU.
SCPs can be applied to shared resources other than VPC subnets for similar control. To find the complete list of resources that can be specified by using ram: RequestedResourceType, see How AWS RAM works with IAM.
VPC subnets can be shared with AWS accounts and OUs only within an organization. For more information, see the Limitations section in Working with shared VPCs.
Summary
This blog post provides a starting point for learning how to use SCPs to create a granular governance control for VPC sharing. See the IAM conditions keys for AWS RAM and Example SCPs for AWS RAM for more information that can help you implement this preventative guardrail in a way that’s suitable for your AWS environment.
Adding granular governance controls using SCP limits overly permissive sharing and prevents unauthorized resource sharing. Granular control of VPC sharing also helps you follow the AWS security best practice, the principle of least privilege, for access to VPCs. You can take advantage of organization-level SCPs for granular control of resources, which doesn’t require that you turn on resource sharing in AWS Organizations for services such as AWS Transit Gateway or Amazon Route 53 resolver rules.
If you have feedback about this post, submit comments in the Comments section below.
Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.
Enterprise AWS customers are often managing many accounts under a payer account, and sometimes accounts are closed before Reserved Instances (RI) or Savings Plans (SP) are fully used. Manually tracking account closures and requesting RI and SP migration from the closed accounts can become complex and error prone.
This blog post describes a solution for automating the process of requesting migration of unused RI and SP from closed accounts that are linked to a payer account. The solution helps reduce manual work and loss of unused RI and SP due to human error.
The solution automatically detects newly closed accounts that are linked to a payer account. If the closed accounts have unused RI and SP attached, it creates support cases with the required information for RI and SP migration. It can optionally send email notifications with the support case IDs. After a support case is created, the AWS Support team starts a workflow for processing the request, and updates the support case when the request is completed.
Solution Overview
The following diagram shows the overview of the solution.
Walkthrough
An Amazon CloudWatch Events time-based rule will create an event with the configured interval, such as one hour.
The event triggers an AWS Lambda function (refresh.js), which will retrieve the current status of all the linked accounts for the payer account from AWS Organizations. It saves the account status as an item in an Amazon DynamoDB table.
The DynamoDB table has Streams enabled and it triggers another Lambda function (process.js) when there are updates in the table. The stream view type is set to NEW_AND_OLD_IMAGES.
The Lambda function performs the following steps:
Compares the differences between the new and the old images in the stream record. If an account’s status is SUSPENDED in the new image and is ACTIVE in the old image, the account is newly closed.
Retrieves the RI and SP utilization information from AWS Cost Explorer for the closed account.
If there are unused RI and SP in the account, it creates support cases to request RI and SP migration and/or send email notifications through Amazon SNS.
Next, let’s take a deeper look at the Lambda functions, which were written in JavaScript. The code for the Lambda functions can be downloaded from this repository.
Lambda function: refresh.js
This Lambda function is triggered by a CloudWatch Events rule at the predefined interval, for example, one hour. It retrieves the account statuses of all the linked accounts under a payer account from AWS Organizations. Then it saves the account statuses to a DynamoDB table.
It calls the AWS Organizations ListAccounts API to get the current status of all the linked accounts for the given payer account. The following sample code is for the ListAccounts API call.
const AWS = require('aws-sdk')
// Environment variable
const organizationsEndpoint = process.env.ORGANIZATIONS_ENDPOINT;
const orgEndpoint = new AWS.Endpoint(organizationsEndpoint);
// Get region from the endpoint hostname, e.g. organizations.us-east-1.amazonaws.com
const orgRegion = organizationsEndpoint.split(".")[1];
const organizations = new AWS.Organizations({
endpoint: orgEndpoint,
region: orgRegion
});
// Call the ListAccounts API to retrieve the status for all the linked accounts
function refreshAccounts() {
console.log("Enter refreshAccounts");
var newData = {Accounts:[]};
var handleError = function(response) {
console.log(response.err, response.err.stack); // an error occurred
throw response.err;
};
var params = {};
organizations.listAccounts(params).on('success', function handlePage(response) {
console.log("ListAccounts response: \n" + JSON.stringify(response.data));
var account;
// extract each account's Id and Status
for (account of response.data.Accounts) {
var accountStatus = {Id: account.Id, Status: account.Status};
newData.Accounts.push(accountStatus);
}
// handle response pagination
if (response.hasNextPage()) {
response.nextPage().on('success', handlePage).on('error', handleError)
.send();
} else {
console.log("Account Status: \n" + JSON.stringify(newData));
// insert code here to save the data to DynamoDB
}
}).on('error', handleError).send();
}
The following sample output is from the ListAccounts API call.
Next, it calls the DynamoDB UpdateItem API to save the current account status data as an item in the DynamoDB table. The API is configured with conditional update.
If the DynamoDB table already has an item with the same key, the item is not updated unless there is a different value. When the table is updated, DynamoDB Streams triggers a call to the next Lambda function. Below is the sample code for the UpdateItem API call.
const tableName = process.env.TABLE_NAME; // environment variable
const dynamodb = new AWS.DynamoDB();
// Save the account status JSON to the DynamoDB table
// if it is different than the existing data in the table
function saveDataToDynamoDB(data) {
console.log("Enter saveDataToDynamoDB");
var params = {
ExpressionAttributeNames: {
"#ACC": "Accounts"
},
ExpressionAttributeValues: {
":t": {
S: data
}
},
Key: {
"Organization": {
S: "default"
}
},
ConditionExpression: "#ACC <> :t",
ReturnValues: "ALL_NEW",
TableName: tableName,
UpdateExpression: "SET #ACC = :t"
};
dynamodb.updateItem(params, function(err, data) {
console.log("DynamoDB callback...");
if (err) {
console.log(err, err.stack); // an error occurred
if (err.code != "ConditionalCheckFailedException") {
throw err;
}
} else {
console.log(data); // successful response
}
});
}
Lambda function: process.js
This Lambda function processes DynamoDB stream records and compares the old and new item data in the stream record. If any of the linked accounts changed statuses to SUSPENDED from ACTIVE, it calls the Cost Explorer APIs – GetReservationUtilization API and GetSavingsPlansUtilizationDetails API– to check if the newly closed accounts have unused RI and SP attached. The following sample code is for the GetReservationUtilization API call.
const costexplorerEndpoint = process.env.COST_EXPLORER_ENDPOINT; // environment variable
const ceEndpoint = new AWS.Endpoint(costexplorerEndpoint);
// Get region from the endpoint hostname, e.g. ce.us-east-1.amazonaws.com
const ceRegion = costexplorerEndpoint.split(".")[1];
const costexplorer = new AWS.CostExplorer({
endpoint:ceEndpoint,
region:ceRegion
});
// Check if the source account has unused RI. If yes, send email notification
// or create support case based on ACTION_TYPE
// Params
// startDate: String with 'YYYY-MM-DD' format
// endDate: String with 'YYYY-MM-DD' format
// sourceAccountId: the AWS account to migrate RI from
// destinationAccountId: the AWS account to migrate RI to
function processReservationUtilization(startDate,endDate,
sourceAccountId,destinationAccountId) {
console.log("Enter processReservationUtilization");
// array to hold all the unused RI lease IDs from the source account
var riLeaseIds = [];
const now = new Date();
var params = {
TimePeriod: {
End: endDate,
Start: startDate
},
Filter: {
"Dimensions": {
"Key": "LINKED_ACCOUNT",
"Values": [
sourceAccountId
]
}
},
GroupBy: [
{
Key: 'SUBSCRIPTION_ID',
Type: "DIMENSION"
}
]
};
var handleError = function(response) {
console.log(response.err, response.err.stack); // an error occurred
throw response.err;
};
costexplorer.getReservationUtilization(params)
.on('success', function handlePage(response) {
console.log("GetReservationUtilization response \n" + response.data);
var utilizationsByTime;
var group;
// Find unused RI in the results
for (utilizationsByTime of response.data.UtilizationsByTime) {
for (group of utilizationsByTime.Groups) {
const endDateTime = new Date(group.Attributes.endDateTime);
if (endDateTime.getTime() > now.getTime()) {
riLeaseIds.push(group.Attributes.leaseId);
}
}
}
// Handle response pagination
if (response.hasNextPage()) {
response.nextPage().on('success', handlePage)
.on('error', handleError).send();
} else if (riLeaseIds.length > 0) {
var requestBody = riRequestBody + "\nSource Account: " + sourceAccountId
+ "\nDestination Account: " + destinationAccountId + "\nSavings Plans Arns: " + JSON.stringify(riLeaseIds);
// Insert code here to create support case and/or send message to SNS
}
}).on('error', handleError).send();
}
// Check if the source account has unused SP. If yes, send email notification
// or create support case based on ACTION_TYPE
// Params
// startDate: String with 'YYYY-MM-DD' format
// endDate: String with 'YYYY-MM-DD' format
// sourceAccountId: the AWS account to migrate SP from
// destinationAccountId: the AWS account to migrate SP to
function processSavingsPlansUtilization(startDate,endDate,
sourceAccountId,destinationAccountId) {
console.log("Enter processSavingsPlansUtilization");
//array to hold all the unused SP ARNs from the source account
var savingsPlansArns = [];
const now = new Date();
var params = {
TimePeriod: { /* required */
End: endDate,
Start: startDate
},
Filter: {
"Dimensions": {
"Key": "LINKED_ACCOUNT",
"Values": [
sourceAccountId
]
}
}
};
var handleError = function(response) {
console.log(response.err, response.err.stack); // an error occurred
throw response.err;
};
costexplorer.getSavingsPlansUtilizationDetails(params).on('success', function handlePage(response) {
console.log("getSavingsPlansUtilizationDetails response \n" + response.data);
var utilizationDetail;
// Find unused SP in the results
for (utilizationDetail of response.data.SavingsPlansUtilizationDetails) {
const endDateTime = new Date(utilizationDetail.Attributes.EndDateTime);
if (endDateTime.getTime() > now.getTime()) {
savingsPlansArns.push(utilizationDetail.SavingsPlanArn);
}
}
// handle response pagination
if (response.hasNextPage()) {
response.nextPage().on('success', handlePage).on('error', handleError).send();
} else if (savingsPlansArns.length > 0) {
var requestBody = spRequestBody + "\nSource Account: " + sourceAccountId + "\nDestination Account: " + destinationAccountId + "\nSavings Plans Arns: " + JSON.stringify(savingsPlansArns);
// insert code here to create support case and/or send message to SNS
}
}).on('error', handleError).send();
}
For those accounts that require RI or SP migration, it calls the AWS Support CreateCase API to create support cases. It can either/or send email notifications based on the value of the environment variable ACTION_TYPE.
EMAIL_ONLY: Send the RI and SP details to an SNS topic for email notification.
SUPPORT_CASE_ONLY: Create support cases to request RI and SP migration.
SUPPORT_CASE_AND_EMAIL: Create support cases to request RI and SP migration and send the request details to an SNS topic for email notification. The support case IDs are included in the email subject.
The following sample code is for the CreateCase API call.
const supportEndpoint = process.env.SUPPORT_ENDPOINT; // environment variable
const supEndpoint = new AWS.Endpoint(supportEndpoint);
// get region from the endpoint hostname, e.g. support.us-east-1.amazonaws.com
const supRegion = supportEndpoint.split(".")[1];
const support = new AWS.Support({
endpoint:supEndpoint,
region:supRegion
});
// Create an AWS Support Case
// Params:
// emailAddress: email address for the support case
// caseSubject: the subject of the support case
// caseBody: the body of the support case
function createSupportCase(emailAddresses, caseSubject, caseBody, notify) {
console.log("Enter createSupportCase");
var params = {
communicationBody: caseBody, /* required */
subject: caseSubject, /* required */
categoryCode: 'reserved-instances',
ccEmailAddresses: [
emailAddresses
],
issueType: 'customer-service',
serviceCode: 'billing',
severityCode: 'low'
};
support.createCase(params, function(err, data) {
console.log("Support callback...");
if (err) {
console.log(err, err.stack); // an error occurred
throw err;
} else {
console.log(data); // successful response
if (notify) {
// insert code here to publish the message to a SNS topic
}
}
});
}
The following sample support case is content from the Lambda function:
Subject:
Savings Plans Migration
Body:
Please migrate the following Savings Plans from the source account to the destination account.
The AWS RI Operations Team has provided the following guidelines for RI and SP migration support cases.
1) If a closed account is still linked to a payer account, create one support case from the payer account. Otherwise, create one support case from each account – source and destination.
2) When creating a support case, use a user ID or a role with RI and SP purchase IAM permissions.
3) In the support case body, provide RI lease IDs or SP ARNs, source account ID, destination account ID, and an explicit request to migrate the RI and SP. If there are many RI lease IDs or SP ARNs, provide the data in CSV format.
Note: Do not use PDF or images.
4) Set severity code to low, service code to billing, category code to reserved-instances, and issue type to customer-service.
Deploy the stack
Download the template for deploying the solution used in this post.
Use this template to launch the solution and all associated components. The default configuration deploys AWS Lambda functions, a DynamoDB table, an Amazon CloudWatch Events rule, an SNS topic, and AWS Identity and Access Management (IAM) roles necessary to set up the solution in your account, but you can customize the template to meet your specific needs.
Before you launch the solution, review the architecture, configuration, network security, and other considerations. Follow the step-by-step instructions in this section to configure and deploy the solution into your account. You need to have authority to launch resources in the payer account before launching the stack.
Note: You are responsible for the cost of the AWS services used while running this solution. For more details, refer to the pricing web page for each AWS service used in this solution.
Time to deploy: Approximately five minutes.
1. Sign in to the AWS Management Console and use the following button to launch the AWS CloudFormation stack. Optionally, you can download the template as a starting point for your own implementation. Note: the CloudFormation stack needs to be created in the payer account.
2. The template launches in the US East (N. Virginia) Region by default. You can choose to launch it in other regions.
3. On the Create stack page, verify that the correct template URL is in the Amazon S3 URL text box and choose Next.
4. On the Specify stack details page, assign a name to your solution stack.
5. Under Parameters, review the parameters for this solution template and modify them as necessary. This solution uses the following default values.
Recommended documentation for reviewing these parameters:
7. On the Configure stack options page, choose Next.
8. On the Review page, review and confirm the settings. Check the box acknowledging that the template will create AWS Identity and Access Management (IAM) resources.
9. Choose Create stack to deploy the stack.
You can view the status of the stack in the AWS CloudFormation console in the Status column. You should receive a CREATE_COMPLETE status in approximately five minutes.
Clean Up
To clean up the stack, select the stack in the AWS CloudFormation console and click the Delete button. In the popup window, choose Delete stack.
Conclusion
This post described a solution for automating the process of detecting account closures and requesting RI and SP migration. The solution will help enterprise customers reduce manual work and avoid losing unused RI and SP due to human errors.
If you have any comments or questions, please don’t hesitate to leave them in the comments section.
Field Notes provides hands-on technical guidance from AWS Solutions Architects, consultants, and technical account managers, based on their experiences in the field solving real-world business problems for customers.
When AWS customers open their first account, they assume the responsibility for securely managing access to their root account credentials, under the Shared Responsibility Model. Initially protected by a password, it is the responsibility of each AWS customer to make decisions based on their operational and security requirements as to how they configure and manage access to this account.
There are many options and decisions both within AWS (configuration of a Multi-Factor Authentication (MFA) device, or providing contact details) and outside (safe logistics, access policies and email configuration), which affect the overall security and availability of the root account credentials, and so there is a great deal of flexibility in the options and configurations each AWS customer may settle on using.
We’re excited to announce the availability of AWS guidance on the recommended approaches that AWS customers should consider and use to protect these credentials both for the management and member accounts of an AWS Organization.
Take a look at root account credential management recommendations for the management account, which also apply to AWS customers operating with a single AWS account,
For the management of member accounts of an AWS Organization, we have a separate set of root account credential management recommendations.
If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, start a new thread on the AWS Organizations forum or contact AWS Support.
Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.
Editor’s note: Although this blog post and its accompanying code make use of the word “Master,” Red Hat is making open source code more inclusive by eradicating “problematic language.” Read more about this.
Introduction
Red Hat OpenShift is an application platform that provides customers with turnkey application platform that is much more than a simple Kubernetes orchestration.
OpenShift customers choose AWS as their cloud of choice because of the efficiency, security, and reliability, scalability, and elasticity it provides. Customers seeking to modernize their business, process, and application stacks are drawn to the rich AWS service and feature sets.
As such, we see some customers migrate from on-premises to AWS or exist in a hybrid context with application workloads running in various locations. For OpenShift customers, this poses a few questions and considerations:
What are the recommendations for the best way to deploy OpenShift on AWS?
How is this different from what customers were used to on-premises?
How does this ensure resilience and availability?
Do customers need a multi-region, multi-account approach?
For hybrid customers, there are assumptions and misconceptions:
Where does the control plane exist?
Is there replication, and if so, what are the considerations and ramifications?
In this post I will run through some of the more common questions and patterns for OpenShift on AWS, while looking at some of the terminology and conceptual differences of AWS. I’ll explore migration and hybrid use cases and address some misconceptions.
OpenShift building blocks
On AWS, OpenShift 4x is the norm. To that effect, I will focus on OpenShift 4, but many of the considerations will apply to both OpenShift 3 and OpenShift 4.
Let’s unpack some of the OpenShift building blocks. An OpenShift cluster consists of Master, infrastructure, and worker nodes. The Master forms the control plane and infrastructure nodes cater to a routing layer and additional functions, such as logging, monitoring etc. Worker nodes are the nodes that customer application container workloads will exist on.
When deployed on-premises, OpenShift nodes will be placed in separate network subnets. Depending on distance, latency, etc., a single OpenShift cluster may span two data centers that have some nodes in a subnet in one data center and other subnets in a different data center. This applies to customers with data centers within a few miles of each other with high-speed connectivity. An alternative would be an OpenShift cluster in each data center.
AWS concepts and terminology
At AWS, the concept of “region” is a geolocation, such as EMEA (Europe, Middle East, and Africa) or APAC (Asian Pacific) rather than a data center or specific building. An Availability Zone (AZ) is the closest construct on AWS that maps to a physical data center. Within each region you will find multiple (typically three or more) AZs. Note that a single AZ will contain multiple physical data centers but we treat it as a single point of failure. For example, an event that impacts an AZ would be expected to impact all the data centers within that AZ. To this effect, customers should deploy workloads spanning multiple AZs to protect against any event that would impact a single AZ.
When deploying an OpenShift cluster on AWS, we recommend starting with three Master nodes spread across three AWS AZs and three worker nodes spread across three AZs. This allows for the combination of resilience and availably constructs provided by AWS as well as Red Hat OpenShift. The OpenShift installer provides a means of deploying the underlying AWS infrastructure in two ways: IPI Installer-provisioned infrastructure and UPI user-provisioned infrastructure. Both Red Hat and AWS collect customer feedback and use this to drive recommended patterns that are then included in the OpenShift installer. As such, the OpenShift installer IPI mode becomes a living reference architecture for deploying OpenShift on AWS.
The installer will require inputs for the environment on which it’s being deployed. In this case, since I am deploying on AWS, I will need to provide the AWS region, AZs, or subnets that related to the AZs, as well as EC2 instance type. The installer will then generate a set of ignition files that will be used during the deployment of OpenShift:
For larger implementations, we would see additional worker nodes spread across three or more AZs. As more worker nodes are added, use of the control plane increases. Initially scaling up the Amazon Elastic Compute Cloud (EC2) instance type to a larger instance type is an effective way of addressing this. It’s possible to add more Master nodes, and we recommend that an odd number of nodes are maintained. It is more common to see scaling out of the infrastructure nodes before there is a need to scale Masters. For large-scale implementations, infrastructure functions such as the router, monitoring, and logging functions can be moved to separate EC2 instances from the Master nodes, as well as from each other. It is important to spread the routing layer across multiple AZs, which is critical to maintaining availability and resilience.
The process of resource separation is now controlled by infrastructure machine sets within OpenShift. An infrastructure machine set would need to be defined, then the infrastructure role edited to be moved from the default to this new infrastructure machine set. Read about this in greater detail.
OpenShift in a multi-account context
Using AWS accounts as a means of separation is a common well-architected pattern. AWS Organizations and AWS Control Tower are services that are commonly adopted as part of a multi-account strategy. This is very much the case when looking to enable teams to use their own accounts and when an account vending process is needed to cater for self-service account provisioning.
OpenShift clusters are deployed into multiple accounts. An OpenShift dev cluster is deployed into an AWS Dev account. This account would typically have AWS Developer Support associated with it. A separate production OpenShift cluster would be provisioned into an AWS production account with AWS Enterprise Support. Enterprise support provides for faster support case response times, and you get the benefit of dedicated resources such as a technical account manager and solutions architect.
CICD pipelines and processes are then used to control the application life cycle from code to dev to production. The pipelines would push the code to different OpenShift cluster end points at different stages of the life cycle.
Hybrid use case implementation
A common misconception of hybrid implementations is that there is a single cluster or control plan that has worker nodes in various locations. For example, there could be a cluster where the Master and infrastructure nodes are deployed in one location, but also worker nodes registered with this cluster that exist on-premises as well as in the cloud.
Having a single customer control plane for a hybrid implementation, even if technically possible, introduces undesired risks.
There is the potential to take multiple environments with very different resilience characteristics and make them interdependent of each other. This can result in performance and reliability issues, and these may increase not only the possibility of the risk manifesting, but also increase in the impact or blast radius.
Instead, hybrid implementations will see separate OpenShift clusters deployed into various locations. A customer may deploy clusters on-premises to cater for a workload that can’t be migrated to the cloud in the short term. Separate OpenShift clusters can then deployed into accounts in AWS for workloads on the cloud. Customers can also deploy separate OpenShift clusters in different AWS regions to cater for proximity to the consuming customer.
Though adding multiple clusters doesn’t add significant administrative overhead, there is a desire to be able to gain visibility and telemetry to all the deployed clusters from a central location. This may see the OpenShift clusters registered with Red Hat Advanced Cluster Manager for Kubernetes.
Summary
Take advantage of the IPI model, not only as a guide but to also save time. Make AWS Organizations, AWS Control Tower, and the AWS Service catalog part of your cloud and hybrid strategies. These will not only speed up migrations but also form building blocks for a modernized business with a focus of enabling prescriptive self-service. Consider Red Hat advanced cluster manager for multi cluster management.
For customers considering the AWS Solution Provider Program, there are challenges to mitigate when building a shared account model with SI partners. AWS Organizations make it possible to build the right account structure to support a resale arrangement. In this engagement model, the end customer gets an AWS invoice from an AWS authorized partner instead of AWS directly.
Partners and customers who want to engage in this service resale arrangement need to build a new account structure. This process includes linking or transferring existing customer accounts to the partner master account. This is so that all the billing data from customer accounts is consolidated into the partner master account.
While linking or transferring existing customer accounts to the new master account, the partner must check the new master account structure. It should not compromise any customer security controls and continue to provide full control of linked accounts to the customer. The new account structure must fulfill the following requirements for both the AWS customer and partner:
The customer maintains full access to the AWS organization and able to perform all critical security-related tasks except access to billing data.
The Partner is able to control only billing information and not able to perform any other task in the root account (master payer account) without approval from the customer.
In case of contract breach / termination, the customer is able to gain back full control of all accounts including the Master.
In this post, you will learn about how partners can create a master account with shared ownership. We also show how to link or transfer customer organization accounts to the new organization master account and set up policies that would provide appropriate access to both partner and customer.
Account Structure
The following architecture represents the account structure setup that can fulfill customer and partner requirements as a part of a service resale arrangement.
As illustrated in the preceding diagram, the following list includes the key architectural components:
As a part of resale arrangement, the customer’s existing AWS organization and related accounts are linked to the partner’s master payer account. The customer can continue to maintain their existing master root account, while all child accounts are linked to the master account (as shown in the list).
Customers may have valid concerns about linking/transferring accounts to the owned master payee account and may come up with many ‘what-if’ scenarios for example “What if the partner shuts down environment/servers?” or, “What if partner blocks access to child accounts?”.
This account structure provides the right controls to both customer and partner that would address customer concerns around the security of their accounts. This includes the following benefits:
Starting with access to the root account, neither customer nor partner can access the root account without the other party’s involvement.
The partner controls the id/password for the root account while the customer maintains the MFA token for the account. The customer also controls the phone number, security questions associated with the root account. That way, the partner cannot replace the MFA token on their own.
The partner only has billing access and does not control any other parts of account including child accounts. Anytime the root account access is needed, both customer and partner team need to collaborate and access the root account.
The customer or partner cannot assign new IAM roles to themselves, therefore protecting the initial account setup.
Security considerations in the shared account setup
The following table highlights both customer and partner responsibilities and access controls provided by the architecture in the previous section.
The following points highlight security recommendations to provide adequate access rights to both partner and customers.
New master payer/ root account has a joint ownership between the Partner and the Customer.
AWS account root users (user id/password) would be with Partner and MFA (multi-factor authentication) device with Customer.
IAM (AWS Identity and Access Management) role to be created under the master payer with policies “FullOrganizationAccess”, “Amazon S3” (Amazon Simple Storage Service), “CloudTrail” (AWS CloudTrail), “CloudWatch”(Amazon CloudWatch) for the Customer.
Security team to log in and manage security of the account. Additional permissions to be added to this role as needed in future. This role does not have ANY billing permissions.
Only the partner has access to AWS billing and usage data.
IAM role / user would be created under master payer with just billing permission for the Partner team to log in and download all invoices. This role does not have any other permissions except billing and usage reports.
Any root login attempts to master payer triggers a notification to Customer’s SOC team and the Partner’s Customer account management team.
The Partner’ email address is used to create an account so invoices can be emailed to the partner’s email. The Customer cannot see these invoices.
The Customer phone number is used to create a master account and the customer maintains security questions/answers. This prevents replacement of MFA token by the Partner team without informing customer. The Customer wouldn’t need the Partner’s help or permission to login and manage any security.
No aspect of the Master Payer / Root Partner team can login to the master payer/Root without the Customer providing an MFA token.
Setting up the shared master AWS account structure
Create a playbook for the account transfer activity based on the following tasks. For each task, identify the owner. Make sure that owners have the right permissions to perform the tasks.
Update contact for security and operations in the Partner Master payee Account
Update demographics -Address and contact details in Partner Master payee Account
Create an IAM role for Customer Team in Partner Master Payee account. IAM role is created under master payer with “FullOrganizationAccess”, “Amazon S3”, “CloudTrail”, “CloudWatch” “CloudFormationFullAccess” for the Customer SOC team to login and manage security of the account. Additional permissions can be added to this role in future if needed.
Select the roles:
7. Create an IAM role/user for Partner billing role in the Partner Master Payee account.
Part II – Setting up customer master account
1. Create an IAM user in the customer’s master account. This user assumes role into the new master payer/root account.
2. Confirm that when the IAM user from the customer account assumes a role in the new master account, and that the user does not have Billing Access.
Part III – Creating an organization structure in partner account
5. Create/Copy Multiple in to Partner Master Payee Account from Customer root Account. Any service control policies from the customer root account should be manually copied to new partner account.
6. If customer root account has any special software installed for example, security, install same software in Partner Master Payee Account.
7. Set alerts in Partner Master Payee root account. Any login to the root account would send alerts to customer and partner teams.
8. It is recommended to keep a copy of all billing history invoices for all accounts to be transferred to partner organization. This could be achieved by either downloading CSV or printing all invoices and storing files in Amazon S3 for long term archival. Billing history and invoices are found by clicking Orders and Invoices on Billing & Cost Management Dashboard. After accounts are transferred to new organization, historic billing data will not be available for those accounts.
9. Remove all the Member Accounts from the current Customer Root Account/ Organization. This step is performed by customer account admin and required before account can be transferred to Partner Account organization.
10. Send an invite from the Partner Master Payee Account to the delinked Member Account
11. Member Accounts to accept the invite from the Partner Master Payee Account.
12. Move the Customer member account to the appropriate OU in the Partner Master Payee Account.
Setting the shared security model between partner and customer contact
While setting up the master account, three contacts need to be updated for notification.
Billing – this is owned by the Partner
Operations – this is owned by the Customer
Security – this is owned by the Customer.
This will trigger a notification of any activity on the root account. The contact details contain Name, Title, Email Address and Phone number. It is recommended to use the Customer’s SOC team distribution email for security and operations, and a phone number that belongs to the organization, and not the individual.
Additionally, before any root account activity takes place, AWS Support will verify using the security challenge questionnaire. These questions and answers are owned by the Customer’s SOC team.
If a customer is not able to access the AWS account, alternate support options are available at Contact us by expanding the “I’m an AWS customer and I’m looking for billing or account support” menu. While contacting AWS Support, all the details that are listed on the account are needed, including full name, phone number, address, email address, and the last four digits of the credit card.
Clean Up
After recovering the account, the Customer should close any accounts that are not in use. It’s a good idea not to have open accounts in your name that could result in charges. For more information, review Closing an Account in the Billing and Cost Management User Guide.
The Shared master root account should be only used for selected activities referred to in the following document.
Conclusion
In this post, you learned how AWS Organizations features can be used to create a shared master account structure. This helps both customer and partner engage in a service resale business engagement. Using AWS Organizations and cross account access, this solution allows customers to control all key aspects of managing the AWS Organization (Security / Logging / Monitoring) and also allows partners to control any billing related data.
Field Notes provides hands-on technical guidance from AWS Solutions Architects, consultants, and technical account managers, based on their experiences in the field solving real-world business problems for customers.
The collective thoughts of the interwebz
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.