forked from vanadium-archive/go.v23
-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.go
365 lines (333 loc) · 14.9 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
// 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.
// Package security defines types and utilities associated with security.
//
// Concept: https://vanadium.github.io/concepts/security.html
// Tutorial: (forthcoming)
//
// The primitives and APIs defined in this package enable bi-directional,
// end-to-end authentication between communicating parties; authorization based
// on that authentication; and secrecy and integrity of all communication.
//
// Overview
//
// The Vanadium security model is centered around the concepts of principals
// and blessings.
//
// A principal in the Vanadium framework is a public and private key pair.
// Every RPC is executed on behalf of a principal.
//
// A blessing is a binding of a human-readable name to a principal, valid under
// some caveats, given by another principal. A principal can have multiple
// blessings bound to it. For instance, a television principal may have a
// blessing from the manufacturer (e.g., popularcorp:products:tv) as well as
// from the owner (e.g., alice:devices:hometv). Principals are authorized for
// operations based on the blessings bound to them.
//
// A principal can "bless" another principal by binding an extension of one of
// its own blessings to the other principal. This enables delegation of
// authority. For example, a principal with the blessing
// "johndoe" can delegate to his phone by blessing the phone as
// "johndoe:phone", which in-turn can delegate to the headset by blessing it as
// "johndoe:phone:headset".
//
// Caveats can be added to a blessing in order to restrict the contexts in which
// it can be used. Amongst other things, caveats can restrict the duration of use and
// the set of peers that can be communicated with using a blessing.
//
// Navigating the interfaces
//
// Godoc renders all interfaces in this package in alphabetical order.
// However, we recommend the following order in order to introduce yourself to
// the API:
//
// * Principal
// * Blessings
// * BlessingStore
// * BlessingRoots
// * NewCaveat
// * ThirdPartyCaveat
// * NewPublicKeyCaveat
//
// Examples
//
// A principal can decide to name itself anything it wants:
// // (in process A)
// var p1 Principal
// alice, _ := p1.BlessSelf("alice")
//
// This "alice" blessing can be presented to to another principal (typically a
// remote process), but that other principal will not recognize this
// "self-proclaimed" authority:
// // (in process B)
// var p2 Principal
// ctx, call := GetContextAndCall() // current context and security state
// names, rejected := RemoteBlessingNames(ctx, call)
// fmt.Printf("%v %v", names, rejected) // Will print [] ["alice": "..."]
//
// However, p2 can decide to trust the roots of the "alice" blessing and then it
// will be able to recognize her delegates as well:
// // (in process B)
// AddToRoots(p2, call.RemoteBlessings())
// names, rejected := RemoteBlessingNames(ctx, call)
// fmt.Printf("%v %v", names, rejected) // Will print ["alice"] []
//
// Furthermore, p2 can seek a blessing from "alice":
// // (in process A)
// call := GetCall() // Call under which p2 is seeking a blessing from alice, call.LocalPrincipal = p1
// key2 := call.RemoteBlessings().PublicKey()
// onlyFor10Minutes := NewExpiryCaveat(time.Now().Add(10*time.Minute))
// aliceFriend, _ := p1.Bless(key2, alice, "friend", onlyFor10Minutes)
// SendBlessingToProcessB(aliceFriend)
//
// p2 can then add this blessing to its store such that this blessing will be
// presented to "alice" (and her delegates) anytime p2 communicates with it in
// the future:
// // (in process B)
// p2.BlessingStore().Set(aliceFriend, "alice")
//
// p2 can also choose to present multiple blessings to some servers:
// // (in process B)
// charlieFriend := ReceiveBlessingFromSomeWhere()
// union, _ := UnionOfBlessings(aliceFriend, charlieFriend)
// p2.BlessingStore().Set(union, "alice:mom")
//
// Thus, when communicating with a "server" that presents the blessing "alice:mom",
// p2 will declare that he is both "alice's friend" and "charlie's friend" and
// the server may authorize actions based on this fact.
//
// p2 may also choose that it wants to present these two blessings when acting
// as a "server", (i.e., when it does not know who the peer is):
// // (in process B)
// default, _ := UnionOfBlessings(aliceFriend, charlieFriend)
// p2.BlessingStore().SetDefault(default)
package security
import (
"time"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/vdl"
)
// Principal represents an entity capable of making or receiving RPCs.
// Principals have a unique (public, private) key pair, have (zero or more)
// blessings bound to them and can bless other principals.
//
// Multiple goroutines may invoke methods on a Principal simultaneously.
//
// See also: https://vanadium.github.io/glossary.html#principal
type Principal interface {
// Bless binds extensions of blessings held by this principal to
// another principal (represented by its public key).
//
// For example, a principal with the blessings "google:alice"
// and "v23:alice" can bind the blessings "google:alice:friend"
// and "v23:alice:friend" to another principal using:
// Bless(<other principal>, <google:alice, v23:alice>, "friend", ...)
//
// To discourage unconstrained delegation of authority, the interface
// requires at least one caveat to be provided. If unconstrained delegation
// is desired, the UnconstrainedUse function can be used to produce
// this argument.
//
// with.PublicKey must be the same as the principal's public key.
Bless(key PublicKey, with Blessings, extension string, caveat Caveat, additionalCaveats ...Caveat) (Blessings, error)
// BlessSelf creates a blessing with the provided name for this principal.
BlessSelf(name string, caveats ...Caveat) (Blessings, error)
// Sign uses the private key of the principal to sign message.
Sign(message []byte) (Signature, error)
// MintDischarge generates a discharge for 'tp'.
//
// It assumes that it is okay to generate a discharge, i.e., any
// restrictions encoded within 'tp' are satisfied.
//
// The returned discharge will be usable only if the provided caveats
// are met when using the discharge.
MintDischarge(forThirdPartyCaveat, caveatOnDischarge Caveat, additionalCaveatsOnDischarge ...Caveat) (Discharge, error)
// PublicKey returns the public key counterpart of the private key held
// by the Principal.
PublicKey() PublicKey
// BlessingStore provides access to the BlessingStore containing blessings
// that have been granted to this principal.
BlessingStore() BlessingStore
// Roots returns the set of recognized authorities (identified by their
// public keys) on blessings that match specific patterns
Roots() BlessingRoots
}
// BlessingStore is the interface for storing blessings bound to a
// principal and managing the subset of blessings to be presented to
// particular peers.
// BlessingStore implementations may also cache Discharges for third-party caveats
// on blessings, allowing unexpired Discharges to be reused.
type BlessingStore interface {
// Set marks the set of blessings to be shared with peers.
//
// Set(b, pattern) marks the intention to reveal b to peers
// who present blessings of their own matching pattern.
//
// If multiple calls to Set are made with the same pattern, the
// last call prevails.
//
// Set(Blessings{}, pattern) can be used to remove the blessings
// previously associated with the pattern (by a prior call to Set).
//
// It is an error to call Set with "blessings" whose public key does
// not match the PublicKey of the principal for which this store hosts
// blessings.
//
// Set returns the Blessings object which was previously associated
// with the pattern.
Set(blessings Blessings, forPeers BlessingPattern) (Blessings, error)
// ForPeer returns the set of blessings that have been previously
// added to the store with an intent of being shared with peers
// that have at least one of the provided blessings.
//
// If no peerBlessings are provided then blessings marked for all peers
// (i.e., added with the AllPrincipals pattern) is returned.
//
// Returns the zero value if there are no matching blessings in the store.
ForPeer(peerBlessings ...string) Blessings
// SetDefault sets up the Blessings made available on a subsequent call
// to Default.
//
// It is an error to call SetDefault with a blessings whose public key
// does not match the PublicKey of the principal for which this store
// hosts blessings.
SetDefault(blessings Blessings) error
// Default returns the blessings to be shared with peers for which no
// other information is available in order to select blessings from the
// store.
//
// For example, Default can be used by servers to identify themselves
// to clients before the client has identified itself.
//
// Default returns the blessings provided to the last call to
// SetDefault and a channel which will be closed when the
// Default changes (i.e., SetDefault is called again).
//
// Returns the zero value if there is no usable blessings.
Default() (Blessings, <-chan struct{})
// PublicKey returns the public key of the Principal for which
// this store hosts blessings.
PublicKey() PublicKey
// PeerBlessings returns all the blessings that the BlessingStore
// currently holds for various peers.
PeerBlessings() map[BlessingPattern]Blessings
// CacheDischarge inserts the discharge for the provided impetus and caveat into the cache.
CacheDischarge(discharge Discharge, caveat Caveat, impetus DischargeImpetus)
// ClearDischarges clears the input discharges from the BlessingStore's
// discharge cache.
ClearDischarges(discharges ...Discharge)
// Discharge takes a caveat and DischargeImpetus and returns a cached discharge
// and the time at which it was cached. Zero values are returned if no
// corresponding cached discharge can be found. Note that in certain upgrade
// situations a zero cacheTime may be returned if the real cache time cannot
// be determined.
Discharge(caveat Caveat, impetus DischargeImpetus) (discharge Discharge, cacheTime time.Time)
// DebugString return a human-readable string description of the store.
// This description is detailed and lists out the contents of the store.
// Use fmt.Sprintf("%v", ...) for a more succinct description.
DebugString() string
}
// BlessingRoots hosts the set of authoritative public keys for roots
// of blessings.
//
// See also: https://vanadium.github.io/glossary.html#blessing-root
type BlessingRoots interface {
// Add marks 'root' (a DER-encoded public key) as an authoritative key
// for blessings that match 'pattern'.
//
// Multiple keys can be added for the same pattern, in which
// case all those keys are considered authoritative for
// blessings that match the pattern.
Add(root []byte, pattern BlessingPattern) error
// Recognized returns nil iff the provided (DER-encoded) root public
// key as an authority on a pattern that is matched by blessing.
Recognized(root []byte, blessing string) error
// Dump returns the set of recognized roots as a map from
// blessing patterns to the set of authoritative keys for that
// pattern.
Dump() map[BlessingPattern][]PublicKey
// DebugString returns a human-readable string description of the roots.
// This description is detailed and lists out all the roots. Use
// fmt.Sprintf("%v", ...) for a more succinct description.
DebugString() string
}
// Signer is the interface for signing arbitrary length messages using private keys.
//
// Multiple goroutines may invoke methods on a Signer simultaneously.
type Signer interface {
// Sign signs an arbitrary length message using the private key associated
// with this Signer.
//
// The provided purpose is used to avoid "type attacks", wherein an honest
// entity is cheated into interpreting a field in a message as one with a
// type other than the intended one.
Sign(purpose, message []byte) (Signature, error)
// PublicKey returns the public key corresponding to the Signer's private key.
PublicKey() PublicKey
}
// ThirdPartyCaveat is a restriction on the applicability of a blessing that is
// considered satisfied only when accompanied with a specific "discharge" from
// the third-party specified in the caveat. (The first two parties are the ones
// presenting a blessing and the one making authorization decisions based on
// the blessing presented).
//
// Multiple goroutines may invoke methods on a ThirdPartyCaveat simultaneously.
//
// See also: https://vanadium.github.io/glossary.html#third-party-caveat
type ThirdPartyCaveat interface {
// ID returns a cryptographically unique identifier for the ThirdPartCaveat.
ID() string
// Location returns the Vanadium object name of the discharging third-party.
Location() string
// Requirements lists the information that the third-party requires
// in order to issue a discharge.
Requirements() ThirdPartyRequirements
// Dischargeable validates all restrictions encoded within the third-party
// caveat under the current call and returns nil iff they have been satisfied,
// and thus ensures that it is okay to generate a discharge for this
// ThirdPartyCaveat.
//
// It assumes that the ThirdPartCaveat was obtained from the remote end of
// call.
Dischargeable(ctx *context.T, call Call) error
}
// Call defines the state available for authorizing a principal.
type Call interface {
// Timestamp returns the time at which the authorization state is to be checked.
Timestamp() time.Time
// Method returns the method being invoked.
Method() string
// MethodTags returns the tags attached to the method, typically through the
// interface specification in VDL.
MethodTags() []*vdl.Value
// Suffix returns the object name suffix for the request.
Suffix() string
// LocalDischarges specify discharges for third-party caveats presented by
// the local end of the call. It maps a third-party caveat identifier to the
// corresponding discharge.
LocalDischarges() map[string]Discharge
// RemoteDischarges specify discharges for third-party caveats presented by
// the remote end of the call. It maps a third-party caveat identifier to the
// corresponding discharge.
RemoteDischarges() map[string]Discharge
// LocalPrincipal returns the principal used to authenticate to the remote end.
LocalPrincipal() Principal
// LocalBlessings returns the blessings (bound to the local end)
// provided to the remote end for authentication.
LocalBlessings() Blessings
// RemoteBlessings returns the blessings (bound to the remote end)
// provided to the local end during authentication.
RemoteBlessings() Blessings
// LocalEndpoint() returns the Endpoint of the principal at the local
// end of communication.
LocalEndpoint() naming.Endpoint
// RemoteEndpoint() returns the Endpoint of the principal at the remote end
// of communication.
RemoteEndpoint() naming.Endpoint
}
// Authorizer is the interface for performing authorization checks.
type Authorizer interface {
Authorize(ctx *context.T, call Call) error
}