fbpx

Governing and securing AWS PrivateLink service access at scale in multi-account environments

Amazon Web Services (AWS) customers have been adopting the approach of using AWS PrivateLink to have secure communication to AWS services, their own internal services, and third-party services in the AWS Cloud. As these environments scale, the number of PrivateLink connections outbound to external services and inbound to internal services increase and are spread out across multiple accounts in virtual private clouds (VPCs). While AWS Identity and Access Management (IAM) policies allow you to control access to individual PrivateLink services, customers want centralized governance for the use of PrivateLink in adherence with organizational standards and security needs.

   <p>This post provides an approach for centralized governance for PrivateLink based services across your multi-account environment. It provides a way to create preventative controls through the use of <a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html" target="_blank" rel="noopener">service control policies (SCPs)</a> and detective controls through event-driven automation. This allows your application teams to consume internal and external services while adhering to organization policies and provides a mechanism for centralized control as your AWS environment grows.</p> 
   <h2>Scenarios faced by customers</h2> 
   <p>Figure 1 shows an example customer environment comprising a multi-account structure created through <a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_getting-started_concepts.html" target="_blank" rel="noopener">AWS Organizations</a> or using <a href="https://aws.amazon.com/controltower/" target="_blank" rel="noopener">AWS Control Tower</a>. There are separate organizational units (OUs) pertaining to different business units (BUs) with respective accounts. The business services’ account hosts several backend services that are utilized by consuming applications for their functionality. Since these services provide functionality to more than one internal application and will require access across VPC and account boundaries, these are exposed through <a href="https://aws.amazon.com/privatelink/" target="_blank" rel="noopener">AWS PrivateLink</a>. One such service is shown in the business services account.</p> 
   <p>The customer has partners that provide services for integration with the customer’s application stack. The approved partner account provides a service that is approved for use by the cloud administration team. The NotApproved partner account provides services that are not approved within the customer’s organization. The customer has another OU dedicated to application teams. The application 1 account has an application that consumes the business service of the approved partner account. It is also planning to use the service from the NotApproved partner, which should be blocked. The application in the application 2 account is planning on using AWS services through interface endpoints as well as the approved partner account through <a href="https://docs.aws.amazon.com/vpc/latest/userguide/endpoint-services-overview.html" target="_blank" rel="noopener">PrivateLink integration</a>. </p> 
   <blockquote> 
    <p><strong>Note:</strong> Throughout this post, “organization” is used to refer to an organization that you create and manage through <a href="https://aws.amazon.com/organizations/" target="_blank" rel="noopener">AWS Organizations</a>.</p> 
   </blockquote> 
   <div id="attachment_34150" class="wp-caption aligncenter"> 
    <img aria-describedby="caption-attachment-34150" src="https://infracom.com.sg/wp-content/uploads/2024/05/img1-4.png" alt="Figure 1: A multi-account customer environment" width="780" class="size-full wp-image-34150"> 
    <p id="caption-attachment-34150" class="wp-caption-text">Figure 1: A multi-account customer environment</p> 
   </div> 
   <h2>Current challenges</h2> 
   <p>Access to individual PrivateLink connections can be controlled through IAM policies. At scale, however, different teams use and adopt PrivateLink for incoming and outgoing connections, and the number of VPC endpoint policies to create and manage increases. As mentioned in the problem statement presented in the introduction, as the customer environment scales and the number of PrivateLink connections increases, customers want centralized guardrails to manage PrivateLink resources at scale. For our example, the customer would like to put the following controls in place:</p> 
   <h3>Preventative controls:</h3> 
   <p>Use case 1:</p> 
   <ul> 
    <li>Allow creation of VPC endpoints and allow access only to PrivateLink enabled AWS services.</li> 
    <li>Allow creation of VPC endpoints and initiating connection only to approved PrivateLink enabled third-party services.</li> 
    <li>Allow creation of VPC endpoints and initiating connection only to internal business services owned by accounts in the same organization.</li> 
   </ul> 
   <p>Use case 2:</p> 
   <ul> 
    <li>Allow only a cloud admin role to add permissions to connect to an endpoint service to prevent connections from external clients to internal VPC endpoint services.</li> 
   </ul> 
   <h3>Detective controls:</h3> 
   <p>Use case 3:</p> 
   <ul> 
    <li>Detect if connections are made to PrivateLink services exposed by AWS accounts <strong>not</strong> belonging to the customer’s organization.</li> 
   </ul> 
   <p>Use case 4:</p> 
   <ul> 
    <li>Detect if connections are made by external AWS accounts (not belonging to the customer’s organization) to PrivateLink services exposed for internal use by the customer’s AWS accounts.</li> 
   </ul> 
   <p>This post presents a solution that uses SCPs, <a href="https://aws.amazon.com/cloudtrail/" target="_blank" rel="noopener">AWS CloudTrail</a>, and <a href="https://aws.amazon.com/config/" target="_blank" rel="noopener">AWS Config</a> to achieve governance. When the solution is deployed in your account, the following components are created as part of the architecture, as shown in Figure 2.</p> 
   <div id="attachment_34151" class="wp-caption aligncenter"> 
    <img aria-describedby="caption-attachment-34151" src="https://infracom.com.sg/wp-content/uploads/2024/05/img2-4.png" alt="Figure 2: Resources deployed in the customer environment by the solution" width="780" class="size-full wp-image-34151"> 
    <p id="caption-attachment-34151" class="wp-caption-text">Figure 2: Resources deployed in the customer environment by the solution</p> 
   </div> 
   <p>The following architecture is now in place:</p> 
   <ul> 
    <li>SCPs to provide preventative controls for the PrivateLink connections.</li> 
    <li><a href="https://aws.amazon.com/eventbridge/" target="_blank" rel="noopener">Amazon EventBridge</a> rules that are configured to trigger based on events from API calls captured by CloudTrail in specified accounts within specified OUs.</li> 
    <li>EventBridge rules in member accounts to send events to the event bus in the Audit account, and a central EventBridge rule in that account to trigger an <a href="https://aws.amazon.com/lambda/" target="_blank" rel="noopener">AWS Lambda</a> function based on PrivateLink related API calls.</li> 
    <li>A Lambda function that receives the events and validates if the VPC endpoint API call is allowed for the PrivateLink service and notifies a cloud administrator if a policy is violated.</li> 
    <li>An AWS Config rule that checks if PrivateLink enabled VPC endpoint services created within your AWS accounts have enabled auto accept of client connections and disabled notifications.</li> 
   </ul> 
   <h2>Use cases and solution approach</h2> 
   <p>This section walks through each use case and how the solution components are used to address each use case. </p> 
   <h3>Preventative control</h3> 
   <p>Use case 1: Allowing the creation of a VPC endpoint connection to only AWS services and approved internal and third-party PrivateLink services</p> 
   <p>This solution allows creating a VPC endpoint for only approved partner PrivateLink services, PrivateLink services internal to the organization, and AWS services. This is implemented using an SCP and can be enforced at the individual account or OU. The approved partner services as well as the internal accounts that can host allowed PrivateLink services can be specified during the solution deployment. Application teams operating in AWS accounts within the customer environment can then create VPC endpoints to PrivateLink services of approved partners or AWS services. However, they will not be able to create a VPC endpoint to an unapproved PrivateLink service, for example. This is shown in Figure 3.</p> 
   <div id="attachment_34152" class="wp-caption aligncenter"> 
    <img aria-describedby="caption-attachment-34152" src="https://infracom.com.sg/wp-content/uploads/2024/05/img3-4.png" alt="Figure 3: Allowed and disallowed paths in PrivateLink connections by SCP" width="780" class="size-full wp-image-34152"> 
    <p id="caption-attachment-34152" class="wp-caption-text">Figure 3: Allowed and disallowed paths in PrivateLink connections by SCP</p> 
   </div> 
   <p>The SCP that allows you to do this preventative control is shown in the following code snippet. In this example SCP policy, <span>AllowedPrivateLinkPartnerService-ServiceName</span> refers to the service name of the allowed partner PrivateLink. Also, the SCP allows the creation of VPC endpoints to internal PrivateLink services that are hosted in <span>AllowedPrivateLinkAccount</span>. Make sure that this SCP does not interfere with the other policies you created within your organization. The solution currently uses <a href="https://docs.aws.amazon.com/vpc/latest/privatelink/security_iam_id-based-policy-examples.html" target="_blank" rel="noopener">ec2:VpceServiceName and ec2:VpceServiceOwner conditions</a> to identify the PrivateLink service of AWS services or a third-party partner. These conditions can be used in an SCP to control the creation of VPC endpoints:</p> 
   <div class="hide-language"> 
    <pre class="unlimited-height-code"><code class="lang-text">{

“Version”: “2012-10-17”,
“Statement”: [
{
“Condition”: {
“StringNotEquals”: {
“ec2:VpceServiceName”: [
“AllowedPrivateLinkPartnerService-ServiceName”,
],
“ec2:VpceServiceOwner”: [
“AllowedPrivateLinkAccount”,
“amazon”
]
}
},
“Action”: [
“ec2:CreateVpcEndpoint”
],
“Resource”: “arn:aws:ec2:::vpc-endpoint/*”,
“Effect”: “Deny”,
“Sid”: “SCPDenyPrivateLink”
}
]
}

   <p>Use case 2: Allow only a cloud admin role to add permissions to connect to an endpoint service</p> 
   <p>This solution makes sure that PrivateLink services that are owned and created in AWS accounts of the customer cannot be connected to consumers unless it is allowed by the cloud administrator role. The cloud administrator can then make sure that only legitimate internal AWS accounts are allowed access to that service and restrict access from other accounts outside of the customer’s organization. This is achieved through the use of a service control policy that will restrict modifications of permissions of the PrivateLink endpoint service. This makes sure that individual teams are not able to use the <strong>Allow principals</strong> configuration to open access to other entities directly, and only a cloud administrator role with the right permissions can make that change.</p> 
   <div class="hide-language"> 
    <pre class="unlimited-height-code"><code class="lang-text">{

“Version”: “2012-10-17”,
“Statement”: [

  "Sid": "Statement1",
  "Effect": "Deny",
  "Action": [
    "ec2:ModifyVpcEndpointServicePermissions"
  ],
  "Resource": [
    "*"
  ],
  "Condition": {
    "StringNotEquals": {
      "aws:PrincipalArn": [
        "arn:aws:iam::*:role/CloudNetworkAdmin"
      ]
    }
  }
}

]
}

This policy can help in achieving the access control, as shown in Figure 4. The cloud administrator uses the Allow principals configuration of the business services PrivateLink service to provide access only to the application 1 account. The SCP allows only the cloud administrator to make the modification and does not allow another member of the team from bypassing that process and adding a nonapproved client application account to access the internal PrivateLink service.

Figure 4: Centralized control on access to the internal PrivateLink service to the customer’s own accounts

Figure 4: Centralized control on access to the internal PrivateLink service to the customer’s own accounts

Detective controls

For detective controls, we discuss two use cases that are deployed as part of the solution and can be enabled and disabled based on the test that you want to perform.

Use case 3: Detecting if connections are made by external AWS accounts (not belonging to the customer’s organization) to PrivateLink services exposed by the customer’s AWS accounts

In this use case, the customer would like to detect if connections are made to their business services from accounts outside of its organization. The solution uses individual member account trails for capturing API calls across the multi-account structure and cross-account EventBridge integration. CloudTrail events from member accounts capture events when a PrivateLink service connection is accepted through the API call event AcceptVPCConnectionEndpoint and sent to the event bus in the audit account. This triggers a Lambda function that then captures the information of the entity requesting the connection and details of the PrivateLink service and sends a notification to the cloud administrator. This is shown in Figure 5.

Figure 5: Detecting the creation of a VPC endpoint or accepting a PrivateLink service connection using CloudTrail events in EventBridge

Figure 5: Detecting the creation of a VPC endpoint or accepting a PrivateLink service connection using CloudTrail events in EventBridge

Custom AWS Config rule for detective control

This detective control mechanism works in cases where PrivateLink services are configured to manually accept client connections. If the endpoint is configured to automatically accept connections, CloudTrail will not generate an event when a connection is accepted. AWS PrivateLink allows customers to configure connection notifications to send connection notification events to an Amazon Simple Notification Service (Amazon SNS) topic. Cloud administrators can get the notifications if they are subscribed to the SNS topic. However, if the notification configuration is removed by the member account, there is no way for the cloud administrator to have visibility for new connections and effectively apply governance requirements.

This solution employs an AWS Config rule to detect if PrivateLink services are created with the Auto Accept Connections setting enabled or without a connection notification configuration and flag it as noncompliant.

This is depicted in Figure 6.

Figure 6: Custom AWS Config rule and SNS notification deployed as part of the solution

Figure 6: Custom AWS Config rule and SNS notification deployed as part of the solution

When a PrivateLink service is created by one of the business services teams, an AWS Config organization rule in the audit account will detect the event, and the custom Lambda function will check if the connection notification configuration is present. If not, then the AWS Config rule will flag the resource as noncompliant. Cloud administrators can view these in the AWS Config dashboard or receive notifications configured through AWS Config.

Use case 4: Detecting if connections are made to PrivateLink services exposed by AWS accounts not belonging to the customer’s organization.

Using the same approach as presented in use case 3, connections made to PrivateLink services exposed by AWS accounts outside of the customer’s organization can be detected through the API call event from CloudTrail CreateVPCEndpoint. This event is sent to the centralized event bus and the Lambda function to check against the criteria and provide notifications to the cloud administrator.

Deploy and test the solution

This section walks through how to deploy and test our recommended solution.

Prerequisites

To deploy the solution, first follow these steps.

  1. In your AWS Organizations multi-account environment, go to the management account and enable trusted access for AWS CloudFormation, enable trusted access for AWS Config, and enable trusted access for CloudTrail.
  2. Identify an account in your organization to serve as the audit account and set it up as a delegated administrator for CloudFormation, AWS Config, and CloudTrail. Follow these steps to perform this step:
    1. Register a delegated administrator for CloudFormation.
    2. Perform the steps mentioned in step 1 of this post to register a delegated administrator for AWS Config.
    3. Register a delegated admin for CloudTrail.
  3. The solution uses the deployment of CloudFormation StackSets with self-managed permissions to set up the resources in the audit account. In order to enable this, create AWSCloudFormationStackSetAdministrationRole in the management account and AWSCloudFormationStackSetExecutionRole in the audit account by using the steps in the topic Grant self-managed permissions.
  4. In a separate AWS account that is different than your multi-account environment, create two PrivateLink VPC endpoint services as explained in the documentation. You can use this template to create a test PrivateLink VPC endpoint service. These will serve as two partner services, one of which is allowed, and another is untrusted and not allowed. Make note of their service names.
   <div id="attachment_34158" class="wp-caption aligncenter"> 
    <img aria-describedby="caption-attachment-34158" src="https://infracom.com.sg/wp-content/uploads/2024/05/img7.png" alt="Figure 7: Simulated partner services (approved and not approved) in a separate test account" width="780" class="size-full wp-image-34158"> 
    <p id="caption-attachment-34158" class="wp-caption-text">Figure 7: Simulated partner services (approved and not approved) in a separate test account</p> 
   </div> 

   <h3>Deploying the solution</h3> 
   <ol> 
    <li>Go to the management account of your AWS Organizations multi-account environment and use <a href="https://vod-anand78.s3.amazonaws.com/templates/privatelink-governance.yaml" target="_blank" rel="noopener">this CloudFormation template</a> to deploy the solution, or choose the following Launch Stack button: <p><a href="https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=PLGovernanceStack&templateURL=https://awsiammedia.s3.amazonaws.com/public/sample/1911-governing-securing-aws-privatelink-application-access-scale-multi-account-environment/privatelink-governance_updated.yaml" rel="noopener noreferrer" target="_blank"><img loading="lazy" src="https://d2908q01vomqb2.cloudfront.net/22d200f8670dbdb3e253a90eee5098477c95c23d/2019/06/05/launch-stack-button.png" alt="Launch stack" width="190" height="36" class="aligncenter size-full wp-image-10149"></a></p> <p>CloudFormation stacks can be deployed using the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html" target="_blank" rel="noopener">AWS CloudFormation console</a> or using the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-cli-creating-stack.html" target="_blank" rel="noopener">AWS CLI</a>.</p> </li> 
    <li>This initially displays the <strong>Create stack</strong> page. Leave the details entered by default, and then choose <strong>Next</strong>.</li> 
    <li>On the <strong>Specify stack details</strong> page, enter the details for the input parameters for this solution. The following table shows the details that you will provide when setting up the CloudFormation template on the <strong>Specify stack details</strong> page on the CloudFormation console.<br><table width="100%"> 
      <tbody> 
       <tr> 
        <td width="35%">AWSOrganizationsId</td> 
        <td width="65%">Identifier for your organization. This can be obtained from your management account as described in the AWS Organizations User Guide.</td> 
       </tr> 
       <tr> 
        <td width="35%">AdminRoleArn</td> 
        <td width="65%">Role of the persona who is allowed to modify PrivateLink endpoint permissions.</td> 
       </tr> 
       <tr> 
        <td width="35%">AllowedPrivateLinkAccounts</td> 
        <td width="65%">AWS account IDs of accounts in your OU that host PrivateLink services.</td> 
       </tr> 
       <tr> 
        <td width="35%">AllowedPrivateLinkPartnerServices</td> 
        <td width="65%">Specify the service name of the approved PrivateLink services from partners. If you want to test with a simulated partner PrivateLink, take the service name of PrivateLink services created in Step 4 of the prerequisites as the partner services to which connections should be allowed. The unique service name of the partner’s PrivateLink service is provided by the partner to the customer so that they can connect to it.</td> 
       </tr> 
       <tr> 
        <td width="35%">AuditAccountId</td> 
        <td width="65%">AWS account ID of the audit account in your multi-account environment.</td> 
       </tr> 
       <tr> 
        <td width="35%">PLOrganizationUnit</td> 
        <td width="65%">OU identifier for the organizational unit where the solution will perform preventative and detective control.</td> 
       </tr> 
      </tbody> 
     </table> 
     <div id="attachment_34159" class="wp-caption aligncenter"> 
      <img aria-describedby="caption-attachment-34159" src="https://infracom.com.sg/wp-content/uploads/2024/05/img8.png" alt="Figure 8: CloudFormation template input parameters for the solution as it appears on the console" width="740" class="size-full wp-image-34159"> 
      <p id="caption-attachment-34159" class="wp-caption-text">Figure 8: CloudFormation template input parameters for the solution as it appears on the console</p> 
     </div> </li> 
    <li>Choose <strong>Next </strong>and keep the defaults for the rest of the fields. Then, on the <strong>Review and create</strong> page, choose <strong>Submit</strong> to finish deploying the solution.</li> 
   </ol> 
   <h3>Testing the solution</h3> 
   <p>Once the solution is deployed successfully, follow these steps to test the solution:</p> 
   <ol> 
    <li>For an account specified in the AllowedPrivateLinkAccounts parameter, create a VPC endpoint service as explained in the topic <a href="https://docs.aws.amazon.com/vpc/latest/privatelink/create-endpoint-service.html" target="_blank" rel="noopener">Create a service powered by AWS PrivateLink</a>. Instead of creating this manually, use <a href="https://awsiammedia.s3.amazonaws.com/public/sample/1911-governing-securing-aws-privatelink-application-access-scale-multi-account-environment/test-vpc-endpoint-service.yaml" target="_blank" rel="noopener">this CloudFormation template</a> to create a test VPC endpoint service.</li> 
    <li>Sign in to a member account within the OU that you specified in the CloudFormation template.</li> 
    <li>From the member account, create a VPC endpoint connection to the internal PrivateLink service created in the account from Step 1. This connection will set up successfully because it is internal to the organization and therefore allowed by the SCP policy, and is not flagged to the cloud administrator as violating organization policy.</li> 
    <li>From the member account, create a VPC endpoint connection to the AWS service that is supporting PrivateLink, such as <a href="https://aws.amazon.com/kms/" target="_blank" rel="noopener">AWS Key Management Service (AWS KMS)</a>. This connection will set up successfully because it is internal to the organization and therefore allowed by the SCP policy, and is not flagged to the cloud administrator as violating organization policy.</li> 
    <li>From the member account, create a VPC endpoint connection to the PrivateLink service created in Step 4 of the prerequisites. This connection will set up successfully because it is internal to the organization and therefore allowed by the SCP policy, and is not flagged to the cloud administrator as violating organization policy.</li> 
    <li>From the member account, create a VPC endpoint connection to the PrivateLink service created in Step 4 of the prerequisites and that is not an allowed partner service. This connection will fail because it is not allowed by the SCP policy.</li> 
    <li>From an account outside of your organization, create a VPC endpoint connection to the internal PrivateLink service created in Step 1. The connection setup is successful, but the cloud administrator will see the internal PrivateLink service as <strong>NOT COMPLIANT</strong> because the connection from external clients is considered to be not compliant with organization requirements in this solution. This information allows the cloud admin to quickly find the noncompliant resource and work with the PrivateLink service owner team to remediate the issue.</li> 
    <li>From the member account, create another VPC endpoint service without configuring the notification configuration, and leave the <strong>Acceptance required</strong> field unchecked. Navigate to the AWS Config console in the audit account and go to <strong>Aggregator</strong>-&gt;<strong>Rules</strong>. Check the evaluation of the rule starting with “OrgConfigRule-pl-governance-rule….” Once the evaluation is complete, it will indicate that this VPC endpoint service is<strong> NOT COMPLIANT</strong>, whereas the service created in Step 1 will show as <strong>COMPLIANT</strong>.</li> 
   </ol> 
   <h2>Considerations</h2> 
   <ul> 
    <li>The solution described here takes the approach of allowing all VPC endpoint connections from within a customer’s organization to the PrivateLink services in specified accounts and detecting and notifying all external ones. This can be modified based on your specific use cases and requirements.</li> 
    <li>The solution uses AWS Config rules that are applied to specific accounts of your organization, even though the solution is applied at an OU level. The AWS Config rules created in this solution are scoped to evaluate VPC endpoint services and should incur charges accordingly. Refer to the <a href="https://aws.amazon.com/config/pricing/" target="_blank" rel="noopener">AWS Config pricing</a> page to understand usage-based pricing for the service.</li> 
    <li>Other services, such <a href="https://aws.amazon.com/lambda/pricing/" target="_blank" rel="noopener">AWS Lambda</a> and <a href="https://aws.amazon.com/eventbridge/pricing/" target="_blank" rel="noopener">Amazon EventBridge</a>, also incur usage-based charges. Please verify that these are deleted to prevent incurring unnecessary charges.</li> 
    <li>SCP policies only affect member accounts. They do not apply to the management account, so actions denied through an SCP policy multi-account will still be allowed in the management account.</li> 
   </ul> 
   <h2>Cleanup</h2> 
   <p>You can delete the solution by following these steps to avoid unnecessary charges:</p> 
   <ul> 
    <li>Delete the CloudFormation stack created as part of Step 4 of the prerequisites.</li> 
    <li><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html" target="_blank" rel="noopener">Delete the CloudFormation stack</a> of the main solution deployed in the management account as part of the <strong>Deploying the solution</strong> section.</li> 
    <li>Delete the CloudFormation stack created as part of Step 1 of <strong>Testing the solution</strong>.</li> 
   </ul> 
   <h2>Summary</h2> 
   <p>As customers adopt AWS PrivateLink throughout their environment, the mechanisms discussed in this post provide a way for administrators to govern and secure their PrivateLink services at scale. This approach can help you create a scalable solution where interconnections are aligned to the organization’s guidelines and security requirements. While this solution presents an approach to governance, customers can tailor this solution to their unique organizational requirements.</p> 
   <p> <br>If you have feedback about this post, submit comments in the<strong> Comments</strong> section below. If you have questions about this post, <a href="https://console.aws.amazon.com/support/home" target="_blank" rel="noopener noreferrer">contact AWS Support</a>.</p> 
   <p><strong>Want more AWS Security news? Follow us on <a title="Twitter" href="https://twitter.com/AWSsecurityinfo" target="_blank" rel="noopener noreferrer">Twitter</a>.</strong></p> 

   <!-- '"` -->