github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/systests/sbs_test.go (about) 1 package systests 2 3 import ( 4 "testing" 5 6 "github.com/keybase/client/go/teams" 7 8 "github.com/keybase/client/go/emails" 9 10 "github.com/keybase/client/go/externals" 11 "github.com/keybase/client/go/kbtest" 12 "github.com/keybase/client/go/libkb" 13 "github.com/keybase/client/go/phonenumbers" 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 "github.com/stretchr/testify/require" 16 context "golang.org/x/net/context" 17 ) 18 19 func assertionFromKV(t *testing.T, key, value string) libkb.AssertionURL { 20 actx := externals.MakeStaticAssertionContext(context.TODO()) 21 ret, err := libkb.ParseAssertionURLKeyValue(actx, key, value, true /* strict */) 22 require.NoError(t, err) 23 return ret 24 } 25 26 // Same SBS test can run against different SBS types, where each one has 27 // different way of proving (verifying), revoking etc. Encapsulate all that 28 // under a type that implements `userSBSProvider` and pass it to the "generic" 29 // SBS test function. 30 type userSBSProvider interface { 31 SetUser(user *userPlusDevice) 32 GetAssertionKV() (key string, value string) 33 Verify() 34 Revoke() 35 } 36 37 // Phone numbers 38 type userSBSPhoneNumber struct { 39 u *userPlusDevice 40 phoneNumber string // without `+` 41 } 42 43 func (p *userSBSPhoneNumber) SetUser(user *userPlusDevice) { 44 p.u = user 45 p.phoneNumber = kbtest.GenerateTestPhoneNumber() 46 } 47 48 func (p *userSBSPhoneNumber) GetAssertionKV() (key string, value string) { 49 return "phone", p.phoneNumber 50 } 51 52 func (p *userSBSPhoneNumber) Verify() { 53 mctx := p.u.MetaContext() 54 tctx := p.u.tc 55 phoneNumber := keybase1.PhoneNumber("+" + p.phoneNumber) 56 require.NoError(tctx.T, phonenumbers.AddPhoneNumber(mctx, phoneNumber, keybase1.IdentityVisibility_PUBLIC)) 57 code, err := kbtest.GetPhoneVerificationCode(libkb.NewMetaContextTODO(tctx.G), phoneNumber) 58 require.NoError(tctx.T, err) 59 require.NoError(tctx.T, phonenumbers.VerifyPhoneNumber(mctx, phoneNumber, code)) 60 } 61 62 func (p *userSBSPhoneNumber) Revoke() { 63 err := phonenumbers.DeletePhoneNumber(p.u.MetaContext(), keybase1.PhoneNumber("+"+p.phoneNumber)) 64 require.NoError(p.u.tc.T, err) 65 } 66 67 // ------------------ 68 69 // Emails 70 type userSBSEmail struct { 71 u *userPlusDevice 72 } 73 74 func (p *userSBSEmail) SetUser(user *userPlusDevice) { 75 p.u = user 76 } 77 78 func (p *userSBSEmail) GetAssertionKV() (key string, value string) { 79 return "email", p.u.userInfo.email 80 } 81 82 func (p *userSBSEmail) Verify() { 83 emailAddress := keybase1.EmailAddress(p.u.userInfo.email) 84 err := emails.SetVisibilityEmail(p.u.MetaContext(), emailAddress, keybase1.IdentityVisibility_PUBLIC) 85 require.NoError(p.u.tc.T, err) 86 err = kbtest.VerifyEmailAuto(p.u.MetaContext(), emailAddress) 87 require.NoError(p.u.tc.T, err) 88 } 89 90 func (p *userSBSEmail) Revoke() { 91 err := emails.DeleteEmail(p.u.MetaContext(), keybase1.EmailAddress(p.u.userInfo.email)) 92 require.NoError(p.u.tc.T, err) 93 } 94 95 // ------------------ 96 97 // Rooter 98 type userSBSRooter struct { 99 u *userPlusDevice 100 } 101 102 func (p *userSBSRooter) SetUser(user *userPlusDevice) { 103 p.u = user 104 } 105 106 func (p *userSBSRooter) GetAssertionKV() (key string, value string) { 107 return "rooter", p.u.username 108 } 109 110 func (p *userSBSRooter) Verify() { 111 p.u.proveRooter() 112 } 113 114 func (p *userSBSRooter) Revoke() { 115 p.u.revokeServiceProof("rooter") 116 } 117 118 // ------------------ 119 120 func testTeamInviteSBS(t *testing.T, sbs userSBSProvider) { 121 tt := newTeamTester(t) 122 defer tt.cleanup() 123 124 ann := tt.addUser("ann") 125 bob := tt.addUser("bob") 126 sbs.SetUser(bob) 127 128 // User 0 creates a team. 129 teamID, teamName := ann.createTeam2() 130 131 key, value := sbs.GetAssertionKV() 132 assertionURL := assertionFromKV(t, key, value) 133 assertion := assertionURL.String() 134 135 ann.addTeamMember(teamName.String(), assertion, keybase1.TeamRole_WRITER) 136 137 ann.kickTeamRekeyd() 138 sbs.Verify() 139 140 ann.waitForTeamChangedGregor(teamID, keybase1.Seqno(3)) 141 bob.waitForTeamChangedGregor(teamID, keybase1.Seqno(3)) 142 143 // The team should have user 1 in it now as a writer. 144 t0 := ann.loadTeam(teamName.String(), true /* admin */) 145 writers, err := t0.UsersWithRole(keybase1.TeamRole_WRITER) 146 require.NoError(t, err) 147 require.Len(t, writers, 1) 148 require.Equal(t, bob.uid, writers[0].Uid) 149 150 // The invite should not be in the active invite map. 151 require.Equal(t, 0, t0.NumActiveInvites()) 152 exists, err := t0.HasActiveInvite(tt.users[0].tc.MetaContext(), keybase1.TeamInviteName(value), key) 153 require.NoError(t, err) 154 require.False(t, exists, "after accepting invite, active invite shouldn't exist") 155 } 156 157 func TestTeamInviteSBSPhone(t *testing.T) { 158 testTeamInviteSBS(t, &userSBSPhoneNumber{}) 159 } 160 161 func TestTeamInviteSBSEmail(t *testing.T) { 162 testTeamInviteSBS(t, &userSBSEmail{}) 163 } 164 165 func TestTeamInviteSBSRooter(t *testing.T) { 166 testTeamInviteSBS(t, &userSBSRooter{}) 167 } 168 169 // ------------------ 170 171 func testTeamInviteExistingUserSBS(t *testing.T, sbs userSBSProvider) { 172 tt := newTeamTester(t) 173 defer tt.cleanup() 174 175 ann := tt.addUser("ann") 176 bob := tt.addUser("bob") 177 sbs.SetUser(bob) 178 179 key, value := sbs.GetAssertionKV() 180 assertionURL := assertionFromKV(t, key, value) 181 assertion := assertionURL.String() 182 183 sbs.Verify() 184 185 // User 0 creates a team. 186 _, teamName := ann.createTeam2() 187 188 // Add bob by SBS assertion. Should just add bob and not an invite. Adding 189 // resolvable SBS assertion via invite would also bounce off the server 190 // with `TEAM_INVITE_USER_EXISTS` error. 191 ann.addTeamMember(teamName.String(), assertion, keybase1.TeamRole_WRITER) 192 193 // The team should have user 1 in it now as a writer. 194 t0 := ann.loadTeam(teamName.String(), true /* admin */) 195 writers, err := t0.UsersWithRole(keybase1.TeamRole_WRITER) 196 require.NoError(t, err) 197 require.Len(t, writers, 1) 198 require.Equal(t, bob.uid, writers[0].Uid) 199 200 // There should be no invite for the SBS. 201 require.Equal(t, 0, t0.NumActiveInvites()) 202 exists, err := t0.HasActiveInvite(tt.users[0].tc.MetaContext(), keybase1.TeamInviteName(value), key) 203 require.NoError(t, err) 204 require.False(t, exists, "after adding resolvable assertion, no invite should have been created") 205 } 206 207 func TestTeamInviteExistingUserSBSPhone(t *testing.T) { 208 testTeamInviteExistingUserSBS(t, &userSBSPhoneNumber{}) 209 } 210 211 func TestTeamInviteExistingUserSBSEmail(t *testing.T) { 212 testTeamInviteExistingUserSBS(t, &userSBSEmail{}) 213 } 214 215 func TestTeamInviteExistingUserSBSRooter(t *testing.T) { 216 testTeamInviteExistingUserSBS(t, &userSBSRooter{}) 217 } 218 219 // ------------------ 220 221 func TestTeamInviteSBSError(t *testing.T) { 222 // Make sure we can't add invites for assertions if we can't attempt to 223 // resolve them. 224 225 tt := newTeamTester(t) 226 defer tt.cleanup() 227 228 ann := tt.addUser("ann") 229 bob := tt.addUser("bob") 230 231 ann.disableTOFUSearch() 232 233 teamID, teamName := ann.createTeam2() 234 235 sbsProviders := []userSBSProvider{ 236 &userSBSEmail{}, 237 &userSBSPhoneNumber{}, 238 } 239 240 for _, sbs := range sbsProviders { 241 sbs.SetUser(bob) 242 sbs.Verify() 243 244 key, value := sbs.GetAssertionKV() 245 assertionURL := assertionFromKV(t, key, value) 246 assertion := assertionURL.String() 247 248 _, err := teams.AddMemberByID(context.TODO(), ann.tc.G, teamID, assertion, keybase1.TeamRole_WRITER, nil, nil /* emailInviteMsg */) 249 require.Error(t, err) 250 require.Contains(t, err.Error(), "error 602") // user cannot search for assertions 251 } 252 253 t0 := ann.loadTeam(teamName.String(), true /* admin */) 254 require.Equal(t, 0, t0.NumActiveInvites()) 255 }