Configure AWS IAM permissions

Create IAM roles for Gloo Gateway service accounts to access, discover, and invoke Lambda functions.

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 IRSAs. For more information, see the AWS documentation.

Note that if you completed the Get started guide, your AWS IAM permissions are already set up. You can proceed to providing AWS account and Lambda details in a CloudProvider resource.

Before you begin

  1. Install Gloo Gateway. Note that certain Lambda integration features, such as unwrapping Lambda responses in the same way as an AWS API Gateway, require ingress gateway proxies to run Istio 1.15.1 or later.

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

Step 1: Save your AWS account details

Save your AWS account details to use in IAM resources in subsequent steps.

  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. Associate an IAM OIDC provider to the EKS cluster that you plan to use for Gloo 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:\/\///")
    

Step 2: Allow the management server to discover Lambda functions

Create an IRSA for the Gloo Gateway management server pods to assume to discover Lambda functions in your AWS account.

  1. Create an IAM policy to allow access to the following Lambda actions.

    cat >policy.json <<EOF
    {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "lambda:ListFunctions",
                   "lambda:GetFunction",
               ],
               "Resource": "*"
           }
       ]
    }
    EOF
    
    aws iam create-policy --policy-name gloo-lambda-discover --policy-document file://policy.json 
    
  2. Create the following IAM role that contains your AWS account details and management server service account name.

    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}:aud": "${STS_ENDPOINT}",
              "${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
    
  3. Use the IAM role to associate the policy with the Kubernetes service account for the Gloo management server. This IAM role for the service account is known as an IRSA. The management server assumes this role to discover Lambda functions. For more information, see the AWS documentation.

    aws iam attach-role-policy --role-name gloo-lambda-mgmt-discover --policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/gloo-lambda-discover
    
  4. 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-discover",
                "PolicyArn": "arn:aws:iam::111122223333:policy/gloo-lambda-discover"
            }
        ]
    }
    
  5. Annotate the management server service account with the ARN of its IAM role. In the following Helm upgrade command, make sure to include the same Helm values that you specifed when you installed Gloo Gateway, either as a configuration file in the --values flag or with --set flags. Otherwise, any previous custom values that you set might be overwritten, which might mean that your Gloo agent and gateway proxies are removed. Additionally, note that your release might be named gloo-mesh-enterprise instead of gloo-mgmt. For more information, see Get your Helm chart values.

    helm upgrade --install gloo-platform gloo-platform/gloo-platform \
    --namespace gloo-mesh \
    --version $GLOO_VERSION \
    --values gloo-gateway-single.yaml \
    --set common.cluster=$CLUSTER_NAME \
    --set licensing.glooGatewayLicenseKey=$GLOO_GATEWAY_LICENSE_KEY \
    --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
    ...
    

Step 3: Allow the gateway proxy to invoke Lambda functions

