bakery

package
v0.0.0-...-8dc4a41 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2018 License: Apache-2.0, LGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

The bakery package layers on top of the macaroon package, providing a transport and store-agnostic way of using macaroons to assert client capabilities.

Summary

The Bakery type is probably where you want to start. It encapsulates a Checker type, which performs checking of operations, and an Oven type, which encapsulates the actual details of the macaroon encoding conventions.

Most other types and functions are designed either to plug into one of the above types (the various Authorizer implementations, for example), or to expose some independent functionality that's potentially useful (Discharge, for example).

The rest of this introduction introduces some of the concepts used by the bakery package.

Identity and entities

An Identity represents some authenticated user (or agent), usually the client in a network protocol. An identity can be authenticated by an external identity server (with a third party macaroon caveat) or by locally provided information such as a username and password.

The Checker type is not responsible for determining identity - that functionality is represented by the IdentityClient interface.

The Checker uses identities to decide whether something should be allowed or not - the Authorizer interface is used to ask whether a given identity should be allowed to perform some set of operations.

Operations

An operation defines some requested action on an entity. For example, if file system server defines an entity for every file in the server, an operation to read a file might look like:

    Op{
		Entity: "/foo",
		Action: "write",
	}

The exact set of entities and actions is up to the caller, but should be kept stable over time because authorization tokens will contain these names.

To authorize some request on behalf of a remote user, first find out what operations that request needs to perform. For example, if the user tries to delete a file, the entity might be the path to the file's directory and the action might be "write". It may often be possible to determine the operations required by a request without reference to anything external, when the request itself contains all the necessary information.

The LoginOp operation is special - any macaroon associated with this operation is treated as a bearer of identity information. If two valid LoginOp macaroons are presented, only the first one will be used for identity.

Authorization

The Authorizer interface is responsible for determining whether a given authenticated identity is authorized to perform a set of operations. This is used when the macaroons provided to Auth are not sufficient to authorize the operations themselves.

Capabilities

A "capability" is represented by a macaroon that's associated with one or more operations, and grants the capability to perform all those operations. The AllowCapability method reports whether a capability is allowed. It takes into account any authenticated identity and any other capabilities provided.

Third party caveats

Sometimes authorization will only be granted if a third party caveat is discharged. This will happen when an IdentityClient or Authorizer returns a third party caveat.

When this happens, a DischargeRequiredError will be returned containing the caveats and the operations required. The caller is responsible for creating a macaroon with those caveats associated with those operations and for passing that macaroon to the client to discharge.

Index

Constants

View Source
const Everyone = "everyone"

Everyone is recognized by ACLAuthorizer as the name of a group that has everyone in it.

View Source
const KeyLen = 32

KeyLen is the byte length of the Ed25519 public and private keys used for caveat id encryption.

View Source
const NonceLen = 24

NonceLen is the byte length of the nonce values used for caveat id encryption.

Variables

View Source
var (
	// OpenAuthorizer is an Authorizer implementation that will authorize all operations without question.
	OpenAuthorizer openAuthorizer

	// ClosedAuthorizer is an Authorizer implementation that will return ErrPermissionDenied
	// on all authorization requests.
	ClosedAuthorizer closedAuthorizer
)
View Source
var (
	// ErrNotFound is returned by Store.Get implementations
	// to signal that an id has not been found.
	ErrNotFound = errgo.New("not found")

	// ErrPermissionDenied is returned from AuthChecker when
	// permission has been denied.
	ErrPermissionDenied = errgo.New("permission denied")
)
View Source
var LoginOp = Op{
	Entity: "login",
	Action: "login",
}

LoginOp represents a login (authentication) operation. A macaroon that is associated with this operation generally carries authentication information with it.

Functions

func DischargeAll

func DischargeAll(
	ctx context.Context,
	m *Macaroon,
	getDischarge func(ctx context.Context, cav macaroon.Caveat, encryptedCaveat []byte) (*Macaroon, error),
) (macaroon.Slice, error)

DischargeAll gathers discharge macaroons for all the third party caveats in m (and any subsequent caveats required by those) using getDischarge to acquire each discharge macaroon. It returns a slice with m as the first element, followed by all the discharge macaroons. All the discharge macaroons will be bound to the primary macaroon.

The getDischarge function is passed the caveat to be discharged; encryptedCaveat will be passed the external caveat payload found in m, if any.

func DischargeAllWithKey

func DischargeAllWithKey(
	ctx context.Context,
	m *Macaroon,
	getDischarge func(ctx context.Context, cav macaroon.Caveat, encodedCaveat []byte) (*Macaroon, error),
	localKey *KeyPair,
) (macaroon.Slice, error)

DischargeAllWithKey is like DischargeAll except that the localKey parameter may optionally hold the key of the client, in which case it will be used to discharge any third party caveats with the special location "local". In this case, the caveat itself must be "true". This can be used be a server to ask a client to prove ownership of the private key.

