Merge branch '21211-pysdk-annotations'
[arvados.git] / lib / controller / auth_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package controller
6
7 import (
8         "context"
9         "encoding/json"
10         "fmt"
11         "net"
12         "net/http"
13         "net/http/httptest"
14         "os"
15         "time"
16
17         "git.arvados.org/arvados.git/sdk/go/arvados"
18         "git.arvados.org/arvados.git/sdk/go/arvadostest"
19         "git.arvados.org/arvados.git/sdk/go/ctxlog"
20         "git.arvados.org/arvados.git/sdk/go/httpserver"
21         "github.com/sirupsen/logrus"
22         check "gopkg.in/check.v1"
23 )
24
25 // Gocheck boilerplate
26 var _ = check.Suite(&AuthSuite{})
27
28 type AuthSuite struct {
29         log logrus.FieldLogger
30         // testServer and testHandler are the controller being tested,
31         // "zhome".
32         testServer  *httpserver.Server
33         testHandler *Handler
34         // remoteServer ("zzzzz") forwards requests to the Rails API
35         // provided by the integration test environment.
36         remoteServer *httpserver.Server
37         // remoteMock ("zmock") appends each incoming request to
38         // remoteMockRequests, and returns 200 with an empty JSON
39         // object.
40         remoteMock         *httpserver.Server
41         remoteMockRequests []http.Request
42
43         fakeProvider *arvadostest.OIDCProvider
44 }
45
46 func (s *AuthSuite) SetUpTest(c *check.C) {
47         s.log = ctxlog.TestLogger(c)
48
49         s.remoteServer = newServerFromIntegrationTestEnv(c)
50         c.Assert(s.remoteServer.Start(), check.IsNil)
51
52         s.remoteMock = newServerFromIntegrationTestEnv(c)
53         s.remoteMock.Server.Handler = http.HandlerFunc(http.NotFound)
54         c.Assert(s.remoteMock.Start(), check.IsNil)
55
56         s.fakeProvider = arvadostest.NewOIDCProvider(c)
57         s.fakeProvider.AuthEmail = "active-user@arvados.local"
58         s.fakeProvider.AuthEmailVerified = true
59         s.fakeProvider.AuthName = "Fake User Name"
60         s.fakeProvider.ValidCode = fmt.Sprintf("abcdefgh-%d", time.Now().Unix())
61         s.fakeProvider.PeopleAPIResponse = map[string]interface{}{}
62         s.fakeProvider.ValidClientID = "test%client$id"
63         s.fakeProvider.ValidClientSecret = "test#client/secret"
64
65         cluster := &arvados.Cluster{
66                 ClusterID:       "zhome",
67                 PostgreSQL:      integrationTestCluster().PostgreSQL,
68                 SystemRootToken: arvadostest.SystemRootToken,
69         }
70         cluster.TLS.Insecure = true
71         cluster.API.MaxItemsPerResponse = 1000
72         cluster.API.MaxRequestAmplification = 4
73         cluster.API.RequestTimeout = arvados.Duration(5 * time.Minute)
74         arvadostest.SetServiceURL(&cluster.Services.RailsAPI, "https://"+os.Getenv("ARVADOS_TEST_API_HOST"))
75         arvadostest.SetServiceURL(&cluster.Services.Controller, "http://localhost/")
76
77         cluster.RemoteClusters = map[string]arvados.RemoteCluster{
78                 "zzzzz": {
79                         Host:   s.remoteServer.Addr,
80                         Proxy:  true,
81                         Scheme: "http",
82                 },
83                 "zmock": {
84                         Host:   s.remoteMock.Addr,
85                         Proxy:  true,
86                         Scheme: "http",
87                 },
88                 "*": {
89                         Scheme: "https",
90                 },
91         }
92         cluster.Login.OpenIDConnect.Enable = true
93         cluster.Login.OpenIDConnect.Issuer = s.fakeProvider.Issuer.URL
94         cluster.Login.OpenIDConnect.ClientID = s.fakeProvider.ValidClientID
95         cluster.Login.OpenIDConnect.ClientSecret = s.fakeProvider.ValidClientSecret
96         cluster.Login.OpenIDConnect.EmailClaim = "email"
97         cluster.Login.OpenIDConnect.EmailVerifiedClaim = "email_verified"
98         cluster.Login.OpenIDConnect.AcceptAccessToken = true
99         cluster.Login.OpenIDConnect.AcceptAccessTokenScope = ""
100
101         s.testHandler = &Handler{Cluster: cluster, BackgroundContext: ctxlog.Context(context.Background(), s.log)}
102         s.testServer = newServerFromIntegrationTestEnv(c)
103         s.testServer.Server.BaseContext = func(net.Listener) context.Context {
104                 return ctxlog.Context(context.Background(), s.log)
105         }
106         s.testServer.Server.Handler = httpserver.AddRequestIDs(httpserver.LogRequests(s.testHandler))
107         c.Assert(s.testServer.Start(), check.IsNil)
108 }
109
110 func (s *AuthSuite) TestLocalOIDCAccessToken(c *check.C) {
111         req := httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
112         req.Header.Set("Authorization", "Bearer "+s.fakeProvider.ValidAccessToken())
113         rr := httptest.NewRecorder()
114         s.testServer.Server.Handler.ServeHTTP(rr, req)
115         resp := rr.Result()
116         c.Check(resp.StatusCode, check.Equals, http.StatusOK)
117         var u arvados.User
118         c.Check(json.NewDecoder(resp.Body).Decode(&u), check.IsNil)
119         c.Check(u.UUID, check.Equals, arvadostest.ActiveUserUUID)
120         c.Check(u.OwnerUUID, check.Equals, "zzzzz-tpzed-000000000000000")
121
122         // Request again to exercise cache.
123         req = httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
124         req.Header.Set("Authorization", "Bearer "+s.fakeProvider.ValidAccessToken())
125         rr = httptest.NewRecorder()
126         s.testServer.Server.Handler.ServeHTTP(rr, req)
127         resp = rr.Result()
128         c.Check(resp.StatusCode, check.Equals, http.StatusOK)
129 }