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

Unified Diff: scheduler/appengine/acl/acl_test.go

Issue 2986033003: [scheduler]: ACLs phase 1 - per Job ACL specification and enforcement. (Closed)
Patch Set: Review. Created 3 years, 4 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
« no previous file with comments | « scheduler/appengine/acl/acl.go ('k') | scheduler/appengine/acl/doc.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: scheduler/appengine/acl/acl_test.go
diff --git a/scheduler/appengine/acl/acl_test.go b/scheduler/appengine/acl/acl_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..9ec1629bac73313e8a00a2ce356d5ae119170cdb
--- /dev/null
+++ b/scheduler/appengine/acl/acl_test.go
@@ -0,0 +1,218 @@
+// Copyright 2017 The LUCI Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package acl
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/luci/luci-go/appengine/gaetesting"
+ "github.com/luci/luci-go/scheduler/appengine/messages"
+ "github.com/luci/luci-go/server/auth"
+ "github.com/luci/luci-go/server/auth/authtest"
+ . "github.com/smartystreets/goconvey/convey"
+)
+
+func TestAclsValidation(t *testing.T) {
+ t.Parallel()
+
+ validGrant := &messages.Acl{Role: messages.Acl_READER, GrantedTo: "group:all"}
+ validGrants := []*messages.Acl{validGrant}
+
+ Convey("grant validation", t, func() {
+ So(validateGrants(validGrants), ShouldBeNil)
+
+ call := func(acls ...*messages.Acl) error {
+ return validateGrants(acls)
+ }
+ So(call(&messages.Acl{Role: messages.Acl_OWNER, GrantedTo: "e@example.com"}), ShouldBeNil)
+
+ So(call(&messages.Acl{Role: 3}).Error(), ShouldResemble, "invalid role \"3\"")
+ So(call(&messages.Acl{Role: messages.Acl_OWNER, GrantedTo: ""}).Error(),
+ ShouldResemble, "missing granted_to for role OWNER")
+ So(call(&messages.Acl{Role: messages.Acl_OWNER, GrantedTo: "group:"}).Error(),
+ ShouldResemble, "invalid granted_to \"group:\" for role OWNER: needs a group name")
+ So(call(&messages.Acl{Role: messages.Acl_OWNER, GrantedTo: "not-email"}).Error(),
+ ShouldStartWith, "invalid granted_to \"not-email\" for role OWNER: ")
+ So(call(&messages.Acl{Role: messages.Acl_OWNER, GrantedTo: "bot:"}).Error(),
+ ShouldStartWith, "invalid granted_to \"bot:\" for role OWNER: ")
+ })
+
+ validAclSet := &messages.AclSet{Name: "public", Acls: validGrants}
+
+ Convey("Validate AclSets", t, func() {
+ as, err := ValidateAclSets([]*messages.AclSet{validAclSet})
+ So(err, ShouldBeNil)
+ So(len(as), ShouldEqual, 1)
+ So(as["public"], ShouldResemble, validGrants)
+
+ shouldError := func(sets ...*messages.AclSet) {
+ _, err := ValidateAclSets(sets)
+ So(err, ShouldNotBeNil)
+ }
+
+ shouldError(&messages.AclSet{Name: "one"})
+ shouldError(&messages.AclSet{Name: "?bad i'd", Acls: validGrants})
+ shouldError(validAclSet, validAclSet)
+ })
+
+ Convey("Task Acls", t, func() {
+ Convey("Without AclSets", func() {
+ jobAcls, err := ValidateTaskAcls(nil, []string{}, validGrants)
+ So(err, ShouldBeNil)
+ So(jobAcls.Owners, ShouldResemble, []string{})
+ So(jobAcls.Readers, ShouldResemble, []string{"group:all"})
+ })
+
+ Convey("Without AclSets but with bad ACLs", func() {
+ _, err := ValidateTaskAcls(nil, []string{}, []*messages.Acl{
+ {Role: messages.Acl_OWNER, GrantedTo: ""}})
+ So(err, ShouldNotBeNil)
+ })
+
+ Convey("Many ACLs", func() {
+ taskGrants := make([]*messages.Acl, maxGrantsPerJob)
+ for i := 0; i < maxGrantsPerJob; i++ {
+ taskGrants[i] = &messages.Acl{Role: messages.Acl_OWNER, GrantedTo: fmt.Sprintf("group:%d", i)}
+ }
+ Convey("Hitting max is OK", func() {
+ r, err := ValidateTaskAcls(nil, []string{}, taskGrants)
+ So(err, ShouldBeNil)
+ So(len(r.Owners), ShouldEqual, maxGrantsPerJob)
+ })
+ Convey("1 too many", func() {
+ aclSets := map[string][]*messages.Acl{
+ "public": {{Role: messages.Acl_READER, GrantedTo: "group:all"}},
+ }
+ _, err := ValidateTaskAcls(aclSets, []string{"public"}, taskGrants)
+ So(err.Error(), ShouldResemble, "Job or Trigger can have at most 32 acls, but 33 given")
+ })
+ })
+
+ protoAclSets := []*messages.AclSet{
+ {Name: "public", Acls: []*messages.Acl{
+ {Role: messages.Acl_READER, GrantedTo: "group:all"},
+ {Role: messages.Acl_OWNER, GrantedTo: "group:owners"},
+ }},
+ {Name: "power-owners", Acls: []*messages.Acl{
+ {Role: messages.Acl_OWNER, GrantedTo: "group:power"},
+ }},
+ {Name: "private", Acls: []*messages.Acl{
+ {Role: messages.Acl_READER, GrantedTo: "group:internal"},
+ }},
+ }
+ aclSets, err := ValidateAclSets(protoAclSets)
+ So(err, ShouldBeNil)
+ So(len(aclSets), ShouldEqual, 3)
+
+ Convey("Bad acl_set reference in a task definition", func() {
+ _, err := ValidateTaskAcls(aclSets, []string{"typo"}, validGrants)
+ So(err.Error(), ShouldResemble, "referencing AclSet 'typo' which doesn't exist")
+ })
+
+ Convey("Merging", func() {
+ jobAcls, err := ValidateTaskAcls(
+ aclSets, []string{"public", "power-owners"},
+ []*messages.Acl{
+ {Role: messages.Acl_OWNER, GrantedTo: "me@example.com"},
+ {Role: messages.Acl_READER, GrantedTo: "you@example.com"},
+ })
+ So(err, ShouldBeNil)
+ So(jobAcls.Owners, ShouldResemble, []string{"group:owners", "group:power", "me@example.com"})
+ So(jobAcls.Readers, ShouldResemble, []string{"group:all", "you@example.com"})
+
+ jobAcls, err = ValidateTaskAcls(
+ aclSets, []string{"private"},
+ []*messages.Acl{
+ {Role: messages.Acl_OWNER, GrantedTo: "me@example.com"},
+ })
+ So(err, ShouldBeNil)
+ So(jobAcls.Owners, ShouldResemble, []string{"me@example.com"})
+ So(jobAcls.Readers, ShouldResemble, []string{"group:internal"})
+ })
+ })
+}
+
+func TestAclsChecks(t *testing.T) {
+ t.Parallel()
+ ctx := gaetesting.TestingContext()
+
+ basicGroups := GrantsByRole{Owners: []string{"group:owners"}, Readers: []string{"group:readers"}}
+
+ Convey("Admins are owners and readers", t, func() {
+ ctx = auth.WithState(ctx, &authtest.FakeState{
+ Identity: "user:admin@example.com",
+ IdentityGroups: []string{"administrators"},
+ })
+ yup, err := basicGroups.IsOwner(ctx)
+ So(err, ShouldBeNil)
+ So(yup, ShouldBeTrue)
+ yup, err = basicGroups.IsReader(ctx)
+ So(err, ShouldBeNil)
+ So(yup, ShouldBeTrue)
+ })
+ Convey("Owners", t, func() {
+ ctx = auth.WithState(ctx, &authtest.FakeState{
+ Identity: "user:owner@example.com",
+ IdentityGroups: []string{"owners"},
+ })
+ yup, err := basicGroups.IsReader(ctx)
+ So(err, ShouldBeNil)
+ So(yup, ShouldBeTrue)
+ yup, err = basicGroups.IsReader(ctx)
+ So(err, ShouldBeNil)
+ So(yup, ShouldBeTrue)
+ })
+ Convey("Readers", t, func() {
+ ctx = auth.WithState(ctx, &authtest.FakeState{
+ Identity: "user:reader@example.com",
+ IdentityGroups: []string{"readers"},
+ })
+ nope, err := basicGroups.IsOwner(ctx)
+ So(err, ShouldBeNil)
+ So(nope, ShouldBeFalse)
+ yup, err := basicGroups.IsReader(ctx)
+ So(err, ShouldBeNil)
+ So(yup, ShouldBeTrue)
+ })
+ Convey("By email", t, func() {
+ ctx = auth.WithState(ctx, &authtest.FakeState{
+ Identity: "user:reader@example.com",
+ IdentityGroups: []string{"all"},
+ })
+ g := GrantsByRole{
+ Owners: []string{"group:owners"},
+ Readers: []string{"group:some", "reader@example.com"},
+ }
+ nope, err := g.IsOwner(ctx)
+ So(err, ShouldBeNil)
+ So(nope, ShouldBeFalse)
+ yup, err := g.IsReader(ctx)
+ So(err, ShouldBeNil)
+ So(yup, ShouldBeTrue)
+ })
+}
+
+func TestAclsEqual(t *testing.T) {
+ t.Parallel()
+ Convey("GrantsByRole.Equal", t, func() {
+ x1 := GrantsByRole{Readers: []string{"a"}, Owners: []string{"b", "c"}}
+ x2 := GrantsByRole{Readers: []string{"a"}, Owners: []string{"b", "c"}}
+ So(x1.Equal(&x2), ShouldBeTrue)
+ y := GrantsByRole{Readers: []string{"e", "g"}, Owners: []string{"b", "d"}}
+ z := GrantsByRole{Readers: []string{"e", "g"}, Owners: []string{"b", "c", "d"}}
+ So(x1.Equal(&y), ShouldBeFalse)
+ So(y.Equal(&z), ShouldBeFalse)
+ })
+}
« no previous file with comments | « scheduler/appengine/acl/acl.go ('k') | scheduler/appengine/acl/doc.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698