When localKey is nil, DischargeAllWithKey is exactly the same as DischargeAll.

func LocalThirdPartyCaveat

func LocalThirdPartyCaveat(key *PublicKey, version Version) checkers.Caveat

LocalThirdPartyCaveat returns a third-party caveat that, when added to a macaroon with AddCaveat, results in a caveat with the location "local", encrypted with the given public key. This can be automatically discharged by DischargeAllWithKey.

func MacaroonVersion

func MacaroonVersion(v Version) macaroon.Version

MacaroonVersion returns the macaroon version that should be used with the given bakery Version.

Types

type ACLAuthorizer

type ACLAuthorizer struct {
	// GetACL returns the ACL that applies to the given operation,
	// and reports whether non-authenticated users should
	// be allowed access when the ACL contains "everyone".
	//
	// If an entity cannot be found or the action is not recognised,
	// GetACLs should return an empty ACL but no error.
	GetACL func(ctx context.Context, op Op) (acl []string, allowPublic bool, err error)
}

ACLAuthorizer is an Authorizer implementation that will check access control list (ACL) membership of users. It uses GetACL to find out the ACLs that apply to the requested operations and will authorize an operation if an ACL contains the group "everyone" or if the context contains an AuthInfo (see ContextWithAuthInfo) that holds an Identity that implements ACLIdentity and its Allow method returns true for the ACL.

func (ACLAuthorizer) Authorize

func (a ACLAuthorizer) Authorize(ctx context.Context, ident Identity, ops []Op) (allowed []bool, caveats []checkers.Caveat, err error)

Authorize implements Authorizer.Authorize by calling ident.Allow to determine whether the identity is a member of the ACLs associated with the given operations.

type ACLIdentity

type ACLIdentity interface {
	Identity

	// Allow reports whether the user should be allowed to access
	// any of the users or groups in the given ACL slice.
	Allow(ctx context.Context, acl []string) (bool, error)
}

ACLIdentity may be implemented by Identity implementions to report group membership information. See ACLAuthorizer for details.

type AuthChecker

type AuthChecker struct {
	// Checker is used to check first party caveats.
	*Checker
	// contains filtered or unexported fields
}

AuthChecker authorizes operations with respect to a user's request. The identity is authenticated only once, the first time any method of the AuthChecker is called, using the context passed in then.

To find out any declared identity without requiring a login, use Allow(ctx); to require authentication but no additional operations, use Allow(ctx, LoginOp).

func (*AuthChecker) Allow

func (a *AuthChecker) Allow(ctx context.Context, ops ...Op) (*AuthInfo, error)

Allow checks that the authorizer's request is authorized to perform all the given operations. Note that Allow does not check first party caveats - if there is more than one macaroon that may authorize the request, it will choose the first one that does regardless

If all the operations are allowed, an AuthInfo is returned holding details of the decision and any first party caveats that must be checked before actually executing any operation.

If operations include LoginOp, the request should contain an authentication macaroon proving the client's identity. Once an authentication macaroon is chosen, it will be used for all other authorization requests.

If an operation was not allowed, an error will be returned which may be *DischargeRequiredError holding the operations that remain to be authorized in order to allow authorization to proceed.

func (*AuthChecker) AllowAny

func (a *AuthChecker) AllowAny(ctx context.Context, ops ...Op) (*AuthInfo, []bool, error)

AllowAny is like Allow except that it will authorize as many of the operations as possible without requiring any to be authorized. If all the operations succeeded, the returned error and slice will be nil.

If any the operations failed, the returned error will be the same that Allow would return and each element in the returned slice will hold whether its respective operation was allowed.

If all the operations succeeded, the returned slice will be nil.

The returned *AuthInfo will always be non-nil.

The LoginOp operation is treated specially - it is always required if present in ops.

func (*AuthChecker) AllowCapability

func (a *AuthChecker) AllowCapability(ctx context.Context, ops ...Op) ([]string, error)

AllowCapability checks that the user is allowed to perform all the given operations. If not, the error will be as returned from Allow.

If AllowCapability succeeds, it returns a list of first party caveat conditions that must be applied to any macaroon granting capability to execute the operations. Those caveat conditions will not include any declarations contained in login macaroons - the caller must be careful not to mint a macaroon associated with the LoginOp operation unless they add the expected declaration caveat too - in general, clients should not create capabilities that grant LoginOp rights.

The operations must include at least one non-LoginOp operation.

func (*AuthChecker) Allowed

func (a *AuthChecker) Allowed(ctx context.Context) (*AuthInfo, map[Op]bool, error)

Allowed returns all the operations allowed by the provided macaroons as keys in the returned map (all the associated values will be true). Note that this does not include operations that would be indirectly allowed via the OpAuthorizer.

