1// Copyright 2023 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15syntax = "proto3"; 16 17package google.cloud.policysimulator.v1; 18 19import "google/api/annotations.proto"; 20import "google/api/client.proto"; 21import "google/api/field_behavior.proto"; 22import "google/api/resource.proto"; 23import "google/cloud/policysimulator/v1/explanations.proto"; 24import "google/iam/v1/policy.proto"; 25import "google/longrunning/operations.proto"; 26import "google/protobuf/timestamp.proto"; 27import "google/rpc/status.proto"; 28import "google/type/date.proto"; 29 30option cc_enable_arenas = true; 31option csharp_namespace = "Google.Cloud.PolicySimulator.V1"; 32option go_package = "cloud.google.com/go/policysimulator/apiv1/policysimulatorpb;policysimulatorpb"; 33option java_multiple_files = true; 34option java_outer_classname = "SimulatorProto"; 35option java_package = "com.google.cloud.policysimulator.v1"; 36option php_namespace = "Google\\Cloud\\PolicySimulator\\V1"; 37option ruby_package = "Google::Cloud::PolicySimulator::V1"; 38 39// Policy Simulator API service. 40// 41// Policy Simulator is a collection of endpoints for creating, running, and 42// viewing a [Replay][google.cloud.policysimulator.v1.Replay]. A 43// [Replay][google.cloud.policysimulator.v1.Replay] is a type of simulation that 44// lets you see how your principals' access to resources might change if you 45// changed your IAM policy. 46// 47// During a [Replay][google.cloud.policysimulator.v1.Replay], Policy Simulator 48// re-evaluates, or replays, past access attempts under both the current policy 49// and your proposed policy, and compares those results to determine how your 50// principals' access might change under the proposed policy. 51service Simulator { 52 option (google.api.default_host) = "policysimulator.googleapis.com"; 53 option (google.api.oauth_scopes) = 54 "https://www.googleapis.com/auth/cloud-platform"; 55 56 // Gets the specified [Replay][google.cloud.policysimulator.v1.Replay]. Each 57 // `Replay` is available for at least 7 days. 58 rpc GetReplay(GetReplayRequest) returns (Replay) { 59 option (google.api.http) = { 60 get: "/v1/{name=projects/*/locations/*/replays/*}" 61 additional_bindings { get: "/v1/{name=folders/*/locations/*/replays/*}" } 62 additional_bindings { 63 get: "/v1/{name=organizations/*/locations/*/replays/*}" 64 } 65 }; 66 option (google.api.method_signature) = "name"; 67 } 68 69 // Creates and starts a [Replay][google.cloud.policysimulator.v1.Replay] using 70 // the given [ReplayConfig][google.cloud.policysimulator.v1.ReplayConfig]. 71 rpc CreateReplay(CreateReplayRequest) returns (google.longrunning.Operation) { 72 option (google.api.http) = { 73 post: "/v1/{parent=projects/*/locations/*}/replays" 74 body: "replay" 75 additional_bindings { 76 post: "/v1/{parent=folders/*/locations/*}/replays" 77 body: "replay" 78 } 79 additional_bindings { 80 post: "/v1/{parent=organizations/*/locations/*}/replays" 81 body: "replay" 82 } 83 }; 84 option (google.api.method_signature) = "parent,replay"; 85 option (google.longrunning.operation_info) = { 86 response_type: "Replay" 87 metadata_type: "ReplayOperationMetadata" 88 }; 89 } 90 91 // Lists the results of running a 92 // [Replay][google.cloud.policysimulator.v1.Replay]. 93 rpc ListReplayResults(ListReplayResultsRequest) 94 returns (ListReplayResultsResponse) { 95 option (google.api.http) = { 96 get: "/v1/{parent=projects/*/locations/*/replays/*}/results" 97 additional_bindings { 98 get: "/v1/{parent=folders/*/locations/*/replays/*}/results" 99 } 100 additional_bindings { 101 get: "/v1/{parent=organizations/*/locations/*/replays/*}/results" 102 } 103 }; 104 option (google.api.method_signature) = "parent"; 105 } 106} 107 108// A resource describing a `Replay`, or simulation. 109message Replay { 110 option (google.api.resource) = { 111 type: "policysimulator.googleapis.com/Replay" 112 pattern: "projects/{project}/locations/{location}/replays/{replay}" 113 pattern: "folders/{folder}/locations/{location}/replays/{replay}" 114 pattern: "organizations/{organization}/locations/{location}/replays/{replay}" 115 }; 116 117 // Summary statistics about the replayed log entries. 118 message ResultsSummary { 119 // The total number of log entries replayed. 120 int32 log_count = 1; 121 122 // The number of replayed log entries with no difference between 123 // baseline and simulated policies. 124 int32 unchanged_count = 2; 125 126 // The number of replayed log entries with a difference between baseline and 127 // simulated policies. 128 int32 difference_count = 3; 129 130 // The number of log entries that could not be replayed. 131 int32 error_count = 4; 132 133 // The date of the oldest log entry replayed. 134 google.type.Date oldest_date = 5; 135 136 // The date of the newest log entry replayed. 137 google.type.Date newest_date = 6; 138 } 139 140 // The current state of the [Replay][google.cloud.policysimulator.v1.Replay]. 141 enum State { 142 // Default value. This value is unused. 143 STATE_UNSPECIFIED = 0; 144 145 // The `Replay` has not started yet. 146 PENDING = 1; 147 148 // The `Replay` is currently running. 149 RUNNING = 2; 150 151 // The `Replay` has successfully completed. 152 SUCCEEDED = 3; 153 154 // The `Replay` has finished with an error. 155 FAILED = 4; 156 } 157 158 // Output only. The resource name of the `Replay`, which has the following 159 // format: 160 // 161 // `{projects|folders|organizations}/{resource-id}/locations/global/replays/{replay-id}`, 162 // where `{resource-id}` is the ID of the project, folder, or organization 163 // that owns the Replay. 164 // 165 // Example: 166 // `projects/my-example-project/locations/global/replays/506a5f7f-38ce-4d7d-8e03-479ce1833c36` 167 string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; 168 169 // Output only. The current state of the `Replay`. 170 State state = 2 [(google.api.field_behavior) = OUTPUT_ONLY]; 171 172 // Required. The configuration used for the `Replay`. 173 ReplayConfig config = 3 [(google.api.field_behavior) = REQUIRED]; 174 175 // Output only. Summary statistics about the replayed log entries. 176 ResultsSummary results_summary = 5 177 [(google.api.field_behavior) = OUTPUT_ONLY]; 178} 179 180// The result of replaying a single access tuple against a simulated state. 181message ReplayResult { 182 option (google.api.resource) = { 183 type: "policysimulator.googleapis.com/ReplayResult" 184 pattern: "projects/{project}/locations/{location}/replays/{replay}/results/{replay_result}" 185 pattern: "folders/{folder}/locations/{location}/replays/{replay}/results/{replay_result}" 186 pattern: "organizations/{organization}/locations/{location}/replays/{replay}/results/{replay_result}" 187 }; 188 189 // The result of replaying the access tuple. 190 oneof result { 191 // The difference between the principal's access under the current 192 // (baseline) policies and the principal's access under the proposed 193 // (simulated) policies. 194 // 195 // This field is only included for access tuples that were successfully 196 // replayed and had different results under the current policies and the 197 // proposed policies. 198 ReplayDiff diff = 5; 199 200 // The error that caused the access tuple replay to fail. 201 // 202 // This field is only included for access tuples that were not replayed 203 // successfully. 204 google.rpc.Status error = 6; 205 } 206 207 // The resource name of the `ReplayResult`, in the following format: 208 // 209 // `{projects|folders|organizations}/{resource-id}/locations/global/replays/{replay-id}/results/{replay-result-id}`, 210 // where `{resource-id}` is the ID of the project, folder, or organization 211 // that owns the [Replay][google.cloud.policysimulator.v1.Replay]. 212 // 213 // Example: 214 // `projects/my-example-project/locations/global/replays/506a5f7f-38ce-4d7d-8e03-479ce1833c36/results/1234` 215 string name = 1; 216 217 // The [Replay][google.cloud.policysimulator.v1.Replay] that the access tuple 218 // was included in. 219 string parent = 2 [(google.api.resource_reference) = { 220 type: "policysimulator.googleapis.com/Replay" 221 }]; 222 223 // The access tuple that was replayed. This field includes information about 224 // the principal, resource, and permission that were involved in the access 225 // attempt. 226 AccessTuple access_tuple = 3; 227 228 // The latest date this access tuple was seen in the logs. 229 google.type.Date last_seen_date = 4; 230} 231 232// Request message for 233// [Simulator.CreateReplay][google.cloud.policysimulator.v1.Simulator.CreateReplay]. 234message CreateReplayRequest { 235 // Required. The parent resource where this 236 // [Replay][google.cloud.policysimulator.v1.Replay] will be created. This 237 // resource must be a project, folder, or organization with a location. 238 // 239 // Example: `projects/my-example-project/locations/global` 240 string parent = 1 [(google.api.field_behavior) = REQUIRED]; 241 242 // Required. The [Replay][google.cloud.policysimulator.v1.Replay] to create. 243 // Set `Replay.ReplayConfig` to configure the replay. 244 Replay replay = 2 [(google.api.field_behavior) = REQUIRED]; 245} 246 247// Metadata about a Replay operation. 248message ReplayOperationMetadata { 249 // Time when the request was received. 250 google.protobuf.Timestamp start_time = 1; 251} 252 253// Request message for 254// [Simulator.GetReplay][google.cloud.policysimulator.v1.Simulator.GetReplay]. 255message GetReplayRequest { 256 // Required. The name of the [Replay][google.cloud.policysimulator.v1.Replay] 257 // to retrieve, in the following format: 258 // 259 // `{projects|folders|organizations}/{resource-id}/locations/global/replays/{replay-id}`, 260 // where `{resource-id}` is the ID of the project, folder, or organization 261 // that owns the `Replay`. 262 // 263 // Example: 264 // `projects/my-example-project/locations/global/replays/506a5f7f-38ce-4d7d-8e03-479ce1833c36` 265 string name = 1 [ 266 (google.api.field_behavior) = REQUIRED, 267 (google.api.resource_reference) = { 268 type: "policysimulator.googleapis.com/Replay" 269 } 270 ]; 271} 272 273// Request message for 274// [Simulator.ListReplayResults][google.cloud.policysimulator.v1.Simulator.ListReplayResults]. 275message ListReplayResultsRequest { 276 // Required. The [Replay][google.cloud.policysimulator.v1.Replay] whose 277 // results are listed, in the following format: 278 // 279 // `{projects|folders|organizations}/{resource-id}/locations/global/replays/{replay-id}` 280 // 281 // Example: 282 // `projects/my-project/locations/global/replays/506a5f7f-38ce-4d7d-8e03-479ce1833c36` 283 string parent = 1 [ 284 (google.api.field_behavior) = REQUIRED, 285 (google.api.resource_reference) = { 286 type: "policysimulator.googleapis.com/Replay" 287 } 288 ]; 289 290 // The maximum number of 291 // [ReplayResult][google.cloud.policysimulator.v1.ReplayResult] objects to 292 // return. Defaults to 5000. 293 // 294 // The maximum value is 5000; values above 5000 are rounded down to 5000. 295 int32 page_size = 2; 296 297 // A page token, received from a previous 298 // [Simulator.ListReplayResults][google.cloud.policysimulator.v1.Simulator.ListReplayResults] 299 // call. Provide this token to retrieve the next page of results. 300 // 301 // When paginating, all other parameters provided to 302 // [Simulator.ListReplayResults[] must match the call that provided the page 303 // token. 304 string page_token = 3; 305} 306 307// Response message for 308// [Simulator.ListReplayResults][google.cloud.policysimulator.v1.Simulator.ListReplayResults]. 309message ListReplayResultsResponse { 310 // The results of running a [Replay][google.cloud.policysimulator.v1.Replay]. 311 repeated ReplayResult replay_results = 1; 312 313 // A token that you can use to retrieve the next page of 314 // [ReplayResult][google.cloud.policysimulator.v1.ReplayResult] objects. If 315 // this field is omitted, there are no subsequent pages. 316 string next_page_token = 2; 317} 318 319// The configuration used for a 320// [Replay][google.cloud.policysimulator.v1.Replay]. 321message ReplayConfig { 322 // The source of the logs to use for a 323 // [Replay][google.cloud.policysimulator.v1.Replay]. 324 enum LogSource { 325 // An unspecified log source. 326 // If the log source is unspecified, the 327 // [Replay][google.cloud.policysimulator.v1.Replay] defaults to using 328 // `RECENT_ACCESSES`. 329 LOG_SOURCE_UNSPECIFIED = 0; 330 331 // All access logs from the last 90 days. These logs may not include logs 332 // from the most recent 7 days. 333 RECENT_ACCESSES = 1; 334 } 335 336 // A mapping of the resources that you want to simulate policies for and the 337 // policies that you want to simulate. 338 // 339 // Keys are the full resource names for the resources. For example, 340 // `//cloudresourcemanager.googleapis.com/projects/my-project`. 341 // For examples of full resource names for Google Cloud services, see 342 // https://cloud.google.com/iam/help/troubleshooter/full-resource-names. 343 // 344 // Values are [Policy][google.iam.v1.Policy] objects representing the policies 345 // that you want to simulate. 346 // 347 // Replays automatically take into account any IAM policies inherited through 348 // the resource hierarchy, and any policies set on descendant resources. You 349 // do not need to include these policies in the policy overlay. 350 map<string, google.iam.v1.Policy> policy_overlay = 1; 351 352 // The logs to use as input for the 353 // [Replay][google.cloud.policysimulator.v1.Replay]. 354 LogSource log_source = 2; 355} 356 357// The difference between the results of evaluating an access tuple under 358// the current (baseline) policies and under the proposed (simulated) policies. 359// This difference explains how a principal's access could change if the 360// proposed policies were applied. 361message ReplayDiff { 362 // A summary and comparison of the principal's access under the current 363 // (baseline) policies and the proposed (simulated) policies for a single 364 // access tuple. 365 // 366 // The evaluation of the principal's access is reported in the 367 // [AccessState][google.cloud.policysimulator.v1.AccessState] field. 368 AccessStateDiff access_diff = 2; 369} 370 371// A summary and comparison of the principal's access under the current 372// (baseline) policies and the proposed (simulated) policies for a single 373// access tuple. 374message AccessStateDiff { 375 // How the principal's access, specified in the AccessState field, changed 376 // between the current (baseline) policies and proposed (simulated) policies. 377 enum AccessChangeType { 378 // Default value. This value is unused. 379 ACCESS_CHANGE_TYPE_UNSPECIFIED = 0; 380 381 // The principal's access did not change. 382 // This includes the case where both baseline and simulated are UNKNOWN, 383 // but the unknown information is equivalent. 384 NO_CHANGE = 1; 385 386 // The principal's access under both the current policies and the proposed 387 // policies is `UNKNOWN`, but the unknown information differs between them. 388 UNKNOWN_CHANGE = 2; 389 390 // The principal had access under the current policies (`GRANTED`), but will 391 // no longer have access after the proposed changes (`NOT_GRANTED`). 392 ACCESS_REVOKED = 3; 393 394 // The principal did not have access under the current policies 395 // (`NOT_GRANTED`), but will have access after the proposed changes 396 // (`GRANTED`). 397 ACCESS_GAINED = 4; 398 399 // This result can occur for the following reasons: 400 // 401 // * The principal had access under the current policies (`GRANTED`), but 402 // their access after the proposed changes is `UNKNOWN`. 403 // 404 // * The principal's access under the current policies is `UNKNOWN`, but 405 // they 406 // will not have access after the proposed changes (`NOT_GRANTED`). 407 ACCESS_MAYBE_REVOKED = 5; 408 409 // This result can occur for the following reasons: 410 // 411 // * The principal did not have access under the current policies 412 // (`NOT_GRANTED`), but their access after the proposed changes is 413 // `UNKNOWN`. 414 // 415 // * The principal's access under the current policies is `UNKNOWN`, but 416 // they will have access after the proposed changes (`GRANTED`). 417 ACCESS_MAYBE_GAINED = 6; 418 } 419 420 // The results of evaluating the access tuple under the current (baseline) 421 // policies. 422 // 423 // If the [AccessState][google.cloud.policysimulator.v1.AccessState] couldn't 424 // be fully evaluated, this field explains why. 425 ExplainedAccess baseline = 1; 426 427 // The results of evaluating the access tuple under the proposed (simulated) 428 // policies. 429 // 430 // If the AccessState couldn't be fully evaluated, this field explains why. 431 ExplainedAccess simulated = 2; 432 433 // How the principal's access, specified in the AccessState field, changed 434 // between the current (baseline) policies and proposed (simulated) policies. 435 AccessChangeType access_change = 3; 436} 437 438// Details about how a set of policies, listed in 439// [ExplainedPolicy][google.cloud.policysimulator.v1.ExplainedPolicy], resulted 440// in a certain [AccessState][google.cloud.policysimulator.v1.AccessState] when 441// replaying an access tuple. 442message ExplainedAccess { 443 // Whether the principal in the access tuple has permission to access the 444 // resource in the access tuple under the given policies. 445 AccessState access_state = 1; 446 447 // If the [AccessState][google.cloud.policysimulator.v1.AccessState] is 448 // `UNKNOWN`, this field contains the policies that led to that result. 449 // 450 // If the `AccessState` is `GRANTED` or `NOT_GRANTED`, this field is 451 // omitted. 452 repeated ExplainedPolicy policies = 2; 453 454 // If the [AccessState][google.cloud.policysimulator.v1.AccessState] is 455 // `UNKNOWN`, this field contains a list of errors explaining why the result 456 // is `UNKNOWN`. 457 // 458 // If the `AccessState` is `GRANTED` or `NOT_GRANTED`, this field is 459 // omitted. 460 repeated google.rpc.Status errors = 3; 461} 462