Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add IAM Conditions support #120

Merged
merged 18 commits into from Feb 28, 2020
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