/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.diqube.itest.tests; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; import org.diqube.config.ConfigKey; import org.diqube.itest.AbstractDiqubeIntegrationTest; import org.diqube.itest.annotations.NeedsServer; import org.diqube.itest.util.IdentityCallbackServiceTestUtil; import org.diqube.itest.util.IdentityCallbackServiceTestUtil.TestIdentityCallbackService; import org.diqube.itest.util.Waiter; import org.diqube.remote.query.thrift.TicketInfo; import org.diqube.thrift.base.thrift.AuthenticationException; import org.diqube.thrift.base.thrift.Ticket; import org.testng.Assert; import org.testng.annotations.Test; /** * Integration test for login/logout mechanisms. * * @author Bastian Gloeckle */ public class LoginLogoutIntegrationTest extends AbstractDiqubeIntegrationTest { private static final String ROOT_PASSWORD = "diqube"; private static final String ROOT_USER = "root"; private static final String TEST_USER = "test"; private static final String TEST_PASSWORD = "test"; @Test @NeedsServer(servers = 2, manualStart = true) public void addUserAndLoginLogoutTest() { serverControl.get(0).start(p -> { p.setProperty(ConfigKey.SUPERUSER, ROOT_USER); p.setProperty(ConfigKey.SUPERUSER_PASSWORD, ROOT_PASSWORD); }); serverControl.get(1).start(p -> { p.setProperty(ConfigKey.SUPERUSER, ROOT_USER); p.setProperty(ConfigKey.SUPERUSER_PASSWORD, ROOT_PASSWORD); }); serverControl.get(0).getSerivceTestUtil().identityService(identityService -> { Ticket rootTicket = identityService.login(ROOT_USER, ROOT_PASSWORD); Assert.assertNotNull(rootTicket, "Expected valid rootTicket"); identityService.createUser(rootTicket, TEST_USER, "", TEST_PASSWORD); Ticket testTicket = identityService.login(TEST_USER, TEST_PASSWORD); Assert.assertNotNull(testTicket, "Expected valid testTicket"); identityService.getPermissions(testTicket, TEST_USER); // expected: no authentication exception identityService.logout(testTicket); try { identityService.getPermissions(testTicket, TEST_USER); Assert.fail("Expected to get an authentication exception"); } catch (AuthenticationException e) { } }); } @Test @NeedsServer(servers = 2, manualStart = true) public void logoutCallbackIsCalledAndInvalidatedTicketIsAvailable() throws IOException { serverControl.get(0).start(p -> { p.setProperty(ConfigKey.SUPERUSER, ROOT_USER); p.setProperty(ConfigKey.SUPERUSER_PASSWORD, ROOT_PASSWORD); }); serverControl.get(1).start(p -> { p.setProperty(ConfigKey.SUPERUSER, ROOT_USER); p.setProperty(ConfigKey.SUPERUSER_PASSWORD, ROOT_PASSWORD); }); try (TestIdentityCallbackService callbackServ = IdentityCallbackServiceTestUtil.createIdentityCallbackService()) { serverControl.get(0).getSerivceTestUtil().identityService(identityService -> { Ticket rootTicket = identityService.login(ROOT_USER, ROOT_PASSWORD); Assert.assertNotNull(rootTicket, "Expected valid rootTicket"); identityService.createUser(rootTicket, TEST_USER, "", TEST_PASSWORD); Ticket testTicket = identityService.login(TEST_USER, TEST_PASSWORD); Assert.assertNotNull(testTicket, "Expected valid testTicket"); identityService.registerCallback(callbackServ.getThisServicesAddr().toRNodeAddress()); identityService.logout(testTicket); // we should receive the invalidation event at least twice: Once the quick-send in IdentityHandler#logout and // then the one when the logout is being applied to LogoutStateMachine! new Waiter().waitUntil("Logout event captured on callback service (twice)", 10, 200, () -> callbackServ.getInvalidTickets().size() >= 2); // validate correct ticket was invalidated Set<TicketInfo> invalidTicketSet = new HashSet<>(callbackServ.getInvalidTickets()); Assert.assertEquals(invalidTicketSet.size(), 1, "Expected correct number of distinct invalid tickets."); TicketInfo invalidInfo = invalidTicketSet.iterator().next(); Assert.assertEquals(invalidInfo.getTicketId(), testTicket.getClaim().getTicketId(), "Expected correct invalidated ticket ID."); Assert.assertEquals(invalidInfo.getValidUntil(), testTicket.getClaim().getValidUntil(), "Expected correct invalidated 'valid until'."); // check that the correct invalidated ticket is returned by IdentityService#getInvalidTickets, too. List<TicketInfo> serviceInvalidTickets = identityService.getInvalidTicketInfos(); Assert.assertEquals(serviceInvalidTickets, invalidTicketSet, "Expected to get correc result when calling IdentityService#getInvalidTicketInfos."); }); } } }