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