// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.policytroubleshooter.iam.v3;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/iam/v1/policy.proto";
import "google/iam/v2/policy.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";
import "google/type/expr.proto";

option cc_enable_arenas = true;
option csharp_namespace = "Google.Cloud.PolicyTroubleshooter.Iam.V3";
option go_package = "cloud.google.com/go/policytroubleshooter/iam/apiv3/iampb;iampb";
option java_multiple_files = true;
option java_outer_classname = "TroubleshooterProto";
option java_package = "com.google.cloud.policytroubleshooter.iam.v3";
option php_namespace = "Google\\Cloud\\PolicyTroubleshooter\\Iam\\V3";
option ruby_package = "Google::Cloud::PolicyTroubleshooter::Iam::V3";

// IAM Policy Troubleshooter service.
//
// This service helps you troubleshoot access issues for Google Cloud resources.
service PolicyTroubleshooter {
  option (google.api.default_host) = "policytroubleshooter.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Checks whether a principal has a specific permission for a specific
  // resource, and explains why the principal does or doesn't have that
  // permission.
  rpc TroubleshootIamPolicy(TroubleshootIamPolicyRequest)
      returns (TroubleshootIamPolicyResponse) {
    option (google.api.http) = {
      post: "/v3/iam:troubleshoot"
      body: "*"
    };
  }
}

// Whether IAM allow policies gives the principal the permission.
enum AllowAccessState {
  // Not specified.
  ALLOW_ACCESS_STATE_UNSPECIFIED = 0;

  // The allow policy gives the principal the permission.
  ALLOW_ACCESS_STATE_GRANTED = 1;

  // The allow policy doesn't give the principal the permission.
  ALLOW_ACCESS_STATE_NOT_GRANTED = 2;

  // The allow policy gives the principal the permission if a condition
  // expression evaluate to `true`. However, the sender of the request didn't
  // provide enough context for Policy Troubleshooter to evaluate the condition
  // expression.
  ALLOW_ACCESS_STATE_UNKNOWN_CONDITIONAL = 3;

  // The sender of the request doesn't have access to all of the allow policies
  // that Policy Troubleshooter needs to evaluate the principal's access.
  ALLOW_ACCESS_STATE_UNKNOWN_INFO = 4;
}

// Whether IAM deny policies deny the principal the permission.
enum DenyAccessState {
  // Not specified.
  DENY_ACCESS_STATE_UNSPECIFIED = 0;

  // The deny policy denies the principal the permission.
  DENY_ACCESS_STATE_DENIED = 1;

  // The deny policy doesn't deny the principal the permission.
  DENY_ACCESS_STATE_NOT_DENIED = 2;

  // The deny policy denies the principal the permission if a condition
  // expression evaluates to `true`. However, the sender of the request didn't
  // provide enough context for Policy Troubleshooter to evaluate the condition
  // expression.
  DENY_ACCESS_STATE_UNKNOWN_CONDITIONAL = 3;

  // The sender of the request does not have access to all of the deny policies
  // that Policy Troubleshooter needs to evaluate the principal's access.
  DENY_ACCESS_STATE_UNKNOWN_INFO = 4;
}

// Whether a role includes a specific permission.
enum RolePermissionInclusionState {
  // Not specified.
  ROLE_PERMISSION_INCLUSION_STATE_UNSPECIFIED = 0;

  // The permission is included in the role.
  ROLE_PERMISSION_INCLUDED = 1;

  // The permission is not included in the role.
  ROLE_PERMISSION_NOT_INCLUDED = 2;

  // The sender of the request is not allowed to access the role definition.
  ROLE_PERMISSION_UNKNOWN_INFO = 3;
}

// Whether the permission in the request matches the permission in the policy.
enum PermissionPatternMatchingState {
  // Not specified.
  PERMISSION_PATTERN_MATCHING_STATE_UNSPECIFIED = 0;

  // The permission in the request matches the permission in the policy.
  PERMISSION_PATTERN_MATCHED = 1;

  // The permission in the request matches the permission in the policy.
  PERMISSION_PATTERN_NOT_MATCHED = 2;
}

// Whether the principal in the request matches the principal in the policy.
enum MembershipMatchingState {
  // Not specified.
  MEMBERSHIP_MATCHING_STATE_UNSPECIFIED = 0;

