mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-08-01 04:46:12 +00:00
refactor upstream refresh test helpers to be more specific to IDP type
This commit is contained in:
+5
-5
@@ -344,7 +344,7 @@ func (c *activeDirectoryWatcherController) validateUpstream(ctx context.Context,
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){
|
||||
"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID"),
|
||||
},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
pwdLastSetAttribute: attributeUnchangedSinceLogin(pwdLastSetAttribute),
|
||||
userAccountControlAttribute: validUserAccountControl,
|
||||
userAccountControlComputedAttribute: validComputedUserAccountControl,
|
||||
@@ -445,7 +445,7 @@ func getDomainFromDistinguishedName(distinguishedName string) (string, error) {
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // this needs to be a global variable so that tests can check pointer equality
|
||||
var validUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.RefreshAttributes) error {
|
||||
var validUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.LDAPRefreshAttributes) error {
|
||||
userAccountControl, err := strconv.Atoi(entry.GetAttributeValue(userAccountControlAttribute))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -459,7 +459,7 @@ var validUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.Refresh
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // this needs to be a global variable so that tests can check pointer equality
|
||||
var validComputedUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.RefreshAttributes) error {
|
||||
var validComputedUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.LDAPRefreshAttributes) error {
|
||||
userAccountControl, err := strconv.Atoi(entry.GetAttributeValue(userAccountControlComputedAttribute))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -473,8 +473,8 @@ var validComputedUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // this needs to be a global variable so that tests can check pointer equality
|
||||
var attributeUnchangedSinceLogin = func(attribute string) func(*ldap.Entry, upstreamprovider.RefreshAttributes) error {
|
||||
return func(entry *ldap.Entry, storedAttributes upstreamprovider.RefreshAttributes) error {
|
||||
var attributeUnchangedSinceLogin = func(attribute string) func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error {
|
||||
return func(entry *ldap.Entry, storedAttributes upstreamprovider.LDAPRefreshAttributes) error {
|
||||
prevAttributeValue := storedAttributes.AdditionalAttributes[attribute]
|
||||
newValues := entry.GetRawAttributeValues(attribute)
|
||||
|
||||
|
||||
+20
-20
@@ -228,7 +228,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -571,7 +571,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -641,7 +641,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: "sAMAccountName",
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -714,7 +714,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -794,7 +794,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -858,7 +858,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1009,7 +1009,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1159,7 +1159,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1231,7 +1231,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1498,7 +1498,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
GroupAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"sAMAccountName": groupSAMAccountNameWithDomainSuffix},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1558,7 +1558,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1622,7 +1622,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1686,7 +1686,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1898,7 +1898,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
GroupNameAttribute: testGroupSearchNameAttrName,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -1961,7 +1961,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
SkipGroupRefresh: true,
|
||||
},
|
||||
UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"),
|
||||
"userAccountControl": validUserAccountControl,
|
||||
"msDS-User-Account-Control-Computed": validComputedUserAccountControl,
|
||||
@@ -2102,8 +2102,8 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
||||
|
||||
expectedRefreshAttributeChecks := copyOfExpectedValueForResultingCache.RefreshAttributeChecks
|
||||
actualRefreshAttributeChecks := actualConfig.RefreshAttributeChecks
|
||||
copyOfExpectedValueForResultingCache.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{}
|
||||
actualConfig.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{}
|
||||
copyOfExpectedValueForResultingCache.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{}
|
||||
actualConfig.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{}
|
||||
require.Equal(t, len(expectedRefreshAttributeChecks), len(actualRefreshAttributeChecks))
|
||||
for k, v := range expectedRefreshAttributeChecks {
|
||||
require.NotNil(t, actualRefreshAttributeChecks[k])
|
||||
@@ -2352,7 +2352,7 @@ func TestValidUserAccountControl(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validUserAccountControl(tt.entry, upstreamprovider.RefreshAttributes{})
|
||||
err := validUserAccountControl(tt.entry, upstreamprovider.LDAPRefreshAttributes{})
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
@@ -2413,7 +2413,7 @@ func TestValidComputedUserAccountControl(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validComputedUserAccountControl(tt.entry, upstreamprovider.RefreshAttributes{})
|
||||
err := validComputedUserAccountControl(tt.entry, upstreamprovider.LDAPRefreshAttributes{})
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
@@ -2488,7 +2488,7 @@ func TestAttributeUnchangedSinceLogin(t *testing.T) {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
initialValRawEncoded := base64.RawURLEncoding.EncodeToString([]byte(initialVal))
|
||||
err := attributeUnchangedSinceLogin(attributeName)(tt.entry, upstreamprovider.RefreshAttributes{AdditionalAttributes: map[string]string{attributeName: initialValRawEncoded}})
|
||||
err := attributeUnchangedSinceLogin(attributeName)(tt.entry, upstreamprovider.LDAPRefreshAttributes{AdditionalAttributes: map[string]string{attributeName: initialValRawEncoded}})
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, tt.wantErr, err.Error())
|
||||
|
||||
@@ -269,30 +269,43 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type expectedUpstreamRefresh struct {
|
||||
type expectedOIDCUpstreamRefresh struct {
|
||||
performedByUpstreamName string
|
||||
args *oidctestutil.PerformRefreshArgs
|
||||
args *oidctestutil.PerformOIDCRefreshArgs
|
||||
}
|
||||
|
||||
type expectedUpstreamValidateTokens struct {
|
||||
type expectedLDAPUpstreamRefresh struct {
|
||||
performedByUpstreamName string
|
||||
args *oidctestutil.PerformLDAPRefreshArgs
|
||||
}
|
||||
|
||||
type expectedGithubUpstreamRefresh struct {
|
||||
performedByUpstreamName string
|
||||
args *oidctestutil.GetUserArgs
|
||||
}
|
||||
|
||||
type expectedOIDCUpstreamValidateTokens struct {
|
||||
performedByUpstreamName string
|
||||
args *oidctestutil.ValidateTokenAndMergeWithUserInfoArgs
|
||||
}
|
||||
|
||||
type tokenEndpointResponseExpectedValues struct {
|
||||
wantStatus int
|
||||
wantSuccessBodyFields []string
|
||||
wantErrorResponseBody string
|
||||
wantClientID string
|
||||
wantRequestedScopes []string
|
||||
wantGrantedScopes []string
|
||||
wantUsername string
|
||||
wantGroups []string
|
||||
wantUpstreamRefreshCall *expectedUpstreamRefresh
|
||||
wantUpstreamOIDCValidateTokenCall *expectedUpstreamValidateTokens
|
||||
wantCustomSessionDataStored *psession.CustomSessionData
|
||||
wantWarnings []RecordedWarning
|
||||
wantAdditionalClaims map[string]interface{}
|
||||
wantStatus int
|
||||
wantSuccessBodyFields []string
|
||||
wantErrorResponseBody string
|
||||
wantClientID string
|
||||
wantRequestedScopes []string
|
||||
wantGrantedScopes []string
|
||||
wantUsername string
|
||||
wantGroups []string
|
||||
wantOIDCUpstreamRefreshCall *expectedOIDCUpstreamRefresh
|
||||
wantLDAPUpstreamRefreshCall *expectedLDAPUpstreamRefresh
|
||||
wantActiveDirectoryUpstreamRefreshCall *expectedLDAPUpstreamRefresh
|
||||
wantGithubUpstreamRefreshCall *expectedGithubUpstreamRefresh
|
||||
wantUpstreamOIDCValidateTokenCall *expectedOIDCUpstreamValidateTokens
|
||||
wantCustomSessionDataStored *psession.CustomSessionData
|
||||
wantWarnings []RecordedWarning
|
||||
wantAdditionalClaims map[string]interface{}
|
||||
// The expected lifetime of the ID tokens issued by authcode exchange and refresh, but not token exchange.
|
||||
// When zero, will assume that the test wants the default value for ID token lifetime.
|
||||
wantIDTokenLifetimeSeconds int
|
||||
@@ -1925,48 +1938,63 @@ func TestRefreshGrant(t *testing.T) {
|
||||
return sessionData
|
||||
}
|
||||
|
||||
happyOIDCUpstreamRefreshCall := func() *expectedUpstreamRefresh {
|
||||
return &expectedUpstreamRefresh{
|
||||
happyOIDCUpstreamRefreshCall := func() *expectedOIDCUpstreamRefresh {
|
||||
return &expectedOIDCUpstreamRefresh{
|
||||
performedByUpstreamName: oidcUpstreamName,
|
||||
args: &oidctestutil.PerformRefreshArgs{
|
||||
args: &oidctestutil.PerformOIDCRefreshArgs{
|
||||
Ctx: nil, // this will be filled in with the actual request context by the test below
|
||||
RefreshToken: oidcUpstreamInitialRefreshToken,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
happyGitHubUpstreamRefreshCall := func() *expectedUpstreamRefresh {
|
||||
return &expectedUpstreamRefresh{
|
||||
happyGitHubUpstreamRefreshCall := func() *expectedGithubUpstreamRefresh {
|
||||
return &expectedGithubUpstreamRefresh{
|
||||
performedByUpstreamName: githubUpstreamName,
|
||||
args: &oidctestutil.GetUserArgs{
|
||||
Ctx: nil, // this will be filled in with the actual request context by the test below
|
||||
AccessToken: githubUpstreamAccessToken,
|
||||
IDPDisplayName: githubUpstreamName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
happyLDAPUpstreamRefreshCall := func() *expectedUpstreamRefresh {
|
||||
return &expectedUpstreamRefresh{
|
||||
happyLDAPUpstreamRefreshCall := func() *expectedLDAPUpstreamRefresh {
|
||||
return &expectedLDAPUpstreamRefresh{
|
||||
performedByUpstreamName: ldapUpstreamName,
|
||||
args: &oidctestutil.PerformRefreshArgs{
|
||||
Ctx: nil,
|
||||
DN: ldapUpstreamDN,
|
||||
ExpectedSubject: goodSubject,
|
||||
ExpectedUsername: goodUsername,
|
||||
args: &oidctestutil.PerformLDAPRefreshArgs{
|
||||
Ctx: nil, // this will be filled in with the actual request context by the test below
|
||||
StoredRefreshAttributes: upstreamprovider.LDAPRefreshAttributes{
|
||||
Username: goodUsername,
|
||||
Subject: goodSubject,
|
||||
DN: ldapUpstreamDN,
|
||||
Groups: goodGroups,
|
||||
AdditionalAttributes: nil,
|
||||
},
|
||||
IDPDisplayName: ldapUpstreamName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
happyActiveDirectoryUpstreamRefreshCall := func() *expectedUpstreamRefresh {
|
||||
return &expectedUpstreamRefresh{
|
||||
happyActiveDirectoryUpstreamRefreshCall := func() *expectedLDAPUpstreamRefresh {
|
||||
return &expectedLDAPUpstreamRefresh{
|
||||
performedByUpstreamName: activeDirectoryUpstreamName,
|
||||
args: &oidctestutil.PerformRefreshArgs{
|
||||
Ctx: nil,
|
||||
DN: activeDirectoryUpstreamDN,
|
||||
ExpectedSubject: goodSubject,
|
||||
ExpectedUsername: goodUsername,
|
||||
args: &oidctestutil.PerformLDAPRefreshArgs{
|
||||
Ctx: nil, // this will be filled in with the actual request context by the test below
|
||||
StoredRefreshAttributes: upstreamprovider.LDAPRefreshAttributes{
|
||||
Username: goodUsername,
|
||||
Subject: goodSubject,
|
||||
DN: activeDirectoryUpstreamDN,
|
||||
Groups: goodGroups,
|
||||
AdditionalAttributes: nil,
|
||||
},
|
||||
IDPDisplayName: activeDirectoryUpstreamName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
happyUpstreamValidateTokenCall := func(expectedTokens *oauth2.Token, requireIDToken bool) *expectedUpstreamValidateTokens {
|
||||
return &expectedUpstreamValidateTokens{
|
||||
happyUpstreamValidateTokenCall := func(expectedTokens *oauth2.Token, requireIDToken bool) *expectedOIDCUpstreamValidateTokens {
|
||||
return &expectedOIDCUpstreamValidateTokens{
|
||||
performedByUpstreamName: oidcUpstreamName,
|
||||
args: &oidctestutil.ValidateTokenAndMergeWithUserInfoArgs{
|
||||
Ctx: nil, // this will be filled in with the actual request context by the test below
|
||||
@@ -2014,7 +2042,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
// same as the same values as the authcode exchange case.
|
||||
want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccess(wantCustomSessionDataStored)
|
||||
// Should always try to perform an upstream refresh.
|
||||
want.wantUpstreamRefreshCall = happyOIDCUpstreamRefreshCall()
|
||||
want.wantOIDCUpstreamRefreshCall = happyOIDCUpstreamRefreshCall()
|
||||
if expectToValidateToken != nil {
|
||||
want.wantUpstreamOIDCValidateTokenCall = happyUpstreamValidateTokenCall(expectToValidateToken, true)
|
||||
}
|
||||
@@ -2026,7 +2054,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
// same as the same values as the authcode exchange case.
|
||||
want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccessWithUsernameAndGroups(wantCustomSessionDataStored, wantDownstreamUsername, wantDownstreamGroups)
|
||||
// Should always try to perform an upstream refresh.
|
||||
want.wantUpstreamRefreshCall = happyOIDCUpstreamRefreshCall()
|
||||
want.wantOIDCUpstreamRefreshCall = happyOIDCUpstreamRefreshCall()
|
||||
if expectToValidateToken != nil {
|
||||
want.wantUpstreamOIDCValidateTokenCall = happyUpstreamValidateTokenCall(expectToValidateToken, true)
|
||||
}
|
||||
@@ -2038,7 +2066,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
// same as the same values as the authcode exchange case.
|
||||
want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccessWithUsernameAndGroups(wantCustomSessionDataStored, wantDownstreamUsername, wantDownstreamGroups)
|
||||
// Should always try to perform an upstream refresh.
|
||||
want.wantUpstreamRefreshCall = happyGitHubUpstreamRefreshCall()
|
||||
want.wantGithubUpstreamRefreshCall = happyGitHubUpstreamRefreshCall()
|
||||
return want
|
||||
}
|
||||
|
||||
@@ -2050,19 +2078,19 @@ func TestRefreshGrant(t *testing.T) {
|
||||
|
||||
happyRefreshTokenResponseForLDAP := func(wantCustomSessionDataStored *psession.CustomSessionData) tokenEndpointResponseExpectedValues {
|
||||
want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccess(wantCustomSessionDataStored)
|
||||
want.wantUpstreamRefreshCall = happyLDAPUpstreamRefreshCall()
|
||||
want.wantLDAPUpstreamRefreshCall = happyLDAPUpstreamRefreshCall()
|
||||
return want
|
||||
}
|
||||
|
||||
happyRefreshTokenResponseForLDAPWithUsernameAndGroups := func(wantCustomSessionDataStored *psession.CustomSessionData, wantDownstreamUsername string, wantDownstreamGroups []string) tokenEndpointResponseExpectedValues {
|
||||
want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccessWithUsernameAndGroups(wantCustomSessionDataStored, wantDownstreamUsername, wantDownstreamGroups)
|
||||
want.wantUpstreamRefreshCall = happyLDAPUpstreamRefreshCall()
|
||||
want.wantLDAPUpstreamRefreshCall = happyLDAPUpstreamRefreshCall()
|
||||
return want
|
||||
}
|
||||
|
||||
happyRefreshTokenResponseForActiveDirectory := func(wantCustomSessionDataStored *psession.CustomSessionData) tokenEndpointResponseExpectedValues {
|
||||
want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccess(wantCustomSessionDataStored)
|
||||
want.wantUpstreamRefreshCall = happyActiveDirectoryUpstreamRefreshCall()
|
||||
want.wantActiveDirectoryUpstreamRefreshCall = happyActiveDirectoryUpstreamRefreshCall()
|
||||
return want
|
||||
}
|
||||
|
||||
@@ -2252,7 +2280,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: transformationUsernamePrefix + goodUsername,
|
||||
wantGroups: testutil.AddPrefixToEach(transformationGroupsPrefix, goodGroups),
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithRefreshTokenWithoutIDToken(), false),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshTokenWithUsername(oidcUpstreamRefreshedRefreshToken, transformationUsernamePrefix+goodUsername),
|
||||
},
|
||||
@@ -2286,7 +2314,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
},
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -2326,7 +2354,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
},
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -2576,7 +2604,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantUsername: "",
|
||||
wantGroups: goodGroups,
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
}),
|
||||
},
|
||||
@@ -2631,7 +2659,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: goodGroups,
|
||||
wantUpstreamOIDCValidateTokenCall: &expectedUpstreamValidateTokens{
|
||||
wantUpstreamOIDCValidateTokenCall: &expectedOIDCUpstreamValidateTokens{
|
||||
oidcUpstreamName,
|
||||
&oidctestutil.ValidateTokenAndMergeWithUserInfoArgs{
|
||||
Ctx: nil, // this will be filled in with the actual request context by the test below
|
||||
@@ -2674,7 +2702,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantSuccessBodyFields: []string{"refresh_token", "access_token", "token_type", "expires_in", "scope"},
|
||||
wantRequestedScopes: []string{"offline_access"},
|
||||
wantGrantedScopes: []string{"offline_access", "username", "groups"},
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithRefreshTokenWithoutIDToken(), false),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantUsername: goodUsername,
|
||||
@@ -2700,7 +2728,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: goodGroups,
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithRefreshTokenWithoutIDToken(), false),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
},
|
||||
@@ -2727,7 +2755,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantWarnings: []RecordedWarning{
|
||||
@@ -2768,7 +2796,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantWarnings: nil, // dynamic clients should not get these warnings which are intended for the pinniped-cli client
|
||||
@@ -2796,7 +2824,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantWarnings: []RecordedWarning{
|
||||
@@ -2827,7 +2855,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{}, // the user no longer belongs to any groups
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantWarnings: []RecordedWarning{
|
||||
@@ -2857,7 +2885,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: goodGroups, // the same groups as from the initial login
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
},
|
||||
@@ -2882,7 +2910,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantCustomSessionDataStored: happyLDAPCustomSessionData,
|
||||
wantWarnings: []RecordedWarning{
|
||||
{Text: `User "some-username" has been added to the following groups: ["new-group1" "new-group2" "new-group3"]`},
|
||||
@@ -2920,7 +2948,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantCustomSessionDataStored: happyLDAPCustomSessionData,
|
||||
wantWarnings: nil, // dynamic clients should not get these warnings which are intended for the pinniped-cli client
|
||||
},
|
||||
@@ -2945,7 +2973,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{},
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantCustomSessionDataStored: happyLDAPCustomSessionData,
|
||||
wantWarnings: []RecordedWarning{
|
||||
{Text: `User "some-username" has been removed from the following groups: ["group1" "groups2"]`},
|
||||
@@ -2988,7 +3016,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, // username and groups were not requested, but granted anyway for backwards compatibility
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantCustomSessionDataStored: happyLDAPCustomSessionData,
|
||||
wantWarnings: []RecordedWarning{
|
||||
{Text: `User "some-username" has been added to the following groups: ["new-group1" "new-group2" "new-group3"]`},
|
||||
@@ -3034,7 +3062,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, // username and groups were not requested, but granted anyway for backwards compatibility
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"},
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
wantWarnings: []RecordedWarning{
|
||||
@@ -3087,7 +3115,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: nil,
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
},
|
||||
@@ -3138,7 +3166,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
r.SetBasicAuth(dynamicClientID, testutil.PlaintextPassword1) // Use basic auth header instead.
|
||||
},
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
// auth was rejected because of the upstream group to which the user belonged, as shown by the configured RejectedAuthenticationMessage appearing here
|
||||
@@ -3188,7 +3216,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: []string{"new-group1", "new-group2", "new-group3"}, // groups are updated even though the scope was not included
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantCustomSessionDataStored: happyLDAPCustomSessionData,
|
||||
wantWarnings: []RecordedWarning{
|
||||
{Text: `User "some-username" has been added to the following groups: ["new-group1" "new-group2" "new-group3"]`},
|
||||
@@ -3213,7 +3241,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: fositeUpstreamGroupClaimErrorBody,
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
},
|
||||
},
|
||||
@@ -3295,7 +3323,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantGrantedScopes: []string{"openid", "offline_access", "pinniped:request-audience", "username", "groups"},
|
||||
wantUsername: goodUsername,
|
||||
wantGroups: goodGroups,
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken),
|
||||
},
|
||||
@@ -3793,8 +3821,8 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
{
|
||||
"error": "error",
|
||||
@@ -3814,7 +3842,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -3842,7 +3870,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -3867,7 +3895,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -3894,7 +3922,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -3921,7 +3949,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(),
|
||||
wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
@@ -4011,8 +4039,8 @@ func TestRefreshGrant(t *testing.T) {
|
||||
},
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
{
|
||||
"error": "error",
|
||||
@@ -4051,8 +4079,8 @@ func TestRefreshGrant(t *testing.T) {
|
||||
},
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
{
|
||||
"error": "error",
|
||||
@@ -4125,7 +4153,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
wantCustomSessionDataStored: happyLDAPCustomSessionData,
|
||||
wantUsername: "",
|
||||
wantGroups: goodGroups,
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -4319,8 +4347,8 @@ func TestRefreshGrant(t *testing.T) {
|
||||
authcodeExchange: happyAuthcodeExchangeInputsForLDAPUpstream,
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
{
|
||||
"error": "error",
|
||||
@@ -4348,8 +4376,8 @@ func TestRefreshGrant(t *testing.T) {
|
||||
},
|
||||
refreshRequest: refreshRequestInputs{
|
||||
want: tokenEndpointResponseExpectedValues{
|
||||
wantUpstreamRefreshCall: happyActiveDirectoryUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantActiveDirectoryUpstreamRefreshCall: happyActiveDirectoryUpstreamRefreshCall(),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantErrorResponseBody: here.Doc(`
|
||||
{
|
||||
"error": "error",
|
||||
@@ -4602,7 +4630,7 @@ func TestRefreshGrant(t *testing.T) {
|
||||
|
||||
// Performing an authcode exchange should not have caused any upstream refresh, which should only
|
||||
// happen during a downstream refresh.
|
||||
test.idps.RequireExactlyZeroCallsToPerformRefresh(t)
|
||||
test.idps.RequireExactlyZeroCallsToAnyUpstreamRefresh(t)
|
||||
test.idps.RequireExactlyZeroCallsToValidateToken(t)
|
||||
|
||||
// Wait one second before performing the refresh so we can see that the refreshed ID token has new issued
|
||||
@@ -4634,21 +4662,38 @@ func TestRefreshGrant(t *testing.T) {
|
||||
t.Logf("second response: %#v", refreshResponse)
|
||||
t.Logf("second response body: %q", refreshResponse.Body.String())
|
||||
|
||||
// Test that we did or did not make a call to the upstream OIDC provider interface to perform a token refresh.
|
||||
if test.refreshRequest.want.wantUpstreamRefreshCall != nil {
|
||||
if test.authcodeExchange.customSessionData.ProviderType != "github" {
|
||||
test.refreshRequest.want.wantUpstreamRefreshCall.args.Ctx = reqContext
|
||||
}
|
||||
test.idps.RequireExactlyOneCallToPerformRefresh(t,
|
||||
test.refreshRequest.want.wantUpstreamRefreshCall.performedByUpstreamName,
|
||||
test.refreshRequest.want.wantUpstreamRefreshCall.args,
|
||||
// Test that we did or did not make a call to the upstream provider's interface to perform refresh.
|
||||
switch {
|
||||
case test.refreshRequest.want.wantOIDCUpstreamRefreshCall != nil:
|
||||
test.refreshRequest.want.wantOIDCUpstreamRefreshCall.args.Ctx = reqContext
|
||||
test.idps.RequireExactlyOneCallToOIDCPerformRefresh(t,
|
||||
test.refreshRequest.want.wantOIDCUpstreamRefreshCall.performedByUpstreamName,
|
||||
test.refreshRequest.want.wantOIDCUpstreamRefreshCall.args,
|
||||
)
|
||||
} else {
|
||||
test.idps.RequireExactlyZeroCallsToPerformRefresh(t)
|
||||
case test.refreshRequest.want.wantLDAPUpstreamRefreshCall != nil:
|
||||
test.refreshRequest.want.wantLDAPUpstreamRefreshCall.args.Ctx = reqContext
|
||||
test.idps.RequireExactlyOneCallToLDAPPerformRefresh(t,
|
||||
test.refreshRequest.want.wantLDAPUpstreamRefreshCall.performedByUpstreamName,
|
||||
test.refreshRequest.want.wantLDAPUpstreamRefreshCall.args,
|
||||
)
|
||||
case test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall != nil:
|
||||
test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall.args.Ctx = reqContext
|
||||
test.idps.RequireExactlyOneCallToActiveDirectoryPerformRefresh(t,
|
||||
test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall.performedByUpstreamName,
|
||||
test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall.args,
|
||||
)
|
||||
case test.refreshRequest.want.wantGithubUpstreamRefreshCall != nil:
|
||||
test.refreshRequest.want.wantGithubUpstreamRefreshCall.args.Ctx = reqContext
|
||||
test.idps.RequireExactlyOneCallToGithubGetUser(t,
|
||||
test.refreshRequest.want.wantGithubUpstreamRefreshCall.performedByUpstreamName,
|
||||
test.refreshRequest.want.wantGithubUpstreamRefreshCall.args,
|
||||
)
|
||||
default:
|
||||
test.idps.RequireExactlyZeroCallsToAnyUpstreamRefresh(t)
|
||||
}
|
||||
|
||||
// Test that we did or did not make a call to the upstream OIDC provider interface to validate the
|
||||
// new ID token that was returned by the upstream refresh.
|
||||
// new ID token that was returned by the upstream refresh, in the case of an OIDC upstream.
|
||||
if test.refreshRequest.want.wantUpstreamOIDCValidateTokenCall != nil {
|
||||
test.refreshRequest.want.wantUpstreamOIDCValidateTokenCall.args.Ctx = reqContext
|
||||
test.idps.RequireExactlyOneCallToValidateToken(t,
|
||||
|
||||
@@ -221,7 +221,7 @@ func (p *FederationDomainResolvedLDAPIdentityProvider) UpstreamRefresh(
|
||||
plog.Debug("attempting upstream refresh request",
|
||||
"providerName", p.Provider.GetName(), "providerType", p.GetSessionProviderType(), "providerUID", p.Provider.GetResourceUID())
|
||||
|
||||
refreshedUntransformedGroups, err := p.Provider.PerformRefresh(ctx, upstreamprovider.RefreshAttributes{
|
||||
refreshedUntransformedGroups, err := p.Provider.PerformRefresh(ctx, upstreamprovider.LDAPRefreshAttributes{
|
||||
Username: identity.UpstreamUsername,
|
||||
Subject: identity.DownstreamSubject,
|
||||
DN: dn,
|
||||
|
||||
@@ -26,9 +26,9 @@ const (
|
||||
AccessTokenType RevocableTokenType = "access_token"
|
||||
)
|
||||
|
||||
// RefreshAttributes contains information about the user from the original login request
|
||||
// LDAPRefreshAttributes contains information about the user from the original login request
|
||||
// and previous refreshes to be used during an LDAP session refresh.
|
||||
type RefreshAttributes struct {
|
||||
type LDAPRefreshAttributes struct {
|
||||
Username string
|
||||
Subject string
|
||||
DN string
|
||||
@@ -125,7 +125,7 @@ type UpstreamLDAPIdentityProviderI interface {
|
||||
authenticators.UserAuthenticator
|
||||
|
||||
// PerformRefresh performs a refresh against the upstream LDAP identity provider
|
||||
PerformRefresh(ctx context.Context, storedRefreshAttributes RefreshAttributes, idpDisplayName string) (groups []string, err error)
|
||||
PerformRefresh(ctx context.Context, storedRefreshAttributes LDAPRefreshAttributes, idpDisplayName string) (groups []string, err error)
|
||||
}
|
||||
|
||||
type GitHubUser struct {
|
||||
|
||||
@@ -14,6 +14,12 @@ import (
|
||||
"go.pinniped.dev/internal/idtransform"
|
||||
)
|
||||
|
||||
type PerformLDAPRefreshArgs struct {
|
||||
Ctx context.Context
|
||||
StoredRefreshAttributes upstreamprovider.LDAPRefreshAttributes
|
||||
IDPDisplayName string
|
||||
}
|
||||
|
||||
func NewTestUpstreamLDAPIdentityProviderBuilder() *TestUpstreamLDAPIdentityProviderBuilder {
|
||||
return &TestUpstreamLDAPIdentityProviderBuilder{}
|
||||
}
|
||||
@@ -102,7 +108,7 @@ type TestUpstreamLDAPIdentityProvider struct {
|
||||
|
||||
// Fields for tracking actual calls make to mock functions.
|
||||
performRefreshCallCount int
|
||||
performRefreshArgs []*PerformRefreshArgs
|
||||
performRefreshArgs []*PerformLDAPRefreshArgs
|
||||
}
|
||||
|
||||
var _ upstreamprovider.UpstreamLDAPIdentityProviderI = &TestUpstreamLDAPIdentityProvider{}
|
||||
@@ -123,16 +129,15 @@ func (u *TestUpstreamLDAPIdentityProvider) GetURL() *url.URL {
|
||||
return u.URL
|
||||
}
|
||||
|
||||
func (u *TestUpstreamLDAPIdentityProvider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.RefreshAttributes, _idpDisplayName string) ([]string, error) {
|
||||
func (u *TestUpstreamLDAPIdentityProvider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.LDAPRefreshAttributes, idpDisplayName string) ([]string, error) {
|
||||
if u.performRefreshArgs == nil {
|
||||
u.performRefreshArgs = make([]*PerformRefreshArgs, 0)
|
||||
u.performRefreshArgs = make([]*PerformLDAPRefreshArgs, 0)
|
||||
}
|
||||
u.performRefreshCallCount++
|
||||
u.performRefreshArgs = append(u.performRefreshArgs, &PerformRefreshArgs{
|
||||
Ctx: ctx,
|
||||
DN: storedRefreshAttributes.DN,
|
||||
ExpectedUsername: storedRefreshAttributes.Username,
|
||||
ExpectedSubject: storedRefreshAttributes.Subject,
|
||||
u.performRefreshArgs = append(u.performRefreshArgs, &PerformLDAPRefreshArgs{
|
||||
Ctx: ctx,
|
||||
StoredRefreshAttributes: storedRefreshAttributes,
|
||||
IDPDisplayName: idpDisplayName,
|
||||
})
|
||||
if u.PerformRefreshErr != nil {
|
||||
return nil, u.PerformRefreshErr
|
||||
@@ -144,9 +149,9 @@ func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshCallCount() int {
|
||||
return u.performRefreshCallCount
|
||||
}
|
||||
|
||||
func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshArgs(call int) *PerformRefreshArgs {
|
||||
func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshArgs(call int) *PerformLDAPRefreshArgs {
|
||||
if u.performRefreshArgs == nil {
|
||||
u.performRefreshArgs = make([]*PerformRefreshArgs, 0)
|
||||
u.performRefreshArgs = make([]*PerformLDAPRefreshArgs, 0)
|
||||
}
|
||||
return u.performRefreshArgs[call]
|
||||
}
|
||||
|
||||
@@ -36,14 +36,11 @@ type PasswordCredentialsGrantAndValidateTokensArgs struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
// PerformRefreshArgs is used to spy on calls to
|
||||
// PerformOIDCRefreshArgs is used to spy on calls to
|
||||
// TestUpstreamOIDCIdentityProvider.PerformRefreshFunc().
|
||||
type PerformRefreshArgs struct {
|
||||
Ctx context.Context
|
||||
RefreshToken string
|
||||
DN string
|
||||
ExpectedUsername string
|
||||
ExpectedSubject string
|
||||
type PerformOIDCRefreshArgs struct {
|
||||
Ctx context.Context
|
||||
RefreshToken string
|
||||
}
|
||||
|
||||
// RevokeTokenArgs is used to spy on calls to
|
||||
@@ -105,7 +102,7 @@ type TestUpstreamOIDCIdentityProvider struct {
|
||||
passwordCredentialsGrantAndValidateTokensCallCount int
|
||||
passwordCredentialsGrantAndValidateTokensArgs []*PasswordCredentialsGrantAndValidateTokensArgs
|
||||
performRefreshCallCount int
|
||||
performRefreshArgs []*PerformRefreshArgs
|
||||
performRefreshArgs []*PerformOIDCRefreshArgs
|
||||
revokeTokenCallCount int
|
||||
revokeTokenArgs []*RevokeTokenArgs
|
||||
validateTokenAndMergeWithUserInfoCallCount int
|
||||
@@ -217,10 +214,10 @@ func (u *TestUpstreamOIDCIdentityProvider) PasswordCredentialsGrantAndValidateTo
|
||||
|
||||
func (u *TestUpstreamOIDCIdentityProvider) PerformRefresh(ctx context.Context, refreshToken string) (*oauth2.Token, error) {
|
||||
if u.performRefreshArgs == nil {
|
||||
u.performRefreshArgs = make([]*PerformRefreshArgs, 0)
|
||||
u.performRefreshArgs = make([]*PerformOIDCRefreshArgs, 0)
|
||||
}
|
||||
u.performRefreshCallCount++
|
||||
u.performRefreshArgs = append(u.performRefreshArgs, &PerformRefreshArgs{
|
||||
u.performRefreshArgs = append(u.performRefreshArgs, &PerformOIDCRefreshArgs{
|
||||
Ctx: ctx,
|
||||
RefreshToken: refreshToken,
|
||||
})
|
||||
@@ -244,9 +241,9 @@ func (u *TestUpstreamOIDCIdentityProvider) PerformRefreshCallCount() int {
|
||||
return u.performRefreshCallCount
|
||||
}
|
||||
|
||||
func (u *TestUpstreamOIDCIdentityProvider) PerformRefreshArgs(call int) *PerformRefreshArgs {
|
||||
func (u *TestUpstreamOIDCIdentityProvider) PerformRefreshArgs(call int) *PerformOIDCRefreshArgs {
|
||||
if u.performRefreshArgs == nil {
|
||||
u.performRefreshArgs = make([]*PerformRefreshArgs, 0)
|
||||
u.performRefreshArgs = make([]*PerformOIDCRefreshArgs, 0)
|
||||
}
|
||||
return u.performRefreshArgs[call]
|
||||
}
|
||||
|
||||
@@ -330,60 +330,111 @@ func (b *UpstreamIDPListerBuilder) RequireExactlyZeroAuthcodeExchanges(t *testin
|
||||
)
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToPerformRefresh(
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToOIDCPerformRefresh(
|
||||
t *testing.T,
|
||||
expectedPerformedByUpstreamName string,
|
||||
expectedArgs *oidctestutil.PerformRefreshArgs,
|
||||
expectedArgs *oidctestutil.PerformOIDCRefreshArgs,
|
||||
) {
|
||||
t.Helper()
|
||||
var actualArgs *oidctestutil.PerformRefreshArgs
|
||||
var actualArgs *oidctestutil.PerformOIDCRefreshArgs
|
||||
var actualNameOfUpstreamWhichMadeCall string
|
||||
actualCallCountAcrossAllUpstreams := 0
|
||||
for _, upstreamOIDC := range b.upstreamOIDCIdentityProviders {
|
||||
callCountOnThisUpstream := upstreamOIDC.PerformRefreshCallCount()
|
||||
actualCallCountAcrossAllUpstreams += callCountOnThisUpstream
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstreamOIDC.Name
|
||||
actualArgs = upstreamOIDC.PerformRefreshArgs(0)
|
||||
}
|
||||
}
|
||||
for _, upstreamLDAP := range b.upstreamLDAPIdentityProviders {
|
||||
callCountOnThisUpstream := upstreamLDAP.PerformRefreshCallCount()
|
||||
actualCallCountAcrossAllUpstreams += callCountOnThisUpstream
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstreamLDAP.Name
|
||||
actualArgs = upstreamLDAP.PerformRefreshArgs(0)
|
||||
}
|
||||
}
|
||||
for _, upstreamAD := range b.upstreamActiveDirectoryIdentityProviders {
|
||||
callCountOnThisUpstream := upstreamAD.PerformRefreshCallCount()
|
||||
actualCallCountAcrossAllUpstreams += callCountOnThisUpstream
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstreamAD.Name
|
||||
actualArgs = upstreamAD.PerformRefreshArgs(0)
|
||||
}
|
||||
}
|
||||
for _, upstream := range b.upstreamGitHubIdentityProviders {
|
||||
// Remember that GitHub does not have a traditional PerformRefresh function.
|
||||
// GitHub calls GetUser during both the original authcode exchange and the refresh.
|
||||
callCountOnThisUpstream := upstream.GetUserCallCount()
|
||||
actualCallCountAcrossAllUpstreams += callCountOnThisUpstream
|
||||
for _, upstream := range b.upstreamOIDCIdentityProviders {
|
||||
callCountOnThisUpstream := upstream.PerformRefreshCallCount()
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstream.Name
|
||||
actualArgs = nil
|
||||
actualArgs = upstream.PerformRefreshArgs(0)
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, actualCallCountAcrossAllUpstreams,
|
||||
"should have been exactly one call to PerformRefresh() by all upstreams",
|
||||
require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(),
|
||||
"should have been exactly one call to upstream refresh by all upstreams",
|
||||
)
|
||||
require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall,
|
||||
"PerformRefresh() was called on the wrong upstream",
|
||||
"upstream refresh was called on the wrong upstream",
|
||||
)
|
||||
require.Equal(t, expectedArgs, actualArgs)
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyZeroCallsToPerformRefresh(t *testing.T) {
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToActiveDirectoryPerformRefresh(
|
||||
t *testing.T,
|
||||
expectedPerformedByUpstreamName string,
|
||||
expectedArgs *oidctestutil.PerformLDAPRefreshArgs,
|
||||
) {
|
||||
t.Helper()
|
||||
var actualArgs *oidctestutil.PerformLDAPRefreshArgs
|
||||
var actualNameOfUpstreamWhichMadeCall string
|
||||
for _, upstream := range b.upstreamActiveDirectoryIdentityProviders {
|
||||
callCountOnThisUpstream := upstream.PerformRefreshCallCount()
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstream.Name
|
||||
actualArgs = upstream.PerformRefreshArgs(0)
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(),
|
||||
"should have been exactly one call to upstream refresh by all upstreams",
|
||||
)
|
||||
require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall,
|
||||
"upstream refresh was called on the wrong upstream",
|
||||
)
|
||||
require.Equal(t, expectedArgs, actualArgs)
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToLDAPPerformRefresh(
|
||||
t *testing.T,
|
||||
expectedPerformedByUpstreamName string,
|
||||
expectedArgs *oidctestutil.PerformLDAPRefreshArgs,
|
||||
) {
|
||||
t.Helper()
|
||||
var actualArgs *oidctestutil.PerformLDAPRefreshArgs
|
||||
var actualNameOfUpstreamWhichMadeCall string
|
||||
for _, upstream := range b.upstreamLDAPIdentityProviders {
|
||||
callCountOnThisUpstream := upstream.PerformRefreshCallCount()
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstream.Name
|
||||
actualArgs = upstream.PerformRefreshArgs(0)
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(),
|
||||
"should have been exactly one call to upstream refresh by all upstreams",
|
||||
)
|
||||
require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall,
|
||||
"upstream refresh was called on the wrong upstream",
|
||||
)
|
||||
require.Equal(t, expectedArgs, actualArgs)
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToGithubGetUser(
|
||||
t *testing.T,
|
||||
expectedPerformedByUpstreamName string,
|
||||
expectedArgs *oidctestutil.GetUserArgs,
|
||||
) {
|
||||
t.Helper()
|
||||
var actualArgs *oidctestutil.GetUserArgs
|
||||
var actualNameOfUpstreamWhichMadeCall string
|
||||
for _, upstream := range b.upstreamGitHubIdentityProviders {
|
||||
// GitHub calls GetUser during both the original authcode exchange and the refresh.
|
||||
callCountOnThisUpstream := upstream.GetUserCallCount()
|
||||
if callCountOnThisUpstream == 1 {
|
||||
actualNameOfUpstreamWhichMadeCall = upstream.Name
|
||||
actualArgs = upstream.GetUserArgs(0)
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(),
|
||||
"should have been exactly one call to upstream refresh by all upstreams",
|
||||
)
|
||||
require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall,
|
||||
"upstream refresh was called on the wrong upstream",
|
||||
)
|
||||
require.Equal(t, expectedArgs, actualArgs)
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyZeroCallsToAnyUpstreamRefresh(t *testing.T) {
|
||||
t.Helper()
|
||||
require.Equal(t, 0, b.CountAllCallsToAnyUpstreamRefresh(),
|
||||
"expected exactly zero calls to any upstream refresh mocks",
|
||||
)
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) CountAllCallsToAnyUpstreamRefresh() int {
|
||||
actualCallCountAcrossAllUpstreams := 0
|
||||
for _, upstreamOIDC := range b.upstreamOIDCIdentityProviders {
|
||||
actualCallCountAcrossAllUpstreams += upstreamOIDC.PerformRefreshCallCount()
|
||||
@@ -394,11 +445,10 @@ func (b *UpstreamIDPListerBuilder) RequireExactlyZeroCallsToPerformRefresh(t *te
|
||||
for _, upstreamActiveDirectory := range b.upstreamActiveDirectoryIdentityProviders {
|
||||
actualCallCountAcrossAllUpstreams += upstreamActiveDirectory.PerformRefreshCallCount()
|
||||
}
|
||||
// TODO: probably add GitHub loop once we flesh out the structs
|
||||
|
||||
require.Equal(t, 0, actualCallCountAcrossAllUpstreams,
|
||||
"expected exactly zero calls to PerformRefresh()",
|
||||
)
|
||||
for _, upstreamGithub := range b.upstreamGitHubIdentityProviders {
|
||||
actualCallCountAcrossAllUpstreams += upstreamGithub.GetUserCallCount()
|
||||
}
|
||||
return actualCallCountAcrossAllUpstreams
|
||||
}
|
||||
|
||||
func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToValidateToken(
|
||||
|
||||
@@ -118,7 +118,7 @@ type ProviderConfig struct {
|
||||
GroupAttributeParsingOverrides map[string]func(*ldap.Entry) (string, error)
|
||||
|
||||
// RefreshAttributeChecks are extra checks that attributes in a refresh response are as expected.
|
||||
RefreshAttributeChecks map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error
|
||||
RefreshAttributeChecks map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error
|
||||
}
|
||||
|
||||
// UserSearchConfig contains information about how to search for users in the upstream LDAP IDP.
|
||||
@@ -186,7 +186,7 @@ func closeAndLogError(conn Conn, doingWhat string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.RefreshAttributes, idpDisplayName string) ([]string, error) {
|
||||
func (p *Provider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.LDAPRefreshAttributes, idpDisplayName string) ([]string, error) {
|
||||
t := trace.FromContext(ctx).Nest("slow ldap refresh attempt", trace.Field{Key: "providerName", Value: p.GetName()})
|
||||
defer t.LogIfLong(500 * time.Millisecond) // to help users debug slow LDAP searches
|
||||
userDN := storedRefreshAttributes.DN
|
||||
|
||||
@@ -641,8 +641,8 @@ func TestEndUserAuthentication(t *testing.T) {
|
||||
username: testUpstreamUsername,
|
||||
password: testUpstreamPassword,
|
||||
providerConfig: providerConfig(func(p *ProviderConfig) {
|
||||
p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error{
|
||||
"some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error {
|
||||
p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -679,8 +679,8 @@ func TestEndUserAuthentication(t *testing.T) {
|
||||
username: testUpstreamUsername,
|
||||
password: testUpstreamPassword,
|
||||
providerConfig: providerConfig(func(p *ProviderConfig) {
|
||||
p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error{
|
||||
"some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error {
|
||||
p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error{
|
||||
"some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -1527,8 +1527,8 @@ func TestUpstreamRefresh(t *testing.T) {
|
||||
Filter: testGroupSearchFilter,
|
||||
GroupNameAttribute: testGroupSearchGroupNameAttribute,
|
||||
},
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.RefreshAttributes) error { return nil },
|
||||
RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error { return nil },
|
||||
},
|
||||
}
|
||||
if editFunc != nil {
|
||||
@@ -2124,8 +2124,8 @@ func TestUpstreamRefresh(t *testing.T) {
|
||||
{
|
||||
name: "search result has a changed pwdLastSet value",
|
||||
providerConfig: providerConfig(func(p *ProviderConfig) {
|
||||
p.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{
|
||||
pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.RefreshAttributes) error {
|
||||
p.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{
|
||||
pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error {
|
||||
return errors.New(`value for attribute "pwdLastSet" has changed since initial value at login`)
|
||||
},
|
||||
}
|
||||
@@ -2201,7 +2201,7 @@ func TestUpstreamRefresh(t *testing.T) {
|
||||
"ldaps://ldap.example.com:8443?base=some-upstream-user-base-dn&idpName=%s&sub=c29tZS11cHN0cmVhbS11aWQtdmFsdWU",
|
||||
testUpstreamName,
|
||||
)
|
||||
groups, err := ldapProvider.PerformRefresh(context.Background(), upstreamprovider.RefreshAttributes{
|
||||
groups, err := ldapProvider.PerformRefresh(context.Background(), upstreamprovider.LDAPRefreshAttributes{
|
||||
Username: testUserSearchResultUsernameAttributeValue,
|
||||
Subject: subject,
|
||||
DN: tt.refreshUserDN,
|
||||
|
||||
Reference in New Issue
Block a user