diff options
author | Martin Stockhammer <martin_s@apache.org> | 2021-01-03 20:28:00 +0100 |
---|---|---|
committer | Martin Stockhammer <martin_s@apache.org> | 2021-01-03 20:28:00 +0100 |
commit | 43a005da1c38b175729f62426bf4a50a2d9076a6 (patch) | |
tree | d77c154baaf6736e0c6db2dfcee79dbcdb40bb30 /archiva-modules/archiva-web/archiva-rest/archiva-rest-services | |
parent | 8bd27b8851f6f917b7725380ddb93d9b88fa09f2 (diff) | |
download | archiva-43a005da1c38b175729f62426bf4a50a2d9076a6.tar.gz archiva-43a005da1c38b175729f62426bf4a50a2d9076a6.zip |
Implementing security config REST v2 methods
Diffstat (limited to 'archiva-modules/archiva-web/archiva-rest/archiva-rest-services')
7 files changed, 264 insertions, 9 deletions
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml index 2183737cd..3b5f3891d 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml @@ -381,8 +381,12 @@ </dependency> <dependency> <groupId>org.apache.archiva.redback</groupId> + <artifactId>redback-rbac-ldap</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.archiva.redback</groupId> <artifactId>redback-rbac-jpa</artifactId> - <version>${redback.version}</version> <scope>test</scope> </dependency> <dependency> diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java index db580338d..b9b504c85 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java @@ -21,6 +21,11 @@ import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration; import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin; import org.apache.archiva.components.rest.model.PagedResult; import org.apache.archiva.components.rest.model.PropertyEntry; +import org.apache.archiva.components.rest.util.PagingHelper; +import org.apache.archiva.components.rest.util.QueryHelper; +import org.apache.archiva.redback.rbac.RBACManager; +import org.apache.archiva.redback.users.UserManager; +import org.apache.archiva.rest.api.model.UserManagerImplementationInformation; import org.apache.archiva.rest.api.model.v2.BeanInformation; import org.apache.archiva.rest.api.model.v2.CacheConfiguration; import org.apache.archiva.rest.api.model.v2.LdapConfiguration; @@ -28,33 +33,66 @@ import org.apache.archiva.rest.api.model.v2.SecurityConfiguration; import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; import org.apache.archiva.rest.api.services.v2.ErrorMessage; import org.apache.archiva.rest.api.services.v2.SecurityConfigurationService; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import javax.inject.Inject; +import javax.management.Query; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.ResourceBundle; +import java.util.function.Predicate; +import java.util.stream.Collectors; import static org.apache.archiva.rest.services.v2.ErrorKeys.REPOSITORY_ADMIN_ERROR; /** * @author Martin Stockhammer <martin_s@apache.org> */ -@Service("v2.defaultSecurityConfigurationService") +@Service( "v2.defaultSecurityConfigurationService" ) public class DefaultSecurityConfigurationService implements SecurityConfigurationService { private static final Logger log = LoggerFactory.getLogger( DefaultSecurityConfigurationService.class ); + private static final QueryHelper<PropertyEntry> PROP_QUERY_HELPER = new QueryHelper( new String[]{"key"} ); + private static final PagingHelper PROP_PAGING_HELPER = new PagingHelper( ); + static { + PROP_QUERY_HELPER.addStringFilter( "key", PropertyEntry::getKey ); + PROP_QUERY_HELPER.addStringFilter( "value", PropertyEntry::getValue ); + PROP_QUERY_HELPER.addNullsafeFieldComparator( "key", PropertyEntry::getKey ); + PROP_QUERY_HELPER.addNullsafeFieldComparator( "value", PropertyEntry::getValue ); + + } + + private ResourceBundle bundle; + + @Inject private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin; + @Inject + private ApplicationContext applicationContext; + + @PostConstruct + void init() { + bundle = ResourceBundle.getBundle( "org.apache.archiva.rest.RestBundle" ); + } + @Override public SecurityConfiguration getConfiguration( ) throws ArchivaRestServiceException { try { RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration(); + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); @@ -69,30 +107,109 @@ public class DefaultSecurityConfigurationService implements SecurityConfiguratio @Override public PagedResult<PropertyEntry> getConfigurationProperties( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException { - return null; + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + boolean ascending = PROP_QUERY_HELPER.isAscending( order ); + Predicate<PropertyEntry> filter = PROP_QUERY_HELPER.getQueryFilter( searchTerm ); + Comparator<PropertyEntry> comparator = PROP_QUERY_HELPER.getComparator( orderBy, ascending ); + Map<String, String> props = redbackRuntimeConfiguration.getConfigurationProperties( ); + int totalCount = props.size( ); + List<PropertyEntry> result = props.entrySet( ).stream( ).map( + entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) ) + ).filter( filter ) + .sorted( comparator ) + .skip( offset ).limit( limit ) + .collect( Collectors.toList( ) ); + return new PagedResult<>( totalCount, offset, limit, result ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } } @Override public LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException { - return null; + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + return LdapConfiguration.of( redbackRuntimeConfiguration.getLdapConfiguration() ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + } @Override public CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException { - return null; + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + return CacheConfiguration.of( redbackRuntimeConfiguration.getUsersCacheConfiguration() ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + } @Override public List<BeanInformation> getAvailableUserManagers( ) throws ArchivaRestServiceException { - return null; + Map<String, UserManager> beans = applicationContext.getBeansOfType( UserManager.class ); + + if ( beans.isEmpty() ) + { + return Collections.emptyList(); + } + + return beans.entrySet( ).stream( ) + .filter( entry -> entry.getValue().isFinalImplementation() ) + .map( (Map.Entry<String, UserManager> entry) -> { + UserManager um = entry.getValue( ); + String id = StringUtils.substringAfter( entry.getKey( ), "#" ); + String displayName = bundle.getString( "user_manager." + id + ".display_name" ); + String description = bundle.getString( "user_manager." + id + ".description" ); + return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, um.getDescriptionKey( ), description, um.isReadOnly( ) ); + } ).collect( Collectors.toList()); } @Override public List<BeanInformation> getAvailableRbacManagers( ) throws ArchivaRestServiceException { - return null; + Map<String, RBACManager> beans = applicationContext.getBeansOfType( RBACManager.class ); + + if ( beans.isEmpty() ) + { + return Collections.emptyList(); + } + + return beans.entrySet( ).stream( ) + .filter( entry -> entry.getValue().isFinalImplementation() ) + .map( (Map.Entry<String, RBACManager> entry) -> { + RBACManager rm = entry.getValue( ); + String id = StringUtils.substringAfter( entry.getKey( ), "#" ); + String displayName = bundle.getString( "rbac_manager." + id + ".display_name" ); + String description = bundle.getString( "rbac_manager." + id + ".description" ); + return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, rm.getDescriptionKey( ), description, rm.isReadOnly( ) ); + } ).collect( Collectors.toList()); } } diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle.properties b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle.properties new file mode 100644 index 000000000..d93435a4c --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle.properties @@ -0,0 +1,26 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +user_manager.ldap.display_name=LDAP User Manager +user_manager.ldap.description=User Manager that connects to LDAP server. +user_manager.jpa.display_name=Database User Manager +user_manager.jpa.description=User Manager that persists the user entries in a database. +rbac_manager.ldap.display_name=LDAP RBAC Manager +rbac_manager.ldap.description=RBAC Manager that connects to LDAP server. +rbac_manager.jpa.display_name=Database RBAC Manager +rbac_manager.jpa.description=RBAC Manager that persists the role entries in a database. diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_de.properties b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_de.properties new file mode 100644 index 000000000..10c3e2db3 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_de.properties @@ -0,0 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +user_manager.ldap.display_name=LDAP User Manager +user_manager.ldap.description=User Manager that connects to LDAP server. +user_manager.jpa.display_name=Database User Manager +user_manager.jpa.description=User Manager that persists the user entries in a database. diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_en.properties b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_en.properties new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_en.properties diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_fr.properties b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_fr.properties new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/org/apache/archiva/rest/RestBundle_fr.properties diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java index eff49c12c..610743f5b 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java @@ -19,6 +19,9 @@ package org.apache.archiva.rest.services.v2; */ import io.restassured.response.Response; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.model.PropertyEntry; +import org.apache.archiva.rest.api.model.v2.BeanInformation; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -31,6 +34,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import java.util.List; + import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; import static org.junit.jupiter.api.Assertions.*; @@ -68,7 +73,6 @@ public class NativeSecurityConfigurationServiceTest extends AbstractNativeRestSe Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) .when( ) .get( "config" ) - .prettyPeek() .then( ).statusCode( 200 ).extract( ).response( ); assertNotNull( response ); assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_user_managers[0]" ) ); @@ -79,4 +83,86 @@ public class NativeSecurityConfigurationServiceTest extends AbstractNativeRestSe assertFalse( response.getBody( ).jsonPath( ).getBoolean( "ldap_active" ) ); } + @Test + void testGetConfigurationProperties() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/properties" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult<PropertyEntry> result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + List<PropertyEntry> propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class ); + assertEquals( 10, result.getPagination( ).getLimit( ) ); + assertEquals( 0, result.getPagination( ).getOffset( ) ); + assertEquals( 47, result.getPagination( ).getTotalCount( ) ); + assertEquals( "authentication.jwt.keystoreType", propList.get( 0 ).getKey() ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .queryParam( "offset", "3" ) + .queryParam( "limit", "5" ) + .get( "config/properties" ) + .then( ).statusCode( 200 ).extract( ).response( ); + + assertNotNull( response ); + result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 5, result.getPagination( ).getLimit( ) ); + assertEquals( 47, result.getPagination( ).getTotalCount( ) ); + propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class ); + assertEquals( "authentication.jwt.refreshLifetimeMs", propList.get( 0 ).getKey() ); + } + + @Test + void testGetLdapConfiguration() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/ldap" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( "", response.getBody( ).jsonPath( ).get( "host_name" ) ); + assertEquals( 13, response.getBody( ).jsonPath( ).getMap( "properties" ).size( ) ); + } + + @Test + void testGetCacheConfiguration() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/cache" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + } + + @Test + void testGetUserManagers() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "user_managers" ) + .prettyPeek() + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List<BeanInformation> usrList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class ); + assertEquals( 2, usrList.size( ) ); + assertTrue( usrList.stream( ).anyMatch( bi -> "LDAP User Manager".equals( bi.getDisplayName( ) ) ) ); + assertTrue( usrList.stream( ).anyMatch( bi -> "Database User Manager".equals( bi.getDisplayName( ) ) ) ); + } + + @Test + void testGetRbacManagers() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "rbac_managers" ) + .prettyPeek() + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List<BeanInformation> rbacList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class ); + assertEquals( 2, rbacList.size( ) ); + assertTrue( rbacList.stream( ).anyMatch( bi -> "Database RBAC Manager".equals( bi.getDisplayName( ) ) ) ); + assertTrue( rbacList.stream( ).anyMatch( bi -> "LDAP RBAC Manager".equals( bi.getDisplayName( ) ) ) ); + } + } |