IAM Conditions for forwarding rules

Identity and Access Management (IAM) Conditions let you define IAM policies with conditional grants. You specify conditions in the role bindings of a resource's IAM policy. If a condition exists, the role is granted only when the condition expression evaluates to true. Each condition expression is a set of logic statements, allowing you to specify one or many attributes. For more information, see the Attribute reference for IAM Conditions.

When used with Cloud Load Balancing, IAM Conditions allow you to conditionally grant predefined roles — such as Load Balancer Admin or Network Admin — or custom roles so that only certain types of load balancers can be created.

IAM Conditions supports a condition expression to check the load balancing scheme of a forwarding rule. For example, you can conditionally grant an IAM member the ability to create internal load balancers, but not external ones. If that IAM member attempts to create a forwarding rule for an external load balancer, Google Cloud denies the action and returns an error like the following:

ERROR: (gcloud.compute.forwarding-rules.create) Could not fetch resource:

 - Required 'compute.forwardingRules.create' permission for
 'projects/project-id/regions/region/forwardingRules/forwarding-rule-name'

Using IAM Conditions on Google Cloud load balancers

The load balancing scheme of a forwarding rule determines which type or types of load balancer can use the forwarding rule. In other words, the load balancing scheme corresponds to the load balancer type, as shown in the following table.

Load balancing scheme Description
EXTERNAL External HTTP(S) Load Balancing
External SSL Proxy and TCP Proxy Load Balancing
External TCP/UDP Network Load Balancing
INTERNAL Internal TCP/UDP Load Balancing
INTERNAL_MANAGED Internal HTTP(S) Load Balancing
INTERNAL_SELF_MANAGED Traffic Director

You specify the loadBalancingScheme field when you create the load balancer. By checking the loadBalancingScheme field in an IAM condition, you can grant members the ability to create certain types of load balancers.

Specifying IAM Conditions

You can set conditional role bindings using the same setIamPolicy method that you use to configure any other role bindings. To set a role binding with a condition on a project, you can use the REST API, the gcloud command-line tool, or the IAM page in the Cloud Console.

For more information, see Managing conditional policies.

Example condition expressions for load balancing

The following condition expression, which can be used in an IAM policy, permits an API request only if one of the following is true:

  • The request doesn't involve creating a forwarding rule.
  • The request is to create a forwarding rule that has one of the internal schemes.
!compute.isForwardingRuleCreationOperation() || (
  compute.isForwardingRuleCreationOperation() &&
  compute.matchLoadBalancingSchemes(['INTERNAL', 'INTERNAL_MANAGED', 'INTERNAL_SELF_MANAGED'])
)

The effect of this policy is to cause a permissions error message to appear if a member tries to create a forwarding rule with the EXTERNAL load balancing scheme, because the load balancing scheme EXTERNAL is omitted.

Example policy

This example IAM policy for a project grants the IAM member jane@example.com the Load Balancer Admin predefined role, excluding the ability to create external load balancers (because the load balancing scheme EXTERNAL is omitted). jane@example.com can create internal load balancers, and can manage, modify, and delete any load balancer.

{
  "bindings": [
    {
      "role": "roles/compute.loadBalancerAdmin",
      "members": ["user:jane@example.com"],
      "condition": {
          "title": "only_internal_lb_schemes",
          "description": "Internal LB creation only permitted",
          "expression": "
             !compute.isForwardingRuleCreationOperation() || (
                compute.isForwardingRuleCreationOperation() &&
                compute.matchLoadBalancingSchemes(['INTERNAL', 'INTERNAL_MANAGED', 'INTERNAL_SELF_MANAGED'])
             )
          "
      }
    }
  ]
}

Granting GKE service account permissions for specific types of forwarding rules

You can also use IAM Conditions to limit access to the GKE service account to create only specific types of forwarding rules.

This JSON example demonstrates a complete IAM policy to grant the GKE service account (service-<project-ID>@container-engine-robot.iam.gserviceaccount.com) the Kubernetes Engine Service Agent role. This role allows the service account to create, modify, and delete load balancer components, except for external forwarding rules.

Using this conditional grant, the GKE service account can only create new internal forwarding rules, but can manage all existing forwarding rules.

{
  "bindings": [
    {
      "role": "roles/container.serviceAgent",
      "members": ["serviceAccount:service-<project-ID>@container-engine-robot.iam.gserviceaccount.com"],
      "condition": {
          "title": "only_internal_lb_schemes",
          "description": "Internal LB Creation Only Permitted",
          "expression": "(
                 compute.isForwardingRuleCreationOperation()
                      &&
                  compute.matchLoadBalancingSchemes(['INTERNAL', 'INTERNAL_MANAGED', 'INTERNAL_SELF_MANAGED'])
              )
                  ||
              !compute.isForwardingRuleCreationOperation()
          "
      }
    }
  ]
}

Absent other grants, attempting to create a new GKE Service of type LoadBalancer, without the annotation for an internal TCP/UDP load balancer, results in an error message like the following:

Error creating load balancer (will retry): failed to ensure load balancer for
service default/SERVICE-NAME: failed to create forwarding rule for load balancer
(a01d427111c7011ea96e142010a80006(default/SERVICE-NAME)): googleapi: Error 403:
Required 'compute.forwardingRules.create' permission for
'projects/[project-id]/regions/[region]/forwardingRules/[forwarding-rule-name]',
forbidden

Additionally, absent other grants, attempting to create a new Ingress object, using the Cloud Load Balancing Ingress controller, results in a similar error message because the Cloud Load Balancing Ingress controller needs to create an external HTTP(S) load balancer.

In the above examples, GKE error messages are available using the kubectl describe and kubectl get events -w commands.

What's next