Skip to content

Commit

Permalink
Added support to get a BlobClient that uses a specific encryption sco…
Browse files Browse the repository at this point in the history
…pe and customer provided key (#21280)
  • Loading branch information
gapra-msft committed Jul 22, 2021
1 parent 77cdb2d commit 0d962c5
Show file tree
Hide file tree
Showing 23 changed files with 663 additions and 2 deletions.
3 changes: 3 additions & 0 deletions sdk/storage/azure-storage-blob-cryptography/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Release History

## 12.12.1 (Unreleased)
- Added support to get a blob client that uses an encryption scope and customer provided key.

## 12.12.0 (2021-06-09)
- GA release

Expand Down
1 change: 1 addition & 0 deletions sdk/storage/azure-storage-blob-cryptography/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
--add-exports com.azure.core/com.azure.core.implementation.serializer.jackson=ALL-UNNAMED
--add-exports com.azure.core/com.azure.core.implementation.util=ALL-UNNAMED
--add-opens com.azure.storage.common/com.azure.storage.common.implementation=ALL-UNNAMED
--add-opens com.azure.storage.blob/com.azure.storage.blob.specialized=ALL-UNNAMED
--add-opens com.azure.storage.blob.cryptography/com.azure.storage.blob.specialized.cryptography=ALL-UNNAMED
--add-reads com.azure.core=ALL-UNNAMED
--add-reads com.azure.core.test=ALL-UNNAMED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.azure.storage.blob.models.AccessTier;
import com.azure.storage.blob.models.BlobHttpHeaders;
import com.azure.storage.blob.models.BlobQueryAsyncResponse;
import com.azure.storage.blob.models.CustomerProvidedKey;
import com.azure.storage.blob.options.BlobQueryOptions;
import com.azure.storage.blob.models.BlobRequestConditions;
import com.azure.storage.blob.options.BlobParallelUploadOptions;
Expand Down Expand Up @@ -119,6 +120,44 @@ public class EncryptedBlobAsyncClient extends BlobAsyncClient {
this.keyWrapAlgorithm = keyWrapAlgorithm;
}

/**
* Creates a new {@link EncryptedBlobAsyncClient} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link EncryptedBlobAsyncClient} with the specified {@code encryptionScope}.
*/
@Override
public EncryptedBlobAsyncClient getEncryptionScopeClient(String encryptionScope) {
EncryptionScope finalEncryptionScope = null;
if (encryptionScope != null) {
finalEncryptionScope = new EncryptionScope().setEncryptionScope(encryptionScope);
}
return new EncryptedBlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), getSnapshotId(), getCustomerProvidedKey(), finalEncryptionScope,
keyWrapper, keyWrapAlgorithm, getVersionId());
}

/**
* Creates a new {@link EncryptedBlobAsyncClient} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link EncryptedBlobAsyncClient} with the specified {@code customerProvidedKey}.
*/
@Override
public EncryptedBlobAsyncClient getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
CpkInfo finalCustomerProvidedKey = null;
if (customerProvidedKey != null) {
finalCustomerProvidedKey = new CpkInfo()
.setEncryptionKey(customerProvidedKey.getKey())
.setEncryptionKeySha256(customerProvidedKey.getKeySha256())
.setEncryptionAlgorithm(customerProvidedKey.getEncryptionAlgorithm());
}
return new EncryptedBlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), getSnapshotId(), finalCustomerProvidedKey, encryptionScope, keyWrapper,
keyWrapAlgorithm, getVersionId());
}

