How to avoid connecting to Azure Active Directory in SpringBootApp - JUnit - azure

I have a Springboot app that connects to Azure Active Directory and getting the properties from there.
I don't know exactly how the Active Directory connection works, but I am trying to write JUnits for the app without having to call the real Azure Active Directory. Whenever I run my JUnit, it keeps calling Azure.
I know I can mock the AzureCredentials class, but I really don't know how to make my JUnit use the mock even if I created a mock. None of the classes explicitly depend on the AzureCredentials class. It's somehow being called inherently.
Please guide me as to how I could JUnit this app without connecting to Azure.
public class AzureCredentials implements AppConfigurationCredentialProvider, KeyVaultCredentialProvider {
#Override
public TokenCredential getKeyVaultCredential(String uri) {
return getCredential();
}
#Override
public TokenCredential getAppConfigCredential(String uri) {
return getCredential();
}
private TokenCredential getCredential() {
return new EnvironmentCredentialBuilder().build();
}
}
EDIT 14/2/2023: I've also tried by using a DUMMY connection string for the tests, but then I get this error:
Suppressed: com.microsoft.aad.msal4j.MsalServiceException: AADSTS500011: The resource principal named https://testEndPoint was not found in the tenant named...
I understand the cause for this error, but I just don't want the test to try to connect at all, if there is a way to do this!

Related

Microsoft.Identity.Web inside an Azure function

