lnd/macaroons
Yong 582b164c46
kvdb: add timeout options for bbolt (#4787)
* mod: bump btcwallet version to accept db timeout

* btcwallet: add DBTimeOut in config

* kvdb: add database timeout option for bbolt

This commit adds a DBTimeout option in bbolt config. The relevant
functions walletdb.Open/Create are updated to use this config. In
addition, the bolt compacter also applies the new timeout option.

* channeldb: add DBTimeout in db options

This commit adds the DBTimeout option for channeldb. A new unit
test file is created to test the default options. In addition,
the params used in kvdb.Create inside channeldb_test is updated
with a DefaultDBTimeout value.

* contractcourt+routing: use DBTimeout in kvdb

This commit touches multiple test files in contractcourt and routing.
The call of function kvdb.Create and kvdb.Open are now updated with
the new param DBTimeout, using the default value kvdb.DefaultDBTimeout.

* lncfg: add DBTimeout option in db config

The DBTimeout option is added to db config. A new unit test is
added to check the default DB config is created as expected.

* migration: add DBTimeout param in kvdb.Create/kvdb.Open

* keychain: update tests to use DBTimeout param

* htlcswitch+chainreg: add DBTimeout option

* macaroons: support DBTimeout config in creation

This commit adds the DBTimeout during the creation of macaroons.db.
The usage of kvdb.Create and kvdb.Open in its tests are updated with
a timeout value using kvdb.DefaultDBTimeout.

* walletunlocker: add dbTimeout option in UnlockerService

This commit adds a new param, dbTimeout, during the creation of
UnlockerService. This param is then passed to wallet.NewLoader
inside various service calls, specifying a timeout value to be
used when opening the bbolt. In addition, the macaroonService
is also called with this dbTimeout param.

* watchtower/wtdb: add dbTimeout param during creation

This commit adds the dbTimeout param for the creation of both
watchtower.db and wtclient.db.

* multi: add db timeout param for walletdb.Create

This commit adds the db timeout param for the function call
walletdb.Create. It touches only the test files found in chainntnfs,
lnwallet, and routing.

* lnd: pass DBTimeout config to relevant services

This commit enables lnd to pass the DBTimeout config to the following
services/config/functions,
  - chainControlConfig
  - walletunlocker
  - wallet.NewLoader
  - macaroons
  - watchtower
In addition, the usage of wallet.Create is updated too.

* sample-config: add dbtimeout option
2020-12-07 15:31:49 -08:00
..
auth.go macaroons: stdlib context 2019-09-28 16:10:57 -07:00
constraints_test.go macaroons test: fix formatting 2020-09-24 11:59:08 +02:00
constraints.go macaroons: stdlib context 2019-09-28 16:10:57 -07:00
context.go macaroons: specify root key ID in bakery 2020-08-11 19:17:48 +08:00
README.md macaroons: add special permission entity for URI specific permissions 2020-09-04 09:22:35 +02:00
security_rpctest.go macaroons: use fast scrypt options in itest and unit tests 2020-03-24 09:52:39 +01:00
security_test.go macaroons: use fast scrypt options in itest and unit tests 2020-03-24 09:52:39 +01:00
security.go macaroons: use fast scrypt options in itest and unit tests 2020-03-24 09:52:39 +01:00
service_test.go kvdb: add timeout options for bbolt (#4787) 2020-12-07 15:31:49 -08:00
service.go kvdb: add timeout options for bbolt (#4787) 2020-12-07 15:31:49 -08:00
store_test.go kvdb: add timeout options for bbolt (#4787) 2020-12-07 15:31:49 -08:00
store.go macaroons: add ability to change the password or create a new root key 2020-11-07 11:24:33 +01:00

macaroons

This is a more detailed, technical description of how macaroons work and how authentication and authorization is implemented in lnd.

For a more high-level overview see macaroons.md in the docs.

Root key

At startup, if the option --no-macaroons is not used, a Bolt DB key/value store named data/macaroons.db is created with a bucket named macrootkeys. In this DB the following two key/value pairs are stored:

  • Key 0: the encrypted root key (32 bytes).
    • If the root key does not exist yet, 32 bytes of pseudo-random data is generated and used.
  • Key enckey: the parameters used to derive a secret encryption key from a passphrase.
    • The following parameters are stored: <salt><digest><N><R><P>
      • salt: 32 byte of random data used as salt for the scrypt key derivation.
      • digest: sha256 hashed key derived from the scrypt operation. Is used to verify if the password is correct.
      • N, P, R: Parameters used for the scrypt operation.
    • The root key is symmetrically encrypted with the derived secret key, using the secretbox method of the library btcsuite/golangcrypto.
    • If the option --noseedbackup is used, then the default passphrase hello is used to encrypt the root key.

Generated macaroons

With the root key set up, lnd continues with creating three macaroon files:

  • invoice.macaroon: Grants read and write access to all invoice related gRPC commands (like generating an address or adding an invoice). Can be used for a web shop application for example. Paying an invoice is not possible, even if the name might suggest it. The permission offchain is needed to pay an invoice which is currently only granted in the admin macaroon.
  • readonly.macaroon: Grants read-only access to all gRPC commands. Could be given to a monitoring application for example.
  • 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.

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

	// invoicePermissions is a slice of all the entities that allows a user
	// to only access calls that are related to invoices, so: streaming
	// RPCs, generating, and listening invoices.
	invoicePermissions = []bakery.Op{
		{
			Entity: "invoices",
			Action: "read",
		},
		{
			Entity: "invoices",
			Action: "write",
		},
		{
			Entity: "address",
			Action: "read",
		},
		{
			Entity: "address",
			Action: "write",
		},
	}

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:

  • 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.

Bakery

As of lnd v0.9.0-beta there is a macaroon bakery available through gRPC and command line. Users can create their own macaroons with custom permissions if the provided default macaroons (admin, invoice and readonly) are not sufficient.

For example, a macaroon that is only allowed to manage peers with a default root key 0 would be created with the following command:

lncli bakemacaroon peers:read peers:write

For even more fine-grained permission control, it is also possible to specify single RPC method URIs that are allowed to be accessed by a macaroon. This can be achieved by passing uri:<methodURI> pairs to bakemacaroon, for example:

lncli bakemacaroon uri:/lnrpc.Lightning/GetInfo uri:/verrpc.Versioner/GetVersion

The macaroon created by this call would only be allowed to call the GetInfo and GetVersion methods instead of all methods that have similar permissions (like info:read for example).

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. Users can view a list of all macaroon root key IDs that are in use using:

lncli listmacaroonids

And remove a specific macaroon root key ID using command:

lncli deletemacaroonid root_key_id

Be careful with the deletemacaroonid command as when a root key is deleted, all the macaroons created from it are invalidated.