mirror of https://github.com/apache/nifi.git
NIFI-6400 Better options, consistent ids for ShellUserGroupProvider.
NIFI-6400 Fixes to address PR feedback. NIFI-6400 Accepts proposed changes. This closes #3637
This commit is contained in:
parent
a1b02ec113
commit
4596ef7c8a
|
@ -469,6 +469,8 @@ The ShellUserGroupProvider has the following properties:
|
|||
| Property Name | Description
|
||||
|`Initial Refresh Delay` | Duration of initial delay before first user and group refresh. (i.e. `10 secs`). Default is `5 mins`.
|
||||
|`Refresh Delay` | Duration of delay between each user and group refresh. (i.e. `10 secs`). Default is `5 mins`.
|
||||
|`Exclude Groups` | Regular expression used to exclude groups. Default is '', which means no groups are excluded.
|
||||
|`Exclude Users` | Regular expression used to exclude users. Default is '', which means no users are excluded.
|
||||
|==================================================================================================================================================
|
||||
|
||||
Like LdapUserGroupProvider, the ShellUserGroupProvider is commented out in the _authorizers.xml_ file. Refer to that comment for usage examples.
|
||||
|
|
|
@ -175,15 +175,17 @@
|
|||
on systems that support `sh`. Implementations available for Linux and Mac OS, and are selected by the
|
||||
provider based on the system property `os.name`.
|
||||
|
||||
'Initial Refresh Delay' - duration to wait before first refresh. Default is '5 mins'.
|
||||
'Refresh Delay' - duration to wait between subsequent refreshes. Default is '5 mins'.
|
||||
'Exclude Groups' - regular expression used to exclude groups. Default is '', which means no groups are excluded.
|
||||
'Exclude Users' - regular expression used to exclude users. Default is '', which means no users are excluded.
|
||||
-->
|
||||
<!-- To enable the shell-user-group-provider remove 2 lines. This is 1 of 2.
|
||||
<userGroupProvider>
|
||||
<identifier>shell-user-group-provider</identifier>
|
||||
<class>org.apache.nifi.authorization.ShellUserGroupProvider</class>
|
||||
<property name="Initial Refresh Delay">5 mins</property>
|
||||
<property name="Refresh Delay">5 mins</property>
|
||||
<property name="Exclude Groups"></property>
|
||||
<property name="Exclude Users"></property>
|
||||
</userGroupProvider>
|
||||
To enable the shell-user-group-provider remove 2 lines. This is 2 of 2. -->
|
||||
|
||||
|
|
|
@ -16,6 +16,15 @@
|
|||
*/
|
||||
package org.apache.nifi.authorization;
|
||||
|
||||
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
||||
import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
|
||||
import org.apache.nifi.authorization.util.ShellRunner;
|
||||
import org.apache.nifi.components.PropertyValue;
|
||||
import org.apache.nifi.util.FormatUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -26,21 +35,14 @@ import java.util.Set;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
||||
import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
|
||||
import org.apache.nifi.authorization.util.ShellRunner;
|
||||
import org.apache.nifi.components.PropertyValue;
|
||||
import org.apache.nifi.util.FormatUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
|
||||
/*
|
||||
* ShellUserGroupProvider implements UserGroupProvider by way of shell commands.
|
||||
*/
|
||||
public class ShellUserGroupProvider implements UserGroupProvider {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ShellUserGroupProvider.class);
|
||||
|
||||
private final static String OS_TYPE_ERROR = "Unsupported operating system.";
|
||||
|
@ -49,12 +51,15 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
private final static Map<String, User> usersByName = new HashMap<>(); // name == identity
|
||||
private final static Map<String, Group> groupsById = new HashMap<>();
|
||||
|
||||
public static final String INITIAL_REFRESH_DELAY_PROPERTY = "Initial Refresh Delay";
|
||||
public static final String REFRESH_DELAY_PROPERTY = "Refresh Delay";
|
||||
|
||||
private static final long MINIMUM_SYNC_INTERVAL_MILLISECONDS = 10_000;
|
||||
private long initialDelay;
|
||||
|
||||
public static final String EXCLUDE_USER_PROPERTY = "Exclude Users";
|
||||
public static final String EXCLUDE_GROUP_PROPERTY = "Exclude Groups";
|
||||
|
||||
private long fixedDelay;
|
||||
private Pattern excludeUsers;
|
||||
private Pattern excludeGroups;
|
||||
|
||||
// Our scheduler has one thread for users, one for groups:
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
|
||||
|
@ -98,11 +103,6 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
user = usersById.get(identifier);
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
refreshOneUser(selectedShellCommands.getUserById(identifier), "Get Single User by Id");
|
||||
user = usersById.get(identifier);
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
logger.debug("getUser (by id) user not found: " + identifier);
|
||||
} else {
|
||||
|
@ -235,7 +235,6 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
*/
|
||||
@Override
|
||||
public void onConfigured(AuthorizerConfigurationContext configurationContext) throws AuthorizerCreationException {
|
||||
initialDelay = getDelayProperty(configurationContext, INITIAL_REFRESH_DELAY_PROPERTY, "5 mins");
|
||||
fixedDelay = getDelayProperty(configurationContext, REFRESH_DELAY_PROPERTY, "5 mins");
|
||||
|
||||
// Our next init step is to select the command set based on the operating system name:
|
||||
|
@ -255,11 +254,26 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
throw new AuthorizerCreationException(SYS_CHECK_ERROR, ioexc.getCause());
|
||||
}
|
||||
|
||||
// The next step is to add the user and group exclude regexes:
|
||||
try {
|
||||
excludeGroups = Pattern.compile(getProperty(configurationContext, EXCLUDE_GROUP_PROPERTY, ""));
|
||||
excludeUsers = Pattern.compile(getProperty(configurationContext, EXCLUDE_USER_PROPERTY, ""));
|
||||
} catch (final PatternSyntaxException e) {
|
||||
throw new AuthorizerCreationException(e);
|
||||
}
|
||||
|
||||
// With our command set selected, and our system check passed, we can pull in the users and groups:
|
||||
refreshUsersAndGroups();
|
||||
|
||||
// And finally, our last init step is to fire off the refresh thread:
|
||||
scheduler.scheduleWithFixedDelay(this::refreshUsersAndGroups, initialDelay, fixedDelay, TimeUnit.SECONDS);
|
||||
scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
refreshUsersAndGroups();
|
||||
}catch (final Throwable t) {
|
||||
logger.error("", t);
|
||||
}
|
||||
}, fixedDelay, fixedDelay, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
private static ShellCommandsProvider getCommandsProviderFromName(String osName) {
|
||||
|
@ -280,6 +294,19 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
return commands;
|
||||
}
|
||||
|
||||
private String getProperty(AuthorizerConfigurationContext authContext, String propertyName, String defaultValue) {
|
||||
final PropertyValue property = authContext.getProperty(propertyName);
|
||||
final String value;
|
||||
|
||||
if (property != null && property.isSet()) {
|
||||
value = property.getValue();
|
||||
} else {
|
||||
value = defaultValue;
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
private long getDelayProperty(AuthorizerConfigurationContext authContext, String propertyName, String defaultValue) {
|
||||
final PropertyValue intervalProperty = authContext.getProperty(propertyName);
|
||||
final String propertyValue;
|
||||
|
@ -445,20 +472,21 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
if (record.length > 2) {
|
||||
String name = record[0], id = record[1], gid = record[2];
|
||||
|
||||
if (name != null && id != null && !name.equals("") && !id.equals("")) {
|
||||
|
||||
User user = new User.Builder().identity(name).identifier(id).build();
|
||||
idToUser.put(id, user);
|
||||
if (name != null && id != null && !name.equals("") && !id.equals("") && !excludeUsers.matcher(name).matches()) {
|
||||
User user = new User.Builder().identity(name).identifierGenerateFromSeed(id).build();
|
||||
idToUser.put(user.getIdentifier(), user);
|
||||
usernameToUser.put(name, user);
|
||||
|
||||
if (gid != null && !gid.equals("")) {
|
||||
gidToUser.put(gid, user);
|
||||
// create a temporary group to deterministically generate the group id and associate this user
|
||||
Group group = new Group.Builder().name(gid).identifierGenerateFromSeed(gid).build();
|
||||
gidToUser.put(group.getIdentifier(), user);
|
||||
} else {
|
||||
logger.warn("Null or empty primary group id for: " + name);
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.warn("Null or empty user name: " + name + " or id: " + id);
|
||||
logger.warn("Null, empty, or skipped user name: " + name + " or id: " + id);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Unexpected record format. Expected 3 or more colon separated values per line.");
|
||||
|
@ -499,12 +527,12 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
logger.error("list membership shell exception: " + ioexc);
|
||||
}
|
||||
|
||||
if (name != null && id != null && !name.equals("") && !id.equals("")) {
|
||||
Group group = new Group.Builder().name(name).identifier(id).addUsers(users).build();
|
||||
groupsById.put(id, group);
|
||||
if (name != null && id != null && !name.equals("") && !id.equals("") && !excludeGroups.matcher(name).matches()) {
|
||||
Group group = new Group.Builder().name(name).identifierGenerateFromSeed(id).addUsers(users).build();
|
||||
groupsById.put(group.getIdentifier(), group);
|
||||
logger.debug("Refreshed group: " + group);
|
||||
} else {
|
||||
logger.warn("Null or empty group name: " + name + " or id: " + id);
|
||||
logger.warn("Null, empty, or skipped group name: " + name + " or id: " + id);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Unexpected record format. Expected 1 or more comma separated values.");
|
||||
|
@ -525,26 +553,18 @@ public class ShellUserGroupProvider implements UserGroupProvider {
|
|||
|
||||
if (primaryGroup == null) {
|
||||
logger.warn("user: " + primaryUser + " primary group not found");
|
||||
} else {
|
||||
} else if (!excludeGroups.matcher(primaryGroup.getName()).matches()) {
|
||||
Set<String> groupUsers = primaryGroup.getUsers();
|
||||
if (!groupUsers.contains(primaryUser.getIdentity())) {
|
||||
Set<String> secondSet = new HashSet<>(groupUsers);
|
||||
secondSet.add(primaryUser.getIdentity());
|
||||
Group group = new Group.Builder().name(primaryGroup.getName()).identifier(primaryGid).addUsers(secondSet).build();
|
||||
gidToGroup.put(primaryGid, group);
|
||||
Group group = new Group.Builder().name(primaryGroup.getName()).identifierGenerateFromSeed(primaryGid).addUsers(secondSet).build();
|
||||
gidToGroup.put(group.getIdentifier(), group);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The initial refresh delay.
|
||||
*/
|
||||
public long getInitialRefreshDelay() {
|
||||
return initialDelay;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The fixed refresh delay.
|
||||
*/
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.nifi.authorization;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
abstract class ShellUserGroupProviderBase {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShellUserGroupProviderBase.class);
|
||||
|
||||
private final String KNOWN_USER = "root";
|
||||
private final String KNOWN_UID = "0";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final String KNOWN_GROUP = "root";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final String OTHER_GROUP = "wheel"; // e.g., macos
|
||||
private final String KNOWN_GID = "0";
|
||||
|
||||
// We're using this knob to control the test runs on Travis. The issue there is that tests
|
||||
// running on Travis do not have `getent`, thus not behaving like a typical Linux installation.
|
||||
protected static boolean systemCheckFailed = false;
|
||||
|
||||
/**
|
||||
* Ensures that the test can run because Docker is available and the remote instance can be reached via ssh.
|
||||
*
|
||||
* @return true if Docker is available on this OS
|
||||
*/
|
||||
protected boolean isSSHAvailable() {
|
||||
return !systemCheckFailed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting its users and checking minimum size.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetUsersAndUsersMinimumCount(UserGroupProvider provider) {
|
||||
assumeTrue(isSSHAvailable());
|
||||
|
||||
Set<User> users = provider.getUsers();
|
||||
assertNotNull(users);
|
||||
assertTrue(users.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known user by uid.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetKnownUserByUsername(UserGroupProvider provider) {
|
||||
// assumeTrue(isSSHAvailable());
|
||||
|
||||
User root = provider.getUser(KNOWN_UID);
|
||||
assertNotNull(root);
|
||||
assertEquals(KNOWN_USER, root.getIdentity());
|
||||
assertEquals(KNOWN_UID, root.getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known user by id.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetKnownUserByUid(UserGroupProvider provider) {
|
||||
assumeTrue(isSSHAvailable());
|
||||
|
||||
User root = provider.getUserByIdentity(KNOWN_USER);
|
||||
assertNotNull(root);
|
||||
assertEquals(KNOWN_USER, root.getIdentity());
|
||||
assertEquals(KNOWN_UID, root.getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting its groups and checking minimum size.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetGroupsAndMinimumGroupCount(UserGroupProvider provider) {
|
||||
assumeTrue(isSSHAvailable());
|
||||
|
||||
Set<Group> groups = provider.getGroups();
|
||||
assertNotNull(groups);
|
||||
assertTrue(groups.size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known group by GID.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetKnownGroupByGid(UserGroupProvider provider) {
|
||||
assumeTrue(isSSHAvailable());
|
||||
|
||||
Group group = provider.getGroup(KNOWN_GID);
|
||||
assertNotNull(group);
|
||||
assertTrue(group.getName().equals(KNOWN_GROUP) || group.getName().equals(OTHER_GROUP));
|
||||
assertEquals(KNOWN_GID, group.getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known group and checking for a known member of it.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetGroupByGidAndGetGroupMembership(UserGroupProvider provider) {
|
||||
assumeTrue(isSSHAvailable());
|
||||
|
||||
Group group = provider.getGroup(KNOWN_GID);
|
||||
assertNotNull(group);
|
||||
|
||||
// These next few try/catch blocks are here for debugging. The user-to-group relationship
|
||||
// is delicate with this implementation, and this approach allows us a measure of control.
|
||||
// Check your logs if you're having problems!
|
||||
|
||||
try {
|
||||
assertTrue(group.getUsers().size() > 0);
|
||||
logger.info("root group count: " + group.getUsers().size());
|
||||
} catch (final AssertionError ignored) {
|
||||
logger.info("root group count zero on this system");
|
||||
}
|
||||
|
||||
try {
|
||||
assertTrue(group.getUsers().contains(KNOWN_USER));
|
||||
logger.info("root group membership: " + group.getUsers());
|
||||
} catch (final AssertionError ignored) {
|
||||
logger.info("root group membership unexpected on this system");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known user and checking its group membership.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
void testGetUserByIdentityAndGetGroupMembership(UserGroupProvider provider) {
|
||||
assumeTrue(isSSHAvailable());
|
||||
|
||||
UserAndGroups user = provider.getUserAndGroups(KNOWN_USER);
|
||||
assertNotNull(user);
|
||||
|
||||
try {
|
||||
assertTrue(user.getGroups().size() > 0);
|
||||
logger.info("root user group count: " + user.getGroups().size());
|
||||
} catch (final AssertionError ignored) {
|
||||
logger.info("root user and groups group count zero on this system");
|
||||
}
|
||||
|
||||
Set<Group> groups = provider.getGroups();
|
||||
assertTrue(groups.size() > user.getGroups().size());
|
||||
}
|
||||
}
|
|
@ -20,6 +20,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
||||
import org.apache.nifi.authorization.util.ShellRunner;
|
||||
import org.apache.nifi.util.MockPropertyValue;
|
||||
|
@ -29,6 +31,7 @@ import org.junit.Assume;
|
|||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
@ -40,7 +43,7 @@ import org.testcontainers.containers.GenericContainer;
|
|||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
|
||||
public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
||||
public class ShellUserGroupProviderIT {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShellUserGroupProviderIT.class);
|
||||
|
||||
// These images are publicly available on the hub.docker.com, and the source to each
|
||||
|
@ -61,10 +64,24 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
private final static String CONTAINER_SSH_AUTH_KEYS = "/root/.ssh/authorized_keys";
|
||||
private final static Integer CONTAINER_SSH_PORT = 22;
|
||||
|
||||
private final String KNOWN_USER = "root";
|
||||
private final String KNOWN_UID = "0";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final String KNOWN_GROUP = "root";
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final String OTHER_GROUP = "wheel"; // e.g., macos
|
||||
private final String KNOWN_GID = "0";
|
||||
|
||||
// We're using this knob to control the test runs on Travis. The issue there is that tests
|
||||
// running on Travis do not have `getent`, thus not behaving like a typical Linux installation.
|
||||
protected static boolean systemCheckFailed = false;
|
||||
|
||||
private static String sshPrivKeyFile;
|
||||
private static String sshPubKeyFile;
|
||||
|
||||
private AuthorizerConfigurationContext authContext;
|
||||
private AuthorizerConfigurationContext authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
private ShellUserGroupProvider localProvider;
|
||||
private UserGroupProviderInitializationContext initContext;
|
||||
|
||||
|
@ -103,8 +120,9 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
initContext = Mockito.mock(UserGroupProviderInitializationContext.class);
|
||||
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.INITIAL_REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("10 sec"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("15 sec"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("10 sec"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.EXCLUDE_GROUP_PROPERTY))).thenReturn(new MockPropertyValue(".*d$"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.EXCLUDE_USER_PROPERTY))).thenReturn(new MockPropertyValue("^s.*"));
|
||||
|
||||
localProvider = new ShellUserGroupProvider();
|
||||
try {
|
||||
|
@ -115,8 +133,7 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
logger.error("setup() exception: " + exc + "; tests cannot run on this system.");
|
||||
return;
|
||||
}
|
||||
Assert.assertEquals(10000, localProvider.getInitialRefreshDelay());
|
||||
Assert.assertEquals(15000, localProvider.getRefreshDelay());
|
||||
Assert.assertEquals(10000, localProvider.getRefreshDelay());
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -124,45 +141,6 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
localProvider.preDestruction();
|
||||
}
|
||||
|
||||
// Our primary test methods all accept a provider; here we define overloads to those methods to
|
||||
// use the local provider. This allows the reuse of those test methods with the remote provider.
|
||||
|
||||
@Test
|
||||
public void testGetUsersAndUsersMinimumCount() {
|
||||
testGetUsersAndUsersMinimumCount(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKnownUserByUsername() {
|
||||
testGetKnownUserByUsername(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKnownUserByUid() {
|
||||
testGetKnownUserByUid(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupsAndMinimumGroupCount() {
|
||||
testGetGroupsAndMinimumGroupCount(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKnownGroupByGid() {
|
||||
testGetKnownGroupByGid(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGroupByGidAndGetGroupMembership() {
|
||||
testGetGroupByGidAndGetGroupMembership(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserByIdentityAndGetGroupMembership() {
|
||||
testGetUserByIdentityAndGetGroupMembership(localProvider);
|
||||
}
|
||||
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
private GenericContainer createContainer(String image) throws IOException, InterruptedException {
|
||||
GenericContainer container = new GenericContainer(image)
|
||||
.withEnv("SSH_ENABLE_ROOT", "true").withExposedPorts(CONTAINER_SSH_PORT);
|
||||
|
@ -192,22 +170,59 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
public void testTooShortDelayIntervalThrowsException() throws AuthorizerCreationException {
|
||||
final AuthorizerConfigurationContext authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
final ShellUserGroupProvider localProvider = new ShellUserGroupProvider();
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.INITIAL_REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("1 milliseconds"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("1 milliseconds"));
|
||||
|
||||
expectedException.expect(AuthorizerCreationException.class);
|
||||
expectedException.expectMessage("The Initial Refresh Delay '1 milliseconds' is below the minimum value of '10000 ms'");
|
||||
expectedException.expectMessage("The Refresh Delay '1 milliseconds' is below the minimum value of '10000 ms'");
|
||||
|
||||
localProvider.onConfigured(authContext);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvalidGroupExcludeExpressionsThrowsException() throws AuthorizerCreationException {
|
||||
AuthorizerConfigurationContext authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
ShellUserGroupProvider localProvider = new ShellUserGroupProvider();
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("3 minutes"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.EXCLUDE_GROUP_PROPERTY))).thenReturn(new MockPropertyValue("(3"));
|
||||
|
||||
expectedException.expect(AuthorizerCreationException.class);
|
||||
expectedException.expectMessage("Unclosed group near index");
|
||||
localProvider.onConfigured(authContext);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidUserExcludeExpressionsThrowsException() throws AuthorizerCreationException {
|
||||
AuthorizerConfigurationContext authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
ShellUserGroupProvider localProvider = new ShellUserGroupProvider();
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("3 minutes"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.EXCLUDE_USER_PROPERTY))).thenReturn(new MockPropertyValue("*"));
|
||||
|
||||
expectedException.expect(AuthorizerCreationException.class);
|
||||
expectedException.expectMessage("Dangling meta character");
|
||||
localProvider.onConfigured(authContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingExcludeExpressionsAllowed() throws AuthorizerCreationException {
|
||||
AuthorizerConfigurationContext authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
ShellUserGroupProvider localProvider = new ShellUserGroupProvider();
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("3 minutes"));
|
||||
|
||||
localProvider.onConfigured(authContext);
|
||||
verifyUsersAndUsersMinimumCount(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidDelayIntervalThrowsException() throws AuthorizerCreationException {
|
||||
final AuthorizerConfigurationContext authContext = Mockito.mock(AuthorizerConfigurationContext.class);
|
||||
final ShellUserGroupProvider localProvider = new ShellUserGroupProvider();
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.INITIAL_REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("Not an interval"));
|
||||
Mockito.when(authContext.getProperty(Mockito.eq(ShellUserGroupProvider.REFRESH_DELAY_PROPERTY))).thenReturn(new MockPropertyValue("Not an interval"));
|
||||
|
||||
expectedException.expect(AuthorizerCreationException.class);
|
||||
expectedException.expectMessage("The Initial Refresh Delay 'Not an interval' is not a valid time interval.");
|
||||
expectedException.expectMessage("The Refresh Delay 'Not an interval' is not a valid time interval.");
|
||||
|
||||
localProvider.onConfigured(authContext);
|
||||
}
|
||||
|
@ -220,23 +235,26 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetOneUserAfterClearingCaches() {
|
||||
// assert known state: empty, testable, not empty
|
||||
localProvider.clearCaches();
|
||||
testGetKnownUserByUid(localProvider);
|
||||
assert localProvider.userCacheSize() > 0;
|
||||
public void testLocalGetUsersAndUsersMinimumCount() {
|
||||
verifyUsersAndUsersMinimumCount(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOneGroupAfterClearingCaches() {
|
||||
Assume.assumeTrue(isSSHAvailable());
|
||||
|
||||
// assert known state: empty, testable, not empty
|
||||
localProvider.clearCaches();
|
||||
testGetKnownGroupByGid(localProvider);
|
||||
assert localProvider.groupCacheSize() > 0;
|
||||
public void testLocalGetKnownUserByUsername() {
|
||||
verifyKnownUserByUsername(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalGetGroupsAndMinimumGroupCount() {
|
||||
verifyGroupsAndMinimumGroupCount(localProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalGetUserByIdentityAndGetGroupMembership() {
|
||||
verifyGetUserByIdentityAndGetGroupMembership(localProvider);
|
||||
}
|
||||
|
||||
// @Ignore // for now
|
||||
@Test
|
||||
public void testVariousSystemImages() {
|
||||
// Here we explicitly clear the system check flag to allow the remote checks that follow:
|
||||
|
@ -262,12 +280,10 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
}
|
||||
|
||||
try {
|
||||
testGetUsersAndUsersMinimumCount(remoteProvider);
|
||||
testGetKnownUserByUsername(remoteProvider);
|
||||
testGetGroupsAndMinimumGroupCount(remoteProvider);
|
||||
testGetKnownGroupByGid(remoteProvider);
|
||||
testGetGroupByGidAndGetGroupMembership(remoteProvider);
|
||||
testGetUserByIdentityAndGetGroupMembership(remoteProvider);
|
||||
verifyUsersAndUsersMinimumCount(remoteProvider);
|
||||
verifyKnownUserByUsername(remoteProvider);
|
||||
verifyGroupsAndMinimumGroupCount(remoteProvider);
|
||||
verifyGetUserByIdentityAndGetGroupMembership(remoteProvider);
|
||||
} catch (final Exception e) {
|
||||
// Some environments don't allow our tests to work.
|
||||
logger.error("Exception running remote provider on image: " + image + ", exception: " + e);
|
||||
|
@ -280,4 +296,90 @@ public class ShellUserGroupProviderIT extends ShellUserGroupProviderBase {
|
|||
}
|
||||
|
||||
// TODO: Make test which retrieves list of users and then getUserByIdentity to ensure the user is populated in the response
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ensures that the test can run because Docker is available and the remote instance can be reached via ssh.
|
||||
*
|
||||
* @return true if Docker is available on this OS
|
||||
*/
|
||||
private boolean isSSHAvailable() {
|
||||
return !systemCheckFailed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting its users and checking minimum size.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
private void verifyUsersAndUsersMinimumCount(UserGroupProvider provider) {
|
||||
Assume.assumeTrue(isSSHAvailable());
|
||||
|
||||
Set<User> users = provider.getUsers();
|
||||
|
||||
// This shows that we don't have any users matching the exclude regex, which is likely because those users
|
||||
// exist but were excluded:
|
||||
for (User user : users) {
|
||||
Assert.assertFalse(user.getIdentifier().startsWith("s"));
|
||||
}
|
||||
|
||||
Assert.assertNotNull(users);
|
||||
Assert.assertTrue(users.size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known user by id.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
private void verifyKnownUserByUsername(UserGroupProvider provider) {
|
||||
Assume.assumeTrue(isSSHAvailable());
|
||||
|
||||
User root = provider.getUserByIdentity(KNOWN_USER);
|
||||
Assert.assertNotNull(root);
|
||||
Assert.assertEquals(KNOWN_USER, root.getIdentity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting its groups and checking minimum size.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
private void verifyGroupsAndMinimumGroupCount(UserGroupProvider provider) {
|
||||
Assume.assumeTrue(isSSHAvailable());
|
||||
|
||||
Set<Group> groups = provider.getGroups();
|
||||
|
||||
// This shows that we don't have any groups matching the exclude regex, which is likely because those groups
|
||||
// exist but were excluded:
|
||||
for (Group group : groups) {
|
||||
Assert.assertFalse(group.getName().endsWith("d"));
|
||||
}
|
||||
|
||||
Assert.assertNotNull(groups);
|
||||
Assert.assertTrue(groups.size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provider behavior by getting a known user and checking its group membership.
|
||||
*
|
||||
* @param provider {@link UserGroupProvider}
|
||||
*/
|
||||
private void verifyGetUserByIdentityAndGetGroupMembership(UserGroupProvider provider) {
|
||||
Assume.assumeTrue(isSSHAvailable());
|
||||
|
||||
UserAndGroups user = provider.getUserAndGroups(KNOWN_USER);
|
||||
Assert.assertNotNull(user);
|
||||
|
||||
try {
|
||||
Assert.assertTrue(user.getGroups().size() > 0);
|
||||
logger.info("root user group count: " + user.getGroups().size());
|
||||
} catch (final AssertionError ignored) {
|
||||
logger.info("root user and groups group count zero on this system");
|
||||
}
|
||||
|
||||
Set<Group> groups = provider.getGroups();
|
||||
Assert.assertTrue(groups.size() > user.getGroups().size());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue