summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-05-15 09:11:16 -0600
committermo khan <mo@mokhan.ca>2025-05-15 09:11:16 -0600
commit3d01a69471fc4f0ae9f2f4145620b6aea50f2216 (patch)
treef85607ebfb2575bce94b5618250ebd957f965f6e /test
parent7c75fac3360b8bc3df630b5f8e12b2ff927a2d23 (diff)
parent564e140de454c78d7e6d34044bb78f53bd0b2bf3 (diff)
Merge branch 'envoy-start' into 'main'
Enable Envoy to run consistently locally and in Docker See merge request gitlab-org/software-supply-chain-security/authorization/sparkled!6
Diffstat (limited to 'test')
-rw-r--r--test/integration/ci.go12
-rw-r--r--test/integration/container.go41
-rw-r--r--test/integration/container_test.go107
-rw-r--r--test/integration/http.go43
-rw-r--r--test/integration/logger.go15
-rw-r--r--test/integration/ui.go33
6 files changed, 188 insertions, 63 deletions
diff --git a/test/integration/ci.go b/test/integration/ci.go
new file mode 100644
index 0000000..7b5280f
--- /dev/null
+++ b/test/integration/ci.go
@@ -0,0 +1,12 @@
+package test
+
+import (
+ "testing"
+
+ "github.com/xlgmokha/x/pkg/env"
+)
+
+func isGitlabCI(t *testing.T) bool {
+ t.Logf("CI? %v\n", env.Fetch("CI", ""))
+ return env.Fetch("CI", "") == "true"
+}
diff --git a/test/integration/container.go b/test/integration/container.go
new file mode 100644
index 0000000..0a210dd
--- /dev/null
+++ b/test/integration/container.go
@@ -0,0 +1,41 @@
+package test
+
+import (
+ "context"
+ "net/http"
+ "testing"
+
+ xcontainer "github.com/docker/docker/api/types/container"
+ "github.com/docker/docker/api/types/network"
+ "github.com/docker/go-connections/nat"
+ "github.com/stretchr/testify/require"
+ "github.com/testcontainers/testcontainers-go"
+ "github.com/testcontainers/testcontainers-go/log"
+ "github.com/testcontainers/testcontainers-go/wait"
+ "github.com/xlgmokha/x/pkg/env"
+ "github.com/xlgmokha/x/pkg/x"
+)
+
+func NewContainer(t *testing.T, ctx context.Context, envVars map[string]string) *testcontainers.DockerContainer {
+ require.Equal(t, http.StatusOK, HttpGet(t, ctx, envVars["OIDC_ISSUER"]+"/.well-known/openid-configuration").StatusCode)
+ container, err := testcontainers.Run(
+ ctx,
+ env.Fetch("IMAGE_TAG", "sparkled:invalid"),
+ testcontainers.WithEnv(envVars),
+ testcontainers.WithLogConsumers(&Logger{TB: t}),
+ testcontainers.WithLogger(log.TestLogger(t)),
+ testcontainers.WithWaitStrategy(
+ wait.ForLog("Listening on"),
+ wait.ForListeningPort(x.Must(nat.NewPort("tcp", "10000"))),
+ wait.ForListeningPort(x.Must(nat.NewPort("tcp", "8080"))),
+ wait.ForListeningPort(x.Must(nat.NewPort("tcp", "9901"))),
+ ),
+ testcontainers.WithHostConfigModifier(func(cfg *xcontainer.HostConfig) {
+ cfg.NetworkMode = xcontainer.NetworkMode(network.NetworkHost)
+ }),
+ // testcontainers.WithExposedPorts("8080/tcp", "9901/tcp", "10000/tcp"),
+ // testcontainers.WithHostPortAccess(port),
+ )
+ require.NoError(t, err)
+ return container
+}
diff --git a/test/integration/container_test.go b/test/integration/container_test.go
index 40bbe74..b956250 100644
--- a/test/integration/container_test.go
+++ b/test/integration/container_test.go
@@ -6,72 +6,53 @@ package test
import (
"context"
"net/http"
- "net/url"
"testing"
"time"
- "github.com/oauth2-proxy/mockoidc"
- "github.com/playwright-community/playwright-go"
+ playwright "github.com/playwright-community/playwright-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
- "github.com/testcontainers/testcontainers-go/wait"
"github.com/xlgmokha/x/pkg/env"
- "github.com/xlgmokha/x/pkg/x"
"gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc"
)
-type TestLogConsumer struct {
- t *testing.T
-}
-
-func (lc *TestLogConsumer) Accept(l testcontainers.Log) {
- lc.t.Logf("%s", l.Content)
+func environmentVariables(srv *oidc.TestServer) map[string]string {
+ return map[string]string{
+ "APP_ENV": "test",
+ "BIND_ADDR": ":8080",
+ "DEBUG": env.Fetch("DEBUG", ""),
+ "HMAC_SESSION_SECRET": "secret",
+ "OAUTH_CLIENT_ID": srv.MockOIDC.ClientID,
+ "OAUTH_CLIENT_SECRET": srv.MockOIDC.ClientSecret,
+ "OAUTH_REDIRECT_URL": "",
+ "OIDC_ISSUER": srv.Issuer(),
+ }
}
func TestContainer(t *testing.T) {
- srv := oidc.NewTestServer(t)
- defer srv.Close()
-
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
- address, err := url.Parse(srv.MockOIDC.Addr())
- require.NoError(t, err)
-
- issuer := srv.Issuer()
- t.Logf("mockoidc: %v %v %v\n", address.String(), issuer, testcontainers.HostInternal)
- container, err := testcontainers.Run(
- ctx,
- env.Fetch("IMAGE_TAG", "sparkled:invalid"),
- testcontainers.WithEnv(map[string]string{
- "APP_ENV": "test",
- "BIND_ADDR": ":8080",
- "DEBUG": env.Fetch("DEBUG", ""),
- "HMAC_SESSION_SECRET": "secret",
- "OAUTH_CLIENT_ID": srv.MockOIDC.Config().ClientID,
- "OAUTH_CLIENT_SECRET": srv.MockOIDC.Config().ClientSecret,
- "OAUTH_REDIRECT_URL": "",
- "OIDC_ISSUER": issuer,
- }),
- testcontainers.WithExposedPorts("8080/tcp", "9901/tcp", "10000/tcp"),
- testcontainers.WithLogConsumers(&TestLogConsumer{t: t}),
- testcontainers.WithWaitStrategy(wait.ForLog("Listening on").WithStartupTimeout(time.Second*5)),
- )
- require.NoError(t, err)
+ srv := oidc.NewTestServer(t)
+ defer srv.Close()
+ container := NewContainer(t, ctx, environmentVariables(srv))
defer testcontainers.TerminateContainer(container)
- oidcProviderEndpoint := address.String()
+ require.True(t, container.IsRunning())
+
sparkleEndpoint, err := container.PortEndpoint(ctx, "8080", "http")
require.NoError(t, err)
envoyEndpoint, err := container.PortEndpoint(ctx, "10000", "http")
require.NoError(t, err)
- client := &http.Client{Timeout: 5 * time.Second}
+ envoyAdminEndpoint, err := container.PortEndpoint(ctx, "9901", "http")
+ require.NoError(t, err)
- publicPaths := []string{
+ for _, publicPath := range []string{
+ envoyAdminEndpoint + "/",
envoyEndpoint + "/",
envoyEndpoint + "/application.js",
envoyEndpoint + "/favicon.ico",
@@ -79,43 +60,43 @@ func TestContainer(t *testing.T) {
envoyEndpoint + "/health",
envoyEndpoint + "/index.html",
envoyEndpoint + "/logo.png",
- oidcProviderEndpoint + mockoidc.DiscoveryEndpoint,
sparkleEndpoint + "/",
sparkleEndpoint + "/favicon.ico",
sparkleEndpoint + "/health",
- }
-
- for _, path := range publicPaths {
- t.Run(path, func(t *testing.T) {
- request, err := http.NewRequestWithContext(ctx, http.MethodGet, path, nil)
- response, err := client.Do(request)
- require.NoError(t, err)
- assert.Equal(t, http.StatusOK, response.StatusCode)
+ srv.DiscoveryEndpoint(),
+ } {
+ t.Run(publicPath, func(t *testing.T) {
+ assert.Equal(t, http.StatusOK, HttpGet(t, ctx, publicPath).StatusCode)
})
}
- t.Run("UI", func(t *testing.T) {
- if env.Fetch("SKIP_E2E", "") != "" {
- t.Skip()
- }
+ t.Run("envoy.yaml", func(t *testing.T) {
+ response := HttpGet(t, ctx, envoyAdminEndpoint+"/config_dump")
- _ = playwright.Install()
+ require.Equal(t, http.StatusOK, response.StatusCode)
+ body := JSONBody[map[string]interface{}](t, response)
- pw := x.Must(playwright.Run())
- browser := x.Must(pw.Firefox.Launch(playwright.BrowserTypeLaunchOptions{
- Headless: playwright.Bool(env.Fetch("HEADLESS", "true") == "true"),
- SlowMo: playwright.Float(1000),
- }))
- page := x.Must(browser.NewPage())
+ assert.NotEmpty(t, "listener_0", body["configs"])
+ })
- defer browser.Close()
- defer pw.Stop()
+ WithUI(t, func(browser playwright.Browser) {
+ page, err := browser.NewPage()
+ require.NoError(t, err)
t.Run("initiates an OIDC login", func(t *testing.T) {
require.NoError(t, page.Context().ClearCookies())
- response, err := page.Goto(sparkleEndpoint + "/")
+ response, err := page.Goto(envoyEndpoint + "/")
require.NoError(t, err)
assert.True(t, response.Ok())
+
+ t.Run("redirects to the OpenID Connect Provider", func(t *testing.T) {
+ t.Skip()
+
+ require.NoError(t, page.GetByText("Login").Click())
+ // The envoy.yaml configuration has a hardcoded path that doesn't match the one provided by mockoidc
+ // because the oauth2 envoy filter doesn't support the OIDC discovery endpoint.
+ assert.Contains(t, page.URL(), srv.AuthorizationEndpoint()+"?client_id="+srv.MockOIDC.ClientID)
+ })
})
})
}
diff --git a/test/integration/http.go b/test/integration/http.go
new file mode 100644
index 0000000..20991a2
--- /dev/null
+++ b/test/integration/http.go
@@ -0,0 +1,43 @@
+package test
+
+import (
+ "context"
+ "net/http"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+ "github.com/xlgmokha/x/pkg/serde"
+)
+
+type testTransport struct {
+ t *testing.T
+}
+
+func (r *testTransport) RoundTrip(request *http.Request) (*http.Response, error) {
+ response, err := http.DefaultTransport.RoundTrip(request)
+ require.NoError(r.t, err)
+ r.t.Logf("%v %v %v\n", response.StatusCode, request.Method, request.URL)
+ return response, err
+}
+
+func HttpGet(t *testing.T, ctx context.Context, path string) *http.Response {
+ client := &http.Client{
+ Timeout: 5 * time.Second,
+ Transport: &testTransport{t: t},
+ }
+
+ request, err := http.NewRequestWithContext(ctx, http.MethodGet, path, nil)
+ require.NoError(t, err)
+
+ response, err := client.Do(request)
+ require.NoError(t, err)
+
+ return response
+}
+
+func JSONBody[T any](t *testing.T, r *http.Response) T {
+ item, err := serde.FromJSON[T](r.Body)
+ require.NoError(t, err)
+ return item
+}
diff --git a/test/integration/logger.go b/test/integration/logger.go
new file mode 100644
index 0000000..86660bc
--- /dev/null
+++ b/test/integration/logger.go
@@ -0,0 +1,15 @@
+package test
+
+import (
+ "testing"
+
+ "github.com/testcontainers/testcontainers-go"
+)
+
+type Logger struct {
+ testing.TB
+}
+
+func (t *Logger) Accept(l testcontainers.Log) {
+ t.Logf("%s", l.Content)
+}
diff --git a/test/integration/ui.go b/test/integration/ui.go
new file mode 100644
index 0000000..1af0744
--- /dev/null
+++ b/test/integration/ui.go
@@ -0,0 +1,33 @@
+package test
+
+import (
+ "testing"
+
+ playwright "github.com/playwright-community/playwright-go"
+ "github.com/stretchr/testify/require"
+ "github.com/xlgmokha/x/pkg/env"
+ "github.com/xlgmokha/x/pkg/x"
+)
+
+func WithUI(t *testing.T, callback x.Visitor[playwright.Browser]) {
+ t.Run("UI", func(t *testing.T) {
+ if isGitlabCI(t) {
+ t.Skip()
+ }
+ _ = playwright.Install()
+
+ driver, err := playwright.Run()
+ require.NoError(t, err)
+
+ browser, err := driver.Firefox.Launch(playwright.BrowserTypeLaunchOptions{
+ Headless: playwright.Bool(env.Fetch("HEADLESS", "true") == "true"),
+ SlowMo: playwright.Float(1000),
+ })
+ require.NoError(t, err)
+
+ defer browser.Close()
+ defer driver.Stop()
+
+ callback(browser)
+ })
+}