Skip to content

Commit

Permalink
feat: Implement manual layer on top of CMEK protos
Browse files Browse the repository at this point in the history
  • Loading branch information
igorbernstein2 authored and ad548 committed Mar 2, 2021
1 parent 7574915 commit 1bfc4f7
Show file tree
Hide file tree
Showing 21 changed files with 849 additions and 10 deletions.
5 changes: 5 additions & 0 deletions google-cloud-bigtable/pom.xml
Expand Up @@ -211,6 +211,11 @@
<artifactId>truth</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth.extensions</groupId>
<artifactId>truth-proto-extension</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
Expand Down
Expand Up @@ -19,6 +19,7 @@
import com.google.api.core.ApiFunction;
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.api.core.BetaApi;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.api.gax.rpc.ApiExceptions;
import com.google.api.gax.rpc.NotFoundException;
Expand All @@ -30,6 +31,8 @@
import com.google.bigtable.admin.v2.ListBackupsRequest;
import com.google.bigtable.admin.v2.ListTablesRequest;
import com.google.bigtable.admin.v2.RestoreTableMetadata;
import com.google.bigtable.admin.v2.Table.ClusterState;
import com.google.bigtable.admin.v2.Table.View;
import com.google.cloud.Policy;
import com.google.cloud.Policy.DefaultMarshaller;
import com.google.cloud.bigtable.admin.v2.BaseBigtableTableAdminClient.ListBackupsPage;
Expand All @@ -40,6 +43,7 @@
import com.google.cloud.bigtable.admin.v2.models.Backup;
import com.google.cloud.bigtable.admin.v2.models.CreateBackupRequest;
import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest;
import com.google.cloud.bigtable.admin.v2.models.EncryptionInfo;
import com.google.cloud.bigtable.admin.v2.models.GCRules;
import com.google.cloud.bigtable.admin.v2.models.ModifyColumnFamiliesRequest;
import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken;
Expand All @@ -49,6 +53,8 @@
import com.google.cloud.bigtable.admin.v2.models.UpdateBackupRequest;
import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.iam.v1.GetIamPolicyRequest;
Expand All @@ -60,6 +66,7 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nonnull;

Expand Down Expand Up @@ -519,6 +526,60 @@ private ApiFuture<Table> getTableAsync(
return transformToTableResponse(this.stub.getTableCallable().futureCall(request));
}

/**
* Gets the current encryption info for the table across all of the clusters.
*
* <p>The returned Map will be keyed by cluster id and contain a status for all of the keys in
* use.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public Map<String, List<EncryptionInfo>> getEncryptionInfo(String tableId) {
return ApiExceptions.callAndTranslateApiException(getEncryptionInfoAsync(tableId));
}

/**
* Asynchronously gets the current encryption info for the table across all of the clusters.
*
* <p>The returned Map will be keyed by cluster id and contain a status for all of the keys in
* use.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public ApiFuture<Map<String, List<EncryptionInfo>>> getEncryptionInfoAsync(String tableId) {
GetTableRequest request =
GetTableRequest.newBuilder()
.setName(getTableName(tableId))
.setView(View.ENCRYPTION_VIEW)
.build();
return ApiFutures.transform(
this.stub.getTableCallable().futureCall(request),
new ApiFunction<com.google.bigtable.admin.v2.Table, Map<String, List<EncryptionInfo>>>() {
@Override
public Map<String, List<EncryptionInfo>> apply(com.google.bigtable.admin.v2.Table table) {
ImmutableMap.Builder<String, List<EncryptionInfo>> result = ImmutableMap.builder();

for (Map.Entry<String, ClusterState> entry : table.getClusterStatesMap().entrySet()) {
ImmutableList.Builder<EncryptionInfo> infos = ImmutableList.builder();

for (com.google.bigtable.admin.v2.EncryptionInfo infoProto :
entry.getValue().getEncryptionInfoList()) {
infos.add(EncryptionInfo.fromProto(infoProto));
}

result.put(entry.getKey(), infos.build());
}

return result.build();
}
},
MoreExecutors.directExecutor());
}

/**
* Lists all table IDs in the instance.
*
Expand Down
Expand Up @@ -16,6 +16,7 @@

package com.google.cloud.bigtable.admin.v2.models;

import com.google.api.core.BetaApi;
import com.google.api.core.InternalApi;
import com.google.bigtable.admin.v2.BackupName;
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
Expand Down Expand Up @@ -142,6 +143,22 @@ public State getState() {
return State.fromProto(proto.getState());
}

/**
* Get the encryption information for the backup.
*
* <p>If encryption_type is CUSTOMER_MANAGED_ENCRYPTION, kms_key_version will be filled in with
* status UNKNOWN.
*
* <p>If encryption_type is GOOGLE_DEFAULT_ENCRYPTION, all other fields will have default value.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public EncryptionInfo getEncryptionInfo() {
return EncryptionInfo.fromProto(proto.getEncryptionInfo());
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.cloud.bigtable.admin.v2.models;

import com.google.api.core.BetaApi;
import com.google.api.core.InternalApi;
import com.google.bigtable.admin.v2.ClusterName;
import com.google.bigtable.admin.v2.LocationName;
Expand Down Expand Up @@ -156,6 +157,20 @@ public StorageType getStorageType() {
return StorageType.fromProto(stateProto.getDefaultStorageType());
}

/**
* Google Cloud Key Management Service (KMS) settings for a CMEK-protected Bigtable cluster.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public String getKmsKeyName() {
if (stateProto.hasEncryptionConfig()) {
return stateProto.getEncryptionConfig().getKmsKeyName();
}
return null;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
Expand Up @@ -17,6 +17,7 @@

import static com.google.cloud.bigtable.admin.v2.models.StorageType.SSD;

import com.google.api.core.BetaApi;
import com.google.api.core.InternalApi;
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
import com.google.common.base.Preconditions;
Expand Down Expand Up @@ -104,6 +105,19 @@ public CreateClusterRequest setStorageType(@Nonnull StorageType storageType) {
return this;
}

/**
* Sets the Google Cloud Key Management Service (KMS) key for a CMEK-protected Bigtable.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public CreateClusterRequest setKmsKeyName(@Nonnull String kmsKeyName) {
Preconditions.checkNotNull(kmsKeyName);
proto.getClusterBuilder().getEncryptionConfigBuilder().setKmsKeyName(kmsKeyName);
return this;
}

/**
* Creates the request protobuf. This method is considered an internal implementation detail and
* not meant to be used by applications.
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.cloud.bigtable.admin.v2.models;

import com.google.api.core.BetaApi;
import com.google.api.core.InternalApi;
import com.google.bigtable.admin.v2.Instance.Type;
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
Expand Down Expand Up @@ -147,6 +148,38 @@ public CreateInstanceRequest addCluster(
return this;
}

/**
* Adds a CMEK protected cluster using the specified KMS key name.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*
* @param clusterId the name of the cluster.
* @param zone the zone where the cluster will be created.
* @param serveNodes the number of nodes that cluster will contain. DEVELOPMENT instance clusters
* must have exactly one node.
* @param storageType the type of storage used by this cluster to serve its parent instance's
* tables.
* @param kmsKeyName the full name of the KMS key name to use.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public CreateInstanceRequest addCmekCluster(
@Nonnull String clusterId,
@Nonnull String zone,
int serveNodes,
@Nonnull StorageType storageType,
@Nonnull String kmsKeyName) {
CreateClusterRequest clusterRequest =
CreateClusterRequest.of("ignored-instance-id", clusterId)
.setZone(zone)
.setServeNodes(serveNodes)
.setStorageType(storageType)
.setKmsKeyName(kmsKeyName);
clusterRequests.add(clusterRequest);

return this;
}

/**
* Adds a DEVELOPMENT cluster to the instance request.
*
Expand Down
@@ -0,0 +1,113 @@
/*
* Copyright 2020 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
*
* https://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.
*/
package com.google.cloud.bigtable.admin.v2.models;

