DocumentDB connection string - azure

Azure application settings (for azure function) has a option for a DocumentDB connection string
Anyone have any idea how this should be populated/formatted?
i currently use:
var documentDbEndpointUri = new Uri(ConfigurationManager.AppSettings["DocumentDbEndpointUri"]);
var documentDbAuthKey = ConfigurationManager.AppSettings["DocumentDbAuthKey"];
return new DocumentClient(documentDbEndpointUri, documentDbAuthKey);
Although I'd like to switch to a single value connection string.

Try AccountEndpoint=https://accountname.documents.azure.com:443/‌​;AccountKey=accountk‌​ey==;Database=database

Firstly, as #Gaurav Mantri said in comment, currently DocumentClient does not have constructor overloads using connection string, you cannot directly use a connection string to create an instance of DocumentClient even if you provide/add connection string for DocumentDB in Azure application settings.
Note: here is a feedback for this issue, if you have same feature request, you can vote for it.
Secondly, If you’d like to access the DocumentDB service via DocumentClient, you can add both DocumentDbEndpointUri and DocumentDbAuthKey in App settings, and then read them in function code.
var serviceEndpoint = System.Configuration.ConfigurationManager.AppSettings["DocumentDbEndpointUri"];
var authKey = System.Configuration.ConfigurationManager.AppSettings["DocumentDbAuthKey"];
//or
//var serviceEndpoint = Environment.GetEnvironmentVariable("DocumentDbEndpointUri");
//var authKey = Environment.GetEnvironmentVariable("DocumentDbAuthKey");

Related

How to Get Azure Event Hub Connection String in C#?

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.

How to find Cosmos DB Endpoint and where to get lib directory referenced in this code?

Here is sample code for querying a CosmosDB
Here is the part of the code I am concerned with replicating so I can make queries on my own database.
const cosmos = require("../../lib/");
const CosmosClient = cosmos.CosmosClient;
const config = require("../Shared/config");
const databaseId = config.names.database;
const containerId = config.names.container;
const endpoint = config.connection.endpoint;
const masterKey = config.connection.authKey;
// Establish a new instance of the CosmosClient to be used throughout this demo
const client = new CosmosClient({ endpoint, auth: { masterKey } });
I'm not sure what my endpoint should be in order to query the database. My queries are Read-only (doesn't need to be strictly read only, but for what I'm doing, read-only is all that's needed), but I don't know what is in ../../lib/ that the cosmos variable is set equal to, and I don't know what the endpoint variable should contain (obviously some sort of endpoint, but which one). The ../../lib/ directory doesn't appear to be in the github repo.
The connection information can be found in the Keys section of the Azure portal.
The endpoint is the value in the URI section.
In case of the CosmosDB emulator, the default URI is https://localhost:8081.

How do I access Cosmos DB database or collection metrics via the Azure REST API?