It also returns the AuthInfo (always non-nil) similarly to AllowAny.

Allowed returns an error only when there is an underlying storage failure, not when operations are not authorized.

type AuthInfo

type AuthInfo struct {
	// Identity holds information on the authenticated user as returned
	// from IdentityClient. It may be nil after a
	// successful authorization if LoginOp access was not required.
	Identity Identity

	// Macaroons holds all the macaroons that were used for the
	// authorization. Macaroons that were invalid or unnecessary are
	// not included.
	Macaroons []macaroon.Slice
}

AuthInfo information about an authorization decision.

type Authorizer

type Authorizer interface {
	// Authorize checks whether the given identity (which will be nil
	// when there is no authenticated user) is allowed to perform
	// the given operations. It should return an error only when
	// the authorization cannot be determined, not when the
	// user has been denied access.
	//
	// On success, each element of allowed holds whether the respective
	// element of ops has been allowed, and caveats holds any additional
	// third party caveats that apply.
	// If allowed is shorter then ops, the additional elements are assumed to
	// be false.
	Authorize(ctx context.Context, id Identity, ops []Op) (allowed []bool, caveats []checkers.Caveat, err error)
}

Authorizer is used to check whether a given user is allowed to perform a set of operations.

type AuthorizerFunc

type AuthorizerFunc func(ctx context.Context, id Identity, op Op) (bool, []checkers.Caveat, error)

AuthorizerFunc implements a simplified version of Authorizer that operates on a single operation at a time.

func (AuthorizerFunc) Authorize

func (f AuthorizerFunc) Authorize(ctx context.Context, id Identity, ops []Op) (allowed []bool, caveats []checkers.Caveat, err error)

Authorize implements Authorizer.Authorize by calling f with the given identity for each operation.

type Bakery

type Bakery struct {
	Oven    *Oven
	Checker *Checker
}

Bakery is a convenience type that contains both an Oven and a Checker.

func New

func New(p BakeryParams) *Bakery

New returns a new Bakery instance which combines an Oven with a Checker for the convenience of callers that wish to use both together.

type BakeryParams

type BakeryParams struct {
	// Checker holds the checker used to check first party caveats.
	// If this is nil, New will use checkers.New(nil).
	Checker FirstPartyCaveatChecker

	// RootKeyStore holds the root key store to use. If you need to
	// use a different root key store for different operations,
	// you'll need to pass a RootKeyStoreForOps value to NewOven
	// directly.
	//
	// If this is nil, New will use NewMemRootKeyStore().
	// Note that that is almost certain insufficient for production services
	// that are spread across multiple instances or that need
	// to persist keys across restarts.
	RootKeyStore RootKeyStore

	// Locator is used to find out information on third parties when
	// adding third party caveats. If this is nil, no non-local third
	// party caveats can be added.
	Locator ThirdPartyLocator

	// Key holds the private key of the oven. If this is nil,
	// no third party caveats may be added.
	Key *KeyPair

	// IdentityClient holds the identity implementation to use for
	// authentication. If this is nil, no authentication will be possible.
	IdentityClient IdentityClient

	// Authorizer is used to check whether an authenticated user is
	// allowed to perform operations. If it is nil, New will
	// use ClosedAuthorizer.
	//
	// The identity parameter passed to Authorizer.Allow will
	// always have been obtained from a call to
	// IdentityClient.DeclaredIdentity.
	Authorizer Authorizer

	// OpsStore is used to persistently store the association of
	// multi-op entities with their associated operations
	// when Oven.NewMacaroon is called with multiple operations.
	//
	// See OvenParams.OpsStore for details.
	OpsStore OpsStore

	// Location holds the location to use when creating new macaroons.
	Location string
}

BakeryParams holds a selection of parameters for the Oven and the Checker created by New.

For more fine-grained control of parameters, create the Oven or Checker directly.

The zero value is OK to use, but won't allow any authentication or third party caveats to be added.

type Checker

type Checker struct {
	FirstPartyCaveatChecker
	// contains filtered or unexported fields
}

Checker wraps a FirstPartyCaveatChecker and adds authentication and authorization checks.

It uses macaroons as authorization tokens but it is not itself responsible for creating the macaroons - see the Oven type (TODO) for one way of doing that.

func NewChecker

func NewChecker(p CheckerParams) *Checker

NewChecker returns a new Checker using the given parameters.

func (*Checker) Auth

func (c *Checker) Auth(mss ...macaroon.Slice) *AuthChecker

Auth makes a new AuthChecker instance using the given macaroons to inform authorization decisions.

type CheckerParams