/**
* Creates a new block blob. By default this method will not overwrite an existing blob.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.azure.storage.blob.models.AccessTier;
import com.azure.storage.blob.models.BlobHttpHeaders;
import com.azure.storage.blob.models.BlockBlobItem;
import com.azure.storage.blob.models.CustomerProvidedKey;
import com.azure.storage.blob.options.BlobQueryOptions;
import com.azure.storage.blob.models.BlobQueryResponse;
import com.azure.storage.blob.models.BlobRequestConditions;
Expand Down Expand Up @@ -73,6 +74,29 @@ public class EncryptedBlobClient extends BlobClient {
this.encryptedBlobAsyncClient = encryptedBlobAsyncClient;
}

/**
* Creates a new {@link EncryptedBlobClient} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link EncryptedBlobClient} with the specified {@code encryptionScope}.
*/
@Override
public EncryptedBlobClient getEncryptionScopeClient(String encryptionScope) {
return new EncryptedBlobClient(encryptedBlobAsyncClient.getEncryptionScopeClient(encryptionScope));
}

/**
* Creates a new {@link EncryptedBlobClient} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link EncryptedBlobClient} with the specified {@code customerProvidedKey}.
*/
@Override
public EncryptedBlobClient getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
return new EncryptedBlobClient(encryptedBlobAsyncClient.getCustomerProvidedKeyClient(customerProvidedKey));
}

/**
* Creates and opens an output stream to write data to the block blob.
* <p>
Expand Down Expand Up @@ -142,7 +166,7 @@ public BlobOutputStream getBlobOutputStream(ParallelTransferOptions parallelTran
* <p>
* Note: We recommend you call write with reasonably sized buffers, you can do so by wrapping the BlobOutputStream
* obtained below with a {@link java.io.BufferedOutputStream}.
*
*
* @param options {@link BlockBlobOutputStreamOptions}
*
* @return A {@link BlobOutputStream} object used to write data to the blob.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,39 @@ class BlobCryptographyBuilderTest extends APISpec {
notThrown(IllegalArgumentException)

}

def "getCustomerProvidedKeyClient"() {
setup:
CustomerProvidedKey originalKey = new CustomerProvidedKey(getRandomKey())
def client = getEncryptedClientBuilder(fakeKey, null, env.primaryAccount.credential, cc.getBlobContainerUrl())
.customerProvidedKey(originalKey)
.blobName(generateBlobName())
.buildEncryptedBlobClient()
def newCpk = new CustomerProvidedKey(getRandomKey())

when:
def newClient = client.getCustomerProvidedKeyClient(newCpk)

then:
newClient instanceof EncryptedBlobClient
newClient.getCustomerProvidedKey() != client.getCustomerProvidedKey()
}

def "getEncryptionScopeClient"() {
setup:
def originalScope = "testscope1"
def client = getEncryptedClientBuilder(fakeKey, null, env.primaryAccount.credential, cc.getBlobContainerUrl())
.encryptionScope(originalScope)
.blobName(generateBlobName())
.buildEncryptedBlobClient()
def newEncryptionScope = "newtestscope"

when:
def newClient = client.getEncryptionScopeClient(newEncryptionScope)

then:
newClient instanceof EncryptedBlobClient
newClient.getEncryptionScope() != client.getEncryptionScope()

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"networkCallRecords" : [ ],
"variables" : [ "8fd82dc5-4054-4e75-9c22-9d18e5a75b50", "c065fac20c065fac202540987dcd4abf12b154b038e5", "c065fac21c065fac202511756b3275434908c44bb9ed", "c065fac22c065fac202504018e65a92442acf400cabc" ]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"networkCallRecords" : [ ],
"variables" : [ "affe8af3-64d9-4865-a098-40845e087454", "76bc7753076bc775385870380ad81fcc3c8964660914", "76bc7753176bc775385820377018788e904b84d85a3a", "76bc7753276bc775385833617e44a75c1d550468bae0" ]
}
3 changes: 3 additions & 0 deletions sdk/storage/azure-storage-blob/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Release History

## 12.12.1 (Unreleased)
- Added support to get a blob client that uses an encryption scope and customer provided key.

## 12.12.0 (2021-06-09)
- GA release

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,44 @@ public BlobAsyncClient getVersionClient(String versionId) {
getContainerName(), getBlobName(), getSnapshotId(), getCustomerProvidedKey(), encryptionScope, versionId);
}

/**
* Creates a new {@link BlobAsyncClient} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link BlobAsyncClient} with the specified {@code encryptionScope}.
*/
@Override
public BlobAsyncClient getEncryptionScopeClient(String encryptionScope) {
EncryptionScope finalEncryptionScope = null;
if (encryptionScope != null) {
finalEncryptionScope = new EncryptionScope().setEncryptionScope(encryptionScope);
}
return new BlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), getSnapshotId(), getCustomerProvidedKey(), finalEncryptionScope,
getVersionId());
}

