package org.keycloak.testsuite.sssd;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import javax.ws.rs.core.Response;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.jboss.arquillian.graphene.page.Page;
import org.jboss.logging.Logger;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.common.constants.GenericConstants;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.pages.AccountPasswordPage;
import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.util.LDAPTestConfiguration;
import com.beust.jcommander.internal.Lists;
public class SSSDTest extends AbstractKeycloakTest {
private static final Logger log = Logger.getLogger(SSSDTest.class);
private static final String DISPLAY_NAME = "Test user federation";
private static final String PROVIDER_NAME = "sssd";
private static final String REALM_NAME = "test";
private static final String sssdConfigPath = "sssd/sssd.properties";
private static final String DISABLED_USER = "disabled";
private static final String NO_EMAIL_USER = "noemail";
private static final String ADMIN_USER = "admin";
private static PropertiesConfiguration sssdConfig;
@Page
protected LoginPage accountLoginPage;
@Page
protected AccountPasswordPage changePasswordPage;
@Page
protected AccountUpdateProfilePage profilePage;
@Rule
public AssertEvents events = new AssertEvents(this);
private String SSSDFederationID;
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_NAME);
realm.setEnabled(true);
testRealms.add(realm);
}
@BeforeClass
public static void loadSSSDConfiguration() throws ConfigurationException {
log.info("Reading SSSD configuration from classpath from: " + sssdConfigPath);
InputStream is = SSSDTest.class.getClassLoader().getResourceAsStream(sssdConfigPath);
sssdConfig = new PropertiesConfiguration();
sssdConfig.load(is);
sssdConfig.setListDelimiter(',');
}
@Before
public void createUserFederation() {
ComponentRepresentation userFederation = new ComponentRepresentation();
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
userFederation.setConfig(config);
userFederation.setName(DISPLAY_NAME);
userFederation.getConfig().putSingle("priority", "0");
userFederation.setProviderType(UserStorageProvider.class.getName());
userFederation.setProviderId(PROVIDER_NAME);
Response response = adminClient.realm(REALM_NAME).components().add(userFederation);
SSSDFederationID = ApiUtil.getCreatedId(response);
response.close();
}
@Test
public void testInvalidPassword() {
String username = getUsername();
log.debug("Testing invalid password for user " + username);
profilePage.open();
Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
accountLoginPage.login(username, "invalid-password");
Assert.assertEquals("Invalid username or password.", accountLoginPage.getError());
}
@Test
public void testDisabledUser() {
String username = getUser(DISABLED_USER);
Assume.assumeTrue("Ignoring test no disabled user configured", username != null);
log.debug("Testing disabled user " + username);
profilePage.open();
Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
accountLoginPage.login(username, getPassword(username));
Assert.assertEquals("Invalid username or password.", accountLoginPage.getError());
}
@Test
public void testAdmin() {
String username = getUser(ADMIN_USER);
Assume.assumeTrue("Ignoring test no admin user configured", username != null);
log.debug("Testing password for user " + username);
profilePage.open();
Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
accountLoginPage.login(username, getPassword(username));
Assert.assertTrue(profilePage.isCurrent());
}
@Test
public void testExistingUserLogIn() {
log.debug("Testing correct password");
for (String username : getUsernames()) {
profilePage.open();
Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
accountLoginPage.login(username, getPassword(username));
Assert.assertTrue(profilePage.isCurrent());
verifyUserGroups(username, getGroups(username));
profilePage.logout();
}
}
@Test
public void testExistingUserWithNoEmailLogIn() {
log.debug("Testing correct password, but no e-mail provided");
String username = getUser(NO_EMAIL_USER);
profilePage.open();
Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
accountLoginPage.login(username, getPassword(username));
Assert.assertTrue(profilePage.isCurrent());
}
@Test
public void testDeleteSSSDFederationProvider() {
log.debug("Testing correct password");
profilePage.open();
String username = getUsername();
Assert.assertEquals("Browser should be on login page now", "Log in to " + REALM_NAME, driver.getTitle());
accountLoginPage.login(username, getPassword(username));
Assert.assertTrue(profilePage.isCurrent());
verifyUserGroups(username, getGroups(username));
int componentsListSize = adminClient.realm(REALM_NAME).components().query().size();
adminClient.realm(REALM_NAME).components().component(SSSDFederationID).remove();
Assert.assertEquals(componentsListSize - 1, adminClient.realm(REALM_NAME).components().query().size());
}
@Test
public void changeReadOnlyProfile() throws Exception {
String username = getUsername();
profilePage.open();
accountLoginPage.login(username, getPassword(username));
Assert.assertEquals(username, profilePage.getUsername());
Assert.assertEquals(sssdConfig.getProperty("user." + username + ".firstname"), profilePage.getFirstName());
Assert.assertEquals(sssdConfig.getProperty("user." + username + ".lastname"), profilePage.getLastName());
Assert.assertEquals(sssdConfig.getProperty("user." + username + ".mail"), profilePage.getEmail());
profilePage.updateProfile("New first", "New last", "new@email.com");
Assert.assertEquals("You can't update your account as it is read only.", profilePage.getError());
}
@Test
public void changeReadOnlyPassword() {
String username = getUsername();
changePasswordPage.open();
accountLoginPage.login(username, getPassword(username));
changePasswordPage.changePassword(getPassword(username), "new-password", "new-password");
Assert.assertEquals("You can't update your password as your account is read only.", profilePage.getError());
}
private void verifyUserGroups(String username, List<String> groups) {
List<UserRepresentation> users = adminClient.realm(REALM_NAME).users().search(username, 0, 1);
Assert.assertTrue("There must be at least one user", users.size() > 0);
Assert.assertEquals("Exactly our test user", username, users.get(0).getUsername());
List<GroupRepresentation> assignedGroups = adminClient.realm(REALM_NAME).users().get(users.get(0).getId()).groups();
Assert.assertEquals("User must have exactly " + groups.size() + " groups", groups.size(), assignedGroups.size());
for (GroupRepresentation group : assignedGroups) {
Assert.assertTrue(groups.contains(group.getName()));
}
}
private String getUsername() {
return sssdConfig.getStringArray("usernames")[0];
}
private String getUser(String type) {
return sssdConfig.getString("user." + type);
}
private List<String> getUsernames() {
return Lists.newArrayList(sssdConfig.getStringArray("usernames"));
}
private String getPassword(String username) {
return sssdConfig.getString("user." + username + ".password");
}
private List<String> getGroups(String username) {
return Lists.newArrayList(sssdConfig.getStringArray("user." + username + ".groups"));
}
}