blob: 77c6ddec95a0cc916dfc939d02edf6c1447aaca6 [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).
Bogdan Caprita6613fc42015-01-28 11:54:23 -080060// 'ctx' should not have a deadline, and should never be cancelled while the
61// principal is in use.
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080062func NewAgentPrincipal(ctx *context.T, fd int, insecureClient ipc.Client) (security.Principal, error) {
Ryan Brown81789442014-10-30 13:23:53 -070063 f := os.NewFile(uintptr(fd), "agent_client")
64 defer f.Close()
65 conn, err := net.FileConn(f)
Ryan Brown50b473a2014-09-23 14:23:00 -070066 if err != nil {
67 return nil, err
68 }
69 // This is just an arbitrary 1 byte string. The value is ignored.
70 data := make([]byte, 1)
Bogdan Capritabb37c542015-01-22 10:21:57 -080071 addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data)
Ryan Brown50b473a2014-09-23 14:23:00 -070072 if err != nil {
73 return nil, err
74 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070075 caller := caller{
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080076 client: insecureClient,
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070077 name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
78 ctx: ctx,
79 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070080 agent := &client{caller: caller}
Ryan Brownfed691e2014-09-15 13:09:40 -070081 if err := agent.fetchPublicKey(); err != nil {
82 return nil, err
83 }
84 return agent, nil
85}
86
87func (c *client) fetchPublicKey() (err error) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070088 var b []byte
89 if err = c.caller.call("PublicKey", results(&b)); err != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -070090 return
91 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070092 c.key, err = security.UnmarshalPublicKey(b)
Ryan Brownfed691e2014-09-15 13:09:40 -070093 return
94}
95
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070096func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
97 var blessings security.WireBlessings
98 marshalledKey, err := key.MarshalBinary()
99 if err != nil {
100 return nil, err
101 }
102 err = c.caller.call("Bless", results(&blessings), marshalledKey, security.MarshalBlessings(with), extension, caveat, additionalCaveats)
103 if err != nil {
104 return nil, err
105 }
106 return security.NewBlessings(blessings)
107}
108
109func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
110 var blessings security.WireBlessings
111 err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
112 if err != nil {
113 return nil, err
114 }
115 return security.NewBlessings(blessings)
116}
117
118func (c *client) Sign(message []byte) (sig security.Signature, err error) {
119 err = c.caller.call("Sign", results(&sig), message)
120 return
121}
122
123func (c *client) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) {
124 var discharge security.Discharge
Todd Wangb86b3522015-01-22 13:34:20 -0800125 err := c.caller.call("MintDischarge", results(&discharge), vdl.AnyRep(tp), caveat, additionalCaveats)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700126 if err != nil {
127 return nil, err
128 }
129 return discharge, nil
130}
131
Ryan Brownfed691e2014-09-15 13:09:40 -0700132func (c *client) PublicKey() security.PublicKey {
133 return c.key
134}
135
gauthamtf8263932014-12-16 10:59:09 -0800136func (c *client) BlessingsByName(pattern security.BlessingPattern) []security.Blessings {
137 var wbResults []security.WireBlessings
138 err := c.caller.call("BlessingsByName", results(&wbResults), pattern)
139 if err != nil {
140 vlog.Errorf("error calling BlessingsByName: %v", err)
141 return nil
142 }
143 blessings := make([]security.Blessings, len(wbResults))
144 for i, wb := range wbResults {
145 var err error
146 blessings[i], err = security.NewBlessings(wb)
147 if err != nil {
148 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
149 }
150 }
151 return blessings
152}
153
gauthamt8dc9a182015-01-08 18:03:18 -0800154func (c *client) BlessingsInfo(blessings security.Blessings) map[string][]security.Caveat {
155 var bInfo map[string][]security.Caveat
156 err := c.caller.call("BlessingsInfo", results(&bInfo), security.MarshalBlessings(blessings))
gauthamtf8263932014-12-16 10:59:09 -0800157 if err != nil {
158 vlog.Errorf("error calling BlessingsInfo: %v", err)
159 return nil
160 }
gauthamt8dc9a182015-01-08 18:03:18 -0800161 return bInfo
gauthamtf8263932014-12-16 10:59:09 -0800162}
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700163func (c *client) BlessingStore() security.BlessingStore {
164 return &blessingStore{c.caller, c.key}
165}
166
167func (c *client) Roots() security.BlessingRoots {
168 return &blessingRoots{c.caller}
169}
170
171func (c *client) AddToRoots(blessings security.Blessings) error {
172 return c.caller.call("AddToRoots", results(), security.MarshalBlessings(blessings))
173}
174
175type blessingStore struct {
176 caller caller
177 key security.PublicKey
178}
179
180func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
181 var resultBlessings security.WireBlessings
182 err := b.caller.call("BlessingStoreSet", results(&resultBlessings), security.MarshalBlessings(blessings), forPeers)
183 if err != nil {
184 return nil, err
Ryan Brownfed691e2014-09-15 13:09:40 -0700185 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700186 return security.NewBlessings(resultBlessings)
187}
188
189func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
190 var resultBlessings security.WireBlessings
191 err := b.caller.call("BlessingStoreForPeer", results(&resultBlessings), peerBlessings)
192 if err != nil {
193 vlog.Errorf("error calling BlessingStoreForPeer: %v", err)
194 return nil
195 }
196 blessings, err := security.NewBlessings(resultBlessings)
197 if err != nil {
198 vlog.Errorf("error creating Blessings from WireBlessings: %v", err)
199 return nil
200 }
201 return blessings
202}
203
204func (b *blessingStore) SetDefault(blessings security.Blessings) error {
205 return b.caller.call("BlessingStoreSetDefault", results(), security.MarshalBlessings(blessings))
206}
207
208func (b *blessingStore) Default() security.Blessings {
209 var resultBlessings security.WireBlessings
210 err := b.caller.call("BlessingStoreDefault", results(&resultBlessings))
211 if err != nil {
212 vlog.Errorf("error calling BlessingStoreDefault: %v", err)
213 return nil
214 }
215 blessings, err := security.NewBlessings(resultBlessings)
216 if err != nil {
217 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
218 return nil
219 }
220 return blessings
221}
222
223func (b *blessingStore) PublicKey() security.PublicKey {
224 return b.key
225}
226
gauthamtf8263932014-12-16 10:59:09 -0800227func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
228 var wbMap map[security.BlessingPattern]security.WireBlessings
229 err := b.caller.call("BlessingStorePeerBlessings", results(&wbMap))
230 if err != nil {
231 vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
232 return nil
233 }
234 bMap := make(map[security.BlessingPattern]security.Blessings)
235 for pattern, wb := range wbMap {
236 blessings, err := security.NewBlessings(wb)
237 if err != nil {
238 vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
239 return nil
240 }
241 bMap[pattern] = blessings
242 }
243 return bMap
244}
245
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700246func (b *blessingStore) DebugString() (s string) {
247 err := b.caller.call("BlessingStoreDebugString", results(&s))
248 if err != nil {
249 s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
250 vlog.Errorf(s)
251 }
252 return
253}
254
255type blessingRoots struct {
256 caller caller
257}
258
259func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
260 marshalledKey, err := root.MarshalBinary()
261 if err != nil {
262 return err
263 }
264 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern)
265}
266
267func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
268 marshalledKey, err := root.MarshalBinary()
269 if err != nil {
270 return err
271 }
Asim Shankarb378e662015-01-16 10:50:48 -0800272 return b.caller.call("BlessingRootsRecognized", results(), marshalledKey, blessing)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700273}
274
275func (b *blessingRoots) DebugString() (s string) {
276 err := b.caller.call("BlessingRootsDebugString", results(&s))
277 if err != nil {
278 s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
279 vlog.Errorf(s)
280 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700281 return
282}