Access AWS Lambda with a service account
Associate an IAM role with a gateway proxy service account, and configure Gloo Gateway to use that service account to access AWS Lambda.
About
Amazon Web Services (AWS) offers the ability to associate an IAM role with a Kubernetes service account, also known as creating an IRSA. Gloo Gateway supports discovering and invoking AWS Lambda functions by using an IRSA. For more information, see the AWS documentation.
In this guide, you follow these steps:
AWS resources:
- Associate your EKS cluster with an IAM OIDC provider
- Create an IAM policy that allows interactions with Lambda functions
- Create an IAM role that associates the IAM policy with the gateway proxy service account (an IRSA)
- Deploy the Amazon EKS Pod Identity Webhook to your cluster
- Create a Lambda function for testing
Gloo resources:
- Install Gloo Gateway, including settings to annotate the gateway proxy service account with the IRSA
- Set up routing to your function by creating
UpstreamandHTTPRouteresources
Before you begin
Before you begin, review the following considerations:
This guide requires you to enable IAM settings in your EKS cluster, such as the AWS Pod Identity Webhook, before you deploy Gloo Gateway components that are created during installation, such as the Gateway CRD and the gateway proxy service account. You might use this guide with a fresh EKS test cluster to try out Lambda function invocation with Gloo Gateway service accounts.
The following steps assume that the AWS account you use to authenticate with Gloo Gateway also contains the Lambda functions that you want to route to. To instead allow Gloo Gateway to route requests to Lambda functions that exist in different accounts, see Configure cross-account Lambda access.
Configure AWS IAM resources
Save your AWS details, and create an IRSA for the gateway proxy pod to use.
Save the region where your Lambda functions exist, the region where your EKS cluster exists, your cluster name, and the ID of the AWS account.
export AWS_LAMBDA_REGION=<lambda_function_region> export AWS_CLUSTER_REGION=<cluster_region> export CLUSTER_NAME=<cluster_name> export ACCOUNT_ID=<account_id>Check whether your EKS cluster has an OIDC provider.
export OIDC_PROVIDER=$(aws eks describe-cluster --name ${CLUSTER_NAME} --region ${AWS_CLUSTER_REGION} --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///") echo $OIDC_PROVIDER- If an OIDC provider in the format
oidc.eks.<region>.amazonaws.com/id/<cluster_id>is returned, continue to the next step. - If an OIDC provider is not returned, follow the AWS documentation to Create an IAM OIDC provider for your cluster, and then run this command again to save the OIDC provider in an environment variable.
- If an OIDC provider in the format
Create an IAM policy to allow access to the following four Lambda actions. Note that the permissions to discover and invoke functions are listed in the same policy. In a more advanced setup, you might separate discovery and invocation permissions into two IAM policies.
cat >policy.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:ListFunctions", "lambda:InvokeFunction", "lambda:GetFunction", "lambda:InvokeAsync" ], "Resource": "*" } ] } EOF aws iam create-policy --policy-name gloo-lambda-policy --policy-document file://policy.jsonUse an IAM role to associate the policy with the Kubernetes service account for the HTTP gateway proxy, which assumes this role to invoke Lambda functions. For more information about these steps, see the AWS documentation.
- Create the following IAM role. Note that the service account name
gloo-proxy-httpin thegloo-systemnamespace is specified, because in later steps you create an HTTP gateway namedhttp.cat >role.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${OIDC_PROVIDER}:sub": [ "system:serviceaccount:gloo-system:gloo-proxy-http" ] } } } ] } EOF aws iam create-role --role-name gloo-lambda-role --assume-role-policy-document file://role.json - Attach the IAM role to the IAM policy. This IAM role for the service account is known as an IRSA.
aws iam attach-role-policy --role-name gloo-lambda-role --policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/gloo-lambda-policy - Verify that the policy is attached to the role.Example output:
aws iam list-attached-role-policies --role-name gloo-lambda-role{ "AttachedPolicies": [ { "PolicyName": "gloo-lambda-policy", "PolicyArn": "arn:aws:iam::111122223333:policy/gloo-lambda-policy" } ] }
- Create the following IAM role. Note that the service account name
Deploy the Amazon EKS Pod Identity Webhook
Before you install Gloo Gateway, deploy the Amazon EKS Pod Identity Webhook, which allows pods’ service accounts to use AWS IAM roles. When you create the Gloo Gateway proxy in the next section, this webhook mutates the proxy’s service account so that it can assume your IAM role to invoke Lambda functions.
In your EKS cluster, install cert-manager, which is a prerequisite for the webhook.
wget https://github.com/cert-manager/cert-manager/releases/download/v1.12.4/cert-manager.yaml kubectl apply -f cert-manager.yamlVerify that all cert-manager pods are running.
kubectl get pods -n cert-managerDeploy the Amazon EKS Pod Identity Webhook.
kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/auth.yaml kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/deployment-base.yaml kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/mutatingwebhook.yaml kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/service.yamlVerify that the webhook deployment completes.
kubectl rollout status deploy/pod-identity-webhook
Install Gloo Gateway with service account authentication
Install the open source or enterprise edition of Gloo Gateway, including settings to support gateway proxy service account authentication with your AWS account.
Open source
Install the custom resources of the Kubernetes Gateway API.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yamlExample output:
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io createdAdd the Helm repository for Gloo Gateway Open Source.
helm repo add gloo https://storage.googleapis.com/solo-public-helm helm repo updateInstall Gloo Gateway. This command creates the
gloo-systemnamespace and installs the Gloo Gateway control plane into it. The following settings also enable Gloo Gateway to use an AWS IRSA and annotate thegloo-proxy-httpservice account.helm install -n gloo-system gloo gloo/gloo \ --create-namespace \ --version 1.20.3 \ -f -<<EOF gatewayProxies: gatewayProxy: disabled: true gloo: disableLeaderElection: true kubeGateway: enabled: true # Annotate the gateway proxy service account gatewayParameters: glooGateway: serviceAccount: extraAnnotations: eks.amazonaws.com/role-arn: arn:aws:iam::${ACCOUNT_ID}:role/gloo-lambda-role # Enable AWS account authentication with IRSA settings: aws: enableServiceAccountCredentials: true stsCredentialsRegion: ${AWS_LAMBDA_REGION} EOFExample output:
NAME: gloo-gateway LAST DEPLOYED: Thu Apr 18 11:50:39 2024 NAMESPACE: gloo-system STATUS: deployed REVISION: 2 TEST SUITE: NoneVerify that the Gloo Gateway control plane is up and running.
kubectl get pods -n gloo-system | grep glooExample output:
NAME READY STATUS RESTARTS AGE gloo-78658959cd-cz6jt 1/1 Running 0 12s
Enterprise edition
Set your Gloo Gateway license key as an environment variable. If you do not have one, contact an account representative.
export GLOO_GATEWAY_LICENSE_KEY=<license-key>Install the custom resources of the Kubernetes Gateway API.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yamlExample output:
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io createdAdd the Helm repository for Gloo Gateway Enterprise Edition.
helm repo add glooe https://storage.googleapis.com/gloo-ee-helm helm repo updateInstall Gloo Gateway. This command creates the
gloo-systemnamespace and installs the Gloo Gateway control plane into it. The following settings also enable Gloo Gateway to use an AWS IRSA and annotate the gateway proxy service account.helm install -n gloo-system gloo glooe/gloo-ee \ --create-namespace \ --version 1.20.3 \ --set-string license_key=$GLOO_GATEWAY_LICENSE_KEY \ -f -<<EOF gloo: gatewayProxies: gatewayProxy: disabled: true kubeGateway: enabled: true # Annotate the gateway proxy service account gatewayParameters: glooGateway: serviceAccount: extraAnnotations: eks.amazonaws.com/role-arn: arn:aws:iam::${ACCOUNT_ID}:role/gloo-lambda-role gloo: disableLeaderElection: true # Enable AWS account authentication with IRSA settings: aws: enableServiceAccountCredentials: true stsCredentialsRegion: ${AWS_LAMBDA_REGION} gloo-fed: enabled: false glooFedApiserver: enable: false grafana: defaultInstallationEnabled: false observability: enabled: false prometheus: enabled: false EOFExample output:
NAME: gloo-gateway LAST DEPLOYED: Thu Apr 18 11:50:39 2024 NAMESPACE: gloo-system STATUS: deployed REVISION: 2 TEST SUITE: NoneVerify that the Gloo Gateway control plane is up and running.
kubectl get pods -n gloo-systemExample output:
NAME READY STATUS RESTARTS AGE extauth-64458459c8-9q9kq 1/1 Running 0 26s gateway-certgen-qpv5q 0/1 Completed 0 31s gloo-68846f8459-nbzxp 1/1 Running 0 26s gloo-resource-rollout-check-xskxt 0/1 Completed 0 25s gloo-resource-rollout-n9kvf 0/1 Completed 0 26s rate-limit-5d8f859465-qhgsg 1/1 Running 0 26s redis-9f4f98445-5fh69 1/1 Running 0 26s
Create a gateway proxy and annotate its service account
Create an HTTP gateway, and verify that its service account is annotated.
Create a Gateway resource and configure an HTTP listener.
kubectl apply -n gloo-system -f- <<EOF kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: http spec: gatewayClassName: gloo-gateway listeners: - protocol: HTTP port: 8080 name: http allowedRoutes: namespaces: from: All EOFVerify that the gateway is created successfully. You can also review the external address that is assigned to the gateway. Note that depending on your environment it might take a few minutes for the load balancer service to be assigned an external address.
kubectl get gateway http -n gloo-systemExample output:
NAME CLASS ADDRESS PROGRAMMED AGE http gloo-gateway a3a6c06e2f4154185bf3f8af46abf22e-139567718.us-east-2.elb.amazonaws.com True 93sGet the external address of the gateway and save it in an environment variable.
Verify that the
gloo-proxy-httpservice account has theeks.amazonaws.com/role-arn: arn:aws:iam::${ACCOUNT_ID}:role/gloo-lambda-roleannotation.kubectl describe serviceaccount gloo-proxy-http -n gloo-system
Create a Lambda function for testing
Create an AWS Lambda function to test routing.
Log in to the AWS console and navigate to the Lambda page.
Click the Create Function button.
Name the function
echoand click Create function.Replace the default contents of
index.mjswith the following Node.js function, which returns a response body that contains exactly what was sent to the function in the request body.export const handler = async(event) => { const response = { statusCode: 200, body: `Response from AWS Lambda. Here's the request you just sent me: ${JSON.stringify(event)}` }; return response; };Click Deploy.
Set up routing to your function
Create Upstream and HTTPRoute resources to route requests to the Lambda function.
Create an Upstream resource that references the AWS region, IAM role, and
echofunction that you created. Note that you can specify multiple functions as a list in thespec.aws.lambdaFunctionsarray.kubectl apply -f - <<EOF apiVersion: gloo.solo.io/v1 kind: Upstream metadata: name: lambda namespace: gloo-system spec: aws: region: ${AWS_LAMBDA_REGION} roleArn: arn:aws:iam::${ACCOUNT_ID}:role/gloo-lambda-role lambdaFunctions: - lambdaFunctionName: echo logicalName: echo EOFCreate an HTTPRoute resource that references the
lambdaUpstream.- In the
rules.matchessection, specify a request matcher for your Lambda function, such as thePathPrefixmatch to/echoin the following example. - In the
backendRefs.filters.extensionRef.namefield, specify your Lambda function name. ThisextensionReftells Gloo Gateway which function in the Upstream to reference, because multiple functions can be listed in thespec.aws.lambdaFunctionsarray of the Upstream. To route to another function that you listed in the same Upstream, you can either add anotherruleentry in this same HTTPRoute that references the same Upstream with a differentextensionReffor the function name, or create a new HTTPRoute to define the routing rule.
You cannot currently attach aprefixRewritepolicy to a Lambda Upstream.kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: lambda namespace: gloo-system spec: parentRefs: - name: http namespace: gloo-system rules: - matches: - path: type: PathPrefix value: /echo backendRefs: - name: lambda namespace: gloo-system group: gloo.solo.io kind: Upstream filters: - type: ExtensionRef extensionRef: group: "gloo.solo.io" kind: Parameter name: echo EOF- In the
Confirm that Gloo Gateway correctly routes requests to Lambda by sending a curl request to the
echofunction. Note that the first request might take a few seconds to process, because the AWS Security Token Service (STS) credential request must be performed first. However, after the credentials are cached, subsequent requests are processed more quickly.Example response:
{"statusCode":200,"body":"Response from AWS Lambda. Here's the request you just sent me: {\"key1\":\"value1\",\"key2\":\"value2\"}"}%
At this point, Gloo Gateway is routing directly to the echo Lambda function using an IRSA!
Cleanup
You can optionally remove the resources that you set up as part of this guide.
Resources for the echo function
Delete the
lambdaHTTPRoute andlambdaUpstream.kubectl delete HTTPRoute lambda -n gloo-system kubectl delete Upstream lambda -n gloo-systemUse the AWS Lambda console to delete the
echotest function.
IRSA authorization (optional)
If you no longer need to access Lambda functions from Gloo Gateway:
Upgrade your Gloo Gateway Helm installation to remove the added settings and annotation.
- Get the Helm values for your current installation, and save them in a file.
helm get values gloo -n gloo-system -o yaml > gloo-gateway.yaml open gloo-gateway.yaml - Delete the following settings, and save the file. For Enterprise edition, these settings are in the
gloosection.kubeGateway.gatewayParameters.glooGateway.serviceAccount.extraAnnotationssettings.aws.enableServiceAccountCredentialssettings.aws.stsCredentialsRegion
- Upgrade the Helm release. Replace the example Gloo Gateway version with the version that you run.
- Open source:
helm upgrade -n gloo-system gloo gloo/gloo \ -f gloo-gateway.yaml \ --version=1.20.3 - Enterprise edition:
helm upgrade -n gloo-system gloo glooe/gloo-ee \ -f gloo-gateway.yaml \ --version=1.20.3
- Open source:
- Get the Helm values for your current installation, and save them in a file.
Delete the pod identity webhook.
kubectl delete deploy pod-identity-webhookRemove cert-manager.
kubectl delete -f cert-manager.yaml -n cert-manager kubectl delete ns cert-managerDelete the AWS IAM resources that you created.
aws iam detach-role-policy --role-name gloo-lambda-role --policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/gloo-lambda-policy aws iam delete-role --role-name gloo-lambda-role aws iam delete-policy --policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/gloo-lambda-policy