mirror of
https://github.com/int128/kubelogin.git
synced 2026-02-14 08:29:51 +00:00
272 lines
8.7 KiB
Go
272 lines
8.7 KiB
Go
package credentialplugin
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
|
"github.com/int128/kubelogin/mocks/github.com/int128/kubelogin/pkg/credentialplugin/writer_mock"
|
|
"github.com/int128/kubelogin/mocks/github.com/int128/kubelogin/pkg/infrastructure/mutex_mock"
|
|
"github.com/int128/kubelogin/mocks/github.com/int128/kubelogin/pkg/tokencache/repository_mock"
|
|
"github.com/int128/kubelogin/mocks/github.com/int128/kubelogin/pkg/usecases/authentication_mock"
|
|
"github.com/int128/kubelogin/pkg/credentialplugin"
|
|
"github.com/int128/kubelogin/pkg/infrastructure/mutex"
|
|
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
|
|
|
|
"github.com/int128/kubelogin/pkg/oidc"
|
|
testingJWT "github.com/int128/kubelogin/pkg/testing/jwt"
|
|
"github.com/int128/kubelogin/pkg/testing/logger"
|
|
"github.com/int128/kubelogin/pkg/tokencache"
|
|
"github.com/int128/kubelogin/pkg/usecases/authentication"
|
|
"github.com/int128/kubelogin/pkg/usecases/authentication/ropc"
|
|
)
|
|
|
|
func TestGetToken_Do(t *testing.T) {
|
|
dummyProvider := oidc.Provider{
|
|
IssuerURL: "https://accounts.google.com",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
}
|
|
issuedIDTokenExpiration := time.Now().Add(1 * time.Hour).Round(time.Second)
|
|
issuedIDToken := testingJWT.EncodeF(t, func(claims *testingJWT.Claims) {
|
|
claims.Issuer = "https://accounts.google.com"
|
|
claims.Subject = "YOUR_SUBJECT"
|
|
claims.ExpiresAt = jwt.NewNumericDate(issuedIDTokenExpiration)
|
|
})
|
|
issuedTokenSet := oidc.TokenSet{
|
|
IDToken: issuedIDToken,
|
|
RefreshToken: "YOUR_REFRESH_TOKEN",
|
|
}
|
|
issuedOutput := credentialplugin.Output{
|
|
Token: issuedIDToken,
|
|
Expiry: issuedIDTokenExpiration,
|
|
}
|
|
grantOptionSet := authentication.GrantOptionSet{
|
|
AuthCodeBrowserOption: &authcode.BrowserOption{
|
|
BindAddress: []string{"127.0.0.1:0"},
|
|
},
|
|
}
|
|
|
|
t.Run("NoTokenCache", func(t *testing.T) {
|
|
tokenCacheKey := tokencache.Key{
|
|
IssuerURL: "https://accounts.google.com",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
}
|
|
ctx := context.TODO()
|
|
in := Input{
|
|
Provider: dummyProvider,
|
|
TokenCacheDir: "/path/to/token-cache",
|
|
GrantOptionSet: grantOptionSet,
|
|
}
|
|
mockAuthentication := authentication_mock.NewMockInterface(t)
|
|
mockAuthentication.EXPECT().
|
|
Do(ctx, authentication.Input{
|
|
Provider: dummyProvider,
|
|
GrantOptionSet: grantOptionSet,
|
|
}).
|
|
Return(&authentication.Output{TokenSet: issuedTokenSet}, nil)
|
|
mockRepository := repository_mock.NewMockInterface(t)
|
|
mockRepository.EXPECT().
|
|
FindByKey("/path/to/token-cache", tokenCacheKey).
|
|
Return(nil, errors.New("file not found"))
|
|
mockRepository.EXPECT().
|
|
Save("/path/to/token-cache", tokenCacheKey, issuedTokenSet).
|
|
Return(nil)
|
|
mockWriter := writer_mock.NewMockInterface(t)
|
|
mockWriter.EXPECT().
|
|
Write(issuedOutput).
|
|
Return(nil)
|
|
u := GetToken{
|
|
Authentication: mockAuthentication,
|
|
TokenCacheRepository: mockRepository,
|
|
Writer: mockWriter,
|
|
Mutex: mutex_mock.NewMockInterface(t),
|
|
Logger: logger.New(t),
|
|
}
|
|
if err := u.Do(ctx, in); err != nil {
|
|
t.Errorf("Do returned error: %+v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("NeedBindPortMutex", func(t *testing.T) {
|
|
grantOptionSet := authentication.GrantOptionSet{
|
|
AuthCodeBrowserOption: &authcode.BrowserOption{
|
|
BindAddress: []string{"127.0.0.1:8080"},
|
|
},
|
|
}
|
|
tokenCacheKey := tokencache.Key{
|
|
IssuerURL: "https://accounts.google.com",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
}
|
|
|
|
ctx := context.TODO()
|
|
in := Input{
|
|
Provider: dummyProvider,
|
|
TokenCacheDir: "/path/to/token-cache",
|
|
GrantOptionSet: grantOptionSet,
|
|
}
|
|
mockAuthentication := authentication_mock.NewMockInterface(t)
|
|
mockAuthentication.EXPECT().
|
|
Do(ctx, authentication.Input{
|
|
Provider: dummyProvider,
|
|
GrantOptionSet: grantOptionSet,
|
|
}).
|
|
Return(&authentication.Output{TokenSet: issuedTokenSet}, nil)
|
|
mockRepository := repository_mock.NewMockInterface(t)
|
|
mockRepository.EXPECT().
|
|
FindByKey("/path/to/token-cache", tokenCacheKey).
|
|
Return(nil, errors.New("file not found"))
|
|
mockRepository.EXPECT().
|
|
Save("/path/to/token-cache", tokenCacheKey, issuedTokenSet).
|
|
Return(nil)
|
|
mockWriter := writer_mock.NewMockInterface(t)
|
|
mockWriter.EXPECT().
|
|
Write(issuedOutput).
|
|
Return(nil)
|
|
mockMutex := mutex_mock.NewMockInterface(t)
|
|
mockMutex.EXPECT().
|
|
Acquire(ctx, "get-token-8080").
|
|
Return(&mutex.Lock{Data: "testData"}, nil)
|
|
mockMutex.EXPECT().
|
|
Release(&mutex.Lock{Data: "testData"}).
|
|
Return(nil)
|
|
u := GetToken{
|
|
Authentication: mockAuthentication,
|
|
TokenCacheRepository: mockRepository,
|
|
Writer: mockWriter,
|
|
Mutex: mockMutex,
|
|
Logger: logger.New(t),
|
|
}
|
|
if err := u.Do(ctx, in); err != nil {
|
|
t.Errorf("Do returned error: %+v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("ROPC", func(t *testing.T) {
|
|
grantOptionSet := authentication.GrantOptionSet{
|
|
ROPCOption: &ropc.Option{Username: "YOUR_USERNAME"},
|
|
}
|
|
tokenCacheKey := tokencache.Key{
|
|
IssuerURL: "https://accounts.google.com",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
Username: "YOUR_USERNAME",
|
|
}
|
|
|
|
ctx := context.TODO()
|
|
in := Input{
|
|
Provider: dummyProvider,
|
|
TokenCacheDir: "/path/to/token-cache",
|
|
GrantOptionSet: grantOptionSet,
|
|
}
|
|
mockAuthentication := authentication_mock.NewMockInterface(t)
|
|
mockAuthentication.EXPECT().
|
|
Do(ctx, authentication.Input{
|
|
Provider: dummyProvider,
|
|
GrantOptionSet: grantOptionSet,
|
|
}).
|
|
Return(&authentication.Output{TokenSet: issuedTokenSet}, nil)
|
|
mockRepository := repository_mock.NewMockInterface(t)
|
|
mockRepository.EXPECT().
|
|
FindByKey("/path/to/token-cache", tokenCacheKey).
|
|
Return(nil, errors.New("file not found"))
|
|
mockRepository.EXPECT().
|
|
Save("/path/to/token-cache", tokenCacheKey, issuedTokenSet).
|
|
Return(nil)
|
|
mockWriter := writer_mock.NewMockInterface(t)
|
|
mockWriter.EXPECT().
|
|
Write(issuedOutput).
|
|
Return(nil)
|
|
u := GetToken{
|
|
Authentication: mockAuthentication,
|
|
TokenCacheRepository: mockRepository,
|
|
Writer: mockWriter,
|
|
Mutex: mutex_mock.NewMockInterface(t),
|
|
Logger: logger.New(t),
|
|
}
|
|
if err := u.Do(ctx, in); err != nil {
|
|
t.Errorf("Do returned error: %+v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("HasValidIDToken", func(t *testing.T) {
|
|
ctx := context.TODO()
|
|
in := Input{
|
|
Provider: dummyProvider,
|
|
TokenCacheDir: "/path/to/token-cache",
|
|
GrantOptionSet: grantOptionSet,
|
|
}
|
|
mockAuthentication := authentication_mock.NewMockInterface(t)
|
|
mockAuthentication.EXPECT().
|
|
Do(ctx, authentication.Input{
|
|
Provider: dummyProvider,
|
|
CachedTokenSet: &issuedTokenSet,
|
|
GrantOptionSet: grantOptionSet,
|
|
}).
|
|
Return(&authentication.Output{
|
|
AlreadyHasValidIDToken: true,
|
|
TokenSet: issuedTokenSet,
|
|
}, nil)
|
|
mockRepository := repository_mock.NewMockInterface(t)
|
|
mockRepository.EXPECT().
|
|
FindByKey("/path/to/token-cache", tokencache.Key{
|
|
IssuerURL: "https://accounts.google.com",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
}).
|
|
Return(&issuedTokenSet, nil)
|
|
mockWriter := writer_mock.NewMockInterface(t)
|
|
mockWriter.EXPECT().
|
|
Write(issuedOutput).
|
|
Return(nil)
|
|
u := GetToken{
|
|
Authentication: mockAuthentication,
|
|
TokenCacheRepository: mockRepository,
|
|
Writer: mockWriter,
|
|
Mutex: mutex_mock.NewMockInterface(t),
|
|
Logger: logger.New(t),
|
|
}
|
|
if err := u.Do(ctx, in); err != nil {
|
|
t.Errorf("Do returned error: %+v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("AuthenticationError", func(t *testing.T) {
|
|
ctx := context.TODO()
|
|
in := Input{
|
|
Provider: dummyProvider,
|
|
TokenCacheDir: "/path/to/token-cache",
|
|
GrantOptionSet: grantOptionSet,
|
|
}
|
|
mockAuthentication := authentication_mock.NewMockInterface(t)
|
|
mockAuthentication.EXPECT().
|
|
Do(ctx, authentication.Input{
|
|
Provider: dummyProvider,
|
|
GrantOptionSet: grantOptionSet,
|
|
}).
|
|
Return(nil, errors.New("authentication error"))
|
|
mockRepository := repository_mock.NewMockInterface(t)
|
|
mockRepository.EXPECT().
|
|
FindByKey("/path/to/token-cache", tokencache.Key{
|
|
IssuerURL: "https://accounts.google.com",
|
|
ClientID: "YOUR_CLIENT_ID",
|
|
ClientSecret: "YOUR_CLIENT_SECRET",
|
|
}).
|
|
Return(nil, errors.New("file not found"))
|
|
u := GetToken{
|
|
Authentication: mockAuthentication,
|
|
TokenCacheRepository: mockRepository,
|
|
Writer: writer_mock.NewMockInterface(t),
|
|
Mutex: mutex_mock.NewMockInterface(t),
|
|
Logger: logger.New(t),
|
|
}
|
|
if err := u.Do(ctx, in); err == nil {
|
|
t.Errorf("err wants non-nil but nil")
|
|
}
|
|
})
|
|
}
|