diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
index b10f56194423..30f9ce61f1fc 100644
--- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
+++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
@@ -655,6 +655,12 @@ public Builder setRetentionPeriod(Long retentionPeriod) {
return this;
}
+ @Override
+ public Builder setIamConfiguration(IamConfiguration iamConfiguration) {
+ infoBuilder.setIamConfiguration(iamConfiguration);
+ return this;
+ }
+
@Override
public Bucket build() {
return new Bucket(storage, infoBuilder);
diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
index caceb2f19d2a..c8d1d07a274b 100644
--- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
+++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
@@ -95,6 +95,118 @@ public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo)
private final Long retentionEffectiveTime;
private final Boolean retentionPolicyIsLocked;
private final Long retentionPeriod;
+ private final IamConfiguration iamConfiguration;
+
+ /**
+ * The Bucket's IAM Configuration.
+ *
+ * @see Bucket Policy Only
+ */
+ public static class IamConfiguration implements Serializable {
+ private static final long serialVersionUID = -8671736104909424616L;
+
+ private Boolean isBucketPolicyOnlyEnabled;
+ private Long bucketPolicyOnlyLockedTime;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ IamConfiguration other = (IamConfiguration) o;
+ return Objects.equals(toPb(), other.toPb());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(isBucketPolicyOnlyEnabled, bucketPolicyOnlyLockedTime);
+ }
+
+ private IamConfiguration(Builder builder) {
+ this.isBucketPolicyOnlyEnabled = builder.isBucketPolicyOnlyEnabled;
+ this.bucketPolicyOnlyLockedTime = builder.bucketPolicyOnlyLockedTime;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ Builder builder = new Builder();
+ builder.isBucketPolicyOnlyEnabled = isBucketPolicyOnlyEnabled;
+ builder.bucketPolicyOnlyLockedTime = bucketPolicyOnlyLockedTime;
+ return builder;
+ }
+
+ public Boolean isBucketPolicyOnlyEnabled() {
+ return isBucketPolicyOnlyEnabled;
+ }
+
+ public Long getBucketPolicyOnlyLockedTime() {
+ return bucketPolicyOnlyLockedTime;
+ }
+
+ Bucket.IamConfiguration toPb() {
+ Bucket.IamConfiguration iamConfiguration = new Bucket.IamConfiguration();
+
+ Bucket.IamConfiguration.BucketPolicyOnly bucketPolicyOnly =
+ new Bucket.IamConfiguration.BucketPolicyOnly();
+ bucketPolicyOnly.setEnabled(isBucketPolicyOnlyEnabled);
+ bucketPolicyOnly.setLockedTime(
+ bucketPolicyOnlyLockedTime == null ? null : new DateTime(bucketPolicyOnlyLockedTime));
+
+ iamConfiguration.setBucketPolicyOnly(bucketPolicyOnly);
+
+ return iamConfiguration;
+ }
+
+ static IamConfiguration fromPb(Bucket.IamConfiguration iamConfiguration) {
+ Bucket.IamConfiguration.BucketPolicyOnly bucketPolicyOnly =
+ iamConfiguration.getBucketPolicyOnly();
+ DateTime lockedTime = bucketPolicyOnly.getLockedTime();
+
+ return newBuilder()
+ .setIsBucketPolicyOnlyEnabled(bucketPolicyOnly.getEnabled())
+ .setBucketPolicyOnlyLockedTime(lockedTime == null ? null : lockedTime.getValue())
+ .build();
+ }
+
+ /** Builder for {@code IamConfiguration} */
+ public static class Builder {
+ private Boolean isBucketPolicyOnlyEnabled;
+ private Long bucketPolicyOnlyLockedTime;
+
+ /**
+ * Sets whether BucketPolicyOnly is enabled for this bucket. When this is enabled, access to
+ * the bucket will be configured through IAM, and legacy ACL policies will not work. When this
+ * is first enabled, {@code bucketPolicyOnly.lockedTime} will be set by the API automatically.
+ * This field can then be disabled until the time specified, after which it will become
+ * immutable and calls to change it will fail. If this is enabled, calls to access legacy ACL
+ * information will fail.
+ */
+ public Builder setIsBucketPolicyOnlyEnabled(Boolean isBucketPolicyOnlyEnabled) {
+ this.isBucketPolicyOnlyEnabled = isBucketPolicyOnlyEnabled;
+ return this;
+ }
+
+ /**
+ * Sets the deadline for switching {@code bucketPolicyOnly.enabled} back to false. After this
+ * time passes, calls to do so will fail. This is package-private, since in general this field
+ * should never be set by a user--it's automatically set by the backend when {@code enabled}
+ * is set to true.
+ */
+ Builder setBucketPolicyOnlyLockedTime(Long bucketPolicyOnlyLockedTime) {
+ this.bucketPolicyOnlyLockedTime = bucketPolicyOnlyLockedTime;
+ return this;
+ }
+
+ /** Builds an {@code IamConfiguration} object */
+ public IamConfiguration build() {
+ return new IamConfiguration(this);
+ }
+ }
+ }
/**
* Lifecycle rule for a bucket. Allows supported Actions, such as deleting and changing storage
@@ -786,6 +898,15 @@ public abstract static class Builder {
@BetaApi
public abstract Builder setRetentionPeriod(Long retentionPeriod);
+ /**
+ * Sets the IamConfiguration to specify whether IAM access should be enabled.
+ *
+ * @see Bucket Policy
+ * Only
+ */
+ @BetaApi
+ public abstract Builder setIamConfiguration(IamConfiguration iamConfiguration);
+
/** Creates a {@code BucketInfo} object. */
public abstract BucketInfo build();
}
@@ -816,6 +937,7 @@ static final class BuilderImpl extends Builder {
private Long retentionEffectiveTime;
private Boolean retentionPolicyIsLocked;
private Long retentionPeriod;
+ private IamConfiguration iamConfiguration;
BuilderImpl(String name) {
this.name = name;
@@ -846,6 +968,7 @@ static final class BuilderImpl extends Builder {
retentionEffectiveTime = bucketInfo.retentionEffectiveTime;
retentionPolicyIsLocked = bucketInfo.retentionPolicyIsLocked;
retentionPeriod = bucketInfo.retentionPeriod;
+ iamConfiguration = bucketInfo.iamConfiguration;
}
@Override
@@ -998,6 +1121,12 @@ public Builder setRetentionPeriod(Long retentionPeriod) {
return this;
}
+ @Override
+ public Builder setIamConfiguration(IamConfiguration iamConfiguration) {
+ this.iamConfiguration = iamConfiguration;
+ return this;
+ }
+
@Override
public BucketInfo build() {
checkNotNull(name);
@@ -1030,6 +1159,7 @@ public BucketInfo build() {
retentionEffectiveTime = builder.retentionEffectiveTime;
retentionPolicyIsLocked = builder.retentionPolicyIsLocked;
retentionPeriod = builder.retentionPeriod;
+ iamConfiguration = builder.iamConfiguration;
}
/** Returns the service-generated id for the bucket. */
@@ -1268,6 +1398,12 @@ public Long getRetentionPeriod() {
return retentionPeriod;
}
+ /** Returns the IAM configuration */
+ @BetaApi
+ public IamConfiguration getIamConfiguration() {
+ return iamConfiguration;
+ }
+
/** Returns a builder for the current bucket. */
public Builder toBuilder() {
return new BuilderImpl(this);
@@ -1405,6 +1541,9 @@ public Rule apply(LifecycleRule lifecycleRule) {
bucketPb.setRetentionPolicy(retentionPolicy);
}
}
+ if (iamConfiguration != null) {
+ bucketPb.setIamConfiguration(iamConfiguration.toPb());
+ }
return bucketPb;
}
@@ -1526,6 +1665,10 @@ public DeleteRule apply(Rule rule) {
builder.setRetentionPeriod(retentionPolicy.getRetentionPeriod());
}
}
+ Bucket.IamConfiguration iamConfiguration = bucketPb.getIamConfiguration();
+ if (iamConfiguration != null) {
+ builder.setIamConfiguration(IamConfiguration.fromPb(iamConfiguration));
+ }
return builder.build();
}
}
diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
index 6ce9ca8c6e2a..534b1e0810aa 100644
--- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
+++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
@@ -96,7 +96,8 @@ enum BucketField implements FieldSelector {
ENCRYPTION("encryption"),
BILLING("billing"),
DEFAULT_EVENT_BASED_HOLD("defaultEventBasedHold"),
- RETENTION_POLICY("retentionPolicy");
+ RETENTION_POLICY("retentionPolicy"),
+ IAMCONFIGURATION("iamConfiguration");
static final List extends FieldSelector> REQUIRED_FIELDS = ImmutableList.of(NAME);
@@ -204,6 +205,18 @@ public static BucketTargetOption metagenerationNotMatch() {
public static BucketTargetOption userProject(String userProject) {
return new BucketTargetOption(StorageRpc.Option.USER_PROJECT, userProject);
}
+
+ /**
+ * Returns an option to define the projection in the API request. In some cases this option may
+ * be needed to be set to `noAcl` to omit ACL data from the response. The default value is
+ * `full`
+ *
+ * @see Buckets:
+ * patch
+ */
+ public static BucketTargetOption projection(String projection) {
+ return new BucketTargetOption(StorageRpc.Option.PROJECTION, projection);
+ }
}
/** Class for specifying bucket source options. */
diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java
index a10b4ef8a973..072b65227be8 100644
--- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java
+++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java
@@ -85,6 +85,7 @@
public class HttpStorageRpc implements StorageRpc {
public static final String DEFAULT_PROJECTION = "full";
+ public static final String NO_ACL_PROJECTION = "noAcl";
private static final String ENCRYPTION_KEY_PREFIX = "x-goog-encryption-";
private static final String SOURCE_ENCRYPTION_KEY_PREFIX = "x-goog-copy-source-encryption-";
@@ -450,10 +451,24 @@ public Bucket patch(Bucket bucket, Map