Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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: 0 additions & 2 deletions eng/common/pipelines/templates/steps/verify-agent-os.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,3 @@ steps:
filePath: ${{ parameters.ScriptDirectory }}/Verify-AgentOS.ps1
arguments: >
-AgentImage "${{ parameters.AgentImage }}"

- template: /eng/common/pipelines/templates/steps/bypass-local-dns.yml
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_47f4243e59"
"Tag": "java/storage/azure-storage-blob_dbe8c45320"
}
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 @@ -28,6 +28,9 @@
import com.azure.storage.blob.implementation.models.EncryptionScope;
import com.azure.storage.blob.implementation.models.ListBlobsFlatSegmentResponse;
import com.azure.storage.blob.implementation.models.ListBlobsHierarchySegmentResponse;
import com.azure.storage.blob.implementation.models.AuthenticationType;
import com.azure.storage.blob.implementation.models.CreateSessionConfiguration;
import com.azure.storage.blob.implementation.models.CreateSessionResponse;
import com.azure.storage.blob.implementation.util.BlobConstants;
import com.azure.storage.blob.implementation.util.BlobSasImplUtil;
import com.azure.storage.blob.implementation.util.ModelHelper;
Expand Down Expand Up @@ -1691,11 +1694,39 @@ 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;
// }
/**
* Creates a session scoped to this container. The session provides temporary credentials (a session token and
* session key) that can be used to sign subsequent requests using the Shared Key protocol.
*
* @return A {@link Mono} containing the {@link CreateSessionResponse} with session credentials.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
Mono<CreateSessionResponse> createSession() {
return createSessionWithResponse().flatMap(FluxUtil::toMono);
}

/**
* Creates a session scoped to this container. The session provides temporary credentials (a session token and
* session key) that can be used to sign subsequent requests using the Shared Key protocol.
*
* @return A {@link Mono} containing a {@link Response} with the {@link CreateSessionResponse}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
Mono<Response<CreateSessionResponse>> createSessionWithResponse() {
try {
return withContext(this::createSessionWithResponse);
} catch (RuntimeException ex) {
return monoError(LOGGER, ex);
}
}

Mono<Response<CreateSessionResponse>> createSessionWithResponse(Context context) {
context = context == null ? Context.NONE : context;
CreateSessionConfiguration config
= new CreateSessionConfiguration().setAuthenticationType(AuthenticationType.HMAC);
return this.azureBlobStorage.getContainers()
.createSessionWithResponseAsync(containerName, config, null, null, context)
.map(response -> new SimpleResponse<>(response, response.getValue()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
import com.azure.storage.blob.implementation.models.FilterBlobSegment;
import com.azure.storage.blob.implementation.models.ListBlobsFlatSegmentResponse;
import com.azure.storage.blob.implementation.models.ListBlobsHierarchySegmentResponse;
import com.azure.storage.blob.implementation.models.AuthenticationType;
import com.azure.storage.blob.implementation.models.CreateSessionConfiguration;
import com.azure.storage.blob.implementation.models.CreateSessionResponse;
import com.azure.storage.blob.implementation.util.BlobConstants;
import com.azure.storage.blob.implementation.util.BlobSasImplUtil;
import com.azure.storage.blob.implementation.util.ModelHelper;
Expand Down Expand Up @@ -1509,4 +1512,37 @@ public String generateSas(BlobServiceSasSignatureValues blobServiceSasSignatureV
.generateSas(SasImplUtils.extractSharedKeyCredential(getHttpPipeline()), stringToSignHandler, context);
}

/**
* Creates a session scoped to this container. The session provides temporary credentials (a session token and
* session key) that can be used to sign subsequent requests using the Shared Key protocol.
*
* @return The {@link CreateSessionResponse} with session credentials.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
CreateSessionResponse createSession() {
return createSessionWithResponse(null, Context.NONE).getValue();
}

/**
* Creates a session scoped to this container. The session provides temporary credentials (a session token and
* session key) that can be used to sign subsequent requests using the Shared Key protocol.
*
* @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @param context Additional context that is passed through the Http pipeline during the service call.
* @return A {@link Response} containing the {@link CreateSessionResponse}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
Response<CreateSessionResponse> createSessionWithResponse(Duration timeout, Context context) {
Context finalContext = context == null ? Context.NONE : context;
CreateSessionConfiguration config
= new CreateSessionConfiguration().setAuthenticationType(AuthenticationType.HMAC);

Callable<Response<CreateSessionResponse>> operation = () -> {
Response<CreateSessionResponse> response = this.azureBlobStorage.getContainers()
.createSessionWithResponse(containerName, config, null, null, finalContext);
return new SimpleResponse<>(response, response.getValue());
};

return sendRequest(operation, timeout, BlobStorageException.class);
}
}
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);
}

/**
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
Loading