// Copyright 2022 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 Cloud Org Policy service provides a simple mechanism for organizations to
// restrict the allowed configurations across their entire Cloud Resource
// hierarchy.
//
// You can use a `policy` to configure restrictions in Cloud resources. For
// example, you can enforce a `policy` that restricts which Google
// Cloud Platform 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
  // a computed `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 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 Org 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";
  }
}

// Defines a Cloud Organization `Policy` which is used to specify `Constraints`
// for configurations of Cloud Platform 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;
}

// 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 Cloud Platform resources.
  PolicySpec spec = 2;
}

// Defines a Cloud Organization `PolicySpec` which is used to specify
// `Constraints` for configurations of Cloud Platform 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 Cloud 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>", e.g. "projects/tokyo-rain-123"
    //     - "folders/<folder-id>", e.g. "folders/1234"
    //     - "organizations/<organization-id>", e.g. "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 PolicyRule. 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 `Policy`, 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 `Policy` 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];

  // Up to 10 PolicyRules are allowed.
  //
  // In Policies for boolean constraints, the following requirements apply:
  //   - There must be one and only one PolicyRule where condition is unset.
  //   - BooleanPolicyRules with conditions must set `enforced` to the opposite
  //     of the PolicyRule without a condition.
  //   - During policy evaluation, PolicyRules 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, PolicyRules 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 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 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` 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` for naming rules.
  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 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 `Policy` for naming rules.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "orgpolicy.googleapis.com/Policy"
    }
  ];
}
