I have all my Cosmos Dbs setup to authenticate using DefaultAzureCredentials, and I have the arm resource manager for my gremlin account using DefaultAzureCredentials, however I can't figure out to get it to work with the gremlin.net side.
Eg I have
var credentials = new DefaultAzureCredentials();
but how do i assign that to
var gremlinServer = new GremlinServer(hostname: _gremlinHostname,
port: _port,
enableSsl: _enableSsl,
username: $"/dbs/{options.UniverseId}/colls/{graphName}",
password: !!crendentials goes here!!);
I believe you'll need to use the Azure CosmosDB SDK to retrieve a RBAC-based access token (the Gremlin.NET API knows nothing of Azure CosmosDB, and RBAC is a CosmosDB based concept).
Once you have an access token retrieved, you would then pass that in as the "password" when instantiating the GremlinServer(...) object.
See https://learn.microsoft.com/en-us/azure/cosmos-db/graph/how-to-use-resource-tokens-gremlin
Related
I'm trying to require aws sdk database for use in a web application, but I'm getting the following errors
const AWS = require(["aws-sdk"]);
AWS.config.update({ region: "ap-southeast-2" });
AWS.config.update({
region: "{Region[enter image description here][1]}",
// For security reasons, do not store AWS Credentials in your files. Use Amazon Cognito instead.
accessKeyId: "{Key}",
// secretAccessKey default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon Cognito instead.
secretAccessKey: "{Key}"
});
You're using the wrong syntax, passing an array to require is part of the callback syntax and expects a function as a second argument.
Try this instead:
const AWS = require("aws-sdk");
Also, I'm not sure why you're calling config.update twice, you probably should just do it once to avoid any issues, or at a minimum to avoid confusion.
We are using the Audit.NET SqlServer Data Provider to store Audit logs in our Microsoft SQL Server. We are currently in the progress of migrating to the use of Azure SQL with Managed Identity to access the database. We haven't been able to get Audit.NET working with Azure SQL and the use of Managed Identity to connect to said database. The documentation doesn't provide any information on whether this functionality is supported or not.
We have managed to do this for our own database connections using Entity Framework Core by adding an Access Token to the SQL connection used by the Context like so:
SqlConnection sqlConnection = new SqlConnection(connectionString);
sqlConnection.AccessToken = new AzureServiceTokenProvider()
.GetAccessTokenAsync("https://database.windows.net/")
.Result;
This works perfectly fine. The issue we are running into is that we want to achieve the same with the Audit.NET Sql Data Provider. Due to the AuditContext being used by the SqlDataProvider being internal we are unable to pass an Access Token to the SqlConnection used.
The only solution we've come up with is writing our own Data Provider that is virtually the same as the SqlDataProvider, the only difference being that the Context used will set an Access Token on the SqlConnection. Is this the only viable solution here or does Audit.NET offer some other way to get it working with Azure SQL and Managed Identity?
I think the best way could be exposing an optional setting to provide the DbContextOptions where you can set an Interceptor like the one from here to set the AccessToken for the connection.
So you could initialize your configuration like this:
Audit.Core.Configuration.Setup()
.UseSqlServer(sql => sql
.ConnectionString("connection string")
.DbContextOptions(new DbContextOptionsBuilder()
.AddInterceptors(new AzureAuthenticationInterceptor(new AzureServiceTokenProvider()))
.Options));
or
Audit.Core.Configuration.Setup()
.UseSqlServer(sql => sql
.DbContextOptions(new DbContextOptionsBuilder()
.UseSqlServer("connection string")
.AddInterceptors(new AzureAuthenticationInterceptor(new AzureServiceTokenProvider()))
.Options));
UPDATE
The new DbContextOptions settings was added on version 16.2.1
I am trying to retrieve secrets from Azure Key Vault using Service Identity in an ASPNet 4.6.2 web application. I am using the code as outlined in this article. Locally, things are working fine, though this is because it is using my identity. When I deploy the application to Azure I get an exception when keyVaultClient.GetSecretAsync(keyUrl) is called.
As best as I can tell everything is configured correctly. I created a User assigned identity so it could be reused and made sure that identity had get access to secrets and keys in the KeyVault policy.
The exception is an AzureServiceTokenProviderException. It is verbose and outlines how it tried four methods to authenticate. The information I'm concerned about is when it tries to use Managed Service Identity:
Tried to get token using Managed Service Identity. Access token could
not be acquired. MSI ResponseCode: BadRequest, Response:
I checked application insights and saw that it tried to make the following connection with a 400 result error:
http://127.0.0.1:41340/MSI/token/?resource=https://vault.azure.net&api-version=2017-09-01
There are two things interesting about this:
Why is it trying to connect to a localhost address? This seems wrong.
Could this be getting a 400 back because the resource parameter isn't escaped?
In the MsiAccessTokenProvider source, it only uses that form of an address when the environment variables MSI_ENDPOINT and MSI_SECRET are set. They are not set in application settings, but I can see them in the debug console when I output environment variables.
At this point I don't know what to do. The examples online all make it seem like magic, but if I'm right about the source of the problem then there's some obscure automated setting that needs fixing.
For completeness here is all of my relevant code:
public class ServiceIdentityKeyVaultUtil : IDisposable
{
private readonly AzureServiceTokenProvider azureServiceTokenProvider;
private readonly Uri baseSecretsUri;
private readonly KeyVaultClient keyVaultClient;
public ServiceIdentityKeyVaultUtil(string baseKeyVaultUrl)
{
baseSecretsUri = new Uri(new Uri(baseKeyVaultUrl, UriKind.Absolute), "secrets/");
azureServiceTokenProvider = new AzureServiceTokenProvider();
keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
}
public async Task<string> GetSecretAsync(string key, CancellationToken cancellationToken = new CancellationToken())
{
var keyUrl = new Uri(baseSecretsUri, key).ToString();
try
{
var secret = await keyVaultClient.GetSecretAsync(keyUrl, cancellationToken);
return secret.Value;
}
catch (Exception ex)
{
/** rethrows error with extra details */
}
}
/** IDisposable support */
}
UPDATE #2 (I erased update #1)
I created a completely new app or a new service instance and was able to recreate the error. However, in all instances I was using a User Assigned Identity. If I remove that and use a System Assigned Identity then it works just fine.
I don't know why these would be any different. Anybody have an insight as I would prefer the user assigned one.
One of the key differences of a user assigned identity is that you can assign it to multiple services. It exists as a separate asset in azure whereas a system identity is bound to the life cycle of the service to which it is paired.
From the docs:
A system-assigned managed identity is enabled directly on an Azure service instance. When the identity is enabled, Azure creates an identity for the instance in the Azure AD tenant that's trusted by the subscription of the instance. After the identity is created, the credentials are provisioned onto the instance. The lifecycle of a system-assigned identity is directly tied to the Azure service instance that it's enabled on. If the instance is deleted, Azure automatically cleans up the credentials and the identity in Azure AD.
A user-assigned managed identity is created as a standalone Azure resource. Through a create process, Azure creates an identity in the Azure AD tenant that's trusted by the subscription in use. After the identity is created, the identity can be assigned to one or more Azure service instances. The lifecycle of a user-assigned identity is managed separately from the lifecycle of the Azure service instances to which it's assigned.
User assigned identities are still in preview for App Services. See the documentation here. It may still be in private preview (i.e. Microsoft has to explicitly enable it on your subscription), it may not be available in the region you have selected, or it could be a defect.
To use a user-assigned identity, the HTTP call to get a token must include the identity's id.
Otherwise it will attempt to use a system-assigned identity.
Why is it trying to connect to a localhost address? This seems wrong.
Because the MSI endpoint is local to App Service, only accessible from within the instance.
Could this be getting a 400 back because the resource parameter isn't escaped?
Yes, but I don't think that was the reason here.
In the MsiAccessTokenProvider source, it only uses that form of an address when the environment variables MSI_ENDPOINT and MSI_SECRET are set. They are not set in application settings, but I can see them in the debug console when I output environment variables.
These are added by App Service invisibly, not added to app settings.
As for how to use the user-assigned identity,
I couldn't see a way to do that with the AppAuthentication library.
You could make the HTTP call manually in Azure: https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http.
Then you gotta take care of caching yourself though!
Managed identity endpoints can't handle a lot of queries at one time :)
Im working on a Cosmos DB app that stores both standard documents and graph documents. We are saving both types via the documentdb api and I am able to run graph queries that return Graphson using the DocumentClient.CreateGremlinQuery method. This graphson is to be read by a web app and the graph displayed for user viewing and so on.
My issue is that I cannot define the version of the Graphson format returned when using the Microsoft.Azure.Graphs method. So i looked into Gremlin.net and that has a lot more options in this regard from the documentation.
However I am finding connecting to the Cosmos Document Db using gremlin.net difficult. The server variable which you define like this :
var server = new GremlinServer("https://localhost/",8081 , enableSsl: true, username: $"/dbs/TheDatabase/colls/TheCOllection", password: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==");
then results in a uri that has "/gremlin" and it cannot locate the database end point.
Has anyone used Gremlin.net to connect to a Cosmos document database (not a Cosmos db configured as a graph db) that has been setup as a document db not a graph db ? The documents in it are graph/gremlin compatible in their format with _isEdge / label / _sink etc.
Cheers,
Mark (Document db/Gremlin/graph newbie)
I am trying to query a Cosmos MongoDB collection, I can connect to it fine with Robo3T and 3T Studio, and dotnet core mongo client (in a test harness). I can do a count of entities (db.[collection_name].count({})) in all of the platforms, but every query (db.[collection_name].find({}) fails with the following error :
Error: error: {
"_t" : "OKMongoResponse",
"ok" : 0,
"code" : 1,
"errmsg" : "Unknown server error occurred when processing this request.",
"$err" : "Unknown server error occurred when processing this request."}
Here is my sample query from Rob3T and below that sample .NET harness.. Doesn't matter what I use, same error every time.
db.wihistory.find({})
and the dotnet core code :
string connectionString = #"my connections string here";
MongoClientSettings settings = MongoClientSettings.FromUrl(
new MongoUrl(connectionString)
);
settings.SslSettings =
new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };
var mongoClient = new MongoClient(settings);
var database = mongoClient.GetDatabase("vstsagileanalytics");
var collection = database.GetCollection<dynamic>("wihistory");
var data = collection.Find(new BsonDocument()).ToList();
System.Console.WriteLine(data.ToString());
The issue comes from mixing API usage in the account. As stated in the comments, you are using Azure Function's Cosmos DB Output binding, which uses the SQL API (.NET SDK for SQL API) to connect to the account and store data. There is a note in that documentation that says:
Don't use Azure Cosmos DB input or output bindings if you're using
MongoDB API on a Cosmos DB account. Data corruption is possible.
The documents stored through this method do not enforce certain MongoDB requirements (like the existence of a "_id" identifier) that a MongoDB client would (a MongoDB client would automatically create the "_id" if not present).
Robo3T and other Mongo clients (including the Azure Portal) are failing to correctly parse and read the stored documents as valid MongoDB documents (due to the lack of requirements like "_id") and that is the cause of the error.
You can either switch to use a Cosmos DB SQL API account if you want to maintain the Azure Functions pipeline or change the output binding and replace it with a manual implementation of a MongoDB client.