blob: 419fed22f9ed3488e31736a1692e427713044f81 [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
Ryan Brownfed691e2014-09-15 13:09:40 -07005// Package agent provides a client for communicating with an "Agent"
6// process holding the private key for an identity.
7package agent
8
9import (
10 "fmt"
Ryan Brown50b473a2014-09-23 14:23:00 -070011 "net"
12 "os"
Ryan Brownfed691e2014-09-15 13:09:40 -070013
Jiri Simsa6ac95222015-02-23 16:11:49 -080014 "v.io/v23/context"
Jiri Simsa6ac95222015-02-23 16:11:49 -080015 "v.io/v23/naming"
16 "v.io/v23/options"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070017 "v.io/v23/rpc"
Jiri Simsa6ac95222015-02-23 16:11:49 -080018 "v.io/v23/security"
Jiri Simsa6ac95222015-02-23 16:11:49 -080019 "v.io/v23/vtrace"
Jiri Simsa337af232015-02-27 14:36:46 -080020 "v.io/x/lib/vlog"
Jiri Simsaffceefa2015-02-28 11:03:34 -080021 "v.io/x/ref/lib/unixfd"
22 "v.io/x/ref/security/agent/cache"
Ryan Brownfed691e2014-09-15 13:09:40 -070023)
24
Ryan Brown50b473a2014-09-23 14:23:00 -070025// FdVarName is the name of the environment variable containing
26// the file descriptor for talking to the agent.
27const FdVarName = "VEYRON_AGENT_FD"
Ryan Brownfed691e2014-09-15 13:09:40 -070028
29type client struct {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070030 caller caller
Ryan Brownfed691e2014-09-15 13:09:40 -070031 key security.PublicKey
32}
33
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070034type caller struct {
Matt Rosencrantz6edab562015-01-12 11:07:55 -080035 ctx *context.T
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070036 client rpc.Client
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070037 name string
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070038}
39
Todd Wange77f9952015-02-18 13:20:50 -080040func (c *caller) call(name string, results []interface{}, args ...interface{}) error {
41 call, err := c.startCall(name, args...)
42 if err != nil {
43 return err
Ryan Brownfed691e2014-09-15 13:09:40 -070044 }
Todd Wange77f9952015-02-18 13:20:50 -080045 if err := call.Finish(results...); err != nil {
46 return err
47 }
48 return nil
Ryan Brownfed691e2014-09-15 13:09:40 -070049}
50
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070051func (c *caller) startCall(name string, args ...interface{}) (rpc.ClientCall, error) {
Ryan Brown81bcb3a2015-02-11 10:58:01 -080052 ctx, _ := vtrace.SetNewTrace(c.ctx)
Suharsh Sivakumar2c5d8102015-03-23 08:49:12 -070053 // SecurityNone is safe here since we're using anonymous unix sockets.
54 return c.client.StartCall(ctx, c.name, name, args, options.SecurityNone, options.NoResolve{})
Ryan Brown81bcb3a2015-02-11 10:58:01 -080055}
56
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070057func results(inputs ...interface{}) []interface{} {
Todd Wange77f9952015-02-18 13:20:50 -080058 return inputs
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070059}
60
61// NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process.
Ryan Brown50b473a2014-09-23 14:23:00 -070062// 'fd' is the socket for connecting to the agent, typically obtained from
63// os.GetEnv(agent.FdVarName).
Bogdan Caprita6613fc42015-01-28 11:54:23 -080064// 'ctx' should not have a deadline, and should never be cancelled while the
65// principal is in use.
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070066func NewAgentPrincipal(ctx *context.T, fd int, insecureClient rpc.Client) (security.Principal, error) {
Ryan Brown81bcb3a2015-02-11 10:58:01 -080067 p, err := newUncachedPrincipal(ctx, fd, insecureClient)
68 if err != nil {
69 return p, err
70 }
71 call, callErr := p.caller.startCall("NotifyWhenChanged")
72 if callErr != nil {
73 return nil, callErr
74 }
75 return cache.NewCachedPrincipal(p.caller.ctx, p, call)
76}
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070077func newUncachedPrincipal(ctx *context.T, fd int, insecureClient rpc.Client) (*client, error) {
Ryan Brown81789442014-10-30 13:23:53 -070078 f := os.NewFile(uintptr(fd), "agent_client")
79 defer f.Close()
80 conn, err := net.FileConn(f)
Ryan Brown50b473a2014-09-23 14:23:00 -070081 if err != nil {
82 return nil, err
83 }
84 // This is just an arbitrary 1 byte string. The value is ignored.
85 data := make([]byte, 1)
Bogdan Capritabb37c542015-01-22 10:21:57 -080086 addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data)
Ryan Brown50b473a2014-09-23 14:23:00 -070087 if err != nil {
88 return nil, err
89 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070090 caller := caller{
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -080091 client: insecureClient,
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070092 name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
93 ctx: ctx,
94 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070095 agent := &client{caller: caller}
Ryan Brownfed691e2014-09-15 13:09:40 -070096 if err := agent.fetchPublicKey(); err != nil {
97 return nil, err
98 }
99 return agent, nil
100}
101
102func (c *client) fetchPublicKey() (err error) {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700103 var b []byte
104 if err = c.caller.call("PublicKey", results(&b)); err != nil {
Ryan Brownfed691e2014-09-15 13:09:40 -0700105 return
106 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700107 c.key, err = security.UnmarshalPublicKey(b)
Ryan Brownfed691e2014-09-15 13:09:40 -0700108 return
109}
110
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700111func (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 -0800112 var blessings security.Blessings
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700113 marshalledKey, err := key.MarshalBinary()
114 if err != nil {
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800115 return security.Blessings{}, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700116 }
Asim Shankarb07ec692015-02-27 23:40:44 -0800117 err = c.caller.call("Bless", results(&blessings), marshalledKey, with, extension, caveat, additionalCaveats)
118 return blessings, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700119}
120
121func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
Asim Shankarb07ec692015-02-27 23:40:44 -0800122 var blessings security.Blessings
123 err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
124 return blessings, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700125}
126
127func (c *client) Sign(message []byte) (sig security.Signature, err error) {
128 err = c.caller.call("Sign", results(&sig), message)
129 return
130}
131
Asim Shankar19da8182015-02-06 01:41:16 -0800132func (c *client) MintDischarge(forCaveat, caveatOnDischarge security.Caveat, additionalCaveatsOnDischarge ...security.Caveat) (security.Discharge, error) {
Asim Shankar08642822015-03-02 21:21:09 -0800133 var discharge security.Discharge
Asim Shankar19da8182015-02-06 01:41:16 -0800134 if err := c.caller.call("MintDischarge", results(&discharge), forCaveat, caveatOnDischarge, additionalCaveatsOnDischarge); err != nil {
Asim Shankar3ad0b8a2015-02-25 00:37:21 -0800135 return security.Discharge{}, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700136 }
Asim Shankar08642822015-03-02 21:21:09 -0800137 return discharge, nil
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700138}
139
Ryan Brownfed691e2014-09-15 13:09:40 -0700140func (c *client) PublicKey() security.PublicKey {
141 return c.key
142}
143
gauthamtf8263932014-12-16 10:59:09 -0800144func (c *client) BlessingsByName(pattern security.BlessingPattern) []security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800145 var blessings []security.Blessings
146 if err := c.caller.call("BlessingsByName", results(&blessings), pattern); err != nil {
gauthamtf8263932014-12-16 10:59:09 -0800147 vlog.Errorf("error calling BlessingsByName: %v", err)
148 return nil
149 }
gauthamtf8263932014-12-16 10:59:09 -0800150 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
Asim Shankarb07ec692015-02-27 23:40:44 -0800155 err := c.caller.call("BlessingsInfo", results(&bInfo), 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 {
Asim Shankarb07ec692015-02-27 23:40:44 -0800171 return c.caller.call("AddToRoots", results(), blessings)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700172}
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) {
Asim Shankarb07ec692015-02-27 23:40:44 -0800180 var previous security.Blessings
181 err := b.caller.call("BlessingStoreSet", results(&previous), blessings, forPeers)
182 return previous, err
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700183}
184
185func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800186 var blessings security.Blessings
187 if err := b.caller.call("BlessingStoreForPeer", results(&blessings), peerBlessings); err != nil {
188 vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700189 }
190 return blessings
191}
192
193func (b *blessingStore) SetDefault(blessings security.Blessings) error {
Asim Shankarb07ec692015-02-27 23:40:44 -0800194 return b.caller.call("BlessingStoreSetDefault", results(), blessings)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700195}
196
197func (b *blessingStore) Default() security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800198 var blessings security.Blessings
199 err := b.caller.call("BlessingStoreDefault", results(&blessings))
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700200 if err != nil {
201 vlog.Errorf("error calling BlessingStoreDefault: %v", err)
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800202 return security.Blessings{}
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700203 }
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700204 return blessings
205}
206
207func (b *blessingStore) PublicKey() security.PublicKey {
208 return b.key
209}
210
gauthamtf8263932014-12-16 10:59:09 -0800211func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
Asim Shankarb07ec692015-02-27 23:40:44 -0800212 var bmap map[security.BlessingPattern]security.Blessings
213 err := b.caller.call("BlessingStorePeerBlessings", results(&bmap))
gauthamtf8263932014-12-16 10:59:09 -0800214 if err != nil {
215 vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
216 return nil
217 }
Asim Shankarb07ec692015-02-27 23:40:44 -0800218 return bmap
gauthamtf8263932014-12-16 10:59:09 -0800219}
220
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700221func (b *blessingStore) DebugString() (s string) {
222 err := b.caller.call("BlessingStoreDebugString", results(&s))
223 if err != nil {
224 s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
225 vlog.Errorf(s)
226 }
227 return
228}
229
230type blessingRoots struct {
231 caller caller
232}
233
234func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
235 marshalledKey, err := root.MarshalBinary()
236 if err != nil {
237 return err
238 }
239 return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern)
240}
241
242func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
243 marshalledKey, err := root.MarshalBinary()
244 if err != nil {
245 return err
246 }
Asim Shankarb378e662015-01-16 10:50:48 -0800247 return b.caller.call("BlessingRootsRecognized", results(), marshalledKey, blessing)
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -0700248}
249
250func (b *blessingRoots) DebugString() (s string) {
251 err := b.caller.call("BlessingRootsDebugString", results(&s))
252 if err != nil {
253 s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
254 vlog.Errorf(s)
255 }
Ryan Brownfed691e2014-09-15 13:09:40 -0700256 return
257}