

# Manage access to VPC Lattice services
<a name="access-management-overview"></a>

VPC Lattice is secure by default because you must be explicit about which services and resource configurations to provide access to and with which VPCs. You can access services through a VPC association or a VPC endpoint of type service network. For multi-account scenarios, you can use [AWS Resource Access Manager](sharing.md) to share services, resource configurations, and service networks across account boundaries.

 VPC Lattice provides a framework that lets you implement a defense-in-depth strategy at multiple layers of the network.
+ **First layer** – The service, resource, VPC, and VPC endpoint association with a service network. A VPC may be connected to a service network either though an association or through a VPC endpoint. If a VPC is not connected to a service network, clients in the VPC cannot access the service and resource configurations that are associated with the service network.
+ **Second layer** – Optional network-level security protections for the service network, such as security groups and network ACLs. By using these, you can allow access to specific groups of clients in a VPC instead of all clients in the VPC.
+ **Third layer** – Optional VPC Lattice auth policy. You can apply an auth policy to service networks and individual services. Typically, the auth policy on the service network is operated by the network or cloud administrator, and they implement coarse-grained authorization. For example, allowing only authenticated requests from a specific organization in AWS Organizations. For an auth policy at the service level, typically the service owner sets fine-grained controls, which might be more restrictive than the coarse-grained authorization applied at the service network level.
**Note**  
The auth policy on the service network doesn’t apply to resource configurations in the service network.

**Methods of access control**
+ [Auth policies](auth-policies.md)
+ [Security groups](security-groups.md)
+ [Network ACLs](network-acls.md)

# Control access to VPC Lattice services using auth policies
<a name="auth-policies"></a>

VPC Lattice auth policies are IAM policy documents that you attach to service networks or services to control whether a specified principal has access to a group of services or specific service. You can attach one auth policy to each service network or service that you want to control access to.

**Note**  
The auth policy on the service network doesn’t apply to resource configurations in the service network.

