How to override request sequence from Spring Cloud Vault to the Vault? - spring-cloud-config

When my application which uses Spring Cloud Vault starter is requesting info from Vault, it searches the followed paths at generic secret back-end:
secret/myapp/vault
secret/myapp/dev
secret/myapp
secret/application/vault
secret/application/dev
secret/application
So as you can see, it does a lot of requests to a Vault and that's a problem because Vault will create a lot of unnecessary logs which is bad for a few reasons.
How can I change paths for the requests?
For instance, I want my application to go to secret/myapp/{profile} and that's all.

There are two approaches you can take:
Setting spring.cloud.vault.generic.default-context to an empty value.
Customize which paths Spring Vault accesses.
Run your app with fewer profiles activated.
Spring Vault creates path matrices based on the application name multiplied with the profiles you activated and based on a generic name multiplied with active profiles.
Providing a VaultConfigurer bean inside the bootstrap context gives you the most control over paths accessed by Spring Cloud Vault:
public class MyVaultConfigurer implements VaultConfigurer {
#Override
public void addSecretBackends(SecretBackendConfigurer configurer) {
configurer.add("secret/my-application");
configurer.registerDefaultGenericSecretBackends(false);
configurer.registerDefaultDiscoveredSecretBackends(true);
}
}

Related

Random ASP.NET Core Identity Logouts in production

