blob: 529229722b61e45e04ed4ed73578c1fa7d4125fd [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Todd Wang88509682015-04-10 10:28:24 -07005// Package agentlib implements a client for communicating with an agentd process
6// holding the private key for an identity.
7package agentlib
Ryan Brownfed691e2014-09-15 13:09:40 -07008
9import (
10 "fmt"
Ryan Brown0a3e28a2015-08-12 14:59:14 -070011 "io"
Ryan Brown0a3e28a2015-08-12 14:59:14 -070012 "sync"
Ryan Brownfed691e2014-09-15 13:09:40 -070013
Jiri Simsa6ac95222015-02-23 16:11:49 -080014 "v.io/v23/security"
Ryan Brown7f950a82015-04-20 18:08:39 -070015 "v.io/v23/verror"
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -070016 "v.io/x/ref/internal/logger"
Ryan Brown0a3e28a2015-08-12 14:59:14 -070017 "v.io/x/ref/services/agent"
Todd Wangb3511492015-04-07 23:32:34 -070018 "v.io/x/ref/services/agent/internal/cache"
Ryan Brown0a3e28a2015-08-12 14:59:14 -070019 "v.io/x/ref/services/agent/internal/ipc"
Ryan Brownfed691e2014-09-15 13:09:40 -070020)
21
Ryan Brown7f950a82015-04-20 18:08:39 -070022const pkgPath = "v.io/x/ref/services/agent/agentlib"
23
24// Errors
25var (
26 errInvalidProtocol = verror.Register(pkgPath+".errInvalidProtocol",
27 verror.NoRetry, "{1:}{2:} invalid agent protocol {3}")
28)
Ryan Brownfed691e2014-09-15 13:09:40 -070029
30type client struct {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070031 caller caller
Ryan Brownfed691e2014-09-15 13:09:40 -070032 key security.PublicKey
33}
34
Ryan Brown0a3e28a2015-08-12 14:59:14 -070035type caller interface {
36 call(name string, results []interface{}, args ...interface{}) error
37 io.Closer
38}
39
40type ipcCaller struct {
41 conn *ipc.IPCConn
42 flush func()
43 mu sync.Mutex
44}
45
46func (i *ipcCaller) call(name string, results []interface{}, args ...interface{}) error {
47 return i.conn.Call(name, args, results...)
48}
49
50func (i *ipcCaller) Close() error {
51 i.conn.Close()
52 return nil
53}
54
55func (i *ipcCaller) FlushAllCaches() error {
56 var flush func()
57 i.mu.Lock()
58 flush = i.flush
59 i.mu.Unlock()
60 if flush != nil {
61 flush()
62 }
63 return nil
64}
65
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070066func results(inputs ...interface{}) []interface{} {
Todd Wange77f9952015-02-18 13:20:50 -080067 return inputs
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070068}
69
Ryan Brown0a3e28a2015-08-12 14:59:14 -070070func newUncachedPrincipalX(path string) (*client, error) {
71 caller := new(ipcCaller)
72 i := ipc.NewIPC()
73 i.Serve(caller)
74 conn, err := i.Connect(path)
75 if err != nil {
76 return nil, err
77 }
78 caller.conn = conn
79 agent := &client{caller: caller}
80 if err := agent.fetchPublicKey(); err != nil {
81 return nil, err
82 }
83 return agent, nil
84}
85
86// NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process.
87// 'path' is the path to the agent socket, typically obtained from
88// os.GetEnv(envvar.AgentAddress).
89func NewAgentPrincipalX(path string) (agent.Principal, error) {
90 p, err := newUncachedPrincipalX(path)
91 if err != nil {
92 return nil, err
93 }
94 cached, flush, err := cache.NewCachedPrincipalX(p)
95 if err != nil {
96 return nil, err
97 }
98 caller := p.caller.(*ipcCaller)
99 caller.mu.Lock()
100 caller.flush = flush
101 caller.mu.Unlock()
102 return cached, nil
103}
104
Ryan Brown0a3e28a2015-08-12 14:59:14 -0700105func (c *client) Close() error {
106 return c.caller.Close()
107}
108
Ryan Brownfed691e2014-09-15 13:09:40 -0700109func (c *client) fetchPublicKey() (err error) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700110 var b []byte
111 if err = c.caller.call("PublicKey", results(&b)); err != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -0700112 return
113 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700114 c.key, err = security.UnmarshalPublicKey(b)
Ryan Brownfed691e2014-09-15 13:09:40 -0700115 return
116}
117
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700118func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
Asim Shankarb07ec692015-02-27 23:40:44 -0800119 var blessings security.Blessings
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700120 marshalledKey, err := key.MarshalBinary()
121 if err != nil {
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800122 return security.Blessings{}, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700123 }
Asim Shankarb07ec692015-02-27 23:40:44 -0800124 err = c.caller.call("Bless", results(&blessings), marshalledKey, with, extension, caveat, additionalCaveats)
125 return blessings, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700126}
127
128func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
Asim Shankarb07ec692015-02-27 23:40:44 -0800129 var blessings security.Blessings
130 err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
131 return blessings, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700132}
133
134func (c *client) Sign(message []byte) (sig security.Signature, err error) {
135 err = c.caller.call("Sign", results(&sig), message)
136 return
137}
138
Asim Shankar19da8182015-02-06 01:41:16 -0800139func (c *client) MintDischarge(forCaveat, caveatOnDischarge security.Caveat, additionalCaveatsOnDischarge ...security.Caveat) (security.Discharge, error) {
Asim Shankar08642822015-03-02 21:21:09 -0800140 var discharge security.Discharge
Asim Shankar19da8182015-02-06 01:41:16 -0800141 if err := c.caller.call("MintDischarge", results(&discharge), forCaveat, caveatOnDischarge, additionalCaveatsOnDischarge); err != nil {
Asim Shankar3ad0b8a2015-02-25 00:37:21 -0800142 return security.Discharge{}, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700143 }
Asim Shankar08642822015-03-02 21:21:09 -0800144 return discharge, nil
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700145}
146
Ryan Brownfed691e2014-09-15 13:09:40 -0700147func (c *client) PublicKey() security.PublicKey {
148 return c.key
149}
150
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700151func (c *client) BlessingStore() security.BlessingStore {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700152 return &blessingStore{caller: c.caller, key: c.key}
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700153}
154
155func (c *client) Roots() security.BlessingRoots {
156 return &blessingRoots{c.caller}
157}
158
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700159type blessingStore struct {
160 caller caller
161 key security.PublicKey
162}
163
164func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
Asim Shankarb07ec692015-02-27 23:40:44 -0800165 var previous security.Blessings
166 err := b.caller.call("BlessingStoreSet", results(&previous), blessings, forPeers)
167 return previous, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700168}
169
170func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800171 var blessings security.Blessings
172 if err := b.caller.call("BlessingStoreForPeer", results(&blessings), peerBlessings); err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700173 logger.Global().Infof("error calling BlessingStorePeerBlessings: %v", err)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700174 }
175 return blessings
176}
177
178func (b *blessingStore) SetDefault(blessings security.Blessings) error {
Asim Shankarb07ec692015-02-27 23:40:44 -0800179 return b.caller.call("BlessingStoreSetDefault", results(), blessings)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700180}
181
182func (b *blessingStore) Default() security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800183 var blessings security.Blessings
184 err := b.caller.call("BlessingStoreDefault", results(&blessings))
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700185 if err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700186 logger.Global().Infof("error calling BlessingStoreDefault: %v", err)
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800187 return security.Blessings{}
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700188 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700189 return blessings
190}
191
192func (b *blessingStore) PublicKey() security.PublicKey {
193 return b.key
194}
195
gauthamtf8263932014-12-16 10:59:09 -0800196func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800197 var bmap map[security.BlessingPattern]security.Blessings
198 err := b.caller.call("BlessingStorePeerBlessings", results(&bmap))
gauthamtf8263932014-12-16 10:59:09 -0800199 if err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700200 logger.Global().Infof("error calling BlessingStorePeerBlessings: %v", err)
gauthamtf8263932014-12-16 10:59:09 -0800201 return nil
202 }
Asim Shankarb07ec692015-02-27 23:40:44 -0800203 return bmap
gauthamtf8263932014-12-16 10:59:09 -0800204}
205
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700206func (b *blessingStore) DebugString() (s string) {
207 err := b.caller.call("BlessingStoreDebugString", results(&s))
208 if err != nil {
209 s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700210 logger.Global().Infof(s)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700211 }
212 return
213}
214
Suharsh Sivakumard7d4e222015-06-22 11:10:44 -0700215func (b *blessingStore) CacheDischarge(d security.Discharge, c security.Caveat, i security.DischargeImpetus) {
216 err := b.caller.call("BlessingStoreCacheDischarge", results(), d, c, i)
217 if err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700218 logger.Global().Infof("error calling BlessingStoreCacheDischarge: %v", err)
Suharsh Sivakumard7d4e222015-06-22 11:10:44 -0700219 }
220}
221
222func (b *blessingStore) ClearDischarges(discharges ...security.Discharge) {
223 err := b.caller.call("BlessingStoreClearDischarges", results(), discharges)
224 if err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700225 logger.Global().Infof("error calling BlessingStoreClearDischarges: %v", err)
Suharsh Sivakumard7d4e222015-06-22 11:10:44 -0700226 }
227}
228
229func (b *blessingStore) Discharge(caveat security.Caveat, impetus security.DischargeImpetus) (out security.Discharge) {
230 err := b.caller.call("BlessingStoreDischarge", results(&out), caveat, impetus)
231 if err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700232 logger.Global().Infof("error calling BlessingStoreDischarge: %v", err)
Suharsh Sivakumard7d4e222015-06-22 11:10:44 -0700233 }
234 return
235}
236
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700237type blessingRoots struct {
238 caller caller
239}
240
Asim Shankar6eba9862015-09-03 01:07:14 -0400241func (b *blessingRoots) Add(root []byte, pattern security.BlessingPattern) error {
242 return b.caller.call("BlessingRootsAdd", results(), root, pattern)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700243}
244
Asim Shankar6eba9862015-09-03 01:07:14 -0400245func (b *blessingRoots) Recognized(root []byte, blessing string) error {
246 return b.caller.call("BlessingRootsRecognized", results(), root, blessing)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700247}
248
Ankur9e5b7722015-04-28 15:00:25 -0700249func (b *blessingRoots) Dump() map[security.BlessingPattern][]security.PublicKey {
250 var marshaledRoots map[security.BlessingPattern][][]byte
251 if err := b.caller.call("BlessingRootsDump", results(&marshaledRoots)); err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700252 logger.Global().Infof("error calling BlessingRootsDump: %v", err)
Ankur9e5b7722015-04-28 15:00:25 -0700253 return nil
254 }
255 ret := make(map[security.BlessingPattern][]security.PublicKey)
256 for p, marshaledKeys := range marshaledRoots {
257 for _, marshaledKey := range marshaledKeys {
258 key, err := security.UnmarshalPublicKey(marshaledKey)
259 if err != nil {
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700260 logger.Global().Infof("security.UnmarshalPublicKey(%v) returned error: %v", marshaledKey, err)
Ankur9e5b7722015-04-28 15:00:25 -0700261 continue
262 }
263 ret[p] = append(ret[p], key)
264 }
265 }
266 return ret
267}
268
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700269func (b *blessingRoots) DebugString() (s string) {
270 err := b.caller.call("BlessingRootsDebugString", results(&s))
271 if err != nil {
272 s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
Cosmos Nicolaou1c33b7d2015-06-24 15:15:54 -0700273 logger.Global().Infof(s)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700274 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700275 return
276}