diff options
author | Vladimir Shushlin <vshushlin@gitlab.com> | 2021-08-16 13:10:57 +0300 |
---|---|---|
committer | Vladimir Shushlin <vshushlin@gitlab.com> | 2021-08-16 13:10:57 +0300 |
commit | 84d1dde7f22aad875f75c2df768f6f2984a3ef4b (patch) | |
tree | 664f0e0c51993d076acb28bf020801d65558c9eb /test | |
parent | ab64173bdba62f9811edb105388f3a5922cfde14 (diff) | |
parent | a54a0b6a1c5f9dfe39a00e01aaacc4f0ddf9754a (diff) |
Merge branch '571-refactor-auth-acceptance-tests' into 'master'
Refactor auth acceptance tests
See merge request gitlab-org/gitlab-pages!540
Diffstat (limited to 'test')
-rw-r--r-- | test/acceptance/acceptance_test.go | 17 | ||||
-rw-r--r-- | test/acceptance/artifacts_test.go | 3 | ||||
-rw-r--r-- | test/acceptance/auth_test.go | 224 | ||||
-rw-r--r-- | test/acceptance/helpers_test.go | 78 | ||||
-rw-r--r-- | test/acceptance/stub_test.go | 67 | ||||
-rw-r--r-- | test/acceptance/testdata/api_responses.go | 46 |
6 files changed, 202 insertions, 233 deletions
diff --git a/test/acceptance/acceptance_test.go b/test/acceptance/acceptance_test.go index becae777..e6b50c10 100644 --- a/test/acceptance/acceptance_test.go +++ b/test/acceptance/acceptance_test.go @@ -67,20 +67,3 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } - -func skipUnlessEnabled(t *testing.T, conditions ...string) { - t.Helper() - - for _, condition := range conditions { - switch condition { - case "not-inplace-chroot": - if os.Getenv("TEST_DAEMONIZE") == "inplace" { - t.Log("Not supported with -daemon-inplace-chroot") - t.SkipNow() - } - default: - t.Error("Unknown condition:", condition) - t.FailNow() - } - } -} diff --git a/test/acceptance/artifacts_test.go b/test/acceptance/artifacts_test.go index 398b62a6..443fedbb 100644 --- a/test/acceptance/artifacts_test.go +++ b/test/acceptance/artifacts_test.go @@ -227,12 +227,11 @@ func TestPrivateArtifactProxyRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - configFile, cleanup := defaultConfigFileWith(t, + configFile := defaultConfigFileWith(t, "gitlab-server="+testServer.URL, "artifacts-server="+artifactServerURL, "auth-redirect-uri=https://projects.gitlab-example.com/auth", tt.binaryOption) - defer cleanup() RunPagesProcessWithStubGitLabServer(t, withListeners([]ListenSpec{httpsListener}), diff --git a/test/acceptance/auth_test.go b/test/acceptance/auth_test.go index c6948c13..152030b0 100644 --- a/test/acceptance/auth_test.go +++ b/test/acceptance/auth_test.go @@ -1,22 +1,20 @@ package acceptance_test import ( - "crypto/tls" "fmt" "io/ioutil" "net/http" "net/url" "os" - "regexp" "testing" - "time" "github.com/stretchr/testify/require" ) func TestWhenAuthIsDisabledPrivateIsNotAccessible(t *testing.T) { - teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "", "") - defer teardown() + RunPagesProcessWithStubGitLabServer(t, + withListeners([]ListenSpec{httpListener}), + ) rsp, err := GetPageFromListener(t, httpListener, "group.auth.gitlab-example.com", "private.project/") @@ -26,8 +24,7 @@ func TestWhenAuthIsDisabledPrivateIsNotAccessible(t *testing.T) { } func TestWhenAuthIsEnabledPrivateWillRedirectToAuthorize(t *testing.T) { - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), "https://internal-gitlab-auth.com", "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpsListener}) rsp, err := GetRedirectPage(t, httpsListener, "group.auth.gitlab-example.com", "private.project/") @@ -57,8 +54,7 @@ func TestWhenAuthIsEnabledPrivateWillRedirectToAuthorize(t *testing.T) { } func TestWhenAuthDeniedWillCauseUnauthorized(t *testing.T) { - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), "https://internal-gitlab-auth.com", "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpsListener}) rsp, err := GetPageFromListener(t, httpsListener, "projects.gitlab-example.com", "/auth?error=access_denied") @@ -68,8 +64,7 @@ func TestWhenAuthDeniedWillCauseUnauthorized(t *testing.T) { require.Equal(t, http.StatusUnauthorized, rsp.StatusCode) } func TestWhenLoginCallbackWithWrongStateShouldFail(t *testing.T) { - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), "https://internal-gitlab-auth.com", "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpsListener}) rsp, err := GetRedirectPage(t, httpsListener, "group.auth.gitlab-example.com", "private.project/") @@ -86,8 +81,7 @@ func TestWhenLoginCallbackWithWrongStateShouldFail(t *testing.T) { } func TestWhenLoginCallbackWithUnencryptedCode(t *testing.T) { - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), "https://internal-gitlab-auth.com", "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpsListener}) rsp, err := GetRedirectPage(t, httpsListener, "group.auth.gitlab-example.com", "private.project/") @@ -110,86 +104,14 @@ func TestWhenLoginCallbackWithUnencryptedCode(t *testing.T) { require.Equal(t, http.StatusInternalServerError, authrsp.StatusCode) } -func handleAccessControlArtifactRequests(t *testing.T, w http.ResponseWriter, r *http.Request) bool { - authorization := r.Header.Get("Authorization") - - switch { - case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/delayed_200.html`).MatchString(r.URL.Path): - sleepIfAuthorized(t, authorization, w) - return true - case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/404.html`).MatchString(r.URL.Path): - w.WriteHeader(http.StatusNotFound) - return true - case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/500.html`).MatchString(r.URL.Path): - returnIfAuthorized(t, authorization, w, http.StatusInternalServerError) - return true - case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/200.html`).MatchString(r.URL.Path): - returnIfAuthorized(t, authorization, w, http.StatusOK) - return true - case regexp.MustCompile(`/api/v4/projects/group/subgroup/private/jobs/\d+/artifacts/200.html`).MatchString(r.URL.Path): - returnIfAuthorized(t, authorization, w, http.StatusOK) - return true - default: - return false - } -} - -func handleAccessControlRequests(t *testing.T, w http.ResponseWriter, r *http.Request) { - allowedProjects := regexp.MustCompile(`/api/v4/projects/1\d{3}/pages_access`) - deniedProjects := regexp.MustCompile(`/api/v4/projects/2\d{3}/pages_access`) - invalidTokenProjects := regexp.MustCompile(`/api/v4/projects/3\d{3}/pages_access`) - - switch { - case allowedProjects.MatchString(r.URL.Path): - require.Equal(t, "Bearer abc", r.Header.Get("Authorization")) - w.WriteHeader(http.StatusOK) - case deniedProjects.MatchString(r.URL.Path): - require.Equal(t, "Bearer abc", r.Header.Get("Authorization")) - w.WriteHeader(http.StatusUnauthorized) - case invalidTokenProjects.MatchString(r.URL.Path): - require.Equal(t, "Bearer abc", r.Header.Get("Authorization")) - w.WriteHeader(http.StatusUnauthorized) - fmt.Fprint(w, "{\"error\":\"invalid_token\"}") - default: - t.Logf("Unexpected r.URL.RawPath: %q", r.URL.Path) - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.WriteHeader(http.StatusNotFound) - } -} - -func returnIfAuthorized(t *testing.T, authorization string, w http.ResponseWriter, status int) { - if authorization != "" { - require.Equal(t, "Bearer abc", authorization) - w.WriteHeader(status) - } else { - w.WriteHeader(http.StatusNotFound) - } -} - -func sleepIfAuthorized(t *testing.T, authorization string, w http.ResponseWriter) { - if authorization != "" { - require.Equal(t, "Bearer abc", authorization) - time.Sleep(2 * time.Second) - } else { - w.WriteHeader(http.StatusNotFound) - } -} - -func TestAccessControlUnderCustomDomain(t *testing.T) { - skipUnlessEnabled(t, "not-inplace-chroot") - - testServer := makeGitLabPagesAccessStub(t) - testServer.Start() - defer testServer.Close() - - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), testServer.URL, "https://public-gitlab-auth.com") - defer teardown() +func TestAccessControlUnderCustomDomainStandalone(t *testing.T) { + runPagesWithAuth(t, []ListenSpec{httpListener}) tests := map[string]struct { domain string path string }{ - "private_domain": { + "private_domain_only": { domain: "private.domain.com", path: "", }, @@ -258,13 +180,7 @@ func TestAccessControlUnderCustomDomain(t *testing.T) { } func TestCustomErrorPageWithAuth(t *testing.T) { - skipUnlessEnabled(t, "not-inplace-chroot") - testServer := makeGitLabPagesAccessStub(t) - testServer.Start() - defer testServer.Close() - - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), testServer.URL, "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpListener}) tests := []struct { name string @@ -294,7 +210,7 @@ func TestCustomErrorPageWithAuth(t *testing.T) { { name: "private_namespace_with_private_project_auth_failed", domain: "group.auth.gitlab-example.com", - // project ID is 2000 + // project ID is 2005 which causes a 401 path: "/private.project.1/unknown", expectedErrorPage: "The page you're looking for could not be found.", }, @@ -367,14 +283,7 @@ func TestCustomErrorPageWithAuth(t *testing.T) { } func TestAccessControlUnderCustomDomainWithHTTPSProxy(t *testing.T) { - skipUnlessEnabled(t, "not-inplace-chroot") - - testServer := makeGitLabPagesAccessStub(t) - testServer.Start() - defer testServer.Close() - - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), testServer.URL, "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{proxyListener}) rsp, err := GetProxyRedirectPageWithCookie(t, proxyListener, "private.domain.com", "/", "", true) require.NoError(t, err) @@ -435,8 +344,7 @@ func TestAccessControlUnderCustomDomainWithHTTPSProxy(t *testing.T) { } func TestAccessControlGroupDomain404RedirectsAuth(t *testing.T) { - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), "https://internal-gitlab-auth.com", "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpListener}) rsp, err := GetRedirectPage(t, httpListener, "group.gitlab-example.com", "/nonexistent/") require.NoError(t, err) @@ -448,9 +356,9 @@ func TestAccessControlGroupDomain404RedirectsAuth(t *testing.T) { require.Equal(t, "projects.gitlab-example.com", url.Host) require.Equal(t, "/auth", url.Path) } + func TestAccessControlProject404DoesNotRedirect(t *testing.T) { - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), "https://internal-gitlab-auth.com", "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{httpListener}) rsp, err := GetRedirectPage(t, httpListener, "group.gitlab-example.com", "/project/nonexistent/") require.NoError(t, err) @@ -458,119 +366,79 @@ func TestAccessControlProject404DoesNotRedirect(t *testing.T) { require.Equal(t, http.StatusNotFound, rsp.StatusCode) } -func setupTransport(t *testing.T) { - transport := (TestHTTPSClient.Transport).(*http.Transport) - defer func(t time.Duration) { - transport.ResponseHeaderTimeout = t - }(transport.ResponseHeaderTimeout) - transport.ResponseHeaderTimeout = 5 * time.Second -} - -type runPagesFunc func(t *testing.T, pagesPath string, listeners []ListenSpec, promPort string, sslCertFile string, authServer string) func() +type runPagesFunc func(t *testing.T, listeners []ListenSpec, sslCertFile string) func testAccessControl(t *testing.T, runPages runPagesFunc) { - skipUnlessEnabled(t, "not-inplace-chroot") - setupTransport(t) keyFile, certFile := CreateHTTPSFixtureFiles(t) - cert, err := tls.LoadX509KeyPair(certFile, keyFile) - require.NoError(t, err) t.Cleanup(func() { os.Remove(keyFile) os.Remove(certFile) }) - testServer := makeGitLabPagesAccessStub(t) - testServer.TLS = &tls.Config{Certificates: []tls.Certificate{cert}} - testServer.StartTLS() - defer testServer.Close() - - tests := []struct { + tests := map[string]struct { host string path string status int redirectBack bool - name string }{ - { - name: "project with access", + "project_with_access": { host: "group.auth.gitlab-example.com", path: "/private.project/", status: http.StatusOK, redirectBack: false, }, - { - name: "project without access", + "project_without_access": { host: "group.auth.gitlab-example.com", path: "/private.project.1/", status: http.StatusNotFound, // Do not expose project existed redirectBack: false, }, - { - name: "invalid token test should redirect back", + "invalid_token_test_should_redirect_back": { host: "group.auth.gitlab-example.com", path: "/private.project.2/", status: http.StatusFound, redirectBack: true, }, - { - name: "no project should redirect to login and then return 404", + "no_project_should_redirect_to_login_and_then_return404": { host: "group.auth.gitlab-example.com", path: "/nonexistent/", status: http.StatusNotFound, redirectBack: false, }, - { - name: "no project should redirect to login and then return 404", - host: "nonexistent.gitlab-example.com", - path: "/nonexistent/", - status: http.StatusNotFound, - redirectBack: false, - }, // subgroups - { - name: "[subgroup] project with access", + // subgroups + "subgroup_project_with_access": { host: "group.auth.gitlab-example.com", path: "/subgroup/private.project/", status: http.StatusOK, redirectBack: false, }, - { - name: "[subgroup] project without access", + "subgroup_project_without_access": { host: "group.auth.gitlab-example.com", path: "/subgroup/private.project.1/", status: http.StatusNotFound, // Do not expose project existed redirectBack: false, }, - { - name: "[subgroup] invalid token test should redirect back", + "subgroup_invalid_token_test_should_redirect_back": { host: "group.auth.gitlab-example.com", path: "/subgroup/private.project.2/", status: http.StatusFound, redirectBack: true, }, - { - name: "[subgroup] no project should redirect to login and then return 404", + "subgroup_no_project_should_redirect_to_login_and_then_return404": { host: "group.auth.gitlab-example.com", path: "/subgroup/nonexistent/", status: http.StatusNotFound, redirectBack: false, }, - { - name: "[subgroup] no project should redirect to login and then return 404", - host: "nonexistent.gitlab-example.com", - path: "/subgroup/nonexistent/", - status: http.StatusNotFound, - redirectBack: false, - }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - teardown := runPages(t, *pagesBinary, []ListenSpec{httpsListener}, "", certFile, testServer.URL) - defer teardown() + runPages(t, []ListenSpec{httpsListener}, certFile) + for tn, tt := range tests { + t.Run(tn, func(t *testing.T) { rsp1, err1 := GetRedirectPage(t, httpsListener, tt.host, tt.path) require.NoError(t, err1) defer rsp1.Body.Close() @@ -643,14 +511,7 @@ func TestAccessControlWithSSLCertDir(t *testing.T) { // Read the issue description if any changes to internal/auth/ break this test. // Related to https://tools.ietf.org/html/rfc6749#section-10.6. func TestHijackedCode(t *testing.T) { - skipUnlessEnabled(t, "not-inplace-chroot") - - testServer := makeGitLabPagesAccessStub(t) - testServer.Start() - defer testServer.Close() - - teardown := RunPagesProcessWithAuth(t, *pagesBinary, supportedListeners(), testServer.URL, "https://public-gitlab-auth.com") - defer teardown() + runPagesWithAuth(t, []ListenSpec{proxyListener}) /****ATTACKER******/ // get valid cookie for a different private project @@ -722,3 +583,26 @@ func getValidCookieAndState(t *testing.T, domain string) (string, string) { return cookie, state } + +func runPagesWithAuth(t *testing.T, listeners []ListenSpec) { + t.Helper() + + runPagesWithAuthAndEnv(t, listeners, nil) +} + +func runPagesWithAuthAndEnv(t *testing.T, listeners []ListenSpec, env []string) { + t.Helper() + + configFile := defaultConfigFileWith(t, + "gitlab-server=https://public-gitlab-auth.com", + "auth-redirect-uri=https://projects.gitlab-example.com/auth", + ) + + RunPagesProcessWithStubGitLabServer(t, + withListeners(listeners), + withArguments([]string{ + "-config=" + configFile, + }), + withEnv(env), + ) +} diff --git a/test/acceptance/helpers_test.go b/test/acceptance/helpers_test.go index a627cc00..4ea28b2a 100644 --- a/test/acceptance/helpers_test.go +++ b/test/acceptance/helpers_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "github.com/gorilla/mux" "github.com/pires/go-proxyproto" "github.com/stretchr/testify/require" "golang.org/x/net/nettest" @@ -255,25 +256,11 @@ func RunPagesProcessWithStubGitLabServer(t *testing.T, opts ...processOption) *L return logBuf } -func RunPagesProcessWithAuth(t *testing.T, pagesBinary string, listeners []ListenSpec, internalServer string, publicServer string) func() { - configFile, cleanup := defaultConfigFileWith(t, - "internal-gitlab-server="+internalServer, - "gitlab-server="+publicServer, - "auth-redirect-uri=https://projects.gitlab-example.com/auth") - defer cleanup() - - _, cleanup2 := runPagesProcess(t, true, pagesBinary, listeners, "", nil, - "-config="+configFile, - ) - return cleanup2 -} - -func RunPagesProcessWithGitlabServerWithSSLCertFile(t *testing.T, pagesBinary string, listeners []ListenSpec, promPort string, sslCertFile string, gitlabServer string) func() { - return runPagesProcessWithGitlabServer(t, pagesBinary, listeners, promPort, - []string{"SSL_CERT_FILE=" + sslCertFile}, gitlabServer) +func RunPagesProcessWithGitlabServerWithSSLCertFile(t *testing.T, listeners []ListenSpec, sslCertFile string) { + runPagesWithAuthAndEnv(t, listeners, []string{"SSL_CERT_FILE=" + sslCertFile}) } -func RunPagesProcessWithGitlabServerWithSSLCertDir(t *testing.T, pagesBinary string, listeners []ListenSpec, promPort string, sslCertFile string, gitlabServer string) func() { +func RunPagesProcessWithGitlabServerWithSSLCertDir(t *testing.T, listeners []ListenSpec, sslCertFile string) { // Create temporary cert dir sslCertDir, err := ioutil.TempDir("", "pages-test-SSL_CERT_DIR") require.NoError(t, err) @@ -282,24 +269,11 @@ func RunPagesProcessWithGitlabServerWithSSLCertDir(t *testing.T, pagesBinary str err = copyFile(sslCertDir+"/"+path.Base(sslCertFile), sslCertFile) require.NoError(t, err) - innerCleanup := runPagesProcessWithGitlabServer(t, pagesBinary, listeners, promPort, - []string{"SSL_CERT_DIR=" + sslCertDir}, gitlabServer) + runPagesWithAuthAndEnv(t, listeners, []string{"SSL_CERT_DIR=" + sslCertDir}) - return func() { - innerCleanup() + t.Cleanup(func() { os.RemoveAll(sslCertDir) - } -} - -func runPagesProcessWithGitlabServer(t *testing.T, pagesBinary string, listeners []ListenSpec, promPort string, extraEnv []string, gitlabServer string) func() { - configFile, cleanup := defaultConfigFileWith(t, - "gitlab-server="+gitlabServer, - "auth-redirect-uri=https://projects.gitlab-example.com/auth") - defer cleanup() - - _, cleanup2 := runPagesProcess(t, true, pagesBinary, listeners, promPort, extraEnv, - "-config="+configFile) - return cleanup2 + }) } func runPagesProcess(t *testing.T, wait bool, pagesBinary string, listeners []ListenSpec, promPort string, extraEnv []string, extraArgs ...string) (*LogCaptureBuffer, func()) { @@ -586,7 +560,7 @@ func NewGitlabDomainsSourceStub(t *testing.T, opts *stubOpts) *httptest.Server { currentStatusCount := 0 - mux := http.NewServeMux() + router := mux.NewRouter() statusHandler := func(w http.ResponseWriter, r *http.Request) { if currentStatusCount < opts.statusReadyCount { w.WriteHeader(http.StatusBadGateway) @@ -600,30 +574,38 @@ func NewGitlabDomainsSourceStub(t *testing.T, opts *stubOpts) *httptest.Server { statusHandler = opts.statusHandler } - mux.HandleFunc("/api/v4/internal/pages/status", statusHandler) + router.HandleFunc("/api/v4/internal/pages/status", statusHandler) pagesHandler := defaultAPIHandler(t, opts) if opts.pagesHandler != nil { pagesHandler = opts.pagesHandler } - mux.HandleFunc("/api/v4/internal/pages", pagesHandler) + router.HandleFunc("/api/v4/internal/pages", pagesHandler) authHandler := defaultAuthHandler(t, opts) if opts.authHandler != nil { authHandler = opts.authHandler } - mux.HandleFunc("/oauth/token", authHandler) + router.HandleFunc("/oauth/token", authHandler) userHandler := defaultUserHandler(t, opts) if opts.userHandler != nil { userHandler = opts.userHandler } - mux.HandleFunc("/api/v4/user", userHandler) + router.HandleFunc("/api/v4/user", userHandler) - return httptest.NewServer(mux) + router.HandleFunc("/api/v4/projects/{project_id:[0-9]+}/pages_access", func(w http.ResponseWriter, r *http.Request) { + if handleAccessControlArtifactRequests(t, w, r) { + return + } + + handleAccessControlRequests(t, w, r) + }) + + return httptest.NewServer(router) } func (o *stubOpts) setAPICalled(v bool) { @@ -720,7 +702,7 @@ func newConfigFile(t *testing.T, configs ...string) string { return f.Name() } -func defaultConfigFileWith(t *testing.T, configs ...string) (string, func()) { +func defaultConfigFileWith(t *testing.T, configs ...string) string { t.Helper() configs = append(configs, "auth-client-id=clientID", @@ -731,12 +713,12 @@ func defaultConfigFileWith(t *testing.T, configs ...string) (string, func()) { name := newConfigFile(t, configs...) - cleanup := func() { + t.Cleanup(func() { err := os.Remove(name) require.NoError(t, err) - } + }) - return name, cleanup + return name } func copyFile(dest, src string) error { @@ -760,3 +742,13 @@ func copyFile(dest, src string) error { _, err = io.Copy(destFile, srcFile) return err } + +func setupTransport(t *testing.T) { + t.Helper() + + transport := (TestHTTPSClient.Transport).(*http.Transport) + defer func(t time.Duration) { + transport.ResponseHeaderTimeout = t + }(transport.ResponseHeaderTimeout) + transport.ResponseHeaderTimeout = 5 * time.Second +} diff --git a/test/acceptance/stub_test.go b/test/acceptance/stub_test.go index a22f798a..10bd3cf6 100644 --- a/test/acceptance/stub_test.go +++ b/test/acceptance/stub_test.go @@ -5,7 +5,9 @@ import ( "io/ioutil" "net/http" "net/http/httptest" + "regexp" "testing" + "time" "github.com/stretchr/testify/require" @@ -135,3 +137,68 @@ func CreateGitLabAPISecretKeyFixtureFile(t *testing.T) (filepath string) { return secretfile.Name() } + +func handleAccessControlArtifactRequests(t *testing.T, w http.ResponseWriter, r *http.Request) bool { + authorization := r.Header.Get("Authorization") + + switch { + case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/delayed_200.html`).MatchString(r.URL.Path): + sleepIfAuthorized(t, authorization, w) + return true + case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/404.html`).MatchString(r.URL.Path): + w.WriteHeader(http.StatusNotFound) + return true + case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/500.html`).MatchString(r.URL.Path): + returnIfAuthorized(t, authorization, w, http.StatusInternalServerError) + return true + case regexp.MustCompile(`/api/v4/projects/group/private/jobs/\d+/artifacts/200.html`).MatchString(r.URL.Path): + returnIfAuthorized(t, authorization, w, http.StatusOK) + return true + case regexp.MustCompile(`/api/v4/projects/group/subgroup/private/jobs/\d+/artifacts/200.html`).MatchString(r.URL.Path): + returnIfAuthorized(t, authorization, w, http.StatusOK) + return true + default: + return false + } +} + +func handleAccessControlRequests(t *testing.T, w http.ResponseWriter, r *http.Request) { + allowedProjects := regexp.MustCompile(`/api/v4/projects/1\d{3}/pages_access`) + deniedProjects := regexp.MustCompile(`/api/v4/projects/2\d{3}/pages_access`) + invalidTokenProjects := regexp.MustCompile(`/api/v4/projects/3\d{3}/pages_access`) + + switch { + case allowedProjects.MatchString(r.URL.Path): + require.Equal(t, "Bearer abc", r.Header.Get("Authorization")) + w.WriteHeader(http.StatusOK) + case deniedProjects.MatchString(r.URL.Path): + require.Equal(t, "Bearer abc", r.Header.Get("Authorization")) + w.WriteHeader(http.StatusUnauthorized) + case invalidTokenProjects.MatchString(r.URL.Path): + require.Equal(t, "Bearer abc", r.Header.Get("Authorization")) + w.WriteHeader(http.StatusUnauthorized) + fmt.Fprint(w, "{\"error\":\"invalid_token\"}") + default: + t.Logf("Unexpected r.URL.RawPath: %q", r.URL.Path) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusNotFound) + } +} + +func returnIfAuthorized(t *testing.T, authorization string, w http.ResponseWriter, status int) { + if authorization != "" { + require.Equal(t, "Bearer abc", authorization) + w.WriteHeader(status) + } else { + w.WriteHeader(http.StatusNotFound) + } +} + +func sleepIfAuthorized(t *testing.T, authorization string, w http.ResponseWriter) { + if authorization != "" { + require.Equal(t, "Bearer abc", authorization) + time.Sleep(2 * time.Second) + } else { + w.WriteHeader(http.StatusNotFound) + } +} diff --git a/test/acceptance/testdata/api_responses.go b/test/acceptance/testdata/api_responses.go index b36563bb..10121f40 100644 --- a/test/acceptance/testdata/api_responses.go +++ b/test/acceptance/testdata/api_responses.go @@ -27,7 +27,16 @@ var DomainResponses = map[string]responseFn{ "zip-not-allowed-path.gitlab.io": customDomain(projectConfig{pathOnDisk: "../../../../"}), "group.gitlab-example.com": generateVirtualDomainFromDir("group", "group.gitlab-example.com", nil), "CapitalGroup.gitlab-example.com": generateVirtualDomainFromDir("CapitalGroup", "CapitalGroup.gitlab-example.com", nil), - "group.404.gitlab-example.com": generateVirtualDomainFromDir("group.404", "group.404.gitlab-example.com", nil), + "group.404.gitlab-example.com": generateVirtualDomainFromDir("group.404", "group.404.gitlab-example.com", map[string]projectConfig{ + "/private_project": { + projectID: 1300, + accessControl: true, + }, + "/private_unauthorized": { + projectID: 2000, + accessControl: true, + }, + }), "group.https-only.gitlab-example.com": generateVirtualDomainFromDir("group.https-only", "group.https-only.gitlab-example.com", map[string]projectConfig{ "/project1": { projectID: 1000, @@ -66,6 +75,41 @@ var DomainResponses = map[string]responseFn{ https: true, pathOnDisk: "group.https-only/project5", }), + "group.auth.gitlab-example.com": generateVirtualDomainFromDir("group.auth", "group.auth.gitlab-example.com", map[string]projectConfig{ + "/": { + projectID: 1005, + accessControl: true, + }, + "/private.project": { + projectID: 1006, + accessControl: true, + }, + "/private.project.1": { + projectID: 2006, + accessControl: true, + }, + "/private.project.2": { + projectID: 3006, + accessControl: true, + }, + "/subgroup/private.project": { + projectID: 1007, + accessControl: true, + }, + "/subgroup/private.project.1": { + projectID: 2007, + accessControl: true, + }, + "/subgroup/private.project.2": { + projectID: 3007, + accessControl: true, + }, + }), + "private.domain.com": customDomain(projectConfig{ + projectID: 1007, + accessControl: true, + pathOnDisk: "group.auth/private.project", + }), // NOTE: before adding more domains here, generate the zip archive by running (per project) // make zip PROJECT_SUBDIR=group/serving // make zip PROJECT_SUBDIR=group/project2 |