Skip to content
This repository has been archived by the owner on Jul 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #517 from Azure/legacy-dev
Browse files Browse the repository at this point in the history
Legacy dev
  • Loading branch information
rickle-msft authored Dec 6, 2019
2 parents 46a61b1 + d1cce18 commit 9beae8b
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 9 deletions.
3 changes: 3 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2019.12.06 Version 8.6.0
* Added the skipDecode flag to the generate sas method on CloudBlob. This flag allows the customer to skip the url decode that happens by default on the string to sign right before signing. This resolves some problems with custom values for some of the query parameters when used with third party clients.

2019.12.02 Version 8.5.0
* Support for HTTP proxy with Basic auth.
* Support for HTTP proxy with Digest auth.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage</artifactId>
<version>8.5.0</version>
<version>8.6.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion microsoft-azure-storage-samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage</artifactId>
<version>8.5.0</version>
<version>8.6.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage</artifactId>
<version>8.5.0</version>
<version>8.6.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.util.*;
Expand Down Expand Up @@ -500,6 +502,35 @@ public void eventOccurred(SendingRequestEvent eventArg) {
sasBlob.download(new ByteArrayOutputStream(), null, null, context);
}

@Test
@Category(SlowTests.class)
public void testBlobSaSWithSharedAccessBlobHeadersSkipDecode() throws InvalidKeyException,
IllegalArgumentException, StorageException, URISyntaxException, InterruptedException, IOException {
SharedAccessBlobPolicy sp = createSharedAccessPolicy(EnumSet.of(SharedAccessBlobPermissions.READ,
SharedAccessBlobPermissions.WRITE, SharedAccessBlobPermissions.LIST), 300);

SharedAccessBlobHeaders headers = new SharedAccessBlobHeaders();
headers.setCacheControl("no%20cache");
headers.setContentDisposition("inline; filename=\"My Image.jpg\"; filename*=UTF-8''My%20Image.jpg");
headers.setContentEncoding("gzip%20");
headers.setContentLanguage("da%20");
headers.setContentType("image/png");

String sasToken = this.blob.generateSharedAccessSignature(sp, headers, null, null, null, true);
URL url = new URL(this.blob.getUri() + "?" + sasToken);

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
assertEquals(200, connection.getResponseCode());
assertEquals("no%20cache", connection.getHeaderField(Constants.HeaderConstants.CACHE_CONTROL));
assertEquals("inline; filename=\"My Image.jpg\"; filename*=UTF-8''My%20Image.jpg",
connection.getHeaderField(Constants.HeaderConstants.CONTENT_DISPOSITION));
assertEquals("gzip%20", connection.getHeaderField(Constants.HeaderConstants.CONTENT_ENCODING));
assertEquals("da%20", connection.getHeaderField(Constants.HeaderConstants.CONTENT_LANGUAGE));
assertEquals("image/png",
connection.getHeaderField(Constants.HeaderConstants.CONTENT_TYPE));
}

