diff --git a/sdk/storage/azure-storage-blob/pom.xml b/sdk/storage/azure-storage-blob/pom.xml index 5e08396ea43ab..e84761c32cfa5 100644 --- a/sdk/storage/azure-storage-blob/pom.xml +++ b/sdk/storage/azure-storage-blob/pom.xml @@ -307,5 +307,44 @@ + + inject-sas-service-version + + env.AZURE_LIVE_TEST_SERVICE_VERSION + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + regex-property + + regex-property + + + AZURE_STORAGE_SAS_SERVICE_VERSION + ${env.AZURE_LIVE_TEST_SERVICE_VERSION} + V(\d+)_(\d+)_(\d+) + $1-$2-$3 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + + ${AZURE_STORAGE_SAS_SERVICE_VERSION} + + + + + + diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobSasImplUtil.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobSasImplUtil.java index 50d9797dcfc0d..7376b8c70e288 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobSasImplUtil.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/BlobSasImplUtil.java @@ -3,14 +3,15 @@ package com.azure.storage.blob.implementation.util; +import com.azure.core.util.Configuration; import com.azure.core.util.Context; import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.blob.BlobServiceVersion; import com.azure.storage.blob.models.UserDelegationKey; import com.azure.storage.blob.sas.BlobContainerSasPermission; import com.azure.storage.blob.sas.BlobSasPermission; import com.azure.storage.blob.sas.BlobServiceSasSignatureValues; -import com.azure.storage.blob.sas.BlobSasServiceVersion; import com.azure.storage.common.StorageSharedKeyCredential; import com.azure.storage.common.implementation.Constants; import com.azure.storage.common.implementation.StorageImplUtils; @@ -49,9 +50,10 @@ public class BlobSasImplUtil { */ private static final String SAS_CONTAINER_CONSTANT = "c"; - private final ClientLogger logger = new ClientLogger(BlobSasImplUtil.class); + private static final ClientLogger LOGGER = new ClientLogger(BlobSasImplUtil.class); - private String version; + private static final String VERSION = Configuration.getGlobalConfiguration() + .get(Constants.PROPERTY_AZURE_STORAGE_SAS_SERVICE_VERSION, BlobServiceVersion.getLatest().getVersion()); private SasProtocol protocol; @@ -112,10 +114,9 @@ public BlobSasImplUtil(BlobServiceSasSignatureValues sasValues, String container String snapshotId, String versionId) { Objects.requireNonNull(sasValues); if (snapshotId != null && versionId != null) { - throw logger.logExceptionAsError( + throw LOGGER.logExceptionAsError( new IllegalArgumentException("'snapshot' and 'versionId' cannot be used at the same time.")); } - this.version = null; /* Setting this to null forces the latest service version - see ensureState. */ this.protocol = sasValues.getProtocol(); this.startTime = sasValues.getStartTime(); this.expiryTime = sasValues.getExpiryTime(); @@ -150,7 +151,7 @@ public String generateSas(StorageSharedKeyCredential storageSharedKeyCredentials // Signature is generated on the un-url-encoded values. final String canonicalName = getCanonicalName(storageSharedKeyCredentials.getAccountName()); final String stringToSign = stringToSign(canonicalName); - StorageImplUtils.logStringToSign(logger, stringToSign, context); + StorageImplUtils.logStringToSign(LOGGER, stringToSign, context); final String signature = storageSharedKeyCredentials.computeHmac256(stringToSign); return encode(null /* userDelegationKey */, signature); @@ -173,7 +174,7 @@ public String generateUserDelegationSas(UserDelegationKey delegationKey, String // Signature is generated on the un-url-encoded values. final String canonicalName = getCanonicalName(accountName); final String stringToSign = stringToSign(delegationKey, canonicalName); - StorageImplUtils.logStringToSign(logger, stringToSign, context); + StorageImplUtils.logStringToSign(LOGGER, stringToSign, context); String signature = StorageImplUtils.computeHMac256(delegationKey.getValue(), stringToSign); return encode(delegationKey, signature); @@ -192,7 +193,7 @@ private String encode(UserDelegationKey userDelegationKey, String signature) { */ StringBuilder sb = new StringBuilder(); - tryAppendQueryParameter(sb, Constants.UrlConstants.SAS_SERVICE_VERSION, this.version); + tryAppendQueryParameter(sb, Constants.UrlConstants.SAS_SERVICE_VERSION, VERSION); tryAppendQueryParameter(sb, Constants.UrlConstants.SAS_PROTOCOL, this.protocol); tryAppendQueryParameter(sb, Constants.UrlConstants.SAS_START_TIME, formatQueryParameterDate(this.startTime)); tryAppendQueryParameter(sb, Constants.UrlConstants.SAS_EXPIRY_TIME, formatQueryParameterDate(this.expiryTime)); @@ -246,13 +247,9 @@ private String encode(UserDelegationKey userDelegationKey, String signature) { * https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/src/Sas/BlobSasBuilder.cs */ private void ensureState() { - if (version == null) { - version = BlobSasServiceVersion.getLatest().getVersion(); - } - if (identifier == null) { if (expiryTime == null || permissions == null) { - throw logger.logExceptionAsError(new IllegalStateException("If identifier is not set, expiry time " + throw LOGGER.logExceptionAsError(new IllegalStateException("If identifier is not set, expiry time " + "and permissions must be set")); } } @@ -279,7 +276,7 @@ private void ensureState() { break; default: // We won't reparse the permissions if we don't know the type. - logger.info("Not re-parsing permissions. Resource type '{}' is unknown.", resource); + LOGGER.info("Not re-parsing permissions. Resource type '{}' is unknown.", resource); break; } } @@ -306,7 +303,7 @@ private String stringToSign(String canonicalName) { this.identifier == null ? "" : this.identifier, this.sasIpRange == null ? "" : this.sasIpRange.toString(), this.protocol == null ? "" : this.protocol.toString(), - version, + VERSION, resource, versionSegment == null ? "" : versionSegment, this.cacheControl == null ? "" : this.cacheControl, @@ -319,30 +316,55 @@ private String stringToSign(String canonicalName) { private String stringToSign(final UserDelegationKey key, String canonicalName) { String versionSegment = this.snapshotId == null ? this.versionId : this.snapshotId; - return String.join("\n", - this.permissions == null ? "" : this.permissions, - this.startTime == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), - this.expiryTime == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), - canonicalName, - key.getSignedObjectId() == null ? "" : key.getSignedObjectId(), - key.getSignedTenantId() == null ? "" : key.getSignedTenantId(), - key.getSignedStart() == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(key.getSignedStart()), - key.getSignedExpiry() == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(key.getSignedExpiry()), - key.getSignedService() == null ? "" : key.getSignedService(), - key.getSignedVersion() == null ? "" : key.getSignedVersion(), - this.authorizedAadObjectId == null ? "" : this.authorizedAadObjectId, - "", /* suoid - empty since this applies to HNS only accounts. */ - this.correlationId == null ? "" : this.correlationId, - this.sasIpRange == null ? "" : this.sasIpRange.toString(), - this.protocol == null ? "" : this.protocol.toString(), - version, - resource, - versionSegment == null ? "" : versionSegment, - this.cacheControl == null ? "" : this.cacheControl, - this.contentDisposition == null ? "" : this.contentDisposition, - this.contentEncoding == null ? "" : this.contentEncoding, - this.contentLanguage == null ? "" : this.contentLanguage, - this.contentType == null ? "" : this.contentType - ); + if (VERSION.compareTo(BlobServiceVersion.V2019_12_12.getVersion()) <= 0) { + return String.join("\n", + this.permissions == null ? "" : this.permissions, + this.startTime == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), + this.expiryTime == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), + canonicalName, + key.getSignedObjectId() == null ? "" : key.getSignedObjectId(), + key.getSignedTenantId() == null ? "" : key.getSignedTenantId(), + key.getSignedStart() == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(key.getSignedStart()), + key.getSignedExpiry() == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(key.getSignedExpiry()), + key.getSignedService() == null ? "" : key.getSignedService(), + key.getSignedVersion() == null ? "" : key.getSignedVersion(), + this.sasIpRange == null ? "" : this.sasIpRange.toString(), + this.protocol == null ? "" : this.protocol.toString(), + VERSION, + resource, + versionSegment == null ? "" : versionSegment, + this.cacheControl == null ? "" : this.cacheControl, + this.contentDisposition == null ? "" : this.contentDisposition, + this.contentEncoding == null ? "" : this.contentEncoding, + this.contentLanguage == null ? "" : this.contentLanguage, + this.contentType == null ? "" : this.contentType + ); + } else { + return String.join("\n", + this.permissions == null ? "" : this.permissions, + this.startTime == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), + this.expiryTime == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), + canonicalName, + key.getSignedObjectId() == null ? "" : key.getSignedObjectId(), + key.getSignedTenantId() == null ? "" : key.getSignedTenantId(), + key.getSignedStart() == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(key.getSignedStart()), + key.getSignedExpiry() == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(key.getSignedExpiry()), + key.getSignedService() == null ? "" : key.getSignedService(), + key.getSignedVersion() == null ? "" : key.getSignedVersion(), + this.authorizedAadObjectId == null ? "" : this.authorizedAadObjectId, + "", /* suoid - empty since this applies to HNS only accounts. */ + this.correlationId == null ? "" : this.correlationId, + this.sasIpRange == null ? "" : this.sasIpRange.toString(), + this.protocol == null ? "" : this.protocol.toString(), + VERSION, + resource, + versionSegment == null ? "" : versionSegment, + this.cacheControl == null ? "" : this.cacheControl, + this.contentDisposition == null ? "" : this.contentDisposition, + this.contentEncoding == null ? "" : this.contentEncoding, + this.contentLanguage == null ? "" : this.contentLanguage, + this.contentType == null ? "" : this.contentType + ); + } } } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobSasServiceVersion.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobSasServiceVersion.java index de955f985fed3..6dc5f59fc06d7 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobSasServiceVersion.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobSasServiceVersion.java @@ -7,7 +7,9 @@ /** * The versions of Azure Storage Blob Sas supported by this client library. + * @deprecated The version is set to the latest version of sas. */ +@Deprecated public enum BlobSasServiceVersion implements ServiceVersion { V2019_02_02("2019-02-02"), V2019_07_07("2019-07-07"), diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobServiceSasSignatureValues.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobServiceSasSignatureValues.java index 7619e7aa27227..4cddfc4fce609 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobServiceSasSignatureValues.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/sas/BlobServiceSasSignatureValues.java @@ -3,8 +3,10 @@ package com.azure.storage.blob.sas; +import com.azure.core.util.Configuration; import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.blob.BlobServiceVersion; import com.azure.storage.blob.models.UserDelegationKey; import com.azure.storage.common.Utility; import com.azure.storage.common.implementation.Constants; @@ -43,9 +45,16 @@ public final class BlobServiceSasSignatureValues { */ private static final String SAS_CONTAINER_CONSTANT = "c"; - private final ClientLogger logger = new ClientLogger(BlobServiceSasSignatureValues.class); + private static final ClientLogger LOGGER = new ClientLogger(BlobServiceSasSignatureValues.class); - private final String version = BlobSasServiceVersion.getLatest().getVersion(); + private static final String VERSION = Configuration.getGlobalConfiguration() + .get(Constants.PROPERTY_AZURE_STORAGE_SAS_SERVICE_VERSION, BlobServiceVersion.getLatest().getVersion()); + + /** + * Pin down to highest version that worked with string to sign defined here. + */ + private static final String VERSION_DEPRECATED_STRING_TO_SIGN = Configuration.getGlobalConfiguration() + .get(Constants.PROPERTY_AZURE_STORAGE_SAS_SERVICE_VERSION, BlobServiceVersion.V2019_12_12.getVersion()); private SasProtocol protocol; @@ -171,7 +180,7 @@ public BlobServiceSasSignatureValues(String version, SasProtocol sasProtocol, Of * targeted by the library. */ public String getVersion() { - return version; + return VERSION; } /** @@ -543,8 +552,6 @@ public BlobServiceSasSignatureValues setCorrelationId(String correlationId) { * *

Notes on SAS generation

*