Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
31ac05b
Feature/storage/bifrost create session (#49448)
browndav-msft Jun 11, 2026
e127ec4
fix bug in storage session credential with get content length 0
browndav-msft Jun 10, 2026
d5d8177
patch to enable session with environement variables
browndav-msft Jun 10, 2026
94145b4
Potential fix for pull request finding
ibrandes Jun 11, 2026
3160091
add code to ensure container name only accepted when session enabled
browndav-msft Jun 11, 2026
cce0354
fix formatting and javadocs alignment
browndav-msft Jun 11, 2026
ba61f35
add forceRefreshSessionInBackground() to SessionTokenCredentialPolicy
browndav-msft Jun 22, 2026
40c0598
remove .env initialization for sessions
browndav-msft Aug 4, 2026
0622cbc
change SessionCredentialCache to AutoRefreshingCache<T>
browndav-msft Aug 5, 2026
b4bc240
rename params for SessionTokenCrednetialPolicy
browndav-msft Aug 7, 2026
2d40a90
add autorefreshcasche specific tests for blob session credential
browndav-msft Aug 7, 2026
1e0e530
wip
browndav-msft Aug 10, 2026
ac6fdc1
Session provider lifecycle refactor: expand public contract, move cac…
browndav-msft Aug 10, 2026
aeb1424
remove sessionacquisitioncooldown, remove log entry
browndav-msft Aug 10, 2026
35275b6
remove SessionRequestSigner, rename SessionClient to SessionProvider
browndav-msft Aug 10, 2026
d9eb0ee
rename SessionProviderSeamTests to SessionProviderTests
browndav-msft Aug 10, 2026
aa11c92
create helper method for session provider inside BuilderHelper
browndav-msft Aug 10, 2026
9fea2ca
refactor beginAccountCooldown
browndav-msft Aug 10, 2026
d80245f
inline error codes, make async code easier to read
browndav-msft Aug 10, 2026
e6fb314
rename BlobSessionProvider to TokenCredentialSessionProvider
browndav-msft Aug 10, 2026
f69d4bb
consolidate testing resources in session package in common, improve s…
browndav-msft Aug 11, 2026
38c9310
rework SessionTokenCredentialPolicyTest to remove warnings
browndav-msft Aug 11, 2026
3ae4d1c
remove normal and trims from TokenCredentialSessionProviderCacheTests
browndav-msft Aug 11, 2026
7b85643
remove unnecessary tests in BuilderHelper
browndav-msft Aug 11, 2026
7d92af1
add recordings for tests
browndav-msft Aug 12, 2026
b00b3c1
fix linting
browndav-msft Aug 12, 2026
06b2453
consolidate session mocks to scriptedHttpClient, remove createSession…
browndav-msft Aug 12, 2026
84a6691
refactor builderhelper test to test customer provided SessionProvider
browndav-msft Aug 12, 2026
b6c6fbb
clean up javadoc for sessionprovider, remove unneeded returns for Scr…
browndav-msft Aug 12, 2026
c930e79
add support for dfs hns
browndav-msft Aug 12, 2026
3ced75e
create live tests for datalake
browndav-msft Aug 13, 2026
703b16e
add public accessors to session methods
browndav-msft Aug 13, 2026
dfd0f88
fix failing compilations, update swagger to use 105
browndav-msft Aug 16, 2026
1e9157a
merge in recordings from create session
browndav-msft Aug 16, 2026
dd138a5
remove container level createSession calls from public api, fix tests…
browndav-msft Aug 18, 2026
1fe704c
undo spacing from builder helper
browndav-msft Aug 18, 2026
1a7c47a
fix builder helper so that diff shows appropriately for createBearerP…
browndav-msft Aug 18, 2026
353bede
fix bytebuddy testing dependency in pom
browndav-msft Aug 18, 2026
2adae2f
Share post-authentication pipeline policies with the CreateSession pi…
browndav-msft Aug 19, 2026
7d50ad2
Cool down accounts that repeatedly reject session credentials
browndav-msft Aug 19, 2026
a71a6be
Sanitize session secrets and mark DataLake session tests live-only
browndav-msft Aug 19, 2026
e981101
De-duplicate pipeline construction in BuilderHelper
browndav-msft Aug 19, 2026
b45b3fb
moved helps from SessionTestHelper to BlobTestBase
browndav-msft Aug 19, 2026
20c3124
Throttle background refresh retries after a failed session creation
browndav-msft Aug 19, 2026
aad68b6
Pin the reentrant forced-refresh behavior of AutoRefreshingCache
browndav-msft Aug 19, 2026
60fded3
Fix reentrant forced-refresh behavior for joiners
browndav-msft Aug 20, 2026
e4d92e4
Remove redundant session credential shadow-copy from ContainerSession…
browndav-msft Aug 20, 2026
844a1aa
Refine session test HTTP transports
browndav-msft Aug 20, 2026
8d2fd04
Localize the CreateSession test transport
browndav-msft Aug 20, 2026
34e29da
Observe session auth requests with the wire tap client
browndav-msft Aug 20, 2026
79a3d27
Align session auth javadocs with the cooldown implementation
browndav-msft Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/storage/azure-storage-blob/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/storage/azure-storage-blob",
"Tag": "java/storage/azure-storage-blob_018b1a065c"
"Tag": "java/storage/azure-storage-blob_49f6817d98"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<suppress files="com.azure.storage.blob.implementation.util.BlobSasImplUtil.java" checks="io.clientcore.linting.extensions.checkstyle.checks.EnforceFinalFieldsCheck" />
<suppress files="com.azure.storage.blob.specialized.BlobOutputStream.java" checks="io.clientcore.linting.extensions.checkstyle.checks.EnforceFinalFieldsCheck" />
<suppress files="com.azure.storage.blob.implementation.util.BlobUserAgentModificationPolicy.java" checks="io.clientcore.linting.extensions.checkstyle.checks.HttpPipelinePolicyCheck" />
<suppress files="com.azure.storage.blob.implementation.util.SessionTokenCredentialPolicy.java" checks="io.clientcore.linting.extensions.checkstyle.checks.HttpPipelinePolicyCheck" />
<suppress files="com.azure.storage.blob.implementation.AzureBlobStorageImplBuilder.java" checks="io.clientcore.linting.extensions.checkstyle.checks.ServiceClientBuilderCheck" />
<suppress files="com.azure.storage.blob.BlobClient.java" checks="io.clientcore.linting.extensions.checkstyle.checks.ServiceClientCheck" />
<suppress files="com.azure.storage.blob.specialized.BlobLeaseAsyncClient.java" checks="io.clientcore.linting.extensions.checkstyle.checks.ServiceClientCheck" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,20 @@ public BlobAsyncClient buildAsyncClient() {

BlobServiceVersion serviceVersion = version != null ? version : BlobServiceVersion.getLatest();

HttpPipeline pipeline = constructPipeline();
HttpPipeline pipeline = constructPipeline(blobContainerName, serviceVersion);

return new BlobAsyncClient(pipeline, endpoint, serviceVersion, accountName, blobContainerName, blobName,
snapshot, customerProvidedKey, encryptionScope, versionId);
}

private HttpPipeline constructPipeline() {
return (httpPipeline != null)
? httpPipeline
: BuilderHelper.buildPipeline(storageSharedKeyCredential, tokenCredential, azureSasCredential, sasToken,
endpoint, retryOptions, coreRetryOptions, logOptions, clientOptions, httpClient, perCallPolicies,
perRetryPolicies, configuration, audience, LOGGER);
private HttpPipeline constructPipeline(String containerName, BlobServiceVersion serviceVersion) {
if (httpPipeline != null) {
return httpPipeline;
}

return BuilderHelper.buildPipeline(storageSharedKeyCredential, tokenCredential, azureSasCredential, sasToken,
endpoint, retryOptions, coreRetryOptions, logOptions, clientOptions, httpClient, perCallPolicies,
perRetryPolicies, configuration, audience, LOGGER, null, serviceVersion);
}

/**
Expand Down Expand Up @@ -650,4 +652,5 @@ public BlobClientBuilder audience(BlobAudience audience) {
this.audience = audience;
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1846,11 +1846,4 @@ public String generateSas(BlobServiceSasSignatureValues blobServiceSasSignatureV
.generateSas(SasImplUtils.extractSharedKeyCredential(getHttpPipeline()), stringToSignHandler, context);
}

// private boolean validateNoTime(BlobRequestConditions modifiedRequestConditions) {
// if (modifiedRequestConditions == null) {
// return true;
// }
// return modifiedRequestConditions.getIfModifiedSince() == null
// && modifiedRequestConditions.getIfUnmodifiedSince() == null;
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public BlobContainerClient buildClient() {

BlobServiceVersion serviceVersion = version != null ? version : BlobServiceVersion.getLatest();

HttpPipeline pipeline = constructPipeline();
HttpPipeline pipeline = constructPipeline(blobContainerName, serviceVersion);

return new BlobContainerClient(pipeline, endpoint, serviceVersion, accountName, blobContainerName,
customerProvidedKey, encryptionScope, blobContainerEncryptionScope);
Expand Down Expand Up @@ -174,18 +174,19 @@ public BlobContainerAsyncClient buildAsyncClient() {

BlobServiceVersion serviceVersion = version != null ? version : BlobServiceVersion.getLatest();

HttpPipeline pipeline = constructPipeline();
HttpPipeline pipeline = constructPipeline(blobContainerName, serviceVersion);

return new BlobContainerAsyncClient(pipeline, endpoint, serviceVersion, accountName, blobContainerName,
customerProvidedKey, encryptionScope, blobContainerEncryptionScope);
}

private HttpPipeline constructPipeline() {
return (httpPipeline != null)
? httpPipeline
: BuilderHelper.buildPipeline(storageSharedKeyCredential, tokenCredential, azureSasCredential, sasToken,
endpoint, retryOptions, coreRetryOptions, logOptions, clientOptions, httpClient, perCallPolicies,
perRetryPolicies, configuration, audience, LOGGER);
private HttpPipeline constructPipeline(String containerName, BlobServiceVersion serviceVersion) {
if (httpPipeline != null) {
return httpPipeline;
}
return BuilderHelper.buildPipeline(storageSharedKeyCredential, tokenCredential, azureSasCredential, sasToken,
endpoint, retryOptions, coreRetryOptions, logOptions, clientOptions, httpClient, perCallPolicies,
perRetryPolicies, configuration, audience, LOGGER, null, serviceVersion);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

session auth is only configurable on BlobServiceClientBuilder, and this container builder (and BlobClientBuilder) pass null for sessionOptions and expose no sessionOptions(...) setter. this would be fine if our clients didnt reuse eachother sometimes, but since BlobServiceClient.getBlobContainerClient reuses the service pipeline, any service-derived containers get sessions, but a BlobContainerClient/BlobClient built directly with a TokenCredential will silently get bearer-only, with no way to enable or disable sessions.

given the session model is inherently container-scoped, this asymmetry might be surprising to customers (two clients that look equivalent authenticate differently based on how they were constructed). can we either add the setter here for consistency, or document the limitation explicitly? might be good to talk about this with gauri too.

}

/**
Expand Down Expand Up @@ -606,4 +607,5 @@ public BlobContainerClientBuilder audience(BlobAudience audience) {
this.audience = audience;
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public BlobContainerClient getBlobContainerClient(String containerName) {
if (CoreUtils.isNullOrEmpty(containerName)) {
containerName = BlobContainerClient.ROOT_CONTAINER_NAME;
}

return new BlobContainerClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(),
containerName, customerProvidedKey, encryptionScope, blobContainerEncryptionScope);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.storage.blob.implementation.models.EncryptionScope;
import com.azure.storage.blob.implementation.util.BuilderHelper;
import com.azure.storage.blob.implementation.util.SessionTokenCredentialPolicy;
import com.azure.storage.blob.models.SessionOptions;
import com.azure.storage.blob.models.BlobAudience;
import com.azure.storage.blob.models.BlobContainerEncryptionScope;
import com.azure.storage.blob.models.CpkInfo;
Expand Down Expand Up @@ -93,6 +95,7 @@ public final class BlobServiceClientBuilder implements TokenCredentialTrait<Blob
private BlobServiceVersion version;
private BlobAudience audience;
private boolean anonymousAccess;
private SessionOptions sessionOptions = new SessionOptions();

/**
* Creates a builder instance that is able to configure and construct {@link BlobServiceClient BlobServiceClients}
Expand Down Expand Up @@ -139,6 +142,10 @@ public BlobServiceClient buildClient() {
foundCredential = true;
break;
}
if (pipeline.getPolicy(i) instanceof SessionTokenCredentialPolicy) {
foundCredential = true;
break;
}
}
anonymousAccess = !foundCredential;

Expand All @@ -147,11 +154,12 @@ public BlobServiceClient buildClient() {
}

private HttpPipeline constructPipeline() {
return (httpPipeline != null)
? httpPipeline
: BuilderHelper.buildPipeline(storageSharedKeyCredential, tokenCredential, azureSasCredential, sasToken,
endpoint, retryOptions, coreRetryOptions, logOptions, clientOptions, httpClient, perCallPolicies,
perRetryPolicies, configuration, audience, LOGGER);
if (httpPipeline != null) {
return httpPipeline;
}
return BuilderHelper.buildPipeline(storageSharedKeyCredential, tokenCredential, azureSasCredential, sasToken,
endpoint, retryOptions, coreRetryOptions, logOptions, clientOptions, httpClient, perCallPolicies,
perRetryPolicies, configuration, audience, LOGGER, sessionOptions, null);
}

/**
Expand Down Expand Up @@ -191,6 +199,10 @@ public BlobServiceAsyncClient buildAsyncClient() {
foundCredential = true;
break;
}
if (pipeline.getPolicy(i) instanceof SessionTokenCredentialPolicy) {
foundCredential = true;
break;
}
}
anonymousAccess = !foundCredential;

Expand Down Expand Up @@ -587,4 +599,22 @@ public BlobServiceClientBuilder audience(BlobAudience audience) {
this.audience = audience;
return this;
}

/**
* Sets the {@link SessionOptions} that controls how the SDK manages session-based authentication
* for container clients created from this service client.
* <p>
* Sessions amortize authentication and authorization cost across many requests by signing them
* with a lightweight HMAC key instead of a full bearer token. This setting is passed to container
* clients created via {@link BlobServiceClient#getBlobContainerClient(String)}. If the options do not
* specify a {@link com.azure.storage.blob.models.SessionProvider}, the SDK creates a built-in provider
* scoped to this service client's pipeline.
*
* @param sessionOptions The session options for the HTTP pipeline.
* @return the updated BlobServiceClientBuilder object.
*/
public BlobServiceClientBuilder sessionOptions(SessionOptions sessionOptions) {
this.sessionOptions = sessionOptions != null ? sessionOptions : new SessionOptions();
return this;
}
}
Loading