I am attempting to use the Azure metrics API to retrieve metrics for Cosmos DB databases and collections.
I am able to use the metrics API to retrieve metrics for the Cosmos DB account itself, but I cannot figure out the resource URL for the databases or collections.
So this works:
public static async Task GetMetricsForCollection(ICosmosDBAccount cosmos, IDocumentClient client)
{
var uriBuilder = new System.Text.StringBuilder();
uriBuilder.Append($"https://management.azure.com{cosmos.Id}");
uriBuilder.Append($"/providers/microsoft.insights/metricDefinitions?api-version=2018-01-01");
//...Use uri to access API over HTTP
But I can't figure out how to get more specific metrics at deeper levels.
I found this post on the MSDN Community that says that this should work
public static async Task GetMetricsForCollection(ICosmosDBAccount cosmos, IDocumentClient client)
{
var db = client.CreateDatabaseQuery().AsEnumerable().First();
var uriBuilder = new System.Text.StringBuilder();
//Use the database resource Id to retrieve the metrics
uriBuilder.Append($"https://management.azure.com{cosmos.Id}/databases/{db.ResourceId}");
uriBuilder.Append($"/providers/microsoft.insights/metricDefinitions?api-version=2018-01-01");
//...Use uri to access API over HTTP
But it returns an error
Response status code does not indicate success: 400
Microsoft.DocumentDB/databaseAccounts/databases is not a supported platform metric namespace, supported ones are
Microsoft.LocationBasedServices/accounts,Microsoft.EventHub/namespaces,Microsoft.EventHub/clusters,Microsoft.ServiceBus/namespaces,
Microsoft.KeyVault/vaults,Microsoft.ClassicCompute/domainNames/slots/roles,Microsoft.ClassicCompute/virtualMachines,
Microsoft.Network/publicIPAddresses,Microsoft.Network/networkInterfaces,Microsoft.Network/loadBalancers,
Microsoft.Network/networkWatchers/connectionMonitors,Microsoft.Network/virtualNetworkGateways,Microsoft.Network/connections,
Microsoft.Network/applicationGateways,Microsoft.Network/dnszones,Microsoft.Network/trafficmanagerprofiles,
Microsoft.Network/expressRouteCircuits,Microsoft.EventGrid/eventSubscriptions,Microsoft.EventGrid/topics,Microsoft.EventGrid/extensionTopics,
Microsoft.Batch/batchAccounts,Microsoft.TimeSeriesInsights/environments,Microsoft.TimeSeriesInsights/environments/eventsources,
Microsoft.OperationalInsights/workspaces,Microsoft.Maps/accounts,Microsoft.Sql/servers,Microsoft.Sql/servers/databases,
Microsoft.Sql/servers/elasticpools,Microsoft.AnalysisServices/servers,Microsoft.Compute/virtualMachines,
Microsoft.Compute/virtualMachineScaleSets,Microsoft.Compute/virtualMachineScaleSets/virtualMachines,Microsoft.DataFactory/dataFactories,
Microsoft.DataFactory/factories,Microsoft.Storage/storageAccounts,Microsoft.Storage/storageAccounts/blobServices,
Microsoft.Storage/storageAccounts/tableServices,Microsoft.Storage/storageAccounts/queueServices,
Microsoft.Storage/storageAccounts/fileServices,Microsoft.Logic/workflows,Microsoft.Automation/automationAccounts,
Microsoft.ContainerService/managedClusters,Microsoft.StorageSync/storageSyncServices,Microsoft.ApiManagement/service,
Microsoft.DBforMySQL/servers,Microsoft.DocumentDB/databaseAccounts,Microsoft.ContainerRegistry/registries,Microsoft.Search/searchServices,
microsoft.insights/components,microsoft.insights/autoscalesettings,Microsoft.DataLakeStore/accounts,Microsoft.Web/serverFarms,
Microsoft.Web/sites,Microsoft.Web/sites/slots,Microsoft.Web/hostingEnvironments/multiRolePools,Microsoft.Web/hostingEnvironments/workerPools,
Microsoft.HDInsight/clusters,Microsoft.NetApp/netAppAccounts/capacityPools,Microsoft.NetApp/netAppAccounts/capacityPools/volumes,
test.shoebox/testresources,test.shoebox/testresources2,Microsoft.NotificationHubs/namespaces/notificationHubs,Microsoft.CustomerInsights/hubs,
CloudSimple.PrivateCloudIaaS/virtualMachines,Microsoft.StreamAnalytics/streamingjobs,Microsoft.CognitiveServices/accounts,
Microsoft.Cache/Redis,Microsoft.Devices/IotHubs,Microsoft.Devices/ElasticPools,Microsoft.Devices/ElasticPools/IotHubTenants,
Microsoft.Devices/ProvisioningServices,Microsoft.SignalRService/SignalR,Microsoft.DataLakeAnalytics/accounts,
Microsoft.DBforPostgreSQL/servers,Microsoft.ContainerInstance/containerGroups,Microsoft.Relay/namespaces,
Microsoft.PowerBIDedicated/capacities
(So you don't have to read all of that, I can confirm that it doesn't mention collections or databases as being usable with this API.)
I've also tried it with db.Id instead of db.ResourceId with the same error.
I've also tried going to the collection with uriBuilder.Append($"https://management.azure.com{cosmos.Id}/databases/{db.ResourceId}/collections/{collection.ResourceId}"); but it also generates the same message.
I'm stumped.
After poking around a bit with network traces while exploring in the Azure Portal, it looks like there are two types of Cosmos metrics: those that use the microsoft.insights provider and those that don't.
For those that use the provider, you can add the database and collection (the human readable names, aka the .Id property) as filters to the metrics API:
public static async Task GetMetricsForCollection(ICosmosDBAccount cosmos, IDocumentClient client)
{
var db = client.CreateDatabaseQuery().AsEnumerable().First();
var dbUri = UriFactory.CreateDatabaseUri(db.Id);
var collection = client.CreateDocumentCollectionQuery(dbUri).AsEnumerable().First();
var uriBuilder = new System.Text.StringBuilder();
//Use the database resource Id to retrieve the metrics
uriBuilder.Append($"https://management.azure.com{cosmos.Id}");
uriBuilder.Append($"/providers/microsoft.insights/metricDefinitions?api-version=2018-01-01");
uriBuilder.Append($"&$filter=DatabaseName eq '{db.Id}' and CollectionName eq '{collection.Id}'");
For those that don't, you can add /metrics to the resource URI suggested by the linked forum post. In this case, you need to use the .ResourceId properties.
It also looks like a filter parameter is required. I'm just copying and pasting from the Azure portal's network traces as I don't believe this is documented anywhere but it ends up looking something like
public static async Task GetMetricsForCollection(ICosmosDBAccount cosmos, IDocumentClient client)
{
var db = client.CreateDatabaseQuery().AsEnumerable().First();
var dbUri = UriFactory.CreateDatabaseUri(db.Id);
var collection = client.CreateDocumentCollectionQuery(dbUri).AsEnumerable().First();
var uriBuilder = new System.Text.StringBuilder();
uriBuilder.Append($"https://management.azure.com{cosmos.Id}");
uriBuilder.Append($"/databases/{db.ResourceId}/collections/{collection.ResourceId}/metrics?api-version=2014-04-01");
uriBuilder.Append($"&$filter=(name.value eq 'Available Storage' or name.value eq 'Data Size' or name.value eq 'Index Size') and endTime eq 2018-06-22T12%3A35%3A00.000Z and startTime eq 2018-06-22T11%3A35%3A00.000Z and timeGrain eq duration'PT5M'");

Where to store DocumentDB Endpoint and Key in production

I have a .Net Core website and Xamarin app that talk to Documentdb and we are preparing to go to production.
All docs I have seen on DocumentDB / CosmosDB hard copy the Key and Endpoint in a C# class. Example: https://learn.microsoft.com/en-us/azure/cosmos-db/tutorial-develop-documentdb-dotnet , http://www.dotnetcurry.com/windows-azure/1395/cosmosdb-webapi-angular-client , to list a few (!), and Azure Security in DocumentDB does not seem to address or mention this issue.
Is there a way to securely store DocuementDB EndPoint and Key in client apps?
Thank you.
You should never use the keys in applications. Azure Key Vault solve this problem.
Please check this
https://sarosh.wordpress.com/2017/11/23/cosmos-db-and-key-vault/
HTH
KeyChain.Net
A simple and unified api that enables developer to set, update, get and delete keys and passwords on the keyChain (supports iOS, Android, and WinPhone)
https://github.com/has-taiar/KeyChain.Net
iOS
var helper = new KeyChain.Net.XamarinIOS.KeyChainHelper();
var isSaved = helper.SetKey("myKey", "myKeyValue");
var keyValue = helper.GetKey("myKey");
var isDeleted = helper.DeleteKey("myKey");
Android
var helper = new KeyChain.Net.XamarinAndroid.KeyChainHelper(myActivity, "myKeyProtectionPassword");
var isSaved = helper.SetKey("myKey", "myKeyValue");
var keyValue = helper.GetKey("myKey");
var isDeleted = helper.DeleteKey("myKey");
Windows Phone
var helper = new KeyChain.Net.XamarinWinRT.KeyChainHelper();
var isSaved = helper.SetKey("myKey", "myKeyValue");
var keyValue = helper.GetKey("myKey");
var isDeleted = helper.DeleteKey("myKey");

How to Create Queue in Windows Azure?

I am using below code to create queue, using SharedSecretTokenProvider. However I am not able to supply correct values of managerName & managerKey value form windows azure portal.
This results in Http 401 Unauthorized exception. How do I resolve this error?
const string queueName = "thequeue";
var tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
ConfigurationManager.AppSettings["managerName"],
ConfigurationManager.AppSettings["managerKey"]);
Uri uri = ServiceBusEnvironment.CreateServiceUri("http", "MyNamespace" , string.Empty);
NamespaceManager namespaceManager = new NamespaceManager(uri, tokenProvider);
QueueDescription qd = namespaceManager.CreateQueue(new QueueDescription(queueName)
{
DefaultMessageTimeToLive = TimeSpan.FromMinutes(15),
DuplicateDetectionHistoryTimeWindow = TimeSpan.FromMinutes(10),
LockDuration = TimeSpan.FromMinutes(2),
EnableBatchedOperations = true,
EnableDeadLetteringOnMessageExpiration = true,
RequiresDuplicateDetection = true
});
I had tried this a couple of times with your code before I realized the problem. You are using the SharedSecretTokenProvider which will go to ACS thinking it has an issuer and a key. Since you are trying to use the SAS you'll want to use a CreateSharedAccessSignatureTokenProvider instead.
Swap that out and provide the key and keyName and you should be good.
Also, Viperguynaz is correct, you should use the "sb" instead of http as well. It was failing before it reached there because the token provider was correctly declining you access since it didn't understand the key and keyname you were passing for what it thought was the issuer and key that ACS uses.
Start with ServiceBusEnvironment.CreateServiceUri Method. Note that Service Bus endpoint URIs must always use the “sb://” protocol; for example sb://contoso.servicebus.windows.net/helloservicebus.
Uri address = ServiceBusEnvironment.CreateServiceUri("sb", "contoso", "helloservicebus");
Get your URI inputs set correctly and you should be in business.

Resources