lncli: add custom caveats to bakemacaroon

With the new condition and checker in place, we can give the end user
the ability to add such a custom caveat to a baked macaroon.
There won't be an RPC counterpart for this operation since all first party
caveats currently are only added on the client side.
This commit is contained in:
Oliver Gugger 2021-08-12 16:07:19 +02:00
parent 045765111a
commit 7b822f41df
No known key found for this signature in database
GPG key ID: 8E4256593F177720

View file

@ -8,6 +8,7 @@ import (
"net"
"strconv"
"strings"
"unicode"
"github.com/golang/protobuf/proto"
"github.com/lightningnetwork/lnd/lncfg"
@ -65,6 +66,16 @@ var bakeMacaroonCommand = cli.Command{
Name: "ip_address",
Usage: "the IP address the macaroon will be bound to",
},
cli.StringFlag{
Name: "custom_caveat_name",
Usage: "the name of the custom caveat to add",
},
cli.StringFlag{
Name: "custom_caveat_condition",
Usage: "the condition of the custom caveat to add, " +
"can be empty if custom caveat doesn't need " +
"a value",
},
cli.Uint64Flag{
Name: "root_key_id",
Usage: "the numerical root key ID used to create the macaroon",
@ -92,6 +103,8 @@ func bakeMacaroon(ctx *cli.Context) error {
savePath string
timeout int64
ipAddress net.IP
customCaveatName string
customCaveatCond string
rootKeyID uint64
parsedPermissions []*lnrpc.MacaroonPermission
err error
@ -116,6 +129,32 @@ func bakeMacaroon(ctx *cli.Context) error {
}
}
if ctx.IsSet("custom_caveat_name") {
customCaveatName = ctx.String("custom_caveat_name")
if containsWhiteSpace(customCaveatName) {
return fmt.Errorf("unexpected white space found in " +
"custom caveat name")
}
if customCaveatName == "" {
return fmt.Errorf("invalid custom caveat name")
}
}
if ctx.IsSet("custom_caveat_condition") {
customCaveatCond = ctx.String("custom_caveat_condition")
if containsWhiteSpace(customCaveatCond) {
return fmt.Errorf("unexpected white space found in " +
"custom caveat condition")
}
if customCaveatCond == "" {
return fmt.Errorf("invalid custom caveat condition")
}
if customCaveatCond != "" && customCaveatName == "" {
return fmt.Errorf("cannot set custom caveat " +
"condition without custom caveat name")
}
}
if ctx.IsSet("root_key_id") {
rootKeyID = ctx.Uint64("root_key_id")
}
@ -186,6 +225,17 @@ func bakeMacaroon(ctx *cli.Context) error {
macaroons.IPLockConstraint(ipAddress.String()),
)
}
// The custom caveat condition is optional, it could just be a marker
// tag in the macaroon with just a name. The interceptor itself doesn't
// care about the value anyway.
if customCaveatName != "" {
macConstraints = append(
macConstraints, macaroons.CustomConstraint(
customCaveatName, customCaveatCond,
),
)
}
constrainedMac, err := macaroons.AddConstraints(
unmarshalMac, macConstraints...,
)
@ -419,3 +469,10 @@ func printMacaroon(ctx *cli.Context) error {
return nil
}
// containsWhiteSpace returns true if the given string contains any character
// that is considered to be a white space or non-printable character such as
// space, tabulator, newline, carriage return and some more exotic ones.
func containsWhiteSpace(str string) bool {
return strings.IndexFunc(str, unicode.IsSpace) >= 0
}