Create an IRSA for the Gloo ingress gateway pods to assume to invoke Lambda functions in your AWS account.

  1. Create an IAM policy to allow access to the following Lambda actions.

    cat >policy.json <<EOF
    {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "lambda:InvokeFunction",
                   "lambda:InvokeAsync"
               ],
               "Resource": "*"
           }
       ]
    }
    EOF
    
    aws iam create-policy --policy-name gloo-lambda-invoke --policy-document file://policy.json
    
  2. 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 gloo-mesh-gateways
    

    In this example output, istio-ingressgateway-1-20-service-account is the name of the ingress gateway service account:

    NAME                                        SECRETS   AGE
    default                                     1         45m
    istio-ingressgateway-1-20-service-account   1         45m
    
  3. Create the following IAM role that contains your AWS account details and service account name. 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": {
            "Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
          },
          "Action": "sts:AssumeRoleWithWebIdentity",
          "Condition": {
            "StringEquals": {
              "${OIDC_PROVIDER}:aud": "${STS_ENDPOINT}",
              "${OIDC_PROVIDER}:sub": "system:serviceaccount:gloo-mesh-gateways:istio-ingressgateway-1-20-service-account"
            }
          }
        }
      ]
    }
    EOF
       
    aws iam create-role --role-name gloo-lambda-gateway-invoke --assume-role-policy-document file://invoke-role.json
    
  4. Use the IAM role to associate the IAM policy with the service account for the ingress gateway. This IAM role for the service account is known as an IRSA. The gateway assumes this role to invoke Lambda functions. For more information, see the AWS documentation.

    aws iam attach-role-policy --role-name gloo-lambda-gateway-invoke --policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/gloo-lambda-invoke
    
  5. 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-invoke",
                "PolicyArn": "arn:aws:iam::111122223333:policy/gloo-lambda-invoke"
            }
        ]
    }
    
  6. Annotate the ingress gateway service account with the ARN of its IAM role. These steps differ depending on whether you installed the ingress gateway with the istioInstallations Helm chart setting, created a GatewayLifecycleManager custom resource, or manually deployed an unmanaged ingress gateway with an Istio Helm chart.

    If you installed managed gateway proxies by using the istioInstallations Helm chart setting:

    1. Perform a canary upgrade of your gateway proxy. When you update your values file to add a canary entry to the istioInstallations.northSouthGateways.installations list, include the following following section. 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.
      istioInstallations:
        ...
        northSouthGateways:
          - enabled: true
            name: istio-ingressgateway
            installations:
              # Installation entry for the canary revision
              - gatewayRevision: $REVISION
                clusters:
                  - name: $CLUSTER_NAME
                    activeGateway: false
                istioOperatorSpec:
                  profile: empty
                  hub: $REPO
                  tag: $ISTIO_IMAGE
                  namespace: gloo-mesh-gateways
                  # NEW SECTION
                  k8s: 
                    overlays:
                      - apiVersion: v1
                        kind: ServiceAccount
                        name: istio-ingressgateway-1-20-service-account
                        patches:
                          - path: metadata.annotations.eks\.amazonaws\.com/role-arn
                            value:
                              arn:aws:iam::$ACCOUNT_ID:role/gloo-lambda-gateway-invoke
      
    2. When you follow the other steps in the upgrade guide, be sure to also include the annotation that you set for the management server in prior steps, so that the value is not overwritten.
      helm upgrade --install gloo-platform gloo-platform/gloo-platform \
      --namespace gloo-mesh \
      --version $GLOO_VERSION \
      --values gloo-gateway-single.yaml \
      --set common.cluster=$CLUSTER_NAME \
      --set licensing.glooGatewayLicenseKey=$GLOO_GATEWAY_LICENSE_KEY \
      --set glooMgmtServer.serviceAccount.extraAnnotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::$ACCOUNT_ID:role/gloo-lambda-mgmt-discover
      

    If you installed managed gateway proxies by creating a GatewayLifecycleManager CR, perform a canary upgrade to annotate the ingress gateway service account. For more information about these steps, see Performing a canary upgrade.

    1. Edit the GatewayLifecycleManager resource for the gateway that you deployed to add another installation entry for the canary revision. For the canary revision, be sure to set defaultRevision to false so that only the existing revision continues to run.
      kubectl edit GatewayLifecycleManager istio-ingressgateway -n gloo-mesh
      

      For example, you might add the following $REVISION-lambda canary revision as a new entry in the installations section. 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.

      apiVersion: admin.gloo.solo.io/v2
      kind: GatewayLifecycleManager
      metadata:
        name: istio-ingressgateway
        namespace: gloo-mesh
      spec:
        installations:
          # Existing revision
          - gatewayRevision: $REVISION
            clusters:
            - name: $CLUSTER_NAME
              # Keep this field set to TRUE so that only the existing revision continues to run
              activeGateway: true
            istioOperatorSpec:
              profile: empty
              ...
          # Canary revision
          - gatewayRevision: $REVISION-lambda
            clusters:
            - name: $CLUSTER_NAME
              # Set this field to FALSE so that only the existing revision continues to run
              activeGateway: false
            istioOperatorSpec:
              profile: empty
              hub: $REPO
              tag: $ISTIO_IMAGE
              components:
                ingressGateways:
                  - name: istio-ingressgateway
                    namespace: gloo-mesh-gateways
                    enabled: true
                    label:
                      istio: ingressgateway
                      app: istio-ingressgateway
                    k8s:
                      service:
                        type: LoadBalancer
                        selector:
                          istio: ingressgateway
                        ports:
                          - name: status-port
                            port: 15021
                            targetPort: 15021
                          - port: 80
                            targetPort: 8080
                            name: http2
                          - port: 443
                            targetPort: 8443
                            name: https
                      overlays:
                        - apiVersion: v1
                          kind: ServiceAccount
                          # Change the name of the ingress gateway service account as needed
                          name: istio-ingressgateway-1-20-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
      
    2. Verify that the ingress gateway for the canary installation is created.
      kubectl get all -n gloo-mesh-gateways
      
    3. Switch to the new gateway by changing activeGateway to false for the old revision and to true for the new revision.
      kubectl edit GatewayLifecycleManager istio-ingressgateway -n gloo-mesh
      

      Example:

      apiVersion: admin.gloo.solo.io/v2
      kind: GatewayLifecycleManager
      metadata:
        name: istio-ingressgateway
        namespace: gloo-mesh
      spec:
        installations:
          # Old revision
          - gatewayRevision: $REVISION
            clusters:
            - name: $CLUSTER_NAME
              # Set this field to FALSE
              activeGateway: false
            istioOperatorSpec:
              profile: empty
              ...
          # New revision
          - gatewayRevision: $REVISION-lambda
            clusters:
            - name: $CLUSTER_NAME
              # Set this field to TRUE
              activeGateway: true
            istioOperatorSpec:
              profile: empty
              ...
      
    4. Verify that the active gateways for the new revision are created, which do not have the revision appended to the name. Note that gateways for the inactive revision that you previously ran also exist in the namespace, in the case that a rollback is required.
      kubectl get all -n gloo-mesh-gateways
      
    5. To uninstall the previous installation, you can edit the GatewayLifecycleManager resource to remove the old revision's entry from the installations list.
      kubectl edit GatewayLifecycleManager istio-ingressgateway -n gloo-mesh
      

    If you manually deployed unmanaged Istio ingress gateways, patch the deployment with the anotated 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-1-20-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} \
        --create-namespace \
        --namespace gloo-mesh-gateways \
        --post-renderer ./kustomize.sh \
        --wait \
        -f ingress-gateway-values.yaml
      

  7. Verify that the service account is annotated with the IRSA.

    kubectl describe serviceaccount istio-ingressgateway-1-20-service-account -n gloo-mesh-gateways
    

    Example output:

    Name:                istio-ingressgateway-1-20-service-account
    Namespace:           gloo-mesh-gateways
    Labels:              app=istio-ingressgateway
                         install.operator.istio.io/owning-resource=istio-ingressgateway-1-20
                         install.operator.istio.io/owning-resource-namespace=gm-iop-1-20
                         istio=ingressgateway
                         istio.io/rev=1-20
                         operator.istio.io/component=IngressGateways
                         operator.istio.io/managed=Reconcile
                         operator.istio.io/version=1.20.2-solo
                         release=istio
                         revision=1-20
    Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::931713665590:role/gloo-lambda-gateway-invoke
    Image pull secrets:  <none>
    Mountable secrets:   istio-ingressgateway-1-20-service-account-token-rwvq8
    Tokens:              istio-ingressgateway-1-20-service-account-token-rwvq8
    Events:              <none>
    

