BakeMacaroon
BakeMacaroon allows the creation of a new macaroon with custom read and write permissions. No first-party caveats are added since this can be done offline.
Source: lightning.proto
gRPC
rpc BakeMacaroon (BakeMacaroonRequest) returns (BakeMacaroonResponse);
REST
HTTP Method | Path |
---|---|
POST | /v1/macaroon |
Code Samples
- gRPC
- REST
- Shell
- Javascript
- Python
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const GRPC_HOST = 'localhost:10009'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
const TLS_PATH = 'LND_DIR/tls.cert'
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('lightning.proto', loaderOptions);
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
const tlsCert = fs.readFileSync(TLS_PATH);
const sslCreds = grpc.credentials.createSsl(tlsCert);
const macaroon = fs.readFileSync(MACAROON_PATH).toString('hex');
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
let client = new lnrpc.Lightning(GRPC_HOST, creds);
let request = {
permissions: <MacaroonPermission>,
root_key_id: <uint64>,
allow_external_permissions: <bool>,
};
client.bakeMacaroon(request, function(err, response) {
console.log(response);
});
// Console output:
// {
// "macaroon": <string>,
// }
import codecs, grpc, os
# Generate the following 2 modules by compiling the lightning.proto with the grpcio-tools.
# See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
import lightning_pb2 as lnrpc, lightning_pb2_grpc as lightningstub
GRPC_HOST = 'localhost:10009'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
# create macaroon credentials
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
def metadata_callback(context, callback):
callback([('macaroon', macaroon)], None)
auth_creds = grpc.metadata_call_credentials(metadata_callback)
# create SSL credentials
os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA'
cert = open(TLS_PATH, 'rb').read()
ssl_creds = grpc.ssl_channel_credentials(cert)
# combine macaroon and SSL credentials
combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
# make the request
channel = grpc.secure_channel(GRPC_HOST, combined_creds)
stub = lightningstub.LightningStub(channel)
request = lnrpc.BakeMacaroonRequest(
permissions=<MacaroonPermission>,
root_key_id=<uint64>,
allow_external_permissions=<bool>,
)
response = stub.BakeMacaroon(request)
print(response)
# {
# "macaroon": <string>,
# }
- Javascript
- Python
const fs = require('fs');
const request = require('request');
const REST_HOST = 'localhost:8080'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
let requestBody = {
permissions: <array>, // <MacaroonPermission>
root_key_id: <string>, // <uint64>
allow_external_permissions: <boolean>, // <bool>
};
let options = {
url: `https://${REST_HOST}/v1/macaroon`,
// Work-around for self-signed certificates.
rejectUnauthorized: false,
json: true,
headers: {
'Grpc-Metadata-macaroon': fs.readFileSync(MACAROON_PATH).toString('hex'),
},
form: JSON.stringify(requestBody),
}
request.post(options, function(error, response, body) {
console.log(body);
});
// Console output:
// {
// "macaroon": <string>, // <string>
// }
import base64, codecs, json, requests
REST_HOST = 'localhost:8080'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
url = f'https://{REST_HOST}/v1/macaroon'
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
headers = {'Grpc-Metadata-macaroon': macaroon}
data = {
'permissions': <MacaroonPermission>,
'root_key_id': <uint64>,
'allow_external_permissions': <bool>,
}
r = requests.post(url, headers=headers, data=json.dumps(data), verify=TLS_PATH)
print(r.json())
# {
# "macaroon": <string>,
# }
$ lncli bakemacaroon --help
NAME:
lncli bakemacaroon - Bakes a new macaroon with the provided list of permissions and restrictions.
USAGE:
lncli bakemacaroon [command options] [--save_to=] [--timeout=] [--ip_address=] [--custom_caveat_name= [--custom_caveat_condition=]] [--root_key_id=] [--allow_external_permissions] [--root_key=] permissions...
CATEGORY:
Macaroons
DESCRIPTION:
Bake a new macaroon that grants the provided permissions and
optionally adds restrictions (timeout, IP address) to it.
The new macaroon can either be shown on command line in hex serialized
format or it can be saved directly to a file using the --save_to
argument.
A permission is a tuple of an entity and an action, separated by a
colon. Multiple operations can be added as arguments, for example:
lncli bakemacaroon info:read invoices:write foo:bar
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 specifying "uri:<methodURI>" pairs,
for example:
lncli bakemacaroon uri:/lnrpc.Lightning/GetInfo uri:/verrpc.Versioner/GetVersion
The macaroon created by this command would only be allowed to use the
"lncli getinfo" and "lncli version" commands.
To get a list of all available URIs and permissions, use the
"lncli listpermissions" command.
If the root key is known (for example because "lncli create" was used
with a custom --mac_root_key value), it can be passed directly as a
hex encoded string using the --root_key flag. This turns the command
into an offline operation and the macaroon will be created without
calling into the server's RPC endpoint.
OPTIONS:
--save_to value save the created macaroon to this file using the default binary format
--timeout value the number of seconds the macaroon will be valid before it times out (default: 0)
--ip_address value the IP address the macaroon will be bound to
--custom_caveat_name value the name of the custom caveat to add
--custom_caveat_condition value the condition of the custom caveat to add, can be empty if custom caveat doesn't need a value
--root_key_id value the numerical root key ID used to create the macaroon (default: 0)
--allow_external_permissions whether permissions lnd is not familiar with are allowed
--root_key value if the root key is known, it can be passed directly as a hex encoded string, turning the command into an offline operation
Messages
lnrpc.BakeMacaroonRequest
Source: lightning.proto
Field | gRPC Type | REST Type | REST Placement |
---|---|---|---|
permissions | MacaroonPermission[] | array | body |
root_key_id | uint64 | string | body |
allow_external_permissions | bool | boolean | body |
lnrpc.BakeMacaroonResponse
Source: lightning.proto
Field | gRPC Type | REST Type |
---|---|---|
macaroon | string | string |
Nested Messages
lnrpc.MacaroonPermission
Field | gRPC Type | REST Type |
---|---|---|
entity | string | string |
action | string | string |