Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: add IAM Conditions support (#120)
* Add IAM Conditions support

* format

* wip

* set version in mock policies

* wip

* address comments

* fix pom.

* revert http-client-bom

* address feedback

* address integration tests feedback

* update core

* lint

* clean up ubla

* format
  • Loading branch information
frankyn committed Feb 28, 2020
1 parent 2627a93 commit 8256f6d
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 40 deletions.
Expand Up @@ -16,14 +16,14 @@

package com.google.cloud.storage;

import com.google.api.services.storage.model.Expr;
import com.google.api.services.storage.model.Policy.Bindings;
import com.google.cloud.Identity;
import com.google.cloud.Binding;
import com.google.cloud.Condition;
import com.google.cloud.Policy;
import com.google.cloud.Role;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Helper for converting between the Policy model provided by the API and the Policy model provided
Expand All @@ -35,29 +35,46 @@ static Policy convertFromApiPolicy(com.google.api.services.storage.model.Policy
Policy.Builder policyBuilder = Policy.newBuilder();
List<Bindings> bindings = apiPolicy.getBindings();
if (null != bindings && !bindings.isEmpty()) {
ImmutableList.Builder<Binding> coreBindings = ImmutableList.builder();
for (Bindings binding : bindings) {
for (String member : binding.getMembers()) {
policyBuilder.addIdentity(Role.of(binding.getRole()), Identity.valueOf(member));
Binding.Builder bindingBuilder = Binding.newBuilder();
bindingBuilder.setRole(binding.getRole());
bindingBuilder.setMembers(binding.getMembers());
if (binding.getCondition() != null) {
Condition.Builder conditionBuilder = Condition.newBuilder();
conditionBuilder.setTitle(binding.getCondition().getTitle());
conditionBuilder.setDescription(binding.getCondition().getDescription());
conditionBuilder.setExpression(binding.getCondition().getExpression());
bindingBuilder.setCondition(conditionBuilder.build());
}
coreBindings.add(bindingBuilder.build());
}
policyBuilder.setBindings(coreBindings.build());
} else {
throw new IllegalStateException("Missing required bindings.");
}
return policyBuilder.setEtag(apiPolicy.getEtag()).build();
return policyBuilder.setEtag(apiPolicy.getEtag()).setVersion(apiPolicy.getVersion()).build();
}

static com.google.api.services.storage.model.Policy convertToApiPolicy(Policy policy) {
List<Bindings> bindings = new ArrayList<>(policy.getBindings().size());
for (Map.Entry<Role, Set<Identity>> entry : policy.getBindings().entrySet()) {
List<String> members = new ArrayList<>(entry.getValue().size());
for (Identity identity : entry.getValue()) {
members.add(identity.strValue());
List<Bindings> bindings = new ArrayList<>(policy.getBindingsList().size());
for (Binding binding : policy.getBindingsList()) {
Bindings apiBinding = new Bindings();
apiBinding.setRole(binding.getRole());
apiBinding.setMembers(new ArrayList<>(binding.getMembers()));
if (binding.getCondition() != null) {
Expr expr = new Expr();
expr.setTitle(binding.getCondition().getTitle());
expr.setDescription(binding.getCondition().getDescription());
expr.setExpression(binding.getCondition().getExpression());
apiBinding.setCondition(expr);
}
bindings.add(new Bindings().setMembers(members).setRole(entry.getKey().getValue()));
bindings.add(apiBinding);
}
return new com.google.api.services.storage.model.Policy()
.setBindings(bindings)
.setEtag(policy.getEtag());
.setEtag(policy.getEtag())
.setVersion(policy.getVersion());
}

private PolicyHelper() {
Expand Down
Expand Up @@ -269,6 +269,10 @@ public static BucketSourceOption metagenerationNotMatch(long metageneration) {
public static BucketSourceOption userProject(String userProject) {
return new BucketSourceOption(StorageRpc.Option.USER_PROJECT, userProject);
}

public static BucketSourceOption requestedPolicyVersion(long version) {
return new BucketSourceOption(StorageRpc.Option.REQUESTED_POLICY_VERSION, version);
}
}

/** Class for specifying listHmacKeys options */
Expand Down
Expand Up @@ -1376,11 +1376,16 @@ public Policy getIamPolicy(String bucket, Map<Option, ?> options) {
Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_GET_BUCKET_IAM_POLICY);
Scope scope = tracer.withSpan(span);
try {
return storage
.buckets()
.getIamPolicy(bucket)
.setUserProject(Option.USER_PROJECT.getString(options))
.execute();
Storage.Buckets.GetIamPolicy getIamPolicy =
storage
.buckets()
.getIamPolicy(bucket)
.setUserProject(Option.USER_PROJECT.getString(options));
if (null != Option.REQUESTED_POLICY_VERSION.getLong(options)) {
getIamPolicy.setOptionsRequestedPolicyVersion(
Option.REQUESTED_POLICY_VERSION.getLong(options).intValue());
}
return getIamPolicy.execute();
} catch (IOException ex) {
span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage()));
throw translate(ex);
Expand Down
Expand Up @@ -64,7 +64,8 @@ enum Option {
USER_PROJECT("userProject"),
KMS_KEY_NAME("kmsKeyName"),
SERVICE_ACCOUNT_EMAIL("serviceAccount"),
SHOW_DELETED_KEYS("showDeletedKeys");
SHOW_DELETED_KEYS("showDeletedKeys"),
REQUESTED_POLICY_VERSION("optionsRequestedPolicyVersion");

private final String value;

Expand Down
Expand Up @@ -41,6 +41,7 @@ public void testEquivalence() {
Identity.user("test1@gmail.com"),
Identity.user("test2@gmail.com"))
.setEtag(ETAG)
.setVersion(1)
.build();
com.google.api.services.storage.model.Policy apiPolicy =
new com.google.api.services.storage.model.Policy()
Expand All @@ -53,7 +54,8 @@ public void testEquivalence() {
.setMembers(
ImmutableList.of("user:test1@gmail.com", "user:test2@gmail.com"))
.setRole("roles/storage.objectAdmin")))
.setEtag(ETAG);
.setEtag(ETAG)
.setVersion(1);

Policy actualLibPolicy = PolicyHelper.convertFromApiPolicy(apiPolicy);
com.google.api.services.storage.model.Policy actualApiPolicy =
Expand Down
Expand Up @@ -288,6 +288,7 @@ public class StorageImplTest {
Identity.user("test1@gmail.com"),
Identity.user("test2@gmail.com"))
.setEtag(POLICY_ETAG1)
.setVersion(1)
.build();

private static final ServiceAccount SERVICE_ACCOUNT = ServiceAccount.of("test@google.com");
Expand All @@ -302,7 +303,8 @@ public class StorageImplTest {
new Bindings()
.setMembers(ImmutableList.of("user:test1@gmail.com", "user:test2@gmail.com"))
.setRole("roles/storage.objectAdmin")))
.setEtag(POLICY_ETAG1);
.setEtag(POLICY_ETAG1)
.setVersion(1);

private static final String PRIVATE_KEY_STRING =
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoG"
Expand Down Expand Up @@ -2891,7 +2893,8 @@ public void testSetIamPolicy() {
new Bindings()
.setMembers(ImmutableList.of("group:test-group@gmail.com"))
.setRole("roles/storage.admin")))
.setEtag(POLICY_ETAG1);
.setEtag(POLICY_ETAG1)
.setVersion(1);
// postCommitApiPolicy is identical but for the etag, which has been updated.
com.google.api.services.storage.model.Policy postCommitApiPolicy =
new com.google.api.services.storage.model.Policy()
Expand All @@ -2907,7 +2910,8 @@ public void testSetIamPolicy() {
new Bindings()
.setMembers(ImmutableList.of("group:test-group@gmail.com"))
.setRole("roles/storage.admin")))
.setEtag(POLICY_ETAG2);
.setEtag(POLICY_ETAG2)
.setVersion(1);
Policy postCommitLibPolicy =
Policy.newBuilder()
.addIdentity(StorageRoles.objectViewer(), Identity.allUsers())
Expand All @@ -2917,6 +2921,7 @@ public void testSetIamPolicy() {
Identity.user("test2@gmail.com"))
.addIdentity(StorageRoles.admin(), Identity.group("test-group@gmail.com"))
.setEtag(POLICY_ETAG2)
.setVersion(1)
.build();

EasyMock.expect(storageRpcMock.getIamPolicy(BUCKET_NAME1, EMPTY_RPC_OPTIONS))
Expand Down

0 comments on commit 8256f6d

Please sign in to comment.