import com.google.api.core.BetaApi;
import com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType;
import com.google.cloud.bigtable.common.Status;
import com.google.common.base.Objects;

/**
* Encryption information for a given resource.
*
* <p>If this resource is protected with customer managed encryption, the in-use Google Cloud Key
* Management Service (KMS) key versions will be specified along with their status.
*
* <p>CMEK is not currently available to end users. This feature might be changed in
* backward-incompatible ways and is not currently subject to any SLA or deprecation policy.
*/
@BetaApi("CMEK is not yet stable and might change in the future")
public final class EncryptionInfo {
public enum Type {
/** Encryption type was not specified, though data at rest remains encrypted. */
ENCRYPTION_TYPE_UNSPECIFIED(
com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType.ENCRYPTION_TYPE_UNSPECIFIED),
/**
* The data backing this resource is encrypted at rest with a key that is fully managed by
* Google. No key version or status will be populated.
*/
GOOGLE_DEFAULT_ENCRYPTION(
com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType.GOOGLE_DEFAULT_ENCRYPTION),
/**
* The data backing this resource is encrypted at rest with a key that is fully managed by
* Google. No key version or status will be populated. This is the default state.
*/
CUSTOMER_MANAGED_ENCRYPTION(
com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION),
/** Type not known by the client, please upgrade your client */
UNRECOGNIZED(com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType.UNRECOGNIZED);

private final com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType proto;

Type(EncryptionType proto) {
this.proto = proto;
}

/** Wraps the EncryptionInfo protobuf. */
public static Type fromProto(com.google.bigtable.admin.v2.EncryptionInfo.EncryptionType proto) {
for (Type type : values()) {
if (Objects.equal(type.proto, proto)) {
return type;
}
}
return UNRECOGNIZED;
}
}

private com.google.bigtable.admin.v2.EncryptionInfo proto;

public static EncryptionInfo fromProto(com.google.bigtable.admin.v2.EncryptionInfo proto) {
return new EncryptionInfo(proto);
}

private EncryptionInfo(com.google.bigtable.admin.v2.EncryptionInfo proto) {
this.proto = proto;
}

public Type getType() {
return EncryptionInfo.Type.fromProto(proto.getEncryptionType());
}

public String getKmsKeyVersion() {
return proto.getKmsKeyVersion();
}

public Status getStatus() {
return Status.fromProto(proto.getEncryptionStatus());
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EncryptionInfo that = (EncryptionInfo) o;
return Objects.equal(proto, that.proto);
}

@Override
public int hashCode() {
return Objects.hashCode(proto);
}

@Override
public String toString() {
return proto.toString();
}
}

0 comments on commit 1bfc4f7

Please sign in to comment.