| package security |
| |
| import ( |
| "bytes" |
| "fmt" |
| "reflect" |
| "strings" |
| "testing" |
| "time" |
| |
| "veyron.io/veyron/veyron/runtimes/google/security/keys" |
| |
| "veyron.io/veyron/veyron2/security" |
| "veyron.io/veyron/veyron2/vom" |
| ) |
| |
| var ( |
| // Trusted identity providers |
| // (type assertion just to ensure test sanity) |
| veyronChain = newChain("veyron").(*chainPrivateID) |
| googleChain = newChain("google").(*chainPrivateID) |
| ) |
| |
| type dischargeMap map[string]security.Discharge |
| |
| func matchesErrorPattern(err error, pattern string) bool { |
| if (len(pattern) == 0) != (err == nil) { |
| return false |
| } |
| return err == nil || strings.Index(err.Error(), pattern) >= 0 |
| } |
| |
| func encode(id security.PublicID) ([]byte, error) { |
| var b bytes.Buffer |
| err := vom.NewEncoder(&b).Encode(id) |
| return b.Bytes(), err |
| } |
| |
| func decode(b []byte) (security.PublicID, error) { |
| dID := new(security.PublicID) |
| err := vom.NewDecoder(bytes.NewReader(b)).Decode(dID) |
| return *dID, err |
| } |
| |
| func roundTrip(id security.PublicID) (security.PublicID, error) { |
| b, err := encode(id) |
| if err != nil { |
| return nil, err |
| } |
| return decode(b) |
| } |
| |
| func newChain(name string) security.PrivateID { |
| id, err := newChainPrivateID(name, nil) |
| if err != nil { |
| panic(err) |
| } |
| return id |
| } |
| |
| func newSetPublicID(ids ...security.PublicID) security.PublicID { |
| id, err := NewSetPublicID(ids...) |
| if err != nil { |
| panic(err) |
| } |
| return id |
| } |
| |
| func newSetPrivateID(ids ...security.PrivateID) security.PrivateID { |
| id, err := NewSetPrivateID(ids...) |
| if err != nil { |
| panic(err) |
| } |
| return id |
| } |
| |
| func bless(blessee security.PublicID, blessor security.PrivateID, name string, caveats ...security.Caveat) security.PublicID { |
| blessed, err := blessor.Bless(blessee, name, 5*time.Minute, caveats) |
| if err != nil { |
| panic(err) |
| } |
| return blessed |
| } |
| |
| func derive(pub security.PublicID, priv security.PrivateID) security.PrivateID { |
| d, err := priv.Derive(pub) |
| if err != nil { |
| panic(err) |
| } |
| return d |
| } |
| |
| func verifyAuthorizedID(origID, authID security.PublicID, authNames []string) error { |
| if authID == nil { |
| if len(authNames) != 0 { |
| return fmt.Errorf("%q.Authorize is nil, want identity with names: %v", origID, authNames) |
| } |
| return nil |
| } |
| if got, want := authID.Names(), authNames; !reflect.DeepEqual(got, want) { |
| return fmt.Errorf("%q(%T).Names(): got: %v, want: %v", authID, authID, got, want) |
| } |
| |
| if !reflect.DeepEqual(origID.PublicKey(), authID.PublicKey()) { |
| return fmt.Errorf("%q.Authorize returned %q with public key %v, should have had %v", origID, authID, authID.PublicKey(), origID.PublicKey()) |
| } |
| if _, err := roundTrip(authID); err != nil { |
| return fmt.Errorf("%q.Authorize returned %q, which failed roundTripping: %v", origID, authID, err) |
| } |
| return nil |
| } |
| |
| func newCaveat(validator security.CaveatValidator) security.Caveat { |
| cav, err := security.NewCaveat(validator) |
| if err != nil { |
| panic(err) |
| } |
| return cav |
| } |
| |
| func mkCaveat(cav security.Caveat, err error) security.Caveat { |
| if err != nil { |
| panic(err) |
| } |
| return cav |
| } |
| |
| func init() { |
| // Mark "veyron" and "google" as trusted identity providers. |
| keys.Trust(veyronChain.PublicID().PublicKey(), "veyron") |
| keys.Trust(googleChain.PublicID().PublicKey(), "google") |
| } |
| |
| func TestTrustIdentityProviders(t *testing.T) { |
| var ( |
| cSelf = newChain("chainself") |
| cProvider = newChain("provider") |
| cBlessed = derive(bless(cSelf.PublicID(), cProvider, "somebody"), cSelf) |
| |
| cProvider1 = newChain("provider") |
| cProvider2 = newChain("provider") |
| cSomebody1 = derive(bless(cSelf.PublicID(), cProvider1, "somebody1"), cSelf) |
| cSomebody2 = derive(bless(cSelf.PublicID(), cProvider2, "somebody2"), cSelf) |
| setID = newSetPrivateID(cSomebody1, cSomebody2) |
| ) |
| // Initially nobody is trusted |
| m := map[security.PrivateID]bool{ |
| cSelf: false, |
| cProvider: false, |
| cBlessed: false, |
| cProvider1: false, |
| cProvider2: false, |
| cSomebody1: false, |
| cSomebody2: false, |
| } |
| test := func() { |
| for priv, want := range m { |
| id := priv.PublicID() |
| switch tl := keys.LevelOfTrust(id.PublicKey(), "provider"); tl { |
| case keys.Trusted: |
| if !want { |
| t.Errorf("%q is trusted, should not be", id) |
| } |
| case keys.Unknown, keys.Mistrusted: |
| if want { |
| t.Errorf("%q is %v, it should be trusted", id, tl) |
| } |
| default: |
| t.Errorf("%q has an invalid trust level: %v", tl) |
| } |
| } |
| } |
| test() |
| // Trusting cBlessed should cause cProvider to be trusted |
| TrustIdentityProviders(cBlessed) |
| m[cProvider] = true |
| test() |
| // Trusting setID should cause both cProvider1 and cProvider2 |
| // to be trusted. |
| TrustIdentityProviders(setID) |
| m[cProvider1] = true |
| m[cProvider2] = true |
| test() |
| } |