/**
* Creates a new {@link BlobAsyncClient} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link BlobAsyncClient} with the specified {@code customerProvidedKey}.
*/
@Override
public BlobAsyncClient getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
CpkInfo finalCustomerProvidedKey = null;
if (customerProvidedKey != null) {
finalCustomerProvidedKey = new CpkInfo()
.setEncryptionKey(customerProvidedKey.getKey())
.setEncryptionKeySha256(customerProvidedKey.getKeySha256())
.setEncryptionAlgorithm(customerProvidedKey.getEncryptionAlgorithm());
}
return new BlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), getSnapshotId(), finalCustomerProvidedKey, encryptionScope,
getVersionId());
}

/**
* Creates a new {@link AppendBlobAsyncClient} associated with this blob.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.azure.core.util.FluxUtil;
import com.azure.core.util.logging.ClientLogger;
import com.azure.storage.blob.models.AccessTier;
import com.azure.storage.blob.models.CustomerProvidedKey;
import com.azure.storage.blob.options.BlobParallelUploadOptions;
import com.azure.storage.blob.models.BlobRequestConditions;
import com.azure.storage.blob.models.BlobHttpHeaders;
Expand Down Expand Up @@ -106,6 +107,29 @@ public BlobClient getVersionClient(String versionId) {
return new BlobClient(client.getVersionClient(versionId));
}

/**
* Creates a new {@link BlobClient} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link BlobClient} with the specified {@code encryptionScope}.
*/
@Override
public BlobClient getEncryptionScopeClient(String encryptionScope) {
return new BlobClient(client.getEncryptionScopeClient(encryptionScope));
}

/**
* Creates a new {@link BlobClient} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link BlobClient} with the specified {@code customerProvidedKey}.
*/
@Override
public BlobClient getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
return new BlobClient(client.getCustomerProvidedKeyClient(customerProvidedKey));
}

/**
* Creates a new {@link AppendBlobClient} associated with this blob.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.azure.storage.blob.implementation.models.AppendBlobsAppendBlockHeaders;
import com.azure.storage.blob.implementation.models.AppendBlobsCreateHeaders;
import com.azure.storage.blob.implementation.models.EncryptionScope;
import com.azure.storage.blob.models.CustomerProvidedKey;
import com.azure.storage.blob.options.AppendBlobCreateOptions;
import com.azure.storage.blob.models.AppendBlobRequestConditions;
import com.azure.storage.blob.models.AppendBlobItem;
Expand Down Expand Up @@ -100,6 +101,44 @@ public final class AppendBlobAsyncClient extends BlobAsyncClientBase {
encryptionScope, versionId);
}

/**
* Creates a new {@link AppendBlobAsyncClient} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link AppendBlobAsyncClient} with the specified {@code encryptionScope}.
*/
@Override
public AppendBlobAsyncClient getEncryptionScopeClient(String encryptionScope) {
EncryptionScope finalEncryptionScope = null;
if (encryptionScope != null) {
finalEncryptionScope = new EncryptionScope().setEncryptionScope(encryptionScope);
}
return new AppendBlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), getSnapshotId(), getCustomerProvidedKey(), finalEncryptionScope,
getVersionId());
}

