Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 83 additions & 27 deletions macaroons/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,35 @@ With the root key set up, `lnd` continues with creating three macaroon files:
* `admin.macaroon`: Grants full read and write access to all gRPC commands.
This is used by the `lncli` client.

These three macaroons all have the location field set to `lnd` and have no
conditions/first party caveats or third party caveats set.
In addition to those three, five sub servers bake a macaroon of their own on
first startup when they are compiled in, scoped to the permissions that sub
server needs. The other sub servers write no file of their own:

* `router.macaroon` (`routerrpc`, always compiled in): `offchain:read`,
`offchain:write`.
* `signer.macaroon` (`signrpc` build tag): `signer:generate`, `signer:read`.
* `walletkit.macaroon` (`walletrpc` build tag): `address:read`,
`address:write`, `onchain:read`, `onchain:write`.
* `chainnotifier.macaroon` (`chainrpc` build tag): `onchain:read`.
* `invoices.macaroon` (`invoicesrpc` build tag): `invoices:read`,
`invoices:write`.

The release builds enable all of those build tags, so an official `lnd` binary
creates all of these files. Four of them can be pointed elsewhere with a
command line option (`--routermacaroonpath`, `--signermacaroonpath`,
`--walletkitmacaroonpath` and `--notifiermacaroonpath`). `invoices.macaroon`
has no such option and is always read from the network directory.

None of these files are written to disk if `--stateless_init` is used. Only the
admin macaroon is returned, in the response of the `InitWallet` call (or of
`ChangePassword` when the root key is rotated). Any other macaroon has to be
baked with `bakemacaroon`.

All macaroons that `lnd` bakes on startup have the location field set to `lnd`
and have no conditions/first party caveats or third party caveats set.

The access restrictions are implemented with a list of entity/action pairs that
is mapped to the gRPC functions by the `rpcserver.go`.
is mapped to the gRPC functions by the `rpcserver.go`.
For example, the permissions for the `invoice.macaroon` looks like this:

```go
Expand All @@ -71,22 +95,67 @@ For example, the permissions for the `invoice.macaroon` looks like this:
Entity: "address",
Action: "write",
},
{
Entity: "onchain",
Action: "read",
},
}
```

## Constraints / First party caveats

There are currently two constraints implemented that can be used by `lncli` to
restrict the macaroon it uses to communicate with the gRPC interface. These can
be found in `constraints.go`:
A constraint is a first party caveat that further restricts an existing
macaroon. Appending a caveat only requires the macaroon itself and not the root
key, so constraints can be added offline by anyone holding the macaroon, and
they can only ever narrow what a macaroon allows, never widen it.

The following constraints are implemented in `constraints.go`, except for
`ProtectorConstraint` which lives in `protector.go`:

* `TimeoutConstraint`: Sets a timeout in seconds after which the macaroon is no
longer valid. Encoded as the standard `time-before` caveat.
* `IPLockConstraint`: Locks the macaroon to a single IP address, encoded as an
`ipaddr` caveat.
* `IPRangeLockConstraint`: Locks the macaroon to an IP range in CIDR notation,
encoded as an `iprange` caveat.
* `CustomConstraint`: Adds an `lnd-custom <name> <condition>` caveat. `lnd`
does not interpret the condition itself. A component such as a registered
RPC middleware has to declare that it handles that caveat name, otherwise
the macaroon is rejected as a whole.
* `ProtectorConstraint`: Adds a `protector <profile-name>` caveat, which
restricts which request fields may be set on the RPC methods covered by the
named profile. Only the profile name travels in the macaroon; the rules
themselves are compiled into `lnd`, so a profile's restrictions can be
tightened by a later release without re-baking any macaroon. A macaroon
naming a profile the validating node does not know is rejected as a whole.
See [macaroons.md](../docs/macaroons.md) for the available profiles.

The `time-before` caveat is validated by the macaroon bakery's own standard
checker. The checker functions for the lnd specific conditions (`ipaddr`,
`iprange`, `lnd-custom` and `protector`) are registered on the macaroon
service in `config_builder.go`.

Constraints can be added while baking a macaroon, or appended to an existing
macaroon file:

```shell
$ lncli bakemacaroon --timeout 3600 --ip_address 10.0.0.5 info:read
$ lncli bakemacaroon --protector channel-management-v1 \
uri:/lnrpc.Lightning/OpenChannel
$ lncli constrainmacaroon --timeout 3600 admin.macaroon limited.macaroon
```

* `TimeoutConstraint`: Set a timeout in seconds after which the macaroon is no
longer valid.
This constraint can be set by adding the parameter `--macaroontimeout xy` to
the `lncli` command.
* `IPLockConstraint`: Locks the macaroon to a specific IP address.
This constraint can be set by adding the parameter `--macaroonip a.b.c.d` to
the `lncli` command.
Two of them can also be applied by `lncli` on the fly, without changing the
macaroon file at all:

* `--macaroontimeout xy` sets the timeout. Note that this one is applied to
**every** call with a default of 60 seconds, as a basic anti-replay measure:
every macaroon that `lncli` sends already carries a short lived `time-before`
caveat.
* `--macaroonip a.b.c.d` locks the macaroon to an IP address.

`IPRangeLockConstraint` is currently only reachable from Go code, neither
`bakemacaroon` nor `constrainmacaroon` registers a command line flag for it.

## Bakery

Expand Down Expand Up @@ -134,23 +203,10 @@ $ lncli bakemacaroon --save_to lnbits.macaroon \
A full list of available entity/action pairs and RPC method URIs can be queried
by using the `lncli listpermissions` command.

### Upgrading from v0.8.0-beta or earlier

Users upgrading from a version prior to `v0.9.0-beta` might get a `permission
denied ` error when trying to use the `lncli bakemacaroon` command.
This is because the bakery requires a new permission (`macaroon/generate`) to
access.
Users can obtain a new `admin.macaroon` that contains this permission by
removing all three default macaroons (`admin.macaroon`, `invoice.macaroon` and
`readonly.macaroon`, **NOT** the `macaroons.db`!) from their
`data/chain/<chain>/<network>/` directory inside the lnd data directory and
restarting lnd.


## Root key rotation

To manage the root keys used by macaroons, there are `listmacaroonids` and
`deletemacaroonid` available through gPRC and command line.
`deletemacaroonid` available through gRPC and command line.
Users can view a list of all macaroon root key IDs that are in use using:

```shell
Expand Down
Loading