Using ARM template, we can define a storage account under a batch account. But how we can do this using .NET SDK? Currently I can create BatchAccount and StorageAccount as separate resources, but what to do if a StorageAccount should be appeared under BatchAccount I.e. under "SETTINGS" TAB of the BatchAccount
Below code works for me.
//Getting StorageAccount to bind
var storageAccount = await storageManagementClient.StorageAccounts.GetPropertiesAsync("testresourcegroup", "teststorageaccount");
//Creating binding properties
AutoStorageBaseProperties baseProperties = new AutoStorageBaseProperties { StorageAccountId = storageAccount.Id };
//Creating update parametrs for Batch Account
BatchAccountUpdateParameters updateParameters = new BatchAccountUpdateParameters { AutoStorage = baseProperties };
//Updatting the BatchAccount to bind with chosen StorageAccount
var response = await batchManagementClient.BatchAccount.UpdateAsync("testresourcegroup", "testbatchaccount", updateParameters);
Related
Given a Event Hub Name, how can I get connection string in C#?
I googled a bit, but nothing useful found so far.
Thanks
Using AAD authentication for an EventHub
var credential = new DefaultAzureCredential();
// or use
// var credential = new Azure.Identity.ClientSecretCredential("tenantId", "clientId", "clientSecret");
EventHubProducerClient producerClient = new EventHubProducerClient(txtNamespace.Text, txtEventHub.Text, credential
var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, txtNamespace.Text, txtEventHub.Text, credential)
Full example and docs
Acquiring the Connection Strings of configured Access Policies
You can use these two Nuget packages:
Azure.ResourceManager.EventHubs
Azure.Identity
Then you can use the resource group name and the eventhub name to retrieve the connection string. You will need to iterate the subscriptions and resource groups if you don't have this information.
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.EventHubs;
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Or use
// ArmClient client = new ArmClient(new Azure.Identity.ClientSecretCredential("tenantId", "clientId", "clientSecret"));
var subscription = await client.GetDefaultSubscriptionAsync();
var resourceGroup = await subscription.GetResourceGroupAsync("myresourcegroup");
var eventhubNamespace = await resourceGroup.Value.GetEventHubsNamespaceAsync("namespacename");
var rules = eventhubNamespace.Value.GetEventHubsNamespaceAuthorizationRules();
foreach (var rule in rules)
{
var keys = await rule.GetKeysAsync();
Console.WriteLine(keys.Value.PrimaryConnectionString);
Console.WriteLine(keys.Value.SecondaryConnectionString);
}
Not sure if this is what you mean, but if you want to access an Event Hub through C# you need to provide the EH connection string into your code. This can be retrieved by adding a Shared access policy for the Event hub that you are trying to access.
Edit: If you are trying to actually create the connection string yourself you could follow this sample where you create the SAS-token yourself. But you would still need to provide the Primary key that is set on the policy from Azure.
I'm trying to upload images to Azure Blob Storage. I'm using .Net Core and Azure.Storage.Blobs v12.8.0.
The following code is what I have so far.
try
{
var documentByteArray = // a valid byte array of a png file
var blobUri = new Uri("https://mystorageaccount.blob.core.windows.net/images/myfile.png");
BlobClient blobClient = new BlobClient(blobUri);
using (MemoryStream stream = new MemoryStream(documentByteArray))
{
await blobClient.UploadAsync(stream, true, default);
await blobClient.SetHttpHeadersAsync(new BlobHttpHeaders
{
ContentType = "image/png"
});
}
}
catch (Exception ex)
{
//
}
...but somewhat predictably it fails with the exception Server failed to authenticate the request. Please refer to the information in the www-authenticate header.. I say predictable because I've not added any authentication...
And this is the problem/question. How do I add authentication so it will upload?
I know there are Access Keys that I can use - but how? I can't find any examples in MS documentation.
Any insight is appreciated.
If you have access to the Azure Portal, you can get the connection string of the storage account (under "Access Keys" section).
Once you have the connection string, you can use the following code:
var connectionString = "your-storage-account-connection-string";
var containerName = "images";
var blobName = "myfile.png";
var blobClient = new BlobClient(connectionString, containerName, blobName);
//do the upload here...
Other option is to use storage account name and access key (again you can get it from Azure Portal). You would do something like:
var accountName = "account-name";
var accountKey = "account-key";
var blobUri = new Uri("https://mystorageaccount.blob.core.windows.net/images/myfile.png");
var credentials = new StorageSharedKeyCredential(accountName, accountKey);
var blobClient = new BlobClient(blobUri, credentials);
//do the upload here...
You can find more information about BlobClient constructors here: https://learn.microsoft.com/en-us/dotnet/api/azure.storage.blobs.blobclient?view=azure-dotnet.
You should upload your blob through a CloudStorageAccount instance, like this:
var storageAccount = new CloudStorageAccount(
new StorageCredentials("<your account name>", "<your key>"),
"core.windows.net",
true);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
var blob = container.GetBlockBlobReference(fileName);
await blob.UploadFromStreamAsync(stream);
I'm creating several storage accounts programmatically via StorageManagementClient and would like to enable blob versioning on account level at the time of account creation. How is this accomplished?
var storageManagementClient = new StorageManagementClient(azureCredentials)
{
SubscriptionId = subscriptionId
};
var storageAccountCreateParameters = new StorageAccountCreateParameters
{
// set properties
};
await storageManagementClient.StorageAccounts.CreateAsync(resourceGroupName, accountName, storageAccountCreateParameters);
I thought that this would be available as a create parameter in StorageAccountCreateParameters, but I don't see anything there.
Also see https://learn.microsoft.com/en-us/azure/storage/blobs/versioning-enable?tabs=portal
The blob versioning is not included in the StorageAccountCreateParameters. It belongs to BlobServiceProperties class.
So after you create the storage account with your code above, you can use the following code to set blob versioning:
var p1 = new BlobServiceProperties()
{
IsVersioningEnabled = true
};
storageManagementClient.BlobServices.SetServiceProperties("resource_group", "account_name", p1);
All the connection strings for an Azure Storage account seem to only be the original url + account.
Is there any way to change the connection string to an Azure Storage account to be my CNAME instead?
EDIT: The answer below is awesome and a few hours AFTER the answer was posted (and ticked) I found some official documentation on this/the same answer :)
Great Question! I think you can but it will only work with Blob Storage as you can only specify a CNAME mapping for blob endpoint plus you will need to use your account name somewhere as it is used for authorization header computation. This is how I did it:
static void ConnectViaCname()
{
var cred = new StorageCredentials("account-name", "account-key");
var account = new CloudStorageAccount(cred, new Uri("https://cnamemapping.com"), null, null, null);
var client = account.CreateCloudBlobClient();
var containers = client.ListContainers();
foreach (var container in containers)
{
Console.WriteLine(container.Uri.AbsoluteUri);
}
}
UPDATE
If you wish to use connection string, please specify the connection string in this format:
DefaultEndpointsProtocol=https;
BlobEndpoint=https://cnamemapping.com;
AccountName=account-name;
AccountKey=account-key
So the code would be:
static void ConnectViaCname()
{
var connectionString = "DefaultEndpointsProtocol=https;BlobEndpoint=https://cnamemapping.com;AccountName=account-name;AccountKey=account-key";
var account = CloudStorageAccount.Parse(connectionString);
var client = account.CreateCloudBlobClient();
var containers = client.ListContainers();
foreach (var container in containers)
{
Console.WriteLine(container.Uri.AbsoluteUri);
}
}
I have found how to upload/manage Azure Batch job Application Packages through the UI:
https://learn.microsoft.com/en-us/azure/batch/batch-application-packages
And how to upload and manage Resource Packages programmatically:
https://github.com/Azure/azure-batch-samples/tree/master/CSharp/GettingStarted/02_PoolsAndResourceFiles
But I can't quite seem to put 2 and 2 together on how to manage Application Packages programmatically. Is there an API endpoint we can call to upload/manage an Application Package when setting up a batch job?
Since this is not quite straightforward, I'll write down my findings.
These are the steps to programmatically upload Application Packages via an application that is unattended - no user input (e.g. Azure credentials) is needed.
In Azure Portal:
Create the Azure Batch application
Create a new Azure AD application (as Application Type use Web app / API)
Follow these steps to create the secret key and assign the role to the Azure Batch account
Note down the following credentials/ids:
Azure AD application id
Azure AD application secret key
Azure AD tenant id
Subscription id
Batch account name
Batch account resource group name
In your code:
Install NuGet packages Microsoft.Azure.Management.Batch, WindowsAzure.Storage and Microsoft.IdentityModel.Clients.ActiveDirectory
Get the access token and create the BatchManagementClient
Call the ApplicationPackageOperationsExtensions.CreateAsync method, which should return an ApplicationPackage
ApplicationPackage contains the StorageUrl which can now be used to upload the Application Package via the storage API
After you have uploaded the ApplicationPackage you have to activate it via ApplicationPackageOperationsExtensions.ActivateAsync
Put together the whole code looks something like this:
private const string ResourceUri = "https://management.core.windows.net/";
private const string AuthUri = "https://login.microsoftonline.com/" + "{TenantId}";
private const string ApplicationId = "{ApplicationId}";
private const string ApplicationSecretKey = "{ApplicationSecretKey}";
private const string SubscriptionId = "{SubscriptionId}";
private const string ResourceGroupName = "{ResourceGroupName}";
private const string BatchAccountName = "{BatchAccountName}";
private async Task UploadApplicationPackageAsync() {
// get the access token
var authContext = new AuthenticationContext(AuthUri);
var authResult = await authContext.AcquireTokenAsync(ResourceUri, new ClientCredential(ApplicationId, ApplicationSecretKey)).ConfigureAwait(false);
// create the BatchManagementClient and set the subscription id
var bmc = new BatchManagementClient(new TokenCredentials(authResult.AccessToken)) {
SubscriptionId = SubscriptionId
};
// create the application package
var createResult = await bmc.ApplicationPackage.CreateWithHttpMessagesAsync(ResourceGroupName, BatchAccountName, "MyPackage", "1.0").ConfigureAwait(false);
// upload the package to the blob storage
var cloudBlockBlob = new CloudBlockBlob(new Uri(createResult.Body.StorageUrl));
cloudBlockBlob.Properties.ContentType = "application/x-zip-compressed";
await cloudBlockBlob.UploadFromFileAsync("myZip.zip").ConfigureAwait(false);
// create the application package
var activateResult = await bmc.ApplicationPackage.ActivateWithHttpMessagesAsync(ResourceGroupName, BatchAccountName, "MyPackage", "1.0", "zip").ConfigureAwait(false);
}
Azure Batch Application Packages management operations occur on the management plane. The MSDN docs for this namespace are here:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.management.batch
The nuget package for Microsoft.Azure.Management.Batch is here:
https://www.nuget.org/packages/Microsoft.Azure.Management.Batch/
And the following sample shows management plane operations in C#, although it is for non-application package operations:
https://github.com/Azure/azure-batch-samples/tree/master/CSharp/AccountManagement