/**
* Creates a new {@link AppendBlobAsyncClient} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link AppendBlobAsyncClient} with the specified {@code customerProvidedKey}.
*/
@Override
public AppendBlobAsyncClient getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
CpkInfo finalCustomerProvidedKey = null;
if (customerProvidedKey != null) {
finalCustomerProvidedKey = new CpkInfo()
.setEncryptionKey(customerProvidedKey.getKey())
.setEncryptionKeySha256(customerProvidedKey.getKeySha256())
.setEncryptionAlgorithm(customerProvidedKey.getEncryptionAlgorithm());
}
return new AppendBlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), getSnapshotId(), finalCustomerProvidedKey, encryptionScope,
getVersionId());
}

/**
* Creates a 0-length append blob. Call appendBlock to append data to an append blob. By default this method will
* not overwrite an existing blob.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.azure.storage.blob.BlobClientBuilder;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.models.CustomerProvidedKey;
import com.azure.storage.blob.options.AppendBlobCreateOptions;
import com.azure.storage.blob.models.AppendBlobItem;
import com.azure.storage.blob.models.AppendBlobRequestConditions;
Expand Down Expand Up @@ -73,6 +74,29 @@ public final class AppendBlobClient extends BlobClientBase {
this.appendBlobAsyncClient = appendBlobAsyncClient;
}

/**
* Creates a new {@link AppendBlobClient} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link AppendBlobClient} with the specified {@code encryptionScope}.
*/
@Override
public AppendBlobClient getEncryptionScopeClient(String encryptionScope) {
return new AppendBlobClient(appendBlobAsyncClient.getEncryptionScopeClient(encryptionScope));
}

/**
* Creates a new {@link AppendBlobClient} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link AppendBlobClient} with the specified {@code customerProvidedKey}.
*/
@Override
public AppendBlobClient getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
return new AppendBlobClient(appendBlobAsyncClient.getCustomerProvidedKeyClient(customerProvidedKey));
}

/**
* Creates and opens an output stream to write data to the append blob. If the blob already exists on the service,
* it will be overwritten.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,41 @@ public BlobAsyncClientBase getVersionClient(String versionId) {
getContainerName(), getBlobName(), getSnapshotId(), getCustomerProvidedKey(), encryptionScope, versionId);
}

/**
* Creates a new {@link BlobAsyncClientBase} with the specified {@code encryptionScope}.
*
* @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope.
* @return a {@link BlobAsyncClientBase} with the specified {@code encryptionScope}.
*/
public BlobAsyncClientBase getEncryptionScopeClient(String encryptionScope) {
EncryptionScope finalEncryptionScope = null;
if (encryptionScope != null) {
finalEncryptionScope = new EncryptionScope().setEncryptionScope(encryptionScope);
}
return new BlobAsyncClientBase(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), snapshot, getCustomerProvidedKey(), finalEncryptionScope,
getVersionId());
}

/**
* Creates a new {@link BlobAsyncClientBase} with the specified {@code customerProvidedKey}.
*
* @param customerProvidedKey the {@link CustomerProvidedKey} for the blob,
* pass {@code null} to use no customer provided key.
* @return a {@link BlobAsyncClientBase} with the specified {@code customerProvidedKey}.
*/
public BlobAsyncClientBase getCustomerProvidedKeyClient(CustomerProvidedKey customerProvidedKey) {
CpkInfo finalCustomerProvidedKey = null;
if (customerProvidedKey != null) {
finalCustomerProvidedKey = new CpkInfo()
.setEncryptionKey(customerProvidedKey.getKey())
.setEncryptionKeySha256(customerProvidedKey.getKeySha256())
.setEncryptionAlgorithm(customerProvidedKey.getEncryptionAlgorithm());
}
return new BlobAsyncClientBase(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
getContainerName(), getBlobName(), snapshot, finalCustomerProvidedKey, encryptionScope,
getVersionId());
}

/**
* Get the url of the storage account.
Expand Down
Loading

0 comments on commit 0d962c5

Please sign in to comment.