type CheckerParams struct {
	// CaveatChecker is used to check first party caveats when authorizing.
	// If this is nil NewChecker will use checkers.New(nil).
	Checker FirstPartyCaveatChecker

	// Authorizer is used to check whether an authenticated user is
	// allowed to perform operations. If it is nil, NewChecker will
	// use ClosedAuthorizer.
	//
	// The identity parameter passed to Authorizer.Allow will
	// always have been obtained from a call to
	// IdentityClient.DeclaredIdentity.
	Authorizer Authorizer

	// OpsAuthorizer is used to check whether operations are authorized
	// by some other already-authorized operation. If it is nil,
	// NewChecker will assume no operation is authorized by any
	// operation except itself.
	OpsAuthorizer OpsAuthorizer

	// IdentityClient is used for interactions with the external
	// identity service used for authentication.
	//
	// If this is nil, no authentication will be possible.
	IdentityClient IdentityClient

	// MacaroonOps is used to retrieve macaroon root keys
	// and other associated information.
	MacaroonOpStore MacaroonOpStore
}

CheckerParams holds parameters for NewChecker.

type DischargeParams

type DischargeParams struct {
	// Id holds the id to give to the discharge macaroon.
	// If Caveat is empty, then the id also holds the
	// encrypted third party caveat.
	Id []byte

	// Caveat holds the encrypted third party caveat. If this
	// is nil, Id will be used.
	Caveat []byte

	// Key holds the key to use to decrypt the third party
	// caveat information and to encrypt any additional
	// third party caveats returned by the caveat checker.
	Key *KeyPair

	// Checker is used to check the third party caveat,
	// and may also return further caveats to be added to
	// the discharge macaroon.
	Checker ThirdPartyCaveatChecker

	// Locator is used to information on third parties
	// referred to by third party caveats returned by the Checker.
	Locator ThirdPartyLocator
}

DischargeParams holds parameters for a Discharge call.

type DischargeRequiredError

type DischargeRequiredError struct {
	// Message holds some reason why the authorization was denied.
	// TODO this is insufficient (and maybe unnecessary) because we
	// can have multiple errors.
	Message string

	// Ops holds all the operations that were not authorized.
	// If Ops contains a single LoginOp member, the macaroon
	// should be treated as an login token. Login tokens (also
	// known as authentication macaroons) usually have a longer
	// life span than other macaroons.
	Ops []Op

	// Caveats holds the caveats that must be added
	// to macaroons that authorize the above operations.
	Caveats []checkers.Caveat
}

DischargeRequiredError is returned when authorization has failed and a discharged macaroon might fix it.

A caller should grant the user the ability to authorize by minting a macaroon associated with Ops (see MacaroonStore.MacaroonIdInfo for how the associated operations are retrieved) and adding Caveats. If the user succeeds in discharging the caveats, the authorization will be granted.

func (*DischargeRequiredError) Error

func (e *DischargeRequiredError) Error() string

type FirstPartyCaveatChecker

type FirstPartyCaveatChecker interface {
	// CheckFirstPartyCaveat checks that the given caveat condition
	// is valid with respect to the given context information.
	CheckFirstPartyCaveat(ctx context.Context, caveat string) error

	// Namespace returns the namespace associated with the
	// caveat checker.
	Namespace() *checkers.Namespace
}

FirstPartyCaveatChecker is used to check first party caveats for validity with respect to information in the provided context.

If the caveat kind was not recognised, the checker should return ErrCaveatNotRecognized.

type Identity

type Identity interface {
	// Id returns the id of the user, which may be an
	// opaque blob with no human meaning.
	// An id is only considered to be unique
	// with a given domain.
	Id() string

	// Domain holds the domain of the user. This
	// will be empty if the user was authenticated
	// directly with the identity provider.
	Domain() string
}

Identity holds identity information declared in a first party caveat added when discharging a third party caveat.

type IdentityClient

type IdentityClient interface {
	// IdentityFromContext returns the identity based on information in the context.
	// If it cannot determine the identity based on the context, then it
	// should return a set of caveats containing a third party caveat that,
	// when discharged, can be used to obtain the identity with DeclaredIdentity.
	//
	// It should only return an error if it cannot check the identity
	// (for example because of a database access error) - it's
	// OK to return all zero values when there's
	// no identity found and no third party to address caveats to.
	IdentityFromContext(ctx context.Context) (Identity, []checkers.Caveat, error)

	// DeclaredIdentity parses the identity declaration from the given
	// declared attributes.
	// TODO take the set of first party caveat conditions instead?
	DeclaredIdentity(ctx context.Context, declared map[string]string) (Identity, error)
}

IdentityClient represents an abstract identity manager. User identities can be based on local informaton (for example HTTP basic auth) or by reference to an external trusted third party (an identity manager).

type Key

type Key [KeyLen]byte

Key is a 256-bit Ed25519 key.

func (Key) MarshalBinary

func (k Key) MarshalBinary() ([]byte, error)

MarshalBinary implements encoding.BinaryMarshaler.MarshalBinary.

func (Key) MarshalText

func (k Key) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.MarshalText.

func (Key) String

