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

Commit ececde6

Browse files
authored
Merge pull request #357 from lrdcasimir/fix-sas-null-parameters
Fix Service SAS null parameters
2 parents 1e7f879 + 17ffe32 commit ececde6

File tree

3 files changed

+93
-27
lines changed

3 files changed

+93
-27
lines changed

src/main/java/com/microsoft/azure/storage/blob/AccountSASSignatureValues.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,7 @@ public SASQueryParameters generateSASQueryParameters(SharedKeyCredentials shared
106106
Utility.assertNotNull("permissions", this.permissions);
107107

108108
// Signature is generated on the un-url-encoded values.
109-
String stringToSign = String.join("\n",
110-
sharedKeyCredentials.getAccountName(),
111-
AccountSASPermission.parse(this.permissions).toString(), // guarantees ordering
112-
this.services,
113-
resourceTypes,
114-
this.startTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.startTime),
115-
this.expiryTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.expiryTime),
116-
this.ipRange == null ? IPRange.DEFAULT.toString() : this.ipRange.toString(),
117-
this.protocol == null ? "" : this.protocol.toString(),
118-
this.version,
119-
Constants.EMPTY_STRING // Account SAS requires an additional newline character
120-
);
109+
final String stringToSign = stringToSign(sharedKeyCredentials);
121110

122111
String signature;
123112
try {
@@ -130,4 +119,19 @@ public SASQueryParameters generateSASQueryParameters(SharedKeyCredentials shared
130119
this.protocol, this.startTime, this.expiryTime, this.ipRange, null,
131120
null, this.permissions, signature);
132121
}
122+
123+
private String stringToSign(final SharedKeyCredentials sharedKeyCredentials) {
124+
return String.join("\n",
125+
sharedKeyCredentials.getAccountName(),
126+
AccountSASPermission.parse(this.permissions).toString(), // guarantees ordering
127+
this.services,
128+
resourceTypes,
129+
this.startTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.startTime),
130+
this.expiryTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.expiryTime),
131+
this.ipRange == null ? IPRange.DEFAULT.toString() : this.ipRange.toString(),
132+
this.protocol == null ? "" : this.protocol.toString(),
133+
this.version,
134+
Constants.EMPTY_STRING // Account SAS requires an additional newline character
135+
);
136+
}
133137
}

src/main/java/com/microsoft/azure/storage/blob/ServiceSASSignatureValues.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,21 +143,7 @@ public SASQueryParameters generateSASQueryParameters(SharedKeyCredentials shared
143143
}
144144

145145
// Signature is generated on the un-url-encoded values.
146-
String stringToSign = String.join("\n",
147-
verifiedPermissions,
148-
this.startTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.startTime),
149-
this.expiryTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.expiryTime),
150-
getCanonicalName(sharedKeyCredentials.getAccountName()),
151-
this.identifier,
152-
this.ipRange == null ? IPRange.DEFAULT.toString() : this.ipRange.toString(),
153-
this.protocol == null ? "" : protocol.toString(),
154-
this.version,
155-
this.cacheControl,
156-
this.contentDisposition,
157-
this.contentEncoding,
158-
this.contentLanguage,
159-
this.contentType
160-
);
146+
final String stringToSign = stringToSign(verifiedPermissions, sharedKeyCredentials);
161147

162148
String signature = null;
163149
try {
@@ -183,4 +169,23 @@ private String getCanonicalName(String accountName) {
183169

184170
return canonicalName.toString();
185171
}
172+
173+
private String stringToSign(final String verifiedPermissions,
174+
final SharedKeyCredentials sharedKeyCredentials) {
175+
return String.join("\n",
176+
verifiedPermissions,
177+
this.startTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.startTime),
178+
this.expiryTime == null ? "" : Utility.ISO8601UTCDateFormatter.format(this.expiryTime),
179+
getCanonicalName(sharedKeyCredentials.getAccountName()),
180+
this.identifier == null ? "" : this.identifier,
181+
this.ipRange == null ? IPRange.DEFAULT.toString() : this.ipRange.toString(),
182+
this.protocol == null ? "" : protocol.toString(),
183+
this.version,
184+
this.cacheControl == null ? "" : this.cacheControl,
185+
this.contentDisposition == null ? "" : this.contentDisposition,
186+
this.contentEncoding == null ? "" : this.contentEncoding,
187+
this.contentLanguage == null ? "" : this.contentLanguage,
188+
this.contentType == null ? "" : this.contentType
189+
);
190+
}
186191
}

