-
Notifications
You must be signed in to change notification settings - Fork 43
/
macaroon_pouch.go
121 lines (103 loc) · 3.52 KB
/
macaroon_pouch.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
package lndclient
import (
"context"
"encoding/hex"
"io/ioutil"
"path/filepath"
"google.golang.org/grpc/metadata"
)
var (
// defaultMacaroonFileNames is the default list of macaroon file names
// that lndclient will attempt to load if a macaroon directory is given
// instead of a single custom macaroon.
defaultMacaroonFileNames = []string{
invoiceMacFilename,
chainMacFilename,
signerMacFilename,
walletKitMacFilename,
routerMacFilename,
adminMacFilename,
readonlyMacFilename,
}
)
// loadMacaroon tries to load a macaroon file either from the default macaroon
// dir and the default filename or, if specified, from the custom macaroon path
// that overwrites the former two parameters.
func loadMacaroon(defaultMacDir, defaultMacFileName,
customMacPath string) (serializedMacaroon, error) {
// If a custom macaroon path is set, we ignore the macaroon dir and
// default filename and always just load the custom macaroon, assuming
// it contains all permissions needed to use the subservers.
if customMacPath != "" {
return newSerializedMacaroon(customMacPath)
}
return newSerializedMacaroon(filepath.Join(
defaultMacDir, defaultMacFileName,
))
}
// serializedMacaroon is a type that represents a hex-encoded macaroon. We'll
// use this primarily vs the raw binary format as the gRPC metadata feature
// requires that all keys and values be strings.
type serializedMacaroon string
// newSerializedMacaroon reads a new serializedMacaroon from that target
// macaroon path. If the file can't be found, then an error is returned.
func newSerializedMacaroon(macaroonPath string) (serializedMacaroon, error) {
macBytes, err := ioutil.ReadFile(macaroonPath)
if err != nil {
return "", err
}
return serializedMacaroon(hex.EncodeToString(macBytes)), nil
}
// WithMacaroonAuth modifies the passed context to include the macaroon KV
// metadata of the target macaroon. This method can be used to add the macaroon
// at call time, rather than when the connection to the gRPC server is created.
func (s serializedMacaroon) WithMacaroonAuth(ctx context.Context) context.Context {
return metadata.AppendToOutgoingContext(ctx, "macaroon", string(s))
}
// macaroonPouch holds the set of macaroons we need to interact with lnd for
// Loop. Each sub-server has its own macaroon, and for the remaining temporary
// calls that directly hit lnd, we'll use the admin macaroon.
type macaroonPouch map[string]serializedMacaroon
// newMacaroonPouch returns a new instance of a fully populated macaroonPouch
// given the directory where all the macaroons are stored.
func newMacaroonPouch(macaroonDir, customMacPath, customMacHex string) (macaroonPouch,
error) {
// If a custom macaroon is specified, we assume it contains all
// permissions needed for the different subservers to function and we
// use it for all of them.
var (
mac serializedMacaroon
err error
)
if customMacPath != "" {
mac, err = loadMacaroon("", "", customMacPath)
if err != nil {
return nil, err
}
} else if customMacHex != "" {
mac = serializedMacaroon(customMacHex)
}
if mac != "" {
return macaroonPouch{
invoiceMacFilename: mac,
chainMacFilename: mac,
signerMacFilename: mac,
walletKitMacFilename: mac,
routerMacFilename: mac,
adminMacFilename: mac,
readonlyMacFilename: mac,
}, nil
}
var (
m = make(macaroonPouch)
)
for _, macFileName := range defaultMacaroonFileNames {
m[macFileName], err = loadMacaroon(
macaroonDir, macFileName, customMacPath,
)
if err != nil {
return nil, err
}
}
return m, nil
}