Scenario:
Imagine you have to store files in the online storages, so you can access them on the internet at anytime and anywhere.
In my case I’m using Azure storage account to store the D365 finance and operation Sales order invoices files and access it. But here the azure blob container is private so to access the files which are store in the private container SAS token needs to be appended to the file path to access it.
Please refer to the Part 1 Blog Azure blob storage: How to Store the Files in the Container – Saina Cloud Software Solutions before continuing.
High level resolution steps
- Create the SAS token for the container.
- Store the container’s SAS token in the table.
- Gather the SAS token from the table append to the azure blob container and access it.
Detailed resolution steps
Code Snippet:
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using System;
internal final class SCCSASTokenGeneration
{
///
/// Class entry point. The system will call this method when a designated menu
/// is selected or when execution starts and this class is set as the startup class.
///
/// The specified arguments.
public static void main(Args _args)
{
SCCSASTokenGeneration:: createSASToken();
}
private static container createSASToken()
{
container sasContainer;
str connectionString = 'kjsnckjnxjklhsquicnssxmmxjnuixxnkl;nxjbconnection_string';
str containerName = 'salesinvoice';
//Connects to the BLOB account
CloudStorageAccount storageAccount = CloudStorageAccount::Parse(connectionString);
Blob.CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
Blob.CloudBlobContainer blobContainer = blobClient.GetContainerReference(containerName);
//Throws error if the connection fails of container does not exists
if (!blobContainer.Exists(null,null))
{
throw Global::error("Invalid credentials");
}
//Set properties for the SAS token
SharedAccessBlobPolicy sharedAccessBlobPolicy = new SharedAccessBlobPolicy();
sharedAccessBlobPolicy.SharedAccessStartTime = new DateTimeOffset(DateTime::UtcNow);
sharedAccessBlobPolicy.SharedAccessExpiryTime = new DateTimeOffset(DateTime::UtcNow.AddDays(30));
sharedAccessBlobPolicy.Permissions = SharedAccessBlobPermissions::Read;
//Retireving the generated token
var sasToken = blobContainer.GetSharedAccessSignature(sharedAccessBlobPolicy);
//inserting SAS token to table
if(sasToken)
{
SCCSalesInvoiceTrackingTable sasKeyTable;
sasKeyTable.SASKey = sasToken;
sasKeyTable.ValidFromDate = DateTimeUtil::getSystemDateTime();
sasKeyTable.ExpiryDate = DateTimeUtil::addDays(DateTimeUtil::getSystemDateTime(), 30);
sasKeyTable.insert();
}
}
}
Code Explanation:
Step 1: We created the runnable class to generate the SAS token for the container and store it in the SAS token table. Below are the namespaces used from the “Dotnet” framework to use the classes which are provides the functionality to interact with azure.
We took the azure blob storage account connection string and container from the azure portal. Using the connection string and container name we are building a connection from the X++ to azure.
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using System;
private static container createSASToken() { container sasContainer; str connectionString = ‘kjsnckjnxjklhsquicnssxmmxjnuixxnkl;nxjbconnection_string’; str containerName = ‘salesinvoice’; //Connects to the BLOB account CloudStorageAccount storageAccount = CloudStorageAccount::Parse(connectionString); Blob.CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); Blob.CloudBlobContainer blobContainer = blobClient.GetContainerReference(containerName); |
Step2: Ensure the container are represent with given connection string and container name. If container doesn’t exist throw the error message. If does exist, create the “Shared access blob policy” that contains details of SAS token such as token valid from, expiry date and using the token what are the action can be performed.
//Throws error if the connection fails of container does not exist if (!blobContainer.Exists(null,null)) { throw Global::error(“Invalid credentials”); } //Set properties for the SAS token SharedAccessBlobPolicy sharedAccessBlobPolicy = new SharedAccessBlobPolicy(); sharedAccessBlobPolicy.SharedAccessStartTime = new DateTimeOffset(DateTime::UtcNow); sharedAccessBlobPolicy.SharedAccessExpiryTime = new DateTimeOffset(DateTime::UtcNow.AddDays(30)); sharedAccessBlobPolicy.Permissions = SharedAccessBlobPermissions::Read; //Retireving the generated token var sasToken = blobContainer.GetSharedAccessSignature(sharedAccessBlobPolicy); |
Step3: By passing the “Shared access blob policy” receive the generated SAS token for the given container. If token exist, store the token into the SAS token table.
//Retireving the generated token var sasToken = blobContainer.GetSharedAccessSignature(sharedAccessBlobPolicy); //inserting SAS token to table if(sasToken) { SCCSalesInvoiceTrackingTable sasKeyTable; sasKeyTable.SASKey = sasToken; sasKeyTable.ValidFromDate = DateTimeUtil::getSystemDateTime(); sasKeyTable.ExpiryDate = DateTimeUtil::addDays(DateTimeUtil::getSystemDateTime(), 30); sasKeyTable.insert(); |
Output
Run the batch job using runnable batch job URL. Once the execution is completed, it will insert the SAS token into the SCCSalesInvoiceTrackingTable.
Once the batch run successfully check the SAS token table.
Take the file path of the “salesinvoice” private container from the azure blob and try to access the file from the container without the SAS token. I will not allow to view the file.
Now take the SAS token which is generated for private container ”salesinvoice“ from the table “SCCSalesInvoiceTrackingTable” and appended to the file path and try to access it.