mirror of
https://github.com/int128/kubelogin.git
synced 2026-02-14 16:39:51 +00:00
308 lines
9.9 KiB
Go
308 lines
9.9 KiB
Go
package integration_test
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/int128/kubelogin/integration_test/httpdriver"
|
|
"github.com/int128/kubelogin/integration_test/keypair"
|
|
"github.com/int128/kubelogin/integration_test/kubeconfig"
|
|
"github.com/int128/kubelogin/integration_test/oidcserver"
|
|
"github.com/int128/kubelogin/integration_test/oidcserver/testconfig"
|
|
"github.com/int128/kubelogin/pkg/di"
|
|
"github.com/int128/kubelogin/pkg/infrastructure/browser"
|
|
"github.com/int128/kubelogin/pkg/testing/clock"
|
|
"github.com/int128/kubelogin/pkg/testing/logger"
|
|
)
|
|
|
|
// Run the integration tests of the Login use-case.
|
|
//
|
|
// 1. Start the auth server.
|
|
// 2. Run the Cmd.
|
|
// 3. Open a request for the local server.
|
|
// 4. Verify the kubeconfig.
|
|
func TestStandalone(t *testing.T) {
|
|
timeout := 3 * time.Second
|
|
now := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
for name, tc := range map[string]struct {
|
|
keyPair keypair.KeyPair
|
|
args []string
|
|
}{
|
|
"NoTLS": {},
|
|
"TLS": {
|
|
keyPair: keypair.Server,
|
|
},
|
|
} {
|
|
httpDriverOption := httpdriver.Config{
|
|
TLSConfig: tc.keyPair.TLSConfig,
|
|
BodyContains: "Authenticated",
|
|
}
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Run("AuthCode", func(t *testing.T) {
|
|
t.Parallel()
|
|
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
|
|
defer cancel()
|
|
sv := oidcserver.New(t, tc.keyPair, testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(time.Hour),
|
|
},
|
|
})
|
|
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
|
|
Issuer: sv.IssuerURL(),
|
|
IDPCertificateAuthority: tc.keyPair.CACertPath,
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.New(ctx, t, httpDriverOption),
|
|
now: now,
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: sv.LastTokenResponse().RefreshToken,
|
|
})
|
|
})
|
|
|
|
t.Run("ROPC", func(t *testing.T) {
|
|
t.Parallel()
|
|
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
|
|
defer cancel()
|
|
sv := oidcserver.New(t, tc.keyPair, testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
Username: "USER1",
|
|
Password: "PASS1",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(time.Hour),
|
|
},
|
|
})
|
|
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
|
|
Issuer: sv.IssuerURL(),
|
|
IDPCertificateAuthority: tc.keyPair.CACertPath,
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.Zero(t),
|
|
now: now,
|
|
args: []string{
|
|
"--username", "USER1",
|
|
"--password", "PASS1",
|
|
},
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: sv.LastTokenResponse().RefreshToken,
|
|
})
|
|
})
|
|
|
|
t.Run("TokenLifecycle", func(t *testing.T) {
|
|
t.Parallel()
|
|
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
|
|
defer cancel()
|
|
sv := oidcserver.New(t, tc.keyPair, testconfig.Config{})
|
|
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
|
|
Issuer: sv.IssuerURL(),
|
|
IDPCertificateAuthority: tc.keyPair.CACertPath,
|
|
})
|
|
|
|
t.Run("NoToken", func(t *testing.T) {
|
|
sv.SetConfig(testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(time.Hour),
|
|
RefreshToken: "REFRESH_TOKEN_1",
|
|
},
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.New(ctx, t, httpDriverOption),
|
|
now: now,
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: "REFRESH_TOKEN_1",
|
|
})
|
|
})
|
|
t.Run("Valid", func(t *testing.T) {
|
|
sv.SetConfig(testconfig.Config{})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.Zero(t),
|
|
now: now,
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: "REFRESH_TOKEN_1",
|
|
})
|
|
})
|
|
t.Run("Refresh", func(t *testing.T) {
|
|
sv.SetConfig(testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
RefreshToken: "REFRESH_TOKEN_1",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(3 * time.Hour),
|
|
RefreshToken: "REFRESH_TOKEN_2",
|
|
},
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.New(ctx, t, httpDriverOption),
|
|
now: now.Add(2 * time.Hour),
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: "REFRESH_TOKEN_2",
|
|
})
|
|
})
|
|
t.Run("RefreshAgain", func(t *testing.T) {
|
|
sv.SetConfig(testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
RefreshToken: "REFRESH_TOKEN_2",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(5 * time.Hour),
|
|
},
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.New(ctx, t, httpDriverOption),
|
|
now: now.Add(4 * time.Hour),
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: "REFRESH_TOKEN_2",
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
t.Run("TLSData", func(t *testing.T) {
|
|
t.Parallel()
|
|
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
|
|
defer cancel()
|
|
sv := oidcserver.New(t, keypair.Server, testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(time.Hour),
|
|
},
|
|
})
|
|
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
|
|
Issuer: sv.IssuerURL(),
|
|
IDPCertificateAuthorityData: keypair.Server.CACertBase64,
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.New(ctx, t, httpdriver.Config{TLSConfig: keypair.Server.TLSConfig}),
|
|
now: now,
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: sv.LastTokenResponse().RefreshToken,
|
|
})
|
|
})
|
|
|
|
t.Run("env_KUBECONFIG", func(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
|
|
defer cancel()
|
|
sv := oidcserver.New(t, keypair.None, testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(time.Hour),
|
|
},
|
|
})
|
|
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
|
|
Issuer: sv.IssuerURL(),
|
|
})
|
|
t.Setenv("KUBECONFIG", kubeConfigFilename+string(os.PathListSeparator)+"kubeconfig/testdata/dummy.yaml")
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
httpDriver: httpdriver.New(ctx, t, httpdriver.Config{}),
|
|
now: now,
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: sv.LastTokenResponse().RefreshToken,
|
|
})
|
|
})
|
|
|
|
t.Run("ExtraScopes", func(t *testing.T) {
|
|
t.Parallel()
|
|
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
|
|
defer cancel()
|
|
sv := oidcserver.New(t, keypair.None, testconfig.Config{
|
|
Want: testconfig.Want{
|
|
Scope: "profile groups openid",
|
|
RedirectURIPrefix: "http://localhost:",
|
|
},
|
|
Response: testconfig.Response{
|
|
IDTokenExpiry: now.Add(time.Hour),
|
|
},
|
|
})
|
|
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
|
|
Issuer: sv.IssuerURL(),
|
|
ExtraScopes: "profile,groups",
|
|
})
|
|
runStandalone(t, ctx, standaloneConfig{
|
|
issuerURL: sv.IssuerURL(),
|
|
kubeConfigFilename: kubeConfigFilename,
|
|
httpDriver: httpdriver.New(ctx, t, httpdriver.Config{}),
|
|
now: now,
|
|
})
|
|
kubeconfig.Verify(t, kubeConfigFilename, kubeconfig.AuthProviderConfig{
|
|
IDToken: sv.LastTokenResponse().IDToken,
|
|
RefreshToken: sv.LastTokenResponse().RefreshToken,
|
|
})
|
|
})
|
|
}
|
|
|
|
type standaloneConfig struct {
|
|
issuerURL string
|
|
kubeConfigFilename string
|
|
httpDriver browser.Interface
|
|
now time.Time
|
|
args []string
|
|
}
|
|
|
|
func runStandalone(t *testing.T, ctx context.Context, cfg standaloneConfig) {
|
|
cmd := di.NewCmdForHeadless(clock.Fake(cfg.now), os.Stdin, os.Stdout, logger.New(t), cfg.httpDriver)
|
|
exitCode := cmd.Run(ctx, append([]string{
|
|
"kubelogin",
|
|
"--kubeconfig", cfg.kubeConfigFilename,
|
|
"--listen-address", "127.0.0.1:0",
|
|
}, cfg.args...), "HEAD")
|
|
if exitCode != 0 {
|
|
t.Errorf("exit status wants 0 but %d", exitCode)
|
|
}
|
|
}
|