| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package delegation | 5 package delegation |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | |
| 9 "io/ioutil" | |
| 10 "net/http" | 8 "net/http" |
| 11 "testing" | 9 "testing" |
| 12 "time" | 10 "time" |
| 13 | 11 |
| 14 "golang.org/x/net/context" | 12 "golang.org/x/net/context" |
| 15 | 13 |
| 16 "github.com/luci/luci-go/common/clock/testclock" | 14 "github.com/luci/luci-go/common/clock/testclock" |
| 17 "github.com/luci/luci-go/common/logging/memlogger" | 15 "github.com/luci/luci-go/common/logging/memlogger" |
| 18 "github.com/luci/luci-go/server/auth/identity" | 16 "github.com/luci/luci-go/server/auth/identity" |
| 19 "github.com/luci/luci-go/server/auth/internal" | 17 "github.com/luci/luci-go/server/auth/internal" |
| 20 | 18 |
| 21 . "github.com/luci/luci-go/common/testing/assertions" | 19 . "github.com/luci/luci-go/common/testing/assertions" |
| 22 . "github.com/smartystreets/goconvey/convey" | 20 . "github.com/smartystreets/goconvey/convey" |
| 23 ) | 21 ) |
| 24 | 22 |
| 25 func TestCreateToken(t *testing.T) { | 23 func TestCreateToken(t *testing.T) { |
| 26 ctx := memlogger.Use(context.Background()) | 24 ctx := memlogger.Use(context.Background()) |
| 27 ctx, _ = testclock.UseTime(ctx, testclock.TestRecentTimeUTC) | 25 ctx, _ = testclock.UseTime(ctx, testclock.TestRecentTimeUTC) |
| 28 | 26 |
| 29 goodReq := TokenRequest{ | 27 goodReq := TokenRequest{ |
| 30 AuthServiceURL: "example.com", | 28 AuthServiceURL: "example.com", |
| 31 Audience: []identity.Identity{"user:a@example.com"}, | 29 Audience: []identity.Identity{"user:a@example.com"}, |
| 32 AudienceGroups: []string{"group"}, | 30 AudienceGroups: []string{"group"}, |
| 33 TargetServices: []identity.Identity{"service:abc"}, | 31 TargetServices: []identity.Identity{"service:abc"}, |
| 34 Impersonate: "user:b@example.com", | 32 Impersonate: "user:b@example.com", |
| 35 ValidityDuration: time.Hour, | 33 ValidityDuration: time.Hour, |
| 36 Intent: "intent", | 34 Intent: "intent", |
| 37 } | 35 } |
| 38 | 36 |
| 39 » ctx, tr := withTestTransport(ctx, `{ | 37 » lastRequestBody := "" |
| 40 » » "delegation_token": "tok", | 38 » ctx = internal.WithTestTransport(ctx, func(r *http.Request, body string)
(int, string) { |
| 41 » » "validity_duration": 3600, | 39 » » lastRequestBody = body |
| 42 » » "subtoken_id": "123" | 40 » » return 200, `{ |
| 43 » }`) | 41 » » » "delegation_token": "tok", |
| 42 » » » "validity_duration": 3600, |
| 43 » » » "subtoken_id": "123" |
| 44 » » }` |
| 45 » }) |
| 44 | 46 |
| 45 Convey("Works", t, func() { | 47 Convey("Works", t, func() { |
| 46 tok, err := CreateToken(ctx, goodReq) | 48 tok, err := CreateToken(ctx, goodReq) |
| 47 So(err, ShouldBeNil) | 49 So(err, ShouldBeNil) |
| 48 So(tok, ShouldResemble, &Token{ | 50 So(tok, ShouldResemble, &Token{ |
| 49 Token: "tok", | 51 Token: "tok", |
| 50 SubtokenID: "123", | 52 SubtokenID: "123", |
| 51 Expiry: testclock.TestRecentTimeUTC.Add(time.Hour), | 53 Expiry: testclock.TestRecentTimeUTC.Add(time.Hour), |
| 52 }) | 54 }) |
| 53 » » So(tr.request, ShouldEqual, | 55 » » So(lastRequestBody, ShouldEqual, |
| 54 `{"audience":["user:a@example.com","group:group"],`+ | 56 `{"audience":["user:a@example.com","group:group"],`+ |
| 55 `"services":["service:abc"],"validity_duration":
3600,`+ | 57 `"services":["service:abc"],"validity_duration":
3600,`+ |
| 56 `"impersonate":"user:b@example.com","intent":"in
tent"}`) | 58 `"impersonate":"user:b@example.com","intent":"in
tent"}`) |
| 57 }) | 59 }) |
| 58 | 60 |
| 59 Convey("Audience check works", t, func() { | 61 Convey("Audience check works", t, func() { |
| 60 req := goodReq | 62 req := goodReq |
| 61 req.Audience = nil | 63 req.Audience = nil |
| 62 req.AudienceGroups = nil | 64 req.AudienceGroups = nil |
| 63 _, err := CreateToken(ctx, req) | 65 _, err := CreateToken(ctx, req) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 87 _, err = CreateToken(ctx, req) | 89 _, err = CreateToken(ctx, req) |
| 88 So(err, ShouldErrLike, "can't specify TargetServices for Untarge
ted=true token") | 90 So(err, ShouldErrLike, "can't specify TargetServices for Untarge
ted=true token") |
| 89 | 91 |
| 90 req = goodReq | 92 req = goodReq |
| 91 req.TargetServices = nil | 93 req.TargetServices = nil |
| 92 req.Untargeted = true | 94 req.Untargeted = true |
| 93 _, err = CreateToken(ctx, req) | 95 _, err = CreateToken(ctx, req) |
| 94 So(err, ShouldBeNil) | 96 So(err, ShouldBeNil) |
| 95 }) | 97 }) |
| 96 } | 98 } |
| 97 | |
| 98 var testTransportKey = "key for testTransport" | |
| 99 | |
| 100 func withTestTransport(c context.Context, response string) (context.Context, *te
stTransport) { | |
| 101 t := &testTransport{response: response} | |
| 102 return context.WithValue(c, &testTransportKey, t), t | |
| 103 } | |
| 104 | |
| 105 type testTransport struct { | |
| 106 response string | |
| 107 request string | |
| 108 } | |
| 109 | |
| 110 func (f *testTransport) RoundTrip(r *http.Request) (*http.Response, error) { | |
| 111 body, err := ioutil.ReadAll(r.Body) | |
| 112 r.Body.Close() | |
| 113 if err != nil { | |
| 114 return nil, err | |
| 115 } | |
| 116 f.request = string(body) | |
| 117 return &http.Response{ | |
| 118 StatusCode: 200, | |
| 119 Status: "OK", | |
| 120 Body: ioutil.NopCloser(bytes.NewReader([]byte(f.response))
), | |
| 121 }, nil | |
| 122 } | |
| 123 | |
| 124 func init() { | |
| 125 internal.RegisterClientFactory(func(c context.Context, scopes []string)
(*http.Client, error) { | |
| 126 return &http.Client{Transport: c.Value(&testTransportKey).(*test
Transport)}, nil | |
| 127 }) | |
| 128 } | |
| OLD | NEW |