Skip to content

Commit a86d1fb

Browse files
ibrandesbrowndav-msftCopilot
authored
Storage - STG101 Beta Features (#48019)
* adding new service version (#47408) * STG 101 - Dynamic User Delegation SAS (#47479) * wip implementation * add base tests for SasImplUtilsTests * add base tests for SasImplUtilsTests * revert changes to stringToSign from changes made based on api * remove static from SasImplUtilsTests so that beforeeach works * add documentation for srq and srh * finish sasClientTests * uncomment stream of args from blobSasImplUtilStringToSignUserDelegationKeySupplier * fix linting issue * combine test for srh and srq into blobSasImplUtilStringToSignUserDelegationKey * add recordings for blobSasImplUtilStringToSignUserDelegationKey * add additional srh test to check for trailing newline * add tests for srq * add tests for srq and srh to datalake * fix failing datalake sas tests * add recordings for blobSasImplUtilStringToSignUserDelegationKey * refactor SasTests to make the suppliers easier to read and write * making new values in commonsasqueryparameters final * adding note to new sas query param javadocs that they're only for UD sas * adding note to datalake sas params too * add header to sasimplutiltests * applying spotless * small refactors in new sas test models * adding extra comments to SasClientTests * applying new sas test model to blob sas tests * returning null instead of empty string during formatting * applying new sas test model to blob sas tests * getting suppliers to use new models * removing debugging method * updating assets and fixing spelling * removing unused import * bruh * datalake tests * spotless * style and assets * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * making new query param values deterministic --------- Co-authored-by: browndav <browndav@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * adding uds changelog feature entires * STG 101 - Deprecating BlobErrorCode Typo and Adding Correct Code (#47409) * applying swagger changes and adding deprecation customization * deleting old generated file * adding changelog entry * STG101 - Add Support for Missing SKU Names (#47437) * applying swagger changes, untested * removing random newline in swagger readme * commiting temp test for history purposes * removing temp test * removing newline * adding changelog entry * adding sku names to cspell overrides * STG101 - Delete Blob Conditional Tier (#47438) * applying swagger and public facing changes, not tested * adding changelog entry * adding tests * STG101 - Server-Side Encryption with Rekeying (#47439) * applying swagger and adding value to options bags * removing redundant module requirement * style * adding tests * adding feature to changelog * re-run ci * adding recordings * updating test assets * STG 101 - Files Provisioned V2 Guardrails (#47464) * generating off swagger * adding changelog entry * Update sdk/storage/azure-storage-file-share/CHANGELOG.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * STG101 - Cross-Tenant Support for Principal Bound Delegation Sas (#47461) * generating off swaggers and blob impl * datalake implementation * share implementation * queue implementation * changing tid to tenantId * removing unused import * updating blobsasimplutilstringtosign test supplier * wip * wip * fixing blob readme * adjusting blob tests * adding blob async tests * datalake tests * file and queue tests * cleanup * small positional change * Update sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileSasClientTests.java subscribing to mono once instead of twice Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fixing test failure * changing test min service version to 2025.07.05 * addressing copilot comments * fixing autorest version i messed up * fixing revapi error * updating assets * updating datalake service client async methods to stop breaking existing test --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * updating swagger links to be 101 pr into main spec * adding missing cross tenant principal bound delegation sas feature changelog entries * updating blob swagger readme * addressing copilot comments * updating assets * spotless * fixing test names --------- Co-authored-by: browndav <browndav@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 2cd82c3 commit a86d1fb

85 files changed

Lines changed: 5361 additions & 1098 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.vscode/cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@
987987
"clientime",
988988
"ctxt",
989989
"etags",
990+
"GZRS",
990991
"HTBB",
991992
"IPMISMATCH",
992993
"myaccountname",
@@ -1003,6 +1004,7 @@
10031004
"myjavacontainerbuffereduploadlength",
10041005
"myjavacontainerparallelupload",
10051006
"RAGRS",
1007+
"RAGZRS",
10061008
"saoid"
10071009
]
10081010
},

sdk/storage/azure-storage-blob/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
## 12.34.0-beta.1 (Unreleased)
44

55
### Features Added
6+
- Added support for specifying a source customer-provided encryption key when using `AppendBlobClient.appendBlockFromUrl()`,
7+
`BlockBlobClient.stageBlockFromUrl()`, `BlockBlobClient.uploadFromUrl()`, and `PageBlobClient.uploadPagesFromUrl()` APIs.
8+
- Added support for `AccessTierIfModifiedSince` and `AccessTierIfUnmodifiedSince` to conditionally perform `BlobClient.delete` operations.
9+
- Added support for missing SKU names `STANDARD_GZRS`, `STANDARD_RAGZRS` and `PREMIUM_ZRS` when using `getAccountInfo()` API.
10+
- Added support for error code `INCREMENTAL_COPY_OF_EARLIER_SNAPSHOT_NOT_ALLOWED`. This replaces `INCREMENTAL_COPY_OF_EARLIER_VERSION_SNAPSHOT_NOT_ALLOWED` which has been deprecated.
11+
- Added support for Dynamic User Delegation SAS.
12+
- Added cross-tenant support for principal bound delegation SAS.
613

