go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/projectscope/rpc_mint_project_token_test.go (about)

     1  // Copyright 2019 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package projectscope
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  	"time"
    21  
    22  	"go.opentelemetry.io/otel/trace"
    23  
    24  	"go.chromium.org/luci/appengine/gaetesting"
    25  	"go.chromium.org/luci/auth/identity"
    26  	"go.chromium.org/luci/common/clock/testclock"
    27  	"go.chromium.org/luci/common/logging"
    28  	"go.chromium.org/luci/common/testing/assertions"
    29  	"go.chromium.org/luci/server/auth"
    30  	"go.chromium.org/luci/server/auth/authtest"
    31  	"go.chromium.org/luci/server/auth/signing/signingtest"
    32  	"go.chromium.org/luci/tokenserver/api/minter/v1"
    33  	"go.chromium.org/luci/tokenserver/appengine/impl/utils/projectidentity"
    34  
    35  	. "github.com/smartystreets/goconvey/convey"
    36  )
    37  
    38  var (
    39  	authorizedGroups = []string{projectActorsGroup}
    40  	testingRequestID = trace.TraceID{1, 2, 3, 4, 5}
    41  )
    42  
    43  func testMintAccessToken(ctx context.Context, params auth.MintAccessTokenParams) (*auth.Token, error) {
    44  	return &auth.Token{
    45  		Token:  "",
    46  		Expiry: time.Now().UTC(),
    47  	}, nil
    48  }
    49  
    50  func testingContext(caller identity.Identity) context.Context {
    51  	ctx := gaetesting.TestingContext()
    52  	ctx = logging.SetLevel(ctx, logging.Debug)
    53  	ctx = trace.ContextWithSpanContext(ctx, trace.NewSpanContext(trace.SpanContextConfig{
    54  		TraceID: testingRequestID,
    55  	}))
    56  	ctx, _ = testclock.UseTime(ctx, testclock.TestTimeUTC)
    57  	return auth.WithState(ctx, &authtest.FakeState{
    58  		Identity:       caller,
    59  		IdentityGroups: authorizedGroups,
    60  	})
    61  
    62  }
    63  
    64  func newTestMintProjectTokenRPC() *MintProjectTokenRPC {
    65  	rpc := MintProjectTokenRPC{
    66  		Signer:            signingtest.NewSigner(nil),
    67  		MintAccessToken:   testMintAccessToken,
    68  		ProjectIdentities: projectidentity.ProjectIdentities,
    69  	}
    70  	return &rpc
    71  }
    72  
    73  func TestMintProjectToken(t *testing.T) {
    74  
    75  	t.Parallel()
    76  	ctx := testingContext("service@example.com")
    77  	member, err := auth.IsMember(ctx, projectActorsGroup)
    78  
    79  	Convey("initialize rpc handler", t, func() {
    80  		rpc := newTestMintProjectTokenRPC()
    81  
    82  		Convey("validateRequest works", func() {
    83  
    84  			Convey("empty fields", func() {
    85  				req := &minter.MintProjectTokenRequest{
    86  					LuciProject:         "",
    87  					OauthScope:          []string{},
    88  					MinValidityDuration: 7200,
    89  				}
    90  				_, err := rpc.MintProjectToken(ctx, req)
    91  				So(err, ShouldNotBeNil)
    92  			})
    93  
    94  			Convey("empty project", func() {
    95  
    96  				req := &minter.MintProjectTokenRequest{
    97  					LuciProject:         "",
    98  					OauthScope:          []string{"https://www.googleapis.com/auth/cloud-platform"},
    99  					MinValidityDuration: 1800,
   100  				}
   101  				_, err := rpc.MintProjectToken(ctx, req)
   102  				So(err, assertions.ShouldErrLike, `luci_project is empty`)
   103  			})
   104  
   105  			Convey("empty scopes", func() {
   106  
   107  				req := &minter.MintProjectTokenRequest{
   108  					LuciProject:         "foo-project",
   109  					OauthScope:          []string{},
   110  					MinValidityDuration: 1800,
   111  				}
   112  
   113  				_, err := rpc.MintProjectToken(ctx, req)
   114  				So(err, assertions.ShouldErrLike, `oauth_scope is required`)
   115  			})
   116  
   117  			Convey("returns nil for valid request", func() {
   118  				req := &minter.MintProjectTokenRequest{
   119  					LuciProject:         "test-project",
   120  					OauthScope:          []string{"https://www.googleapis.com/auth/cloud-platform"},
   121  					MinValidityDuration: 3600,
   122  				}
   123  				_, err := rpc.MintProjectToken(ctx, req)
   124  				So(err, assertions.ShouldErrLike, "min_validity_duration must not exceed 1800")
   125  			})
   126  		})
   127  
   128  		Convey("MintProjectToken does not return errors with valid input", func() {
   129  			So(err, ShouldBeNil)
   130  			So(member, ShouldBeTrue)
   131  
   132  			identity, err := rpc.ProjectIdentities(ctx).Create(
   133  				ctx,
   134  				&projectidentity.ProjectIdentity{Project: "service-project", Email: "foo@bar.com"})
   135  			So(err, ShouldBeNil)
   136  			So(identity, ShouldNotBeNil)
   137  
   138  			req := &minter.MintProjectTokenRequest{
   139  				LuciProject: "service-project",
   140  				OauthScope:  []string{"https://www.googleapis.com/auth/cloud-platform"},
   141  			}
   142  			resp, err := rpc.MintProjectToken(ctx, req)
   143  			So(err, ShouldBeNil)
   144  			So(resp, ShouldNotBeNil)
   145  
   146  		})
   147  
   148  	})
   149  
   150  }