Skip to content

Commit

Permalink
Merge pull request #420 from molgenis/feat/basic-auth-profile
Browse files Browse the repository at this point in the history
feat: add profile that only runs on basic auth
  • Loading branch information
marikaris authored Apr 17, 2023
2 parents da8b1ca + 972714d commit 3006e9e
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 65 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,6 @@ build/
/docker/logs/
/docker/data/
**/audit.log

application.yaml
application.yml
116 changes: 61 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,31 +47,79 @@ Armadillo 3 can be installed on any flavor of linux OS or modern Unix-based Mac
* Java 17 JRE or JDK
* Docker (for profiles)

To spin up your own server on a laptop, you first need
the [application.yml](https://raw.githubusercontent.com/molgenis/molgenis-service-armadillo/master/scripts/install/conf/application-local.yml)
and edit for your needs. Then you can run:

```
export SPRING_PROFILES_ACTIVE=<your profile>
export SPRING_CONFIG_LOCATION=<location to>/application-local.yml
java -jar molgenis-armadillo-3.*.jar
```
## To run using basic auth (only for testing!)

Armadillo assumes that you will use OIDC for user/password management, ideally linked to an identity provider such as [LS login](https://lifescience-ri.eu/ls-login/).
However, for most minimal testing you can run uses only basic auth and with one account with username/password 'admin'/'admin'.
Note that the 'oauth2' sign in option then is not functional.

Or using development mode
`
java -jar molgenis-armadillo-3.*.jar \
-Dspring.profiles.active=basic
`

## To run in development mode

Using development profile, we can test against auth.molgenis.org that is preconfigured in /armadillo/src/main/resources/application.yaml.
However, you then need a client-id and a secret

```
export SPRING_PROFILES_ACTIVE=development
java -jar molgenis-armadillo-3.*.jar
java -jar molgenis-armadillo-3.*.jar \
-Dspring.profiles.active=development
-Dspring.security.oauth2.client.registration.molgenis.client-id=xxx
-Dspring.security.oauth2.client.registration.molgenis.client-secret=xxx
```

## Systemd Service
> note you can also use these -D options also in IntelliJ for development, which is better practice then editing the file that might be accidentally committed
## To run in production mode

When running in production mode you should create your own `application.yml` file in your working directory.
An example can be found below, copy into `application.yml` file.

`
armadillo:
oidc-permission-enabled: false
docker-management-enabled: true
oidc-admin-user: <your OIDC email>
spring:
security:
user:
name: admin
password: <your admin password for basic auth default user>
oauth2:
client:
registration:
molgenis:
client-id: <your client id>
client-secret: <your client secret>
provider:
molgenis:
issuer-uri: 'https://auth.molgenis.org'
resourceserver:
jwt:
issuer-uri: 'https://auth.molgenis.org'
opaquetoken:
client-id: 'b396233b-cdb2-449e-ac5c-a0d28b38f791'
`
> Note: If don't want to configure an oauth2 client for any reason, just remove the `oauth2` section.
And then you can run:

`
java -jar molgenis-armadillo-3.*.jar \
-Dspring.profiles.active=myprofile
`

## Run as systemd Service

Armadillo 3 is tested on latest Ubuntu-LTS based servers. To run armadillo 3 as service please follow this
guide: https://github.com/molgenis/molgenis-service-armadillo/blob/master/scripts/install/README.md

## Docker images

For testing, Armadillo 3 docker images are also available as docker image. These run in 'development' profile.
For testing, Armadillo 3 docker images are also available as docker image. These run in 'basic' profile.

- release at https://hub.docker.com/r/molgenis/molgenis-armadillo
- snapshot builds from pull requests at https://hub.docker.com/r/molgenis/molgenis-armadillo-snapshot
Expand Down Expand Up @@ -132,16 +180,6 @@ For local storage, you don't need to do anything. Data is automatically stored i
in `application.yml` by changing the `storage.root-dir`
setting.

If you want to use MinIO as storage (including the test data), do the following:

1. Start the container with `docker-compose --profile minio up`
2. In your browser, go to `http://localhost:9090`
3. Log in with _molgenis_ / _molgenis_
4. Add a bucket `shared-lifecyle`
5. Copy the folders in `data/shared-lifecycle` in this repository to the bucket
6. In `application.yml`, uncomment the `minio` section.
7. Now Armadillo will automatically connect to MinIO at startup.

> **_Note_**: When you run Armadillo locally for the first time, the `lifecycle` project has not been
> added to the system metadata yet. To add it automatically, see [Application properties](#application-properties).
> Or you can add it manually:
Expand All @@ -150,35 +188,3 @@ If you want to use MinIO as storage (including the test data), do the following:
> - Add the project `lifecycle`
>
> Now you're all set!
### Application properties

You can configure the application in `application.yml`. During development however, it is more convenient to override these settings in a local .yml file that
you do not commit to git. Here's how to set that up:

- Next to `application.yml`, create a file `application-local.yml` (this file is ignored by git)
- Give it the following content:

```
armadillo:
oidc-permission-enabled: false
docker-management-enabled: true
oidc-admin-user: <your OIDC email>
spring:
security:
oauth2:
client:
registration:
molgenis:
client-id: <OIDC client ID>
client-secret: <OIDC client secret>
```

> Note: If can't configure an oauth2 client for any reason, just remove the `spring` section.
- Now, in the Run Configuration for the DatashieldServiceApplication, add the following program argument:

```--spring.config.additional-location=file:armadillo/src/main/resources/application-local.yml```

Now the lifecycle test project (including its data) will work out of the box, and you will be able to log in with your OIDC account immediately.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
Expand All @@ -31,7 +30,6 @@
@SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "JSESSIONID")
@RequestMapping("my")
@PreAuthorize("isAuthenticated()")
public class CurrentUserController {

private final OAuth2AuthorizedClientService clientService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public AuthInfoContributor(OAuth2ResourceServerProperties properties) {

@Override
public void contribute(Builder builder) {
builder.withDetail("auth", Map.of("clientId", clientId, "issuerUri", issuerUri));
if (clientId != null && issuerUri != null) {
builder.withDetail("auth", Map.of("clientId", clientId, "issuerUri", issuerUri));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;

@Profile("!test")
@Profile({"!test", "!basic"})
@Import(UserDetailsServiceAutoConfiguration.class)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
Expand All @@ -49,7 +49,41 @@ public class AuthConfig {

@Configuration
@EnableWebSecurity
@Profile({"!test"})
@Profile("basic")
@Order(0)
public static class LocalConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(
"/",
"/info",
"/index.html",
"/basic-login",
"/armadillo-logo.png",
"favicon.ico",
"/assets/**",
"/v3/**",
"/swagger-ui/**",
"/ui/**",
"/swagger-ui.html")
.permitAll()
.requestMatchers(EndpointRequest.to(InfoEndpoint.class, HealthEndpoint.class))
.permitAll()
.requestMatchers(toAnyEndpoint())
.authenticated()
.and()
.httpBasic()
.and()
.csrf()
.disable();
}
}

@Configuration
@EnableWebSecurity
@Profile({"!test", "!basic"})
@ConditionalOnProperty("spring.security.oauth2.client.registration.molgenis.client-id")
@Order(1)
// check against JWT and basic auth. You can also sign in using 'oauth2'
public static class JwtConfig extends WebSecurityConfigurerAdapter {
Expand Down Expand Up @@ -104,7 +138,7 @@ Converter<Jwt, AbstractAuthenticationToken> grantedAuthoritiesExtractor() {
@EnableWebSecurity
@Order(2)
@ConditionalOnProperty("spring.security.oauth2.client.registration.molgenis.client-id")
@Profile({"!test"})
@Profile({"!test", "!basic"})
// otherwise we gonna offer sign in
public static class Oauth2LoginConfig extends WebSecurityConfigurerAdapter {
AccessService accessService;
Expand Down Expand Up @@ -152,7 +186,7 @@ private GrantedAuthoritiesMapper userAuthoritiesMapper() {
}

/** Allow CORS requests, needed for swagger UI to work, if the development profile is active. */
@Profile("development")
@Profile({"development", "basic"})
@Bean
CorsConfigurationSource corsConfigurationSource() {
return request -> ALLOW_CORS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class JwtDecoderConfig {

private static final Logger LOG = LoggerFactory.getLogger(JwtDecoderConfig.class);

@Value("${spring.profiles.active}")
private String activeProfile;
@Value("${spring.profiles.active:default}")
private String activeProfile = "default";

@Bean
public JwtDecoder jwtDecoder(OAuth2ResourceServerProperties properties) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.molgenis.armadillo.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.oauth2.jwt.*;

// in case of test there are no oidc then we will have dummy JWT
@Configuration
@Profile("basic")
public class JwtDecoderConfigLocal {

private static final Logger LOG = LoggerFactory.getLogger(JwtDecoderConfigLocal.class);

@Bean
public JwtDecoder jwtDecoder() {
return token -> {
throw new UnsupportedOperationException("JWT dummy configuration for 'test'");
};
}
}
18 changes: 18 additions & 0 deletions armadillo/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ audit:
logging:
config: classpath:logback-file.xml

storage:
root-dir: data

---
# 'basic' profile is a configuration without oidc
# you can only sign in using basicauth 'admin' 'admin'

spring:
security:
user:
password: admin
config:
activate:
on-profile: basic

storage:
root-dir: data

---
spring:
security:
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ services:
armadillo:
image: molgenis/molgenis-armadillo-snapshot:latest
environment:
SPRING_PROFILES_ACTIVE: development
SPRING_PROFILES_ACTIVE: basic
# basic doesn't use OIDC
LOGGING_CONFIG: 'classpath:logback-file.xml'
AUDIT_LOG_PATH: '/app/logs/audit.log'
# SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: 'https://auth.molgenis.org'
Expand Down

0 comments on commit 3006e9e

Please sign in to comment.