714
### Breaking Changes
815

sdk/storage/azure-storage-blob/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "java",
44
"TagPrefix": "java/storage/azure-storage-blob",
5-
"Tag": "java/storage/azure-storage-blob_8c8c6e5dfd"
5+
"Tag": "java/storage/azure-storage-blob_4ab10936db"
66
}

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceAsyncClient.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.azure.storage.blob.models.TaggedBlobItem;
3838
import com.azure.storage.blob.models.UserDelegationKey;
3939
import com.azure.storage.blob.options.BlobContainerCreateOptions;
40+
import com.azure.storage.blob.options.BlobGetUserDelegationKeyOptions;
4041
import com.azure.storage.blob.options.FindBlobsOptions;
4142
import com.azure.storage.blob.options.UndeleteBlobContainerOptions;
4243
import com.azure.storage.common.StorageSharedKeyCredential;
@@ -873,7 +874,7 @@ public Mono<UserDelegationKey> getUserDelegationKey(OffsetDateTime start, Offset
873874
*
874875
* @param start Start time for the key's validity. Null indicates immediate start.
875876
* @param expiry Expiration of the key's validity.
876-
* @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} containing the user
877+
* @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains the user
877878
* delegation key.
878879
* @throws IllegalArgumentException If {@code start} isn't null and is after {@code expiry}.
879880
* @throws NullPointerException If {@code expiry} is null.
@@ -888,20 +889,44 @@ public Mono<Response<UserDelegationKey>> getUserDelegationKeyWithResponse(Offset
888889
}
889890
}
890891

892+
/**
893+
* Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when
894+
* using {@link TokenCredential} in this object's {@link HttpPipeline}.
895+
*
896+
* @param options The {@link BlobGetUserDelegationKeyOptions options} to configure the request.
897+
* @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains the user
898+
* delegation key.
899+
*/
900+
@ServiceMethod(returns = ReturnType.SINGLE)
901+
public Mono<Response<UserDelegationKey>> getUserDelegationKeyWithResponse(BlobGetUserDelegationKeyOptions options) {
902+
try {
903+
StorageImplUtils.assertNotNull("options", options);
904+
return withContext(context -> getUserDelegationKeyWithResponse(options.getStartsOn(),
905+
options.getExpiresOn(), options.getDelegatedUserTenantId(), context));
906+
} catch (RuntimeException ex) {
907+
return monoError(LOGGER, ex);
908+
}
909+
}
910+
891911
Mono<Response<UserDelegationKey>> getUserDelegationKeyWithResponse(OffsetDateTime start, OffsetDateTime expiry,
892912
Context context) {
893-
StorageImplUtils.assertNotNull("expiry", expiry);
913+
return getUserDelegationKeyWithResponse(start, expiry, null, context);
914+
}
915+
916+
Mono<Response<UserDelegationKey>> getUserDelegationKeyWithResponse(OffsetDateTime start, OffsetDateTime expiry,
917+
String delegatedUserTenantId, Context context) {
918+
context = context == null ? Context.NONE : context;
919+
throwOnAnonymousAccess();
894920
if (start != null && !start.isBefore(expiry)) {
895921
throw LOGGER.logExceptionAsError(
896922
new IllegalArgumentException("`start` must be null or a datetime before `expiry`."));
897923
}
898-
throwOnAnonymousAccess();
899-
context = context == null ? Context.NONE : context;
900924

901925
return this.azureBlobStorage.getServices()
902926
.getUserDelegationKeyWithResponseAsync(
903927
new KeyInfo().setStart(start == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(start))
904-
.setExpiry(Constants.ISO_8601_UTC_DATE_FORMATTER.format(expiry)),
928+
.setExpiry(Constants.ISO_8601_UTC_DATE_FORMATTER.format(expiry))
929+
.setDelegatedUserTenantId(delegatedUserTenantId),
905930
null, null, context)
906931
.map(rb -> new SimpleResponse<>(rb, rb.getValue()));
907932
}

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceClient.java

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import com.azure.storage.blob.models.TaggedBlobItem;
4545
import com.azure.storage.blob.models.UserDelegationKey;
4646
import com.azure.storage.blob.options.BlobContainerCreateOptions;
47+
import com.azure.storage.blob.options.BlobGetUserDelegationKeyOptions;
4748
import com.azure.storage.blob.options.FindBlobsOptions;
4849
import com.azure.storage.blob.options.UndeleteBlobContainerOptions;
4950
import com.azure.storage.common.StorageSharedKeyCredential;
@@ -761,7 +762,8 @@ public Response<Void> setPropertiesWithResponse(BlobServiceProperties properties
761762
*/
762763
@ServiceMethod(returns = ReturnType.SINGLE)
763764
public UserDelegationKey getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry) {
764-
return getUserDelegationKeyWithResponse(start, expiry, null, Context.NONE).getValue();
765+
return getUserDelegationKeyWithResponse(new BlobGetUserDelegationKeyOptions(expiry).setStartsOn(start), null,
766+
Context.NONE).getValue();
765767
}
766768

