mirror of
https://github.com/apache/jclouds.git
synced 2025-03-03 06:49:11 +00:00
[JCLOUDS-1428] Support for SAS token based Authentication for Azure Blob Storage (#1270)
This commit is contained in:
parent
b3aa23bb05
commit
0ce926108e
@ -21,10 +21,13 @@ import static com.google.common.io.ByteStreams.readBytes;
|
||||
import static org.jclouds.crypto.Macs.asByteProcessor;
|
||||
import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
|
||||
import static org.jclouds.util.Strings2.toInputStream;
|
||||
import org.jclouds.http.Uris.UriBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import org.jclouds.http.Uris;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
@ -67,12 +70,15 @@ import com.google.common.net.HttpHeaders;
|
||||
@Singleton
|
||||
public class SharedKeyLiteAuthentication implements HttpRequestFilter {
|
||||
private static final Collection<String> FIRST_HEADERS_TO_SIGN = ImmutableList.of(HttpHeaders.DATE);
|
||||
|
||||
private final SignatureWire signatureWire;
|
||||
private final Supplier<Credentials> creds;
|
||||
private final Provider<String> timeStampProvider;
|
||||
private final Crypto crypto;
|
||||
private final String credential;
|
||||
private final String identity;
|
||||
private final HttpUtils utils;
|
||||
private final URI storageUrl;
|
||||
private final boolean isSAS;
|
||||
|
||||
@Resource
|
||||
@Named(Constants.LOGGER_SIGNATURE)
|
||||
@ -81,27 +87,73 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
|
||||
@Inject
|
||||
public SharedKeyLiteAuthentication(SignatureWire signatureWire,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds, @TimeStamp Provider<String> timeStampProvider,
|
||||
Crypto crypto, HttpUtils utils) {
|
||||
Crypto crypto, HttpUtils utils, @Named("sasAuth") boolean sasAuthentication) {
|
||||
this.crypto = crypto;
|
||||
this.utils = utils;
|
||||
this.signatureWire = signatureWire;
|
||||
this.storageUrl = URI.create("https://" + creds.get().identity + ".blob.core.windows.net/");
|
||||
this.creds = creds;
|
||||
this.identity = creds.get().identity;
|
||||
this.credential = creds.get().credential;
|
||||
this.timeStampProvider = timeStampProvider;
|
||||
this.isSAS = sasAuthentication;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this is an updated filter method, which decides whether the SAS or SharedKeyLite
|
||||
* is used and applies the right filtering.
|
||||
*/
|
||||
public HttpRequest filter(HttpRequest request) throws HttpException {
|
||||
request = replaceDateHeader(request);
|
||||
String signature = calculateSignature(createStringToSign(request));
|
||||
request = replaceAuthorizationHeader(request, signature);
|
||||
request = this.isSAS ? filterSAS(request, this.credential) : filterKey(request);
|
||||
utils.logRequest(signatureLog, request, "<<");
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this filter method is applied only for the cases with SAS Authentication.
|
||||
*/
|
||||
public HttpRequest filterSAS(HttpRequest request, String credential) throws HttpException, IllegalArgumentException {
|
||||
URI requestUri = request.getEndpoint();
|
||||
String formattedCredential = credential.startsWith("?") ? credential.substring(1) : credential;
|
||||
String initialQuery = requestUri.getQuery();
|
||||
String finalQuery = initialQuery == null ? formattedCredential : initialQuery + "&" + formattedCredential;
|
||||
String[] parametersArray = cutUri(requestUri);
|
||||
String containerName = parametersArray[1];
|
||||
UriBuilder endpoint = Uris.uriBuilder(storageUrl).appendPath(containerName);
|
||||
if (parametersArray.length == 3) {
|
||||
endpoint.appendPath(parametersArray[2]).query(finalQuery);
|
||||
} else {
|
||||
endpoint.query("restype=container&" + finalQuery);
|
||||
}
|
||||
return removeAuthorizationHeader(
|
||||
replaceDateHeader(request.toBuilder()
|
||||
.endpoint(endpoint.build())
|
||||
.build()));
|
||||
}
|
||||
|
||||
/**
|
||||
* this is a 'standard' filter method, applied when SharedKeyLite authentication is used.
|
||||
*/
|
||||
public HttpRequest filterKey(HttpRequest request) throws HttpException {
|
||||
request = replaceDateHeader(request);
|
||||
String signature = calculateSignature(createStringToSign(request));
|
||||
return replaceAuthorizationHeader(request, signature);
|
||||
}
|
||||
|
||||
HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
|
||||
return request.toBuilder()
|
||||
.replaceHeader(HttpHeaders.AUTHORIZATION, "SharedKeyLite " + creds.get().identity + ":" + signature)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* this method removes Authorisation header, since it is not needed for SAS Authentication
|
||||
*/
|
||||
HttpRequest removeAuthorizationHeader(HttpRequest request) {
|
||||
return request.toBuilder()
|
||||
.removeHeader(HttpHeaders.AUTHORIZATION)
|
||||
.build();
|
||||
}
|
||||
|
||||
HttpRequest replaceDateHeader(HttpRequest request) {
|
||||
Builder<String, String> builder = ImmutableMap.builder();
|
||||
@ -110,6 +162,18 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
|
||||
request = request.toBuilder().replaceHeaders(Multimaps.forMap(builder.build())).build();
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* this is the method to parse container name and blob name from the HttpRequest.
|
||||
*/
|
||||
public String[] cutUri(URI uri) throws IllegalArgumentException {
|
||||
String path = uri.getPath();
|
||||
String[] result = path.split("/");
|
||||
if (result.length < 2) {
|
||||
throw new IllegalArgumentException("there is neither ContainerName nor BlobName in the URI path");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String createStringToSign(HttpRequest request) {
|
||||
utils.logRequest(signatureLog, request, ">>");
|
||||
|
@ -23,6 +23,7 @@ import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
|
||||
import org.jclouds.blobstore.BlobRequestSigner;
|
||||
@ -35,11 +36,11 @@ import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.Uris;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
|
||||
@Singleton
|
||||
public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||
private static final int DEFAULT_EXPIRY_SECONDS = 15 * 60;
|
||||
@ -51,19 +52,23 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||
private final Provider<String> timeStampProvider;
|
||||
private final DateService dateService;
|
||||
private final SharedKeyLiteAuthentication auth;
|
||||
private final String credential;
|
||||
private final boolean isSAS;
|
||||
|
||||
@Inject
|
||||
public AzureBlobRequestSigner(
|
||||
BlobToHttpGetOptions blob2HttpGetOptions, @TimeStamp Provider<String> timeStampProvider,
|
||||
DateService dateService, SharedKeyLiteAuthentication auth,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds)
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds, @Named("sasAuth") boolean sasAuthentication)
|
||||
throws SecurityException, NoSuchMethodException {
|
||||
this.identity = creds.get().identity;
|
||||
this.credential = creds.get().credential;
|
||||
this.storageUrl = URI.create("https://" + creds.get().identity + ".blob.core.windows.net/");
|
||||
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
|
||||
this.timeStampProvider = checkNotNull(timeStampProvider, "timeStampProvider");
|
||||
this.dateService = checkNotNull(dateService, "dateService");
|
||||
this.auth = auth;
|
||||
this.isSAS = sasAuthentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -107,12 +112,14 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||
return sign("GET", container, name, blob2HttpGetOptions.apply(checkNotNull(options, "options")),
|
||||
DEFAULT_EXPIRY_SECONDS, null, null);
|
||||
}
|
||||
|
||||
private HttpRequest sign(String method, String container, String name, @Nullable GetOptions options, long expires, @Nullable Long contentLength, @Nullable String contentType) {
|
||||
|
||||
/**
|
||||
* method to sign HttpRequest when SharedKey Authentication is used
|
||||
*/
|
||||
private HttpRequest signKey(String method, String container, String name, @Nullable GetOptions options, long expires, @Nullable Long contentLength, @Nullable String contentType) {
|
||||
checkNotNull(method, "method");
|
||||
checkNotNull(container, "container");
|
||||
checkNotNull(name, "name");
|
||||
|
||||
String nowString = timeStampProvider.get();
|
||||
Date now = dateService.rfc1123DateParse(nowString);
|
||||
Date expiration = new Date(now.getTime() + TimeUnit.SECONDS.toMillis(expires));
|
||||
@ -125,7 +132,6 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||
} else {
|
||||
signedPermission = "r";
|
||||
}
|
||||
|
||||
HttpRequest.Builder request = HttpRequest.builder()
|
||||
.method(method)
|
||||
.endpoint(Uris.uriBuilder(storageUrl).appendPath(container).appendPath(name).build())
|
||||
@ -134,23 +140,7 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||
.addQueryParam("se", iso8601)
|
||||
.addQueryParam("sr", "b") // blob resource
|
||||
.addQueryParam("sp", signedPermission); // permission
|
||||
|
||||
if (contentLength != null) {
|
||||
request.replaceHeader(HttpHeaders.CONTENT_LENGTH, contentLength.toString());
|
||||
}
|
||||
|
||||
if (contentType != null) {
|
||||
request.replaceHeader("x-ms-blob-content-type", contentType);
|
||||
}
|
||||
|
||||
if (options != null) {
|
||||
request.headers(options.buildRequestHeaders());
|
||||
}
|
||||
|
||||
if (method.equals("PUT")) {
|
||||
request.replaceHeader("x-ms-blob-type", "BlockBlob");
|
||||
}
|
||||
|
||||
request = setHeaders(request, method, options, contentLength, contentType);
|
||||
String stringToSign =
|
||||
signedPermission + "\n" + // signedpermission
|
||||
"\n" + // signedstart
|
||||
@ -165,9 +155,50 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||
"\n" + // rsce
|
||||
"\n" + // rscl
|
||||
""; // rsct
|
||||
|
||||
String signature = auth.calculateSignature(stringToSign);
|
||||
request.addQueryParam("sig", signature);
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private HttpRequest.Builder setHeaders(HttpRequest.Builder request, String method, @Nullable GetOptions options, @Nullable Long contentLength, @Nullable String contentType){
|
||||
if (contentLength != null) {
|
||||
request.replaceHeader(HttpHeaders.CONTENT_LENGTH, contentLength.toString());
|
||||
}
|
||||
if (contentType != null) {
|
||||
request.replaceHeader("x-ms-blob-content-type", contentType);
|
||||
}
|
||||
if (options != null) {
|
||||
request.headers(options.buildRequestHeaders());
|
||||
}
|
||||
if (method.equals("PUT")) {
|
||||
request.replaceHeader("x-ms-blob-type", "BlockBlob");
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* method, compatible with SAS Authentication
|
||||
*/
|
||||
private HttpRequest signSAS(String method, String container, String name, @Nullable GetOptions options, long expires, @Nullable Long contentLength, @Nullable String contentType) {
|
||||
checkNotNull(method, "method");
|
||||
checkNotNull(container, "container");
|
||||
checkNotNull(name, "name");
|
||||
String nowString = timeStampProvider.get();
|
||||
HttpRequest.Builder request = HttpRequest.builder()
|
||||
.method(method)
|
||||
.endpoint(Uris.uriBuilder(storageUrl).appendPath(container).appendPath(name).query(this.credential).build())
|
||||
.replaceHeader(HttpHeaders.DATE, nowString);
|
||||
request = setHeaders(request, method, options, contentLength, contentType);
|
||||
return request.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* modified sign() method, which acts depending on the Auth input.
|
||||
*/
|
||||
public HttpRequest sign(String method, String container, String name, @Nullable GetOptions options, long expires, @Nullable Long contentLength, @Nullable String contentType) {
|
||||
if (isSAS) {
|
||||
return signSAS(method, container, name, options, expires, contentLength, contentType);
|
||||
}
|
||||
return signKey(method, container, name, options, expires, contentLength, contentType);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,15 @@ package org.jclouds.azureblob.config;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||
|
||||
import static com.google.common.base.Predicates.in;
|
||||
|
||||
import static com.google.common.collect.Iterables.all;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
@ -36,6 +44,7 @@ import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.config.HttpApiModule;
|
||||
import org.jclouds.domain.Credentials;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
@ -63,6 +72,23 @@ public class AzureBlobHttpApiModule extends HttpApiModule<AzureBlobClient> {
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
return cache.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* checks which Authentication type is used
|
||||
*/
|
||||
@Named("sasAuth")
|
||||
@Provides
|
||||
protected boolean authSAS(@org.jclouds.location.Provider Supplier<Credentials> creds) {
|
||||
String credential = creds.get().credential;
|
||||
String formattedCredential = credential.startsWith("?") ? credential.substring(1) : credential;
|
||||
List<String> required = ImmutableList.of("sv", "se", "sig", "sp");
|
||||
try {
|
||||
Map<String, String> tokens = Splitter.on('&').withKeyValueSeparator('=').split(formattedCredential);
|
||||
return all(required, in(tokens.keySet()));
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* borrowing concurrency code to ensure that caching takes place properly
|
||||
|
@ -42,6 +42,8 @@ public class SharedKeyLiteAuthenticationTest {
|
||||
private static final String ACCOUNT = "foo";
|
||||
private Injector injector;
|
||||
private SharedKeyLiteAuthentication filter;
|
||||
private SharedKeyLiteAuthentication filterSAS;
|
||||
private SharedKeyLiteAuthentication filterSASQuestionMark;
|
||||
|
||||
@DataProvider(parallel = true)
|
||||
public Object[][] dataProvider() {
|
||||
@ -52,6 +54,19 @@ public class SharedKeyLiteAuthenticationTest {
|
||||
+ ".blob.core.windows.net/movies/MOV1.avi?comp=blocklist&timeout=120").build() },
|
||||
{ HttpRequest.builder().method(HttpMethod.GET).endpoint("http://" + ACCOUNT + ".blob.core.windows.net/movies/MOV1.avi").build() } };
|
||||
}
|
||||
|
||||
@DataProvider(name = "auth-sas-data", parallel = true)
|
||||
public Object[][] requests(){
|
||||
return new Object[][]{
|
||||
{ HttpRequest.builder().method(HttpMethod.PUT).endpoint("https://" + ACCOUNT
|
||||
+ ".blob.core.windows.net/movies/MOV1.avi?comp=block&blockid=BlockId1&timeout=60").build(), filterSAS, "https://foo.blob.core.windows.net/movies/MOV1.avi?comp=block&blockid=BlockId1&timeout=60&sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-02-13T17%3A18%3A22Z&st=2019-02-13T09%3A18%3A22Z&spr=https&sig=sMnaKSD94CzEPeGnWauTT0wBNIn%2B4ySkZO5PEAW7zs%3D"},
|
||||
{ HttpRequest.builder().method(HttpMethod.PUT).endpoint("https://" + ACCOUNT
|
||||
+ ".blob.core.windows.net/movies/MOV1.avi?comp=blocklist&timeout=120").build(), filterSAS, "https://foo.blob.core.windows.net/movies/MOV1.avi?comp=blocklist&timeout=120&sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-02-13T17%3A18%3A22Z&st=2019-02-13T09%3A18%3A22Z&spr=https&sig=sMnaKSD94CzEPeGnWauTT0wBNIn%2B4ySkZO5PEAW7zs%3D" },
|
||||
{ HttpRequest.builder().method(HttpMethod.GET).endpoint("https://" + ACCOUNT
|
||||
+ ".blob.core.windows.net/movies/MOV1.avi").build(), filterSAS, "https://foo.blob.core.windows.net/movies/MOV1.avi?sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-02-13T17%3A18%3A22Z&st=2019-02-13T09%3A18%3A22Z&spr=https&sig=sMnaKSD94CzEPeGnWauTT0wBNIn%2B4ySkZO5PEAW7zs%3D" },
|
||||
{ HttpRequest.builder().method(HttpMethod.GET).endpoint("https://" + ACCOUNT
|
||||
+ ".blob.core.windows.net/movies/MOV1.avi").build(), filterSASQuestionMark, "https://foo.blob.core.windows.net/movies/MOV1.avi?sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-02-13T17%3A18%3A22Z&st=2019-02-13T09%3A18%3A22Z&spr=https&sig=sMnaKSD94CzEPeGnWauTT0wBNIn%2B4ySkZO5PEAW7zs%3D" } };
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE this test is dependent on how frequently the timestamp updates. At
|
||||
@ -74,6 +89,15 @@ public class SharedKeyLiteAuthenticationTest {
|
||||
System.out.printf("%s: %d iterations before the timestamp updated %n", Thread.currentThread().getName(),
|
||||
iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* this test is similar to testIdempotent; it checks whether request is properly filtered when it comes to SAS Authentication
|
||||
*/
|
||||
@Test(dataProvider = "auth-sas-data")
|
||||
void testFilter(HttpRequest request, SharedKeyLiteAuthentication filter, String expected) {
|
||||
request = filter.filter(request);
|
||||
assertEquals(request.getEndpoint().toString(), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAclQueryStringRoot() {
|
||||
@ -127,5 +151,19 @@ public class SharedKeyLiteAuthenticationTest {
|
||||
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule()))
|
||||
.buildInjector();
|
||||
filter = injector.getInstance(SharedKeyLiteAuthentication.class);
|
||||
injector = ContextBuilder
|
||||
.newBuilder("azureblob")
|
||||
.endpoint("https://${jclouds.identity}.blob.core.windows.net")
|
||||
.credentials(ACCOUNT, "sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-02-13T17:18:22Z&st=2019-02-13T09:18:22Z&spr=https&sig=sMnaKSD94CzEPeGnWauTT0wBNIn%2B4ySkZO5PEAW7zs%3D")
|
||||
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule()))
|
||||
.buildInjector();
|
||||
filterSAS = injector.getInstance(SharedKeyLiteAuthentication.class);
|
||||
injector = ContextBuilder
|
||||
.newBuilder("azureblob")
|
||||
.endpoint("https://${jclouds.identity}.blob.core.windows.net")
|
||||
.credentials(ACCOUNT, "?sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-02-13T17:18:22Z&st=2019-02-13T09:18:22Z&spr=https&sig=sMnaKSD94CzEPeGnWauTT0wBNIn%2B4ySkZO5PEAW7zs%3D")
|
||||
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule()))
|
||||
.buildInjector();
|
||||
filterSASQuestionMark = injector.getInstance(SharedKeyLiteAuthentication.class);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.azureblob.config;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
@Test(groups = "unit", testName = "AzureBlobHttpApiModuleTest")
|
||||
public class AzureBlobHttpApiModuleTest {
|
||||
|
||||
@DataProvider(name = "auth-sas-tokens")
|
||||
public static Object[][] tokens() {
|
||||
return new Object[][]{
|
||||
{false, "sv=2018-03-28&se=2019-02-14T11:12:13Z"},
|
||||
{false, "sv=2018-03-28&se=2019-02-14T11:12:13Z&sp=abc&st=2019-01-20T11:12:13Z"},
|
||||
{false, "u2iAP01ARTewyK/MhOM1d1ASPpjqclkldsdkljfas2kfjkh895ssfslkjpXKfhg=="},
|
||||
{false, "sadf;gjkhflgjkhfdlkfdljghskldjghlfdghw4986754ltjkghdlfkjghst;lyho56[09y7poinh"},
|
||||
{false, "a=apple&b=banana&c=cucumber&d=diet"},
|
||||
{false, "sva=swajak&sta=stancyja&spa=spakoj&sea=mora&sig=podpis"},
|
||||
{true, "sv=2018-03-28&ss=b&srt=sco&sp=r&se=2019-02-13T17:03:09Z&st=2019-02-13T09:03:09Z&spr=https&sig=wNkWK%2GURTjHWhtqG6Q2Gu%2Qu%3FPukW6N4%2FIH4Mr%2F%2FO42M%3D"},
|
||||
{true, "sp=rl&st=2019-02-14T08:50:26Z&se=2019-02-15T08:50:26Z&sv=2018-03-28&sig=Ukow8%2GtpQpAiVZBLcWp1%2RSpFq928MAqzp%2BdrdregaB6%3D&sr=b"},
|
||||
{false, ""}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "auth-sas-tokens")
|
||||
void testAuthSasNonSufficientParametersSvSe(boolean expected, String credential){
|
||||
AzureBlobHttpApiModule module = new AzureBlobHttpApiModule();
|
||||
Credentials creds = new Credentials("identity", credential);
|
||||
assertEquals(module.authSAS(Suppliers.ofInstance(creds)), expected);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user