I'm trying to deploy a VM by uploading an ARM Template and Parameters file into a private Blob storage container and then download them when needed. The files upload into the container fine, but when the trying to download them the SAS token fails to authenticate giving the error:
Microsoft.Rest.Azure.CloudException:
Unable to download deployment content from 'https://cloudstationsbackendsa.blob.core.windows.net/workstation-templates/CreateVMTemplate.json?sv=2018-03-28&sr=b&sig=GHgWUiEG7bG3%2FDN4cjSsmHGrBTdM8F2LRxNTss5cJB0%3D&st=2019-03-06T11:16:42Z&se=2019-03-06T11:31:42Z&sp=r'
Visiting this URL in a browser produces the following error:
<Error>
<Code>AuthenticationFailed</Code>
<Message>
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:8e274bc1-101e-0011-3f0c-d45f43000000 Time:2019-03-06T11:03:53.3144543Z
</Message>
<AuthenticationErrorDetail>
Signature did not match. String to sign used was r 2019-03-06T10:58:39Z 2019-03-06T11:13:39Z /blob/cloudstationsbackendsa/workstation-templates/CreateVMTemplate.json 2018-03-28
</AuthenticationErrorDetail>
</Error>
This is the method used to upload the files and generate the SAS tokens:
public async Task<StorageAccountAccessDTO> UploadTemplatesAsync(string azureIdentifier)
{
// Access to Storage Account
var account = CloudStorageAccount.Parse(_config.GetValue<string>("ConnectionStrings:StorageAccount"));
var serviceClient = account.CreateCloudBlobClient();
var container = serviceClient.GetContainerReference("workstation-templates");
// Upload VM ARM Template
var templateBlob = container.GetBlockBlobReference("CreateVMTemplate.json");
await templateBlob.UploadFromFileAsync("CreateVMTemplate.json");
// Upload VM ARM Parameters
var parameterBlob = container.GetBlockBlobReference("Parameters.json");
await parameterBlob.UploadFromFileAsync("Parameters.json");
// Create SAS Tokens
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5);
sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddMinutes(10);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;
var accessDTO = new StorageAccountAccessDTO()
{
TemplateURL = templateBlob.Uri + templateBlob.GetSharedAccessSignature(sasConstraints),
ParametersURL = templateBlob.Uri + parameterBlob.GetSharedAccessSignature(sasConstraints)
};
return accessDTO;
}
The SAS tokens are appended to the URI of the blob and returned in a StorageAccountAccessDTO, this is passed into the method below to produce the VM:
public async Task CreateVirtualMachineAsync(string azureIdentifier, StorageAccountAccessDTO accessDTO)
{
await _azure.Deployments.Define("myDeployment")
.WithExistingResourceGroup(azureIdentifier + "-RG")
.WithTemplateLink(accessDTO.TemplateURL, "1.0.0.0")
.WithParametersLink(accessDTO.ParametersURL, "1.0.0.0")
.WithMode(DeploymentMode.Incremental)
.CreateAsync();
}
Thanks for your time and let me know if you require any extra details!