Skip to content

Commit

Permalink
feat: implement GrpcStorageImpl#*HmacKey
Browse files Browse the repository at this point in the history
* GrpcStorageImpl#createHmacKey
* GrpcStorageImpl#getHmacKey
* GrpcStorageImpl#updateHmacKey
* GrpcStorageImpl#deleteHmacKey

Add tests for each Hmac method to ITGrpcTest
  • Loading branch information
BenWhitehead committed Aug 19, 2022
1 parent 317d3ec commit 4d94420
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ private com.google.api.services.storage.model.HmacKeyMetadata hmacKeyMetadataEnc
to.setId(from.getId());
to.setProjectId(from.getProjectId());
ifNonNull(from.getServiceAccount(), ServiceAccount::getEmail, to::setServiceAccountEmail);
ifNonNull(from.getState(), Object::toString, to::setState);
ifNonNull(from.getState(), Enum::name, to::setState);
ifNonNull(from.getCreateTimeOffsetDateTime(), dateTimeCodec::encode, to::setTimeCreated);
ifNonNull(from.getUpdateTimeOffsetDateTime(), dateTimeCodec::encode, to::setUpdated);
return to;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.google.cloud.storage.Utils.durationMillisCodec;
import static com.google.cloud.storage.Utils.ifNonNull;
import static com.google.cloud.storage.Utils.lift;
import static com.google.cloud.storage.Utils.projectNameCodec;
import static com.google.cloud.storage.Utils.toImmutableListOf;
import static com.google.cloud.storage.Utils.todo;

Expand Down Expand Up @@ -678,12 +679,12 @@ private BucketInfo.LifecycleRule lifecycleRuleDecode(Bucket.Lifecycle.Rule from)

