Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi: create challenger, secret, and interceptor packages #91

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
32 changes: 19 additions & 13 deletions aperture.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ import (
gateway "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
flags "github.com/jessevdk/go-flags"
"github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/challenger"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit message comment:

  • NewLndChallenger isnt altered to take in an lndclient (which is the thing that would cause an import cycle), but rather is altered to take a challenger.InvoiceClient (which lnd client just happens to implement)
  • nitty nit: check out LND contribution guidelines for ideal commit title & message structure 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also - for easier review, I think perhaps do 1 commit where you do the refactoring and then a separate commit for the NewLndChallenger change

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the NewLndChallenger changes into a new commit. The change was a bit awkward because NewLndChallenger initially needs AuthConfig, which is defined in the main package. But then in the next commit we remove AuthConfig entirely because it's not needed once we update NewLndChallenger to take in the client as a parameter. This was the cleanest way I could think to make the change - maybe it's still worth it for review readability. Lmk your thoughts!

"github.com/lightninglabs/aperture/mint"
"github.com/lightninglabs/aperture/proxy"
"github.com/lightninglabs/aperture/secrets"
"github.com/lightninglabs/lightning-node-connect/hashmailrpc"
"github.com/lightninglabs/lndclient"
"github.com/lightningnetwork/lnd"
"github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/cert"
Expand All @@ -42,14 +45,6 @@ import (
)

const (
// topLevelKey is the top level key for an etcd cluster where we'll
// store all LSAT proxy related data.
topLevelKey = "lsat/proxy"

// etcdKeyDelimeter is the delimeter we'll use for all etcd keys to
// represent a path-like structure.
etcdKeyDelimeter = "/"

// selfSignedCertOrganization is the static string that we encode in the
// organization field of a certificate if we create it ourselves.
selfSignedCertOrganization = "aperture autogenerated cert"
Expand Down Expand Up @@ -160,7 +155,7 @@ type Aperture struct {
cfg *Config

etcdClient *clientv3.Client
challenger *LndChallenger
challenger *challenger.LndChallenger
httpsServer *http.Server
torHTTPServer *http.Server
proxy *proxy.Proxy
Expand Down Expand Up @@ -229,8 +224,19 @@ func (a *Aperture) Start(errChan chan error) error {
}

if !a.cfg.Authenticator.Disable {
a.challenger, err = NewLndChallenger(
a.cfg.Authenticator, genInvoiceReq, errChan,
client, err := lndclient.NewBasicClient(
a.cfg.Authenticator.LndHost,
a.cfg.Authenticator.TLSPath,
a.cfg.Authenticator.MacDir,
a.cfg.Authenticator.Network,
lndclient.MacFilename(challenger.InvoiceMacaroonName),
)
if err != nil {
return err
}

a.challenger, err = challenger.NewLndChallenger(
genInvoiceReq, client, errChan,
)
if err != nil {
return err
Expand Down Expand Up @@ -655,12 +661,12 @@ func initTorListener(cfg *Config, etcd *clientv3.Client) (*tor.Controller, error
}

// createProxy creates the proxy with all the services it needs.
func createProxy(cfg *Config, challenger *LndChallenger,
func createProxy(cfg *Config, challenger *challenger.LndChallenger,
etcdClient *clientv3.Client) (*proxy.Proxy, func(), error) {

minter := mint.New(&mint.Config{
Challenger: challenger,
Secrets: newSecretStore(etcdClient),
Secrets: secrets.NewStore(etcdClient),
ServiceLimiter: newStaticServiceLimiter(cfg.Services),
Now: time.Now,
})
Expand Down
30 changes: 4 additions & 26 deletions auth/authenticator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,15 @@ import (

"github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/lsat"
"gopkg.in/macaroon.v2"
)

// createDummyMacHex creates a valid macaroon with dummy content for our tests.
func createDummyMacHex(preimage string) string {
dummyMac, err := macaroon.New(
[]byte("aabbccddeeff00112233445566778899"), []byte("AA=="),
"aperture", macaroon.LatestVersion,
)
if err != nil {
panic(err)
}
preimageCaveat := lsat.Caveat{Condition: lsat.PreimageKey, Value: preimage}
err = lsat.AddFirstPartyCaveats(dummyMac, preimageCaveat)
if err != nil {
panic(err)
}
macBytes, err := dummyMac.MarshalBinary()
if err != nil {
panic(err)
}
return hex.EncodeToString(macBytes)
}

// TestLsatAuthenticator tests that the authenticator properly handles auth
// headers and the tokens contained in them.
func TestLsatAuthenticator(t *testing.T) {
var (
testPreimage = "49349dfea4abed3cd14f6d356afa83de" +
"9787b609f088c8df09bacc7b4bd21b39"
testMacHex = createDummyMacHex(testPreimage)
testMacHex = auth.CreateDummyMacHex(testPreimage)
testMacBytes, _ = hex.DecodeString(testMacHex)
testMacBase64 = base64.StdEncoding.EncodeToString(
testMacBytes,
Expand Down Expand Up @@ -139,10 +117,10 @@ func TestLsatAuthenticator(t *testing.T) {
}
)

c := &mockChecker{}
a := auth.NewLsatAuthenticator(&mockMint{}, c)
c := &auth.MockChecker{}
a := auth.NewLsatAuthenticator(&auth.MockMint{}, c)
for _, testCase := range headerTests {
c.err = testCase.checkErr
c.Err = testCase.checkErr
result := a.Accept(testCase.header, "test")
if result != testCase.result {
t.Fatalf("test case %s failed. got %v expected %v",
Expand Down
40 changes: 0 additions & 40 deletions auth/mock_test.go

This file was deleted.

64 changes: 64 additions & 0 deletions auth/test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package auth

import (
"context"
"encoding/hex"
"time"

"github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/aperture/mint"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"gopkg.in/macaroon.v2"
)

// CreateDummyMacHex creates a valid macaroon with dummy content for our tests.
func CreateDummyMacHex(preimage string) string {
dummyMac, err := macaroon.New(
[]byte("aabbccddeeff00112233445566778899"), []byte("AA=="),
"aperture", macaroon.LatestVersion,
)
if err != nil {
panic(err)
}
preimageCaveat := lsat.Caveat{
Condition: lsat.PreimageKey,
Value: preimage,
}
err = lsat.AddFirstPartyCaveats(dummyMac, preimageCaveat)
if err != nil {
panic(err)
}
macBytes, err := dummyMac.MarshalBinary()
if err != nil {
panic(err)
}
return hex.EncodeToString(macBytes)
}

type MockMint struct {
}

var _ Minter = (*MockMint)(nil)

func (m *MockMint) MintLSAT(_ context.Context,
services ...lsat.Service) (*macaroon.Macaroon, string, error) {

return nil, "", nil
}

func (m *MockMint) VerifyLSAT(_ context.Context, p *mint.VerificationParams) error {
return nil
}

type MockChecker struct {
Err error
}

var _ InvoiceChecker = (*MockChecker)(nil)

func (m *MockChecker) VerifyInvoiceStatus(lntypes.Hash,
lnrpc.Invoice_InvoiceState, time.Duration) error {

return m.Err
}
19 changes: 5 additions & 14 deletions challenger.go → challenger/challenger.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package aperture
package challenger

import (
"context"
Expand All @@ -11,7 +11,6 @@ import (

"github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/mint"
"github.com/lightninglabs/lndclient"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"google.golang.org/grpc"
Expand Down Expand Up @@ -61,28 +60,20 @@ var _ mint.Challenger = (*LndChallenger)(nil)
var _ auth.InvoiceChecker = (*LndChallenger)(nil)

const (
// invoiceMacaroonName is the name of the invoice macaroon belonging
// InvoiceMacaroonName is the name of the invoice macaroon belonging
// to the target lnd node.
invoiceMacaroonName = "invoice.macaroon"
InvoiceMacaroonName = "invoice.macaroon"
)

// NewLndChallenger creates a new challenger that uses the given connection
// details to connect to an lnd backend to create payment challenges.
func NewLndChallenger(cfg *AuthConfig, genInvoiceReq InvoiceRequestGenerator,
errChan chan<- error) (*LndChallenger, error) {
func NewLndChallenger(genInvoiceReq InvoiceRequestGenerator,
client InvoiceClient, errChan chan<- error) (*LndChallenger, error) {

if genInvoiceReq == nil {
return nil, fmt.Errorf("genInvoiceReq cannot be nil")
}

client, err := lndclient.NewBasicClient(
cfg.LndHost, cfg.TLSPath, cfg.MacDir, cfg.Network,
lndclient.MacFilename(invoiceMacaroonName),
)
if err != nil {
return nil, err
}

invoicesMtx := &sync.Mutex{}
return &LndChallenger{
client: client,
Expand Down
92 changes: 3 additions & 89 deletions challenger_test.go → challenger/challenger_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package aperture
package challenger

import (
"context"
"fmt"
"sync"
"testing"
Expand All @@ -10,86 +9,14 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
)

var (
defaultTimeout = 100 * time.Millisecond
)

type invoiceStreamMock struct {
lnrpc.Lightning_SubscribeInvoicesClient

updateChan chan *lnrpc.Invoice
errChan chan error
quit chan struct{}
}

func (i *invoiceStreamMock) Recv() (*lnrpc.Invoice, error) {
select {
case msg := <-i.updateChan:
return msg, nil

case err := <-i.errChan:
return nil, err

case <-i.quit:
return nil, context.Canceled
}
}

type mockInvoiceClient struct {
invoices []*lnrpc.Invoice
updateChan chan *lnrpc.Invoice
errChan chan error
quit chan struct{}

lastAddIndex uint64
}

// ListInvoices returns a paginated list of all invoices known to lnd.
func (m *mockInvoiceClient) ListInvoices(_ context.Context,
_ *lnrpc.ListInvoiceRequest,
_ ...grpc.CallOption) (*lnrpc.ListInvoiceResponse, error) {

return &lnrpc.ListInvoiceResponse{
Invoices: m.invoices,
}, nil
}

// SubscribeInvoices subscribes to updates on invoices.
func (m *mockInvoiceClient) SubscribeInvoices(_ context.Context,
in *lnrpc.InvoiceSubscription, _ ...grpc.CallOption) (
lnrpc.Lightning_SubscribeInvoicesClient, error) {

m.lastAddIndex = in.AddIndex

return &invoiceStreamMock{
updateChan: m.updateChan,
errChan: m.errChan,
quit: m.quit,
}, nil
}

// AddInvoice adds a new invoice to lnd.
func (m *mockInvoiceClient) AddInvoice(_ context.Context, in *lnrpc.Invoice,
_ ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error) {

m.invoices = append(m.invoices, in)

return &lnrpc.AddInvoiceResponse{
RHash: in.RHash,
PaymentRequest: in.PaymentRequest,
AddIndex: uint64(len(m.invoices) - 1),
}, nil
}

func (m *mockInvoiceClient) stop() {
close(m.quit)
}

func newChallenger() (*LndChallenger, *mockInvoiceClient, chan error) {
mockClient := &mockInvoiceClient{
func newChallenger() (*LndChallenger, *MockInvoiceClient, chan error) {
mockClient := &MockInvoiceClient{
updateChan: make(chan *lnrpc.Invoice),
errChan: make(chan error, 1),
quit: make(chan struct{}),
Expand All @@ -111,19 +38,6 @@ func newChallenger() (*LndChallenger, *mockInvoiceClient, chan error) {
}, mockClient, mainErrChan
}

func newInvoice(hash lntypes.Hash, addIndex uint64,
state lnrpc.Invoice_InvoiceState) *lnrpc.Invoice {

return &lnrpc.Invoice{
PaymentRequest: "foo",
RHash: hash[:],
AddIndex: addIndex,
State: state,
CreationDate: time.Now().Unix(),
Expiry: 10,
}
}

func TestLndChallenger(t *testing.T) {
t.Parallel()

Expand Down
Loading