func (k Key) String() string

String returns the base64 representation of the key.

func (*Key) UnmarshalBinary

func (k *Key) UnmarshalBinary(data []byte) error

UnmarshalBinary implements encoding.BinaryUnmarshaler.UnmarshalBinary.

func (*Key) UnmarshalText

func (k *Key) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.UnmarshalText.

type KeyPair

type KeyPair struct {
	Public  PublicKey  `json:"public"`
	Private PrivateKey `json:"private"`
}

KeyPair holds a public/private pair of keys.

func GenerateKey

func GenerateKey() (*KeyPair, error)

GenerateKey generates a new key pair.

func MustGenerateKey

func MustGenerateKey() *KeyPair

MustGenerateKey is like GenerateKey but panics if GenerateKey returns an error - useful in tests.

func (*KeyPair) String

func (key *KeyPair) String() string

String implements the fmt.Stringer interface by returning the base64 representation of the public key part of key.

func (*KeyPair) UnmarshalJSON

func (k *KeyPair) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (*KeyPair) UnmarshalYAML

func (k *KeyPair) UnmarshalYAML(unmarshal func(interface{}) error) error

UnmarshalYAML implements yaml.Unmarshaler.

type Macaroon

type Macaroon struct {
	// contains filtered or unexported fields
}

Macaroon represents an undischarged macaroon along with its first party caveat namespace and associated third party caveat information which should be passed to the third party when discharging a caveat.

func Discharge

func Discharge(ctx context.Context, p DischargeParams) (*Macaroon, error)

Discharge creates a macaroon to discharges a third party caveat. The given parameters specify the caveat and how it should be checked/

The condition implicit in the caveat is checked for validity using p.Checker. If it is valid, a new macaroon is returned which discharges the caveat.

The macaroon is created with a version derived from the version that was used to encode the id.

func NewLegacyMacaroon

func NewLegacyMacaroon(m *macaroon.Macaroon) (*Macaroon, error)

NewLegacyMacaroon returns a new macaroon holding m. This should only be used when there's no alternative (for example when m has been unmarshaled from some alternative format).

func NewMacaroon

func NewMacaroon(rootKey, id []byte, location string, version Version, ns *checkers.Namespace) (*Macaroon, error)

NewMacaroon creates and returns a new macaroon with the given root key, id and location. If the version is more than the latest known version, the latest known version will be used. The namespace is that of the service creating it.

func (*Macaroon) AddCaveat

func (m *Macaroon) AddCaveat(ctx context.Context, cav checkers.Caveat, key *KeyPair, loc ThirdPartyLocator) error

AddCaveat adds a caveat to the given macaroon.

If it's a third-party caveat, it encrypts it using the given key pair and by looking up the location using the given locator. If it's a first party cavat, key and loc are unused.

As a special case, if the caveat's Location field has the prefix "local " the caveat is added as a client self-discharge caveat using the public key base64-encoded in the rest of the location. In this case, the Condition field must be empty. The resulting third-party caveat will encode the condition "true" encrypted with that public key. See LocalThirdPartyCaveat for a way of creating such caveats.

func (*Macaroon) AddCaveats

func (m *Macaroon) AddCaveats(ctx context.Context, cavs []checkers.Caveat, key *KeyPair, loc ThirdPartyLocator) error

AddCaveats is a convenienced method that calls m.AddCaveat for each caveat in cavs.

func (*Macaroon) Clone

func (m *Macaroon) Clone() *Macaroon

Clone returns a copy of the macaroon. Note that the the new macaroon's namespace still points to the same underlying Namespace - copying the macaroon does not make a copy of the namespace.

func (*Macaroon) M

func (m *Macaroon) M() *macaroon.Macaroon

M returns the underlying macaroon held within m.

func (*Macaroon) MarshalJSON

func (m *Macaroon) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler by marshaling the macaroon into the original macaroon format if the version is earlier than Version3.

func (*Macaroon) Namespace

func (m *Macaroon) Namespace() *checkers.Namespace

Namespace returns the first party caveat namespace of the macaroon.

func (*Macaroon) UnmarshalJSON

func (m *Macaroon) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler by unmarshaling in a backwardly compatible way - if provided with a previous macaroon version, it will unmarshal that too.

func (*Macaroon) Version

func (m *Macaroon) Version() Version

Version returns the bakery version of the first party that created the macaroon.

type MacaroonOpStore

type MacaroonOpStore interface {
	// MacaroonOps verifies the signature of the given macaroon and returns
	// information on its associated operations, and all the first party
	// caveat conditions that need to be checked.
	//
	// This method should not check first party caveats itself.
	//
	// It should return a *VerificationError if the error occurred
	// because the macaroon signature failed or the root key
	// was not found - any other error will be treated as fatal
	// by Checker and cause authorization to terminate.
	MacaroonOps(ctx context.Context, ms macaroon.Slice) ([]Op, []string, error)
}

