I have following problem
While I am trying to connect to the DocumentDB database using MongoDb API:
var cstring = "mongodb://textadmin:<MY VERY SECRET PASSWORD>#<MY SERVER>.documents.azure.com:10250/?ssl=true"
var client = new MongoDB.Driver.MongoClient(cstring)
var server = client.GetServer()
server.Ping()
I have the following error:
Authentication failed because the remote party has closed the transport stream
Any ideas what to change in the code (or in the server settings perhaps)?
You need to set EnabledSslProtocols to TLS12 to be able to connect to DocumentDB using MongoDB API. By default, the Mongo C# driver does not use TLS1.2 causing the connection to fail during SSL handshake.
Sample Code:
MongoClientSettings settings = new MongoClientSettings();
settings.Server = new MongoServerAddress(host, 10250);
settings.UseSsl = true;
settings.SslSettings = new SslSettings();
settings.SslSettings.EnabledSslProtocols = SslProtocols.Tls12;
MongoIdentity identity = new MongoInternalIdentity(dbName, userName);
MongoIdentityEvidence evidence = new PasswordEvidence(password);
settings.Credentials = new List<MongoCredential>()
{
new MongoCredential("SCRAM-SHA-1", identity, evidence)
};
MongoClient client = new MongoClient(settings);
Reference: https://azure.microsoft.com/en-us/documentation/articles/documentdb-mongodb-samples/
Related
I am trying to create a database and container using C# I am trying to use the newest version of Azure.ResourceManager.CosmosDB 1.2.0.
In a previos version I used:
var client = new CosmosDBManagementClient("someendpoint", new DefaultAzureCredential());
var database = await client.SqlResources.StartCreateUpdateSqlDatabaseAsync(
AzureResourceGroup, AccountName, DatabaseName,
new SqlDatabaseCreateUpdateParameters(
new SqlDatabaseResource(DatabaseName),
new CreateUpdateOptions()
)
);
var armcontainer = await client.SqlResources.StartCreateUpdateSqlContainerAsync(
AzureResourceGroup, AccountName, DatabaseName,
ContainerName,
GetContainerParameters()
);
However, the CosmosDBManagementClient is no longer in library.
I know there is:
var client = new CosmosClient(endpoint, new DefaultAzureCredential());
await client.CreateDatabaseIfNotExistsAsync("testing",
throughput: null, new RequestOptions());
I also can't get this to work due to 403 error, even with the contributor permissions, but I know this was an error because you are supposed to use the resource manager.
Any suggestions would be appreciated.
I haven't worked with passwordless access but have you tried providing the id explictely?
string userAssignedClientId = "<your managed identity client Id>";
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });
var client = new CosmosClient(endpoint, new DefaultAzureCredential());
If this doesn't work you could try the connection string approach:
using CosmosClient client = new(
accountEndpoint: "endpoint here",
authKeyOrResourceToken: "key here");
I'm updating a .NET 6 Blazor Server app that uses the .AddAzureKeyVault() extension method to add an Azure KeyVault configuration provider from the old Microsoft.Extensions.Configuration.AzureKeyVault over to the recommended Azure.Extensions.AspNetCore.Configuration.Secrets package that uses the new SDK.
The complication I have is that the request goes through a network proxy. The current working version I have that uses the old SDK is this:
using Microsoft.Extensions.Configuration.AzureKeyVault; // 3.1.22
using Microsoft.Azure.Services.AppAuthentication; // 1.6.2
using Microsoft.Azure.KeyVault; // 3.0.5 (this needs to be version 3.0.0 or greater)
var builder = WebApplication.CreateBuilder(args);
var webProxy = new WebProxy(new Uri("{proxy_url}")) {
Credentials = CredentialCache.DefaultNetworkCredentials
};
var httpClient = new HttpClient(new HttpClientHandler {
Proxy = webProxy, SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
});
var authenticationCallback = new KeyVaultClient.AuthenticationCallback(
new AzureServiceTokenProvider().KeyVaultTokenCallback);
var keyVaultClient = new KeyVaultClient(authenticationCallback, httpClient);
builder.Configuration
.AddAzureKeyVault("{keyvault_url}", keyVaultClient, new DefaultKeyVaultSecretManager());
var output = builder.Configuration
.GetSection("ApplicationInsights:InstrumentationKey").Value; // successfully retrieves value
With the new SDK I attempted to pass the proxy into the HttpClientTransport class but recieve a "The proxy tunnel request to proxy '{proxy_url}' failed with status code '407'." exception:
using Azure.Identity; // 1.5.0
using Azure.Security.KeyVault.Secrets; // 1.2.1
var builder = WebApplication.CreateBuilder(args);
var webProxy = new WebProxy(new Uri("{proxy_url}")) {
Credentials = CredentialCache.DefaultNetworkCredentials
};
var httpClient = new HttpClient(new HttpClientHandler {
Proxy = webProxy, SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
});
var azureCredentialOpts = new DefaultAzureCredentialOptions {
Transport = new HttpClientTransport(httpClient)
};
var secretClient = new SecretClient(new Uri("{keyvault_url}"),
new DefaultAzureCredential(azureCredentialOpts));
builder.Configuration
.AddAzureKeyVault(secretClient, new AzureKeyVaultConfigurationOptions());
// throws request to proxy failed with status code '407'
var output = builder.Configuration
.GetSection("ApplicationInsights:InstrumentationKey").Value;
I could find any mention of how to do this in the Microsoft docs and any examples I find use the old SDK. I did find this related question here - Azure .NET v4 SDK Proxy Configuration in .NET Framework, but the proposed solution never worked for me.
Only other thing to note was I did get this same '407' exception with the old SDK when using the Microsoft.Extensions.Configuration.AzureKeyVault package and I had to explicitly upgrade the Microsoft.Azure.KeyVault package to a version over 3.0.0 to get it to work, so not sure if this may be related (potentially the new SDK doesn't support the auth with the network proxy?...)
Would anyone know how I could use the Azure.Extensions.AspNetCore.Configuration.Secrets package through a proxy?
Managed to resolve my issue, turns out I was setting the proxy in DefaultAzureCredentialOptions when I should have been setting it in SecretClientOptions to be used with the SecretClient. I found this migration guide from Microsoft helpful in finding out where I was going wrong - https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/keyvault/Azure.Security.KeyVault.Secrets/MigrationGuide.md
One thing to note is I had to use the beta version v4.3.0-beta.4 of the Azure.Security.KeyVault.Secrets package otherwise you have to specify the tenant id explicitly, from another post it seems to be because versions below this don't have the automatic tenancy discovery feature - Visual Studio 2019 TokenService.exe has failed with unexpected error: TS003: Error, TS004: Unable to get access token.
The working version of my code is this:
using Azure.Extensions.AspNetCore.Configuration.Secrets; // v1.2.1
using Azure.Identity; // v1.5.0
using Azure.Security.KeyVault.Secrets; // v4.3.0-beta.4
var builder = WebApplication.CreateBuilder(args);
var webProxy = new WebProxy(new Uri("{proxy_url}")) {
Credentials = CredentialCache.DefaultNetworkCredentials
};
var httpClient = new HttpClient(new HttpClientHandler {
Proxy = kpmgWebProxy, SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
});
var secretClientOptions = new SecretClientOptions {
Transport = new HttpClientTransport(httpClient)
};
// `Azure.Security.KeyVault.Secrets` package version < 4.3.0 does not have the tenant discovery feature, therefore you will have to set this i nthe options.
/*var defaultAzureCredentialOptions = new DefaultAzureCredentialOptions()
{
VisualStudioTenantId = "",
};*/
var secretClient = new SecretClient(
new Uri(azureKeyVaultUrl),
new DefaultAzureCredential(/*defaultAzureCredentialOptions*/),
secretClientOptions);
builder.Configuration
.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
var output = builder.Configuration
.GetSection("ApplicationInsights:InstrumentationKey").Value;
I have mongodb database with username and password, I am trying to access to it from C#, I'm worjking with MongoDBDriver version 2.9.1 from NuGet, I tried the following code:
var client = new MongoClient($"mongodb://usre1:123#localhost/GSCADB");
IMongoDatabase db = client.GetDatabase("GSCADB");
var collection = db.GetCollection<BsonDocument>("GSCALogs");
int TotalFiles = collection.Find(new BsonDocument()).ToList().Count;
but this gives the exception:
Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1.
I have a .Net Standard client application running on UWP.
My client application contacts the server that generates a sas key like so:
var myPrivateStorageAccount = CloudStorageAccount.Parse(mystorageAccountKey);
var myPrivateTableClient = myPrivateStorageAccount.CreateCloudTableClient();
SharedAccessTablePolicy pol = new SharedAccessTablePolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(59),
Permissions = SharedAccessTablePermissions.Query | SharedAccessTablePermissions.Add
};
CloudTable myPrivateTable = myPrivateTableClient.GetTableReference(tableName);
String sas = myPrivateTable.GetSharedAccessSignature(pol);
return sas;
My client application then runs the following:
StorageCredentials creds = new StorageCredentials(sas);
this.tableClient = new CloudTableClient(tableServiceURI, creds);
this.table = tableClient.GetTableReference(tableName);
TableQuery<DynamicTableEntity> projectionQuery = new TableQuery<DynamicTableEntity>().Select(new string[] { "DocumentName" }).Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, cc));
var res = await table.ExecuteQuerySegmentedAsync<DynamicTableEntity>(projectionQuery, null);
and gets the following error:
Server failed to authenticate the request. Make sure the value of
Authorization header is formed correctly including the signature. sr
is mandatory. Cannot be empty
but as this is tablestorage I dont think sr is required
and my SAS key looks fine to me:
?sv=2018-03-28&tn=MyTable&sig=RandomSig151235341543&st=2019-01-17T12%3A00%3A28Z&se=2019-01-17T12%3A59%3A28Z&sp=ra
so whats the problem here?
Ok so this is kind of stupid but I will post anyway.
I was sending the request to:
https://myaccount.blob.core.windows.net/
and should have been sending the request to:
https://myaccount.table.core.windows.net/
I try to connect to server and get database. It run properly but it VS2013 show me a warning :
Warning 1 'MongoDB.Driver.MongoClientExtensions.GetServer(MongoDB.Driver.MongoClient)' is obsolete: 'Use the new API instead.
string connectionString = "mongodb://localhost:27017";
MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
MongoClient mongoClient = new MongoClient(settings);
var server = mongoClient.GetServer();
var db = server.GetDatabase("bookstore");
var bookCollection = db.GetCollection<Book>("Book");
Can someone help me solve this ? Tks for reading.
The MongoServer class was deprecated in version 2.0.0 (see here). You can call GetDatabase() directly on the MongoClient object:
MongoClient mongoClient = new MongoClient(settings);
var db = mongoClient.GetDatabase("bookstore");
More documentation about connecting to the MongoDB server, retrieving a database, etc. can be found in the reference documentation.
I changed my code to following:
var mongoUrl = new MongoUrl(connectionString);
var mongoClient = new MongoClient(mongoUrl);
MongoServer server = new MongoServer(MongoServerSettings.FromClientSettings(mongoClient.Settings));
The example code from #Robby works, but it doesn't return what your code is expecting; it returns Interface objects. The C# driver was updated to utilize Interface methods, as well as a number of asynchronous functions, so updating your code is probably a good idea.
The new way to get a database is -- well, you don't get a database anymore. You get an IMongoDatabase which is an interface to the database. Also, you should not work with MongoCollections anymore (from the MongoDatabase object), when you get an IMongoDatabase you will work with an IMongoCollection. Refactoring? You bet! But it's worth it.
I would also recommend putting your default database in the Mongo URL formatted connection strings. That way you can keep hard-coded constants, such as the database name, out of your code.
// Get your connection string -- use the URL format as in example below:
// name="MongoConnectionStr" connectionString="mongodb://localhost/bookstore"
var connectionString = ConfigurationManager.ConnectionStrings["MongoConnectionStr"].ConnectionString;
var mongoUrl = MongoUrl.Create(connectionString);
var client = new MongoClient(connectionString);
// Use the Mongo URL to avoid hard-coding the database name.
var db = new MongoClient(mongoUrl).GetDatabase(mongoUrl.DatabaseName);
// books below is an IMongoCollection
var books = db.GetCollection<Book>("Books");