  // The principal in the request matches the principal in the policy. The
  // principal can be included directly or indirectly:
  //
  // * A principal is included directly if that principal is listed in the
  //   role binding.
  // * A principal is included indirectly if that principal is in a Google
  //   group, Google Workspace account, or Cloud Identity domain that is listed
  //   in the policy.
  MEMBERSHIP_MATCHED = 1;

  // The principal in the request doesn't match the principal in the policy.
  MEMBERSHIP_NOT_MATCHED = 2;

  // The principal in the policy is a group or domain, and the sender of the
  // request doesn't have permission to view whether the principal in the
  // request is a member of the group or domain.
  MEMBERSHIP_UNKNOWN_INFO = 3;

  // The principal is an unsupported type.
  MEMBERSHIP_UNKNOWN_UNSUPPORTED = 4;
}

// The extent to which a single data point contributes to an overall
// determination.
enum HeuristicRelevance {
  // Not specified.
  HEURISTIC_RELEVANCE_UNSPECIFIED = 0;

  // The data point has a limited effect on the result. Changing the data point
  // is unlikely to affect the overall determination.
  HEURISTIC_RELEVANCE_NORMAL = 1;

  // The data point has a strong effect on the result. Changing the data point
  // is likely to affect the overall determination.
  HEURISTIC_RELEVANCE_HIGH = 2;
}

// Request for
// [TroubleshootIamPolicy][google.cloud.policytroubleshooter.iam.v3.PolicyTroubleshooter.TroubleshootIamPolicy].
message TroubleshootIamPolicyRequest {
  // The information to use for checking whether a principal has a permission
  // for a resource.
  AccessTuple access_tuple = 1;
}

// Response for
// [TroubleshootIamPolicy][google.cloud.policytroubleshooter.iam.v3.PolicyTroubleshooter.TroubleshootIamPolicy].
message TroubleshootIamPolicyResponse {
  // Whether the principal has the permission on the resource.
  enum OverallAccessState {
    // Not specified.
    OVERALL_ACCESS_STATE_UNSPECIFIED = 0;

    // The principal has the permission.
    CAN_ACCESS = 1;

    // The principal doesn't have the permission.
    CANNOT_ACCESS = 2;

    // The principal might have the permission, but the sender can't access all
    // of the information needed to fully evaluate the principal's access.
    UNKNOWN_INFO = 3;

    // The principal might have the permission, but Policy Troubleshooter can't
    // fully evaluate the principal's access because the sender didn't provide
    // the required context to evaluate the condition.
    UNKNOWN_CONDITIONAL = 4;
  }

  // Indicates whether the principal has the specified permission for the
  // specified resource, based on evaluating all types of the applicable IAM
  // policies.
  OverallAccessState overall_access_state = 1;

  // The access tuple from the request, including any provided context used to
  // evaluate the condition.
  AccessTuple access_tuple = 2;

  // An explanation of how the applicable IAM allow policies affect the final
  // access state.
  AllowPolicyExplanation allow_policy_explanation = 3;

  // An explanation of how the applicable IAM deny policies affect the final
  // access state.
  DenyPolicyExplanation deny_policy_explanation = 4;
}

// Information about the principal, resource, and permission to check.
message AccessTuple {
  // Required. The email address of the principal whose access you want to
  // check. For example, `alice@example.com` or
  // `my-service-account@my-project.iam.gserviceaccount.com`.
  //
  // The principal must be a Google Account or a service account. Other types of
  // principals are not supported.
  string principal = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The full resource name that identifies the resource. For example,
  // `//compute.googleapis.com/projects/my-project/zones/us-central1-a/instances/my-instance`.
  //
  // For examples of full resource names for Google Cloud services, see
  // https://cloud.google.com/iam/help/troubleshooter/full-resource-names.
  string full_resource_name = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The IAM permission to check for, either in the `v1` permission
  // format or the `v2` permission format.
  //
  // For a complete list of IAM permissions in the `v1` format, see
  // https://cloud.google.com/iam/help/permissions/reference.
  //
  // For a list of IAM permissions in the `v2` format, see
  // https://cloud.google.com/iam/help/deny/supported-permissions.
  //
  // For a complete list of predefined IAM roles and the permissions in each
  // role, see https://cloud.google.com/iam/help/roles/reference.
  string permission = 3 [(google.api.field_behavior) = REQUIRED];

  // Output only. The permission that Policy Troubleshooter checked for, in
  // the `v2` format.
  string permission_fqdn = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Additional context for the request, such as the request time or
  // IP address. This context allows Policy Troubleshooter to troubleshoot
  // conditional role bindings and deny rules.
  ConditionContext condition_context = 5
      [(google.api.field_behavior) = OPTIONAL];
}

