Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Unified Diff: tokenserver/appengine/delegation/rpc_mint_delegation_token_test.go

Issue 2413683004: token-server: Delegation config import, validation and evaluation. (Closed)
Patch Set: also check validity_duration Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tokenserver/appengine/delegation/rpc_mint_delegation_token_test.go
diff --git a/tokenserver/appengine/delegation/rpc_mint_delegation_token_test.go b/tokenserver/appengine/delegation/rpc_mint_delegation_token_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..8429a79f58350acc3a6e364d67240d21231ef9cf
--- /dev/null
+++ b/tokenserver/appengine/delegation/rpc_mint_delegation_token_test.go
@@ -0,0 +1,295 @@
+// Copyright 2016 The LUCI Authors. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+package delegation
+
+import (
+ "fmt"
+ "net/url"
+ "testing"
+
+ "golang.org/x/net/context"
+
+ "github.com/luci/luci-go/server/auth"
+ "github.com/luci/luci-go/server/auth/authtest"
+ "github.com/luci/luci-go/server/auth/identity"
+ admin "github.com/luci/luci-go/tokenserver/api/admin/v1"
+ minter "github.com/luci/luci-go/tokenserver/api/minter/v1"
+
+ . "github.com/luci/luci-go/common/testing/assertions"
+ . "github.com/smartystreets/goconvey/convey"
+)
+
+func mockedFetchLUCIServiceIdentity(c context.Context, u string) (identity.Identity, error) {
+ l, err := url.Parse(u)
+ if err != nil {
+ return "", err
+ }
+ if l.Scheme != "https" {
+ return "", fmt.Errorf("wrong scheme")
+ }
+ if l.Host == "crash" {
+ return "", fmt.Errorf("boom")
+ }
+ return identity.MakeIdentity("service:" + l.Host)
+}
+
+func init() {
+ fetchLUCIServiceIdentity = mockedFetchLUCIServiceIdentity
+}
+
+func TestBuildRulesQuery(t *testing.T) {
+ ctx := context.Background()
+
+ Convey("Happy path", t, func() {
+ q, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "user:delegated@example.com",
+ Audience: []string{"group:A", "group:B", "user:c@example.com"},
+ Services: []string{"service:A", "*"},
+ }, "user:requestor@example.com")
+ So(err, ShouldBeNil)
+ So(q, ShouldNotBeNil)
+
+ So(q.Requestor, ShouldEqual, "user:requestor@example.com")
+ So(q.Delegatee, ShouldEqual, "user:delegated@example.com")
+ So(q.Audience.ToStrings(), ShouldResemble, []string{"group:A", "group:B", "user:c@example.com"})
+ So(q.Services.ToStrings(), ShouldResemble, []string{"*"})
+ })
+
+ Convey("REQUESTOR usage works", t, func() {
+ q, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"group:A", "group:B", "REQUESTOR"},
+ Services: []string{"*"},
+ }, "user:requestor@example.com")
+ So(err, ShouldBeNil)
+ So(q, ShouldNotBeNil)
+
+ So(q.Requestor, ShouldEqual, "user:requestor@example.com")
+ So(q.Delegatee, ShouldEqual, "user:requestor@example.com")
+ So(q.Audience.ToStrings(), ShouldResemble, []string{"group:A", "group:B", "user:requestor@example.com"})
+ })
+
+ Convey("bad 'delegated_identity'", t, func() {
+ _, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `'delegated_identity' is required`)
+
+ _, err = buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "junk",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `bad 'delegated_identity' - auth: bad identity string "junk"`)
+ })
+
+ Convey("bad 'audience'", t, func() {
+ _, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Services: []string{"*"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `'audience' is required`)
+
+ _, err = buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR", "junk"},
+ Services: []string{"*"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `bad 'audience' - auth: bad identity string "junk"`)
+ })
+
+ Convey("bad 'services'", t, func() {
+ _, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `'services' is required`)
+
+ _, err = buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"junk"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `bad 'services' - auth: bad identity string "junk"`)
+
+ _, err = buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"user:abc@example.com"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `bad 'services' - "user:abc@example.com" is not a service ID`)
+
+ _, err = buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"group:abc"},
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `bad 'services' - can't specify groups`)
+ })
+
+ Convey("resolves https:// service refs", t, func() {
+ q, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "user:delegated@example.com",
+ Audience: []string{"*"},
+ Services: []string{
+ "service:A",
+ "service:B",
+ "https://C",
+ "https://B",
+ "https://A",
+ },
+ }, "user:requestor@example.com")
+ So(err, ShouldBeNil)
+ So(q, ShouldNotBeNil)
+
+ So(q.Services.ToStrings(), ShouldResemble, []string{
+ "service:A",
+ "service:B",
+ "service:C",
+ })
+ })
+
+ Convey("handles errors when resolving https:// service refs", t, func() {
+ _, err := buildRulesQuery(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "user:delegated@example.com",
+ Audience: []string{"*"},
+ Services: []string{
+ "https://A",
+ "https://B",
+ "https://crash",
+ },
+ }, "user:requestor@example.com")
+ So(err, ShouldErrLike, `could not resolve "https://crash" to service ID - boom`)
+ })
+}
+
+func TestMintDelegationToken(t *testing.T) {
+ Convey("with mocked config and state", t, func() {
+ cfg, err := loadConfig(`
+ rules {
+ name: "requstor for itself"
+ requestor: "user:requestor@example.com"
+ target_service: "*"
+ allowed_to_impersonate: "REQUESTOR"
+ allowed_audience: "REQUESTOR"
+ max_validity_duration: 3600
+ }
+ `)
+ So(err, ShouldBeNil)
+
+ mintMock := func(context.Context, *minter.MintDelegationTokenRequest,
+ *RulesQuery, *admin.DelegationRule) (*minter.MintDelegationTokenResponse, error) {
+ return &minter.MintDelegationTokenResponse{Token: "valid_token"}, nil
+ }
+
+ rpc := MintDelegationTokenRPC{
+ ConfigLoader: func(context.Context) (*DelegationConfig, error) { return cfg, nil },
+ mintMock: mintMock,
+ }
+
+ Convey("Happy path", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:requestor@example.com",
+ })
+ resp, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ })
+ So(err, ShouldBeNil)
+ So(resp.Token, ShouldEqual, "valid_token")
+ })
+
+ Convey("Using delegated identity for auth is forbidden", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:requestor@example.com",
+ PeerIdentityOverride: "user:impersonator@example.com",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ })
+ So(err, ShouldErrLike, `code = 7 desc = delegation is forbidden for this API call`)
+ })
+
+ Convey("Anonymous calls are forbidden", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "anonymous:anonymous",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ })
+ So(err, ShouldErrLike, `code = 16 desc = authentication required`)
+ })
+
+ Convey("Unauthorized requestor", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:unknown@example.cim",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ })
+ So(err, ShouldErrLike, `code = 7 desc = not authorized`)
+ })
+
+ Convey("Negative validity duration", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:requestor@example.com",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ ValidityDuration: -1,
+ })
+ So(err, ShouldErrLike, `code = 3 desc = bad request - invalid 'validity_duration' (-1)`)
+ })
+
+ Convey("Malformed request", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:requestor@example.com",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"junk"},
+ Services: []string{"*"},
+ })
+ So(err, ShouldErrLike, `code = 3 desc = bad request - bad 'audience' - auth: bad identity string "junk"`)
+ })
+
+ Convey("No matching rules", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:requestor@example.com",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"user:someone-else@example.com"},
+ Services: []string{"*"},
+ })
+ So(err, ShouldErrLike, `code = 7 desc = forbidden - no matching delegation rules in the config`)
+ })
+
+ Convey("Forbidden validity duration", func() {
+ ctx := auth.WithState(context.Background(), &authtest.FakeState{
+ Identity: "user:requestor@example.com",
+ })
+ _, err := rpc.MintDelegationToken(ctx, &minter.MintDelegationTokenRequest{
+ DelegatedIdentity: "REQUESTOR",
+ Audience: []string{"REQUESTOR"},
+ Services: []string{"*"},
+ ValidityDuration: 3601,
+ })
+ So(err, ShouldErrLike,
+ `rpc error: code = 7 desc = forbidden - the requested validity duration (3601 sec) exceeds the maximum allowed one (3600 sec)`)
+ })
+
+ })
+}
« no previous file with comments | « tokenserver/appengine/delegation/rpc_mint_delegation_token.go ('k') | tokenserver/appengine/delegation/validation.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698