Skip to content

Commit

Permalink
Merge branch 'feature/shibui-2393' of bitbucket.org:unicon/shib-idp-u…
Browse files Browse the repository at this point in the history
…i into feature/shibui-2393-ui
  • Loading branch information
rmathis committed Nov 17, 2022
2 parents f5ee608 + 0ae6bfb commit d8a4cb3
Show file tree
Hide file tree
Showing 30 changed files with 1,088 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import edu.internet2.tier.shibboleth.admin.ui.service.JPAFilterTargetServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolversPositionOrderContainerService;
import edu.internet2.tier.shibboleth.admin.ui.service.ShibRestTemplateDelegate;
import edu.internet2.tier.shibboleth.admin.util.AttributeUtility;
import edu.internet2.tier.shibboleth.admin.util.EntityDescriptorConversionUtils;
import edu.internet2.tier.shibboleth.admin.util.LuceneUtility;
Expand All @@ -43,12 +44,14 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
Expand All @@ -57,6 +60,7 @@
import org.springframework.web.util.UrlPathHelper;

import javax.servlet.http.HttpServletRequest;
import java.net.URL;

@Configuration
@Import(SearchConfiguration.class)
Expand Down Expand Up @@ -243,7 +247,10 @@ public IShibUiPermissionEvaluator shibUiPermissionEvaluator(EntityDescriptorRepo
}