I have an ASP.NET Core MVC web application that uses Identity to handle user account Authentication and Authorization. When running the app on my local IIS express everything was working properly. After deploying the app to a shared web server I started to notice that the logged-in user accounts would get logged out at seemingly random intervals. Through experimentation, I was able to determine that the log-outs were occurring whether the account was active or idle. They were occuring at no recuring time interval and completely unrelated to any expiry time that I set on my cookies. The logouts were occuring on every view in the web app so I couldn't pin the issue to any particular controller. Also I use the same Database for the published and the local testing version of the app and therefore the same user accounts. I anyone has an idea where to start looking for a solution it would be greatly appreciated.
I posted this question because there is a great answer that 90% solves the issue Here however of the multiple forums that I have been scouring over the last few days there are none with an accepted answer. I am posting this answer to address this. The underlying cause of the issue is that IIS application pool is being reset or recyling and on a shared host with multiple applications using it this can be happening fairly frequently. As is suggested in the above link Data Protection has to be used to persist the keys if IIS application pool recycles. Here is the code offered in the original answer.
services.AddDataProtection()
.PersistKeysToFileSystem(new System.IO.DirectoryInfo("SOME WHERE IN STORAGE"))
//.ProtectKeysWithCertificate(new X509Certificate2());
.SetDefaultKeyLifetime(TimeSpan.FromDays(90));
This code is to be added in ConfigureServices in Startup.cs
As my application is being hosted on a shared server using .PersistKeysToFileSystem was not an option so instead I persisted the keys using DbContext like this:
services.AddDataProtection().PersistKeysToDbContext<MyKeysContext>()
.SetDefaultKeyLifetime(TimeSpan.FromDays(90));
Based on This article here I build MyKeysContext as follows.
// Add a DbContext to store your Database Keys
services.AddDbContext<MyKeysContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyKeysConnection")));
In ConfigureServices in Startup.cs and then created a class called MyKeysContext as follows:
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;
namespace WebApp1
{
public class MyKeysContext : DbContext, IDataProtectionKeyContext
{
// A recommended constructor overload when using EF Core
// with dependency injection.
public MyKeysContext(DbContextOptions<MyKeysContext> options)
: base(options) { }
// This maps to the table that stores keys.
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
}
I created the database on my Host this will probably be different so I have omitted this step. then I applied the migrations to the database like this.
Add-Migration AddDataProtectionKeys -Context MyKeysContext
Update-Database -Context MyKeysContext

Data Protection keys collection is intermittently modified causing 401 errors

I have a two sites that share an authentication cookie:
Main site that generates auth cookie
Chat site that hosts a SignalR Hub.
The Main site's cookie is sent through and used to authenticate SignalR negotiation requests.
I recently deployed some large scale changes moving from ASP.NET Framework to .NET5. Part of this change meant using the new Data Protection keys so the auth ticket on both apps could be decrypted (previously, the ASP.NET Framework version just needed the machine keys on both apps to match, which could be set in web.config).
Here's what the Data Protection code looks like, used in both the Main and Chat sites:
public void ConfigureServices(IServiceCollection services)
{
services.AddCustomDataProtection(_configuration);
...
}
public static IServiceCollection AddCustomDataProtection(this IServiceCollection services, IConfiguration configuration)
{
var siteSettings = configuration
.GetSection(SiteSettings.SectionName)
.Get<SiteSettings>();
var dataProtection = services.AddDataProtection()
.SetApplicationName(siteSettings.SiteName);
var dataProtectionSettings = configuration
.GetSection(DataProtectionSettings.SectionName)
.Get<DataProtectionSettings>();
if (!string.IsNullOrWhiteSpace(dataProtectionSettings.KeyVaultIdentifier))
{
dataProtection
.PersistKeysToAzureBlobStorage(
configuration.GetConnectionString("StorageConnectionString"),
dataProtectionSettings.KeyStoreContainerName,
dataProtectionSettings.KeyStoreBlobName)
.ProtectKeysWithAzureKeyVault(
new Uri(dataProtectionSettings.KeyVaultIdentifier),
new DefaultAzureCredential());
}
return services;
}
Since this was deployed, we've had some strange issues whereby the Data Protection keys blob stored in Azure Storage is modified throughout the day. It doesn't look like there's any rhyme or reason behind when this happens.
From my understanding, the Data Protection keys are by default refresh every 90 days or so, however this is happening 1-2 times a day. The code in the apps never interact with the Key Vault keys nor the Data Protection key blob directly (only via the code posted below) and I have added logs that show the correct settings are being passed through to the Data Protection extension methods.
On the other hand, I have been having intermittent issues where when the Main site sends an negotiate request to the Chat site, it receives a 401 error, indicating that the the cookie/auth ticket was invalid or otherwise couldn't be decrypted. I can reproduce this when the key is modified by restarting the Main site, logging out and then logging in again. I think these two problems are related.
My stab-in-the-dark explanation of this behaviour would be that perhaps the Main site is correctly picking up a change in the Data Protection keys, however the Chat site does not. The Chat site cannot then decrypt an auth ticket that was encrypted using a key it doesn't have access to. Restarting the Chat site fixes the issue, presumably because the Data Protection keys are reloaded at startup.
So I have two main concerns:
why is the Data Protection key blob being modified?
why is the Chat site not picking up the new keys if indeed new keys are being added to the collection of Data Protection keys?
The issue ended up being that both the Main and Chat sites stored the data protection keys in the same blob in Azure Storage. This caused the strange behaviour I was witnessing with the blob being modified, and in turn, the application errors I was experiencing.
I figured storing the keys in the same location would be fine due to my reading of the documentation at the time relating to the SetApplicationName() method causing the keys to be isolated from one another. Unfortunately that isolation did not extend to the actual physical data protection keys rather, just the payload stored inside of them. The documentation surrounding app isolation has since been updated and is now far more detailed.

Bypass setup wizard in fusion auth to create application

I am using Fusion Auth as an auth backend for my project.
After starting up the container as shown here(https://fusionauth.io/docs/v1/tech/installation-guide/docker), if we open the URL(Ex: http://localhost:9011) we need to create an admin user and then we will be able to create Application, API Key, Lambda.
As my project doesn't involve UI interaction, I wanted to create Application without involving UI interaction(i.e., setup-wizard).
I was unable to find an API that relates to setup-wizard.
As I saw Since this is your own private instance of FusionAuth, you need to create a new administrator account that you will use to log in to the FusionAuth web interface. in setup-wizard I thought this is required only for UI, So I tried to create Application using this(https://fusionauth.io/docs/v1/tech/apis/applications#create-an-application) API, but it is returning a 401(Unauthorized).
Can someone help me to either create an application without authentication or bypass setup-wizard?
The FusionAuth Kickstart does exactly what you need. It will allow you to pre-define the configuration that you require in a JSON file and then the system will bootstrap itself automatically.
The base use case it to provision an API key which would allow you to programmatically configure the rest of the system by using APIs after an API key has been created.
{
"apiKeys": [{
"key": "a super secret API key that nobody knows"
}]
}
You also have the option of building your entire configuration in the Kickstart definition. There are a bunch of examples and walk throughs on the Kickstart installation guide.
Good luck!

OAuth2 (Okta): How to set authorization

I'm writing an application using Oauth2 using Okta, and I'm running into a problem:
What I would like to do is have Okta (or some other method) to automatically set up and provide authorization details of my user. I already have Okta able to support authentication of the user, I am specifically looking for help regarding authorization. In particular, what I would like to do is divide authorization of my APIs into 3 segments:
1) A group of APIs which are available to any user, even ones who are not authenticated.
2) A group of APIs which are only available to authenticated users.
3) A group of APIs which are locked under permission-based (authorization) requirements.
It's the 3rd group I'm having trouble with. I have my security context set up as follows:
#Configuration
#EnableOAuth2Sso
public class SecurityConfig extends OAuth2SsoDefaultConfiguration {
public SecurityConfig(ApplicationContext applicationContext) {
super(applicationContext);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/anyaccess/**").permitAll()
.antMatchers("/credential/**").hasRole("ADMIN");
super.configure(http);
http.logout().logoutSuccessUrl("/");
}
}
So /anyaccess can be accessed by anyone, and anything else except /credential can be accessed by any authenticated user.
When I log into my application through Okta, I get an Authentication and Principal object which seem to be automatically generated somewhere, somehow (it's this somewhere, somehow that I'm mostly looking for clarification on). However, those objects do not have any set permissions, nor do they appear to provide a way to add additional permissions for future requests. How can I:
1) Set up these Authentication and Principal objects to contain the permissions I want per user?
2) Make sure that these are set up automatically on user sign-in through Okta and don't require an additional API call?
3) Persist changes to this configuration and make that part of my application authorization service?
4) Is there any way I can manage this through Okta configuration, or so I need to have a separate service set up to manage this and tack that onto my Okta authentication service?
Thanks.
You can add user's groups to a "groups" claim and the Okta Spring Boot starter will automatically convert those to Spring Security authorities.
From the top menu, go to API and click on Authorization Servers.
Click on the default authorization server.
Click on the Claims tab.
Click the Add Claim button.
Update the popup form to match the image below.
Note that the Filter Regex is .*.
Then you can use #PreAuthorize("role_name") on your methods.
This blog post has more information.

How to propagate spring security login to EJBs?

Context
I have a J2EE application running on a JBoss 4.2.3 application server. The application is reachable through a web interface. The authentication is done with basic authentication. Inside of the EJBs I ask the security context of the bean for the principal (the name of the logged in user) and do some authorization checks if this user is allowed to access this method of the EJB. The EJBs life inside a different ear than the servlets handling the web frontend, so I can't access the spring application context directly.
Required change
I want to switch to Spring Security for handling the user login.
Question
How can I propagate the spring login information to the JBoss security context so I can still use my EJBs without having to rewrite them?
Ideas and links
I already found a page talking about "Propagating Identity from Spring Security to the EJB Layer", but unfortunatelly it refers to an older version of Spring Security (Acegi) and I'm not familiar enough with Spring Security to make this work with the actual version (3.0.2).
Here is something that looks similar using WebLogic.
If you properly configure spring-security (filter in filter chain, security-context.xml),
you may use annotation #Secured, to restrict users with needed user roles. You may use this annotation on class level or/and method level.
If you need to know all authorization info about current user, you may use this helper (i wrote this for my webapp, but it maybe useful for other. MyUserDetails is a service bean, the spring-security's UserDetail descendant.):
public class LoginHelper {
/**
* #return user object if user is authenticated and null if is not
*/
public static User getUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Object principal = authentication.getPrincipal();
if (principal instanceof MyUserDetails) {
return ((MyUserDetails) principal).getUser();
}
}
return null;
}
/**
* Check for authenticated user
*
* #return true if user is authenticated and false if is not
*/
public static boolean isAuthenticated() {
final User user = getUser();
return user != null;
}
}
I have the same issue, and it would be great if someone could think of a better way to integrate Spring Security and a Java EE application with EJBs.
I think you can annotate your classes with your own annotations such as #MyAnnotation("ADMIN"). And then create an interceptor to manually check the beforementioned "LoginHelper" to get the users's privilege and compare with the method's annotation attributes. And throw an exception when the Names don't match.