diff --git a/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java b/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java index 09ac541162..107b97afe4 100644 --- a/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java +++ b/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java @@ -21,42 +21,52 @@ package org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage; public final class AzureConstants { /** - * Azure Stoage Account name + * Azure storage account name */ public static final String AZURE_STORAGE_ACCOUNT_NAME = "accessKey"; /** - * Azure Stoage Account Key + * Azure storage account key */ public static final String AZURE_STORAGE_ACCOUNT_KEY = "secretKey"; /** - * Azure Blob Storage container name + * Azure shared access signature token + */ + public static final String AZURE_SAS = "azureSas"; + + /** + * Azure blob endpoint + */ + public static final String AZURE_BLOB_ENDPOINT = "azureBlobEndpoint"; + + /** + * Azure blob storage container name */ public static final String AZURE_BLOB_CONTAINER_NAME = "container"; /** - * Azure Blob Storage request timeout. + * Azure blob storage request timeout */ public static final String AZURE_BLOB_REQUEST_TIMEOUT = "socketTimeout"; /** - * Azure Blob Storage maximum retries per request. + * Azure blob storage maximum retries per request */ public static final String AZURE_BLOB_MAX_REQUEST_RETRY = "maxErrorRetry"; /** - * Azure Blob Storage maximum connections per operation (default 1) + * Azure blob storage maximum connections per operation (default 1) */ public static final String AZURE_BLOB_CONCURRENT_REQUESTS_PER_OPERATION = "maxConnections"; /** - * Constant to set proxy host. + * Proxy host */ public static final String PROXY_HOST = "proxyHost"; /** - * Constant to set proxy port. + * Proxy port */ public static final String PROXY_PORT = "proxyPort"; diff --git a/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/Utils.java b/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/Utils.java index d4305973fa..4a4213e372 100644 --- a/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/Utils.java +++ b/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/Utils.java @@ -101,11 +101,23 @@ public final class Utils { public static String getConnectionStringFromProperties(Properties properties) { + + String sasUri = properties.getProperty(AzureConstants.AZURE_SAS, ""); + String blobEndpoint = properties.getProperty(AzureConstants.AZURE_BLOB_ENDPOINT, ""); + + if (!sasUri.isEmpty()) { + return getConnectionStringForSas(sasUri, blobEndpoint); + } + return getConnectionString( properties.getProperty(AzureConstants.AZURE_STORAGE_ACCOUNT_NAME, ""), properties.getProperty(AzureConstants.AZURE_STORAGE_ACCOUNT_KEY, "")); } + private static String getConnectionStringForSas(String sasUri, String blobEndpoint) { + return String.format("BlobEndpoint=%s;SharedAccessSignature=%s", blobEndpoint, sasUri); + } + public static String getConnectionString(final String accountName, final String accountKey) { return String.format( "DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s", diff --git a/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStoreUtils.java b/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStoreUtils.java index e8ad0ef59c..76adcdddc1 100644 --- a/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStoreUtils.java +++ b/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataStoreUtils.java @@ -52,10 +52,15 @@ public class AzureDataStoreUtils extends DataStoreUtils { */ public static boolean isAzureConfigured() { Properties props = getAzureConfig(); + //need either access keys or sas if (!props.containsKey(AzureConstants.AZURE_STORAGE_ACCOUNT_KEY) || !props.containsKey(AzureConstants.AZURE_STORAGE_ACCOUNT_NAME) || !(props.containsKey(AzureConstants.AZURE_BLOB_CONTAINER_NAME))) { + if (!props.containsKey(AzureConstants.AZURE_SAS) || !props.containsKey(AzureConstants.AZURE_BLOB_ENDPOINT) + || !(props.containsKey(AzureConstants.AZURE_BLOB_CONTAINER_NAME))) { return false; } + + } return true; } diff --git a/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/UtilsTest.java b/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/UtilsTest.java new file mode 100644 index 0000000000..81f64964c7 --- /dev/null +++ b/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/UtilsTest.java @@ -0,0 +1,63 @@ +/* + * 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.apache.jackrabbit.oak.blob.cloud.azure.blobstorage; + +import org.junit.Test; + +import java.util.Properties; + +import static org.junit.Assert.assertEquals; + +public class UtilsTest { + + @Test + public void testConnectionStringIsBasedOnSAS() { + Properties properties = new Properties(); + properties.put(AzureConstants.AZURE_SAS, "sas"); + properties.put(AzureConstants.AZURE_BLOB_ENDPOINT, "endpoint"); + String connectionString = Utils.getConnectionStringFromProperties(properties); + assertEquals(connectionString, + String.format("BlobEndpoint=%s;SharedAccessSignature=%s", "endpoint", "sas")); + } + + @Test + public void testConnectionStringIsBasedOnAccessKeyIfSASMissing() { + Properties properties = new Properties(); + properties.put(AzureConstants.AZURE_STORAGE_ACCOUNT_NAME, "accessKey"); + properties.put(AzureConstants.AZURE_STORAGE_ACCOUNT_KEY, "secretKey"); + + String connectionString = Utils.getConnectionStringFromProperties(properties); + assertEquals(connectionString, + String.format("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s","accessKey","secretKey")); + } + + @Test + public void testConnectionStringSASIsPriority() { + Properties properties = new Properties(); + properties.put(AzureConstants.AZURE_SAS, "sas"); + properties.put(AzureConstants.AZURE_BLOB_ENDPOINT, "endpoint"); + + properties.put(AzureConstants.AZURE_STORAGE_ACCOUNT_NAME, "accessKey"); + properties.put(AzureConstants.AZURE_STORAGE_ACCOUNT_KEY, "secretKey"); + + String connectionString = Utils.getConnectionStringFromProperties(properties); + assertEquals(connectionString, + String.format("BlobEndpoint=%s;SharedAccessSignature=%s", "endpoint", "sas")); + } + + +} diff --git a/oak-blob-cloud-azure/src/test/resources/azure.properties b/oak-blob-cloud-azure/src/test/resources/azure.properties index c6205c7048..50276365a0 100644 --- a/oak-blob-cloud-azure/src/test/resources/azure.properties +++ b/oak-blob-cloud-azure/src/test/resources/azure.properties @@ -26,6 +26,11 @@ secretKey= # of blobs. https://msdn.microsoft.com/en-us/library/dd135715.aspx container= +azureSas= + +azureBlobEndpoint= + + # The timeout interval, in milliseconds, to use for the request (default 5 minutes) socketTimeout=120000