@Test
public void testAppendBlobCopyWithSasAndSnapshot()
throws URISyntaxException, StorageException, InterruptedException, IOException, InvalidKeyException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ public static class HeaderConstants {
/**
* Specifies the value to use for UserAgent header.
*/
public static final String USER_AGENT_VERSION = "8.5.0";
public static final String USER_AGENT_VERSION = "8.6.0";

/**
* The default type for content-type and accept
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2207,7 +2207,45 @@ public String generateSharedAccessSignature(final SharedAccessBlobPolicy policy,
public String generateSharedAccessSignature(
final SharedAccessBlobPolicy policy, final SharedAccessBlobHeaders headers,
final String groupPolicyIdentifier, final IPRange ipRange, final SharedAccessProtocols protocols)
throws InvalidKeyException, StorageException {
throws StorageException, InvalidKeyException {
return this.generateSharedAccessSignature(policy, headers, groupPolicyIdentifier, ipRange, protocols, false);
}

/**
* Returns a shared access signature for the blob using the specified group policy identifier and operation context.
* Note this does not contain the leading "?".
*
* @param policy
* A <code>{@link SharedAccessPolicy}</code> object that represents the access policy for the shared
* access signature.
* @param headers
* A <code>{@link SharedAccessBlobHeaders}</code> object that represents the optional header values to
* set for a blob accessed with this shared access signature.
* @param groupPolicyIdentifier
* A <code>String</code> that represents the container-level access policy.
* @param ipRange
* A {@link IPRange} object containing the range of allowed IP addresses.
* @param protocols
* A {@link SharedAccessProtocols} representing the allowed Internet protocols.
* @param skipDecoding
* A <code>boolean</code> to indicate that the query parameters should not be decoded before being
* signed. This should only be used if the customer is sure the values passed are in the desired format.
* This may be useful in some scenarios where the client is used to generate a sas to a third party that
* will not be using this sdk to make the requests.
*
* @return A <code>String</code> that represents the shared access signature.
*
* @throws IllegalArgumentException
* If the credentials are invalid or the blob is a snapshot.
* @throws InvalidKeyException
* If the credentials are invalid.
* @throws StorageException
* If a storage service error occurred.
*/
public String generateSharedAccessSignature(
final SharedAccessBlobPolicy policy, final SharedAccessBlobHeaders headers,
final String groupPolicyIdentifier, final IPRange ipRange, final SharedAccessProtocols protocols,
boolean skipDecoding) throws InvalidKeyException, StorageException {

if (!StorageCredentialsHelper.canCredentialsSignRequest(this.blobServiceClient.getCredentials())) {
throw new IllegalArgumentException(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
Expand All @@ -2218,7 +2256,7 @@ public String generateSharedAccessSignature(
final String signature = SharedAccessSignatureHelper.generateSharedAccessSignatureHashForBlobAndFile(
policy, headers, groupPolicyIdentifier, resourceName, ipRange, protocols, this.blobServiceClient,
this.isSnapshot() ? Constants.QueryConstants.BLOB_SNAPSHOT_SERVICE : Constants.QueryConstants.BLOB_RESOURCE,
this.getSnapshotID());
this.getSnapshotID(), skipDecoding);

final UriQueryBuilder builder = SharedAccessSignatureHelper.generateSharedAccessSignatureForBlobAndFile(
policy, headers, groupPolicyIdentifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,38 @@ public static String generateSharedAccessSignatureHashForBlobAndFile(final Share
SharedAccessHeaders headers, final String accessPolicyIdentifier, final String resourceName,
final IPRange ipRange, final SharedAccessProtocols protocols, final ServiceClient client,
final String service, final String snapshotId) throws InvalidKeyException, StorageException {
return generateSharedAccessSignatureHashForBlobAndFile(policy, headers, accessPolicyIdentifier, resourceName,
ipRange,protocols, client, service, snapshotId, false);
}

/**
* Get the signature hash embedded inside the Shared Access Signature for the blob or file service.
*
* @param policy
* The shared access policy to hash.
* @param headers
* The optional header values to set for a blob or file accessed with this shared access signature.
* @param accessPolicyIdentifier
* An optional identifier for the policy.
* @param resourceName
* The resource name.
* @param ipRange
* The range of IP addresses to hash.
* @param protocols
* The Internet protocols to hash.
* @param client
* The ServiceClient associated with the object.
* @param skipDecoding
* Skip decoding the string to sign before signing.
*
* @return The signature hash embedded inside the Shared Access Signature.
* @throws InvalidKeyException
* @throws StorageException
*/
public static String generateSharedAccessSignatureHashForBlobAndFile(final SharedAccessPolicy policy,
SharedAccessHeaders headers, final String accessPolicyIdentifier, final String resourceName,
final IPRange ipRange, final SharedAccessProtocols protocols, final ServiceClient client,
final String service, final String snapshotId, boolean skipDecoding) throws InvalidKeyException, StorageException {

String stringToSign = generateSharedAccessSignatureStringToSign(
policy, resourceName, ipRange, protocols, accessPolicyIdentifier);
Expand Down Expand Up @@ -341,7 +373,7 @@ public static String generateSharedAccessSignatureHashForBlobAndFile(final Share
contentLanguage == null ? Constants.EMPTY_STRING : contentLanguage,
contentType == null ? Constants.EMPTY_STRING : contentType);

return generateSharedAccessSignatureHashHelper(stringToSign, client.getCredentials());
return generateSharedAccessSignatureHashHelper(stringToSign, client.getCredentials(), skipDecoding);
}

/**
Expand Down Expand Up @@ -692,12 +724,34 @@ private static UriQueryBuilder generateSharedAccessSignatureHelper(
*/
private static String generateSharedAccessSignatureHashHelper(String stringToSign, final StorageCredentials creds)
throws StorageException, InvalidKeyException {
return generateSharedAccessSignatureHashHelper(stringToSign, creds, false);
}

/**
* Get the signature hash embedded inside the Shared Access Signature.
*
* @param stringToSign
* The string to decode and hash
* @param creds
* Reference to the {@link StorageCredentials}.
* @param skipDecoding
* Skip decoding the string to sign before signing.
*
* @return The signature hash embedded inside the Shared Access Signature.
*
* @throws InvalidKeyException
* @throws StorageException
*/
private static String generateSharedAccessSignatureHashHelper(String stringToSign, final StorageCredentials creds,
boolean skipDecoding) throws StorageException, InvalidKeyException {

Utility.assertNotNull("credentials", creds);

Logger.trace(null, LogConstants.SIGNING, stringToSign);

stringToSign = Utility.safeDecode(stringToSign);
if (!skipDecoding) {
stringToSign = Utility.safeDecode(stringToSign);
}
return StorageCredentialsHelper.computeHmac256(creds, stringToSign);
}

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage</artifactId>
<version>8.5.0</version>
<version>8.6.0</version>
<packaging>jar</packaging>

<name>Microsoft Azure Storage Client SDK</name>
Expand Down

0 comments on commit 9beae8b

Please sign in to comment.