diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fb31087..ac500777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [1.5.1](https://github.com/googleapis/java-iam/compare/v1.5.0...v1.5.1) (2022-07-12) + + +### Documentation + +* **samples:** add iam deny samples and test ([#371](https://github.com/googleapis/java-iam/issues/371)) ([c503444](https://github.com/googleapis/java-iam/commit/c50344450dcaaeed31ea33c494edf507c9b6ff6b)) + + +### Dependencies + +* update dependency com.google.apis:google-api-services-cloudresourcemanager to v3-rev20220619-1.32.1 ([#375](https://github.com/googleapis/java-iam/issues/375)) ([9102337](https://github.com/googleapis/java-iam/commit/91023372c5ba198e428e0a5f87f657334f65d5da)) +* update dependency com.google.auth:google-auth-library-oauth2-http to v1.8.0 ([#377](https://github.com/googleapis/java-iam/issues/377)) ([2687617](https://github.com/googleapis/java-iam/commit/268761726c8b70010d243b7f0c58db45a6590ef4)) +* update dependency com.google.http-client:google-http-client-jackson2 to v1.42.1 ([#378](https://github.com/googleapis/java-iam/issues/378)) ([7ea1243](https://github.com/googleapis/java-iam/commit/7ea1243a734745d04edba01c75e996737f97eee5)) + ## [1.5.0](https://github.com/googleapis/java-iam/compare/v1.4.1...v1.5.0) (2022-06-30) diff --git a/google-iam-policy/pom.xml b/google-iam-policy/pom.xml index 245de440..7ed41878 100644 --- a/google-iam-policy/pom.xml +++ b/google-iam-policy/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-iam-policy - 1.5.0 + 1.5.1 jar Google IAM Policy https://github.com/googleapis/java-eventarc @@ -11,7 +11,7 @@ com.google.cloud google-iam-parent - 1.5.0 + 1.5.1 google-iam-policy diff --git a/grpc-google-iam-v1/pom.xml b/grpc-google-iam-v1/pom.xml index badfc9ee..321c2dd5 100644 --- a/grpc-google-iam-v1/pom.xml +++ b/grpc-google-iam-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-iam-v1 - 1.5.0 + 1.5.1 grpc-google-iam-v1 GRPC library for grpc-google-iam-v1 com.google.cloud google-iam-parent - 1.5.0 + 1.5.1 diff --git a/grpc-google-iam-v2beta/pom.xml b/grpc-google-iam-v2beta/pom.xml index 0eacc7fe..4fe0190d 100644 --- a/grpc-google-iam-v2beta/pom.xml +++ b/grpc-google-iam-v2beta/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-iam-v2beta - 1.5.0 + 1.5.1 grpc-google-iam-v2beta GRPC library for proto-google-iam-v1 com.google.cloud google-iam-parent - 1.5.0 + 1.5.1 diff --git a/pom.xml b/pom.xml index 5521cc84..064ae2d7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-iam-parent pom - 1.5.0 + 1.5.1 Google IAM Parent https://github.com/googleapis/java-iam @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.0 + 1.5.1 @@ -77,27 +77,27 @@ com.google.cloud google-iam-policy - 1.5.0 + 1.5.1 com.google.api.grpc proto-google-iam-v2beta - 1.5.0 + 1.5.1 com.google.api.grpc grpc-google-iam-v1 - 1.5.0 + 1.5.1 com.google.api.grpc grpc-google-iam-v2beta - 1.5.0 + 1.5.1 com.google.api.grpc proto-google-iam-v1 - 1.5.0 + 1.5.1 diff --git a/proto-google-iam-v1/pom.xml b/proto-google-iam-v1/pom.xml index b9871ef5..7b8648ab 100644 --- a/proto-google-iam-v1/pom.xml +++ b/proto-google-iam-v1/pom.xml @@ -3,13 +3,13 @@ 4.0.0 com.google.api.grpc proto-google-iam-v1 - 1.5.0 + 1.5.1 proto-google-iam-v1 PROTO library for proto-google-iam-v1 com.google.cloud google-iam-parent - 1.5.0 + 1.5.1 diff --git a/proto-google-iam-v2beta/pom.xml b/proto-google-iam-v2beta/pom.xml index b6fe0dd4..262b8c41 100644 --- a/proto-google-iam-v2beta/pom.xml +++ b/proto-google-iam-v2beta/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-iam-v2beta - 1.5.0 + 1.5.1 proto-google-iam-v2beta Proto library for proto-google-iam-v1 com.google.cloud google-iam-parent - 1.5.0 + 1.5.1 diff --git a/samples/cloud-client/snippets/pom.xml b/samples/cloud-client/snippets/pom.xml new file mode 100644 index 00000000..a43094fc --- /dev/null +++ b/samples/cloud-client/snippets/pom.xml @@ -0,0 +1,97 @@ + + + + iam-deny-samples + 4.0.0 + 1.0-SNAPSHOT + + + + + com.google.apis + google-api-services-cloudresourcemanager + v3-rev20220619-1.32.1 + + + com.google.auth + google-auth-library-oauth2-http + 1.8.0 + + + com.google.http-client + google-http-client-jackson2 + 1.42.1 + + + com.google.apis + google-api-services-iam + v2beta-rev20220526-1.32.1 + + + com.google.apis + google-api-services-iamcredentials + v1-rev20211203-1.32.1 + + + + + truth + com.google.truth + test + 1.1.3 + + + junit + junit + test + 4.13.2 + + + + + + + + libraries-bom + com.google.cloud + import + pom + 26.0.0 + + + + + + + shared-configuration + com.google.cloud.samples + 1.2.0 + + + + 11 + 11 + + + gce-diregapic + + diff --git a/samples/cloud-client/snippets/src/main/java/CreateDenyPolicy.java b/samples/cloud-client/snippets/src/main/java/CreateDenyPolicy.java new file mode 100644 index 00000000..a41b6fc1 --- /dev/null +++ b/samples/cloud-client/snippets/src/main/java/CreateDenyPolicy.java @@ -0,0 +1,164 @@ +/* + * 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. + */ + +// [START iam_create_deny_policy] + +import com.google.iam.v2beta.CreatePolicyRequest; +import com.google.iam.v2beta.DenyRule; +import com.google.iam.v2beta.PoliciesClient; +import com.google.iam.v2beta.Policy; +import com.google.iam.v2beta.PolicyRule; +import com.google.longrunning.Operation; +import com.google.type.Expr; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CreateDenyPolicy { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // ID or number of the Google Cloud project you want to use. + String projectId = "sitalakshmi-deny"; + + // Specify the id of the Deny policy you want to create. + String policyId = "deny-policy-id-1"; + + createDenyPolicy(projectId, policyId); + } + + // Create a deny policy. + // You can add deny policies to organizations, folders, and projects. + // Each of these resources can have up to 5 deny policies. + // + // Deny policies contain deny rules, which specify the following: + // 1. The permissions to deny and/or exempt. + // 2. The principals that are denied, or exempted from denial. + // 3. An optional condition on when to enforce the deny rules. + public static void createDenyPolicy(String projectId, String policyId) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + + try (PoliciesClient policiesClient = PoliciesClient.create()) { + // Each deny policy is attached to an organization, folder, or project. + // To work with deny policies, specify the attachment point. + // + // Its format can be one of the following: + // 1. cloudresourcemanager.googleapis.com/organizations/ORG_ID + // 2. cloudresourcemanager.googleapis.com/folders/FOLDER_ID + // 3. cloudresourcemanager.googleapis.com/projects/PROJECT_ID + // + // The attachment point is identified by its URL-encoded resource name. + String urlEncodedResource = + URLEncoder.encode( + "cloudresourcemanager.googleapis.com/projects/", StandardCharsets.UTF_8); + String attachmentPoint = String.format("%s%s", urlEncodedResource, projectId); + + // Construct the full path of the resource to which the policy is attached. + // Its format is: "policies/{attachmentPoint}/denypolicies/{policyId}" + String policyParent = String.format("policies/%s/denypolicies", attachmentPoint); + + DenyRule denyRule = + DenyRule.newBuilder() + // Add one or more principals who should be denied the permissions specified in this + // rule. + // For more information on allowed values, see: + // https://cloud.google.com/iam/docs/principal-identifiers + .addDeniedPrincipals("principalSet://goog/public:all") + + // Optionally, set the principals who should be exempted from the + // list of denied principals. For example, if you want to deny certain permissions + // to a group but exempt a few principals, then add those here. + // .addExceptionPrincipals( + // "principalSet://goog/group/project-admins@example.com") + + // Set the permissions to deny. + // The permission value is of the format: service_fqdn/resource.action + // For the list of supported permissions, see: + // https://cloud.google.com/iam/help/deny/supported-permissions + .addDeniedPermissions("cloudresourcemanager.googleapis.com/projects.delete") + + // Optionally, add the permissions to be exempted from this rule. + // Meaning, the deny rule will not be applicable to these permissions. + // .addExceptionPermissions("cloudresourcemanager.googleapis.com/projects.create") + + // Set the condition which will enforce the deny rule. If this condition is true, + // the deny rule will be applicable. Else, the rule will not be enforced. + .setDenialCondition( + Expr.newBuilder() + // The expression uses Common Expression Language syntax (CEL). + // Here we block access based on tags. + // + // A tag is a key-value pair that can be attached to an organization, folder, + // or project. You can use deny policies to deny permissions based on tags + // without adding an IAM Condition to every role grant. + // For example, imagine that you tag all of your projects as dev, test, or + // prod. You want only members of project-admins@example.com to be able to + // perform operations on projects that are tagged prod. + // To solve this problem, you create a deny rule that denies the + // cloudresourcemanager.googleapis.com/projects.delete permission to everyone + // except project-admins@example.com for resources that are tagged test. + .setExpression("!resource.matchTag('12345678/env', 'test')") + .setTitle("Only for test projects") + .build()) + .build(); + + // Add the deny rule and a description for it. + Policy policy = + Policy.newBuilder() + // Set the deny rule. + .addRules( + PolicyRule.newBuilder() + // Set a description for the rule. + .setDescription( + "block all principals from deleting projects, unless the principal is a member of project-admins@example.com and the project being deleted has a tag with the value test") + .setDenyRule(denyRule) + .build()) + .build(); + + // Set the policy resource path, policy rules and a unique ID for the policy. + CreatePolicyRequest createPolicyRequest = + CreatePolicyRequest.newBuilder() + .setParent(policyParent) + .setPolicy(policy) + .setPolicyId(policyId) + .build(); + + // Build the create policy request. + Operation operation = + policiesClient + .createPolicyCallable() + .futureCall(createPolicyRequest) + .get(3, TimeUnit.MINUTES); + + // Wait for the operation to complete. + if (!operation.getDone() || operation.hasError()) { + System.out.println("Error in creating the policy " + operation.getError()); + return; + } + + // Retrieve the policy name. + Policy response = policiesClient.getPolicy(String.format("%s/%s", policyParent, policyId)); + String policyName = response.getName(); + System.out.println( + "Created the deny policy: " + policyName.substring(policyName.lastIndexOf("/") + 1)); + } + } +} +// [END iam_create_deny_policy] diff --git a/samples/cloud-client/snippets/src/main/java/DeleteDenyPolicy.java b/samples/cloud-client/snippets/src/main/java/DeleteDenyPolicy.java new file mode 100644 index 00000000..bf98545c --- /dev/null +++ b/samples/cloud-client/snippets/src/main/java/DeleteDenyPolicy.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +// [START iam_delete_deny_policy] + +import com.google.iam.v2beta.DeletePolicyRequest; +import com.google.iam.v2beta.PoliciesClient; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class DeleteDenyPolicy { + + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + + // ID or number of the Google Cloud project you want to use. + String projectId = "your-google-cloud-project-id"; + + // Specify the ID of the deny policy you want to retrieve. + String policyId = "deny-policy-id"; + + deleteDenyPolicy(projectId, policyId); + } + + // Delete the policy if you no longer want to enforce the rules in a deny policy. + public static void deleteDenyPolicy(String projectId, String policyId) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + try (PoliciesClient policiesClient = PoliciesClient.create()) { + + // Each deny policy is attached to an organization, folder, or project. + // To work with deny policies, specify the attachment point. + // + // Its format can be one of the following: + // 1. cloudresourcemanager.googleapis.com/organizations/ORG_ID + // 2. cloudresourcemanager.googleapis.com/folders/FOLDER_ID + // 3. cloudresourcemanager.googleapis.com/projects/PROJECT_ID + // + // The attachment point is identified by its URL-encoded resource name. + String urlEncodedResource = + URLEncoder.encode( + "cloudresourcemanager.googleapis.com/projects/", StandardCharsets.UTF_8); + String attachmentPoint = String.format("%s%s", urlEncodedResource, projectId); + + // Construct the full path of the resource to which the policy is attached. + // Its format is: "policies/{attachmentPoint}/denypolicies/{policyId}" + String policyParent = String.format("policies/%s/denypolicies/%s", attachmentPoint, policyId); + + // Create the DeletePolicy request. + DeletePolicyRequest deletePolicyRequest = + DeletePolicyRequest.newBuilder().setName(policyParent).build(); + + // Delete the policy and wait for the operation to complete. + Operation operation = + policiesClient + .deletePolicyCallable() + .futureCall(deletePolicyRequest) + .get(3, TimeUnit.MINUTES); + + if (!operation.getDone() || operation.hasError()) { + System.out.println("Error in deleting the policy " + operation.getError()); + return; + } + + System.out.println("Deleted the deny policy: " + policyId); + } + } +} +// [END iam_delete_deny_policy] diff --git a/samples/cloud-client/snippets/src/main/java/GetDenyPolicy.java b/samples/cloud-client/snippets/src/main/java/GetDenyPolicy.java new file mode 100644 index 00000000..10b1b5c2 --- /dev/null +++ b/samples/cloud-client/snippets/src/main/java/GetDenyPolicy.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +// [START iam_get_deny_policy] + +import com.google.iam.v2beta.GetPolicyRequest; +import com.google.iam.v2beta.PoliciesClient; +import com.google.iam.v2beta.Policy; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +public class GetDenyPolicy { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + + // ID or number of the Google Cloud project you want to use. + String projectId = "your-google-cloud-project-id"; + + // Specify the ID of the deny policy you want to retrieve. + String policyId = "deny-policy-id"; + + getDenyPolicy(projectId, policyId); + } + + // Retrieve the deny policy given the project ID and policy ID. + public static void getDenyPolicy(String projectId, String policyId) throws IOException { + // Create the IAM Policies client. + try (PoliciesClient policiesClient = PoliciesClient.create()) { + + // Each deny policy is attached to an organization, folder, or project. + // To work with deny policies, specify the attachment point. + // + // Its format can be one of the following: + // 1. cloudresourcemanager.googleapis.com/organizations/ORG_ID + // 2. cloudresourcemanager.googleapis.com/folders/FOLDER_ID + // 3. cloudresourcemanager.googleapis.com/projects/PROJECT_ID + // + // The attachment point is identified by its URL-encoded resource name. + String urlEncodedResource = + URLEncoder.encode( + "cloudresourcemanager.googleapis.com/projects/", StandardCharsets.UTF_8); + String attachmentPoint = String.format("%s%s", urlEncodedResource, projectId); + + // Construct the full path of the resource to which the policy is attached. + // Its format is: "policies/{attachmentPoint}/denypolicies/{policyId}" + String policyParent = String.format("policies/%s/denypolicies/%s", attachmentPoint, policyId); + + // Specify the policyParent and execute the GetPolicy request. + GetPolicyRequest getPolicyRequest = + GetPolicyRequest.newBuilder().setName(policyParent).build(); + + Policy policy = policiesClient.getPolicy(getPolicyRequest); + System.out.printf("Retrieved the deny policy: %s : %s%n", policyId, policy); + } + } +} +// [END iam_get_deny_policy] diff --git a/samples/cloud-client/snippets/src/main/java/ListDenyPolicies.java b/samples/cloud-client/snippets/src/main/java/ListDenyPolicies.java new file mode 100644 index 00000000..b8f89da3 --- /dev/null +++ b/samples/cloud-client/snippets/src/main/java/ListDenyPolicies.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +// [START iam_list_deny_policy] + +import com.google.iam.v2beta.PoliciesClient; +import com.google.iam.v2beta.Policy; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +public class ListDenyPolicies { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + // ID or number of the Google Cloud project you want to use. + String projectId = "your-google-cloud-project-id"; + + listDenyPolicies(projectId); + } + + // List all the deny policies that are attached to a resource. + // A resource can have up to 5 deny policies. + public static void listDenyPolicies(String projectId) throws IOException { + // Initialize the Policies client. + try (PoliciesClient policiesClient = PoliciesClient.create()) { + + // Each deny policy is attached to an organization, folder, or project. + // To work with deny policies, specify the attachment point. + // + // Its format can be one of the following: + // 1. cloudresourcemanager.googleapis.com/organizations/ORG_ID + // 2. cloudresourcemanager.googleapis.com/folders/FOLDER_ID + // 3. cloudresourcemanager.googleapis.com/projects/PROJECT_ID + // + // The attachment point is identified by its URL-encoded resource name. + String urlEncodedResource = + URLEncoder.encode( + "cloudresourcemanager.googleapis.com/projects/", StandardCharsets.UTF_8); + String attachmentPoint = String.format("%s%s", urlEncodedResource, projectId); + + // Construct the full path of the resource to which the policy is attached. + // Its format is: "policies/{attachmentPoint}/denypolicies" + String policyParent = String.format("policies/%s/denypolicies", attachmentPoint); + + // Create a list request and iterate over the returned policies. + for (Policy policy : policiesClient.listPolicies(policyParent).iterateAll()) { + System.out.println(policy.getName()); + } + System.out.println("Listed all deny policies"); + } + } +} +// [END iam_list_deny_policy] diff --git a/samples/cloud-client/snippets/src/main/java/UpdateDenyPolicy.java b/samples/cloud-client/snippets/src/main/java/UpdateDenyPolicy.java new file mode 100644 index 00000000..e0846d7c --- /dev/null +++ b/samples/cloud-client/snippets/src/main/java/UpdateDenyPolicy.java @@ -0,0 +1,158 @@ +/* + * 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. + */ + +// [START iam_update_deny_policy] + +import com.google.iam.v2beta.DenyRule; +import com.google.iam.v2beta.PoliciesClient; +import com.google.iam.v2beta.Policy; +import com.google.iam.v2beta.PolicyRule; +import com.google.iam.v2beta.UpdatePolicyRequest; +import com.google.longrunning.Operation; +import com.google.type.Expr; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class UpdateDenyPolicy { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + + // ID or number of the Google Cloud project you want to use. + String projectId = "your-google-cloud-project-id"; + + // Specify the ID of the Deny policy you want to retrieve. + String policyId = "deny-policy-id"; + + // Etag field that identifies the policy version. The etag changes each time + // you update the policy. Get the etag of an existing policy by performing a GetPolicy request. + String etag = "policy_etag"; + + updateDenyPolicy(projectId, policyId, etag); + } + + // Update the deny rules and/ or its display name after policy creation. + public static void updateDenyPolicy(String projectId, String policyId, String etag) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + + try (PoliciesClient policiesClient = PoliciesClient.create()) { + + // Each deny policy is attached to an organization, folder, or project. + // To work with deny policies, specify the attachment point. + // + // Its format can be one of the following: + // 1. cloudresourcemanager.googleapis.com/organizations/ORG_ID + // 2. cloudresourcemanager.googleapis.com/folders/FOLDER_ID + // 3. cloudresourcemanager.googleapis.com/projects/PROJECT_ID + // + // The attachment point is identified by its URL-encoded resource name. + String urlEncodedResource = + URLEncoder.encode( + "cloudresourcemanager.googleapis.com/projects/", StandardCharsets.UTF_8); + String attachmentPoint = String.format("%s%s", urlEncodedResource, projectId); + + // Construct the full path of the resource to which the policy is attached to. + // Its format is: "policies/{attachmentPoint}/denypolicies/{policyId}" + String policyParent = String.format("policies/%s/denypolicies/%s", attachmentPoint, policyId); + + DenyRule denyRule = + DenyRule.newBuilder() + // Add one or more principals who should be denied the permissions specified in this + // rule. + // For more information on allowed values, see: + // https://cloud.google.com/iam/docs/principal-identifiers + .addDeniedPrincipals("principalSet://goog/public:all") + + // Optionally, set the principals who should be exempted from the list of principals + // added in "DeniedPrincipals". + // Example, if you want to deny certain permissions to a group but exempt a few + // principals, then add those here. + // .addExceptionPrincipals( + // "principalSet://goog/group/project-admins@example.com") + + // Set the permissions to deny. + // The permission value is of the format: service_fqdn/resource.action + // For the list of supported permissions, see: + // https://cloud.google.com/iam/help/deny/supported-permissions + .addDeniedPermissions("cloudresourcemanager.googleapis.com/projects.delete") + + // Add the permissions to be exempted from this rule. + // Meaning, the deny rule will not be applicable to these permissions. + // .addExceptionPermissions("cloudresourcemanager.googleapis.com/projects.get") + + // Set the condition which will enforce the deny rule. + // If this condition is true, the deny rule will be applicable. Else, the rule will + // not be enforced. + .setDenialCondition( + Expr.newBuilder() + // The expression uses Common Expression Language syntax (CEL). Here we block + // access based on tags. + // + // A tag is a key-value pair that can be attached to an organization, folder, + // or project. You can use deny policies to deny permissions based on tags + // without adding an IAM Condition to every role grant. + // For example, imagine that you tag all of your projects as dev, test, or + // prod. You want only members of project-admins@example.com to be able to + // perform operations on projects that are tagged prod. + // To solve this problem, you create a deny rule that denies the + // cloudresourcemanager.googleapis.com/projects.delete permission to everyone + // except project-admins@example.com for resources that are tagged prod. + .setExpression("!resource.matchTag('12345678/env', 'prod')") + .setTitle("Only for prod projects") + .build()) + .build(); + + // Set the policy resource path, version (etag) and the updated deny rules. + Policy policy = + Policy.newBuilder() + .setName(policyParent) + .setEtag(etag) + .addRules( + PolicyRule.newBuilder() + // Set the rule description to update. + .setDescription( + "Block all principals from deleting projects, unless the principal is a member of project-admins@example.com and the project being deleted has a tag with the value prod") + // Set the deny rule to update. + .setDenyRule(denyRule) + .build()) + .build(); + + // Create the update policy request. + UpdatePolicyRequest updatePolicyRequest = + UpdatePolicyRequest.newBuilder().setPolicy(policy).build(); + + // Wait for the operation to complete. + Operation operation = + policiesClient + .updatePolicyCallable() + .futureCall(updatePolicyRequest) + .get(3, TimeUnit.MINUTES); + + if (!operation.getDone() || operation.hasError()) { + System.out.println("Error in updating the policy " + operation.getError()); + return; + } + + System.out.println("Updated the deny policy: " + policyId); + } + } +} +// [END iam_update_deny_policy] diff --git a/samples/cloud-client/snippets/src/test/java/DenyIT.java b/samples/cloud-client/snippets/src/test/java/DenyIT.java new file mode 100644 index 00000000..a0af4cbc --- /dev/null +++ b/samples/cloud-client/snippets/src/test/java/DenyIT.java @@ -0,0 +1,130 @@ +/* + * 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. + */ + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.iam.v2beta.PoliciesClient; +import com.google.iam.v2beta.Policy; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DenyIT { + + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String GOOGLE_APPLICATION_CREDENTIALS = + System.getenv("GOOGLE_APPLICATION_CREDENTIALS"); + private static String POLICY_ID; + + private ByteArrayOutputStream stdOut; + + // Check if the required environment variables are set. + public static void requireEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) + .that(System.getenv(envVarName)) + .isNotEmpty(); + } + + @BeforeClass + public static void setUp() + throws IOException, InterruptedException, ExecutionException, TimeoutException { + final PrintStream out = System.out; + ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + + POLICY_ID = "limit-project-deletion" + UUID.randomUUID(); + + CreateDenyPolicy.createDenyPolicy(PROJECT_ID, POLICY_ID); + assertThat(stdOut.toString()).contains(String.format("Created the deny policy: %s", POLICY_ID)); + + stdOut.close(); + System.setOut(out); + } + + @AfterClass + public static void cleanup() + throws IOException, InterruptedException, ExecutionException, TimeoutException { + final PrintStream out = System.out; + ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + + DeleteDenyPolicy.deleteDenyPolicy(PROJECT_ID, POLICY_ID); + assertThat(stdOut.toString()).contains(String.format("Deleted the deny policy: %s", POLICY_ID)); + + stdOut.close(); + System.setOut(out); + } + + @Before + public void beforeEach() { + stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + } + + @After + public void afterEach() { + stdOut = null; + System.setOut(null); + } + + @Test + public void testListDenyPolicies() throws IOException { + ListDenyPolicies.listDenyPolicies(PROJECT_ID); + assertThat(stdOut.toString()).contains("Listed all deny policies"); + } + + @Test + public void testGetDenyPolicy() throws IOException { + GetDenyPolicy.getDenyPolicy(PROJECT_ID, POLICY_ID); + assertThat(stdOut.toString()) + .contains(String.format("Retrieved the deny policy: %s", POLICY_ID)); + assertThat(stdOut.toString()).contains(POLICY_ID); + } + + @Test + public void testUpdateDenyPolicy() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + + try (PoliciesClient policiesClient = PoliciesClient.create()) { + // Get the etag from the Deny policy. + String attachmentPoint = + String.format("cloudresourcemanager.googleapis.com/projects/%s", PROJECT_ID) + .replaceAll("/", "%2F"); + String policyParent = + String.format("policies/%s/denypolicies/%s", attachmentPoint, POLICY_ID); + Policy policy = policiesClient.getPolicy(policyParent); + + // Test policy update. + UpdateDenyPolicy.updateDenyPolicy(PROJECT_ID, POLICY_ID, policy.getEtag()); + assertThat(stdOut.toString()) + .contains(String.format("Updated the deny policy: %s", POLICY_ID)); + } + } +} diff --git a/versions.txt b/versions.txt index 3f1840c4..844af1a5 100644 --- a/versions.txt +++ b/versions.txt @@ -1,8 +1,8 @@ # Format: # module:released-version:current-version -proto-google-iam-v1:1.5.0:1.5.0 -grpc-google-iam-v1:1.5.0:1.5.0 -proto-google-iam-v2beta:1.5.0:1.5.0 -grpc-google-iam-v2beta:1.5.0:1.5.0 -google-iam-policy:1.5.0:1.5.0 +proto-google-iam-v1:1.5.1:1.5.1 +grpc-google-iam-v1:1.5.1:1.5.1 +proto-google-iam-v2beta:1.5.1:1.5.1 +grpc-google-iam-v2beta:1.5.1:1.5.1 +google-iam-policy:1.5.1:1.5.1