#539 - Add spring-data-geode-examples module.
This commit is contained in:
committed by
Mark Paluch
parent
08dce4f0f3
commit
fa0021cffb
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security;
|
||||
|
||||
/**
|
||||
* The [Constants] class contains properties and other constants used in the Apache Geode Integrated Security
|
||||
* framework.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String SECURITY_PASSWORD_PROPERTY = "security-password";
|
||||
public static final String SECURITY_USERNAME_PROPERTY = "security-username";
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A customer used for Lucene examples.
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
@Region(name = "Customers")
|
||||
public class Customer implements Serializable {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private EmailAddress emailAddress;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
public Customer(Long id, EmailAddress emailAddress, String firstName, String lastName) {
|
||||
this.id = id;
|
||||
this.emailAddress = emailAddress;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Value object to represent email addresses.
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
public class EmailAddress implements Serializable {
|
||||
private String value;
|
||||
|
||||
public EmailAddress(String value) {
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
122
geode/security/src/main/java/example/springdata/geode/client/security/Role.java
Executable file
122
geode/security/src/main/java/example/springdata/geode/client/security/Role.java
Executable file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.cp.elements.lang.Identifiable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The [Role] class is an Abstract Data Type (ADT) modeling a role of a user (e.g. Admin).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see Serializable
|
||||
* @see Comparable
|
||||
* @see Iterable
|
||||
* @see ResourcePermission
|
||||
* @see org.cp.elements.lang.Identifiable
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
public class Role implements Comparable<Role>, Identifiable<String>, Iterable<ResourcePermission>, Serializable {
|
||||
|
||||
private String name;
|
||||
private HashSet<ResourcePermission> permissions = new HashSet<>();
|
||||
|
||||
public Role(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(String id) {
|
||||
throw new UnsupportedOperationException("Operation Not Supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Role other) {
|
||||
return name.compareTo(other.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this [Role] has been assigned (granted) the given [permission][ResourcePermission].
|
||||
*
|
||||
* @param permission [ResourcePermission] to evaluate.
|
||||
* @return a boolean value indicating whether this [Role] has been assigned (granted)
|
||||
* the given [permission][ResourcePermission].
|
||||
* @see ResourcePermission
|
||||
*/
|
||||
public boolean hasPermission(ResourcePermission permission) {
|
||||
return this.permissions.contains(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Iterator<ResourcePermission> iterator() {
|
||||
return this.permissions.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds (assigns/grants) all given [persmissions][ResourcePermission] to this [Role].
|
||||
*
|
||||
* @param permissions [ResourcePermission]s to assign/grant to this [Role].
|
||||
* @return this [Role].
|
||||
* @see ResourcePermission
|
||||
*/
|
||||
public Role withPermissions(ResourcePermission... permissions) {
|
||||
this.permissions.addAll((Arrays.asList(permissions)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds (assigns/grants) all given [persmissions][ResourcePermission] to this [Role].
|
||||
*
|
||||
* @param permissions [ResourcePermission]s to assign/grant to this [Role].
|
||||
* @return this [Role].
|
||||
* @see ResourcePermission
|
||||
*/
|
||||
public Role withPersmissions(Iterable<ResourcePermission> permissions) {
|
||||
this.permissions.addAll((Collection<? extends ResourcePermission>) permissions);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new instance of [Role] initialized with the given name.
|
||||
*
|
||||
* @param name [String] indicating the name of the new [Role].
|
||||
* @return a new [Role] initialized with the given name.
|
||||
* @see Role
|
||||
*/
|
||||
public static Role newRole(String name) {
|
||||
return new Role(name);
|
||||
}
|
||||
}
|
||||
144
geode/security/src/main/java/example/springdata/geode/client/security/User.java
Executable file
144
geode/security/src/main/java/example/springdata/geode/client/security/User.java
Executable file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.cp.elements.lang.Identifiable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class User implements Comparable<User>, Cloneable, Principal, Serializable, Iterable<Role>, Identifiable<String> {
|
||||
|
||||
private String name;
|
||||
private List<Role> roles;
|
||||
|
||||
private String credentials = null;
|
||||
|
||||
public User(String name, List<Role> roles) {
|
||||
this.name = name;
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public User(String name) {
|
||||
this(name, new ArrayList<Role>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(String id) {
|
||||
throw new UnsupportedOperationException("Operation Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Role> iterator() {
|
||||
return roles.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object clone() {
|
||||
return newUser(name).withCredentials(credentials).withRoles(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(User other) {
|
||||
return this.getName().compareTo(other.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this [User] has been granted (assigned) the given [permission][ResourcePermission].
|
||||
*
|
||||
* @param permission [ResourcePermission] to evalute.
|
||||
* @return a boolean value indicating whether this [User] has been granted (assigned)
|
||||
* the given [ResourcePermission].
|
||||
* @see ResourcePermission
|
||||
*/
|
||||
public boolean hasPermission(ResourcePermission permission) {
|
||||
for (Role role : roles) {
|
||||
if (role.hasPermission(permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this [User] has the specified [Role].
|
||||
*
|
||||
* @param role [Role] to evaluate.
|
||||
* @return a boolean value indicating whether this [User] has the specified [Role].
|
||||
* @see Role
|
||||
*/
|
||||
public boolean hasRole(Role role) {
|
||||
return roles.contains(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the array of [Roles][Role] granting (resource) permissions to this [User].
|
||||
*
|
||||
* @param roles array of [Roles][Role] granting (resource) permissions to this [User].
|
||||
* @return this [User].
|
||||
* @see Role
|
||||
*/
|
||||
public User withRoles(Role... roles) {
|
||||
this.roles.addAll(Arrays.asList(roles));
|
||||
return this;
|
||||
}
|
||||
|
||||
public User withRoles(Collection<Role> roles) {
|
||||
this.roles.addAll(roles);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this [User's][User] credentials (e.g. password) to the given value.
|
||||
*
|
||||
* @param credentials [String] containing this [User's][User] credentials (e.g. password).
|
||||
* @return this [User].
|
||||
* @see User
|
||||
*/
|
||||
public User withCredentials(String credentials) {
|
||||
this.credentials = credentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static User newUser(String name) {
|
||||
return new User(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.client;
|
||||
|
||||
import example.springdata.geode.client.security.Customer;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
List<Customer> findAll();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.client;
|
||||
|
||||
import example.springdata.geode.client.security.Customer;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
|
||||
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
|
||||
|
||||
@Configuration
|
||||
@EnableSecurity
|
||||
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
|
||||
@ClientCacheApplication(name = "SecurityClient", logLevel = "error", pingInterval = 5000L, readTimeout = 15000, retryAttempts = 1)
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Customer.class, clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY)
|
||||
public class SecurityEnabledClientConfiguration {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
|
||||
|
||||
@Configuration
|
||||
@EnableSecurity(shiroIniResourcePath = "shiro.ini")
|
||||
@Profile("shiro-ini-configuration")
|
||||
public class ApacheShiroIniConfiguration {
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import example.springdata.geode.client.security.User;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The [CachingSecurityRepository] class caches Security Configuration Meta-Data and is meant to be extended
|
||||
* by classes that are data store specified (e.g. JDBC/RDBMS, LDAP, etc).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see User
|
||||
* @see SecurityRepository
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class CachingSecurityRepository implements SecurityRepository {
|
||||
private Map<String, User> users = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Iterable<User> findAll() {
|
||||
return users.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(User user) {
|
||||
if (user != null) {
|
||||
return users.remove(user.getName()) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User save(User user) {
|
||||
User putUser = users.put(user.getName(), user);
|
||||
return putUser != null ? putUser : user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableSecurity(securityManagerClassName = "example.springdata.geode.client.security.server.SecurityManagerProxy")
|
||||
@Profile({"default", "geode-security-manager-proxy-configuration"})
|
||||
public class GeodeIntegratedSecurityProxyConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import example.springdata.geode.client.security.Role;
|
||||
import example.springdata.geode.client.security.User;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class JdbcSecurityRepository extends CachingSecurityRepository implements InitializingBean {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private static final String ROLES_QUERY = "SELECT name FROM geode_security.roles";
|
||||
private static final String ROLE_PERMISSIONS_QUERY = ""
|
||||
+ " SELECT rolePerms.resource, rolePerms.operation, rolePerms.region_name, rolePerms.key_name"
|
||||
+ " FROM geode_security.roles_permissions rolePerms"
|
||||
+ " INNER JOIN geode_security.roles roles ON roles.id = rolePerms.role_id "
|
||||
+ " WHERE roles.name = ?";
|
||||
private static final String USERS_QUERY = "SELECT name, credentials FROM geode_security.users";
|
||||
private static final String USER_ROLES_QUERY = ""
|
||||
+ " SELECT roles.name"
|
||||
+ " FROM geode_security.roles roles"
|
||||
+ " INNER JOIN geode_security.users_roles userRoles ON roles.id = userRoles.role_id"
|
||||
+ " INNER JOIN geode_security.users users ON userRoles.user_id = users.id"
|
||||
+ " WHERE users.name = ?";
|
||||
|
||||
public JdbcSecurityRepository(JdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
List<Role> roles = this.jdbcTemplate.query(ROLES_QUERY, (resultSet, i) -> Role.newRole(resultSet.getString(1)));
|
||||
HashMap<String, Role> roleMapping = new HashMap<>(roles.size());
|
||||
|
||||
roles.forEach((role) -> {
|
||||
this.jdbcTemplate.query(ROLE_PERMISSIONS_QUERY, Collections.singleton(role.getName()).toArray(),
|
||||
(RowMapper<Object>) (resultSet, i) -> role.withPermissions(newResourcePermission(
|
||||
resultSet.getString(1), resultSet.getString(2),
|
||||
resultSet.getString(3), resultSet.getString(4))));
|
||||
|
||||
roleMapping.put(role.getName(), role);
|
||||
});
|
||||
|
||||
List<User> users = this.jdbcTemplate.query(USERS_QUERY, (resultSet, i) ->
|
||||
createUser(resultSet.getString(1)).withCredentials(resultSet.getString(2)));
|
||||
|
||||
users.forEach((role) -> {
|
||||
this.jdbcTemplate.query(USER_ROLES_QUERY, Collections.singleton(role.getName()).toArray(),
|
||||
(RowMapper<Object>) (resultSet, i) -> role.withRoles(roleMapping.get(resultSet.getString(1))));
|
||||
|
||||
save(role);
|
||||
});
|
||||
|
||||
logger.debug("Users {}", users);
|
||||
}
|
||||
|
||||
protected ResourcePermission newResourcePermission(String resource, String operation, String region, String key) {
|
||||
return new ResourcePermission(resource, operation, region, key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
@SpringBootApplication(scanBasePackageClasses = SecurityEnabledServerConfiguration.class)
|
||||
public class SecurityEnabledServer {
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(SecurityEnabledServer.class)
|
||||
.web(WebApplicationType.NONE)
|
||||
.build()
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import example.springdata.geode.client.security.Customer;
|
||||
import org.apache.geode.cache.RegionShortcut;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableIndexing;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLocator;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableManager;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Configuration
|
||||
@EnableLocator
|
||||
@EnableIndexing
|
||||
@EnableManager
|
||||
@Import({ApacheShiroIniConfiguration.class, GeodeIntegratedSecurityProxyConfiguration.class})
|
||||
@CacheServerApplication(port = 0, logLevel = "error")
|
||||
@EnableEntityDefinedRegions(basePackageClasses = Customer.class, serverRegionShortcut = RegionShortcut.REPLICATE)
|
||||
public class SecurityEnabledServerConfiguration {
|
||||
|
||||
@Bean
|
||||
DataSource hsqlDataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setName("geode_security")
|
||||
.setScriptEncoding("UTF-8")
|
||||
.setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScript("sql/geode-security-schema-ddl.sql")
|
||||
.addScript("sql/define-roles-table-ddl.sql")
|
||||
.addScript("sql/define-roles-permissions-table-ddl.sql")
|
||||
.addScript("sql/define-users-table-ddl.sql")
|
||||
.addScript("sql/define-users-roles-table-ddl.sql")
|
||||
.addScript("sql/insert-roles-dml.sql")
|
||||
.addScript("sql/insert-roles-permissions-dml.sql")
|
||||
.addScript("sql/insert-users-dml.sql")
|
||||
.addScript("sql/insert-users-roles-dml.sql")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.cp.elements.lang.Assert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.support.LazyWiringDeclarableSupport;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* The {@link SecurityManagerProxy} class is a Proxy delegating to an underlying Apache Geode
|
||||
* {@link org.apache.geode.security.SecurityManager} implementation, that maybe a Spring managed bean
|
||||
* in a Spring context that may have been configured and auto-wired the Spring container, or possibly
|
||||
* other managed environment (Cloud or Java EE Server, etc).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @see org.springframework.data.gemfire.support.LazyWiringDeclarableSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class SecurityManagerProxy extends LazyWiringDeclarableSupport
|
||||
implements org.apache.geode.security.SecurityManager {
|
||||
|
||||
private org.apache.geode.security.SecurityManager securityManager;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the {@link SecurityManagerProxy}, whick will delegate all Apache Geode
|
||||
* security operations to a Spring managed {@link org.apache.geode.security.SecurityManager} bean.
|
||||
*/
|
||||
public SecurityManagerProxy() {
|
||||
// TODO remove init() call when GEODE-2083 (https://issues.apache.org/jira/browse/GEODE-2083) is resolved!
|
||||
// NOTE the init(:Properties) call in the constructor is less than ideal since...
|
||||
// 1) it allows the *this* reference to escape, and...
|
||||
// 2) it is Geode's responsibility to identify Geode Declarable objects and invoke their init(:Properties) method
|
||||
// However, the init(:Properties) method invocation in the constructor is necessary to enable this Proxy to be
|
||||
// identified and auto-wired in a Spring context.
|
||||
init(new Properties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
|
||||
* delegated to by this {@link SecurityManagerProxy}.
|
||||
*
|
||||
* @return a reference to the underlying, Apache Geode {@link org.apache.geode.security.SecurityManager}
|
||||
* instance delegated to by this {@link SecurityManagerProxy}.
|
||||
* @throws IllegalStateException if the configured Apache Geode {@link org.apache.geode.security.SecurityManager}
|
||||
* was not properly initialized.
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
*/
|
||||
protected org.apache.geode.security.SecurityManager getSecurityManager() {
|
||||
Assert.state(this.securityManager != null, "SecurityManager was not properly initialized");
|
||||
return this.securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
|
||||
* delegated to by this {@link SecurityManagerProxy}.
|
||||
*
|
||||
* @param securityManager reference to the underlying, Apache Geode {@link org.apache.geode.security.SecurityManager}
|
||||
* instance delegated to by this {@link SecurityManagerProxy}.
|
||||
* @throws IllegalArgumentException if the Apache Geode {@link org.apache.geode.security.SecurityManager} reference
|
||||
* is {@literal null}.
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
*/
|
||||
@Autowired
|
||||
public void setSecurityManager(org.apache.geode.security.SecurityManager securityManager) {
|
||||
Assert.notNull(securityManager, "SecurityManager must not be null");
|
||||
this.securityManager = securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object authenticate(Properties properties) throws AuthenticationFailedException {
|
||||
return getSecurityManager().authenticate(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean authorize(Object principal, ResourcePermission permission) {
|
||||
return getSecurityManager().authorize(principal, permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
getSecurityManager().close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import example.springdata.geode.client.security.Constants;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* The [SecurityManagerSupport] class is an Apache Geode [SecurityManager] interface adapter providing
|
||||
* default implementations of the [SecurityManager] interface operations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see Principal
|
||||
* @see ResourcePermission
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class SecurityManagerSupport implements org.apache.geode.security.SecurityManager {
|
||||
|
||||
protected Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
/* (non-Javadoc)*/
|
||||
protected String getName(Object principal) {
|
||||
if (principal instanceof Principal) {
|
||||
return ((Principal) principal).getName();
|
||||
} else {
|
||||
return principal.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)*/
|
||||
protected String getPassword(Properties securityProperties) {
|
||||
return getPropertyValue(securityProperties, Constants.SECURITY_PASSWORD_PROPERTY);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)*/
|
||||
protected String getUsername(Properties securityProperties) {
|
||||
return getPropertyValue(securityProperties, Constants.SECURITY_USERNAME_PROPERTY);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)*/
|
||||
protected String getPropertyValue(Properties properties, String propertyName) {
|
||||
return properties.getProperty(propertyName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)*/
|
||||
protected void logDebug(String message, Object... args) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(message, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void init(Properties securityProperties) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Security Properties [{}]", securityProperties);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object authenticate(Properties securityProperties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean authorize(Object principal, ResourcePermission permission) {
|
||||
return principal != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing SecurityManager [{}]", this.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import example.springdata.geode.client.security.Role;
|
||||
import example.springdata.geode.client.security.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The [SecurityRepository] interface is a contract for Data Access Objects (DAO) implementing this interface
|
||||
* to perform CRUD and query operations on [User] information, pertinent to the security of the system.
|
||||
*
|
||||
* @author John Blum
|
||||
* @author Udo Kohlmeyer
|
||||
* @see Role
|
||||
* @see User
|
||||
* @see org.springframework.stereotype.Repository
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface SecurityRepository {
|
||||
/**
|
||||
* Finds all [Users][User] of the system.
|
||||
*
|
||||
* @return an [Iterable] of [Users][User] of the system.
|
||||
* @see User
|
||||
* @see Iterable
|
||||
*/
|
||||
Iterable<User> findAll();
|
||||
|
||||
/**
|
||||
* Deletes the given [User] from the system.
|
||||
*
|
||||
* @param user [User] to delete.
|
||||
* @return a boolean value indicating if the [User] was deleted successfully.
|
||||
* @see User
|
||||
*/
|
||||
boolean delete(User user);
|
||||
|
||||
/**
|
||||
* Records (persist) the information (state) of the [User].
|
||||
*
|
||||
* @param user [User] to store.
|
||||
* @return the [User].
|
||||
* @see User
|
||||
*/
|
||||
User save(User user);
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default int count() {
|
||||
int count = 0;
|
||||
Iterable<User> users = findAll();
|
||||
for (User user : users) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default User createUser(String username, Role... roles) {
|
||||
return save(User.newUser(username).withRoles(roles));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default boolean delete(String username) {
|
||||
User user = findBy(username);
|
||||
if (user != null) {
|
||||
return delete(user);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default boolean deleteAll(String... username) {
|
||||
return deleteAll(findAll(username));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default boolean deleteAll(User... users) {
|
||||
return deleteAll(Arrays.asList(users));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default boolean deleteAll(Iterable<User> users) {
|
||||
for (User user : users) {
|
||||
if (!delete(user)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default boolean deleteAll() {
|
||||
return deleteAll(findAll());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default boolean exists(String username) {
|
||||
return findBy(username) != null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default Iterable<User> findAll(String... username) {
|
||||
return findAll(Arrays.asList(username));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default Iterable<User> findAll(Iterable<String> username) {
|
||||
List<User> all = new ArrayList<>();
|
||||
username.forEach(u -> {
|
||||
if (u != null) {
|
||||
all.add(findBy(u));
|
||||
}
|
||||
});
|
||||
return all;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default User findBy(String username) {
|
||||
for (User user : findAll()) {
|
||||
if (user.getName().equals(username)) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default Iterable<User> saveAll(User... users) {
|
||||
return saveAll(Arrays.asList(users));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
default Iterable<User> saveAll(Iterable<User> users) {
|
||||
List<User> saved = new ArrayList<>();
|
||||
users.forEach(user -> saved.add(save(user)));
|
||||
return saved;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.server;
|
||||
|
||||
import example.springdata.geode.client.security.Role;
|
||||
import example.springdata.geode.client.security.User;
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* The [SimpleSecurityManager] class is an example Apache Geode [SecurityManager] provider implementation
|
||||
* used to secure Apache Geode.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see SecurityManagerSupport
|
||||
* @see Role
|
||||
* @see User
|
||||
* @see SecurityRepository
|
||||
* @see ResourcePermission
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @see org.springframework.stereotype.Service
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class SimpleSecurityManager extends SecurityManagerSupport {
|
||||
|
||||
protected SecurityRepository securityRepository;
|
||||
|
||||
public SimpleSecurityManager(SecurityRepository securityRepository) {
|
||||
this.securityRepository = securityRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object authenticate(Properties securityProperties) {
|
||||
String username = getUsername(securityProperties);
|
||||
String password = getPassword(securityProperties);
|
||||
|
||||
logDebug("User with name [{}] is attempting to login with password [{}]", username, password);
|
||||
|
||||
User user = securityRepository.findBy(username);
|
||||
|
||||
if (isNotAuthentic(user, password)) {
|
||||
throw new AuthenticationFailedException(String.format("Failed to authenticate user [%s]", username));
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isAuthentic(User user, String credentials) {
|
||||
return user != null && user.getCredentials().equals(credentials);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isNotAuthentic(User user, String credentials) {
|
||||
return !isAuthentic(user, credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean authorize(Object principal, ResourcePermission permission) {
|
||||
logDebug("Principal [{}] is requesting access to a Resource {} with the required Permission [{}]",
|
||||
principal, permission.getResource(), permission);
|
||||
|
||||
return isAuthorized(principal, permission);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isAuthorized(Object principal, ResourcePermission permission) {
|
||||
User user = resolveUser(principal);
|
||||
|
||||
return user != null && isAuthorized(user, permission);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected User resolveUser(Object principal) {
|
||||
if (principal instanceof User) {
|
||||
return (User) principal;
|
||||
} else {
|
||||
return securityRepository.findBy(getName(principal));
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isAuthorized(User user, ResourcePermission requiredPermission) {
|
||||
if (!user.hasPermission(requiredPermission)) {
|
||||
for (Role role : user.getRoles()) {
|
||||
for (ResourcePermission userPermission : role.getPermissions()) {
|
||||
if (isPermitted(userPermission, requiredPermission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isPermitted(ResourcePermission userPermission, ResourcePermission resourcePermission) {
|
||||
return userPermission.implies(resourcePermission);
|
||||
}
|
||||
|
||||
}
|
||||
2
geode/security/src/main/resources/application.properties
Executable file
2
geode/security/src/main/resources/application.properties
Executable file
@@ -0,0 +1,2 @@
|
||||
spring.data.gemfire.security.username=scientist
|
||||
spring.data.gemfire.security.password=w0rk!ng4u
|
||||
42
geode/security/src/main/resources/shiro.ini
Executable file
42
geode/security/src/main/resources/shiro.ini
Executable file
@@ -0,0 +1,42 @@
|
||||
# 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.
|
||||
|
||||
# Shiro INI configuration
|
||||
|
||||
# Objects and their properties are defined here, such as the securityManager, Realms and anything else needed
|
||||
# to build the SecurityManager
|
||||
[main]
|
||||
|
||||
# The 'users' section is for simple deployments when you only need a small number of statically-defined
|
||||
# set of User accounts.
|
||||
# username = password, roleName1, roleName2, …, roleNameN
|
||||
[users]
|
||||
root = s3cr3t!, ADMIN, DBA
|
||||
scientist = w0rk!ng4u, DATA_SCIENTIST
|
||||
analyst = p@55w0rd, DATA_ANALYST
|
||||
guest = guest, GUEST
|
||||
|
||||
# The 'roles' section is for simple deployments when you only need a small number of statically-defined roles.
|
||||
# rolename = permissionDefinition1, permissionDefinition2, …, permissionDefinitionN
|
||||
[roles]
|
||||
ADMIN = CLUSTER:MANAGE, CLUSTER:READ, CLUSTER:WRITE
|
||||
DBA = DATA:MANAGE, DATA:READ, DATA:WRITE
|
||||
DATA_SCIENTIST = DATA:READ, DATA:WRITE
|
||||
DATA_ANALYST = DATA:READ
|
||||
GUEST = NULL
|
||||
|
||||
# The 'urls' section is used for url-based security in web applications. We'll discuss this section
|
||||
# in the Web documentation
|
||||
[urls]
|
||||
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS geode_security.roles_permissions (
|
||||
role_id INTEGER REFERENCES geode_security.roles(id),
|
||||
resource VARCHAR(32) NOT NUll,
|
||||
operation VARCHAR(32) NOT NULL,
|
||||
region_name VARCHAR(255),
|
||||
key_name VARCHAR(255)
|
||||
);
|
||||
4
geode/security/src/main/resources/sql/define-roles-table-ddl.sql
Executable file
4
geode/security/src/main/resources/sql/define-roles-table-ddl.sql
Executable file
@@ -0,0 +1,4 @@
|
||||
CREATE TABLE IF NOT EXISTS geode_security.roles (
|
||||
id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1),
|
||||
name VARCHAR(32) NOT NULL
|
||||
);
|
||||
4
geode/security/src/main/resources/sql/define-users-roles-table-ddl.sql
Executable file
4
geode/security/src/main/resources/sql/define-users-roles-table-ddl.sql
Executable file
@@ -0,0 +1,4 @@
|
||||
CREATE TABLE IF NOT EXISTS geode_security.users_roles (
|
||||
user_id INTEGER REFERENCES geode_security.users(id),
|
||||
role_id INTEGER REFERENCES geode_security.roles(id)
|
||||
);
|
||||
5
geode/security/src/main/resources/sql/define-users-table-ddl.sql
Executable file
5
geode/security/src/main/resources/sql/define-users-table-ddl.sql
Executable file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS geode_security.users (
|
||||
id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
credentials VARCHAR(255)
|
||||
);
|
||||
1
geode/security/src/main/resources/sql/geode-security-schema-ddl.sql
Executable file
1
geode/security/src/main/resources/sql/geode-security-schema-ddl.sql
Executable file
@@ -0,0 +1 @@
|
||||
CREATE SCHEMA geode_security
|
||||
5
geode/security/src/main/resources/sql/insert-roles-dml.sql
Executable file
5
geode/security/src/main/resources/sql/insert-roles-dml.sql
Executable file
@@ -0,0 +1,5 @@
|
||||
INSERT INTO geode_security.roles (name) VALUES ('ADMIN');
|
||||
INSERT INTO geode_security.roles (name) VALUES ('DBA');
|
||||
INSERT INTO geode_security.roles (name) VALUES ('DATA_SCIENTIST');
|
||||
INSERT INTO geode_security.roles (name) VALUES ('DATA_ANALYST');
|
||||
INSERT INTO geode_security.roles (name) VALUES ('GUEST');
|
||||
11
geode/security/src/main/resources/sql/insert-roles-permissions-dml.sql
Executable file
11
geode/security/src/main/resources/sql/insert-roles-permissions-dml.sql
Executable file
@@ -0,0 +1,11 @@
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'ADMIN'), 'CLUSTER', 'MANAGE');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'ADMIN'), 'CLUSTER', 'READ');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'ADMIN'), 'CLUSTER', 'WRITE');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'DBA'), 'DATA', 'MANAGE');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'DBA'), 'DATA', 'READ');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'DBA'), 'DATA', 'WRITE');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'DATA_SCIENTIST'), 'DATA', 'READ');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'DATA_SCIENTIST'), 'DATA', 'WRITE');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'DATA_ANALYST'), 'DATA', 'READ');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'GUEST'), 'CLUSTER', 'NULL');
|
||||
INSERT INTO geode_security.roles_permissions (role_id, resource, operation) VALUES ((SELECT id FROM geode_security.roles WHERE name = 'GUEST'), 'DATA', 'NULL');
|
||||
4
geode/security/src/main/resources/sql/insert-users-dml.sql
Executable file
4
geode/security/src/main/resources/sql/insert-users-dml.sql
Executable file
@@ -0,0 +1,4 @@
|
||||
INSERT INTO geode_security.users (name, credentials) VALUES ('root', 's3cr3t!');
|
||||
INSERT INTO geode_security.users (name, credentials) VALUES ('scientist', 'w0rk!ng4u');
|
||||
INSERT INTO geode_security.users (name, credentials) VALUES ('analyst', 'p@55w0rd');
|
||||
INSERT INTO geode_security.users (name, credentials) VALUES ('guest', 'guest');
|
||||
5
geode/security/src/main/resources/sql/insert-users-roles-dml.sql
Executable file
5
geode/security/src/main/resources/sql/insert-users-roles-dml.sql
Executable file
@@ -0,0 +1,5 @@
|
||||
INSERT INTO geode_security.users_roles (user_id, role_id) VALUES ((SELECT id FROM geode_security.users WHERE name = 'root'), (SELECT id FROM geode_security.roles WHERE name = 'ADMIN'));
|
||||
INSERT INTO geode_security.users_roles (user_id, role_id) VALUES ((SELECT id FROM geode_security.users WHERE name = 'root'), (SELECT id FROM geode_security.roles WHERE name = 'DBA'));
|
||||
INSERT INTO geode_security.users_roles (user_id, role_id) VALUES ((SELECT id FROM geode_security.users WHERE name = 'scientist'), (SELECT id FROM geode_security.roles WHERE name = 'DATA_SCIENTIST'));
|
||||
INSERT INTO geode_security.users_roles (user_id, role_id) VALUES ((SELECT id FROM geode_security.users WHERE name = 'analyst'), (SELECT id FROM geode_security.roles WHERE name = 'DATA_ANALYST'));
|
||||
INSERT INTO geode_security.users_roles (user_id, role_id) VALUES ((SELECT id FROM geode_security.users WHERE name = 'guest'), (SELECT id FROM geode_security.roles WHERE name = 'GUEST'));
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.client;
|
||||
|
||||
import example.springdata.geode.client.security.Customer;
|
||||
import example.springdata.geode.client.security.EmailAddress;
|
||||
import example.springdata.geode.client.security.server.SecurityEnabledServer;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = SecurityEnabledClientConfiguration.class)
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
public class SecurityEnabledClientShiroTests extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
@Autowired
|
||||
private CustomerRepository customerRepository;
|
||||
|
||||
@Resource(name = "Customers")
|
||||
private Region<Long, Customer> customers;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
startGemFireServer(SecurityEnabledServer.class, "-Dspring.profiles.active=shiro-ini-configuration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void securityWasConfiguredCorrectly() {
|
||||
logger.info("Inserting 3 entries for keys: 1, 2, 3");
|
||||
Customer john = new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith");
|
||||
Customer frank = new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport");
|
||||
Customer jude = new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons");
|
||||
customerRepository.save(john);
|
||||
customerRepository.save(frank);
|
||||
customerRepository.save(jude);
|
||||
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
|
||||
logger.info("Customers saved on server:");
|
||||
List<Customer> customerList = customerRepository.findAll();
|
||||
assertThat(customerList.size()).isEqualTo(3);
|
||||
assertThat(customerList.contains(john)).isTrue();
|
||||
assertThat(customerList.contains(frank)).isTrue();
|
||||
assertThat(customerList.contains(jude)).isTrue();
|
||||
customerList.forEach(customer -> logger.info("\t Entry: \n \t\t " + customer));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
package example.springdata.geode.client.security.client;
|
||||
|
||||
import example.springdata.geode.client.security.Customer;
|
||||
import example.springdata.geode.client.security.EmailAddress;
|
||||
import example.springdata.geode.client.security.server.SecurityEnabledServer;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = SecurityEnabledClientConfiguration.class)
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
public class SecurityEnabledClientTests extends ForkingClientServerIntegrationTestsSupport {
|
||||
|
||||
@Autowired
|
||||
private CustomerRepository customerRepository;
|
||||
|
||||
@Resource(name = "Customers")
|
||||
private Region<Long, Customer> customers;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
startGemFireServer(SecurityEnabledServer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SecurityWasConfiguredCorrectly() {
|
||||
logger.info("Inserting 3 entries for keys: 1, 2, 3");
|
||||
Customer john = new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith");
|
||||
Customer frank = new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport");
|
||||
Customer jude = new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons");
|
||||
customerRepository.save(john);
|
||||
customerRepository.save(frank);
|
||||
customerRepository.save(jude);
|
||||
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
|
||||
logger.info("Customers saved on server:");
|
||||
List<Customer> customerList = customerRepository.findAll();
|
||||
assertThat(customerList.size()).isEqualTo(3);
|
||||
assertThat(customerList.contains(john)).isTrue();
|
||||
assertThat(customerList.contains(frank)).isTrue();
|
||||
assertThat(customerList.contains(jude)).isTrue();
|
||||
customerList.forEach(customer -> logger.info("\t Entry: \n \t\t " + customer));
|
||||
}
|
||||
}
|
||||
11
geode/security/src/test/resources/logback.xml
Normal file
11
geode/security/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="error">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user