// Additional context for troubleshooting conditional role bindings and deny
// rules.
message ConditionContext {
  // Core attributes for a resource. A resource is an
  // addressable (named) entity provided by the destination service. For
  // example, a Compute Engine instance.
  message Resource {
    // The name of the service that this resource belongs to, such as
    // `compute.googleapis.com`. The service name might not match the DNS
    // hostname that actually serves the request.
    //
    // For a full list of resource service values, see
    // https://cloud.google.com/iam/help/conditions/resource-services
    string service = 1;

    // The stable identifier (name) of a resource on the `service`. A resource
    // can be logically identified as `//{resource.service}/{resource.name}`.
    // Unlike the resource URI, the resource name doesn't contain any protocol
    // and version information.
    //
    // For a list of full resource name formats, see
    // https://cloud.google.com/iam/help/troubleshooter/full-resource-names
    string name = 2;

    // The type of the resource, in the format `{service}/{kind}`.
    //
    // For a full list of resource type values, see
    // https://cloud.google.com/iam/help/conditions/resource-types
    string type = 3;
  }

  // This message defines attributes for a node that handles a network request.
  // The node can be either a service or an application that sends, forwards,
  // or receives the request. Service peers should fill in
  // `principal` and `labels` as appropriate.
  message Peer {
    // The IPv4 or IPv6 address of the peer.
    string ip = 1;

    // The network port of the peer.
    int64 port = 2;
  }

  // This message defines attributes for an HTTP request. If the actual
  // request is not an HTTP request, the runtime system should try to map
  // the actual request to an equivalent HTTP request.
  message Request {
    // Optional. The timestamp when the destination service receives the first
    // byte of the request.
    google.protobuf.Timestamp receive_time = 1
        [(google.api.field_behavior) = OPTIONAL];
  }

  // A tag that applies to a resource during policy evaluation. Tags can be
  // either directly bound to a resource or inherited from its ancestor.
  // `EffectiveTag` contains the `name` and `namespaced_name` of the tag value
  // and tag key, with additional fields of `inherited` to indicate the
  // inheritance status of the effective tag.
  message EffectiveTag {
    // Output only. Resource name for TagValue in the format `tagValues/456`.
    string tag_value = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The namespaced name of the TagValue. Can be in the form
    // `{organization_id}/{tag_key_short_name}/{tag_value_short_name}` or
    // `{project_id}/{tag_key_short_name}/{tag_value_short_name}` or
    // `{project_number}/{tag_key_short_name}/{tag_value_short_name}`.
    string namespaced_tag_value = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The name of the TagKey, in the format `tagKeys/{id}`, such
    // as `tagKeys/123`.
    string tag_key = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. The namespaced name of the TagKey. Can be in the form
    // `{organization_id}/{tag_key_short_name}` or
    // `{project_id}/{tag_key_short_name}` or
    // `{project_number}/{tag_key_short_name}`.
    string namespaced_tag_key = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

    // The parent name of the tag key.
    // Must be in the format `organizations/{organization_id}` or
    // `projects/{project_number}`
    string tag_key_parent_name = 6;

    // Output only. Indicates the inheritance status of a tag value
    // attached to the given resource. If the tag value is inherited from one of
    // the resource's ancestors, inherited will be true. If false, then the tag
    // value is directly attached to the resource, inherited will be false.
    bool inherited = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Represents a target resource that is involved with a network activity.
  // If multiple resources are involved with an activity, this must be the
  // primary one.
  Resource resource = 1;

  // The destination of a network activity, such as accepting a TCP connection.
  // In a multi-hop network activity, the destination represents the receiver of
  // the last hop.
  Peer destination = 2;

  // Represents a network request, such as an HTTP request.
  Request request = 3;

  // Output only. The effective tags on the resource. The effective tags are
  // fetched during troubleshooting.
  repeated EffectiveTag effective_tags = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Details about how the relevant IAM allow policies affect the final access
// state.
message AllowPolicyExplanation {
  // Indicates whether the principal has the specified permission for the
  // specified resource, based on evaluating all applicable IAM allow policies.
  AllowAccessState allow_access_state = 1;

  // List of IAM allow policies that were evaluated to check the principal's
  // permissions, with annotations to indicate how each policy contributed to
  // the final result.
  //
  // The list of policies includes the policy for the resource itself, as well
  // as allow policies that are inherited from higher levels of the resource
  // hierarchy, including the organization, the folder, and the project.
  //
  // To learn more about the resource hierarchy, see
  // https://cloud.google.com/iam/help/resource-hierarchy.
  repeated ExplainedAllowPolicy explained_policies = 2;

  // The relevance of the allow policy type to the overall access state.
  HeuristicRelevance relevance = 3;
}

// Details about how a specific IAM allow policy contributed to the final access
// state.
message ExplainedAllowPolicy {
  // Required. Indicates whether _this policy_ provides the specified permission
  // to the specified principal for the specified resource.
  //
  // This field does _not_ indicate whether the principal actually has the
  // permission for the resource. There might be another policy that overrides
  // this policy. To determine whether the principal actually has the
  // permission, use the `overall_access_state` field in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  AllowAccessState allow_access_state = 1
      [(google.api.field_behavior) = REQUIRED];

  // The full resource name that identifies the resource. For example,
  // `//compute.googleapis.com/projects/my-project/zones/us-central1-a/instances/my-instance`.
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  //
  // For examples of full resource names for Google Cloud services, see
  // https://cloud.google.com/iam/help/troubleshooter/full-resource-names.
  string full_resource_name = 2;

  // Details about how each role binding in the policy affects the principal's
  // ability, or inability, to use the permission for the resource. The order of
  // the role bindings matches the role binding order in the policy.
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  repeated AllowBindingExplanation binding_explanations = 3;

  // The relevance of this policy to the overall access state in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  HeuristicRelevance relevance = 4;

  // The IAM allow policy attached to the resource.
  //
  // If the sender of the request does not have access to the policy, this field
  // is empty.
  google.iam.v1.Policy policy = 5;
}

// Details about how a role binding in an allow policy affects a principal's
// ability to use a permission.
message AllowBindingExplanation {
  // Details about whether the role binding includes the principal.
  message AnnotatedAllowMembership {
    // Indicates whether the role binding includes the principal.
    MembershipMatchingState membership = 1;

    // The relevance of the principal's status to the overall determination for
    // the role binding.
    HeuristicRelevance relevance = 2;
  }

  // Required. Indicates whether _this role binding_ gives the specified
  // permission to the specified principal on the specified resource.
  //
  // This field does _not_ indicate whether the principal actually has the
  // permission on the resource. There might be another role binding that
  // overrides this role binding. To determine whether the principal actually
  // has the permission, use the `overall_access_state` field in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  AllowAccessState allow_access_state = 1
      [(google.api.field_behavior) = REQUIRED];

  // The role that this role binding grants. For example,
  // `roles/compute.admin`.
  //
  // For a complete list of predefined IAM roles, as well as the permissions in
  // each role, see https://cloud.google.com/iam/help/roles/reference.
  string role = 2;

  // Indicates whether the role granted by this role binding contains the
  // specified permission.
  RolePermissionInclusionState role_permission = 3;

  // The relevance of the permission's existence, or nonexistence, in the role
  // to the overall determination for the entire policy.
  HeuristicRelevance role_permission_relevance = 4;

  // The combined result of all memberships. Indicates if the principal is
  // included in any role binding, either directly or indirectly.
  AnnotatedAllowMembership combined_membership = 5;

  // Indicates whether each role binding includes the principal specified in the
  // request, either directly or indirectly. Each key identifies a principal in
  // the role binding, and each value indicates whether the principal in the
  // role binding includes the principal in the request.
  //
  // For example, suppose that a role binding includes the following principals:
  //
  // * `user:alice@example.com`
  // * `group:product-eng@example.com`
  //
  // You want to troubleshoot access for `user:bob@example.com`. This user is a
  // member of the group `group:product-eng@example.com`.
  //
  // For the first principal in the role binding, the key is
  // `user:alice@example.com`, and the `membership` field in the value is set to
  // `NOT_INCLUDED`.
  //
  // For the second principal in the role binding, the key is
  // `group:product-eng@example.com`, and the `membership` field in the value is
  // set to `INCLUDED`.
  map<string, AnnotatedAllowMembership> memberships = 6;

  // The relevance of this role binding to the overall determination for the
  // entire policy.
  HeuristicRelevance relevance = 7;

  // A condition expression that specifies when the role binding grants access.
  //
  // To learn about IAM Conditions, see
  // https://cloud.google.com/iam/help/conditions/overview.
  google.type.Expr condition = 8;

  // Condition evaluation state for this role binding.
  ConditionExplanation condition_explanation = 9;
}

// Details about how the relevant IAM deny policies affect the final access
// state.
message DenyPolicyExplanation {
  // Indicates whether the principal is denied the specified permission for
  // the specified resource, based on evaluating all applicable IAM deny
  // policies.
  DenyAccessState deny_access_state = 1;

  // List of resources with IAM deny policies that were evaluated to check the
  // principal's denied permissions, with annotations to indicate how each
  // policy contributed to the final result.
  //
  // The list of resources includes the policy for the resource itself, as well
  // as policies that are inherited from higher levels of the resource
  // hierarchy, including the organization, the folder, and the project. The
  // order of the resources starts from the resource and climbs up the resource
  // hierarchy.
  //
  // To learn more about the resource hierarchy, see
  // https://cloud.google.com/iam/help/resource-hierarchy.
  repeated ExplainedDenyResource explained_resources = 2;

  // The relevance of the deny policy result to the overall access state.
  HeuristicRelevance relevance = 3;

  // Indicates whether the permission to troubleshoot is supported in deny
  // policies.
  bool permission_deniable = 4;
}

// Details about how a specific resource contributed to the deny policy
// evaluation.
message ExplainedDenyResource {
  // Required. Indicates whether any policies attached to _this resource_ deny
  // the specific permission to the specified principal for the specified
  // resource.
  //
  // This field does _not_ indicate whether the principal actually has the
  // permission for the resource. There might be another policy that overrides
  // this policy. To determine whether the principal actually has the
  // permission, use the `overall_access_state` field in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  DenyAccessState deny_access_state = 1
      [(google.api.field_behavior) = REQUIRED];

  // The full resource name that identifies the resource. For example,
  // `//compute.googleapis.com/projects/my-project/zones/us-central1-a/instances/my-instance`.
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  //
  // For examples of full resource names for Google Cloud services, see
  // https://cloud.google.com/iam/help/troubleshooter/full-resource-names.
  string full_resource_name = 2;

  // List of IAM deny policies that were evaluated to check the principal's
  // denied permissions, with annotations to indicate how each policy
  // contributed to the final result.
  repeated ExplainedDenyPolicy explained_policies = 3;

  // The relevance of this policy to the overall access state in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  HeuristicRelevance relevance = 4;
}

// Details about how a specific IAM deny policy [Policy][google.iam.v2.Policy]
// contributed to the access check.
message ExplainedDenyPolicy {
  // Required. Indicates whether _this policy_ denies the specified permission
  // to the specified principal for the specified resource.
  //
  // This field does _not_ indicate whether the principal actually has the
  // permission for the resource. There might be another policy that overrides
  // this policy. To determine whether the principal actually has the
  // permission, use the `overall_access_state` field in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  DenyAccessState deny_access_state = 1
      [(google.api.field_behavior) = REQUIRED];

  // The IAM deny policy attached to the resource.
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  google.iam.v2.Policy policy = 2;

  // Details about how each rule in the policy affects the principal's inability
  // to use the permission for the resource. The order of the deny rule matches
  // the order of the rules in the deny policy.
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  repeated DenyRuleExplanation rule_explanations = 3;

  // The relevance of this policy to the overall access state in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  //
  // If the sender of the request does not have access to the policy, this field
  // is omitted.
  HeuristicRelevance relevance = 4;
}

// Details about how a deny rule in a deny policy affects a principal's ability
// to use a permission.
message DenyRuleExplanation {
  // Details about whether the permission in the request is denied by the
  // deny rule.
  message AnnotatedPermissionMatching {
    // Indicates whether the permission in the request is denied by the deny
    // rule.
    PermissionPatternMatchingState permission_matching_state = 1;

    // The relevance of the permission status to the overall determination for
    // the rule.
    HeuristicRelevance relevance = 2;
  }

  // Details about whether the principal in the request is listed as a denied
  // principal in the deny rule, either directly or through membership in a
  // principal set.
  message AnnotatedDenyPrincipalMatching {
    // Indicates whether the principal is listed as a denied principal in the
    // deny rule, either directly or through membership in a principal set.
    MembershipMatchingState membership = 1;

    // The relevance of the principal's status to the overall determination for
    // the role binding.
    HeuristicRelevance relevance = 2;
  }

  // Required. Indicates whether _this rule_ denies the specified permission to
  // the specified principal for the specified resource.
  //
  // This field does _not_ indicate whether the principal is actually denied on
  // the permission for the resource. There might be another rule that overrides
  // this rule. To determine whether the principal actually has the permission,
  // use the `overall_access_state` field in the
  // [TroubleshootIamPolicyResponse][google.cloud.policytroubleshooter.iam.v3.TroubleshootIamPolicyResponse].
  DenyAccessState deny_access_state = 1
      [(google.api.field_behavior) = REQUIRED];

  // Indicates whether the permission in the request is listed as a denied
  // permission in the deny rule.
  AnnotatedPermissionMatching combined_denied_permission = 2;

  // Lists all denied permissions in the deny rule and indicates whether each
  // permission matches the permission in the request.
  //
  // Each key identifies a denied permission in the rule, and each value
  // indicates whether the denied permission matches the permission in the
  // request.
  map<string, AnnotatedPermissionMatching> denied_permissions = 3;

  // Indicates whether the permission in the request is listed as an exception
  // permission in the deny rule.
  AnnotatedPermissionMatching combined_exception_permission = 4;

  // Lists all exception permissions in the deny rule and indicates whether each
  // permission matches the permission in the request.
  //
  // Each key identifies a exception permission in the rule, and each value
  // indicates whether the exception permission matches the permission in the
  // request.
  map<string, AnnotatedPermissionMatching> exception_permissions = 5;

  // Indicates whether the principal is listed as a denied principal in the
  // deny rule, either directly or through membership in a principal set.
  AnnotatedDenyPrincipalMatching combined_denied_principal = 6;

  // Lists all denied principals in the deny rule and indicates whether each
  // principal matches the principal in the request, either directly or through
  // membership in a principal set.
  //
  // Each key identifies a denied principal in the rule, and each value
  // indicates whether the denied principal matches the principal in the
  // request.
  map<string, AnnotatedDenyPrincipalMatching> denied_principals = 7;

  // Indicates whether the principal is listed as an exception principal in the
  // deny rule, either directly or through membership in a principal set.
  AnnotatedDenyPrincipalMatching combined_exception_principal = 8;

  // Lists all exception principals in the deny rule and indicates whether each
  // principal matches the principal in the request, either directly or through
  // membership in a principal set.
  //
  // Each key identifies a exception principal in the rule, and each value
  // indicates whether the exception principal matches the principal in the
  // request.
  map<string, AnnotatedDenyPrincipalMatching> exception_principals = 9;

  // The relevance of this role binding to the overall determination for the
  // entire policy.
  HeuristicRelevance relevance = 10;

  // A condition expression that specifies when the deny rule denies the
  // principal access.
  //
  // To learn about IAM Conditions, see
  // https://cloud.google.com/iam/help/conditions/overview.
  google.type.Expr condition = 11;

  // Condition evaluation state for this role binding.
  ConditionExplanation condition_explanation = 12;
}

// Explanation for how a condition affects a principal's access
message ConditionExplanation {
  // Evaluated state of a condition expression.
  message EvaluationState {
    // Start position of an expression in the condition, by character.
    int32 start = 1;

    // End position of an expression in the condition, by character,
    // end included, for example: the end position of the first part of
    // `a==b || c==d` would be 4.
    int32 end = 2;

    // Value of this expression.
    google.protobuf.Value value = 3;

    // Any errors that prevented complete evaluation of the condition
    // expression.
    repeated google.rpc.Status errors = 4;
  }

  // Value of the condition.
  google.protobuf.Value value = 1;

  // Any errors that prevented complete evaluation of the condition expression.
  repeated google.rpc.Status errors = 3;

  // The value of each statement of the condition expression. The value can be
  // `true`, `false`, or `null`. The value is `null` if the statement can't be
  // evaluated.
  repeated EvaluationState evaluation_states = 2;
}