src/test/java/com/microsoft/azure/storage/HelperTest.groovy

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@
1515

1616
package com.microsoft.azure.storage
1717

18+
import com.microsoft.azure.storage.blob.AccountSASResourceType
19+
import com.microsoft.azure.storage.blob.AccountSASService
20+
import com.microsoft.azure.storage.blob.AccountSASSignatureValues
21+
import com.microsoft.azure.storage.blob.BlobSASPermission
22+
import com.microsoft.azure.storage.blob.ContainerSASPermission
23+
import com.microsoft.azure.storage.blob.IPRange
1824
import com.microsoft.azure.storage.blob.RequestRetryFactory
1925
import com.microsoft.azure.storage.blob.RequestRetryOptions
2026
import com.microsoft.azure.storage.blob.RequestRetryTestFactory
2127
import com.microsoft.azure.storage.blob.RetryPolicyType
28+
import com.microsoft.azure.storage.blob.SASProtocol
29+
import com.microsoft.azure.storage.blob.ServiceSASSignatureValues
2230
import com.microsoft.azure.storage.blob.StorageException
31+
import com.microsoft.azure.storage.blob.Utility
2332
import com.microsoft.azure.storage.blob.models.StorageErrorCode
2433
import com.microsoft.azure.storage.blob.models.StorageErrorException
2534
import com.microsoft.rest.v2.http.HttpHeaders
@@ -30,6 +39,10 @@ import com.microsoft.rest.v2.http.HttpResponse
3039
import io.reactivex.Flowable
3140
import spock.lang.Unroll
3241

42+
import java.time.OffsetDateTime
43+
import java.time.ZoneOffset
44+
import java.time.ZonedDateTime
45+
3346
class HelperTest extends APISpec {
3447

3548
def "responseError"() {
@@ -43,4 +56,48 @@ class HelperTest extends APISpec {
4356
e.message().contains("Value for one of the query parameters specified in the request URI is invalid.")
4457
e.getMessage().contains("<?xml") // Ensure that the details in the payload are printable
4558
}
59+
60+
def "serviceSasSignatures"() {
61+
when:
62+
def v = new ServiceSASSignatureValues()
63+
v.blobName = "foo"
64+
v.containerName = "bar"
65+
v.expiryTime = OffsetDateTime.of(2017, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)
66+
v.protocol = SASProtocol.HTTPS_ONLY
67+
def p = new BlobSASPermission()
68+
p.read = true
69+
v.permissions = p.toString();
70+
def expectedCanonicalName = "/blob/${primaryCreds.accountName}/${v.containerName}/${v.blobName}"
71+
def expectedStringToSign = "${v.permissions}\n\n${Utility.ISO8601UTCDateFormatter.format(v.expiryTime)}\n${expectedCanonicalName}\n\n${IPRange.DEFAULT.toString()}\n${v.protocol}\n${v.version}\n\n\n\n\n"
72+
73+
def token = v.generateSASQueryParameters(primaryCreds)
74+
75+
then:
76+
token.signature == primaryCreds.computeHmac256(expectedStringToSign)
77+
}
78+
79+
def "accountSasSignatures"() {
80+
when:
81+
def v = new AccountSASSignatureValues()
82+
v.expiryTime = OffsetDateTime.of(2017, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)
83+
v.protocol = SASProtocol.HTTPS_ONLY
84+
def p = new ContainerSASPermission()
85+
p.read = true
86+
v.permissions = p.toString()
87+
def s = new AccountSASService()
88+
s.blob = true
89+
v.services = s.toString()
90+
def t = new AccountSASResourceType()
91+
t.container = true
92+
t.object = true
93+
v.resourceTypes = t.toString()
94+
def expectedStringToSign = "${primaryCreds.accountName}\n${p.toString()}\n${v.services}\n${v.resourceTypes}\n\n${Utility.ISO8601UTCDateFormatter.format(v.expiryTime)}\n${IPRange.DEFAULT.toString()}\n${SASProtocol.HTTPS_ONLY}\n${v.version}\n"
95+
def token = v.generateSASQueryParameters(primaryCreds)
96+
97+
then:
98+
token.signature == primaryCreds.computeHmac256(expectedStringToSign)
99+
100+
}
101+
102+
46103
}

0 commit comments

Comments
 (0)