Skip to content

Get started

Page as Markdown

Invoke AWS Lambda functions from your Gloo Mesh Gateway cluster by using an IAM role for a service account (IRSA).

Overview

Amazon Web Services (AWS) offers the ability to associate an IAM role with a Kubernetes service account, also known as creating an IRSA. Gloo Mesh Gateway supports discovering and invoking AWS Lambda functions by using an IRSA. For more information, see the AWS documentation.

In this getting started tutorial, 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 Gloo Mesh Gateway service accounts (an IRSA)
  • Create a Lambda function for testing

Gloo resources:

  • Annotate Gloo Mesh Gateway service accounts with the IRSA
    • Provide AWS account and Lambda details in CloudProvider and CloudResources custom resources (CRs)
    • Set up routing to your function by creating a RouteTable CR

    After you create these resources, requests to your Lambda function follow this network traffic flow:

    Figure: Gloo custom resources for AWS Lambda details
    Figure: Gloo custom resources for AWS Lambda details
    1. A client makes a request to the host and path that you set up for the function, such as https://www.example.com/test-lambda.
    2. Gloo Mesh Gateway receives the request for the host as specified in the route table, and matches the host to a particular AWS account and Lambda function as specified in the cloud provider and cloud resource. Using these details, Gloo Mesh Gateway assumes an IAM role to invoke the function.
    3. The Lambda function in your AWS account receives the request, and returns a response to Gloo Mesh Gateway.
    4. Gloo Mesh Gateway applies any transformations that you configured (such as AWS response transformations) to the response, and returns it to the client.

    Before you begin

    1. Install Gloo Mesh Gateway. Your ingress gateway proxies must run a Solo distribution of Istio, and note that certain Lambda integration features, such as unwrapping Lambda responses in the same way as an AWS API Gateway, require Istio version 1.15.1 or later.

      • Install quickly with meshctl.
      • Customize your installation with Helm.
    2. Configure an HTTPS listener on your ingress gateway.

    Configure AWS IAM resources

    Save your AWS details, and create an IRSA for the Gloo Mesh Gateway deployment pods to use.

    1. Save the details of the AWS region and account that your Lambda functions are in.

      export AWS_REGION=<region>
      export ACCOUNT_ID=<account_id>
    2. Save the AWS Security Token Service (AWS STS) endpoint to use when retrieving the necessary AWS credentials for accessing Lambda functions. Note that STS endpoints are unique to a particular listener port on a workload. For more information about STS endpoints, see the AWS documentation.

      • Global STS endpoint (default):
        export STS_ENDPOINT=sts.amazonaws.com
      • Regional STS endpoints:
        export STS_ENDPOINT=sts.$AWS_REGION.com
    3. Create an IAM OIDC provider for your EKS cluster that you plan to use for Gloo Mesh Gateway.

    4. Save your cluster’s OIDC identity provider in an environment variable.

      export OIDC_PROVIDER=$(aws eks describe-cluster --name $CLUSTER_NAME --region $AWS_REGION --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
    5. Create an IAM policy to allow access to the following four Lambda actions. Note: In this getting started guide, the permissions to discover and invoke functions are listed in the same policy, and this policy is used by both the Gloo Mesh Gateway management server for discovery and the gateway proxy for invocation. 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.json 
    6. Use an IAM role to associate the policy with the Kubernetes service account for the Gloo management server. The management server assumes this role to discover Lambda functions. For more information about these steps, see the AWS documentation.

      1. Create the following IAM role.
        cat >discover-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-mesh:gloo-mesh-mgmt-server"
                }
              }
            }
          ]
        }
        EOF
        
        aws iam create-role --role-name gloo-lambda-mgmt-discover --assume-role-policy-document file://discover-role.json
      2. Use the IAM role to associate the IAM policy with the service account. This IAM role for the service account is known as an IRSA.
        aws iam attach-role-policy --role-name gloo-lambda-mgmt-discover --policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/gloo-lambda-policy
      3. Verify that the policy is attached to the role.
        aws iam list-attached-role-policies --role-name gloo-lambda-mgmt-discover
        Example output:
        {
            "AttachedPolicies": [
                {
                    "PolicyName": "gloo-lambda-policy",
                    "PolicyArn": "arn:aws:iam::111122223333:policy/gloo-lambda-policy"
                }
            ]
        }
      4. Get the current Helm values for your Gloo installation.
        helm get values gloo-platform -n gloo-mesh -o yaml > gloo-gateway-single.yaml
      5. Annotate the management server service account with the ARN of its IAM role.
        helm upgrade --install gloo-platform gloo-platform/gloo-platform \
        --namespace gloo-mesh \
        --version $GLOO_VERSION \
        --values gloo-gateway-single.yaml \
        --set glooMgmtServer.serviceAccount.extraAnnotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::$ACCOUNT_ID:role/gloo-lambda-mgmt-discover
      6. Verify that the service account is annotated with the IRSA.
        kubectl describe serviceaccount gloo-mesh-mgmt-server -n gloo-mesh
        Example output:
        Name:                gloo-mesh-mgmt-server
        Namespace:           gloo-mesh
        Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/gloo-lambda-mgmt-discover
        Image pull secrets:  <none>
        Mountable secrets:   gloo-mesh-mgmt-server-token-qqjfl
        Tokens:              gloo-mesh-mgmt-server-token-qqjfl
        ...
    7. Use an IAM role to associate the policy with the Kubernetes service account for the ingress gateway. The gateway assumes this role to invoke Lambda functions. For more information about these steps, see the AWS documentation.

      1. Find the name of the service account for the ingress gateway. The service account might exist in another namespace, depending on where you deployed your gateway proxy.
        kubectl get serviceaccount -n istio-ingress
        In this example output, istio-ingressgateway-main-service-account is the name of the ingress gateway service account:
        NAME                                        SECRETS   AGE
        default                                     1         45m
        istio-ingressgateway-main-service-account   1         45m
      2. Create the following IAM role. Change the namespace and name of the ingress gateway service account as needed.
        cat >invoke-role.json <<EOF
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": "ec2.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
            },
            {
              "Effect": "Allow",
              "Principal": {
                "Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
              },
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "${OIDC_PROVIDER}:sub": "system:serviceaccount:istio-ingress:istio-ingressgateway-main-service-account"
                }
              }
            }
          ]
        }
        EOF
        
        aws iam create-role --role-name gloo-lambda-gateway-invoke --assume-role-policy-document file://invoke-role.json
      3. Use the IAM role to associate the IAM policy with the service account. This IAM role for the service account is known as an IRSA.
        aws iam attach-role-policy --role-name gloo-lambda-gateway-invoke --policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/gloo-lambda-policy
      4. Verify that the policy is attached to the role.
        aws iam list-attached-role-policies --role-name gloo-lambda-gateway-invoke
        Example output:
        {
            "AttachedPolicies": [
                {
                    "PolicyName": "gloo-lambda-policy",
                    "PolicyArn": "arn:aws:iam::111122223333:policy/gloo-lambda-policy"
                }
            ]
        }
      5. Annotate the ingress gateway service account with the ARN of its IAM role. These steps differ depending on whether you used the Gloo gateway lifecycle manager to install your gateways, or manually deployed an unmanaged ingress gateway with an Istio Helm chart.

        If you manually deployed unmanaged Istio ingress gateways, patch the deployment with the annotated service account.

        These steps use the post rendering feature supported in Helm 3.1 and later, along with Kustomize. These features patch the rendered manifest of the istio-ingressgateway deployment before it is applied to the cluster without the need to modify the Helm chart itself, because deployment patches cannot be added to the istio-ingressgateway Helm chart directly.

        1. Save the following patch, which updates the ingress gateway deployment with the annotated service account before the deployment is applied to the cluster.

          cat > sa-patch.yaml <<EOF
          apiVersion: v1
          kind: ServiceAccount
          metadata:
            # Change the name of the ingress gateway service account as needed
            name: istio-ingressgateway-main-service-account
            annotations:
              eks.amazonaws.com/role-arn: "arn:aws:iam::$ACCOUNT_ID:role/gloo-lambda-gateway-invoke"
          EOF
        2. To use Kustomize files with Helm rendering, which requires stdin/stdout, create a shell script named kustomize.sh.

          cat > kustomize.sh <<EOF
          #!/bin/sh
          cat > base.yaml
          exec kubectl kustomize
          EOF
          chmod +x ./kustomize.sh
        3. Create the kustomization.yaml file, which provides the patch input for Kustomize.

          cat > kustomization.yaml <<EOF
          resources:
          - base.yaml
          patchesStrategicMerge:
          - sa-patch.yaml
          EOF
        4. Follow the guide to upgrade the ingress gateway. When you run the helm upgrade command for the ingress gateway, be sure to include the --post-renderer ./kustomize.sh flag, such as the following:

          helm upgrade --install istio-ingressgateway-${REVISION} istio/gateway \
            --version ${ISTIO_IMAGE} \
            --namespace istio-ingress \
            --post-renderer ./kustomize.sh \
            --wait \
            -f ingress-gateway-values.yaml

        Version 2.11 and earlier only: If you use Gloo-managed gateway proxies, follow the steps in the Istio lifecycle manager upgrade guide. In the istioOperatorSpec.components.ingressGateways.k8s section, add the following overlay to annotate the service account. Replace $ACCOUNT_ID with your actual account ID, and update the name of the ingress gateway service account as needed. Note that the other environment variables are provided as example placeholders for the actual values in your file.

        ...
        istioOperatorSpec:
          profile: empty
          hub: $REPO
          tag: $ISTIO_IMAGE
          components:
            ingressGateways:
            - name: istio-ingressgateway
              namespace: istio-ingress
              enabled: true
              label:
                istio: ingressgateway
                app: istio-ingressgateway
              k8s:
                overlays:
                  - apiVersion: v1
                    kind: ServiceAccount
                    # Change the name of the ingress gateway service account as needed
                    name: istio-ingressgateway-main-service-account
                    patches:
                      - path: metadata.annotations.eks\.amazonaws\.com/role-arn
                        value:
                          # Replace with your own account ID
                          arn:aws:iam::$ACCOUNT_ID:role/gloo-lambda-gateway-invoke
      6. Verify that the service account is annotated with the IRSA.
        kubectl describe serviceaccount istio-ingressgateway-main-service-account -n istio-ingress
        Example output:
        Name:                istio-ingressgateway-main-service-account
        Namespace:           istio-ingress
        Labels:              app=istio-ingressgateway
                             install.operator.istio.io/owning-resource=istio-ingressgateway-main
                             install.operator.istio.io/owning-resource-namespace=gm-iop-main
                             istio=ingressgateway
                             istio.io/rev=main
                             operator.istio.io/component=IngressGateways
                             operator.istio.io/managed=Reconcile
                             operator.istio.io/version=1.29.1-solo
                             release=istio
                             revision=main
        Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::931713665590:role/gloo-lambda-gateway-invoke
        Image pull secrets:  <none>
        Mountable secrets:   istio-ingressgateway-main-service-account-token-rwvq8
        Tokens:              istio-ingressgateway-main-service-account-token-rwvq8
        Events:              <none>

    Create a Lambda function for testing

    Create an AWS Lambda function to test Gloo Mesh Gateway routing.

    1. Log in to the AWS console and navigate to the Lambda page.

    2. Click the Create Function button.

    3. Name the function test-lambda and click Create function.

    4. Replace the default contents of index.mjs with 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;
      };
    5. Click Deploy.

    Set up routing to your function

    To invoke the function from Gloo Mesh Gateway, provide your AWS account and Lambda details in the CloudProvider and CloudResources resources. Then, set up routing to your function by creating a RouteTable.

    • CloudProvider: Define your AWS details and IAM roles in a CloudProvider CR. The CloudProvider CR serves as a centralized location for configuration settings for each cloud provider and the resources you want to use, such as AWS and AWS Lambda. You can also choose whether Gloo Mesh Gateway can automatically discover the Lambda functions in your account and region, or whether you want to manually list functions in a CloudResources resource.
    • CloudResources: Details about the functions that Gloo Mesh Gateway can access are listed in the CloudResources CR. If you enable automatic discovery of functions, Gloo creates a CloudResources configuration that contains entries for each Lambda that it discovers. If you do not enable discovery, you can manually specify the functions that Gloo Mesh Gateway can access in a CloudResources CR. Each item in the list contains an internal function name to route requests to, the actual name of the Lambda in AWS, and the version of the function to call.
    • RouteTable: Create a RouteTable CR to define a hostname and a specific path that your Lambda is available through. The route table ensures that Gloo Mesh Gateway directs all requests on the hostname and path to your function, and uses the correct IAM roles from your CloudProvider resource to invoke the function.

    Figure: Gloo custom resources for AWS Lambda details
    Figure: Gloo custom resources for AWS Lambda details

    1. Define your AWS details and IAM roles in a CloudProvider resource. The configuration steps vary depending on whether you want Gloo Mesh Gateway to automatically discover the Lambda functions in your account and region, or you want to manually list functions in a CloudResources resource.

      1. Define your AWS details in a CloudProvider resource. These settings enable automatic discovery of functions in your account and region, but filters the functions for the name test-lambda.
        kubectl apply -f - <<EOF
        apiVersion: infrastructure.gloo.solo.io/v2
        kind: CloudProvider
        metadata:
          name: aws-provider
          namespace: gloo-mesh
        spec:
          aws:
            accountId: "$ACCOUNT_ID"
            region: $AWS_REGION
            stsEndpoint: $STS_ENDPOINT
            lambda:
              discovery:
                enabled: true
                filter:
                  names: test-lambda
                  latestOnly: true
              invokeRoleName: gloo-lambda-gateway-invoke
        EOF
      2. Verify that Gloo Mesh Gateway discovered the test-lambda function. Gloo automatically creates a CloudResources configuration that contains entries for each Lambda that it discovers.
        kubectl get CloudResources -n gloo-mesh
      1. Define your AWS details in a CloudProvider resource.
        kubectl apply -f - <<EOF
        apiVersion: infrastructure.gloo.solo.io/v2
        kind: CloudProvider
        metadata:
          name: aws-provider
          namespace: gloo-mesh
        spec:
          aws:
            accountId: "$ACCOUNT_ID"
            region: $AWS_REGION
            stsEndpoint: $STS_ENDPOINT
            lambda:
              invokeRoleName: gloo-lambda-gateway-invoke
        EOF
      2. Specify the test Lambda that you created in a CloudResources resource.
        kubectl apply -f - <<EOF
        apiVersion: infrastructure.gloo.solo.io/v2
        kind: CloudResources
        metadata:
          name: aws-functions
          namespace: gloo-mesh
        spec:
          # Name of the CloudProvider resource
          provider: aws-provider
          aws: 
            lambda:
                # Actual name of the function in AWS
              - lambdaFunctionName: test-lambda
                # Version of the function to call
                qualifier: $LATEST
        EOF

    2. Create a RouteTable resource to direct all requests on the /test-lambda path to your Lambda function. Update the example values with your own details as needed, such as the virtualGateways reference details.

      kubectl apply -f - <<EOF
      apiVersion: networking.gloo.solo.io/v2
      kind: RouteTable
      metadata:
        name: test-lambda-route
        namespace: gloo-mesh
      spec:
        # Applies to any host; can indicate a specific domain, like example.com
        hosts:
          - '*'
        # Selects a virtual gateway you previously created.
        # Change name and namespace as needed.
        virtualGateways:
          - name: istio-ingressgateway
            namespace: bookinfo
        http:
          - name: test-lambda-route
            labels:
              route: lambda
            matchers:
            - uri:
                prefix: /test-lambda
            forwardTo:
              destinations:
                # Reference to the function in the CloudProvider resource
                - awsLambda:
                    cloudProvider:
                      name: aws-provider
                      namespace: gloo-mesh
                      cluster: $CLUSTER_NAME
                    function: test-lambda
      EOF
    3. Get the hostname of your ingress gateway to test the /test-lambda route.

      export INGRESS_GW_ADDRESS=$(kubectl get svc -n istio-ingress istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
      echo $INGRESS_GW_ADDRESS
    4. Send a request to the Lambda endpoint to verify that the request is successfully resolved by the gateway.

      curl -vik https://${INGRESS_GW_ADDRESS}:443/test-lambda -H "host: www.example.com:443"

      Example output:

      Response from AWS Lambda. Here's the request you just sent me: {"headers":{":authority":"www.example.com",":method":"GET",":path":"/test-lambda",":scheme":"http","accept":"*/*","user-agent":"curl/7.79.1","x-envoy-decorator-operation":"dummy-route.blackhole.solo.unused:8080/test-lambda*","x-envoy-internal":"true","x-envoy-peer-metadata":"ChQKDk<...>","x-envoy-peer-metadata-id":"router~192.168.47.140~istio-ingressgateway-main-68bdd78cc4-zqjx7.istio-ingress~istio-ingress.svc.cluster.local","x-forwarded-for":"192.168.90.112","x-forwarded-proto":"http","x-request-id":"40e70781-3da4-4cf1-8fd2-47b84858fffb"},"httpMethod":"GET","path":"/test-lambda","queryString":""}% 

      Note: Gloo Mesh Gateway uses a dummy route for the connection between Gloo Mesh Gateway and AWS Lambda, such as dummy-route.blackhole.solo.unused:8080/test-lambda* in this example output. This route indicates that the connection is functioning as intended.

    Next steps

    Now that you’ve set up Gloo Mesh Gateway to invoke Lambda functions, check out the following pages to configure your own functions for Gloo Mesh Gateway invocation.