I need to call a downstream API, i.e., PowerBI Service, from inside my Azure Function. I have a working example inside a web app but I am not able to make it happen inside my Azure Function.
In the web app sample, the configuration happens via Microsoft.Identity.Web like this.
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Then inside a controller I am able to receive a ITokenAcquisition object injected in the constructor
public HomeController(ITokenAcquisition tokenAcquisition, ...
{
this._tokenAcquisition = tokenAcquisition;
and I can do:
var accessToken =
this._tokenAcquisition.GetAccessTokenForAppAsync(powerbiApiDefaultScope).Result;
and get a token credential like this:
var tokenCredentials = new TokenCredentials(accessToken, "Bearer");
With this tokenCredentials I can achieve my goal, i.e., instantiate a PowerBIClient class to interact with PowerBI service.
var client = new PowerBIClient(new Uri(urlPowerBiServiceApiRoot), tokenCredentials);
The problem is that I am not able to set the configuration in the Startup class of my isolated Azure Function. Therefore, I cannot get a ITokenAcquisition injected in my Azure Fucntion that allows me to get an access token.
Could anybody please advice? Thanks a million.

Downscope Azure SQL Server permissions

While running on an app service in Azure, I would like to use the managed service identity to authenticate against Azure SQL Server with two sets of permissions. Within my service I'd like to have a read/write DBContext and a readonly DBContext. Is there a way to downgrade access after authenticating?
I don't necessarily have access to an AG with a readonly replica so I don't think I can use applicationintent=readonly and EXECUTE AS only seems to apply in a stored procedure or function.
Any other suggestions?
I was wrong about EXECUTE AS not working outside of a stored proc/function (I found this documentation to be misleading, and later found this.
As such, I ended up going with the following solution:
Create a read-only user with no login
CREATE USER [readonly_user] WITHOUT LOGIN
ALTER ROLE [db_datareader] ADD MEMBER [readonly_user]
I create an interceptor that looks for the applicationintent=readonly flag to be set in the connection string
public class SessionContextDbConnectionInterceptor: DbCommandInterceptor {
/// <inheritdoc />
public override Task<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
DbCommand command,
CommandEventData eventData,
InterceptionResult<DbDataReader> result,
CancellationToken cancellationToken = new CancellationToken()) {
if (eventData.Connection.ConnectionString.Contains("applicationintent=readonly",
StringComparison.InvariantCultureIgnoreCase)) {
command.CommandText = $"EXECUTE AS USER = 'readonly_user';\n{command.CommandText};\nREVERT;";
}
return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
}
}
Then register the interceptor with the DB context
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"))
.AddInterceptors(new SessionContextDbConnectionInterceptor()));

ServiceStack + Azure Cloud Service (CloudConfigurationManager)

We've recently converted our ServiceStack application to an Azure Cloud Service.
We're finding that, internally, ServiceStack is not aware that it needs to load configuration settings (like oauth.RedirectUrl) using CloudServiceConfiguration manager instead of ConfigurationManager.
Is there a way to wire up ServiceStack appropriate for the new environment?
Thanks!
There's no AppSettings provider for Azure CloudServiceConfiguration, it should be fairly easy to create one by inheriting AppSettingsBase and overriding GetNullableString() otherwise the easiest way is to populate a Dictionary<string,string> with the configuration from Azure and load them into DictionarySettings, e.g:
AppSettings = new DictionarySettings(azureSettings);
If you want to both Web.config <appSettings/> and Azure Settings together you should use a cascading source of AppSettings in your AppHost constructor using MultiAppSettings, e.g:
AppSettings = new MultiAppSettings(
new DictionarySettings(azureSettings),
new AppSettings());
You don't need to use 'MultiAppSettings' because CloudConfigurationManager will fall back to your config appsettings section.
(appsettings only)
From my testing it seems you don't seem to need anything at all in asp.net website as web.config settings seem to get somehow overridden with azure settings. In a webjob however you will need to use the CloudConfigurationManager ...below is a suitable implementation of an servicestack AppSettings provider to wrap it.
public class AzureCloudSettings : AppSettingsBase
{
private class CloudConfigurationManagerWrapper : ISettings
{
public string Get(string key)
{
return CloudConfigurationManager.GetSetting(key, false);
}
public List<string> GetAllKeys()
{
throw new NotImplementedException("Not possible with CloudConfigurationManager");
}
}
public AzureCloudSettings() : base(new CloudConfigurationManagerWrapper()) { }
public override string GetString(string name)
{
return GetNullableString(name);
}
public override string GetNullableString(string name)
{
return base.Get(name);
}
}

Is it possible to set a machinekey for an Azure Worker Role

I have hosted an Owin WebAPI Server in an Azure Worker Role.
The Owin Authentication middleware seems to use the MachineKey to encrypt and generate Tokens.
This works perfectly when I have only one instance of this role, but as soon as I want to use several instances, the tokens generated by each instance are differents.
This is the same problem as a web farm, Azure automatically solves this for WebRoles using the same .net Machine Key for all instances in Web.config.
But this does not work for Worker Role instances.
Is there a trick to have Azure using the same machine key for all the intsances of a worker Role ?
Seems it would be easier than rewriting code to generate the tokens for Owin.
If your self-hosted application can reference System.Web, then you can use the same MachineKey implementaiton that the Microsoft.Owin.Host.SystemWeb does.
Put the configuration/system.web/machineKey settings in your App.config just like it is in the Web.config.
Reference reference System.Web and add the following class:
public class MachineKeyDataProtector : IDataProtector
{
private readonly string[] purposes;
public MachineKeyDataProtector(params string[] purposes)
{
this.purposes = purposes;
}
public byte[] Protect(byte[] userData)
{
return MachineKey.Protect(userData, this.purposes);
}
public byte[] Unprotect(byte[] protectedData)
{
return MachineKey.Unprotect(protectedData, this.purposes);
}
}
Then set your authentication options using that class:
var authenticationOptions = new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = new TicketDataFormat(new MachineKeyDataProtector(
typeof(OAuthBearerAuthenticationMiddleware).Namespace, "Access_Token", "v1")),
AccessTokenProvider = new AuthenticationTokenProvider(),
};

ServiceStack Tenant resolution by domain

I am looking for an example implementation for resolving tenants in a multi-tenant ServiceStack API layer.
If you've got your Api host setup and you've providing an implementation of AppHostBase, you can override the Configure method like so;
public class ApiHost : AppHostBase
{
public ApiHost() : base("Service Name", typeof(ApiHost).Assembly) { }
public override void Configure(Funq.Container container)
{
//resolve your tenant here..
}
}
Now you probably want some code to resolve your tenant. Say you were doing this via subdomain, you want something like this;
string subdomain = HttpContext.Current.Request.Url.Host.Split('.')[0].ToLower();
You should probably perform some checks to ensure validity of the url too. Then just use your repository or DAL to resolve your tenant with a relevant query.
After that you need to decide how you're going to pass your tenant about to your services and such. Question for another time, probably :)

Resources