blob: 37d4dafc910c0fa0f3ec6c0428c413ee73d9942a [file]
// Copyright 2016 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 authdb
import (
"encoding/json"
"net"
"net/http"
"testing"
"golang.org/x/net/context"
"github.com/luci/luci-go/server/auth/identity"
"github.com/luci/luci-go/server/auth/internal"
"github.com/luci/luci-go/server/auth/service/protocol"
"github.com/luci/luci-go/server/auth/signing"
"github.com/luci/luci-go/server/auth/signing/signingtest"
. "github.com/smartystreets/goconvey/convey"
)
func TestSnapshotDB(t *testing.T) {
Convey("IsAllowedOAuthClientID works", t, func() {
c := context.Background()
db, err := NewSnapshotDB(&protocol.AuthDB{
OauthClientId: strPtr("primary-client-id"),
OauthAdditionalClientIds: []string{
"additional-client-id-1",
"additional-client-id-2",
},
}, "http://auth-service", 1234)
So(err, ShouldBeNil)
call := func(email, clientID string) bool {
res, err := db.IsAllowedOAuthClientID(c, email, clientID)
So(err, ShouldBeNil)
return res
}
So(call("abc@appspot.gserviceaccount.com", "anonymous"), ShouldBeTrue)
So(call("dude@example.com", ""), ShouldBeFalse)
So(call("dude@example.com", googleAPIExplorerClientID), ShouldBeTrue)
So(call("dude@example.com", "primary-client-id"), ShouldBeTrue)
So(call("dude@example.com", "additional-client-id-2"), ShouldBeTrue)
So(call("dude@example.com", "unknown-client-id"), ShouldBeFalse)
})
Convey("IsMember works", t, func() {
c := context.Background()
db, err := NewSnapshotDB(&protocol.AuthDB{
Groups: []*protocol.AuthGroup{
{
Name: strPtr("direct"),
Members: []string{"user:abc@example.com"},
},
{
Name: strPtr("via glob"),
Globs: []string{"user:*@example.com"},
},
{
Name: strPtr("via nested"),
Nested: []string{"direct"},
},
{
Name: strPtr("cycle"),
Nested: []string{"cycle"},
},
{
Name: strPtr("unknown nested"),
Nested: []string{"unknown"},
},
},
}, "http://auth-service", 1234)
So(err, ShouldBeNil)
call := func(ident string, groups ...string) bool {
res, err := db.IsMember(c, identity.Identity(ident), groups...)
So(err, ShouldBeNil)
return res
}
So(call("user:abc@example.com", "direct"), ShouldBeTrue)
So(call("user:another@example.com", "direct"), ShouldBeFalse)
So(call("user:abc@example.com", "via glob"), ShouldBeTrue)
So(call("user:abc@another.com", "via glob"), ShouldBeFalse)
So(call("user:abc@example.com", "via nested"), ShouldBeTrue)
So(call("user:another@example.com", "via nested"), ShouldBeFalse)
So(call("user:abc@example.com", "cycle"), ShouldBeFalse)
So(call("user:abc@example.com", "unknown"), ShouldBeFalse)
So(call("user:abc@example.com", "unknown nested"), ShouldBeFalse)
So(call("user:abc@example.com"), ShouldBeFalse)
So(call("user:abc@example.com", "unknown", "direct"), ShouldBeTrue)
So(call("user:abc@example.com", "via glob", "direct"), ShouldBeTrue)
})
Convey("GetCertificates works", t, func(c C) {
db, err := NewSnapshotDB(&protocol.AuthDB{
OauthClientId: strPtr("primary-client-id"),
OauthAdditionalClientIds: []string{
"additional-client-id-1",
"additional-client-id-2",
},
TokenServerUrl: strPtr("http://token-server"),
}, "http://auth-service", 1234)
So(err, ShouldBeNil)
tokenService := signingtest.NewSigner(1, &signing.ServiceInfo{
AppID: "token-server",
ServiceAccountName: "token-server-account@example.com",
})
calls := 0
ctx := context.Background()
ctx = internal.WithTestTransport(ctx, func(r *http.Request, body string) (int, string) {
calls++
if r.URL.String() != "http://token-server/auth/api/v1/server/certificates" {
return 404, "Wrong URL"
}
certs, err := tokenService.Certificates(ctx)
if err != nil {
panic(err)
}
blob, err := json.Marshal(certs)
if err != nil {
panic(err)
}
return 200, string(blob)
})
certs, err := db.GetCertificates(ctx, "user:token-server-account@example.com")
So(err, ShouldBeNil)
So(certs, ShouldNotBeNil)
// Fetched one bundle.
So(calls, ShouldEqual, 1)
// For unknown signer returns (nil, nil).
certs, err = db.GetCertificates(ctx, "user:unknown@example.com")
So(err, ShouldBeNil)
So(certs, ShouldBeNil)
})
Convey("IsInWhitelist works", t, func() {
c := context.Background()
db, err := NewSnapshotDB(&protocol.AuthDB{
IpWhitelistAssignments: []*protocol.AuthIPWhitelistAssignment{
{
Identity: strPtr("user:abc@example.com"),
IpWhitelist: strPtr("whitelist"),
},
},
IpWhitelists: []*protocol.AuthIPWhitelist{
{
Name: strPtr("whitelist"),
Subnets: []string{
"1.2.3.4/32",
"10.0.0.0/8",
},
},
{
Name: strPtr("empty"),
},
},
}, "http://auth-service", 1234)
So(err, ShouldBeNil)
wl, err := db.GetWhitelistForIdentity(c, "user:abc@example.com")
So(err, ShouldBeNil)
So(wl, ShouldEqual, "whitelist")
wl, err = db.GetWhitelistForIdentity(c, "user:unknown@example.com")
So(err, ShouldBeNil)
So(wl, ShouldEqual, "")
call := func(ip, whitelist string) bool {
ipaddr := net.ParseIP(ip)
So(ipaddr, ShouldNotBeNil)
res, err := db.IsInWhitelist(c, ipaddr, whitelist)
So(err, ShouldBeNil)
return res
}
So(call("1.2.3.4", "whitelist"), ShouldBeTrue)
So(call("10.255.255.255", "whitelist"), ShouldBeTrue)
So(call("9.255.255.255", "whitelist"), ShouldBeFalse)
So(call("1.2.3.4", "empty"), ShouldBeFalse)
})
}
func strPtr(s string) *string { return &s }
func BenchmarkIsMember(b *testing.B) {
c := context.Background()
db, _ := NewSnapshotDB(&protocol.AuthDB{
Groups: []*protocol.AuthGroup{
{
Name: strPtr("outer"),
Nested: []string{"A", "B"},
},
{
Name: strPtr("A"),
Nested: []string{"A_A", "A_B"},
},
{
Name: strPtr("B"),
Nested: []string{"B_A", "B_B"},
},
{
Name: strPtr("A_A"),
Nested: []string{"A_A_A"},
},
{
Name: strPtr("A_A_A"),
Nested: []string{"A_A_A_A"},
},
{
Name: strPtr("A_A_A_A"),
},
{
Name: strPtr("A_B"),
},
{
Name: strPtr("B_A"),
},
{
Name: strPtr("B_B"),
},
},
}, "http://auth-service", 1234)
b.ResetTimer()
for i := 0; i < b.N; i++ {
db.IsMember(c, "user:somedude@example.com", "outer")
}
}