blob: f3128f949a24e97ba1df5cff30f1d0050460c15e [file] [log] [blame]
Ryan Brownfed691e2014-09-15 13:09:40 -07001// Package agent provides a client for communicating with an "Agent"
2// process holding the private key for an identity.
3package agent
4
5import (
6 "fmt"
Ryan Brown50b473a2014-09-23 14:23:00 -07007 "net"
8 "os"
Ryan Brownfed691e2014-09-15 13:09:40 -07009
Jiri Simsa764efb72014-12-25 20:57:03 -080010 "v.io/core/veyron/lib/unixfd"
11 "v.io/core/veyron2/context"
12 "v.io/core/veyron2/ipc"
13 "v.io/core/veyron2/naming"
Suharsh Sivakumarae774a52015-01-09 14:26:32 -080014 "v.io/core/veyron2/options"
Jiri Simsa764efb72014-12-25 20:57:03 -080015 "v.io/core/veyron2/security"
Todd Wangb86b3522015-01-22 13:34:20 -080016 "v.io/core/veyron2/vdl"
Jiri Simsa764efb72014-12-25 20:57:03 -080017 "v.io/core/veyron2/vlog"
Matt Rosencrantz6edab562015-01-12 11:07:55 -080018 "v.io/core/veyron2/vtrace"
Ryan Brownfed691e2014-09-15 13:09:40 -070019)
20
Ryan Brown50b473a2014-09-23 14:23:00 -070021// FdVarName is the name of the environment variable containing
22// the file descriptor for talking to the agent.
23const FdVarName = "VEYRON_AGENT_FD"
Ryan Brownfed691e2014-09-15 13:09:40 -070024
25type client struct {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070026 caller caller
Ryan Brownfed691e2014-09-15 13:09:40 -070027 key security.PublicKey
28}
29
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070030type caller struct {
Matt Rosencrantz6edab562015-01-12 11:07:55 -080031 ctx *context.T
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070032 client ipc.Client
33 name string
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070034}
35
36func (c *caller) call(name string, results []interface{}, args ...interface{}) (err error) {
Ryan Brownfed691e2014-09-15 13:09:40 -070037 var call ipc.Call
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070038 results = append(results, &err)
Matt Rosencrantz6edab562015-01-12 11:07:55 -080039
40 ctx, _ := vtrace.SetNewTrace(c.ctx)
Suharsh Sivakumarae774a52015-01-09 14:26:32 -080041 // VCSecurityNone is safe here since we're using anonymous unix sockets.
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080042 if call, err = c.client.StartCall(ctx, c.name, name, args, options.VCSecurityNone, options.NoResolve{}); err == nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070043 if ierr := call.Finish(results...); ierr != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070044 err = ierr
45 }
46 }
47 return
48}
49
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070050func results(inputs ...interface{}) []interface{} {
51 if len(inputs) > 0 {
52 return inputs
53 }
54 return make([]interface{}, 0)
55}
56
57// NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process.
Ryan Brown50b473a2014-09-23 14:23:00 -070058// 'fd' is the socket for connecting to the agent, typically obtained from
59// os.GetEnv(agent.FdVarName).
Ryan Brownfed691e2014-09-15 13:09:40 -070060// 'ctx' should not have a deadline, and should never be cancelled.
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080061func NewAgentPrincipal(ctx *context.T, fd int, insecureClient ipc.Client) (security.Principal, error) {
Ryan Brown81789442014-10-30 13:23:53 -070062 f := os.NewFile(uintptr(fd), "agent_client")
63 defer f.Close()
64 conn, err := net.FileConn(f)
Ryan Brown50b473a2014-09-23 14:23:00 -070065 if err != nil {
66 return nil, err
67 }
68 // This is just an arbitrary 1 byte string. The value is ignored.
69 data := make([]byte, 1)
Bogdan Capritabb37c542015-01-22 10:21:57 -080070 addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data)
Ryan Brown50b473a2014-09-23 14:23:00 -070071 if err != nil {
72 return nil, err
73 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070074 caller := caller{
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080075 client: insecureClient,
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070076 name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
77 ctx: ctx,
78 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070079 agent := &client{caller: caller}
Ryan Brownfed691e2014-09-15 13:09:40 -070080 if err := agent.fetchPublicKey(); err != nil {
81 return nil, err
82 }
83 return agent, nil
84}
85
86func (c *client) fetchPublicKey() (err error) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070087 var b []byte
88 if err = c.caller.call("PublicKey", results(&b)); err != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070089 return
90 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070091 c.key, err = security.UnmarshalPublicKey(b)
Ryan Brownfed691e2014-09-15 13:09:40 -070092 return
93}
94
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070095func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
96 var blessings security.WireBlessings
97 marshalledKey, err := key.MarshalBinary()
98 if err != nil {
99 return nil, err
100 }
101 err = c.caller.call("Bless", results(&blessings), marshalledKey, security.MarshalBlessings(with), extension, caveat, additionalCaveats)
102 if err != nil {
103 return nil, err
104 }
105 return security.NewBlessings(blessings)
106}
107
108func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
109 var blessings security.WireBlessings
110 err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
111 if err != nil {
112 return nil, err
113 }
114 return security.NewBlessings(blessings)
115}
116
117func (c *client) Sign(message []byte) (sig security.Signature, err error) {
118 err = c.caller.call("Sign", results(&sig), message)
119 return
120}
121
122func (c *client) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) {
123 var discharge security.Discharge
Todd Wangb86b3522015-01-22 13:34:20 -0800124 err := c.caller.call("MintDischarge", results(&discharge), vdl.AnyRep(tp), caveat, additionalCaveats)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700125 if err != nil {
126 return nil, err
127 }
128 return discharge, nil
129}
130
Ryan Brownfed691e2014-09-15 13:09:40 -0700131func (c *client) PublicKey() security.PublicKey {
132 return c.key
133}
134
gauthamtf8263932014-12-16 10:59:09 -0800135func (c *client) BlessingsByName(pattern security.BlessingPattern) []security.Blessings {
136 var wbResults []security.WireBlessings
137 err := c.caller.call("BlessingsByName", results(&wbResults), pattern)
138 if err != nil {
139 vlog.Errorf("error calling BlessingsByName: %v", err)
140 return nil
141 }
142 blessings := make([]security.Blessings, len(wbResults))
143 for i, wb := range wbResults {
144 var err error
145 blessings[i], err = security.NewBlessings(wb)
146 if err != nil {
147 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
148 }
149 }
150 return blessings
151}
152
gauthamt8dc9a182015-01-08 18:03:18 -0800153func (c *client) BlessingsInfo(blessings security.Blessings) map[string][]security.Caveat {
154 var bInfo map[string][]security.Caveat
155 err := c.caller.call("BlessingsInfo", results(&bInfo), security.MarshalBlessings(blessings))
gauthamtf8263932014-12-16 10:59:09 -0800156 if err != nil {
157 vlog.Errorf("error calling BlessingsInfo: %v", err)
158 return nil
159 }
gauthamt8dc9a182015-01-08 18:03:18 -0800160 return bInfo
gauthamtf8263932014-12-16 10:59:09 -0800161}
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700162func (c *client) BlessingStore() security.BlessingStore {
163 return &blessingStore{c.caller, c.key}
164}
165
166func (c *client) Roots() security.BlessingRoots {
167 return &blessingRoots{c.caller}
168}
169
170func (c *client) AddToRoots(blessings security.Blessings) error {
171 return c.caller.call("AddToRoots", results(), security.MarshalBlessings(blessings))
172}
173
174type blessingStore struct {
175 caller caller
176 key security.PublicKey
177}
178
179func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
180 var resultBlessings security.WireBlessings
181 err := b.caller.call("BlessingStoreSet", results(&resultBlessings), security.MarshalBlessings(blessings), forPeers)
182 if err != nil {
183 return nil, err
Ryan Brownfed691e2014-09-15 13:09:40 -0700184 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700185 return security.NewBlessings(resultBlessings)
186}
187
188func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
189 var resultBlessings security.WireBlessings
190 err := b.caller.call("BlessingStoreForPeer", results(&resultBlessings), peerBlessings)
191 if err != nil {
192 vlog.Errorf("error calling BlessingStoreForPeer: %v", err)
193 return nil
194 }
195 blessings, err := security.NewBlessings(resultBlessings)
196 if err != nil {
197 vlog.Errorf("error creating Blessings from WireBlessings: %v", err)
198 return nil
199 }
200 return blessings
201}
202
203func (b *blessingStore) SetDefault(blessings security.Blessings) error {
204 return b.caller.call("BlessingStoreSetDefault", results(), security.MarshalBlessings(blessings))
205}
206
207func (b *blessingStore) Default() security.Blessings {
208 var resultBlessings security.WireBlessings
209 err := b.caller.call("BlessingStoreDefault", results(&resultBlessings))
210 if err != nil {
211 vlog.Errorf("error calling BlessingStoreDefault: %v", err)
212 return nil
213 }
214 blessings, err := security.NewBlessings(resultBlessings)
215 if err != nil {
216 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
217 return nil
218 }
219 return blessings
220}
221
222func (b *blessingStore) PublicKey() security.PublicKey {
223 return b.key
224}
225
gauthamtf8263932014-12-16 10:59:09 -0800226func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
227 var wbMap map[security.BlessingPattern]security.WireBlessings
228 err := b.caller.call("BlessingStorePeerBlessings", results(&wbMap))
229 if err != nil {
230 vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
231 return nil
232 }
233 bMap := make(map[security.BlessingPattern]security.Blessings)
234 for pattern, wb := range wbMap {
235 blessings, err := security.NewBlessings(wb)
236 if err != nil {
237 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
238 return nil
239 }
240 bMap[pattern] = blessings
241 }
242 return bMap
243}
244
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700245func (b *blessingStore) DebugString() (s string) {
246 err := b.caller.call("BlessingStoreDebugString", results(&s))
247 if err != nil {
248 s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
249 vlog.Errorf(s)
250 }
251 return
252}
253
254type blessingRoots struct {
255 caller caller
256}
257
258func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
259 marshalledKey, err := root.MarshalBinary()
260 if err != nil {
261 return err
262 }
263 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern)
264}
265
266func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
267 marshalledKey, err := root.MarshalBinary()
268 if err != nil {
269 return err
270 }
Asim Shankarb378e662015-01-16 10:50:48 -0800271 return b.caller.call("BlessingRootsRecognized", results(), marshalledKey, blessing)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700272}
273
274func (b *blessingRoots) DebugString() (s string) {
275 err := b.caller.call("BlessingRootsDebugString", results(&s))
276 if err != nil {
277 s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
278 vlog.Errorf(s)
279 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700280 return
281}