Skip to content
Permalink
Browse files
JCLOUDS-1557 - Azure local server support
Co-authored-by: David Sloan <david.sloan@lenses.io>
  • Loading branch information
davidsloan and davidsloan committed Dec 8, 2020
1 parent 3a7e41f commit 17fd80cd5a10ed2ab6886ad436f51b62ad0a826d
Showing 11 changed files with 414 additions and 31 deletions.
@@ -21,44 +21,45 @@
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.net.URI;
import java.util.Arrays;
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;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import org.jclouds.Constants;
import org.jclouds.azure.storage.util.storageurl.StorageUrlSupplier;
import org.jclouds.crypto.Crypto;
import org.jclouds.date.TimeStamp;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.Uris;
import org.jclouds.http.Uris.UriBuilder;
import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger;
import org.jclouds.util.Strings2;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.io.ByteProcessor;
import com.google.common.net.HttpHeaders;
@@ -76,7 +77,6 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
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;
@@ -88,13 +88,13 @@ 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, @Named("sasAuth") boolean sasAuthentication) {
Crypto crypto, HttpUtils utils, @Named("sasAuth") boolean sasAuthentication,
StorageUrlSupplier storageUrlSupplier) {
this.crypto = crypto;
this.utils = utils;
this.signatureWire = signatureWire;
this.storageUrl = URI.create("https://" + creds.get().identity + ".blob.core.windows.net/");
this.storageUrl = storageUrlSupplier.get();
this.creds = creds;
this.identity = creds.get().identity;
this.credential = creds.get().credential;
this.timeStampProvider = timeStampProvider;
this.isSAS = sasAuthentication;
@@ -0,0 +1,58 @@
/*
* 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.azure.storage.util.storageurl;

import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;

import javax.inject.Inject;
import javax.inject.Singleton;

import static org.jclouds.azure.storage.util.storageurl.TrailingSlashUtil.ensureTrailingSlash;
import java.net.URI;

@Singleton
public class AppendAccountToEndpoint implements StorageUrlSupplier {

private final Supplier<URI> endpointSupplier;
private final Supplier<Credentials> credentialsSupplier;

@Inject
public AppendAccountToEndpoint(@Provider Supplier<URI> endpointSupplier, @Provider Supplier<Credentials> credentialsSupplier) {
this.endpointSupplier = endpointSupplier;
this.credentialsSupplier = credentialsSupplier;
}

@Override
public URI get() {

URI endpoint = endpointSupplier.get();

Preconditions.checkNotNull(endpoint, "An endpoint must be configured in order to use AppendAccountToEndpoint module");

String endpointTrailingSlash = new StringBuilder(ensureTrailingSlash(endpoint))
.append(credentialsSupplier.get().identity)
.append("/")
.toString();

return URI.create(endpointTrailingSlash);

}

}
@@ -0,0 +1,55 @@
/*
* 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.azure.storage.util.storageurl;

import com.google.common.base.Supplier;
import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.net.URI;
import static org.jclouds.azure.storage.util.storageurl.TrailingSlashUtil.ensureTrailingSlash;

@Singleton
public class StorageAccountInVhost implements StorageUrlSupplier {

private final Supplier<URI> endpointSupplier;
private final Supplier<Credentials> credentialsSupplier;

@Inject
public StorageAccountInVhost(@Provider Supplier<URI> endpointSupplier, @Provider Supplier<Credentials> credentialsSupplier) {
this.endpointSupplier = endpointSupplier;
this.credentialsSupplier = credentialsSupplier;
}

@Override
public URI get() {

URI endpoint = endpointSupplier.get();

String uri = endpoint == null ? buildUri() : ensureTrailingSlash(endpoint);

return URI.create(uri);

}

private String buildUri() {
return "https://" + credentialsSupplier.get().identity + ".blob.core.windows.net/";
}

}
@@ -0,0 +1,26 @@
/*
* 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.azure.storage.util.storageurl;

import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;

import java.net.URI;

@ImplementedBy(StorageAccountInVhost.class)
public interface StorageUrlSupplier extends Supplier<URI> {
}
@@ -0,0 +1,28 @@
/*
* 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.azure.storage.util.storageurl;

import java.net.URI;

public class TrailingSlashUtil {

static String ensureTrailingSlash(URI endpointUri) {
String endpoint = endpointUri.toString();
return endpoint.endsWith("/") ? endpoint : endpoint + "/";
}

}
@@ -21,11 +21,13 @@
import java.net.URI;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.inject.Named;
import javax.inject.Singleton;

import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.azure.storage.util.storageurl.StorageUrlSupplier;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
@@ -36,6 +38,7 @@
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;
@@ -53,17 +56,18 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
private final DateService dateService;
private final SharedKeyLiteAuthentication auth;
private final String credential;
private final boolean isSAS;
private final boolean isSAS;

@Inject
public AzureBlobRequestSigner(
BlobToHttpGetOptions blob2HttpGetOptions, @TimeStamp Provider<String> timeStampProvider,
DateService dateService, SharedKeyLiteAuthentication auth,
@org.jclouds.location.Provider Supplier<Credentials> creds, @Named("sasAuth") boolean sasAuthentication)
@org.jclouds.location.Provider Supplier<Credentials> creds, @Named("sasAuth") boolean sasAuthentication,
StorageUrlSupplier storageUriSupplier)
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.storageUrl = storageUriSupplier.get();
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
this.timeStampProvider = checkNotNull(timeStampProvider, "timeStampProvider");
this.dateService = checkNotNull(dateService, "dateService");
@@ -16,27 +16,24 @@
*/
package org.jclouds.azureblob.blobstore.config;

import java.util.concurrent.TimeUnit;

import javax.inject.Singleton;
import javax.inject.Named;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import org.jclouds.azureblob.AzureBlobClient;
import org.jclouds.azureblob.blobstore.AzureBlobRequestSigner;
import org.jclouds.azureblob.blobstore.AzureBlobStore;
import org.jclouds.azureblob.config.InsufficientAccessRightsException;
import org.jclouds.azureblob.domain.PublicAccess;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.azureblob.config.InsufficientAccessRightsException;


import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.concurrent.TimeUnit;

public class AzureBlobStoreContextModule extends AbstractModule {

@@ -0,0 +1,30 @@
/*
* 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 com.google.inject.AbstractModule;
import org.jclouds.azure.storage.util.storageurl.AppendAccountToEndpoint;
import org.jclouds.azure.storage.util.storageurl.StorageUrlSupplier;

public class AppendAccountToEndpointModule extends AbstractModule {

@Override
protected void configure() {
bind(StorageUrlSupplier.class).to(AppendAccountToEndpoint.class);
}

}
@@ -44,6 +44,7 @@ public class SharedKeyLiteAuthenticationTest {
private SharedKeyLiteAuthentication filter;
private SharedKeyLiteAuthentication filterSAS;
private SharedKeyLiteAuthentication filterSASQuestionMark;
private SharedKeyLiteAuthentication filterSASCustomEndpoint;

@DataProvider(parallel = true)
public Object[][] dataProvider() {
@@ -67,8 +68,11 @@ public Object[][] requests(){
{ 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" } };
}
+ ".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" },
{ HttpRequest.builder().method(HttpMethod.GET).endpoint("http://my-custom-endpoint.net/movies/MOV1.avi").build(), filterSASCustomEndpoint,
"http://my-custom-endpoint.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
@@ -167,5 +171,12 @@ protected void createFilter() throws IOException {
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule()))
.buildInjector();
filterSASQuestionMark = injector.getInstance(SharedKeyLiteAuthentication.class);
injector = ContextBuilder
.newBuilder("azureblob")
.endpoint("http://my-custom-endpoint.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();
filterSASCustomEndpoint = injector.getInstance(SharedKeyLiteAuthentication.class);
}
}

0 comments on commit 17fd80c

Please sign in to comment.