// Copyright 2024 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.orgpolicy.v2;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/orgpolicy/v2/constraint.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "google/type/expr.proto";

option csharp_namespace = "Google.Cloud.OrgPolicy.V2";
option go_package = "cloud.google.com/go/orgpolicy/apiv2/orgpolicypb;orgpolicypb";
option java_multiple_files = true;
option java_outer_classname = "OrgPolicyProto";
option java_package = "com.google.cloud.orgpolicy.v2";
option php_namespace = "Google\\Cloud\\OrgPolicy\\V2";
option ruby_package = "Google::Cloud::OrgPolicy::V2";

// An interface for managing organization policies.
//
// The Organization Policy Service provides a simple mechanism for
// organizations to restrict the allowed configurations across their entire
// resource hierarchy.
//
// You can use a policy to configure restrictions on resources. For
// example, you can enforce a policy that restricts which Google
// Cloud APIs can be activated in a certain part of your resource
// hierarchy, or prevents serial port access to VM instances in a
// particular folder.
//
// Policies are inherited down through the resource hierarchy. A policy
// applied to a parent resource automatically applies to all its child resources
// unless overridden with a policy lower in the hierarchy.
//
// A constraint defines an aspect of a resource's configuration that can be
// controlled by an organization's policy administrator. Policies are a
// collection of constraints that defines their allowable configuration on a
// particular resource and its child resources.
service OrgPolicy {
  option (google.api.default_host) = "orgpolicy.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Lists constraints that could be applied on the specified resource.
  rpc ListConstraints(ListConstraintsRequest)
      returns (ListConstraintsResponse) {
    option (google.api.http) = {
      get: "/v2/{parent=projects/*}/constraints"
      additional_bindings { get: "/v2/{parent=folders/*}/constraints" }
      additional_bindings { get: "/v2/{parent=organizations/*}/constraints" }
    };
    option (google.api.method_signature) = "parent";
  }

  // Retrieves all of the policies that exist on a particular resource.
  rpc ListPolicies(ListPoliciesRequest) returns (ListPoliciesResponse) {
    option (google.api.http) = {
      get: "/v2/{parent=projects/*}/policies"
      additional_bindings { get: "/v2/{parent=folders/*}/policies" }
      additional_bindings { get: "/v2/{parent=organizations/*}/policies" }
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets a policy on a resource.
  //
  // If no policy is set on the resource, `NOT_FOUND` is returned. The
  // `etag` value can be used with `UpdatePolicy()` to update a
  // policy during read-modify-write.
  rpc GetPolicy(GetPolicyRequest) returns (Policy) {
    option (google.api.http) = {
      get: "/v2/{name=projects/*/policies/*}"
      additional_bindings { get: "/v2/{name=folders/*/policies/*}" }
      additional_bindings { get: "/v2/{name=organizations/*/policies/*}" }
    };
    option (google.api.method_signature) = "name";
  }

  // Gets the effective policy on a resource. This is the result of merging
  // policies in the resource hierarchy and evaluating conditions. The
  // returned policy will not have an `etag` or `condition` set because it is
  // an evaluated policy across multiple resources.
  // Subtrees of Resource Manager resource hierarchy with 'under:' prefix will
  // not be expanded.
  rpc GetEffectivePolicy(GetEffectivePolicyRequest) returns (Policy) {
    option (google.api.http) = {
      get: "/v2/{name=projects/*/policies/*}:getEffectivePolicy"
      additional_bindings {
        get: "/v2/{name=folders/*/policies/*}:getEffectivePolicy"
      }
      additional_bindings {
        get: "/v2/{name=organizations/*/policies/*}:getEffectivePolicy"
      }
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a policy.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // constraint does not exist.
  // Returns a `google.rpc.Status` with `google.rpc.Code.ALREADY_EXISTS` if the
  // policy already exists on the given Google Cloud resource.
  rpc CreatePolicy(CreatePolicyRequest) returns (Policy) {
    option (google.api.http) = {
      post: "/v2/{parent=projects/*}/policies"
      body: "policy"
      additional_bindings {
        post: "/v2/{parent=folders/*}/policies"
        body: "policy"
      }
      additional_bindings {
        post: "/v2/{parent=organizations/*}/policies"
        body: "policy"
      }
    };
    option (google.api.method_signature) = "parent,policy";
  }

  // Updates a policy.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // constraint or the policy do not exist.
  // Returns a `google.rpc.Status` with `google.rpc.Code.ABORTED` if the etag
  // supplied in the request does not match the persisted etag of the policy
  //
  // Note: the supplied policy will perform a full overwrite of all
  // fields.
  rpc UpdatePolicy(UpdatePolicyRequest) returns (Policy) {
    option (google.api.http) = {
      patch: "/v2/{policy.name=projects/*/policies/*}"
      body: "policy"
      additional_bindings {
        patch: "/v2/{policy.name=folders/*/policies/*}"
        body: "policy"
      }
      additional_bindings {
        patch: "/v2/{policy.name=organizations/*/policies/*}"
        body: "policy"
      }
    };
    option (google.api.method_signature) = "policy";
  }

  // Deletes a policy.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // constraint or organization policy does not exist.
  rpc DeletePolicy(DeletePolicyRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v2/{name=projects/*/policies/*}"
      additional_bindings { delete: "/v2/{name=folders/*/policies/*}" }
      additional_bindings { delete: "/v2/{name=organizations/*/policies/*}" }
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a custom constraint.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // organization does not exist.
  // Returns a `google.rpc.Status` with `google.rpc.Code.ALREADY_EXISTS` if the
  // constraint already exists on the given organization.
  rpc CreateCustomConstraint(CreateCustomConstraintRequest)
      returns (CustomConstraint) {
    option (google.api.http) = {
      post: "/v2/{parent=organizations/*}/customConstraints"
      body: "custom_constraint"
    };
    option (google.api.method_signature) = "parent,custom_constraint";
  }

  // Updates a custom constraint.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // constraint does not exist.
  //
  // Note: the supplied policy will perform a full overwrite of all
  // fields.
  rpc UpdateCustomConstraint(UpdateCustomConstraintRequest)
      returns (CustomConstraint) {
    option (google.api.http) = {
      patch: "/v2/{custom_constraint.name=organizations/*/customConstraints/*}"
      body: "custom_constraint"
    };
    option (google.api.method_signature) = "custom_constraint";
  }

  // Gets a custom constraint.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // custom constraint does not exist.
  rpc GetCustomConstraint(GetCustomConstraintRequest)
      returns (CustomConstraint) {
    option (google.api.http) = {
      get: "/v2/{name=organizations/*/customConstraints/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Retrieves all of the custom constraints that exist on a particular
  // organization resource.
  rpc ListCustomConstraints(ListCustomConstraintsRequest)
      returns (ListCustomConstraintsResponse) {
    option (google.api.http) = {
      get: "/v2/{parent=organizations/*}/customConstraints"
    };
    option (google.api.method_signature) = "parent";
  }

  // Deletes a custom constraint.
  //
  // Returns a `google.rpc.Status` with `google.rpc.Code.NOT_FOUND` if the
  // constraint does not exist.
  rpc DeleteCustomConstraint(DeleteCustomConstraintRequest)
      returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v2/{name=organizations/*/customConstraints/*}"
    };
    option (google.api.method_signature) = "name";
  }
}

// Defines an organization policy which is used to specify constraints
// for configurations of Google Cloud resources.
message Policy {
  option (google.api.resource) = {
    type: "orgpolicy.googleapis.com/Policy"
    pattern: "projects/{project}/policies/{policy}"
    pattern: "folders/{folder}/policies/{policy}"
    pattern: "organizations/{organization}/policies/{policy}"
  };

  // Immutable. The resource name of the policy. Must be one of the following
  // forms, where `constraint_name` is the name of the constraint which this
  // policy configures:
  //
  // * `projects/{project_number}/policies/{constraint_name}`
  // * `folders/{folder_id}/policies/{constraint_name}`
  // * `organizations/{organization_id}/policies/{constraint_name}`
  //
  // For example, `projects/123/policies/compute.disableSerialPortAccess`.
  //
  // Note: `projects/{project_id}/policies/{constraint_name}` is also an
  // acceptable name for API requests, but responses will return the name using
  // the equivalent project number.
  string name = 1 [(google.api.field_behavior) = IMMUTABLE];

  // Basic information about the Organization Policy.
  PolicySpec spec = 2;

  // Deprecated.
  AlternatePolicySpec alternate = 3 [deprecated = true];

  // Dry-run policy.
  // Audit-only policy, can be used to monitor how the policy would have
  // impacted the existing and future resources if it's enforced.
  PolicySpec dry_run_spec = 4;

  // Optional. An opaque tag indicating the current state of the policy, used
  // for concurrency control. This 'etag' is computed by the server based on the
  // value of other fields, and may be sent on update and delete requests to
  // ensure the client has an up-to-date value before proceeding.
  string etag = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Similar to PolicySpec but with an extra 'launch' field for launch reference.
// The PolicySpec here is specific for dry-run/darklaunch.
message AlternatePolicySpec {
  // Reference to the launch that will be used while audit logging and to
  // control the launch.
  // Should be set only in the alternate policy.
  string launch = 1;

  // Specify constraint for configurations of Google Cloud resources.
  PolicySpec spec = 2;
}

// Defines a Google Cloud policy specification which is used to specify
// constraints for configurations of Google Cloud resources.
message PolicySpec {
  // A rule used to express this policy.
  message PolicyRule {
    // A message that holds specific allowed and denied values.
    // This message can define specific values and subtrees of the Resource
    // Manager resource hierarchy (`Organizations`, `Folders`, `Projects`) that
    // are allowed or denied. This is achieved by using the `under:` and
    // optional `is:` prefixes.
    // The `under:` prefix is used to denote resource subtree values.
    // The `is:` prefix is used to denote specific values, and is required only
    // if the value contains a ":". Values prefixed with "is:" are treated the
    // same as values with no prefix.
    // Ancestry subtrees must be in one of the following formats:
    //
    // - `projects/<project-id>` (for example, `projects/tokyo-rain-123`)
    // - `folders/<folder-id>` (for example, `folders/1234`)
    // - `organizations/<organization-id>` (for example, `organizations/1234`)
    //
    // The `supports_under` field of the associated `Constraint`  defines
    // whether ancestry prefixes can be used.
    message StringValues {
      // List of values allowed at this resource.
      repeated string allowed_values = 1;

      // List of values denied at this resource.
      repeated string denied_values = 2;
    }

    oneof kind {
      // List of values to be used for this policy rule. This field can be set
      // only in policies for list constraints.
      StringValues values = 1;

      // Setting this to true means that all values are allowed. This field can
      // be set only in policies for list constraints.
      bool allow_all = 2;

      // Setting this to true means that all values are denied. This field can
      // be set only in policies for list constraints.
      bool deny_all = 3;

      // If `true`, then the policy is enforced. If `false`, then any
      // configuration is acceptable.
      // This field can be set only in policies for boolean constraints.
      bool enforce = 4;
    }

    // A condition which determines whether this rule is used
    // in the evaluation of the policy. When set, the `expression` field in
    // the `Expr' must include from 1 to 10 subexpressions, joined by the "||"
    // or "&&" operators. Each subexpression must be of the form
    // "resource.matchTag('<ORG_ID>/tag_key_short_name,
    // 'tag_value_short_name')". or "resource.matchTagId('tagKeys/key_id',
    // 'tagValues/value_id')". where key_name and value_name are the resource
    // names for Label Keys and Values. These names are available from the Tag
    // Manager Service. An example expression is:
    // "resource.matchTag('123456789/environment,
    // 'prod')". or "resource.matchTagId('tagKeys/123',
    // 'tagValues/456')".
    google.type.Expr condition = 5;
  }

  // An opaque tag indicating the current version of the policySpec, used for
  // concurrency control.
  //
  // This field is ignored if used in a `CreatePolicy` request.
  //
  // When the policy is returned from either a `GetPolicy` or a
  // `ListPolicies` request, this `etag` indicates the version of the
  // current policySpec to use when executing a read-modify-write loop.
  //
  // When the policy is returned from a `GetEffectivePolicy` request, the
  // `etag` will be unset.
  string etag = 1;

  // Output only. The time stamp this was previously updated. This
  // represents the last time a call to `CreatePolicy` or `UpdatePolicy` was
  // made for that policy.
  google.protobuf.Timestamp update_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // In policies for boolean constraints, the following requirements apply:
  //
  //   - There must be one and only one policy rule where condition is unset.
  //   - Boolean policy rules with conditions must set `enforced` to the
  //     opposite of the policy rule without a condition.
  //   - During policy evaluation, policy rules with conditions that are
  //     true for a target resource take precedence.
  repeated PolicyRule rules = 3;

  // Determines the inheritance behavior for this policy.
  //
  // If `inherit_from_parent` is true, policy rules set higher up in the
  // hierarchy (up to the closest root) are inherited and present in the
  // effective policy. If it is false, then no rules are inherited, and this
  // policy becomes the new root for evaluation.
  // This field can be set only for policies which configure list constraints.
  bool inherit_from_parent = 4;

  // Ignores policies set above this resource and restores the
  // `constraint_default` enforcement behavior of the specific constraint at
  // this resource.
  // This field can be set in policies for either list or boolean
  // constraints. If set, `rules` must be empty and `inherit_from_parent`
  // must be set to false.
  bool reset = 5;
}

// The request sent to the [ListConstraints]
// [google.cloud.orgpolicy.v2.OrgPolicy.ListConstraints] method.
message ListConstraintsRequest {
  // Required. The Google Cloud resource that parents the constraint. Must be in
  // one of the following forms:
  //
  // * `projects/{project_number}`
  // * `projects/{project_id}`
  // * `folders/{folder_id}`
  // * `organizations/{organization_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "orgpolicy.googleapis.com/Constraint"
    }
  ];

  // Size of the pages to be returned. This is currently unsupported and will
  // be ignored. The server may at any point start using this field to limit
  // page size.
  int32 page_size = 2;

  // Page token used to retrieve the next page. This is currently unsupported
  // and will be ignored. The server may at any point start using this field.
  string page_token = 3;
}

// The response returned from the [ListConstraints]
// [google.cloud.orgpolicy.v2.OrgPolicy.ListConstraints] method.
message ListConstraintsResponse {
  // The collection of constraints that are available on the targeted resource.
  repeated Constraint constraints = 1;

  // Page token used to retrieve the next page. This is currently not used.
  string next_page_token = 2;
}

// The request sent to the [ListPolicies]
// [google.cloud.orgpolicy.v2.OrgPolicy.ListPolicies] method.
message ListPoliciesRequest {
  // Required. The target Google Cloud resource that parents the set of
  // constraints and policies that will be returned from this call. Must be in
  // one of the following forms:
  //
  // * `projects/{project_number}`
  // * `projects/{project_id}`
  // * `folders/{folder_id}`
  // * `organizations/{organization_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "orgpolicy.googleapis.com/Policy"
    }
  ];

  // Size of the pages to be returned. This is currently unsupported and will
  // be ignored. The server may at any point start using this field to limit
  // page size.
  int32 page_size = 2;

  // Page token used to retrieve the next page. This is currently unsupported
  // and will be ignored. The server may at any point start using this field.
  string page_token = 3;
}

// The response returned from the [ListPolicies]
// [google.cloud.orgpolicy.v2.OrgPolicy.ListPolicies] method. It will be empty
// if no policies are set on the resource.
message ListPoliciesResponse {
  // All policies that exist on the resource. It will be empty if no
  // policies are set.
  repeated Policy policies = 1;

  // Page token used to retrieve the next page. This is currently not used, but
  // the server may at any point start supplying a valid token.
  string next_page_token = 2;
}

// The request sent to the [GetPolicy]
// [google.cloud.orgpolicy.v2.OrgPolicy.GetPolicy] method.
message GetPolicyRequest {
  // Required. Resource name of the policy. See
  // [Policy][google.cloud.orgpolicy.v2.Policy] for naming requirements.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "orgpolicy.googleapis.com/Policy"
    }
  ];
}

// The request sent to the [GetEffectivePolicy]
// [google.cloud.orgpolicy.v2.OrgPolicy.GetEffectivePolicy] method.
message GetEffectivePolicyRequest {
  // Required. The effective policy to compute. See
  // [Policy][google.cloud.orgpolicy.v2.Policy] for naming requirements.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "orgpolicy.googleapis.com/Policy"
    }
  ];
}

// The request sent to the [CreatePolicyRequest]
// [google.cloud.orgpolicy.v2.OrgPolicy.CreatePolicy] method.
message CreatePolicyRequest {
  // Required. The Google Cloud resource that will parent the new policy. Must
  // be in one of the following forms:
  //
  // * `projects/{project_number}`
  // * `projects/{project_id}`
  // * `folders/{folder_id}`
  // * `organizations/{organization_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "orgpolicy.googleapis.com/Policy"
    }
  ];

  // Required. Policy to create.
  Policy policy = 3 [(google.api.field_behavior) = REQUIRED];
}

// The request sent to the [UpdatePolicyRequest]
// [google.cloud.orgpolicy.v2.OrgPolicy.UpdatePolicy] method.
message UpdatePolicyRequest {
  // Required. Policy to update.
  Policy policy = 1 [(google.api.field_behavior) = REQUIRED];

  // Field mask used to specify the fields to be overwritten in the policy
  // by the set. The fields specified in the update_mask are relative to the
  // policy, not the full request.
  google.protobuf.FieldMask update_mask = 3;
}

// The request sent to the [DeletePolicy]
// [google.cloud.orgpolicy.v2.OrgPolicy.DeletePolicy] method.
message DeletePolicyRequest {
  // Required. Name of the policy to delete.
  // See the policy entry for naming rules.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "orgpolicy.googleapis.com/Policy"
    }
  ];

  // Optional. The current etag of policy. If an etag is provided and does not
  // match the current etag of the policy, deletion will be blocked and an
  // ABORTED error will be returned.
  string etag = 2 [(google.api.field_behavior) = OPTIONAL];
}

// The request sent to the [CreateCustomConstraintRequest]
// [google.cloud.orgpolicy.v2.OrgPolicy.CreateCustomConstraint] method.
message CreateCustomConstraintRequest {
  // Required. Must be in the following form:
  //
  // * `organizations/{organization_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "orgpolicy.googleapis.com/CustomConstraint"
    }
  ];

  // Required. Custom constraint to create.
  CustomConstraint custom_constraint = 2
      [(google.api.field_behavior) = REQUIRED];
}

// The request sent to the [GetCustomConstraint]
// [google.cloud.orgpolicy.v2.OrgPolicy.GetCustomConstraint] method.
message GetCustomConstraintRequest {
  // Required. Resource name of the custom constraint. See the custom constraint
  // entry for naming requirements.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "orgpolicy.googleapis.com/CustomConstraint"
    }
  ];
}

// The request sent to the [ListCustomConstraints]
// [google.cloud.orgpolicy.v2.OrgPolicy.ListCustomConstraints] method.
message ListCustomConstraintsRequest {
  // Required. The target Google Cloud resource that parents the set of custom
  // constraints that will be returned from this call. Must be in one of the
  // following forms:
  //
  // * `organizations/{organization_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "orgpolicy.googleapis.com/CustomConstraint"
    }
  ];

  // Size of the pages to be returned. This is currently unsupported and will
  // be ignored. The server may at any point start using this field to limit
  // page size.
  int32 page_size = 2;

  // Page token used to retrieve the next page. This is currently unsupported
  // and will be ignored. The server may at any point start using this field.
  string page_token = 3;
}

// The response returned from the [ListCustomConstraints]
// [google.cloud.orgpolicy.v2.OrgPolicy.ListCustomConstraints] method. It will
// be empty if no custom constraints are set on the organization resource.
message ListCustomConstraintsResponse {
  // All custom constraints that exist on the organization resource. It will be
  // empty if no custom constraints are set.
  repeated CustomConstraint custom_constraints = 1;

  // Page token used to retrieve the next page. This is currently not used, but
  // the server may at any point start supplying a valid token.
  string next_page_token = 2;
}

// The request sent to the [UpdateCustomConstraintRequest]
// [google.cloud.orgpolicy.v2.OrgPolicy.UpdateCustomConstraint] method.
message UpdateCustomConstraintRequest {
  // Required. `CustomConstraint` to update.
  CustomConstraint custom_constraint = 1
      [(google.api.field_behavior) = REQUIRED];
}

// The request sent to the [DeleteCustomConstraint]
// [google.cloud.orgpolicy.v2.OrgPolicy.DeleteCustomConstraint] method.
message DeleteCustomConstraintRequest {
  // Required. Name of the custom constraint to delete.
  // See the custom constraint entry for naming rules.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "orgpolicy.googleapis.com/CustomConstraint"
    }
  ];
}
