Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Authorization tests to Spar regarding Scim User management #620

Merged
merged 5 commits into from
Feb 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions services/spar/test-integration/Test/Spar/Scim/AuthSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import Spar.Scim
import Spar.Types (ScimTokenInfo(..))
import Util

import qualified Galley.Types.Teams as Galley

-- | Tests for authentication and operations with provisioning tokens ('ScimToken's).
spec :: SpecWith TestEnv
spec = do
Expand All @@ -31,6 +33,7 @@ specCreateToken = describe "POST /auth-tokens" $ do
it "works" $ testCreateToken
it "respects the token limit" $ testTokenLimit
it "requires the team to have an IdP" $ testIdPIsNeeded
it "authorizes only team owner" $ testCreateTokenAuthorizesOnlyTeamOwner

-- | Test that token creation is sane:
--
Expand Down Expand Up @@ -82,6 +85,28 @@ testIdPIsNeeded = do
(env ^. teSpar)
!!! const 400 === statusCode

-- | Test that a token can only be created as a team owner
testCreateTokenAuthorizesOnlyTeamOwner :: TestSpar ()
testCreateTokenAuthorizesOnlyTeamOwner =
do
env <- ask
(_, teamId,_) <- registerTestIdP
teamMemberId <- runHttpT (env ^. teMgr)
$ createTeamMember
(env ^. teBrig)
(env ^. teGalley)
teamId
(Galley.rolePermissions Galley.RoleMember)
createToken_
teamMemberId
(CreateScimToken
{ createScimTokenDescr = "testCreateToken"
})
(env ^. teSpar)
!!! const 403
=== statusCode


----------------------------------------------------------------------------
-- Token listing

Expand Down
78 changes: 78 additions & 0 deletions services/spar/test-integration/Test/Spar/Scim/UserSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ specCreateUser :: SpecWith TestEnv
specCreateUser = describe "POST /Users" $ do
it "creates a user in an existing team" $ testCreateUser
it "requires externalId to be present" $ testExternalIdIsRequired
it "rejects invalid handle" $ testCreateRejectsInvalidHandle
it "rejects occupied handle" $ testCreateRejectsTakenHandle
it "gives created user a valid 'SAML.UserRef' for SSO" $ pending
it "attributes of {brig, scim, saml} user are mapped as documented" $ pending
it "writes all the stuff to all the places" $
Expand Down Expand Up @@ -83,6 +85,39 @@ testExternalIdIsRequired = do
createUser_ (Just tok) user' (env ^. teSpar)
!!! const 400 === statusCode

-- | Test that user creation fails if handle is invalid
testCreateRejectsInvalidHandle :: TestSpar ()
testCreateRejectsInvalidHandle = do
env <- ask
-- Create a user via SCIM
user <- randomScimUser
(tok, _) <- registerIdPAndScimToken
createUser_ (Just tok) (user{Scim.User.userName="#invalid name"}) (env ^. teSpar)
!!! const 400 === statusCode

-- | Test that user creation fails if handle is already in use (even on different team).
testCreateRejectsTakenHandle :: TestSpar ()
testCreateRejectsTakenHandle = do
env <- ask

user1 <- randomScimUser
user2 <- randomScimUser
user3 <- randomScimUser
(tokTeamA, _) <- registerIdPAndScimToken
(tokTeamB, _) <- registerIdPAndScimToken

-- Create and add a first user: success!
createUser_ (Just tokTeamA) user1 (env ^. teSpar)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use createUser here.

!!! const 201 === statusCode

-- Try to create different user with same handle in same team.
createUser_ (Just tokTeamA) (user2 { Scim.User.userName = Scim.User.userName user1 }) (env ^. teSpar)
!!! const 409 === statusCode

-- Try to create different user with same handle in different team.
createUser_ (Just tokTeamB) (user3 { Scim.User.userName = Scim.User.userName user1 }) (env ^. teSpar)
!!! const 409 === statusCode

----------------------------------------------------------------------------
-- Listing users