MacaroonOpStore provides a mapping from a set of macaroons to their associated operations and caveats.

type Op

type Op struct {
	// Entity holds the name of the entity to be authorized.
	// Entity names should not contain spaces and should
	// not start with the prefix "login" or "multi-" (conventionally,
	// entity names will be prefixed with the entity type followed
	// by a hyphen.
	Entity string

	// Action holds the action to perform on the entity, such as "read"
	// or "delete". It is up to the service using a checker to define
	// a set of operations and keep them consistent over time.
	Action string
}

Op holds an entity and action to be authorized on that entity.

func CanonicalOps

func CanonicalOps(ops []Op) []Op

CanonicalOps returns the given operations slice sorted with duplicates removed.

type OpsAuthorizer

type OpsAuthorizer interface {
	// AuthorizeOp reports which elements of queryOps are authorized by
	// authorizedOp. On return, each element of the slice should represent
	// whether the respective element in queryOps has been authorized.
	// An empty returned slice indicates that no operations are authorized.
	AuthorizeOps(ctx context.Context, authorizedOp Op, queryOps []Op) ([]bool, error)
}

OpsAuthorizer is used to check whether an operation authorizes some other operation. For example, a macaroon with an operation allowing general access to a service might also grant access to a more specific operation.

type OpsStore

type OpsStore interface {
	// PutOps creates an entry in the store associated with the given
	// key. A subsequent Get of the same key should result in the
	// same set of entities. Multiple puts of the same key should be
	// idempotent. The value associated with a given key will always
	// be the same.
	//
	// The context is derived from the context provided to Authorize
	// or Capability.
	//
	// The key must persist at least until the given expiry time.
	//
	// Implementations may assume that the operations
	// are in canonical order and contain no duplicates.
	PutOps(ctx context.Context, key string, ops []Op, expiry time.Time) error

	// GetOps returns the set of operations for a given key.
	// If the key was not found, it should return an error with an
	// ErrNotFound cause.
	//
	// The context is derived from the context provided to Authorize or Capability.
	//
	// TODO Perhaps this should return an interface that
	// can be used to check membership rather than the
	// whole set of operations. Then an implementation
	// might be able to scale more easily to large sets of
	// operations, for example by using a bloom filter.
	GetOps(ctx context.Context, key string) ([]Op, error)
}

OpsStore defines a persistent store for operation sets stored by the Oven.

Implementations must be suitable for concurrent use.

func NewMemOpsStore

func NewMemOpsStore() OpsStore

NewMemOpsStore returns a new multi-op store that stores the operations in memory.

type Oven

type Oven struct {
	// contains filtered or unexported fields
}

Oven bakes macaroons. They emerge sweet and delicious and ready for use in a Checker.

All macaroons are associated with one or more operations (see the Op type) which define the capabilities of the macaroon.

There is one special operation, "login" (defined by LoginOp) which grants the capability to speak for a particular user. The login capability will never be mixed with other capabilities.

It is up to the caller to decide on semantics for other operations.

func NewOven

func NewOven(p OvenParams) *Oven

NewOven returns a new oven using the given parameters.

func (*Oven) AddCaveat

func (o *Oven) AddCaveat(ctx context.Context, m *Macaroon, cav checkers.Caveat) error

AddCaveat adds a caveat to the given macaroon.

func (*Oven) AddCaveats

func (o *Oven) AddCaveats(ctx context.Context, m *Macaroon, caveats []checkers.Caveat) error

AddCaveats adds all the caveats to the given macaroon.

func (*Oven) Key

func (o *Oven) Key() *KeyPair

Key returns the oven's private/public key par.

func (*Oven) Locator

func (o *Oven) Locator() ThirdPartyLocator

Locator returns the third party locator that the oven was created with.

func (*Oven) MacaroonOps

func (o *Oven) MacaroonOps(ctx context.Context, ms macaroon.Slice) (ops []Op, conditions []string, err error)

MacaroonOps implements MacaroonOpStore.MacaroonOps, making Oven an instance of MacaroonOpStore.

For macaroons minted with previous bakery versions, it always returns a single LoginOp operation.

func (*Oven) NewMacaroon

func (o *Oven) NewMacaroon(ctx context.Context, version Version, expiry time.Time, caveats []checkers.Caveat, ops ...Op) (*Macaroon, error)

NewMacaroon takes a macaroon with the given version from the oven, associates it with the given operations and attaches the given caveats. There must be at least one operation specified.

The macaroon will expire at the given time - a TimeBefore first party caveat will be added with that time.

type OvenParams

type OvenParams struct {
	// Namespace holds the namespace to use when adding first party caveats.
	// If this is nil, checkers.New(nil).Namespace will be used.
	Namespace *checkers.Namespace

	// RootKeyStoreForEntity returns the macaroon storage to be
	// used for root keys associated with macaroons created
	// wth NewMacaroon.
	//
	// If this is nil, NewMemRootKeyStore will be used to create
	// a new store to be used for all entities.
	RootKeyStoreForOps func(ops []Op) RootKeyStore

	// OpsStore is used to persistently store the association of
	// multi-op entities with their associated operations
	// when NewMacaroon is called with multiple operations.
	//
	// If this is nil, embed the operations will be stored directly in the macaroon id.
	// Note that this can make the macaroons large.
	//
	// When this is in use, operation entities with the prefix "multi-" are
	// reserved - a "multi-"-prefixed entity represents a set of operations
	// stored in the OpsStore.
	OpsStore OpsStore

	// Key holds the private key pair used to encrypt third party caveats.
	// If it is nil, no third party caveats can be created.
	Key *KeyPair

	// Location holds the location that will be associated with new macaroons
	// (as returned by Macaroon.Location).
	Location string

	// Locator is used to find out information on third parties when
	// adding third party caveats. If this is nil, no non-local third
	// party caveats can be added.
	Locator ThirdPartyLocator
}

type PrivateKey

type PrivateKey struct {
	Key
}

PrivateKey is a 256-bit Ed25519 private key.

type PublicKey

type PublicKey struct {
	Key
}

PublicKey is a 256-bit Ed25519 public key.

type RootKeyStore

type RootKeyStore interface {
	// Get returns the root key for the given id.
	// If the item is not there, it returns ErrNotFound.
	Get(ctx context.Context, id []byte) ([]byte, error)

	// RootKey returns the root key to be used for making a new
	// macaroon, and an id that can be used to look it up later with
	// the Get method.
	//
	// Note that the root keys should remain available for as long
	// as the macaroons using them are valid.
	//
	// Note that there is no need for it to return a new root key
	// for every call - keys may be reused, although some key
	// cycling is over time is advisable.
	RootKey(ctx context.Context) (rootKey []byte, id []byte, err error)
}

RootKeyStore defines store for macaroon root keys.

func NewMemRootKeyStore

func NewMemRootKeyStore() RootKeyStore

NewMemRootKeyStore returns an implementation of Store that generates a single key and always returns that from RootKey. The same id ("0") is always used.

type SimpleIdentity

type SimpleIdentity string

SimpleIdentity implements a simple form of identity where the user is represented by a string.

func (SimpleIdentity) Allow

func (id SimpleIdentity) Allow(ctx context.Context, acl []string) (bool, error)

Allow implements ACLIdentity by allowing the identity access to ACL members that are equal to id. That is, some user u is considered a member of group u and no other.

func (SimpleIdentity) Domain

func (SimpleIdentity) Domain() string

Domain implements Identity.Domain by always returning the empty domain.

func (SimpleIdentity) Id

func (id SimpleIdentity) Id() string

Id returns id as a string.

type Slice

type Slice []*Macaroon

Slice holds a slice of unbound macaroons.

func (Slice) Bind

func (s Slice) Bind() macaroon.Slice

Bind prepares the macaroon slice for use in a request. This must be done before presenting the macaroons to a service for use as authorization tokens. The result will only be valid if s contains discharge macaroons for all third party caveats.

All the macaroons in the returned slice will be copies of this in s, not references.

func (Slice) DischargeAll

func (ms Slice) DischargeAll(ctx context.Context, getDischarge func(ctx context.Context, cav macaroon.Caveat, encryptedCaveat []byte) (*Macaroon, error), localKey *KeyPair) (Slice, error)

DischargeAll discharges all the third party caveats in the slice for which discharge macaroons are not already present, using getDischarge to acquire the discharge macaroons. It always returns the slice with any acquired discharge macaroons added, even on error. It returns an error if all the discharges could not be acquired.

Note that this differs from DischargeAll in that it can be given several existing discharges, and that the resulting discharges are not bound to the primary, so it's still possible to add caveats and reacquire expired discharges without reacquiring the primary macaroon.

func (Slice) Purge

func (ms Slice) Purge(t time.Time) Slice

Purge returns a new slice holding all macaroons in s that expire after the given time.

type ThirdPartyCaveatChecker

type ThirdPartyCaveatChecker interface {
	CheckThirdPartyCaveat(ctx context.Context, info *ThirdPartyCaveatInfo) ([]checkers.Caveat, error)
}

ThirdPartyCaveatChecker holds a function that checks third party caveats for validity. If the caveat is valid, it returns a nil error and optionally a slice of extra caveats that will be added to the discharge macaroon. The caveatId parameter holds the still-encoded id of the caveat.

If the caveat kind was not recognised, the checker should return an error with a ErrCaveatNotRecognized cause.

type ThirdPartyCaveatCheckerFunc

type ThirdPartyCaveatCheckerFunc func(context.Context, *ThirdPartyCaveatInfo) ([]checkers.Caveat, error)

ThirdPartyCaveatCheckerFunc implements ThirdPartyCaveatChecker by calling a function.

func (ThirdPartyCaveatCheckerFunc) CheckThirdPartyCaveat

func (c ThirdPartyCaveatCheckerFunc) CheckThirdPartyCaveat(ctx context.Context, info *ThirdPartyCaveatInfo) ([]checkers.Caveat, error)

CheckThirdPartyCaveat implements ThirdPartyCaveatChecker.CheckThirdPartyCaveat by calling the receiver with the given arguments

type ThirdPartyCaveatInfo

type ThirdPartyCaveatInfo struct {
	// Condition holds the third party condition to be discharged.
	// This is the only field that most third party dischargers will
	// need to consider.
	Condition []byte

	// FirstPartyPublicKey holds the public key of the party
	// that created the third party caveat.
	FirstPartyPublicKey PublicKey

	// ThirdPartyKeyPair holds the key pair used to decrypt
	// the caveat - the key pair of the discharging service.
	ThirdPartyKeyPair KeyPair

	// RootKey holds the secret root key encoded by the caveat.
	RootKey []byte

	// CaveatId holds the full encoded caveat id from which all
	// the other fields are derived.
	Caveat []byte

	// Version holds the version that was used to encode
	// the caveat id.
	Version Version

	// Id holds the id of the third party caveat (the id that
	// the discharge macaroon should be given). This
	// will differ from Caveat when the caveat information
	// is encoded separately.
	Id []byte

	// Namespace holds the namespace of the first party
	// that created the macaroon, as encoded by the party
	// that added the third party caveat.
	Namespace *checkers.Namespace
}

ThirdPartyCaveatInfo holds the information decoded from a third party caveat id.

type ThirdPartyInfo

type ThirdPartyInfo struct {
	// PublicKey holds the public key of the third party.
	PublicKey PublicKey

	// Version holds latest the bakery protocol version supported
	// by the discharger.
	Version Version
}

ThirdPartyInfo holds information on a given third party discharge service.

type ThirdPartyLocator

type ThirdPartyLocator interface {
	// ThirdPartyInfo returns information on the third
	// party at the given location. It returns ErrNotFound if no match is found.
	// This method must be safe to call concurrently.
	ThirdPartyInfo(ctx context.Context, loc string) (ThirdPartyInfo, error)
}

ThirdPartyLocator is used to find information on third party discharge services.

type ThirdPartyStore

type ThirdPartyStore struct {
	// contains filtered or unexported fields
}

ThirdPartyStore implements a simple ThirdPartyLocator. A trailing slash on locations is ignored.

func NewThirdPartyStore

func NewThirdPartyStore() *ThirdPartyStore

NewThirdPartyStore returns a new instance of ThirdPartyStore that stores locations in memory.

func (*ThirdPartyStore) AddInfo

func (s *ThirdPartyStore) AddInfo(loc string, info ThirdPartyInfo)

AddInfo associates the given information with the given location, ignoring any trailing slash. This method is OK to call concurrently with sThirdPartyInfo.

func (*ThirdPartyStore) ThirdPartyInfo

func (s *ThirdPartyStore) ThirdPartyInfo(ctx context.Context, loc string) (ThirdPartyInfo, error)

ThirdPartyInfo implements the ThirdPartyLocator interface.

type VerificationError

type VerificationError struct {
	Reason error
}

VerificationError is used to signify that an error is because of a verification failure rather than because verification could not be done.

func (*VerificationError) Error

func (e *VerificationError) Error() string

type Version

type Version int

Version represents a version of the bakery protocol.

const (
	// In version 0, discharge-required errors use status 407
	Version0 Version = 0
	// In version 1,  discharge-required errors use status 401.
	Version1 Version = 1
	// In version 2, binary macaroons and caveat ids are supported.
	Version2 Version = 2
	// In version 3, we support operations associated with macaroons
	// and external third party caveats.
	Version3      Version = 3
	LatestVersion         = Version3
)

Directories

Path Synopsis
The checkers package provides some standard first-party caveat checkers and some primitives for combining them.
The checkers package provides some standard first-party caveat checkers and some primitives for combining them.
This example demonstrates three components: - A target service, representing a web server that wishes to use macaroons for authorization.
This example demonstrates three components: - A target service, representing a web server that wishes to use macaroons for authorization.
internal
macaroonpb
Package macaroonpb is an internal package that allows us to hide the internal serialization details of macaroon ids.
Package macaroonpb is an internal package that allows us to hide the internal serialization details of macaroon ids.
Package mgorootkeystore provides an implementation of bakery.RootKeyStore that uses MongoDB as a persistent store.
Package mgorootkeystore provides an implementation of bakery.RootKeyStore that uses MongoDB as a persistent store.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL