The code below uses blob storage endpoint, SAS, and names of two different containers (CONTAINER_1_NAME, CONTAINER_2_NAME) to get references of two "CloudBlobContainer" objects (private attributes: 'container1' and 'container2'). In this approach, I'm using an "account-level SAS". However, we can also create container-level SAS using the Azure portal as well (We can even use stored access policies with container-level SAS but not with account-level SAS currently).
My question is, how to change this code such that it uses "container-level SAS" (Not account-level SAS)? Ultimately I need to get two "CloudBlobContainer" objects ('container1' and 'container2').
CODE:
CloudStorageAccount storage = null;
try {
this.BLOB_STORAGE_ENDPOINT = blobstorageConnection.getEndpoint();
String SAS = blobstorageConnection.getSas();
this.CONTAINER_1_NAME = blobstorageConnection.getContainer1Name();
this.CONTAINER_2_NAME = blobstorageConnection.getContainer2Name();
String SASBasedConnectionString = "BlobEndpoint=" + BLOB_STORAGE_ENDPOINT + ";SharedAccessSignature=" + SAS;
storage = CloudStorageAccount.parse(SASBasedConnectionString);
CloudBlobClient serviceClient = storage.createCloudBlobClient();
this.container1 = serviceClient.getContainerReference(CONTAINER_1_NAME);
this.container2 = serviceClient.getContainerReference(CONTAINER_2_NAME);
container1.createIfNotExists();
container2.createIfNotExists();
} catch (URISyntaxException | InvalidKeyException | StorageException e) {
throw new RuntimeException(e);
}
NOTE:
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage</artifactId>
<version>8.6.6</version>
</dependency>
I asked the same question in Microsoft Q&A platform and got the below answer. But it gives me an error (Please finde it below the answer.)
ANSWER FROM MICROSOFT EMPLOYEE:
To use container-level SAS instead of account-level SAS in your code, you need to modify the SASBasedConnectionString to include the SAS token for each container. Here's an example of how you can modify your code to use container-level SAS.
In this modified code, you need to add two new properties to your blobstorageConnection object: "container1Sas" and "container2Sas". These properties should contain the container-level SAS tokens for each container.
Then, you need to modify the SASBasedConnectionString to include the SAS token and container name for each container. Finally, you need to create a new CloudStorageAccount object and CloudBlobClient object for each container, and get a reference to the container using the container name.
String SASBasedConnectionString = "BlobEndpoint=" + BLOB_STORAGE_ENDPOINT + ";";
SASBasedConnectionString += "SharedAccessSignature=" + CONTAINER_1_SAS + ";";
SASBasedConnectionString += "ContainerName=" + CONTAINER_1_NAME + ";";
storage = CloudStorageAccount.parse(SASBasedConnectionString);
CloudBlobClient serviceClient = storage.createCloudBlobClient();
this.container1 = serviceClient.getContainerReference(CONTAINER_1_NAME);
container1.createIfNotExists();
SASBasedConnectionString = "BlobEndpoint=" + BLOB_STORAGE_ENDPOINT + ";";
SASBasedConnectionString += "SharedAccessSignature=" + CONTAINER_2_SAS + ";";
SASBasedConnectionString += "ContainerName=" + CONTAINER_2_NAME + ";";
storage = CloudStorageAccount.parse(SASBasedConnectionString);
serviceClient = storage.createCloudBlobClient();
this.container2 = serviceClient.getContainerReference(CONTAINER_2_NAME);
container2.createIfNotExists();
ERROR THAT I'M GETTING AFTER IMPLEMNTING THE ABOVE SOLUTION:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid connection string.
at com.microsoft.azure.storage.CloudStorageAccount.parse(CloudStorageAccount.java:290)
at org.wso2.carbon.wum.ucreator.blobstorage.BlobStorageManager.<init>(BlobStorageManager.java:57)
NOTE: BlobStorageManager.java:57 is the line:
storage = CloudStorageAccount.parse(SASBasedConnectionString);
I have tried your requirement in my environment, and I was also getting the same error with the connection string.
To resolve this, I have tried by adding the storage endpoint.
Note: I have used the storage endpoint but the SAS token is container level.
Below is the code I have tried by writing an API to call the functionality.
@GetMapping("/getdata")
public String getData() throws URISyntaxException, StorageException {
String sasToken = "<Container_level_SAS_Token>";
String containerName = "<Your_Container_Name>";
String accountName = "<Storage_Account_Name>";
String endpoint = String.format("https://%s.blob.core.windows.net", accountName);
StorageCredentials credentials = new StorageCredentialsSharedAccessSignature(sasToken);
URI uri = new URI(endpoint);
CloudBlobClient blobClient = new CloudBlobClient(uri, credentials);
CloudBlobContainer container = blobClient.getContainerReference(containerName);
return "My Container Name is " + container.getName();
}
Using the container level SAS token as shown below:
Result: