Obtain Access Token for the connection to PostgreSQL in Azure Functions - postgresql

I have created some Azure Functions, and I would like to connect to Postgres database using an Access Token (for the connection of the user is doing the request to the endpoint of Azure Function). I've been following this page: https://learn.microsoft.com/en-us/azure/postgresql/howto-configure-sign-in-aad-authentication
For Authentication/Authorization in my functions I have created an Azure Active Directory app (in App registrarions). In this app, (not sure if this is useful) I have given permissions to the API of OSSRDBMS:
Then, I get the Access Token of the next endpoint of my App Service (where are my Functions):
MYAPP_SERVICE.azurewebsites.net/.auth/me
And I am trying to get the connection with this Access Token, but appearly is not the good one. What am I missing or how can I get the correct Access Token? I understand how works with Azure CLI, but I am trying to use the Access Token of the endpoint of my App Service... or can I do an HTTP Request to get the correct token?
I need a bit of guidance in this matter.
Thanks beforehand

If you want to connect Postgres database with Azure AD auth in Azure function, we can Azure Managed Identity to do Azure AD auth then get Azure AD access token and connect database.
The detailed steps are as below
Enable Azure MSI fro your Azure function app
Get the client id of the MSI
az login
az ad sp show --id <the object id of the msi> --query appId --output tsv
Configure Azure AD admin in Postgres database
Use the Azure AD admin to connect the database. (I use PgAdmin to connect)
SET aad_validate_oids_in_tenant = off;
CREATE ROLE <userName> WITH LOGIN PASSWORD '<the appid of the MSI>' IN ROLE azure_ad_user;
Configure Postgres server firewall. Please add the Azure function app outbound IP addresses in the firewall. Regarding how to get the Azure function app outbound IP addresses and configure Postgres server firewall, please refer to here and here
If you enable SSL, please download SSL certificate via the link
Function. (I use .net core to write the sample)
a. sdk
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.5.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.8" />
<PackageReference Include="Npgsql" Version="4.1.3.1" />
b. add above SSL certificate in project. For example, I create a folder cert in my project and save cert in the folder
c. code
[FunctionName("Http")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log, ExecutionContext context)
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://ossrdbms-aad.database.windows.net");
string Host = "test05.postgres.database.azure.com";
string User = "testuer#test05";
string Database = "postgres";
string connString =
String.Format(
"Server={0}; User Id={1}; Database={2}; Port={3}; Password={4};SSLMode=Require",
Host,
User,
Database,
5432,
accessToken);
string result = string.Empty;
using (var conn = new NpgsqlConnection(connString))
{
ProvideClientCertificatesCallback provideClientCertificates = clientCerts =>
{
string clientCertPath = context.FunctionAppDirectory + "\\cert\\BaltimoreCyberTrustRoot.crt.pem";
var cert = new X509Certificate2(clientCertPath);
clientCerts.Add(cert);
};
conn.ProvideClientCertificatesCallback += provideClientCertificates;
Console.Out.WriteLine("Opening connection using access token...");
conn.Open();
using (var command = new NpgsqlCommand("SELECT version()", conn))
{
var reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("\nConnected!\n\nPostgres version: {0}", reader.GetString(0));
result = reader.GetString(0);
}
}
}
return new OkObjectResult(result);
}
For more details, please refer to here

Related

Unable to configure multi tenant Azure ad with Identity server 4

I am having flutter mobile app and using identity server 4. Now I need to configure Azure Ad with identity server. In our scenario we have different customers having there own azure ad setup and we have a common login page.
Now, How can I configure multiple azure ad with identity server for different organizations having the fact each organization has its own AAD setup.
It would great if someone can share workflow details about how can we do this with flutter app.
• You can surely configure Azure AD as an external identity provider in Identity Server 4 by adding appropriate authentication handlers for Azure AD in your Identity Server 4 as below. Please do ensure that an application is registered in your client’s Azure AD for your Identity Server 4 with the redirect URI as ‘http://localhost:5000/signin-aad’(you can find it in the ‘Startup’ class in the ‘ConfigureServices’ method in your Identity Server 4 portal). Kindly enter the required details of the application registered, i.e., application ID, tenant ID, etc. in the below mentioned authentication handler for Azure AD and accordingly update it in the Identity Server 4: -
services.AddAuthentication()
.AddOpenIdConnect("aad", "Azure AD", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://login.windows.net/<Directory (tenant) ID>";
options.ClientId = "<Your Application (client) ID>";
options.ResponseType = OpenIdConnectResponseType.IdToken;
options.CallbackPath = "/signin-aad";
options.SignedOutCallbackPath = "/signout-callback-aad";
options.RemoteSignOutPath = "/signout-aad";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
Kindly find the below application registration details snapshot for your reference. Once done, then you will be able to see the ‘Azure AD’ login tab on your Identity Server 4 login portal under external login section. Through this option, a registered Azure AD user from your client side will be able to login to the Identity Server 4 with Azure AD credentials: -
Please do ensure that basically it is considered that Identity Server 4 is configured on ASP .Net Core build versions. Thus, the authentication handlers accordingly. Likewise, you can configure multiple authentication handlers in your Identity Server 4 for multiple Azure AD tenants and ensure that external identity login is enabled for every tenant. Please find the below link for more information: -
https://www.ashleyhollis.com/how-to-configure-azure-active-directory-with-identityserver4

DevOps : Non-Interactive login in new DevOps(VSTS) not working getting error 'TF30063: You are not authorized to access

I am trying to connect to Azure DevOps previously known as VSTS using c#. I want to connect to it without the login screen of azure DevOps. I am currently trying the following code but some how it is not working
NetworkCredential netCred = new NetworkCredential("test#hotmail.com", "test");
Uri tfsuri = new Uri("https://dev.azure.com/test10");
VssBasicCredential bsCred = new VssBasicCredential(netCred);
VssCredentials vssCred = new VssClientCredentials(bsCred);
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(tfsuri, vssCred);
collection.Authenticate();
var witClient = collection.GetClient<ProjectHttpClient>();
var listOfProjects = witClient.GetProjects().Result;
libraries I am using
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.Operations;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
The code prompts a login screen, on which if I enter the password the auth still does not work. I dont want the login screen to appear and only want to connect with the username and password.
With alternate credentials this method is working but it is not my requirement and I can not use alternate credentials.
I have tried following the samples from the official site but no solution is working for the new DevOps.
Any Solution how can I authenticate with usernanme/password in the new DevOps without the login screen
The class TfsTeamProjectCollection is from the old .Net libraries, try the new Azure DevOps .Net libraries, and you can authenticate in a few ways:
NTLM
The most basic one is constructing a VssCredentials instance with no parameter at all and what you’ll be using is simply put integrated authentication / NTLM:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssCredentials());
Basic Authentication
VSTS and TFS also provide means to utilize Basic authentication (HTTP AUTH) which you need to create and enable first (see VSTS guidelines) and once you’ve done so, you can use them via the API like this:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssBasicCredential(username, password));
Personal Access Tokens
Next up are Personal Access Tokens (PAT) which you can easily create following the VSTS guidelines and those PATs are a means of authenticating separately from your actual credentials with a fine-grained & per access token scopes of security. Simply put it allows you to create a PAT for every use-case or even application and thereby enabling a secure and clearly separated way of giving an application or 3rd party access to your VSTS or TFS system on your behalf.
To use these via the API, you use the exact same mechanism as via Basic Authentication but you simply don’t provide any username (well – an empty one to be precise), and the PAT itself is used as the password:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssBasicCredential(string.Empty, pat));
Visual Studio Sign-in Prompt
Moreover, another way of authenticating is using the standard VS Sign-In prompt which is similarly easy and exposed via the VssClientCredentials class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssClientCredentials());
OAuth Authentication
OAuth is a widely used but a slightly more tedious authorization protocol to implement but luckily there’s a thorough sample application available at CodePlex specifically for VSTS / VSO (which also works for on-premises).
Once you have the corresponding access token, you can use it to VSTS / TFS utilizing the VssOAuthCredential class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssOAuthCredential(accessToken));
Azure Active Directory Authentication
Last but not least you can utilize Azure Active Directory identities to authenticate against a VSTS or TFS system via the VssAadCredential class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssAadCredential(username, password));

Azure Key Vault: Secret not found error

I've created the Key Vault and entered a secret. When I run my services locally using .NET, I am able to retrieve the secret via the key vault. Here's what I did:
1) Created an SSL certificate
2) Used that SSL certificate to create an AD application
3) Created a Service Principle for the above application
4) Gave full key vault access to this application
5) I put the VaultURI, ServicePrincipal.Application ID, and the cert thumbprint in the Web.config file
6) I also uploaded the *.pfx of that cert to my cloud service
When I run my service locally, I am able to retrieve the secret. I have even tried retrieving the secret via powershell and I have been successful. When I deploy my code to Azure, I am unable to retrieve the secret.
It says:
Type : Microsoft.Azure.KeyVault.Models.KeyVaultErrorException, Microsoft.Azure.KeyVault, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 Message : Secret not found: QSAccounts7126 Source : Microsoft.Azure.KeyVault Help link :
I have spent 3 days looking at it and retesting every possible scenario and haven't figured out what is wrong. Can someone please help in identifying the issue or directing me in the right path for debugging?
I even tried publishing the cloud service in debug mode in Azure, and for some reason that did not work either.
Any help you can provide would be greatly appreciated.
private async Task<string> getSecretConnection(string connectionName)
{
var kvName = ConfigurationManager.AppSettings["vaultName"];
var kvClientId = ConfigurationManager.AppSettings["clientId"];
var kvClientThumbprint = ConfigurationManager.AppSettings["clientThumbprint"];
using (keyVaultHelper = new AzureKeyVaultHelper(kvClientId, kvClientThumbprint, kvName))
{
var bundle = await keyVaultHelper.GetAzureKeyVaultSecretAsync(connectionName);
return bundle;
}
public async Task<string> GetAzureKeyVaultSecretAsync(string secretName)
{
var bundle = await this.KvClient.GetSecretAsync(KeyVaultUrl, secretName);
return bundle.Value;
}
This is the code that runs for authentication:
private async Task<string> getAccessTokenFromSPNAsync(string authority, string resource, string scope)
{
//clientID and clientSecret are obtained by registering
//the application in Azure AD
var certificate = CertificateHelper.FindCertificateByThumbprint(this.ClientThumbprint);
var assertionCert = new ClientAssertionCertificate(this.ClientId, certificate); //needed for authentication
var clientCredential = new ClientCredential(this.ClientId, this.ClientThumbprint);
var authContext = new AuthenticationContext(authority, TokenCache.DefaultShared);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, assertionCert);
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the token from Azure AD using certificate");
}
return result.AccessToken;
}
Can someone please help in identifying the issue or directing me in the right path for debugging?
It seems that you need to add the WEBSITE_LOAD_CERTIFICATES in your Azure WebApp setting to load certification to your web applications personal certificate store. More details you could refer this blog. We also could remote debug the WebApp to get more detail error information.
Adding an app setting named WEBSITE_LOAD_CERTIFICATES with its value set to the thumbprint of the certificate will make it accessible to your web application. You can have multiple comma-separated thumbprint values or can set this value to “ * “ (without quotes) in which case all your certificates will be loaded to your web applications personal certificate store.
I am not sure that your code is correct.
For example the constructor for ClientCredential takes a Client ID and Client Secret, your code is passing in a Client ID and Certificate Thumbprint.
See the Microsoft article Use Azure Key Vault from a Web Application for example code. I have used the code in this article and it works as expected when deployed to Azure.

azure sdk for net login is takes too long

I am using Fluent Library to develop a web app which can create a sql server on azure. The console app works great but when I implement the code to a web api it stuck in authentication step. I'm sure about the credentials which are true and I have a Service Principal.
// Authenticate
var credentials = new AzureCredentials(new ServicePrincipalLoginInformation { ClientId = ClientId, ClientSecret = Password }, tenantId, AzureEnvironment.AzureGlobalCloud);
var azure = Azure.Configure().Authenticate(credentials).WithDefaultSubscription();
I also can repro it on my side. I try to debug it with following code and add quick watch for azureauth.WithDefaultSubscription(), then get value The function evaluation requires all threads to run. So I guess that it may run some threads that WebAPI can't handle.
var azureauth = Azure.Configure().Authenticate(credentials);
azureauth.WithDefaultSubscription()
Please have a try to use following code to use specified subscriptionId as workaround. It works correctly on my side.
var azure = Azure.Configure().Authenticate(credentials).WithSubscription("subscriptionId");

Box - How to create a Service Account

I'd like to create a Service Account so I'd be able to authenticate with it with my app.
All I found is this guide, but it doesn't say how to create such an account.
Can anyone assist?
Thanks
The docs aren't that clear but a Service Account == App. So if you create an app in the developer console and set authentication type to server authentication (jwt) and add your public key and get the app authorized in the admin console then you're ready to instantiate a service account with the following code:
String privateKey = new String(Files.readAllBytes(Paths.get(PRIVATE_KEY_FILE)));
JWTEncryptionPreferences encryptionPref = new JWTEncryptionPreferences();
encryptionPref.setPublicKeyID(PUBLIC_KEY_ID);
encryptionPref.setPrivateKey(privateKey);
encryptionPref.setPrivateKeyPassword(PRIVATE_KEY_PASSWORD);
encryptionPref.setEncryptionAlgorithm(EncryptionAlgorithm.RSA_SHA_256);
IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(MAX_CACHE_ENTRIES);
// BoxDeveloperAPIConnection == Service Account
BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(ENTERPRISE_ID, CLIENT_ID, CLIENT_SECRET, encryptionPref, accessTokenCache);