blob: 1ff5fce42438ab03b86579ed6786427f6702ef13 [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 groovy.org.apache.cloudstack.ldap
import com.cloud.server.auth.UserAuthenticator
import com.cloud.user.Account
import com.cloud.user.AccountManager
import com.cloud.user.User
import com.cloud.user.UserAccount
import com.cloud.user.UserAccountVO
import com.cloud.user.dao.UserAccountDao
import com.cloud.utils.Pair
import org.apache.cloudstack.ldap.LdapAuthenticator
import org.apache.cloudstack.ldap.LdapManager
import org.apache.cloudstack.ldap.LdapTrustMapVO
import org.apache.cloudstack.ldap.LdapUser
class LdapAuthenticatorSpec extends spock.lang.Specification {
def "Test a failed authentication due to user not being found within cloudstack"() {
given: "We have an LdapManager, userAccountDao and ldapAuthenticator and the user doesn't exist within cloudstack."
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
userAccountDao.getUserAccount(_, _) >> null
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
when: "A user authentications"
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
then: "their authentication fails"
result.first() == false
}
def "Test failed authentication due to ldap bind being unsuccessful"() {
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
def ldapManager = Mock(LdapManager)
def ldapUser = Mock(LdapUser)
ldapUser.isDisabled() >> false
ldapManager.isLdapEnabled() >> true
ldapManager.getUser("rmurphy", null) >> ldapUser
ldapManager.canAuthenticate(_, _, _) >> false
UserAccountDao userAccountDao = Mock(UserAccountDao)
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
when: "The user authenticates with an incorrect password"
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
then: "their authentication fails"
result.first() == false
}
def "Test failed authentication due to ldap not being configured"() {
given: "We have an LdapManager, A configured LDAP server, a userAccountDao and LdapAuthenticator"
def ldapManager = Mock(LdapManager)
ldapManager.isLdapEnabled() >> false
UserAccountDao userAccountDao = Mock(UserAccountDao)
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
when: "The user authenticates"
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
then: "their authentication fails"
result.first() == false
}
def "Test successful authentication"() {
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
def ldapManager = Mock(LdapManager)
def ldapUser = Mock(LdapUser)
ldapUser.isDisabled() >> false
ldapManager.isLdapEnabled() >> true
ldapManager.canAuthenticate(_, _, _) >> true
ldapManager.getUser("rmurphy", null) >> ldapUser
UserAccountDao userAccountDao = Mock(UserAccountDao)
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
when: "The user authenticates with an incorrect password"
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
then: "their authentication passes"
result.first() == true
}
def "Test that encode doesn't change the input"() {
given: "We have an LdapManager, userAccountDao and LdapAuthenticator"
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
when: "a users password is encoded"
def result = ldapAuthenticator.encode("password")
then: "it doesn't change"
result == "password"
}
def "test authentication when ldap is disabled"(){
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
ldapManager.isLdapEnabled() >> false
when:
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate("rajanik", "password", 1, null)
then:
result.first() == false
result.second() == null
}
// tests when domain is linked to LDAP
def "test authentication when domain is linked and user disabled in ldap"(){
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
AccountManager accountManager = Mock(AccountManager)
def ldapAuthenticator = new LdapAuthenticator()
ldapAuthenticator._ldapManager = ldapManager
ldapAuthenticator._userAccountDao = userAccountDao
ldapAuthenticator._accountManager = accountManager
long domainId = 1;
String username = "rajanik"
LdapManager.LinkType type = LdapManager.LinkType.GROUP
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
ldapManager.isLdapEnabled() >> true
UserAccount userAccount = Mock(UserAccount)
userAccountDao.getUserAccount(username, domainId) >> userAccount
userAccount.getId() >> 1
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true, null)
//user should be disabled in cloudstack
accountManager.disableUser(1) >> userAccount
when:
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
then:
result.first() == false
result.second() == UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT
}
def "test authentication when domain is linked and first time user can authenticate in ldap"(){
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
AccountManager accountManager = Mock(AccountManager)
def ldapAuthenticator = new LdapAuthenticator()
ldapAuthenticator._ldapManager = ldapManager
ldapAuthenticator._userAccountDao = userAccountDao
ldapAuthenticator._accountManager = accountManager
long domainId = 1;
String username = "rajanik"
LdapManager.LinkType type = LdapManager.LinkType.GROUP
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
ldapManager.isLdapEnabled() >> true
userAccountDao.getUserAccount(username, domainId) >> null
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)0)
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
ldapManager.canAuthenticate(_, _, _) >> true
//user should be created in cloudstack
accountManager.createUserAccount(username, "", "firstname", "lastname", "email", null, username, (short) 2, domainId, username, null, _, _, User.Source.LDAP) >> Mock(UserAccount)
when:
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
then:
result.first() == true
result.second() == null
}
def "test authentication when domain is linked and existing user can authenticate in ldap"(){
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
AccountManager accountManager = Mock(AccountManager)
def ldapAuthenticator = new LdapAuthenticator()
ldapAuthenticator._ldapManager = ldapManager
ldapAuthenticator._userAccountDao = userAccountDao
ldapAuthenticator._accountManager = accountManager
long domainId = 1;
String username = "rajanik"
LdapManager.LinkType type = LdapManager.LinkType.GROUP
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
ldapManager.isLdapEnabled() >> true
UserAccount userAccount = Mock(UserAccount)
userAccountDao.getUserAccount(username, domainId) >> userAccount
userAccount.getId() >> 1
userAccount.getState() >> Account.State.disabled.toString()
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
ldapManager.canAuthenticate(_, _, _) >> true
//user should be enabled in cloudstack if disabled
accountManager.enableUser(1) >> userAccount
when:
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
then:
result.first() == true
result.second() == null
}
def "test authentication when domain is linked and user cannot authenticate in ldap"(){
LdapManager ldapManager = Mock(LdapManager)
UserAccountDao userAccountDao = Mock(UserAccountDao)
AccountManager accountManager = Mock(AccountManager)
def ldapAuthenticator = new LdapAuthenticator()
ldapAuthenticator._ldapManager = ldapManager
ldapAuthenticator._userAccountDao = userAccountDao
ldapAuthenticator._accountManager = accountManager
long domainId = 1;
String username = "rajanik"
LdapManager.LinkType type = LdapManager.LinkType.GROUP
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
ldapManager.isLdapEnabled() >> true
UserAccount userAccount = Mock(UserAccount)
userAccountDao.getUserAccount(username, domainId) >> userAccount
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
ldapManager.canAuthenticate(_, _, _) >> false
when:
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
then:
result.first() == false
result.second() == UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT
}
}