| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- package login
- import (
- "errors"
- "testing"
- . "github.com/smartystreets/goconvey/convey"
- "github.com/grafana/grafana/pkg/models"
- "github.com/grafana/grafana/pkg/services/ldap"
- )
- func TestAuthenticateUser(t *testing.T) {
- Convey("Authenticate user", t, func() {
- authScenario("When a user authenticates without setting a password", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(nil, sc)
- mockLoginUsingLDAP(false, nil, sc)
- loginQuery := models.LoginUserQuery{
- Username: "user",
- Password: "",
- }
- err := AuthenticateUser(&loginQuery)
- Convey("login should fail", func() {
- So(sc.grafanaLoginWasCalled, ShouldBeFalse)
- So(sc.ldapLoginWasCalled, ShouldBeFalse)
- So(err, ShouldEqual, ErrPasswordEmpty)
- })
- })
- authScenario("When a user authenticates having too many login attempts", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(ErrTooManyLoginAttempts, sc)
- mockLoginUsingGrafanaDB(nil, sc)
- mockLoginUsingLDAP(true, nil, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, ErrTooManyLoginAttempts)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeFalse)
- So(sc.ldapLoginWasCalled, ShouldBeFalse)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeFalse)
- })
- })
- authScenario("When grafana user authenticate with valid credentials", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(nil, sc)
- mockLoginUsingLDAP(true, ErrInvalidCredentials, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, nil)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeFalse)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeFalse)
- })
- })
- authScenario("When grafana user authenticate and unexpected error occurs", func(sc *authScenarioContext) {
- customErr := errors.New("custom")
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(customErr, sc)
- mockLoginUsingLDAP(true, ErrInvalidCredentials, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, customErr)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeFalse)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeFalse)
- })
- })
- authScenario("When a non-existing grafana user authenticate and ldap disabled", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(models.ErrUserNotFound, sc)
- mockLoginUsingLDAP(false, nil, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, ErrInvalidCredentials)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeTrue)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeFalse)
- })
- })
- authScenario("When a non-existing grafana user authenticate and invalid ldap credentials", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(models.ErrUserNotFound, sc)
- mockLoginUsingLDAP(true, ldap.ErrInvalidCredentials, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, ErrInvalidCredentials)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeTrue)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeTrue)
- })
- })
- authScenario("When a non-existing grafana user authenticate and valid ldap credentials", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(models.ErrUserNotFound, sc)
- mockLoginUsingLDAP(true, nil, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldBeNil)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeTrue)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeFalse)
- })
- })
- authScenario("When a non-existing grafana user authenticate and ldap returns unexpected error", func(sc *authScenarioContext) {
- customErr := errors.New("custom")
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(models.ErrUserNotFound, sc)
- mockLoginUsingLDAP(true, customErr, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, customErr)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeTrue)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeFalse)
- })
- })
- authScenario("When grafana user authenticate with invalid credentials and invalid ldap credentials", func(sc *authScenarioContext) {
- mockLoginAttemptValidation(nil, sc)
- mockLoginUsingGrafanaDB(ErrInvalidCredentials, sc)
- mockLoginUsingLDAP(true, ldap.ErrInvalidCredentials, sc)
- mockSaveInvalidLoginAttempt(sc)
- err := AuthenticateUser(sc.loginUserQuery)
- Convey("it should result in", func() {
- So(err, ShouldEqual, ErrInvalidCredentials)
- So(sc.loginAttemptValidationWasCalled, ShouldBeTrue)
- So(sc.grafanaLoginWasCalled, ShouldBeTrue)
- So(sc.ldapLoginWasCalled, ShouldBeTrue)
- So(sc.saveInvalidLoginAttemptWasCalled, ShouldBeTrue)
- })
- })
- })
- }
- type authScenarioContext struct {
- loginUserQuery *models.LoginUserQuery
- grafanaLoginWasCalled bool
- ldapLoginWasCalled bool
- loginAttemptValidationWasCalled bool
- saveInvalidLoginAttemptWasCalled bool
- }
- type authScenarioFunc func(sc *authScenarioContext)
- func mockLoginUsingGrafanaDB(err error, sc *authScenarioContext) {
- loginUsingGrafanaDB = func(query *models.LoginUserQuery) error {
- sc.grafanaLoginWasCalled = true
- return err
- }
- }
- func mockLoginUsingLDAP(enabled bool, err error, sc *authScenarioContext) {
- loginUsingLDAP = func(query *models.LoginUserQuery) (bool, error) {
- sc.ldapLoginWasCalled = true
- return enabled, err
- }
- }
- func mockLoginAttemptValidation(err error, sc *authScenarioContext) {
- validateLoginAttempts = func(username string) error {
- sc.loginAttemptValidationWasCalled = true
- return err
- }
- }
- func mockSaveInvalidLoginAttempt(sc *authScenarioContext) {
- saveInvalidLoginAttempt = func(query *models.LoginUserQuery) {
- sc.saveInvalidLoginAttemptWasCalled = true
- }
- }
- func authScenario(desc string, fn authScenarioFunc) {
- Convey(desc, func() {
- origLoginUsingGrafanaDB := loginUsingGrafanaDB
- origLoginUsingLDAP := loginUsingLDAP
- origValidateLoginAttempts := validateLoginAttempts
- origSaveInvalidLoginAttempt := saveInvalidLoginAttempt
- sc := &authScenarioContext{
- loginUserQuery: &models.LoginUserQuery{
- Username: "user",
- Password: "pwd",
- IpAddress: "192.168.1.1:56433",
- },
- }
- defer func() {
- loginUsingGrafanaDB = origLoginUsingGrafanaDB
- loginUsingLDAP = origLoginUsingLDAP
- validateLoginAttempts = origValidateLoginAttempts
- saveInvalidLoginAttempt = origSaveInvalidLoginAttempt
- }()
- fn(sc)
- })
- }
|