767769
/**
@@ -786,19 +788,39 @@ public UserDelegationKey getUserDelegationKey(OffsetDateTime start, OffsetDateTi
786788
@ServiceMethod(returns = ReturnType.SINGLE)
787789
public Response<UserDelegationKey> getUserDelegationKeyWithResponse(OffsetDateTime start, OffsetDateTime expiry,
788790
Duration timeout, Context context) {
789-
StorageImplUtils.assertNotNull("expiry", expiry);
790-
if (start != null && !start.isBefore(expiry)) {
791+
return getUserDelegationKeyWithResponse(new BlobGetUserDelegationKeyOptions(expiry).setStartsOn(start), timeout,
792+
context);
793+
}
794+
795+
/**
796+
* Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when
797+
* using {@link TokenCredential} in this object's {@link HttpPipeline}.
798+
*
799+
* @param options The {@link BlobGetUserDelegationKeyOptions options} to configure the request.
800+
* @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
801+
* @param context Additional context that is passed through the Http pipeline during the service call.
802+
* @return A {@link Response} whose {@link Response#getValue() value} contains the user delegation key.
803+
*/
804+
@ServiceMethod(returns = ReturnType.SINGLE)
805+
public Response<UserDelegationKey> getUserDelegationKeyWithResponse(BlobGetUserDelegationKeyOptions options,
806+
Duration timeout, Context context) {
807+
Context finalContext = context == null ? Context.NONE : context;
808+
StorageImplUtils.assertNotNull("options", options);
809+
throwOnAnonymousAccess();
810+
if (options.getStartsOn() != null && !options.getStartsOn().isBefore(options.getExpiresOn())) {
791811
throw LOGGER.logExceptionAsError(
792812
new IllegalArgumentException("`start` must be null or a datetime before `expiry`."));
793813
}
794-
throwOnAnonymousAccess();
795-
Context finalContext = context == null ? Context.NONE : context;
814+
796815
Callable<ResponseBase<ServicesGetUserDelegationKeyHeaders, UserDelegationKey>> operation
797816
= () -> this.azureBlobStorage.getServices()
798-
.getUserDelegationKeyWithResponse(
799-
new KeyInfo().setStart(start == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(start))
800-
.setExpiry(Constants.ISO_8601_UTC_DATE_FORMATTER.format(expiry)),
801-
null, null, finalContext);
817+
.getUserDelegationKeyWithResponse(new KeyInfo()
818+
.setStart(options.getStartsOn() == null
819+
? ""
820+
: Constants.ISO_8601_UTC_DATE_FORMATTER.format(options.getStartsOn()))
821+
.setExpiry(Constants.ISO_8601_UTC_DATE_FORMATTER.format(options.getExpiresOn()))
822+
.setDelegatedUserTenantId(options.getDelegatedUserTenantId()), null, null, finalContext);
823+
802824
ResponseBase<ServicesGetUserDelegationKeyHeaders, UserDelegationKey> response
803825
= sendRequest(operation, timeout, BlobStorageException.class);
804826
return new SimpleResponse<>(response, response.getValue());

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceVersion.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,12 @@ public enum BlobServiceVersion implements ServiceVersion {
152152
/**
153153
* Service version {@code 2026-02-06}.
154154
*/
155-
V2026_02_06("2026-02-06");
155+
V2026_02_06("2026-02-06"),
156+
157+
/**
158+
* Service version {@code 2026-04-06}.
159+
*/
160+
V2026_04_06("2026-04-06");
156161

157162
private final String version;
158163

@@ -174,6 +179,6 @@ public String getVersion() {
174179
* @return the latest {@link BlobServiceVersion}
175180
*/
176181
public static BlobServiceVersion getLatest() {
177-
return V2026_02_06;
182+
return V2026_04_06;
178183
}
179184
}

0 commit comments

Comments
 (0)