@Bean
public DynamicRegistrationService dynamicRegistrationService(DynamicRegistrationInfoRepository driRepo, OwnershipRepository ownershipRepo, IShibUiPermissionEvaluator permissionEvaluator, UserService userService, IGroupService groupService) {
return new JPADynamicRegistrationServiceImpl(groupService, driRepo, ownershipRepo, permissionEvaluator, userService);
public DynamicRegistrationService dynamicRegistrationService(DynamicRegistrationInfoRepository driRepo, OwnershipRepository ownershipRepo, IShibUiPermissionEvaluator permissionEvaluator, UserService userService, IGroupService groupService, ShibUIConfiguration config, RestTemplateBuilder restTemplateBuilder) {
URL idpUrl = config.getShibIdpServer();
RestTemplate template = restTemplateBuilder.build();
ShibRestTemplateDelegate delegate = new ShibRestTemplateDelegate(idpUrl, template);
return new JPADynamicRegistrationServiceImpl(groupService, driRepo, ownershipRepo, delegate, permissionEvaluator, userService);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;

import java.net.URL;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -39,4 +40,9 @@ public class ShibUIConfiguration {
* A list of roles to bootstrap into the system.
*/
private Set<String> roles;

/**
* The URL of the shib idp server ala - https://idp.someschool.edu/idp
*/
private URL shibIdpServer;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.tags.Tags;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PatchMapping;
Expand Down Expand Up @@ -45,8 +46,13 @@ public class ActivateController {
@Transactional
public ResponseEntity<?> enableDynamicRegistration(@PathVariable String resourceId, @PathVariable String mode) throws PersistentEntityNotFound, ForbiddenException, UnsupportedShibUiOperationException {
if ("enable".equalsIgnoreCase(mode)) {
DynamicRegistrationRepresentation drr = dynamicRegistrationService.enableDynamicRegistration(resourceId);
return ResponseEntity.ok(drr);
HttpStatus status = dynamicRegistrationService.enableDynamicRegistration(resourceId);
switch (status) {
case OK:
case ACCEPTED: return ResponseEntity.ok("Service enabled");
case NOT_FOUND: throw new UnsupportedShibUiOperationException("Request returned NOT FOUND, please contact a system admin to check configuration");
case FORBIDDEN: throw new ForbiddenException("Request was denied with FORBIDDEN, please contact a system admin to check configuration");
}
}
throw new UnsupportedShibUiOperationException("Disable is not a valid operation for Dynamic Registrations at this time");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException;
import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException;
import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound;
import edu.internet2.tier.shibboleth.admin.ui.exception.UnsupportedShibUiOperationException;
import org.springframework.http.HttpStatus;

import java.util.List;

Expand All @@ -15,7 +17,8 @@ DynamicRegistrationRepresentation approveDynamicRegistration(String resourceId,

void delete(String resourceId) throws ForbiddenException, PersistentEntityNotFound;

DynamicRegistrationRepresentation enableDynamicRegistration(String resourceId) throws PersistentEntityNotFound, ForbiddenException;
HttpStatus enableDynamicRegistration(String resourceId)
throws PersistentEntityNotFound, ForbiddenException, UnsupportedShibUiOperationException;

List<DynamicRegistrationRepresentation> getAllDynamicRegistrationsBasedOnUserAccess() throws ForbiddenException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException;
import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException;
import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound;
import edu.internet2.tier.shibboleth.admin.ui.exception.UnsupportedShibUiOperationException;
import edu.internet2.tier.shibboleth.admin.ui.security.model.Approvers;
import edu.internet2.tier.shibboleth.admin.ui.security.model.Group;
import edu.internet2.tier.shibboleth.admin.ui.security.model.Owner;
Expand All @@ -22,6 +23,7 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
Expand All @@ -34,19 +36,21 @@
@NoArgsConstructor
public class JPADynamicRegistrationServiceImpl implements DynamicRegistrationService {
@Autowired
IGroupService groupService;
private IGroupService groupService;

@Autowired
DynamicRegistrationInfoRepository repository;
private DynamicRegistrationInfoRepository repository;

@Autowired
OwnershipRepository ownershipRepository;
private OwnershipRepository ownershipRepository;

private ShibRestTemplateDelegate shibRestTemplateDelegate;

@Autowired
private IShibUiPermissionEvaluator shibUiAuthorizationDelegate;

@Autowired
UserService userService;
private UserService userService;

@Override
public DynamicRegistrationRepresentation approveDynamicRegistration(String resourceId, boolean status) throws PersistentEntityNotFound, ForbiddenException {
Expand Down Expand Up @@ -125,16 +129,15 @@ public void delete(String resourceId) throws ForbiddenException, PersistentEntit
}

@Override
public DynamicRegistrationRepresentation enableDynamicRegistration(String resourceId) throws PersistentEntityNotFound, ForbiddenException {
public HttpStatus enableDynamicRegistration(String resourceId) throws PersistentEntityNotFound, ForbiddenException, UnsupportedShibUiOperationException {
DynamicRegistrationInfo existingDri = repository.findByResourceId(resourceId);
if (existingDri == null) {
throw new PersistentEntityNotFound(String.format("The dynamic registration with id [%s] was not found for update.", existingDri.getResourceId()));
}
if (!shibUiAuthorizationDelegate.hasPermission(userService.getCurrentUserAuthentication(), existingDri, PermissionType.enable)) {
throw new ForbiddenException("You do not have the permissions necessary to enable this service");
}
// TODO do something...
return new DynamicRegistrationRepresentation(existingDri);
return shibRestTemplateDelegate.sendRequest(existingDri);
}

private boolean entityExists(String id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package edu.internet2.tier.shibboleth.admin.ui.service;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.DynamicRegistrationInfo;
import edu.internet2.tier.shibboleth.admin.ui.exception.UnsupportedShibUiOperationException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
* Requires that the shib server url be non-null
*/
public class ShibRestTemplateDelegate {
private URL shibUrl;
private RestTemplate restTemplate;

public ShibRestTemplateDelegate(URL url, RestTemplate template) {
this.restTemplate = template;
if (url != null) {
try {
shibUrl = new URL(url.toExternalForm() + "/profile/oidc/register");
}
catch (MalformedURLException e) {
shibUrl = null;
}
}
}

public HttpStatus sendRequest(DynamicRegistrationInfo dri) throws UnsupportedShibUiOperationException {
if (shibUrl == null) {
throw new UnsupportedShibUiOperationException("Dynamic Registration endpoint not configured properly, please contact your system admin.");
}
try {
ResponseEntity response = restTemplate.postForEntity(shibUrl.toURI(), convertDynamicReg(dri), Map.class);
return response.getStatusCode();
}
catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

private Object convertDynamicReg(DynamicRegistrationInfo dri) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // skip any null values

Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("redirect_uris", dri.getRedirectUris());
valuesMap.put("response_types", dri.getResponseTypes());
valuesMap.put("grant_types", dri.getGrantType().name());
valuesMap.put("application_type", dri.getApplicationType());
valuesMap.put("contacts", dri.getContacts());
valuesMap.put("subject_type", dri.getSubjectType());
valuesMap.put("jwks", dri.getJwks());
valuesMap.put("token_endpoint_auth_method", dri.getTokenEndpointAuthMethod());
valuesMap.put("logo_uri", dri.getLogoUri());
valuesMap.put("policy_uri", dri.getPolicyUri());
valuesMap.put("tos_uri", dri.getTosUri());
valuesMap.put("scope", dri.getScope());

String json;
try {
json = mapper.writeValueAsString(valuesMap);
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return new HttpEntity<String>(json, headers);
}
}
25 changes: 18 additions & 7 deletions backend/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ custom:
helpText: tooltip.ignore-request-signatures
attributeName: http://shibboleth.net/ns/profiles/ignoreRequestSignatures
attributeFriendlyName: ignoreRequestSignatures
- name: postAuthenticationFlows
attributeFriendlyName: postAuthenticationFlows
displayName: label.postAuthenticationFlows
helpText: tooltip.postAuthenticationFlows
displayType: selection_list
defaultValues:
- attribute-release
- expiring-password
- terms-of-use
attributeName: http://shibboleth.net/ns/profiles/postAuthenticationFlows"
protocol: saml,oidc
- name: inboundInterceptorFlows
attributeFriendlyName: inboundInterceptorFlows
displayName: label.inboundInterceptorFlows
Expand All @@ -189,13 +200,13 @@ custom:
defaultValue: client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt
attributeName: http://shibboleth.net/ns/profiles/tokenEndpointAuthMethods
protocol: oidc
- name: postAuthenticationFlows
attributeFriendlyName: postAuthenticationFlows
displayName: label.postAuthenticationFlows
helpText: tooltip.postAuthenticationFlows
displayType: string
attributeName: http://shibboleth.net/ns/profiles/postAuthenticationFlows
protocol: oidc
# - name: postAuthenticationFlows
# attributeFriendlyName: postAuthenticationFlows
# displayName: label.postAuthenticationFlows
# helpText: tooltip.postAuthenticationFlows
# displayType: string
# attributeName: http://shibboleth.net/ns/profiles/postAuthenticationFlows
# protocol: oidc
- name: proxyCount
attributeFriendlyName: proxyCount
displayName: label.proxyCount
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import spock.lang.Specification
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.JsonSchemaLocationBuilder
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ALGORITHM_FILTER
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.DYNAMIC_REGISTRATION
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER
Expand Down Expand Up @@ -100,7 +101,12 @@ class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Speci
.jacksonMapper(jacksonMapper)
.detectMalformedJson(false)
.build())

.register(DYNAMIC_REGISTRATION, JsonSchemaLocationBuilder.with()
.jsonSchemaLocation('classpath:dynamic-registration.schema.json')
.resourceLoader(resourceLoader)
.jacksonMapper(jacksonMapper)
.detectMalformedJson(false)
.build())
}
}
}
2 changes: 1 addition & 1 deletion testbed/authentication/shibboleth-idp/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM tier/shib-idp:4.0.0_20200518
FROM i2incommon/shib-idp:4.2.1_20220624

# The build args below can be used at build-time to tell the build process where to find your config files. This is for a completely burned-in config.
ARG TOMCFG=config/tomcat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<ref bean="SAML1.AttributeQuery" />
<ref bean="SAML1.ArtifactResolution" />
-->
<bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" />
<ref bean="SAML2.SSO" />
<ref bean="SAML2.ECP" />
<ref bean="SAML2.Logout" />
<!--
Expand Down
4 changes: 4 additions & 0 deletions testbed/integration/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ services:
depends_on:
- directory
- reverse-proxy
- database
networks:
- reverse-proxy
- idp
- backend
volumes:
- ../directory/certs/ca.crt:/opt/shibboleth-idp/credentials/ldap-server.crt
- dynamic_metadata:/opt/shibboleth-idp/metadata/dynamic
Expand Down Expand Up @@ -86,6 +88,8 @@ services:
- backend
volumes:
- database_data:/var/lib/postgresql/data
- ./shibboleth-idp/db/oidc_dynreg.sql:/docker-entrypoint-initdb.d/oidc_dynreg.sql

networks:
reverse-proxy:
idp:
Expand Down
18 changes: 16 additions & 2 deletions testbed/integration/shibboleth-idp/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM i2incommon/shib-idp:4.1.4_20210802
FROM i2incommon/shib-idp:4.2.1_20220624

# The build args below can be used at build-time to tell the build process where to find your config files. This is for a completely burned-in config.
ARG TOMCFG=config/tomcat
Expand All @@ -10,16 +10,30 @@ ARG SHBVIEWS=config/shib-idp/views
ARG SHBEDWAPP=config/shib-idp/edit-webapp
ARG SHBMSGS=config/shib-idp/messages
ARG SHBMD=config/shib-idp/metadata
ARG OIDCREG=config/shib-idp/static
ARG TOMREWRITE=config/tomcat/rewrite.config

#enable OIDC plugins and generate needed keys
ADD ${SHBCREDS} /opt/shibboleth-idp/credentials
RUN /opt/shibboleth-idp/bin/plugin.sh -i https://shibboleth.net/downloads/identity-provider/plugins/oidc-common/2.1.0/oidc-common-dist-2.1.0.tar.gz --noPrompt
RUN /opt/shibboleth-idp/bin/plugin.sh -i https://shibboleth.net/downloads/identity-provider/plugins/oidc-op/3.2.1/idp-plugin-oidc-op-distribution-3.2.1.tar.gz --noPrompt
RUN /opt/shibboleth-idp/bin/module.sh -e idp.authn.RemoteUserInternal
RUN /opt/shibboleth-idp/bin/jwtgen.sh -t RSA -s 2048 -u sig -i defaultRSASign | tail -n +2 > /opt/shibboleth-idp/credentials/idp-signing-rs.jwk
RUN /opt/shibboleth-idp/bin/jwtgen.sh -t EC -c P-256 -u sig -i defaultECSign | tail -n +2 > /opt/shibboleth-idp/credentials/idp-signing-es.jwk
RUN /opt/shibboleth-idp/bin/jwtgen.sh -t RSA -s 2048 -u enc -i defaultRSAEnc | tail -n +2 > /opt/shibboleth-idp/credentials/idp-encryption-rsa.jwk
ADD https://jdbc.postgresql.org/download/postgresql-42.5.0.jar /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/
ADD https://repo1.maven.org/maven2/com/zaxxer/HikariCP/5.0.1/HikariCP-5.0.1.jar /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/

# copy in the needed config files
ADD ${TOMCFG} /usr/local/tomcat/conf
ADD ${TOMCERT} /opt/certs
ADD ${TOMWWWROOT} /usr/local/tomcat/webapps/ROOT
ADD ${SHBCFG} /opt/shibboleth-idp/conf
ADD ${SHBCREDS} /opt/shibboleth-idp/credentials
#ADD ${SHBVIEWS} /opt/shibboleth-idp/views
#ADD ${SHBEDWAPP} /opt/shibboleth-idp/edit-webapp
#ADD ${SHBMSGS} /opt/shibboleth-idp/messages
ADD ${SHBMD} /opt/shibboleth-idp/metadata
ADD ${OIDCREG} /opt/shibboleth-idp/static
ADD ${TOMREWRITE} /usr/local/tomcat/conf/Catalina/localhost/rewrite.config

EXPOSE 8080
Loading

0 comments on commit d8a4cb3

Please sign in to comment.