Skip to content

Commit

Permalink
Merged develop into bugfix/SHIBUI-2352
Browse files Browse the repository at this point in the history
  • Loading branch information
chasegawa committed Aug 30, 2022
2 parents acb1a0f + 313b466 commit 6e456f1
Show file tree
Hide file tree
Showing 22 changed files with 668 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public class Version implements Serializable {

private String creator;

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
private ZonedDateTime date;

private static final long serialVersionUID = 3429591830989243421L;

}
}
1 change: 1 addition & 0 deletions backend/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
# identityProviderMetadataPath: "/etc/shibui/idp-metadata.xml"
# forceServiceProviderMetadataGeneration: false
# callbackUrl: "https://localhost:8443/callback"
# postLogoutURL: "https://idp.example.com/idp/profile/Logout" # Must set this to get IDP logout
# maximumAuthenticationLifetime: 3600000
# requireAssertedRoleForNewUsers: false
# saml2ProfileMapping:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class VersionJsonSerializationBasicTests extends Specification {
{
"id": "2",
"creator": "kramer",
"date": "2019-05-20T15:00:00.574Z"
"date": "2019-05-20T15:00:00.574000"
}
"""
def expectedJsonMap = jsonSlurper.parseText(expectedJson)
Expand All @@ -40,4 +40,4 @@ class VersionJsonSerializationBasicTests extends Specification {
deSerializedJsonMap.id == expectedJsonMap.id
deSerializedJsonMap.creator == expectedJsonMap.creator
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import net.unicon.shibui.pac4j.authenticator.ShibuiSAML2Authenticator;
import org.pac4j.core.client.Clients;
import org.pac4j.core.config.Config;
import org.pac4j.core.engine.LogoutLogic;
import org.pac4j.core.matching.matcher.PathMatcher;
import org.pac4j.core.profile.definition.CommonProfileDefinition;
import org.pac4j.http.client.direct.HeaderClient;
Expand Down Expand Up @@ -69,32 +70,39 @@ public Config config(final Pac4jConfigurationProperties pac4jConfigProps,
case "SAML2":
default:
log.info("**** Configuring PAC4J SAML2");
final SAML2Configuration saml2Config = new SAML2Configuration();
saml2Config.setKeystorePath(pac4jConfigProps.getKeystorePath());
saml2Config.setKeystorePassword(pac4jConfigProps.getKeystorePassword());
saml2Config.setPrivateKeyPassword(pac4jConfigProps.getPrivateKeyPassword());
saml2Config.setIdentityProviderMetadataPath(pac4jConfigProps.getIdentityProviderMetadataPath());
saml2Config.setMaximumAuthenticationLifetime(pac4jConfigProps.getMaximumAuthenticationLifetime());
saml2Config.setServiceProviderEntityId(pac4jConfigProps.getServiceProviderEntityId());
saml2Config.setServiceProviderMetadataPath(pac4jConfigProps.getServiceProviderMetadataPath());
saml2Config.setForceServiceProviderMetadataGeneration(pac4jConfigProps.isForceServiceProviderMetadataGeneration());
saml2Config.setWantsAssertionsSigned(pac4jConfigProps.isWantAssertionsSigned());
saml2Config.setAttributeAsId(pac4jConfigProps.getSimpleProfileMapping().getUsername());
final SAML2Configuration saml2Config = buildSaml2ConfigFromPac4JConfiguration(pac4jConfigProps);


final SAML2Client saml2Client = new SAML2Client(saml2Config);
saml2Client.setName(PAC4J_CLIENT_NAME);
saml2Client.addAuthorizationGenerator(saml2ModelAuthorizationGenerator);
SAML2Authenticator saml2Authenticator = new ShibuiSAML2Authenticator(saml2Config.getAttributeAsId(), saml2Config.getMappedAttributes(), userService);
saml2Authenticator.setProfileDefinition(new CommonProfileDefinition(p -> new BetterSAML2Profile(pac4jConfigProps.getSimpleProfileMapping())));
saml2Client.setAuthenticator(saml2Authenticator);

saml2Client.setName(PAC4J_CLIENT_NAME);
clients.setClients(saml2Client);
break;
}
config.setClients(clients);
return config;
}


private SAML2Configuration buildSaml2ConfigFromPac4JConfiguration(Pac4jConfigurationProperties pac4jConfigProps) {
SAML2Configuration saml2Config = new SAML2Configuration();
saml2Config.setKeystorePath(pac4jConfigProps.getKeystorePath());
saml2Config.setKeystorePassword(pac4jConfigProps.getKeystorePassword());
saml2Config.setPrivateKeyPassword(pac4jConfigProps.getPrivateKeyPassword());
saml2Config.setIdentityProviderMetadataPath(pac4jConfigProps.getIdentityProviderMetadataPath());
saml2Config.setMaximumAuthenticationLifetime(pac4jConfigProps.getMaximumAuthenticationLifetime());
saml2Config.setServiceProviderEntityId(pac4jConfigProps.getServiceProviderEntityId());
saml2Config.setServiceProviderMetadataPath(pac4jConfigProps.getServiceProviderMetadataPath());
saml2Config.setForceServiceProviderMetadataGeneration(pac4jConfigProps.isForceServiceProviderMetadataGeneration());
saml2Config.setWantsAssertionsSigned(pac4jConfigProps.isWantAssertionsSigned());
saml2Config.setAttributeAsId(pac4jConfigProps.getSimpleProfileMapping().getUsername());
saml2Config.setPostLogoutURL(pac4jConfigProps.getPostLogoutURL());
return saml2Config;
}

@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return this::registerErrorPages;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Pac4jConfigurationProperties {
private String serviceProviderEntityId = "https://unicon.net/shibui";
private String serviceProviderMetadataPath = "/tmp/sp-metadata.xml";
private String typeOfAuth = "SAML2";
private String postLogoutURL;

private boolean wantAssertionsSigned = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import edu.internet2.tier.shibboleth.admin.ui.security.service.IRolesService;
import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService;
import edu.internet2.tier.shibboleth.admin.ui.service.EmailService;
import org.jadira.usertype.spi.utils.lang.StringUtils;
import org.pac4j.core.authorization.authorizer.DefaultAuthorizers;
import org.pac4j.core.config.Config;
import org.pac4j.core.matching.matcher.Matcher;
import org.pac4j.springframework.security.web.CallbackFilter;
import org.pac4j.springframework.security.web.LogoutFilter;
import org.pac4j.springframework.security.web.SecurityFilter;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
Expand Down Expand Up @@ -64,12 +66,23 @@ public Pac4jWebSecurityConfigurerAdapter(final Config config, UserService userSe
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/unsecured/**/*").permitAll();

// adding the authorizor bypasses the default behavior of checking CSRF in Pac4J's default securitylogic+defaultauthorizationchecker
// adding the authorizer bypasses the default behavior of checking CSRF in Pac4J's default securitylogic+defaultauthorizationchecker
final SecurityFilter securityFilter = new SecurityFilter(this.config, PAC4J_CLIENT_NAME, DefaultAuthorizers.IS_AUTHENTICATED);

// add filter based on auth type
http.antMatcher("/**").addFilterBefore(getFilter(config, pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class);
// If the post logout URL is configured, setup the logout filter
if (StringUtils.isNotEmpty(pac4jConfigurationProperties.getPostLogoutURL())){
final LogoutFilter logoutFilter = new LogoutFilter(config);
logoutFilter.setLocalLogout(Boolean.TRUE);
logoutFilter.setSuffix("login"); // "logout" is redirected before we ever hit the filters - sent to /login?logout
logoutFilter.setCentralLogout(Boolean.TRUE);
logoutFilter.setDefaultUrl(pac4jConfigurationProperties.getPostLogoutURL());
http.antMatcher("/**").addFilterBefore(logoutFilter, BasicAuthenticationFilter.class);
}

// add filters
http.antMatcher("/**").addFilterBefore(getFilter(pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class);
http.antMatcher("/**").addFilterBefore(securityFilter, BasicAuthenticationFilter.class);

// add the new user filter
http.addFilterAfter(new AddNewUserFilter(pac4jConfigurationProperties, userService, rolesService, getPathMatcher("exclude-paths-matcher"), groupService, emailService), SecurityFilter.class);

Expand All @@ -84,7 +97,7 @@ private Matcher getPathMatcher(String name) {
return config.getMatchers().get(name);
}

private Filter getFilter(Config config2, String typeOfAuth) {
private Filter getFilter(String typeOfAuth) {
switch (typeOfAuth) {
case "SAML2":
return new CallbackFilter(this.config);
Expand Down
1 change: 1 addition & 0 deletions testbed/authentication/shibui/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ shibui:
forceServiceProviderMetadataGeneration: true
callbackUrl: "https://shibui.unicon.local/callback"
maximumAuthenticationLifetime: 3600000
postLogoutURL: "https://idp.unicon.local/idp/profile/Logout"
simpleProfileMapping:
username: urn:oid:0.9.2342.19200300.100.1.1
firstName: urn:oid:2.5.4.42
Expand Down
110 changes: 110 additions & 0 deletions testbed/smoke-test/cheat.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<html>
<body>
<h2>Reload Service</h2>
<form action="https://idp.unicon.local/idp/profile/admin/reload-service" target="_blank" method="get">
<label for="id">id</label>
<select name="id" id="id">
<option value="shibboleth.LoggingService">LoggingService</option>
<option value="shibboleth.AttributeFilterService">AttributeFilterService</option>
<option value="shibboleth.AttributeResolverService">AttributeResolverService</option>
<option value="shibboleth.AttributeRegistryService">AttributeRegistryService</option>
<option value="shibboleth.NameIdentifierGenerationService">NameIdentifierGenerationService</option>
<option value="shibboleth.RelyingPartyResolverService">RelyingPartyResolverService</option>
<option value="shibboleth.MetadataResolverService">MetadataResolverService</option>
<option value="shibboleth.ReloadableAccessControlService">ReloadableAccessControlService</option>
<option value="shibboleth.ReloadableCASServiceRegistry">ReloadableCASServiceRegistry</option>
</select>
<input type="submit" />
</form>
<h2>Attribute Resolution</h2>
<form action="https://idp.unicon.local/idp/profile/admin/resolvertest" target="_blank" method="get">
<table>
<tr>
<td>
<label for="requester">Requester</label>
</td>
<td>
<input name="requester" id="requester" type="text" />
</td>
</tr>
<tr>
<td>
<label for="principal">Principal</label>
</td>
<td>
<input name="principal" id="principal" type="text" />
</td>
</tr>
<tr>
<td>
<label for="acsIndex">acs index</label>
</td>
<td>
<input name="acsIndex" id="acsIndex" type="number" />
</td>
</tr>
<tr>
<td>
<label for="saml1">SAML1</label>
</td>
<td>
<input name="saml1" id="saml1" type="checkbox" />
</td>
</tr>
<tr>
<td>
<label for="saml2">SAML2</label>
</td>
<td>
<input name="saml2" id="saml2" type="checkbox" />
</td>
</tr>
</table>
<input type="submit" />

</form>
<form action="https://idp.unicon.local/idp/profile/admin/mdquery" target="_blank" method="get">
<h2>Metadata Query</h2>
<table>
<tr>
<td>
<label for="entityID">Entity ID</label>
</td>
<td>
<input name="entityID" id="entityID" type="text" />
</td>
</tr>
</table>
<input type="submit" />
</form>
<form action="https://idp.unicon.local/idp/profile/admin/reload-metadata" target="_blank" method="get">
<h2>Reload Metadata</h2>
<table>
<tr>
<td>
<label for="id">provider id</label>
</td>
<td>
<input name="id" id="provider" type="text" />
</td>
</tr>
</table>
<input type="submit" />
</form>
<form action="https://idp.unicon.local/idp/profile/SAML2/Unsolicited/SSO" target="_blank" method="get">
<h2>Unsolicited SSO</h2>
<table>
<tr>
<td>
<label for="providerId">provider id</label>
</td>
<td>
<input name="providerId" type="text" />
</td>
</tr>
</table>
<input type="submit" />
</form>
<a href="https://idp.unicon.local/idp/profile/admin/metrics" target="_blank">metrics</a>
</body>
</html>
13 changes: 13 additions & 0 deletions testbed/smoke-test/db_configs/mariadb.application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
spring:
profiles:
include:
datasource:
platform: mysql
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://database:3306/shibui
username: shibui
password: shibui
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MariaDB103Dialect
19 changes: 19 additions & 0 deletions testbed/smoke-test/db_configs/mariadb.docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
services:
database:
image: mariadb
environment:
MYSQL_DATABASE: shibui
MYSQL_USER: shibui
MYSQL_PASSWORD: shibui
MYSQL_ROOT_PASSWORD: root
healthcheck:
test: mysql -u shibui --password=shibui shibui -e "select 1"
interval: 5s
retries: 5
start_period: 5s
timeout: 10s
shib-idp-ui:
depends_on:
database:
condition: service_healthy

13 changes: 13 additions & 0 deletions testbed/smoke-test/db_configs/mysql.application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
spring:
profiles:
include:
datasource:
platform: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://database:3306/shibui
username: shibui
password: shibui
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
19 changes: 19 additions & 0 deletions testbed/smoke-test/db_configs/mysql.docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
services:
database:
image: mysql
environment:
MYSQL_DATABASE: shibui
MYSQL_USER: shibui
MYSQL_PASSWORD: shibui
MYSQL_ROOT_PASSWORD: root
healthcheck:
test: mysql -u shibui --password=shibui shibui -e "select 1"
interval: 5s
retries: 5
start_period: 5s
timeout: 10s
shib-idp-ui:
depends_on:
database:
condition: service_healthy

13 changes: 13 additions & 0 deletions testbed/smoke-test/db_configs/postgres.application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
spring:
profiles:
include:
datasource:
platform: postgres
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://database:5432/shibui
username: shibui
password: shibui
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
13 changes: 13 additions & 0 deletions testbed/smoke-test/db_configs/sqlServer.application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
spring:
profiles:
include:
datasource:
platform: sqlserver
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://database:1433
username: sa
password: Password1
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.SQLServerDialect
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
database:
build:
context: ../sqlServer
dockerfile: ../sqlServer/docker/Dockerfile
image: smoke-test_database
# healthcheck:
# test: mysql -u shibui --password=shibui shibui -e "select 1"
# interval: 5s
# retries: 5
# start_period: 5s
# timeout: 10s
# shib-idp-ui:
# depends_on:
# database:
# condition: service_healthy

Loading

0 comments on commit 6e456f1

Please sign in to comment.