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 Upstream and HTTPRoute resources

Before you begin

Before you begin, review the following considerations:

Configure AWS IAM resources

Save your AWS details, and create an IRSA for the gateway proxy pod to use.

  1. 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>
      
  2. 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.
  3. 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.json 
      
  4. Use 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.

    1. Create the following IAM role. Note that the service account name gloo-proxy-http in the gloo-system namespace is specified, because in later steps you create an HTTP gateway named http.
        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
        
    2. 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
        
    3. Verify that the policy is attached to the role.
        aws iam list-attached-role-policies --role-name gloo-lambda-role
        
      Example output:
        {
          "AttachedPolicies": [
              {
                  "PolicyName": "gloo-lambda-policy",
                  "PolicyArn": "arn:aws:iam::111122223333:policy/gloo-lambda-policy"
              }
          ]
      }
        

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.

  1. 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.yaml
      
  2. Verify that all cert-manager pods are running.

      kubectl get pods -n cert-manager
      
  3. Deploy 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.yaml
      
  4. Verify 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

  1. Install the custom resources of the Kubernetes Gateway API.

      kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
      

    Example 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 created
      
  2. Add the Helm repository for Gloo Gateway Open Source.

      helm repo add gloo https://storage.googleapis.com/solo-public-helm
    helm repo update
      
  3. Install Gloo Gateway. This command creates the gloo-system namespace and installs the Gloo Gateway control plane into it. The following settings also enable Gloo Gateway to use an AWS IRSA and annotate the gloo-proxy-http service account.

      helm install -n gloo-system gloo gloo/gloo \
    --create-namespace \
    --version 1.19.0-beta2 \
    -f -<<EOF
    discovery:
      enabled: false
    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}
    EOF
      

    Example output:

      NAME: gloo-gateway
    LAST DEPLOYED: Thu Apr 18 11:50:39 2024
    NAMESPACE: gloo-system
    STATUS: deployed
    REVISION: 2
    TEST SUITE: None
      
  4. Verify that the Gloo Gateway control plane is up and running.

      kubectl get pods -n gloo-system | grep gloo
      

    Example output:

      NAME                                  READY   STATUS    RESTARTS   AGE
    gloo-78658959cd-cz6jt                 1/1     Running   0          12s
      

Enterprise edition

  1. 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>
      
  2. Install the custom resources of the Kubernetes Gateway API.

      kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
      

    Example 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 created
      
  3. Add the Helm repository for Gloo Gateway Enterprise Edition.

      helm repo add glooe https://storage.googleapis.com/gloo-ee-helm
    helm repo update
      
  4. Install Gloo Gateway. This command creates the gloo-system namespace 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.18.1 \
    --set-string license_key=$GLOO_GATEWAY_LICENSE_KEY \
    -f -<<EOF
    gloo:
      discovery:
        enabled: false
      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
    EOF
      

    Example output:

      NAME: gloo-gateway
    LAST DEPLOYED: Thu Apr 18 11:50:39 2024
    NAMESPACE: gloo-system
    STATUS: deployed
    REVISION: 2
    TEST SUITE: None
      
  5. Verify that the Gloo Gateway control plane is up and running.

      kubectl get pods -n gloo-system
      

    Example 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.

  1. 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
    EOF
      
  2. Verify 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-system
      

    Example output:

      NAME   CLASS          ADDRESS                                                                  PROGRAMMED   AGE
    http   gloo-gateway   a3a6c06e2f4154185bf3f8af46abf22e-139567718.us-east-2.elb.amazonaws.com   True         93s
      
  3. Get the external address of the gateway and save it in an environment variable.

  4. Verify that the gloo-proxy-http service account has the eks.amazonaws.com/role-arn: arn:aws:iam::${ACCOUNT_ID}:role/gloo-lambda-role annotation.

      kubectl describe serviceaccount gloo-proxy-http -n gloo-system
      

Create a Lambda function for testing

Create an AWS Lambda function to test routing.

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

  2. Click the Create Function button.

  3. Name the function echo 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

Create Upstream and HTTPRoute resources to route requests to the Lambda function.

  1. Create an Upstream resource that references the AWS region, IAM role, and echo function that you created.

      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
    EOF
      
  2. Create an HTTPRoute resource that references the 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
      
  3. Confirm that Gloo Gateway correctly routes requests to Lambda by sending a curl request to the echo function. 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

  1. Delete the lambda HTTPRoute and lambda Upstream.

      kubectl delete HTTPRoute lambda -n gloo-system
    kubectl delete Upstream lambda -n gloo-system
      
  2. Use the AWS Lambda console to delete the echo test function.

IRSA authorization (optional)

If you no longer need to access Lambda functions from Gloo Gateway:

  1. Upgrade your Gloo Gateway Helm installation to remove the added settings and annotation.

    1. 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
        
    2. Delete the following settings, and save the file. For Enterprise edition, these settings are in the gloo section.
      • kubeGateway.gatewayParameters.glooGateway.serviceAccount.extraAnnotations
      • settings.aws.enableServiceAccountCredentials
      • settings.aws.stsCredentialsRegion
    3. 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.19.0-beta2
          
      • Enterprise edition:
          helm upgrade -n gloo-system gloo glooe/gloo-ee \
          -f gloo-gateway.yaml \
          --version=1.18.1
          
  2. Delete the pod identity webhook.

      kubectl delete deploy pod-identity-webhook
      
  3. Remove cert-manager.

      kubectl delete -f cert-manager.yaml -n cert-manager
    kubectl delete ns cert-manager
      
  4. Delete 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