mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-03 09:19:10 +01:00
lnd: generate default macaroons independently
This modifies the `genMacaroons` logic to indepently check for each of the three default macaroons (admin, readonly, invoice) and generate whichever are missing. Previously, this was an all or nothing routine. In other words, either all three didn't exist on disk and all three are created, or no macaroons are created. Although that works for the first run of a new node, it can result in inconsistent states if only one or two of the macaroons is deleted. See https://github.com/lightningnetwork/lnd/discussions/7566.
This commit is contained in:
parent
fdc1ae9d57
commit
16463d4bd4
3 changed files with 57 additions and 37 deletions
|
@ -470,14 +470,10 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
|
|||
|
||||
// If the user requested a stateless initialization, no macaroon
|
||||
// files should be created.
|
||||
if !walletInitParams.StatelessInit &&
|
||||
!lnrpc.FileExists(d.cfg.AdminMacPath) &&
|
||||
!lnrpc.FileExists(d.cfg.ReadMacPath) &&
|
||||
!lnrpc.FileExists(d.cfg.InvoiceMacPath) {
|
||||
|
||||
// Create macaroon files for lncli to use if they don't
|
||||
// exist.
|
||||
err = genMacaroons(
|
||||
if !walletInitParams.StatelessInit {
|
||||
// Create default macaroon files for lncli to use if
|
||||
// they don't exist.
|
||||
err = genDefaultMacaroons(
|
||||
ctx, macaroonService, d.cfg.AdminMacPath,
|
||||
d.cfg.ReadMacPath, d.cfg.InvoiceMacPath,
|
||||
)
|
||||
|
|
|
@ -13,8 +13,14 @@
|
|||
the entire retribution struct. This reduces the amount of data that needs to
|
||||
be held in memory.
|
||||
|
||||
## Misc
|
||||
|
||||
* [Generate default macaroons
|
||||
independently](https://github.com/lightningnetwork/lnd/pull/7592) on wallet
|
||||
unlock or create.
|
||||
|
||||
# Contributors (Alphabetical Order)
|
||||
|
||||
* Daniel McNally
|
||||
* Elle Mouton
|
||||
* Jordi Montes
|
||||
|
||||
|
|
74
lnd.go
74
lnd.go
|
@ -690,46 +690,64 @@ func bakeMacaroon(ctx context.Context, svc *macaroons.Service,
|
|||
return mac.M().MarshalBinary()
|
||||
}
|
||||
|
||||
// genMacaroons generates three macaroon files; one admin-level, one for
|
||||
// invoice access and one read-only. These can also be used to generate more
|
||||
// granular macaroons.
|
||||
func genMacaroons(ctx context.Context, svc *macaroons.Service,
|
||||
// saveMacaroon bakes a macaroon with the specified macaroon permissions and
|
||||
// writes it to a file with the given filename and file permissions.
|
||||
func saveMacaroon(ctx context.Context, svc *macaroons.Service, filename string,
|
||||
macaroonPermissions []bakery.Op, filePermissions os.FileMode) error {
|
||||
|
||||
macaroonBytes, err := bakeMacaroon(ctx, svc, macaroonPermissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(filename, macaroonBytes, filePermissions)
|
||||
if err != nil {
|
||||
_ = os.Remove(filename)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// genDefaultMacaroons checks for three default macaroon files and generates
|
||||
// them if they do not exist; one admin-level, one for invoice access and one
|
||||
// read-only. Each macaroon is checked and created independently to ensure all
|
||||
// three exist. The admin macaroon can also be used to generate more granular
|
||||
// macaroons.
|
||||
func genDefaultMacaroons(ctx context.Context, svc *macaroons.Service,
|
||||
admFile, roFile, invoiceFile string) error {
|
||||
|
||||
// First, we'll generate a macaroon that only allows the caller to
|
||||
// access invoice related calls. This is useful for merchants and other
|
||||
// services to allow an isolated instance that can only query and
|
||||
// modify invoices.
|
||||
invoiceMacBytes, err := bakeMacaroon(ctx, svc, invoicePermissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(invoiceFile, invoiceMacBytes, 0644)
|
||||
if err != nil {
|
||||
_ = os.Remove(invoiceFile)
|
||||
return err
|
||||
if !lnrpc.FileExists(invoiceFile) {
|
||||
err := saveMacaroon(
|
||||
ctx, svc, invoiceFile, invoicePermissions, 0644,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the read-only macaroon and write it to a file.
|
||||
roBytes, err := bakeMacaroon(ctx, svc, readPermissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ioutil.WriteFile(roFile, roBytes, 0644); err != nil {
|
||||
_ = os.Remove(roFile)
|
||||
return err
|
||||
if !lnrpc.FileExists(roFile) {
|
||||
err := saveMacaroon(
|
||||
ctx, svc, roFile, readPermissions, 0644,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the admin macaroon and write it to a file.
|
||||
admBytes, err := bakeMacaroon(ctx, svc, adminPermissions())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(admFile, admBytes, adminMacaroonFilePermissions)
|
||||
if err != nil {
|
||||
_ = os.Remove(admFile)
|
||||
return err
|
||||
if !lnrpc.FileExists(admFile) {
|
||||
err := saveMacaroon(
|
||||
ctx, svc, admFile, adminPermissions(),
|
||||
adminMacaroonFilePermissions,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
Loading…
Add table
Reference in a new issue