Expand All @@ -93,6 +128,7 @@ specListUsers = describe "GET /Users" $ do
it "finds a SCIM-provisioned user by username" $ pending
it "finds a non-SCIM-provisioned user by username" $ pending
it "doesn't list deleted users" $ testListNoDeletedUsers
it "doesn't find users from other teams" $ testUserListFailsWithNotFoundIfOutsideTeam

-- | Test that SCIM-provisioned team members are listed, and users that were not provisioned
-- via SCIM are not listed.
Expand Down Expand Up @@ -125,6 +161,17 @@ testListNoDeletedUsers = do
-- Check that the user is absent
liftIO $ users `shouldSatisfy` all ((/= userid) . scimUserId)

-- | Test that users are not listed if not in the team associated with the token.
testUserListFailsWithNotFoundIfOutsideTeam :: TestSpar ()
testUserListFailsWithNotFoundIfOutsideTeam = do
user <- randomScimUser
(tokTeamA, _) <- registerIdPAndScimToken
(tokTeamB, _) <- registerIdPAndScimToken
storedUser <- createUser tokTeamA user
let userid = scimUserId storedUser
users <- listUsers tokTeamB Nothing
liftIO $ users `shouldSatisfy` all ((/= userid) . scimUserId)

----------------------------------------------------------------------------
-- Fetching a single user

Expand All @@ -141,6 +188,7 @@ specGetUser = describe "GET /Users/:id" $ do
-- create another team and another user in it
-- check that this user can not be found in the "wrong" team
it "doesn't find a deleted user" $ testGetNoDeletedUsers
it "doesn't find users from other teams" $ testUserGetFailsWithNotFoundIfOutsideTeam

-- | Test that a SCIM-provisioned user is fetchable.
testGetUser :: TestSpar ()
Expand Down Expand Up @@ -169,6 +217,19 @@ testGetNoDeletedUsers = do
!!! const 404 === statusCode
pendingWith "TODO: delete via SCIM"

-- | Test that gets are not allowed if token is not for the user's team
testUserGetFailsWithNotFoundIfOutsideTeam :: TestSpar ()
testUserGetFailsWithNotFoundIfOutsideTeam = do
env <- ask
user <- randomScimUser
(tokTeamA, _) <- registerIdPAndScimToken
(tokTeamB, _) <- registerIdPAndScimToken
storedUser <- createUser tokTeamA user
let userid = scimUserId storedUser
getUser_ (Just tokTeamB) userid (env ^. teSpar)
!!! const 404 === statusCode


{- does not find a non-scim-provisioned user:

env <- ask
Expand All @@ -195,6 +256,8 @@ specUpdateUser = describe "PUT /Users/:id" $ do
it "works fine when neither name nor handle are changed" $ testUpdateSameHandle
it "updates the 'SAML.UserRef' index in Spar" $ testUpdateUserRefIndex
it "updates the matching Brig user" $ testBrigSideIsUpdated
context "user is from different team" $ do
it "fails to update user with 404" testUserUpdateFailsWithNotFoundIfOutsideTeam
context "scim_user has no entry with this id" $ do
it "fails" $ pending
context "brig user is updated" $ do
Expand All @@ -213,6 +276,21 @@ testUpdateRequiresUserId = do
updateUser_ (Just tok) Nothing user (env ^. teSpar)
!!! assertTrue_ (inRange (400, 499) . statusCode)

-- | Test that updates are not allowed if token is not for the user's team
testUserUpdateFailsWithNotFoundIfOutsideTeam :: TestSpar ()
testUserUpdateFailsWithNotFoundIfOutsideTeam = do
env <- ask
-- Create a user via SCIM
user <- randomScimUser
(tokTeamA, _) <- registerIdPAndScimToken
(tokTeamB, _) <- registerIdPAndScimToken
storedUser <- createUser tokTeamA user
let userid = scimUserId storedUser
-- Overwrite the user with another randomly-generated user
user' <- randomScimUser
updateUser_ (Just tokTeamB) (Just userid) user' (env ^. teSpar)
!!! const 404 === statusCode

-- | Test that @PUT@-ting the user and then @GET@-ting it returns the right thing.
testScimSideIsUpdated :: TestSpar ()
testScimSideIsUpdated = do
Expand Down