Auth policies are different from IAM identity-based policies. IAM identity-based policies are attached to IAM users, groups, or roles and define what actions those identities can do on which resources. Auth policies are attached to services and service networks. For authorization to succeed, both auth policies and identity-based policies need to have explicit allow statements. For more information, see [How authorization works](#auth-policies-evaluation-logic).

You can use the AWS CLI and console to view, add, update, or remove auth policies on services and service networks. When you add, update, or remove an auth policy, it might take a few minutes to be ready. When using the AWS CLI, make sure you are in the correct Region. You can either change the default Region for your profile, or use the `--region` parameter with the command.

**Topics**
+ [Common elements in an auth policy](#auth-policies-common-elements)
+ [Resource format for auth policies](#auth-policies-resource-format)
+ [Condition keys that can be used in auth policies](#auth-policies-condition-keys)
+ [Resource tags](#resource-tags)
+ [Principal tags](#principal-tags)
+ [Anonymous (unauthenticated) principals](#anonymous-unauthenticated-principals)
+ [Example auth policies](#example-auth-policies)
+ [How authorization works](#auth-policies-evaluation-logic)

To get started with auth policies, follow the procedure to create an auth policy that applies to a service network. For more restrictive permissions that you don't want applied to other services, you can optionally set auth policies on individual services.

## Manage access to a service network with auth policies
<a name="manage-access-to-service-networks"></a>

The following AWS CLI tasks show you how to manage access to a service network using auth policies. For instructions that use the console, see [Service networks in VPC Lattice](service-networks.md).

**Topics**
+ [Add an auth policy to a service network](#add-service-network-auth-policy)
+ [Change a service network's auth type](#change-service-network-auth-type)
+ [Remove an auth policy from a service network](#remove-service-network-auth-policy)

### Add an auth policy to a service network
<a name="add-service-network-auth-policy"></a>

Follow the steps in this section to use the AWS CLI to:
+ Enable access control on a service network using IAM.
+ Add an auth policy to the service network. If you do not add an auth policy, all traffic will get an access denied error.

**To enable access control and add an auth policy to a new service network**

1. To enable access control on a service network so that it can use an auth policy, use the **create-service-network** command with the `--auth-type` option and a value of `AWS_IAM`.

   ```
   aws vpc-lattice create-service-network --name Name --auth-type AWS_IAM [--tags TagSpecification]
   ```

   If successful, the command returns output similar to the following.

   ```
   {
      "arn": "arn",
      "authType": "AWS_IAM",
      "id": "sn-0123456789abcdef0",
      "name": "Name"
   }
   ```

1. Use the **put-auth-policy** command, specifying the ID of the service network where you want to add the auth policy and the auth policy you want to add.

   For example, use the following command to create an auth policy for the service network with the ID *`sn-0123456789abcdef0`*.

   ```
   aws vpc-lattice put-auth-policy --resource-identifier sn-0123456789abcdef0 --policy file://policy.json
   ```

   Use JSON to create a policy definition. For more information, see [Common elements in an auth policy](#auth-policies-common-elements).

   If successful, the command returns output similar to the following.

   ```
   {
      "policy": "policy",
      "state": "Active"
   }
   ```

**To enable access control and add an auth policy to an existing service network**

1. To enable access control on a service network so that it can use an auth policy, use the **update-service-network** command with the `--auth-type` option and a value of `AWS_IAM`.

   ```
   aws vpc-lattice update-service-network --service-network-identifier sn-0123456789abcdef0 --auth-type AWS_IAM
   ```

   If successful, the command returns output similar to the following.

   ```
   {
      "arn": "arn",
      "authType": "AWS_IAM",
      "id": "sn-0123456789abcdef0",
      "name": "Name"
   }
   ```

1. Use the **put-auth-policy** command, specifying the ID of the service network where you want to add the auth policy and the auth policy you want to add. 

   ```
   aws vpc-lattice put-auth-policy --resource-identifier sn-0123456789abcdef0 --policy file://policy.json
   ```

   Use JSON to create a policy definition. For more information, see [Common elements in an auth policy](#auth-policies-common-elements).

   If successful, the command returns output similar to the following.

   ```
   {
      "policy": "policy",
      "state": "Active"
   }
   ```

### Change a service network's auth type
<a name="change-service-network-auth-type"></a>

**To disable the auth policy for a service network**  
Use the **update-service-network** command with the `--auth-type` option and a value of `NONE`.

```
aws vpc-lattice update-service-network --service-network-identifier sn-0123456789abcdef0 --auth-type NONE
```

If you need to enable the auth policy again later, run this command with `AWS_IAM` specified for the `--auth-type` option.

### Remove an auth policy from a service network
<a name="remove-service-network-auth-policy"></a>

**To remove an auth policy from a service network**  
Use the **delete-auth-policy** command.

```
aws vpc-lattice delete-auth-policy --resource-identifier sn-0123456789abcdef0
```

The request fails if you remove an auth policy before changing the auth type of a service network to `NONE`.

## Manage access to a service with auth policies
<a name="manage-access-to-services"></a>

The following AWS CLI tasks show you how to manage access to a service using auth policies. For instructions that use the console, see [Services in VPC Lattice](services.md). 

**Topics**
+ [Add an auth policy to a service](#add-service-auth-policy)
+ [Change a service's auth type](#change-service-auth-type)
+ [Remove an auth policy from a service](#remove-service-auth-policy)

### Add an auth policy to a service
<a name="add-service-auth-policy"></a>

Follow these steps to use the AWS CLI to:
+ Enable access control on a service using IAM.
+ Add an auth policy to the service. If you do not add an auth policy, all traffic will get an access denied error.

**To enable access control and add an auth policy to a new service**

1. To enable access control on a service so that it can use an auth policy, use the **create-service** command with the `--auth-type` option and a value of `AWS_IAM`.

   ```
   aws vpc-lattice create-service --name Name --auth-type AWS_IAM [--tags TagSpecification]
   ```

   If successful, the command returns output similar to the following.

   ```
   {
      "arn": "arn",
      "authType": "AWS_IAM",
      "dnsEntry": { 
         ...
      },
      "id": "svc-0123456789abcdef0",
      "name": "Name",
      "status": "CREATE_IN_PROGRESS"
   }
   ```

1. Use the **put-auth-policy** command, specifying the ID of the service where you want to add the auth policy and the auth policy you want to add.

   For example, use the following command to create an auth policy for the service with the ID *svc-0123456789abcdef0*.

   ```
   aws vpc-lattice put-auth-policy --resource-identifier svc-0123456789abcdef0 --policy file://policy.json
   ```

   Use JSON to create a policy definition. For more information, see [Common elements in an auth policy](#auth-policies-common-elements).

   If successful, the command returns output similar to the following.

   ```
   {
      "policy": "policy",
      "state": "Active"
   }
   ```

**To enable access control and add an auth policy to an existing service**

1. To enable access control on a service so that it can use an auth policy, use the **update-service** command with the `--auth-type` option and a value of `AWS_IAM`.

   ```
   aws vpc-lattice update-service --service-identifier svc-0123456789abcdef0 --auth-type AWS_IAM
   ```

   If successful, the command returns output similar to the following.

   ```
   {
      "arn": "arn",
      "authType": "AWS_IAM",
      "id": "svc-0123456789abcdef0",
      "name": "Name"
   }
   ```

1. Use the **put-auth-policy** command, specifying the ID of the service where you want to add the auth policy and the auth policy you want to add.

   ```
   aws vpc-lattice put-auth-policy --resource-identifier svc-0123456789abcdef0 --policy file://policy.json
   ```

   Use JSON to create a policy definition. For more information, see [Common elements in an auth policy](#auth-policies-common-elements).

   If successful, the command returns output similar to the following.

   ```
   {
      "policy": "policy",
      "state": "Active"
   }
   ```

### Change a service's auth type
<a name="change-service-auth-type"></a>

**To disable the auth policy for a service**  
Use the **update-service** command with the `--auth-type` option and a value of `NONE`.

```
aws vpc-lattice update-service --service-identifier svc-0123456789abcdef0 --auth-type NONE
```

If you need to enable the auth policy again later, run this command with `AWS_IAM` specified for the `--auth-type` option.

### Remove an auth policy from a service
<a name="remove-service-auth-policy"></a>

**To remove an auth policy from a service**  
Use the **delete-auth-policy** command.

```
aws vpc-lattice delete-auth-policy --resource-identifier svc-0123456789abcdef0
```

The request fails if you remove an auth policy before changing the auth type of the service to `NONE`.

If you enable auth policies that require authenticated requests to a service, any requests to that service must contain a valid request signature that is computed using Signature Version 4 (SigV4). For more information, see [SIGv4 authenticated requests for Amazon VPC Lattice](sigv4-authenticated-requests.md).

## Common elements in an auth policy
<a name="auth-policies-common-elements"></a>

VPC Lattice auth policies are specified using the same syntax as IAM policies. For more information, see [Identity-based policies and resource-based policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html) in the *IAM User Guide*.

An auth policy contains the following elements:
+ **Principal** – The person or application who is allowed access to the actions and resources in the statement. In an auth policy, the principal is the IAM entity who is the recipient of this permission. The principal is authenticated as an IAM entity to make requests to a specific resource, or group of resources as in the case of services in a service network. 

  You must specify a principal in a resource-based policy. Principals can include accounts, users, roles, federated users, or AWS services. For more information, see [AWS JSON policy elements: Principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html) in the *IAM User Guide*.
+ **Effect** – The effect when the specified principal requests the specific action. This can be either `Allow` or `Deny`. By default, when you enable access control on a service or service network using IAM, principals have no permissions to make requests to the service or service network.
+ **Actions** – The specific API action for which you are granting or denying permission. VPC Lattice supports actions that use the `vpc-lattice-svcs` prefix. For more information, see [Actions defined by Amazon VPC Lattice Services](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonvpclatticeservices.html#amazonvpclatticeservices-actions-as-permissions) in the *Service Authorization Reference*.
+ **Resources** – The services that are affected by the action. 
+ **Condition** – Conditions are optional. You can use them to control when your policy is in effect. For more information, see [Condition keys for Amazon VPC Lattice Services ](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonvpclatticeservices.html#amazonvpclatticeservices-policy-keys) in the *Service Authorization Reference*.

As you create and manage auth policies, you might want to use the [IAM Policy Generator](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html#access_policies_create-generator).

**Requirement**  
The policy in JSON must not contain newlines or blank lines.

## Resource format for auth policies
<a name="auth-policies-resource-format"></a>

You can restrict access to specific resources by creating an auth policy that uses a matching schema with a `<serviceARN>/<path>` pattern and code the `Resource` element as shown in the following examples. 


| Protocol | Examples | 
| --- | --- | 
| HTTP |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/vpc-lattice/latest/ug/auth-policies.html)  | 
| gRPC |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/vpc-lattice/latest/ug/auth-policies.html)  | 

Use the following Amazon Resource Name (ARN) resource format for `<serviceARN>`:

```
arn:aws:vpc-lattice:region:account-id:service/service-id
```

For example:

```
"Resource": "arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0"
```

## Condition keys that can be used in auth policies
<a name="auth-policies-condition-keys"></a>

Access can be further controlled by condition keys in the **Condition** element of auth policies. These condition keys are present for evaluation depending on the protocol and whether the request is signed with [Signature Version 4 (SigV4)](sigv4-authenticated-requests.md) or anonymous. Condition keys are case sensitive.

AWS provides global condition keys that you can use to control access, such as `aws:PrincipalOrgID` and `aws:SourceIp`. To see a list of the AWS global condition keys, see [AWS global condition context keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html) in the *IAM User Guide*.

The following tale lists the VPC Lattice condition keys. For more information, see [Condition keys for Amazon VPC Lattice Services ](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonvpclatticeservices.html#amazonvpclatticeservices-policy-keys) in the *Service Authorization Reference*.


| Condition keys | Description | Example | Available for anonymous (unauthenticated) caller? | Available for gRPC? | 
| --- | --- | --- | --- | --- | 
| vpc-lattice-svcs:Port | Filters access by the service port the request is made to | 80 | Yes | Yes | 
| vpc-lattice-svcs:RequestMethod | Filters access by the method of the request | GET | Yes | Always POST | 
| vpc-lattice-svcs:RequestPath | Filters access by the path portion of the request URL | /path | Yes | Yes | 
| vpc-lattice-svcs:RequestHeader/header-name: value | Filters access by a header name-value pair in the request headers | content-type: application/json | Yes | Yes | 
| vpc-lattice-svcs:RequestQueryString/key-name: value | Filters access by the query string key-value pairs in the request URL | quux: [corge, grault] | Yes | No | 
| vpc-lattice-svcs:ServiceNetworkArn | Filters access by the ARN of the service network of the service that is receiving the request | arn:aws:vpc-lattice:us-west-2:123456789012:servicenetwork/sn-0123456789abcdef0 | Yes | Yes | 
| vpc-lattice-svcs:ServiceArn | Filters access by the ARN of the service that is receiving the request | arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0 | Yes | Yes | 
| vpc-lattice-svcs:SourceVpc | Filters access by the VPC the request is made from | vpc-1a2b3c4d | Yes | Yes | 
| vpc-lattice-svcs:SourceVpcOwnerAccount | Filters access by the owning account of the VPC the request is made from | 123456789012 | Yes | Yes | 

## Resource tags
<a name="resource-tags"></a>

A *tag* is a metadata label that you assign or that AWS assigns to an AWS resource. Each tag has two parts:
+ A *tag key* (for example, `CostCenter`, `Environment`, or `Project`). Tag keys are case sensitive.
+ An optional field known as a *tag value* (for example, `111122223333` or `Production`). Omitting the tag value is the same as using an empty string. Like tag keys, tag values are case-sensitive.

For more information about tagging, see [Controlling access to AWS resources using tags](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_tags.html)

You can use tags in your auth policies using the `aws:ResourceTag/key` AWS global condition context key.

The following example policy grants access to services with the tag `Environment=Gamma`. This policy lets you refer to services without hard‑coding service ARNs or IDs.

```
{
  "Version": "2012-10-17", 		 	 	 		 	 	 
  "Statement": [
    {
      "Sid": "AllowGammaAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "vpc-lattice-svcs:Invoke",
      "Resource": "arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0124446789abcdef0/*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/Environment": "Gamma",
        }
      }
    }
  ]
}
```

## Principal tags
<a name="principal-tags"></a>

You can control access to your services and resources based on the tags attached to the caller's identity. VPC Lattice supports access control based on any principal tags on the user, role, or session tags using the `aws:PrincipalTag/context` variables. For more information, see [Controlling access for IAM principals](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_iam-tags.html#access_iam-tags_control-principals).

The following example policy grants access only to identities with the tag `Team=Payments`. This policy lets you control access without hard‑coding account IDs or role ARNs.

```
{
  "Version": "2012-10-17", 		 	 	 		 	 	 
  "Statement": [
    {
      "Sid": "AllowPaymentsTeam",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "vpc-lattice-svcs:Invoke",
      "Resource": "arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0/*",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalTag/Team": "Payments",
        }
      }
    }
  ]
}
```

## Anonymous (unauthenticated) principals
<a name="anonymous-unauthenticated-principals"></a>

Anonymous principals are callers that don't sign their AWS requests with [Signature Version 4 (SigV4)](sigv4-authenticated-requests.md), and are within a VPC that is connected to the service network. Anonymous principals can make unauthenticated requests to services in the service network if an auth policy allows it.

## Example auth policies
<a name="example-auth-policies"></a>

The following are example auth policies that require requests to be made by authenticated principals.

All examples use the `us-west-2` Region and contain fictitious account IDs.

**Example 1: Restrict access to services by a specific AWS organization**  
The following auth policy example grants permissions to any authenticated request to access any services in the service network to which the policy applies. However, the request must originate from principals that belong to the AWS organization specified in the condition.

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": "*",
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": "*",
         "Condition": {
            "StringEquals": {
               "aws:PrincipalOrgID": [ 
                  "o-123456example"
               ]
            }
         }
      }
   ]
}
```

------

**Example 2: Restrict access to a service by a specific IAM role**  
The following auth policy example grants permissions to any authenticated request that uses the IAM role `rates-client` to make HTTP GET requests on the service specified in the `Resource` element. The resource in the `Resource` element is the same as the service that the policy is attached to.

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": [
               "arn:aws:iam::123456789012:role/rates-client"
            ]
         },
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": [
            "arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0/*"
         ],
         "Condition": {
            "StringEquals": {
               "vpc-lattice-svcs:RequestMethod": "GET"
            }
         }
      }
   ]
}
```

------

**Example 3: Restrict access to services by authenticated principals in a specific VPC**  
The following auth policy example only allows authenticated requests from principals in the VPC whose VPC ID is `vpc-1a2b3c4d`.

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": "*",
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": "*",
         "Condition": {
            "StringNotEquals": {
               "aws:PrincipalType": "Anonymous"
            },
            "StringEquals": {
               "vpc-lattice-svcs:SourceVpc": "vpc-1a2b3c4d"
            }
         }
      }
   ]
}
```

------

## How authorization works
<a name="auth-policies-evaluation-logic"></a>

When a VPC Lattice service receives a request, the AWS enforcement code evaluates all relevant permissions policies together to determine whether to authorize or deny the request. It evaluates all the IAM identity-based policies and auth policies that are applicable in the request context during authorization. By default, all requests are implicitly denied when the auth type is `AWS_IAM`. An explicit allow from all relevant policies overrides the default.

Authorization includes:
+ Collecting all the relevant IAM identity-based policies and auth policies.
+ Evaluating the resulting set of policies:
  + Verifying that the requester (such as an IAM user or role) has permissions to perform the operation from the account to which the requester belongs. If there is no explicit allow statement, AWS does not authorize the request.
  + Verifying that the request is allowed by the auth policy for the service network. If an auth policy is enabled, but there is no explicit allow statement, AWS does not authorize the request. If there is an explicit allow statement, or the auth type is `NONE`, the code continues. 
  + Verifying that the request is allowed by the auth policy for the service. If an auth policy is enabled, but there is no explicit allow statement, AWS does not authorize the request. If there is an explicit allow statement,or the auth type is `NONE`, then the enforcement code returns a final decision of **Allow**.
  + An explicit deny in any policy overrides any allows.

The diagram shows the authorization workflow. When a request is made, the relevant policies allow or deny the request access to a given service.

![\[Authorization workflow\]](http://docs.aws.amazon.com/vpc-lattice/latest/ug/images/authpolicy.png)


# Control traffic in VPC Lattice using security groups
<a name="security-groups"></a>

AWS security groups act as virtual firewalls, controlling the network traffic to and from the entities that they are associated with. With VPC Lattice, you can create security groups and assign them to the VPC association that connects a VPC to a service network to enforce additional network-level security protections for your service network. If you connect a VPC to a service network using a VPC endpoint, you can assign security groups to the VPC endpoint too. Similarly you can assign security groups to resource gateways that you create to enable access to resources in your VPC.

**Topics**
+ [Managed prefix list](#managed-prefix-list)
+ [Security group rules](#security-groups-rules)
+ [Manage security groups for a VPC association](#service-network-security-group)

## Managed prefix list
<a name="managed-prefix-list"></a>

VPC Lattice provides managed prefix lists that includes the IP addresses used to route traffic over the VPC Lattice network when you use a service-network association to connect your VPC to a service network using a VPC association. These IPs are either private link-local IPs or non-routeable public IPs.

 You can reference the VPC Lattice managed prefix lists in your security group rules. This allows traffic to flow from clients, through the VPC Lattice service network, and to the VPC Lattice service targets.

For example, suppose that you have an EC2 instance registered as a target in the US West (Oregon) Region (`us-west-2`). You can add a rule to the instance security group that allows inbound HTTPS access from the VPC Lattice managed prefix list, so that the VPC Lattice traffic in this Region can reach the instance. If you remove all other inbound rules from the security group, you can prevent any traffic other than VPC Lattice traffic from reaching the instance.

The names of the managed prefix lists for VPC Lattice are as follows:
+ com.amazonaws.*region*.vpc-lattice
+ com.amazonaws.*region*.ipv6.vpc-lattice

For more information, see [AWS-managed prefix lists](https://docs.aws.amazon.com/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html#available-aws-managed-prefix-lists) in the *Amazon VPC User Guide*.

**Windows and macOS clients**  
The addresses in the VPC Lattice prefix lists are link-local addresses and non-routable public addresses. If you connect to VPC Lattice from these clients, you must update their configurations so that it forwards the IP addresses in the managed prefix list to the primary IP address for the client. The following is an example command that updates the configuration of the Windows client, where 169.254.171.0 is one of the addresses in the managed prefix list. 

```
C:\> route add 169.254.171.0 mask 255.255.255.0 primary-ip-address
```

The following is an example command that updates the configuration of the macOS client, where 169.254.171.0 is one of the addresses in the managed prefix list. 

```
sudo route -n add -net 169.254.171.0 primary-ip-address 255.255.255.0
```

To avoid creating a static route, we recommend that you use a service network endpoint in a VPC to establish connectivity. For more information, see [Manage service network VPC endpoint associations](service-network-associations.md#service-network-vpc-endpoint-associations).

## Security group rules
<a name="security-groups-rules"></a>

Using VPC Lattice with or without security groups will not impact your existing VPC security group configuration. However, you can add your own security groups at any time.

**Key considerations**
+ Security group rules for clients control outbound traffic to VPC Lattice. 
+ Security group rules for targets control inbound traffic from VPC Lattice to the targets, including health check traffic. 
+ Security group rules for the association between the service network and VPC control which clients can access the VPC Lattice service network.
+ Security group rules for resource gateway control outbound traffic from the resource gateway to resources.

**Recommended outbound rules for traffic flowing from resource gateway to a database resource**  
For traffic to flow from resource gateway to resources, you must create outbound rules for the open ports and accepted listener protocols for the resources.


| Destination | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| CIDR range for resource | TCP | 3306 | Allow traffic from resource gateway to databases | 

**Recommended inbound rules for service network and VPC associations**  
For traffic to flow from client VPCs to the services associated with the service network, you must create inbound rules for the listener ports and listener protocols for the services.


| Source | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| VPC CIDR | listener | listener | Allow traffic from clients to VPC Lattice | 

**Recommended outbound rules for traffic flowing from client instances to VPC Lattice**  
By default, security groups allow all outbound traffic. However, if you have custom outbound rules, you must allow outbound traffic to VPC Lattice prefix for listener ports and protocols so that client instances can connect to all services associated with the VPC Lattice service network. You can allow this traffic by referencing the ID of the prefix list for VPC Lattice.


| Destination | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| ID of the VPC Lattice prefix list | listener | listener | Allow traffic from clients to VPC Lattice | 

**Recommended inbound rules for traffic flowing from VPC Lattice to target instances**  
You can't use the client security group as a source for your target's security groups, because traffic flows from VPC Lattice. You can reference the ID of the prefix list for VPC Lattice.


| Source | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| ID of the VPC Lattice prefix list | target | target | Allow traffic from VPC Lattice to targets | 
| ID of the VPC Lattice prefix list | health check | health check | Allow health check traffic from VPC Lattice to targets | 

## Manage security groups for a VPC association
<a name="service-network-security-group"></a>

You can use the AWS CLI to view, add, or update security groups on the VPC to service network association. When using the AWS CLI, remember that your commands run in the AWS Region configured for your profile. If you want to run the commands in a different Region, either change the default Region for your profile, or use the `--region` parameter with the command.

Before you begin, confirm that you have created the security group in the same VPC as the VPC you want to add to the service network. For more information, see [Control traffic to your resources using security groups](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html) in the *Amazon VPC User Guide*

**To add a security group when you create a VPC association using the console**

1. Open the Amazon VPC console at [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/).

1. In the navigation pane, under **VPC Lattice**, choose **Service networks**.

1. Select the name of the service network to open its details page.

1. On the **VPC associations** tab, choose **Create VPC associations** and then choose **Add VPC association**.

1. Select a VPC and up to five security groups.

1. Choose **Save changes**.

**To add or update security groups for an existing VPC association using the console**

1. Open the Amazon VPC console at [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/).

1. In the navigation pane, under **VPC Lattice**, choose **Service networks**.

1. Select the name of the service network to open its details page.

1. On the **VPC associations** tab, select the check box for the association and then choose **Actions**, **Edit security groups**.

1. Add and remove security groups as needed.

1. Choose **Save changes**.

**To add a security group when you create a VPC association using the AWS CLI**  
Use the [create-service-network-vpc-association](https://docs.aws.amazon.com/cli/latest/reference/vpc-lattice/create-service-network-vpc-association.html) command, specifying the ID of the VPC for the VPC association and the ID of the security groups to add.

```
aws vpc-lattice create-service-network-vpc-association \
    --service-network-identifier sn-0123456789abcdef0 \
    --vpc-identifier vpc-1a2b3c4d \
    --security-group-ids sg-7c2270198example
```

If successful, the command returns output similar to the following.

```
{
  "arn": "arn",
  "createdBy": "464296918874",
  "id": "snva-0123456789abcdef0",
  "status": "CREATE_IN_PROGRESS",
  "securityGroupIds": ["sg-7c2270198example"]
}
```

**To add or update security groups for an existing VPC association using the AWS CLI**  
Use the [update-service-network-vpc-association](https://docs.aws.amazon.com/cli/latest/reference/vpc-lattice/update-service-network-vpc-association.html) command, specifying the ID of the service network and the IDs of the security groups. These security groups override any previously associated security groups. Define at least one security group when updating the list.

```
aws vpc-lattice update-service-network-vpc-association 
    --service-network-vpc-association-identifier sn-903004f88example \
    --security-group-ids sg-7c2270198example sg-903004f88example
```

**Warning**  
You can't remove all security groups. Instead, you must first delete the VPC association, and then re-create the VPC association without any security groups. Be cautious when deleting the VPC association. This prevents traffic from reaching services that are in that service network.

# Control traffic to VPC Lattice using network ACLs
<a name="network-acls"></a>

A network access control list (ACL) allows or denies specific inbound or outbound traffic at the subnet level. The default network ACL allows all inbound and outbound traffic. You can create custom network ACLs for your subnets to provide an additional layer of security. For more information, see [Network ACLs](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html) in the *Amazon VPC User Guide*.

**Topics**
+ [Network ACLs for your client subnets](#network-acl-client-subnets)
+ [Network ACLs for your target subnets](#network-acl-target-subnets)

## Network ACLs for your client subnets
<a name="network-acl-client-subnets"></a>

The network ACLs for client subnets must allow traffic between clients and VPC Lattice. You can get the IP address ranges to allow from the [managed prefix list](security-groups.md#managed-prefix-list) for VPC Lattice.

The following is an example inbound rule.


| Source | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| vpc\$1lattice\$1cidr\$1block | TCP | 1025-65535 | Allow traffic from VPC Lattice to clients | 

The following is an example outbound rule.


| Destination | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| vpc\$1lattice\$1cidr\$1block | listener | listener | Allow traffic from clients to VPC Lattice | 

## Network ACLs for your target subnets
<a name="network-acl-target-subnets"></a>

The network ACLs for target subnets must allow traffic between targets and VPC Lattice on both the target port and the health check port. You can get the IP address ranges to allow from the [managed prefix list](security-groups.md#managed-prefix-list) for VPC Lattice.

The following is an example inbound rule.


| Source | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| vpc\$1lattice\$1cidr\$1block | target | target | Allow traffic from VPC Lattice to targets | 
| vpc\$1lattice\$1cidr\$1block | health check | health check | Allow health check traffic from VPC Lattice to targets | 

The following is an example outbound rule.


| Destination | Protocol | Port range | Comment | 
| --- | --- | --- | --- | 
| vpc\$1lattice\$1cidr\$1block | target | 1024-65535 | Allow traffic from targets to VPC Lattice | 
| vpc\$1lattice\$1cidr\$1block | health check | 1024-65535 | Allow health check traffic from targets to VPC Lattice | 

# SIGv4 authenticated requests for Amazon VPC Lattice
<a name="sigv4-authenticated-requests"></a>

VPC Lattice uses Signature Version 4 (SIGv4) or Signature Version 4A (SIGv4A) for client authentication. For more information, see [AWS Signature Version 4 for API requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) in the *IAM User Guide*.

**Considerations**
+ VPC Lattice attempts to authenticate any request that is signed with SIGv4 or SIGv4A. The request fails without authentication.
+ VPC Lattice does not support payload signing. You must send an `x-amz-content-sha256` header with the value set to `"UNSIGNED-PAYLOAD"`.

**Topics**
+ [Python](#sigv4-authenticated-requests-python)
+ [Java](#sigv4-authenticated-requests-java-custom-interceptor)
+ [Node.js](#sigv4-authenticated-requests-nodejs)
+ [Golang](#sigv4-authenticated-requests-golang)
+ [Golang - GRPC](#sigv4-authenticated-requests-golang-grpc)

## Python
<a name="sigv4-authenticated-requests-python"></a>

This example sends the signed requests over a secure connection to a service registered in the network. If you prefer to use [requests](https://requests.readthedocs.io/en/latest/), the [botocore](https://github.com/boto/botocore) package simplifies the authentication process, but is not strictly required. For more information, see [Credentials](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html) in the Boto3 documentation.

To install the `botocore` and `awscrt` packages, use the following command. For more information, see [AWS CRT Python](https://pypi.org/project/awscrt/).

```
pip install botocore awscrt
```

If you run the client application on Lambda, install the required modules using [Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/python-layers.html), or include them in your deployment package.

In the following example, replace the placeholder values with your own values.

------
#### [ SIGv4 ]

```
from botocore import crt
import requests 
from botocore.awsrequest import AWSRequest
import botocore.session

if __name__ == '__main__':
    session = botocore.session.Session()
    signer = crt.auth.CrtSigV4Auth(session.get_credentials(), 'vpc-lattice-svcs', 'us-west-2')
    endpoint = 'https://data-svc-022f67d3a42.1234abc.vpc-lattice-svcs.us-west-2.on.aws'
    data = "some-data-here"
    headers = {'Content-Type': 'application/json', 'x-amz-content-sha256': 'UNSIGNED-PAYLOAD'}
    request = AWSRequest(method='POST', url=endpoint, data=data, headers=headers)
    request.context["payload_signing_enabled"] = False
    signer.add_auth(request)
    
    prepped = request.prepare()
    
    response = requests.post(prepped.url, headers=prepped.headers, data=data)
    print(response.text)
```

------
#### [ SIGv4A ]

```
from botocore import crt
import requests 
from botocore.awsrequest import AWSRequest
import botocore.session

if __name__ == '__main__':
    session = botocore.session.Session()
    signer = crt.auth.CrtSigV4AsymAuth(session.get_credentials(), 'vpc-lattice-svcs', '*')
    endpoint = 'https://data-svc-022f67d3a42.1234abc.vpc-lattice-svcs.us-west-2.on.aws'
    data = "some-data-here"
    headers = {'Content-Type': 'application/json', 'x-amz-content-sha256': 'UNSIGNED-PAYLOAD'}
    request = AWSRequest(method='POST', url=endpoint, data=data, headers=headers)
    request.context["payload_signing_enabled"] = False 
    signer.add_auth(request)
    
    prepped = request.prepare()
    
    response = requests.post(prepped.url, headers=prepped.headers, data=data)
    print(response.text)
```

------

## Java
<a name="sigv4-authenticated-requests-java-custom-interceptor"></a>

This example shows how you can perform request signing by using custom interceptors. It uses the default credentials provider class from [AWS SDK for Java 2.x](https://github.com/aws/aws-sdk-java-v2), which gets the correct credentials for you. If you would prefer to use a specific credential provider, you can select one from the [AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html). The AWS SDK for Java allows only unsigned payloads over HTTPS. However, you can extend the signer to support unsigned payloads over HTTP.

------
#### [ SIGv4 ]

```
package com.example;

import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;

import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.http.HttpExecuteRequest;
import software.amazon.awssdk.http.HttpExecuteResponse;
import java.io.IOException;
import java.net.URI;

import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;

public class sigv4 {

    public static void main(String[] args) {
        AwsV4HttpSigner signer = AwsV4HttpSigner.create();

        AwsCredentialsIdentity credentials = DefaultCredentialsProvider.create().resolveCredentials();

        if (args.length < 2) {
            System.out.println("Usage: sample <url> <region>");
            System.exit(1);
        }
        // Create the HTTP request to be signed
        var url = args[0];
        SdkHttpRequest httpRequest = SdkHttpRequest.builder()
                .uri(URI.create(url))
                .method(SdkHttpMethod.GET)
                .build();

        SignedRequest signedRequest = signer.sign(r -> r.identity(credentials)
                .request(httpRequest)
                .putProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "vpc-lattice-svcs")
                .putProperty(AwsV4HttpSigner.PAYLOAD_SIGNING_ENABLED, false)
                .putProperty(AwsV4HttpSigner.REGION_NAME, args[1]));

        System.out.println("[*] Raw request headers:");
        signedRequest.request().headers().forEach((key, values) -> {
            values.forEach(value -> System.out.println("  " + key + ": " + value));
        });

        try (SdkHttpClient httpClient = ApacheHttpClient.create()) {
            HttpExecuteRequest httpExecuteRequest = HttpExecuteRequest.builder()
                    .request(signedRequest.request())
                    .contentStreamProvider(signedRequest.payload().orElse(null))
                    .build();

            System.out.println("[*] Sending request to: " + url);

            HttpExecuteResponse httpResponse = httpClient.prepareRequest(httpExecuteRequest).call();

            System.out.println("[*] Request sent");

            System.out.println("[*] Response status code: " + httpResponse.httpResponse().statusCode());
            // Read and print the response body
            httpResponse.responseBody().ifPresent(inputStream -> {
                try {
                    String responseBody = new String(inputStream.readAllBytes());
                    System.out.println("[*] Response body: " + responseBody);
                } catch (IOException e) {
                    System.err.println("[*] Failed to read response body");
                    e.printStackTrace();
                } finally {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        System.err.println("[*] Failed to close input stream");
                        e.printStackTrace();
                    }
                }
            });
        } catch (IOException e) {
            System.err.println("[*] HTTP Request Failed.");
            e.printStackTrace();
        }

    }
}
```

------
#### [ SIGv4A ]

This example requires an additional dependency on `software.amazon.awssdk:http-auth-aws-crt`.

```
package com.example;


import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;

import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.http.HttpExecuteRequest;
import software.amazon.awssdk.http.HttpExecuteResponse;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;

import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;

public class sigv4a {
    
    public static void main(String[] args) {
        AwsV4aHttpSigner signer = AwsV4aHttpSigner.create();

        AwsCredentialsIdentity credentials = DefaultCredentialsProvider.create().resolveCredentials();

        if (args.length < 2) {
            System.out.println("Usage: sample <url> <regionset>");
            System.exit(1);
        }
        // Create the HTTP request to be signed
        var url = args[0];
        SdkHttpRequest httpRequest = SdkHttpRequest.builder()
                .uri(URI.create(url))
                .method(SdkHttpMethod.GET)
                .build();

        SignedRequest signedRequest = signer.sign(r -> r.identity(credentials)
                .request(httpRequest)
                .putProperty(AwsV4aHttpSigner.SERVICE_SIGNING_NAME, "vpc-lattice-svcs")
                .putProperty(AwsV4aHttpSigner.PAYLOAD_SIGNING_ENABLED, false)
                .putProperty(AwsV4aHttpSigner.REGION_SET, RegionSet.create(String.join(" ",Arrays.copyOfRange(args, 1, args.length)))));

        System.out.println("[*] Raw request headers:");
        signedRequest.request().headers().forEach((key, values) -> {
            values.forEach(value -> System.out.println("  " + key + ": " + value));
        });

        try (SdkHttpClient httpClient = ApacheHttpClient.create()) {
            HttpExecuteRequest httpExecuteRequest = HttpExecuteRequest.builder()
                    .request(signedRequest.request())
                    .contentStreamProvider(signedRequest.payload().orElse(null))
                    .build();

            System.out.println("[*] Sending request to: " + url);

            HttpExecuteResponse httpResponse = httpClient.prepareRequest(httpExecuteRequest).call();

            System.out.println("[*] Request sent");

            System.out.println("[*] Response status code: " + httpResponse.httpResponse().statusCode());
            // Read and print the response body
            httpResponse.responseBody().ifPresent(inputStream -> {
                try {
                    String responseBody = new String(inputStream.readAllBytes());
                    System.out.println("[*] Response body: " + responseBody);
                } catch (IOException e) {
                    System.err.println("[*] Failed to read response body");
                    e.printStackTrace();
                } finally {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        System.err.println("[*] Failed to close input stream");
                        e.printStackTrace();
                    }
                }
            });
        } catch (IOException e) {
            System.err.println("[*] HTTP Request Failed.");
            e.printStackTrace();
        }
    }
}
```

------

## Node.js
<a name="sigv4-authenticated-requests-nodejs"></a>

This example uses [aws-crt NodeJS bindings](https://github.com/awslabs/aws-crt-nodejs) to send a signed request using HTTPS.

To install the `aws-crt` package, use the following command.

```
npm -i aws-crt
```

If the `AWS_REGION` environment variable exists, the example uses the Region specified by `AWS_REGION`. The default Region is `us-east-1`.

------
#### [ SIGv4 ]

```
const https = require('https')
const crt = require('aws-crt')
const { HttpRequest } = require('aws-crt/dist/native/http')

function sigV4Sign(method, endpoint, service, algorithm) {
    const host = new URL(endpoint).host
    const request = new HttpRequest(method, endpoint)
    request.headers.add('host', host)
    // crt.io.enable_logging(crt.io.LogLevel.INFO)
    const config = {
        service: service,
        region: process.env.AWS_REGION ? process.env.AWS_REGION : 'us-east-1',
        algorithm: algorithm,
        signature_type: crt.auth.AwsSignatureType.HttpRequestViaHeaders,
        signed_body_header: crt.auth.AwsSignedBodyHeaderType.XAmzContentSha256,
        signed_body_value: crt.auth.AwsSignedBodyValue.UnsignedPayload,
        provider: crt.auth.AwsCredentialsProvider.newDefault()
    }

    return crt.auth.aws_sign_request(request, config)
}

if (process.argv.length === 2) {
  console.error(process.argv[1] + ' <url>')
  process.exit(1)
}

const algorithm = crt.auth.AwsSigningAlgorithm.SigV4;

sigV4Sign('GET', process.argv[2], 'vpc-lattice-svcs', algorithm).then(
  httpResponse => {
    var headers = {}

    for (const sigv4header of httpResponse.headers) {
      headers[sigv4header[0]] = sigv4header[1]
    }

    const options = {
      hostname: new URL(process.argv[2]).host,
      path: new URL(process.argv[2]).pathname,
      method: 'GET',
      headers: headers
    }

    req = https.request(options, res => {
      console.log('statusCode:', res.statusCode)
      console.log('headers:', res.headers)
      res.on('data', d => {
        process.stdout.write(d)
      })
    })
    req.on('error', err => {
      console.log('Error: ' + err)
    })
    req.end()
  }
)
```

------
#### [ SIGv4A ]

```
const https = require('https')
const crt = require('aws-crt')
const { HttpRequest } = require('aws-crt/dist/native/http')

function sigV4Sign(method, endpoint, service, algorithm) {
    const host = new URL(endpoint).host
    const request = new HttpRequest(method, endpoint)
    request.headers.add('host', host)
    // crt.io.enable_logging(crt.io.LogLevel.INFO)
    const config = {
        service: service,
        region: process.env.AWS_REGION ? process.env.AWS_REGION : 'us-east-1',
        algorithm: algorithm,
        signature_type: crt.auth.AwsSignatureType.HttpRequestViaHeaders,
        signed_body_header: crt.auth.AwsSignedBodyHeaderType.XAmzContentSha256,
        signed_body_value: crt.auth.AwsSignedBodyValue.UnsignedPayload,
        provider: crt.auth.AwsCredentialsProvider.newDefault()
    }

    return crt.auth.aws_sign_request(request, config)
}

if (process.argv.length === 2) {
  console.error(process.argv[1] + ' <url>')
  process.exit(1)
}

const algorithm = crt.auth.AwsSigningAlgorithm.SigV4Asymmetric;

sigV4Sign('GET', process.argv[2], 'vpc-lattice-svcs', algorithm).then(
  httpResponse => {
    var headers = {}

    for (const sigv4header of httpResponse.headers) {
      headers[sigv4header[0]] = sigv4header[1]
    }

    const options = {
      hostname: new URL(process.argv[2]).host,
      path: new URL(process.argv[2]).pathname,
      method: 'GET',
      headers: headers
    }

    req = https.request(options, res => {
      console.log('statusCode:', res.statusCode)
      console.log('headers:', res.headers)
      res.on('data', d => {
        process.stdout.write(d)
      })
    })
    req.on('error', err => {
      console.log('Error: ' + err)
    })
    req.end()
  }
)
```

------

## Golang
<a name="sigv4-authenticated-requests-golang"></a>

This example uses the [Smithy code generators for Go](https://github.com/aws/smithy-go) and the [AWS SDK for the Go programming language](https://github.com/aws/aws-sdk-go) to handle request signing requests. The example requires a Go version of 1.21 or higher.

------
#### [ SIGv4 ]

```
package main
 
import (
        "context"
        "flag"
        "fmt"
        "io"
        "log"
        "net/http"
        "net/http/httputil"
        "os"
        "strings"
 
        "github.com/aws/aws-sdk-go-v2/aws"
        "github.com/aws/aws-sdk-go-v2/config"
        "github.com/aws/smithy-go/aws-http-auth/credentials"
        "github.com/aws/smithy-go/aws-http-auth/sigv4"
        v4 "github.com/aws/smithy-go/aws-http-auth/v4"
)
 
type nopCloser struct {
        io.ReadSeeker
}
 
func (nopCloser) Close() error {
        return nil
}
 
type stringFlag struct {
        set   bool
        value string
}
 
 
        flag.PrintDefaults()
        os.Exit(1)
}
 
func main() {
        flag.Parse()
        if !url.set || !region.set {
                Usage()
        }
 
        cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithClientLogMode(aws.LogSigning))
        if err != nil {
                log.Fatalf("failed to load SDK configuration, %v", err)
        }
 
        if len(os.Args) < 2 {
                log.Fatalf("Usage: go run main.go  <url>")
        }
 
        // Retrieve credentials from an SDK source, such as the instance profile
        sdkCreds, err := cfg.Credentials.Retrieve(context.TODO())
        if err != nil {
                log.Fatalf("Unable to retrieve credentials from SDK, %v", err)
        }
 
        creds := credentials.Credentials{
                AccessKeyID:     sdkCreds.AccessKeyID,
                SecretAccessKey: sdkCreds.SecretAccessKey,
                SessionToken:    sdkCreds.SessionToken,
        }
 
        // Add a payload body, which will not be part of the signature calculation
        body := nopCloser{strings.NewReader(`Example payload body`)}
 
        req, _ := http.NewRequest(http.MethodPost, url.value, body)
 
        // Create a sigv4a signer with specific options
        signer := sigv4.New(func(o *v4.SignerOptions) {
                o.DisableDoublePathEscape = true
                // This will add the UNSIGNED-PAYLOAD sha256 header
                o.AddPayloadHashHeader = true
                o.DisableImplicitPayloadHashing = true
        })
 
        // Perform the signing on req, using the credentials we retrieved from the SDK
        err = signer.SignRequest(&sigv4.SignRequestInput{
                Request:     req,
                Credentials: creds,
                Service:     "vpc-lattice-svcs",
                Region: region.String(),
        })
 
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        res, err := httputil.DumpRequest(req, true)
 
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        log.Printf("[*] Raw request\n%s\n", string(res))
 
        log.Printf("[*] Sending request to %s\n", url.value)
 
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        log.Printf("[*] Request sent\n")
 
        log.Printf("[*] Response status code: %d\n", resp.StatusCode)
 
        respBody, err := io.ReadAll(resp.Body)
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        log.Printf("[*] Response body: \n%s\n", respBody)
}
```

------
#### [ SIGv4A ]

```
package main
 
import (
        "context"
        "flag"
        "fmt"
        "io"
        "log"
        "net/http"
        "net/http/httputil"
        "os"
        "strings"
 
        "github.com/aws/aws-sdk-go-v2/aws"
        "github.com/aws/aws-sdk-go-v2/config"
        "github.com/aws/smithy-go/aws-http-auth/credentials"
        "github.com/aws/smithy-go/aws-http-auth/sigv4a"
        v4 "github.com/aws/smithy-go/aws-http-auth/v4"
)
 
type nopCloser struct {
        io.ReadSeeker
}
 
func (nopCloser) Close() error {
        return nil
}
 
type stringFlag struct {
 
func main() {
        flag.Parse()
        if !url.set || !regionSet.set {
                Usage()
        }
 
        cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithClientLogMode(aws.LogSigning))
        if err != nil {
                log.Fatalf("failed to load SDK configuration, %v", err)
        }
 
        if len(os.Args) < 2 {
                log.Fatalf("Usage: go run main.go <url>")
        }
 
        // Retrieve credentials from an SDK source, such as the instance profile
        sdkCreds, err := cfg.Credentials.Retrieve(context.TODO())
        if err != nil {
                log.Fatalf("Unable to retrieve credentials from SDK, %v", err)
        }
 
        creds := credentials.Credentials{
                AccessKeyID:     sdkCreds.AccessKeyID,
                SecretAccessKey: sdkCreds.SecretAccessKey,
                SessionToken:    sdkCreds.SessionToken,
        }
 
        // Add a payload body, which will not be part of the signature calculation
        body := nopCloser{strings.NewReader(`Example payload body`)}
 
        req, _ := http.NewRequest(http.MethodPost, url.value, body)
 
        // Create a sigv4a signer with specific options
        signer := sigv4a.New(func(o *v4.SignerOptions) {
                o.DisableDoublePathEscape = true
                // This will add the UNSIGNED-PAYLOAD sha256 header
                o.AddPayloadHashHeader = true
                o.DisableImplicitPayloadHashing = true
        })
 
        // Create a slice out of the provided regionset
        rs := strings.Split(regionSet.value, ",")
 
        // Perform the signing on req, using the credentials we retrieved from the SDK
        err = signer.SignRequest(&sigv4a.SignRequestInput{
                Request:     req,
                Credentials: creds,
                Service:     "vpc-lattice-svcs",
                RegionSet: rs,
        })
 
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        res, err := httputil.DumpRequest(req, true)
 
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        log.Printf("[*] Raw request\n%s\n", string(res))
 
        log.Printf("[*] Sending request to %s\n", url.value)
 
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        log.Printf("[*] Request sent\n")
 
        log.Printf("[*] Response status code: %d\n", resp.StatusCode)
 
        respBody, err := io.ReadAll(resp.Body)
        if err != nil {
                log.Fatalf("%s", err)
        }
 
        log.Printf("[*] Response body: \n%s\n", respBody)
}
```

------

## Golang - GRPC
<a name="sigv4-authenticated-requests-golang-grpc"></a>

This example uses the [AWS SDK for the Go programming language](https://github.com/aws/aws-sdk-go-v2/) to handle request signing for GRPC requests. This can be used with the [echo server](https://github.com/grpc/grpc-go/tree/master/examples/features/proto/echo) from the GRPC sample code repository.

```
package main

import (
    "context"
    "crypto/tls"
    "crypto/x509"

    "flag"
    "fmt"
    "log"
    "net/http"
    "net/url"
    "strings"
    "time"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"

    "github.com/aws/aws-sdk-go-v2/aws"
    v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
    "github.com/aws/aws-sdk-go-v2/config"

    ecpb "google.golang.org/grpc/examples/features/proto/echo"
)

const (
    headerContentSha    = "x-amz-content-sha256"
    headerSecurityToken = "x-amz-security-token"
    headerDate          = "x-amz-date"
    headerAuthorization = "authorization"
    unsignedPayload     = "UNSIGNED-PAYLOAD"
)

type SigV4GrpcSigner struct {
    service      string
    region       string
    credProvider aws.CredentialsProvider
    signer       *v4.Signer
}

func NewSigV4GrpcSigner(service string, region string, credProvider aws.CredentialsProvider) *SigV4GrpcSigner {
    signer := v4.NewSigner()
    return &SigV4GrpcSigner{
        service:      service,
        region:       region,
        credProvider: credProvider,
        signer:       signer,
    }
}

func (s *SigV4GrpcSigner) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    ri, _ := credentials.RequestInfoFromContext(ctx)
    creds, err := s.credProvider.Retrieve(ctx)
    if err != nil {
        return nil, fmt.Errorf("failed to load credentials: %w", err)
    }

    // The URI we get here is scheme://authority/service/ - for siging we want to include the RPC name
    // But RequestInfoFromContext only has the combined /service/rpc-name - so read the URI, and
    // replace the Path with what we get from RequestInfo.
    parsed, err := url.Parse(uri[0])
    if err != nil {
        return nil, err
    }
    parsed.Path = ri.Method

    // Build a request for the signer.
    bodyReader := strings.NewReader("")
    req, err := http.NewRequest("POST", uri[0], bodyReader)
    if err != nil {
        return nil, err
    }
    date := time.Now()
    req.Header.Set(headerContentSha, unsignedPayload)
    req.Header.Set(headerDate, date.String())
    if creds.SessionToken != "" {
        req.Header.Set(headerSecurityToken, creds.SessionToken)
    }
    // The signer wants this as //authority/path
    // So get this by triming off the scheme and the colon before the first slash.
    req.URL.Opaque = strings.TrimPrefix(parsed.String(), parsed.Scheme+":")

    err = s.signer.SignHTTP(context.Background(), creds, req, unsignedPayload, s.service, s.region, date)
    if err != nil {
        return nil, fmt.Errorf("failed to sign request: %w", err)
    }

    // Pull the relevant headers out of the signer, and return them to get
    // included in the request we make.
    reqHeaders := map[string]string{
        headerContentSha:    req.Header.Get(headerContentSha),
        headerDate:          req.Header.Get(headerDate),
        headerAuthorization: req.Header.Get(headerAuthorization),
    }
    if req.Header.Get(headerSecurityToken) != "" {
        reqHeaders[headerSecurityToken] = req.Header.Get(headerSecurityToken)
    }

    return reqHeaders, nil
}

func (c *SigV4GrpcSigner) RequireTransportSecurity() bool {
    return true
}

var addr = flag.String("addr", "some-lattice-service:443", "the address to connect to")
var region = flag.String("region", "us-west-2", "region")

func callUnaryEcho(client ecpb.EchoClient, message string) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    resp, err := client.UnaryEcho(ctx, &ecpb.EchoRequest{Message: message})
    if err != nil {
        log.Fatalf("client.UnaryEcho(_) = _, %v: ", err)
    }
    fmt.Println("UnaryEcho: ", resp.Message)
}

func main() {
    flag.Parse()
    cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithClientLogMode(aws.LogSigning))
    if err != nil {
        log.Fatalf("failed to load SDK configuration, %v", err)
    }

    pool, _ := x509.SystemCertPool()
    tlsConfig := &tls.Config{
        RootCAs: pool,
    }

    authority, _, _ := strings.Cut(*addr, ":") // Remove the port from the addr
    opts := []grpc.DialOption{
        grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),

        // Lattice needs both the Authority to be set (without a port), and the SigV4 signer
        grpc.WithAuthority(authority),
        grpc.WithPerRPCCredentials(NewSigV4GrpcSigner("vpc-lattice-svcs", *region, cfg.Credentials)),
    }

    conn, err := grpc.Dial(*addr, opts...)

    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    rgc := ecpb.NewEchoClient(conn)

    callUnaryEcho(rgc, "hello world")
}
```