private HmacKeyMetadata hmacKeyMetadataEncode(HmacKey.HmacKeyMetadata from) {
HmacKeyMetadata.Builder to = HmacKeyMetadata.newBuilder();
to.setAccessId(from.getAccessId());
// TODO etag
to.setId(from.getId());
to.setProject(from.getProjectId());
ifNonNull(from.getEtag(), to::setEtag);
ifNonNull(from.getId(), to::setId);
ifNonNull(from.getAccessId(), to::setAccessId);
ifNonNull(from.getProjectId(), projectNameCodec::encode, to::setProject);
ifNonNull(from.getServiceAccount(), ServiceAccount::getEmail, to::setServiceAccountEmail);
ifNonNull(from.getState(), java.lang.Object::toString, to::setState);
ifNonNull(from.getState(), Enum::name, to::setState);
ifNonNull(from.getCreateTimeOffsetDateTime(), timestampCodec::encode, to::setCreateTime);
ifNonNull(from.getUpdateTimeOffsetDateTime(), timestampCodec::encode, to::setUpdateTime);
return to.build();
Expand All @@ -694,7 +695,7 @@ private HmacKey.HmacKeyMetadata hmacKeyMetadataDecode(HmacKeyMetadata from) {
.setAccessId(from.getAccessId())
.setCreateTimeOffsetDateTime(timestampCodec.decode(from.getCreateTime()))
.setId(from.getId())
.setProjectId(from.getProject())
.setProjectId(projectNameCodec.decode(from.getProject()))
.setState(HmacKey.HmacKeyState.valueOf(from.getState()))
.setUpdateTimeOffsetDateTime(timestampCodec.decode(from.getUpdateTime()))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import static com.google.cloud.storage.Utils.bucketNameCodec;
import static com.google.cloud.storage.Utils.ifNonNull;
import static com.google.cloud.storage.Utils.projectNameCodec;
import static com.google.cloud.storage.Utils.todo;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.util.Objects.requireNonNull;
Expand Down Expand Up @@ -46,23 +45,28 @@
import com.google.cloud.storage.UnifiedOpts.BucketSourceOpt;
import com.google.cloud.storage.UnifiedOpts.BucketTargetOpt;
import com.google.cloud.storage.UnifiedOpts.HmacKeyListOpt;
import com.google.cloud.storage.UnifiedOpts.HmacKeySourceOpt;
import com.google.cloud.storage.UnifiedOpts.HmacKeyTargetOpt;
import com.google.cloud.storage.UnifiedOpts.ObjectListOpt;
import com.google.cloud.storage.UnifiedOpts.ObjectSourceOpt;
import com.google.cloud.storage.UnifiedOpts.ObjectTargetOpt;
import com.google.cloud.storage.UnifiedOpts.Opts;
import com.google.cloud.storage.UnifiedOpts.ProjectId;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteStreams;
import com.google.protobuf.ByteString;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.storage.v2.ComposeObjectRequest;
import com.google.storage.v2.ComposeObjectRequest.SourceObject;
import com.google.storage.v2.CreateBucketRequest;
import com.google.storage.v2.CreateHmacKeyRequest;
import com.google.storage.v2.DeleteBucketRequest;
import com.google.storage.v2.DeleteHmacKeyRequest;
import com.google.storage.v2.DeleteObjectRequest;
import com.google.storage.v2.GetBucketRequest;
import com.google.storage.v2.GetHmacKeyRequest;
import com.google.storage.v2.GetObjectRequest;
import com.google.storage.v2.GetServiceAccountRequest;
import com.google.storage.v2.ListBucketsRequest;
Expand All @@ -78,6 +82,7 @@
import com.google.storage.v2.StorageClient.ListObjectsPage;
import com.google.storage.v2.StorageClient.ListObjectsPagedResponse;
import com.google.storage.v2.UpdateBucketRequest;
import com.google.storage.v2.UpdateHmacKeyRequest;
import com.google.storage.v2.UpdateObjectRequest;
import com.google.storage.v2.WriteObjectRequest;
import com.google.storage.v2.WriteObjectResponse;
Expand Down Expand Up @@ -122,7 +127,7 @@ final class GrpcStorageImpl extends BaseService<StorageOptions> implements Stora
private final GrpcRetryAlgorithmManager retryAlgorithmManager;
private final SyntaxDecoders syntaxDecoders;

private final transient ProjectId defaultProjectId;
@Deprecated private final transient ProjectId defaultProjectId;

GrpcStorageImpl(GrpcStorageOptions options, GrpcStorageStub grpcStorageStub) {
super(options);
Expand Down Expand Up @@ -372,9 +377,12 @@ public Page<Bucket> list(BucketListOption... options) {
Opts<BucketListOpt> opts = Opts.unwrap(options);
GrpcCallContext grpcCallContext =
opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault());
ListBucketsRequest.Builder builder =
ListBucketsRequest.newBuilder().setParent(projectNameCodec.encode(defaultProjectId.val));
ListBucketsRequest request = opts.listBucketsRequest().apply(builder).build();
ListBucketsRequest request =
defaultProjectId
.listBuckets()
.andThen(opts.listBucketsRequest())
.apply(ListBucketsRequest.newBuilder())
.build();
ListBucketsPagedResponse call = listBucketsCallable.call(request, grpcCallContext);
ListBucketsPage page = call.getPage();
return new TransformingPageDecorator<>(page, syntaxDecoders.bucket);
Expand Down Expand Up @@ -840,7 +848,27 @@ public List<Acl> listAcls(BlobId blob) {

@Override
public HmacKey createHmacKey(ServiceAccount serviceAccount, CreateHmacKeyOption... options) {
return todo();
Opts<HmacKeyTargetOpt> opts = Opts.unwrap(options);
GrpcCallContext grpcCallContext =
opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault());
CreateHmacKeyRequest request =
defaultProjectId
.createHmacKey()
.andThen(opts.createHmacKeysRequest())
.apply(CreateHmacKeyRequest.newBuilder())
.setServiceAccountEmail(serviceAccount.getEmail())
.build();
return Retrying.run(
getOptions(),
retryAlgorithmManager.getFor(request),
() -> grpcStorageStub.createHmacKeyCallable().call(request, grpcCallContext),
resp -> {
ByteString secretKeyBytes = resp.getSecretKeyBytes();
String b64SecretKey = BaseEncoding.base64().encode(secretKeyBytes.toByteArray());
return HmacKey.newBuilder(b64SecretKey)
.setMetadata(codecs.hmacKeyMetadata().decode(resp.getMetadata()))
.build();
});
}

@Override
Expand All @@ -851,19 +879,34 @@ public Page<HmacKeyMetadata> listHmacKeys(ListHmacKeysOption... options) {
GrpcCallContext grpcCallContext =
opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault());

ProjectId projectId = opts.projectId().orElse(defaultProjectId);

ListHmacKeysRequest.Builder builder =
projectId.listHmacKeys().apply(ListHmacKeysRequest.newBuilder());
ListHmacKeysRequest request = opts.listHmacKeysRequest().apply(builder).build();
ListHmacKeysRequest request =
defaultProjectId
.listHmacKeys()
.andThen(opts.listHmacKeysRequest())
.apply(ListHmacKeysRequest.newBuilder())
.build();
ListHmacKeysPagedResponse call = listHmacKeysCallable.call(request, grpcCallContext);
ListHmacKeysPage page = call.getPage();
return new TransformingPageDecorator<>(page, codecs.hmacKeyMetadata());
}

@Override
public HmacKeyMetadata getHmacKey(String accessId, GetHmacKeyOption... options) {
return todo();
Opts<HmacKeySourceOpt> opts = Opts.unwrap(options);
GrpcCallContext grpcCallContext =
opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault());
GetHmacKeyRequest request =
defaultProjectId
.getHmacKey()
.andThen(opts.getHmacKeysRequest())
.apply(GetHmacKeyRequest.newBuilder())
.setAccessId(accessId)
.build();
return Retrying.run(
getOptions(),
retryAlgorithmManager.getFor(request),
() -> grpcStorageStub.getHmacKeyCallable().call(request, grpcCallContext),
codecs.hmacKeyMetadata());
}

@Override
Expand All @@ -889,7 +932,21 @@ public void deleteHmacKey(HmacKeyMetadata hmacKeyMetadata, DeleteHmacKeyOption..
@Override
public HmacKeyMetadata updateHmacKeyState(
HmacKeyMetadata hmacKeyMetadata, HmacKeyState state, UpdateHmacKeyOption... options) {
return todo();
Opts<HmacKeyTargetOpt> opts = Opts.unwrap(options);
GrpcCallContext grpcCallContext =
opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault());
com.google.storage.v2.HmacKeyMetadata encode =
codecs.hmacKeyMetadata().encode(hmacKeyMetadata).toBuilder().setState(state.name()).build();

UpdateHmacKeyRequest.Builder builder =
opts.updateHmacKeysRequest().apply(UpdateHmacKeyRequest.newBuilder()).setHmacKey(encode);
UpdateHmacKeyRequest request =
builder.setUpdateMask(FieldMask.newBuilder().addPaths("state").build()).build();
return Retrying.run(
getOptions(),
retryAlgorithmManager.getFor(request),
() -> grpcStorageStub.updateHmacKeyCallable().call(request, grpcCallContext),
codecs.hmacKeyMetadata());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ public Mapper<ListObjectsRequest.Builder> listObjects() {
*/
@Deprecated
static final class ProjectId extends RpcOptVal<String>
implements HmacKeySourceOpt, HmacKeyTargetOpt, HmacKeyListOpt {
implements HmacKeySourceOpt, HmacKeyTargetOpt, HmacKeyListOpt, BucketListOpt {
private static final long serialVersionUID = 1471462503030451598L;

private ProjectId(String val) {
Expand All @@ -1122,9 +1122,14 @@ public Mapper<GetHmacKeyRequest.Builder> getHmacKey() {
}

@Override
public Mapper<DeleteHmacKeyRequest.Builder> deleteHmacKey() {
public Mapper<CreateHmacKeyRequest.Builder> createHmacKey() {
return b -> b.setProject(projectNameCodec.encode(val));
}

@Override
public Mapper<ListBucketsRequest.Builder> listBuckets() {
return b -> b.setParent(projectNameCodec.encode(val));
}
}

static final class Projection extends RpcOptVal<String> implements BucketTargetOpt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,19 @@
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketFixture;
import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.HmacKey;
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
import com.google.cloud.storage.HmacKey.HmacKeyState;
import com.google.cloud.storage.ServiceAccount;
import com.google.cloud.storage.Storage.CreateHmacKeyOption;
import com.google.cloud.storage.Storage.ListHmacKeysOption;
import com.google.cloud.storage.StorageFixture;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.storage.conformance.retry.CleanupStrategy;
import com.google.cloud.storage.conformance.retry.TestBench;
import com.google.cloud.storage.testing.RemoteStorageHelper;
import com.google.common.collect.ImmutableList;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
import org.junit.ClassRule;
import org.junit.Test;
Expand Down Expand Up @@ -86,4 +93,67 @@ public void listBuckets() {

assertThat(bucketNames).contains(bucketFixture.getBucketInfo().getName());
}

@Test
public void createHmacKey() {
ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
HmacKey hmacKey = storageFixture.getInstance().createHmacKey(serviceAccount);
assertThat(hmacKey).isNotNull();
assertThat(hmacKey.getSecretKey()).isNotNull();
assertThat(hmacKey.getMetadata().getServiceAccount()).isEqualTo(serviceAccount);
}

@Test
public void getHmacKey() {
ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
HmacKey hmacKey = storageFixture.getInstance().createHmacKey(serviceAccount);
HmacKeyMetadata actual =
storageFixture.getInstance().getHmacKey(hmacKey.getMetadata().getAccessId());
assertThat(actual).isEqualTo(hmacKey.getMetadata());
}

@Test
public void listHmacKeys() {
ImmutableList<HmacKey> keys =
IntStream.rangeClosed(1, 4)
.mapToObj(i -> ServiceAccount.of(String.format("x-%[email protected]", i)))
.map(
sa ->
storageFixture
.getInstance()
.createHmacKey(sa, CreateHmacKeyOption.projectId("proj")))
.collect(ImmutableList.toImmutableList());

ImmutableList<HmacKeyMetadata> expected =
keys.stream().map(HmacKey::getMetadata).collect(ImmutableList.toImmutableList());

Page<HmacKeyMetadata> page =
storageFixture.getInstance().listHmacKeys(ListHmacKeysOption.projectId("proj"));

ImmutableList<HmacKeyMetadata> actual =
StreamSupport.stream(page.iterateAll().spliterator(), false)
.collect(ImmutableList.toImmutableList());

assertThat(actual).isEqualTo(expected);
}

@Test
public void updateHmacKey() {
ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
HmacKey hmacKey = storageFixture.getInstance().createHmacKey(serviceAccount);
HmacKeyMetadata updated =
storageFixture
.getInstance()
.updateHmacKeyState(hmacKey.getMetadata(), HmacKeyState.INACTIVE);
assertThat(updated.getServiceAccount()).isEqualTo(serviceAccount);
assertThat(updated.getState()).isEqualTo(HmacKeyState.INACTIVE);
}

@Test
public void deleteHmacKey() {
ServiceAccount serviceAccount = ServiceAccount.of("[email protected]");
HmacKey hmacKey = storageFixture.getInstance().createHmacKey(serviceAccount);
storageFixture.getInstance().updateHmacKeyState(hmacKey.getMetadata(), HmacKeyState.INACTIVE);
storageFixture.getInstance().deleteHmacKey(hmacKey.getMetadata());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtyp
(accessId, projectID, state, createTime, updateTime, email) ->
HmacKeyMetadata.newBuilder()
.setAccessId(accessId)
.setProject(projectID.get())
.setProject("projects/" + projectID.get())
.setId(projectID.get() + "/" + accessId)
.setState(state.toString())
.setCreateTime(createTime)
Expand Down

0 comments on commit 4d94420

Please sign in to comment.