blob: b4d230e3cd60d5e8c0e4b444acba0263dae55084 [file] [log] [blame]
/*
* 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.cloudstack.api.command;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.response.LoginCmdResponse;
import org.apache.cloudstack.saml.SAML2AuthManager;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.HttpUtils;
import junit.framework.TestCase;
@RunWith(MockitoJUnitRunner.class)
public class ListAndSwitchSAMLAccountCmdTest extends TestCase {
@Mock
ApiServerService apiServer;
@Mock
SAML2AuthManager samlAuthManager;
@Mock
AccountService accountService;
@Mock
UserAccountDao userAccountDao;
@Mock
UserDao userDao;
@Mock
DomainDao domainDao;
@Mock
HttpSession session;
@Mock
HttpServletResponse resp;
@Mock
HttpServletRequest req;
@Test
public void testListAndSwitchSAMLAccountCmd() throws Exception {
// Setup
final Map<String, Object[]> params = new HashMap<String, Object[]>();
final String sessionKeyValue = "someSessionIDValue";
Mockito.when(session.getAttribute(ApiConstants.SESSIONKEY)).thenReturn(sessionKeyValue);
Mockito.when(session.getAttribute("userid")).thenReturn(2L);
params.put(ApiConstants.USER_ID, new String[]{"2"});
params.put(ApiConstants.DOMAIN_ID, new String[]{"1"});
Mockito.when(userDao.findByUuid(anyString())).thenReturn(new UserVO(2L));
Mockito.when(domainDao.findByUuid(anyString())).thenReturn(new DomainVO());
// Mock/field setup
ListAndSwitchSAMLAccountCmd cmd = new ListAndSwitchSAMLAccountCmd();
Field apiServerField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_apiServer");
apiServerField.setAccessible(true);
apiServerField.set(cmd, apiServer);
Field managerField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_samlAuthManager");
managerField.setAccessible(true);
managerField.set(cmd, samlAuthManager);
Field accountServiceField = BaseCmd.class.getDeclaredField("_accountService");
accountServiceField.setAccessible(true);
accountServiceField.set(cmd, accountService);
Field userAccountDaoField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_userAccountDao");
userAccountDaoField.setAccessible(true);
userAccountDaoField.set(cmd, userAccountDao);
Field userDaoField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_userDao");
userDaoField.setAccessible(true);
userDaoField.set(cmd, userDao);
Field domainDaoField = ListAndSwitchSAMLAccountCmd.class.getDeclaredField("_domainDao");
domainDaoField.setAccessible(true);
domainDaoField.set(cmd, domainDao);
// invalid session test
try {
cmd.authenticate("command", params, null, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
} finally {
Mockito.verify(accountService, Mockito.times(0)).getUserAccountById(Mockito.anyLong());
}
// invalid sessionkey value test
params.put(ApiConstants.SESSIONKEY, new String[]{"someOtherValue"});
try {
Mockito.when(session.isNew()).thenReturn(false);
cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
} finally {
Mockito.verify(accountService, Mockito.times(0)).getUserAccountById(Mockito.anyLong());
}
// valid sessionkey value test
params.put(ApiConstants.SESSIONKEY, new String[]{sessionKeyValue});
try {
cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.ACCOUNT_ERROR);
} finally {
Mockito.verify(accountService, Mockito.times(1)).getUserAccountById(Mockito.anyLong());
}
// valid sessionkey, invalid useraccount type (non-saml) value test
UserAccountVO mockedUserAccount = new UserAccountVO();
mockedUserAccount.setId(2L);
mockedUserAccount.setAccountState(Account.State.ENABLED.toString());
mockedUserAccount.setUsername("someUsername");
mockedUserAccount.setExternalEntity("some IDP ID");
mockedUserAccount.setDomainId(0L);
mockedUserAccount.setSource(User.Source.UNKNOWN);
Mockito.when(accountService.getUserAccountById(Mockito.anyLong())).thenReturn(mockedUserAccount);
try {
cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
assertEquals(exception.getErrorCode(), ApiErrorCode.ACCOUNT_ERROR);
} finally {
// accountService should have been called twice by now, for this case and the case above
Mockito.verify(accountService, Mockito.times(2)).getUserAccountById(Mockito.anyLong());
}
// all valid test
mockedUserAccount.setSource(User.Source.SAML2);
Mockito.when(accountService.getUserAccountById(Mockito.anyLong())).thenReturn(mockedUserAccount);
Mockito.when(apiServer.verifyUser(Mockito.anyLong())).thenReturn(true);
LoginCmdResponse loginCmdResponse = new LoginCmdResponse();
loginCmdResponse.setUserId("1");
loginCmdResponse.setDomainId("1");
loginCmdResponse.setType("1");
loginCmdResponse.setUsername("userName");
loginCmdResponse.setAccount("someAccount");
loginCmdResponse.setFirstName("firstName");
loginCmdResponse.setLastName("lastName");
loginCmdResponse.setSessionKey("newSessionKeyString");
loginCmdResponse.set2FAenabled("false");
Mockito.when(apiServer.loginUser(nullable(HttpSession.class), nullable(String.class), nullable(String.class),
nullable(Long.class), nullable(String.class), nullable(InetAddress.class), nullable(Map.class))).thenReturn(loginCmdResponse);
Mockito.doNothing().when(resp).sendRedirect(nullable(String.class));
try {
cmd.authenticate("command", params, session, null, HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
} catch (ServerApiException exception) {
fail("SAML list and switch account API failed to pass for all valid data: " + exception.getMessage());
} finally {
// accountService should have been called 4 times by now, for this case twice and 2 for cases above
Mockito.verify(accountService, Mockito.times(4)).getUserAccountById(Mockito.anyLong());
Mockito.verify(resp, Mockito.times(1)).sendRedirect(anyString());
}
}
@Test
public void testGetAPIType() {
Assert.assertTrue(new ListAndSwitchSAMLAccountCmd().getAPIType() == APIAuthenticationType.READONLY_API);
}
}