blob: 2ce46f59279b95f4a1e98194de3a332b8be27230 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file was auto-generated by the vanadium vdl tool.
// Source: types.vdl
// Package access defines types and interfaces for dynamic access control.
// Examples: "allow app to read this photo", "prevent user from modifying this
// file".
//
// Target Developers
//
// Developers creating functionality to share data or services between
// multiple users/devices/apps.
//
// Overview
//
// Vanadium objects provide GetPermissions and SetPermissions methods. An
// AccessList contains the set of blessings that grant principals access to the
// object. All methods on objects can have "tags" on them and the AccessList
// used for the method is selected based on that tag (from a Permissions).
//
// An object can have multiple names, so GetPermissions and SetPermissions can
// be invoked on any of these names, but the object itself has a single
// AccessList.
//
// SetPermissions completely replaces the Permissions. To perform an atomic
// read-modify-write of the AccessList, use the version parameter.
//
// Conventions
//
// Service implementors should follow the conventions below to be consistent
// with other parts of Vanadium and with each other.
//
// All methods that create an object (e.g. Put, Mount, Link) should take an
// optional AccessList parameter. If the AccessList is not specified, the new
// object, O, copies its AccessList from the parent. Subsequent changes to the
// parent AccessList are not automatically propagated to O. Instead, a client
// library must make recursive AccessList changes.
//
// Resolve access is required on all components of a name, except the last one,
// in order to access the object referenced by that name. For example, for
// principal P to access the name "a/b/c", P must have resolve access to "a"
// and "a/b".
//
// The Resolve tag means that a principal can traverse that component of the
// name to access the child. It does not give the principal permission to list
// the children via Glob or a similar method. For example, a server might have
// an object named "home" with a child for each user of the system. If these
// users were allowed to list the contents of "home", they could discover the
// other users of the system. That could be a privacy violation. Without
// Resolve, every user of the system would need read access to "home" to access
// "home/<user>". If the user called Glob("home/*"), it would then be up to
// the server to filter out the names that the user could not access. That
// could be a very expensive operation if there were a lot of children of
// "home". Resolve protects these servers against potential denial of service
// attacks on these large, shared directories.
//
// Blessings allow for sweeping access changes. In particular, a blessing is
// useful for controlling access to objects that are always accessed together.
// For example, a document may have embedded images and comments, each with a
// unique name. When accessing a document, the server would generate a blessing
// that the client would use to fetch the images and comments; the images and
// comments would have this blessed identity in their AccessLists. Changes to
// the document's AccessLists are therefore "propagated" to the images and
// comments.
//
// In the future, we may add some sort of "groups" mechanism to provide an
// alternative way to express access control policies.
//
// Some services will want a concept of implicit access control. They are free
// to implement this as appropriate for their service. However, GetPermissions
// should respond with the correct Permissions. For example, a corporate file
// server would allow all employees to create their own directory and have full
// control within that directory. Employees should not be allowed to modify
// other employee directories. In other words, within the directory "home",
// employee E should be allowed to modify only "home/E". The file server doesn't
// know the list of all employees a priori, so it uses an
// implementation-specific rule to map employee identities to their home
// directory.
//
// Examples
//
// client := access.ObjectClient(name)
// for {
// perms, version, err := client.GetPermissions()
// if err != nil {
// return err
// }
// perms[newTag] = AccessList{In: []security.BlessingPattern{newPattern}}
// // Use the same version with the modified perms to ensure that no other
// // client has modified the perms since GetPermissions returned.
// if err := client.SetPermissions(perms, version); err != nil {
// if verror.ErrorID(err) == verror.ErrBadVersion.Id {
// // Another client replaced the Permissions after our GetPermissions
// // returned. Try again.
// continue
// }
// return err
// }
// }
package access
import (
// VDL system imports
"v.io/v23/context"
"v.io/v23/i18n"
"v.io/v23/vdl"
"v.io/v23/verror"
// VDL user imports
"v.io/v23/security"
"v.io/v23/uniqueid"
)
// AccessList represents a set of blessings that should be granted access.
//
// See also: https://github.com/vanadium/docs/blob/master/glossary.md#access-list
type AccessList struct {
// In denotes the set of blessings (represented as BlessingPatterns) that
// should be granted access, unless blacklisted by an entry in NotIn.
//
// For example:
// In: {"alice:family"}
// grants access to a principal that presents at least one of
// "alice:family", "alice:family:friend", "alice:family:friend:spouse" etc.
// as a blessing.
In []security.BlessingPattern
// NotIn denotes the set of blessings (and their delegates) that
// have been explicitly blacklisted from the In set.
//
// For example:
// In: {"alice:friend"}, NotIn: {"alice:friend:bob"}
// grants access to principals that present "alice:friend",
// "alice:friend:carol" etc. but NOT to a principal that presents
// "alice:friend:bob" or "alice:friend:bob:spouse" etc.
NotIn []string
}
func (AccessList) __VDLReflect(struct {
Name string `vdl:"v.io/v23/security/access.AccessList"`
}) {
}
// Permissions maps string tags to access lists specifying the blessings
// required to invoke methods with that tag.
//
// These tags are meant to add a layer of interposition between the set of
// users (blessings, specifically) and the set of methods, much like "Roles" do
// in Role Based Access Control.
// (http://en.wikipedia.org/wiki/Role-based_access_control)
type Permissions map[string]AccessList
func (Permissions) __VDLReflect(struct {
Name string `vdl:"v.io/v23/security/access.Permissions"`
}) {
}
// Tag is used to associate methods with an AccessList in a Permissions.
//
// While services can define their own tag type and values, many
// services should be able to use the type and values defined in
// this package.
type Tag string
func (Tag) __VDLReflect(struct {
Name string `vdl:"v.io/v23/security/access.Tag"`
}) {
}
func init() {
vdl.Register((*AccessList)(nil))
vdl.Register((*Permissions)(nil))
vdl.Register((*Tag)(nil))
}
const Admin = Tag("Admin") // Operations that require privileged access for object administration.
const Debug = Tag("Debug") // Operations that return debugging information (e.g., logs, statistics etc.) about the object.
const Read = Tag("Read") // Operations that do not mutate the state of the object.
const Write = Tag("Write") // Operations that mutate the state of the object.
const Resolve = Tag("Resolve") // Operations involving namespace navigation.
// AccessTagCaveat represents a caveat that validates iff the method being invoked has
// at least one of the tags listed in the caveat.
var AccessTagCaveat = security.CaveatDescriptor{
Id: uniqueid.Id{
239,
205,
227,
117,
20,
22,
199,
59,
24,
156,
232,
156,
204,
147,
128,
0,
},
ParamType: vdl.TypeOf([]Tag(nil)),
}
var (
// The AccessList is too big. Use groups to represent large sets of principals.
ErrTooBig = verror.Register("v.io/v23/security/access.TooBig", verror.NoRetry, "{1:}{2:} AccessList is too big")
ErrNoPermissions = verror.Register("v.io/v23/security/access.NoPermissions", verror.NoRetry, "{1:}{2:} {3} does not have {5} access (rejected blessings: {4})")
ErrAccessListMatch = verror.Register("v.io/v23/security/access.AccessListMatch", verror.NoRetry, "{1:}{2:} {3} does not match the access list (rejected blessings: {4})")
ErrUnenforceablePatterns = verror.Register("v.io/v23/security/access.UnenforceablePatterns", verror.NoRetry, "{1:}{2:} AccessList contains the following invalid or unrecognized patterns in the In list: {3}")
ErrInvalidOpenAccessList = verror.Register("v.io/v23/security/access.InvalidOpenAccessList", verror.NoRetry, "{1:}{2:} AccessList with the pattern ... in its In list must have no other patterns in the In or NotIn lists")
ErrAccessTagCaveatValidation = verror.Register("v.io/v23/security/access.AccessTagCaveatValidation", verror.NoRetry, "{1:}{2:} access tags on method ({3}) do not include any of the ones in the caveat ({4}), or the method is using a different tag type")
)
func init() {
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrTooBig.ID), "{1:}{2:} AccessList is too big")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrNoPermissions.ID), "{1:}{2:} {3} does not have {5} access (rejected blessings: {4})")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrAccessListMatch.ID), "{1:}{2:} {3} does not match the access list (rejected blessings: {4})")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrUnenforceablePatterns.ID), "{1:}{2:} AccessList contains the following invalid or unrecognized patterns in the In list: {3}")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrInvalidOpenAccessList.ID), "{1:}{2:} AccessList with the pattern ... in its In list must have no other patterns in the In or NotIn lists")
i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrAccessTagCaveatValidation.ID), "{1:}{2:} access tags on method ({3}) do not include any of the ones in the caveat ({4}), or the method is using a different tag type")
}
// NewErrTooBig returns an error with the ErrTooBig ID.
func NewErrTooBig(ctx *context.T) error {
return verror.New(ErrTooBig, ctx)
}
// NewErrNoPermissions returns an error with the ErrNoPermissions ID.
func NewErrNoPermissions(ctx *context.T, validBlessings []string, rejectedBlessings []security.RejectedBlessing, tag string) error {
return verror.New(ErrNoPermissions, ctx, validBlessings, rejectedBlessings, tag)
}
// NewErrAccessListMatch returns an error with the ErrAccessListMatch ID.
func NewErrAccessListMatch(ctx *context.T, validBlessings []string, rejectedBlessings []security.RejectedBlessing) error {
return verror.New(ErrAccessListMatch, ctx, validBlessings, rejectedBlessings)
}
// NewErrUnenforceablePatterns returns an error with the ErrUnenforceablePatterns ID.
func NewErrUnenforceablePatterns(ctx *context.T, rejectedPatterns []security.BlessingPattern) error {
return verror.New(ErrUnenforceablePatterns, ctx, rejectedPatterns)
}
// NewErrInvalidOpenAccessList returns an error with the ErrInvalidOpenAccessList ID.
func NewErrInvalidOpenAccessList(ctx *context.T) error {
return verror.New(ErrInvalidOpenAccessList, ctx)
}
// NewErrAccessTagCaveatValidation returns an error with the ErrAccessTagCaveatValidation ID.
func NewErrAccessTagCaveatValidation(ctx *context.T, methodTags []string, caveatTags []Tag) error {
return verror.New(ErrAccessTagCaveatValidation, ctx, methodTags, caveatTags)
}