Step 4: Decide how workloads can invoke functions

On the next page, you provide the details of your AWS account and Lambda functions to Gloo Gateway in a CloudProvider CR. When you create the CloudProvider, you choose how workloads in a workspace can invoke the Lambda functions in an AWS account.

Workloads can invoke functions in the following ways:

Default IRSA

If you want workloads to use the same IRSA that the gateway service account assumes, no further IAM resources are needed. When you create your CloudProvider, you specify that IRSA role name in the lambda.invokeRoleName field. For example, in this guide, the IRSA is named gloo-lambda-gateway-invoke.

Specific override IAM role

If you want workloads to use a specific IAM role that is different from the IRSA on the gateway deployment, create that IAM role, and specify that role name in the lambda.invokeRoleName field of your CloudProvider. For example, if you want a team's workloads to only access a certain subset of all the Lambda functions that Gloo Gateway can invoke, you might specify an IAM role that grants permission to only that subset. For more information about separating access by teams, see Use CloudProvider CRs for multitenancy.

Resource-based invocation policy

If you do not want workloads to assume an IAM role at all, you can instead set up a resource-based invocation policy for a Lambda function for the workload pod to use. This setup is especially useful for cross-account function invocation, because the resource-based policy can give other accounts the permission to invoke the function, without requiring the other account to assume a role. Note that through the IRSA of the ingress gateway, the workload still has an identity in the account that the Lambda function is in. However, the workload does not assume this role for invocation.

Invoking Lambda functions by using a resource-based policy is supported only for ingress gateways that run a Solo distribution of Istio at version 1.17.3 and later.

  1. Get the ARN or name of the Lambda function that you want to invoke (in “account A”), and ID of the account where you want to invoke from (“account B”).

  2. For the Lambda function in account A, create a resource-based policy statement so that any identity in account B can invoke the function. In the following example, replace <account-A-lambda-arn> with the Lambda function's ARN or name, and <account-B-id> with the second account's ID.

    aws lambda add-permission \
    --statement-id test-cross-account \
    --action lambda:InvokeFunction \
    --output text \
    --function-name <account-A-lambda-name-or-arn> \
    --principal <account-B-id>
    
  3. When you create your CloudProvider in the workspace for account B, do not specify the lambda.invokeRoleName field. The workloads in the account B workspace can use the resource-based policy permisson to invoke the Lambda function in account A.

For more information about separating access by teams, see Use CloudProvider CRs for multitenancy.

Next steps