mirror of
https://github.com/lightninglabs/aperture.git
synced 2025-12-17 09:04:19 +01:00
multi: replace LSAT with L402
auth: LsatAuthenticator -> L402Authenticator sed -i 's/LsatAuthenticator/L402Authenticator/g' aperture.go auth/authenticator.go auth/authenticator_test.go rename package lsat to l402 git mv lsat/ l402 sed 's@aperture/lsat@aperture/l402@g' -i `git grep -l aperture/lsat` sed -i 's@package lsat@package l402@' `git grep -l 'package lsat'` sed -i 's@lsat\.@l402.@g' -i `git grep -l 'lsat\.'` sed 's@l402.Id@lsat.Id@' -i mint/mint_test.go replace lsat with l402 in the code sed 's@lsat@l402@' -i mint/mint_test.go sed 's@Lsat@L402@' -i l402/client_interceptor.go sed 's@lsatstore@l402store@' -i l402/store_test.go replace LSAT to L402 in comments sed '/\/\//s@LSAT@L402@g' -i `git grep -l '//.*LSAT'` replace LSAT -> L402 in the code, skip when a string starts with it sed 's@\([^"/]\)LSAT@\1L402@g' -i `git grep -l LSAT`
This commit is contained in:
@@ -47,7 +47,7 @@ import (
|
||||
|
||||
const (
|
||||
// topLevelKey is the top level key for an etcd cluster where we'll
|
||||
// store all LSAT proxy related data.
|
||||
// store all L402 proxy related data.
|
||||
topLevelKey = "lsat/proxy"
|
||||
|
||||
// etcdKeyDelimeter is the delimeter we'll use for all etcd keys to
|
||||
@@ -819,7 +819,7 @@ func createProxy(cfg *Config, challenger challenger.Challenger,
|
||||
ServiceLimiter: newStaticServiceLimiter(cfg.Services),
|
||||
Now: time.Now,
|
||||
})
|
||||
authenticator := auth.NewLsatAuthenticator(minter, challenger)
|
||||
authenticator := auth.NewL402Authenticator(minter, challenger)
|
||||
|
||||
// By default the static file server only returns 404 answers for
|
||||
// security reasons. Serving files from the staticRoot directory has to
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/lightninglabs/aperture/aperturedb/sqlc"
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
)
|
||||
@@ -81,11 +81,11 @@ func NewSecretsStore(db BatchedSecretsDB) *SecretsStore {
|
||||
// NewSecret creates a new cryptographically random secret which is
|
||||
// keyed by the given hash.
|
||||
func (s *SecretsStore) NewSecret(ctx context.Context,
|
||||
hash [sha256.Size]byte) ([lsat.SecretSize]byte, error) {
|
||||
hash [sha256.Size]byte) ([l402.SecretSize]byte, error) {
|
||||
|
||||
var secret [lsat.SecretSize]byte
|
||||
var secret [l402.SecretSize]byte
|
||||
if _, err := rand.Read(secret[:]); err != nil {
|
||||
return [lsat.SecretSize]byte{}, err
|
||||
return [l402.SecretSize]byte{}, err
|
||||
}
|
||||
|
||||
var writeTxOpts SecretsDBTxOptions
|
||||
@@ -103,7 +103,7 @@ func (s *SecretsStore) NewSecret(ctx context.Context,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return [lsat.SecretSize]byte{}, fmt.Errorf("unable to insert "+
|
||||
return [l402.SecretSize]byte{}, fmt.Errorf("unable to insert "+
|
||||
"new secret for hash(%x): %w", hash, err)
|
||||
}
|
||||
|
||||
@@ -114,9 +114,9 @@ func (s *SecretsStore) NewSecret(ctx context.Context,
|
||||
// corresponds to the given hash. If there is no secret, then
|
||||
// ErrSecretNotFound is returned.
|
||||
func (s *SecretsStore) GetSecret(ctx context.Context,
|
||||
hash [sha256.Size]byte) ([lsat.SecretSize]byte, error) {
|
||||
hash [sha256.Size]byte) ([l402.SecretSize]byte, error) {
|
||||
|
||||
var secret [lsat.SecretSize]byte
|
||||
var secret [l402.SecretSize]byte
|
||||
readOpts := NewSecretsDBReadTx()
|
||||
err := s.db.ExecTx(ctx, &readOpts, func(db SecretsDB) error {
|
||||
secretRow, err := db.GetSecretByHash(ctx, hash[:])
|
||||
@@ -134,7 +134,7 @@ func (s *SecretsStore) GetSecret(ctx context.Context,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return [lsat.SecretSize]byte{}, fmt.Errorf("unable to get "+
|
||||
return [l402.SecretSize]byte{}, fmt.Errorf("unable to get "+
|
||||
"secret for hash(%x): %w", hash, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,28 +6,28 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
)
|
||||
|
||||
// LsatAuthenticator is an authenticator that uses the LSAT protocol to
|
||||
// L402Authenticator is an authenticator that uses the L402 protocol to
|
||||
// authenticate requests.
|
||||
type LsatAuthenticator struct {
|
||||
type L402Authenticator struct {
|
||||
minter Minter
|
||||
checker InvoiceChecker
|
||||
}
|
||||
|
||||
// A compile time flag to ensure the LsatAuthenticator satisfies the
|
||||
// A compile time flag to ensure the L402Authenticator satisfies the
|
||||
// Authenticator interface.
|
||||
var _ Authenticator = (*LsatAuthenticator)(nil)
|
||||
var _ Authenticator = (*L402Authenticator)(nil)
|
||||
|
||||
// NewLsatAuthenticator creates a new authenticator that authenticates requests
|
||||
// based on LSAT tokens.
|
||||
func NewLsatAuthenticator(minter Minter,
|
||||
checker InvoiceChecker) *LsatAuthenticator {
|
||||
// NewL402Authenticator creates a new authenticator that authenticates requests
|
||||
// based on L402 tokens.
|
||||
func NewL402Authenticator(minter Minter,
|
||||
checker InvoiceChecker) *L402Authenticator {
|
||||
|
||||
return &LsatAuthenticator{
|
||||
return &L402Authenticator{
|
||||
minter: minter,
|
||||
checker: checker,
|
||||
}
|
||||
@@ -37,11 +37,11 @@ func NewLsatAuthenticator(minter Minter,
|
||||
// to a given backend service.
|
||||
//
|
||||
// NOTE: This is part of the Authenticator interface.
|
||||
func (l *LsatAuthenticator) Accept(header *http.Header, serviceName string) bool {
|
||||
func (l *L402Authenticator) Accept(header *http.Header, serviceName string) bool {
|
||||
// Try reading the macaroon and preimage from the HTTP header. This can
|
||||
// be in different header fields depending on the implementation and/or
|
||||
// protocol.
|
||||
mac, preimage, err := lsat.FromHeader(header)
|
||||
mac, preimage, err := l402.FromHeader(header)
|
||||
if err != nil {
|
||||
log.Debugf("Deny: %v", err)
|
||||
return false
|
||||
@@ -52,9 +52,9 @@ func (l *LsatAuthenticator) Accept(header *http.Header, serviceName string) bool
|
||||
Preimage: preimage,
|
||||
TargetService: serviceName,
|
||||
}
|
||||
err = l.minter.VerifyLSAT(context.Background(), verificationParams)
|
||||
err = l.minter.VerifyL402(context.Background(), verificationParams)
|
||||
if err != nil {
|
||||
log.Debugf("Deny: LSAT validation failed: %v", err)
|
||||
log.Debugf("Deny: L402 validation failed: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -75,24 +75,24 @@ func (l *LsatAuthenticator) Accept(header *http.Header, serviceName string) bool
|
||||
// complete.
|
||||
//
|
||||
// NOTE: This is part of the Authenticator interface.
|
||||
func (l *LsatAuthenticator) FreshChallengeHeader(r *http.Request,
|
||||
func (l *L402Authenticator) FreshChallengeHeader(r *http.Request,
|
||||
serviceName string, servicePrice int64) (http.Header, error) {
|
||||
|
||||
service := lsat.Service{
|
||||
service := l402.Service{
|
||||
Name: serviceName,
|
||||
Tier: lsat.BaseTier,
|
||||
Tier: l402.BaseTier,
|
||||
Price: servicePrice,
|
||||
}
|
||||
mac, paymentRequest, err := l.minter.MintLSAT(
|
||||
mac, paymentRequest, err := l.minter.MintL402(
|
||||
context.Background(), service,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Error minting LSAT: %v", err)
|
||||
log.Errorf("Error minting L402: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
macBytes, err := mac.MarshalBinary()
|
||||
if err != nil {
|
||||
log.Errorf("Error serializing LSAT: %v", err)
|
||||
log.Errorf("Error serializing L402: %v", err)
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("LSAT macaroon=\"%s\", invoice=\"%s\"",
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
@@ -21,8 +21,8 @@ func createDummyMacHex(preimage string) string {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
preimageCaveat := lsat.Caveat{Condition: lsat.PreimageKey, Value: preimage}
|
||||
err = lsat.AddFirstPartyCaveats(dummyMac, preimageCaveat)
|
||||
preimageCaveat := l402.Caveat{Condition: l402.PreimageKey, Value: preimage}
|
||||
err = l402.AddFirstPartyCaveats(dummyMac, preimageCaveat)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -33,9 +33,9 @@ func createDummyMacHex(preimage string) string {
|
||||
return hex.EncodeToString(macBytes)
|
||||
}
|
||||
|
||||
// TestLsatAuthenticator tests that the authenticator properly handles auth
|
||||
// TestL402Authenticator tests that the authenticator properly handles auth
|
||||
// headers and the tokens contained in them.
|
||||
func TestLsatAuthenticator(t *testing.T) {
|
||||
func TestL402Authenticator(t *testing.T) {
|
||||
var (
|
||||
testPreimage = "49349dfea4abed3cd14f6d356afa83de" +
|
||||
"9787b609f088c8df09bacc7b4bd21b39"
|
||||
@@ -65,21 +65,21 @@ func TestLsatAuthenticator(t *testing.T) {
|
||||
{
|
||||
id: "empty auth header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderAuthorization: []string{},
|
||||
l402.HeaderAuthorization: []string{},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
id: "zero length auth header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderAuthorization: []string{""},
|
||||
l402.HeaderAuthorization: []string{""},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
id: "invalid auth header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderAuthorization: []string{
|
||||
l402.HeaderAuthorization: []string{
|
||||
"foo",
|
||||
},
|
||||
},
|
||||
@@ -88,21 +88,21 @@ func TestLsatAuthenticator(t *testing.T) {
|
||||
{
|
||||
id: "invalid macaroon metadata header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderMacaroonMD: []string{"foo"},
|
||||
l402.HeaderMacaroonMD: []string{"foo"},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
id: "invalid macaroon header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderMacaroon: []string{"foo"},
|
||||
l402.HeaderMacaroon: []string{"foo"},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
id: "valid auth header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderAuthorization: []string{
|
||||
l402.HeaderAuthorization: []string{
|
||||
"LSAT " + testMacBase64 + ":" +
|
||||
testPreimage,
|
||||
},
|
||||
@@ -112,7 +112,7 @@ func TestLsatAuthenticator(t *testing.T) {
|
||||
{
|
||||
id: "valid macaroon metadata header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderMacaroonMD: []string{
|
||||
l402.HeaderMacaroonMD: []string{
|
||||
testMacHex,
|
||||
}},
|
||||
result: true,
|
||||
@@ -120,7 +120,7 @@ func TestLsatAuthenticator(t *testing.T) {
|
||||
{
|
||||
id: "valid macaroon header",
|
||||
header: &http.Header{
|
||||
lsat.HeaderMacaroon: []string{
|
||||
l402.HeaderMacaroon: []string{
|
||||
testMacHex,
|
||||
},
|
||||
},
|
||||
@@ -129,7 +129,7 @@ func TestLsatAuthenticator(t *testing.T) {
|
||||
{
|
||||
id: "valid macaroon header, wrong invoice state",
|
||||
header: &http.Header{
|
||||
lsat.HeaderMacaroon: []string{
|
||||
l402.HeaderMacaroon: []string{
|
||||
testMacHex,
|
||||
},
|
||||
},
|
||||
@@ -140,7 +140,7 @@ func TestLsatAuthenticator(t *testing.T) {
|
||||
)
|
||||
|
||||
c := &mockChecker{}
|
||||
a := auth.NewLsatAuthenticator(&mockMint{}, c)
|
||||
a := auth.NewL402Authenticator(&mockMint{}, c)
|
||||
for _, testCase := range headerTests {
|
||||
c.err = testCase.checkErr
|
||||
result := a.Accept(testCase.header, "test")
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
@@ -30,14 +30,14 @@ type Authenticator interface {
|
||||
FreshChallengeHeader(*http.Request, string, int64) (http.Header, error)
|
||||
}
|
||||
|
||||
// Minter is an entity that is able to mint and verify LSATs for a set of
|
||||
// Minter is an entity that is able to mint and verify L402s for a set of
|
||||
// services.
|
||||
type Minter interface {
|
||||
// MintLSAT mints a new LSAT for the target services.
|
||||
MintLSAT(context.Context, ...lsat.Service) (*macaroon.Macaroon, string, error)
|
||||
// MintL402 mints a new L402 for the target services.
|
||||
MintL402(context.Context, ...l402.Service) (*macaroon.Macaroon, string, error)
|
||||
|
||||
// VerifyLSAT attempts to verify an LSAT with the given parameters.
|
||||
VerifyLSAT(context.Context, *mint.VerificationParams) error
|
||||
// VerifyL402 attempts to verify an L402 with the given parameters.
|
||||
VerifyL402(context.Context, *mint.VerificationParams) error
|
||||
}
|
||||
|
||||
// InvoiceChecker is an entity that is able to check the status of an invoice,
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
@@ -17,13 +17,13 @@ type mockMint struct {
|
||||
|
||||
var _ auth.Minter = (*mockMint)(nil)
|
||||
|
||||
func (m *mockMint) MintLSAT(_ context.Context,
|
||||
services ...lsat.Service) (*macaroon.Macaroon, string, error) {
|
||||
func (m *mockMint) MintL402(_ context.Context,
|
||||
services ...l402.Service) (*macaroon.Macaroon, string, error) {
|
||||
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
func (m *mockMint) VerifyLSAT(_ context.Context, p *mint.VerificationParams) error {
|
||||
func (m *mockMint) VerifyL402(_ context.Context, p *mint.VerificationParams) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// LNCChallenger is a challenger that uses LNC to connect to an lnd backend to
|
||||
// create new LSAT payment challenges.
|
||||
// create new L402 payment challenges.
|
||||
type LNCChallenger struct {
|
||||
lndChallenger *LndChallenger
|
||||
nodeConn *lnc.NodeConn
|
||||
@@ -61,7 +61,7 @@ func (l *LNCChallenger) Stop() {
|
||||
l.lndChallenger.Stop()
|
||||
}
|
||||
|
||||
// NewChallenge creates a new LSAT payment challenge, returning a payment
|
||||
// NewChallenge creates a new L402 payment challenge, returning a payment
|
||||
// request (invoice) and the corresponding payment hash.
|
||||
//
|
||||
// NOTE: This is part of the mint.Challenger interface.
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
)
|
||||
|
||||
// LndChallenger is a challenger that uses an lnd backend to create new LSAT
|
||||
// LndChallenger is a challenger that uses an lnd backend to create new L402
|
||||
// payment challenges.
|
||||
type LndChallenger struct {
|
||||
client InvoiceClient
|
||||
@@ -247,7 +247,7 @@ func (l *LndChallenger) Stop() {
|
||||
l.wg.Wait()
|
||||
}
|
||||
|
||||
// NewChallenge creates a new LSAT payment challenge, returning a payment
|
||||
// NewChallenge creates a new L402 payment challenge, returning a payment
|
||||
// request (invoice) and the corresponding payment hash.
|
||||
//
|
||||
// NOTE: This is part of the mint.Challenger interface.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -20,10 +20,10 @@ var (
|
||||
"\"condition=value\"")
|
||||
)
|
||||
|
||||
// Caveat is a predicate that can be applied to an LSAT in order to restrict its
|
||||
// use in some form. Caveats are evaluated during LSAT verification after the
|
||||
// LSAT's signature is verified. The predicate of each caveat must hold true in
|
||||
// order to successfully validate an LSAT.
|
||||
// Caveat is a predicate that can be applied to an L402 in order to restrict its
|
||||
// use in some form. Caveats are evaluated during L402 verification after the
|
||||
// L402's signature is verified. The predicate of each caveat must hold true in
|
||||
// order to successfully validate an L402.
|
||||
type Caveat struct {
|
||||
// Condition serves as a way to identify a caveat and how to satisfy it.
|
||||
Condition string
|
||||
@@ -92,11 +92,11 @@ func HasCaveat(m *macaroon.Macaroon, cond string) (string, bool) {
|
||||
return *value, true
|
||||
}
|
||||
|
||||
// VerifyCaveats determines whether every relevant caveat of an LSAT holds true.
|
||||
// VerifyCaveats determines whether every relevant caveat of an L402 holds true.
|
||||
// A caveat is considered relevant if a satisfier is provided for it, which is
|
||||
// what we'll use as their evaluation.
|
||||
//
|
||||
// NOTE: The caveats provided should be in the same order as in the LSAT to
|
||||
// NOTE: The caveats provided should be in the same order as in the L402 to
|
||||
// ensure the correctness of each satisfier's SatisfyPrevious.
|
||||
func VerifyCaveats(caveats []Caveat, satisfiers ...Satisfier) error {
|
||||
// Construct a set of our satisfiers to determine which caveats we know
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -79,7 +79,7 @@ func TestHasCaveat(t *testing.T) {
|
||||
t.Fatal("found unexpected caveat with unknown condition")
|
||||
}
|
||||
|
||||
// Add two caveats, one in a valid LSAT format and another invalid.
|
||||
// Add two caveats, one in a valid L402 format and another invalid.
|
||||
// We'll test that we're still able to determine the macaroon contains
|
||||
// the valid caveat even though there is one that is invalid.
|
||||
invalidCaveat := []byte("invalid")
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -44,12 +44,12 @@ const (
|
||||
AuthHeader = "WWW-Authenticate"
|
||||
|
||||
// DefaultMaxCostSats is the default maximum amount in satoshis that we
|
||||
// are going to pay for an LSAT automatically. Does not include routing
|
||||
// are going to pay for an L402 automatically. Does not include routing
|
||||
// fees.
|
||||
DefaultMaxCostSats = 1000
|
||||
|
||||
// DefaultMaxRoutingFeeSats is the default maximum routing fee in
|
||||
// satoshis that we are going to pay to acquire an LSAT token.
|
||||
// satoshis that we are going to pay to acquire an L402 token.
|
||||
DefaultMaxRoutingFeeSats = 10
|
||||
|
||||
// PaymentTimeout is the maximum time we allow a payment to take before
|
||||
@@ -76,7 +76,7 @@ var (
|
||||
"failure state")
|
||||
)
|
||||
|
||||
// ClientInterceptor is a gRPC client interceptor that can handle LSAT
|
||||
// ClientInterceptor is a gRPC client interceptor that can handle L402
|
||||
// authentication challenges with embedded payment requests. It uses a
|
||||
// connection to lnd to automatically pay for an authentication token.
|
||||
type ClientInterceptor struct {
|
||||
@@ -90,7 +90,7 @@ type ClientInterceptor struct {
|
||||
}
|
||||
|
||||
// NewInterceptor creates a new gRPC client interceptor that uses the provided
|
||||
// lnd connection to automatically acquire and pay for LSAT tokens, unless the
|
||||
// lnd connection to automatically acquire and pay for L402 tokens, unless the
|
||||
// indicated store already contains a usable token.
|
||||
func NewInterceptor(lnd *lndclient.LndServices, store Store,
|
||||
rpcCallTimeout time.Duration, maxCost,
|
||||
@@ -140,7 +140,7 @@ func (i *ClientInterceptor) UnaryInterceptor(ctx context.Context, method string,
|
||||
}
|
||||
|
||||
// Try executing the call now. If anything goes wrong, we only handle
|
||||
// the LSAT error message that comes in the form of a gRPC status error.
|
||||
// the L402 error message that comes in the form of a gRPC status error.
|
||||
rpcCtx, cancel := context.WithTimeout(ctx, i.callTimeout)
|
||||
defer cancel()
|
||||
err = invoker(rpcCtx, method, req, reply, cc, iCtx.opts...)
|
||||
@@ -155,7 +155,7 @@ func (i *ClientInterceptor) UnaryInterceptor(ctx context.Context, method string,
|
||||
return err
|
||||
}
|
||||
|
||||
// Execute the same request again, now with the LSAT
|
||||
// Execute the same request again, now with the L402
|
||||
// token added as an RPC credential.
|
||||
rpcCtx2, cancel2 := context.WithTimeout(ctx, i.callTimeout)
|
||||
defer cancel2()
|
||||
@@ -188,7 +188,7 @@ func (i *ClientInterceptor) StreamInterceptor(ctx context.Context,
|
||||
}
|
||||
|
||||
// Try establishing the stream now. If anything goes wrong, we only
|
||||
// handle the LSAT error message that comes in the form of a gRPC status
|
||||
// handle the L402 error message that comes in the form of a gRPC status
|
||||
// error. The context of a stream will be used for the whole lifetime of
|
||||
// it, so we can't really clamp down on the initial call with a timeout.
|
||||
stream, err := streamer(ctx, desc, cc, method, iCtx.opts...)
|
||||
@@ -203,7 +203,7 @@ func (i *ClientInterceptor) StreamInterceptor(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Execute the same request again, now with the LSAT token added
|
||||
// Execute the same request again, now with the L402 token added
|
||||
// as an RPC credential.
|
||||
return streamer(ctx, desc, cc, method, iCtx.opts...)
|
||||
}
|
||||
@@ -240,7 +240,7 @@ func (i *ClientInterceptor) newInterceptContext(ctx context.Context,
|
||||
// this call. We also never send a pending payment to the server since
|
||||
// we know it's not valid.
|
||||
case !iCtx.token.isPending():
|
||||
if err = i.addLsatCredentials(iCtx); err != nil {
|
||||
if err = i.addL402Credentials(iCtx); err != nil {
|
||||
log.Errorf("Adding macaroon to request failed: %v", err)
|
||||
return nil, fmt.Errorf("adding macaroon failed: %v",
|
||||
err)
|
||||
@@ -250,8 +250,8 @@ func (i *ClientInterceptor) newInterceptContext(ctx context.Context,
|
||||
// We need a way to extract the response headers sent by the server.
|
||||
// This can only be done through the experimental grpc.Trailer call
|
||||
// option. We execute the request and inspect the error. If it's the
|
||||
// LSAT specific payment required error, we might execute the same
|
||||
// method again later with the paid LSAT token.
|
||||
// L402 specific payment required error, we might execute the same
|
||||
// method again later with the paid L402 token.
|
||||
iCtx.opts = append(iCtx.opts, grpc.Trailer(iCtx.metadata))
|
||||
return iCtx, nil
|
||||
}
|
||||
@@ -262,8 +262,8 @@ func (i *ClientInterceptor) handlePayment(iCtx *interceptContext) error {
|
||||
switch {
|
||||
// Resume/track a pending payment if it was interrupted for some reason.
|
||||
case iCtx.token != nil && iCtx.token.isPending():
|
||||
log.Infof("Payment of LSAT token is required, resuming/" +
|
||||
"tracking previous payment from pending LSAT token")
|
||||
log.Infof("Payment of L402 token is required, resuming/" +
|
||||
"tracking previous payment from pending L402 token")
|
||||
err := i.trackPayment(iCtx.mainCtx, iCtx.token)
|
||||
|
||||
// If the payment failed for good, it will never come back to a
|
||||
@@ -277,9 +277,9 @@ func (i *ClientInterceptor) handlePayment(iCtx *interceptContext) error {
|
||||
}
|
||||
|
||||
// Let's try again by paying for the new token.
|
||||
log.Infof("Retrying payment of LSAT token invoice")
|
||||
log.Infof("Retrying payment of L402 token invoice")
|
||||
var err error
|
||||
iCtx.token, err = i.payLsatToken(
|
||||
iCtx.token, err = i.payL402Token(
|
||||
iCtx.mainCtx, iCtx.metadata,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -295,27 +295,27 @@ func (i *ClientInterceptor) handlePayment(iCtx *interceptContext) error {
|
||||
// We don't have a token yet, try to get a new one.
|
||||
case iCtx.token == nil:
|
||||
// We don't have a token yet, get a new one.
|
||||
log.Infof("Payment of LSAT token is required, paying invoice")
|
||||
log.Infof("Payment of L402 token is required, paying invoice")
|
||||
var err error
|
||||
iCtx.token, err = i.payLsatToken(iCtx.mainCtx, iCtx.metadata)
|
||||
iCtx.token, err = i.payL402Token(iCtx.mainCtx, iCtx.metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We have a token and it's valid, nothing more to do here.
|
||||
default:
|
||||
log.Debugf("Found valid LSAT token to add to request")
|
||||
log.Debugf("Found valid L402 token to add to request")
|
||||
}
|
||||
|
||||
if err := i.addLsatCredentials(iCtx); err != nil {
|
||||
if err := i.addL402Credentials(iCtx); err != nil {
|
||||
log.Errorf("Adding macaroon to request failed: %v", err)
|
||||
return fmt.Errorf("adding macaroon failed: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// addLsatCredentials adds an LSAT token to the given intercept context.
|
||||
func (i *ClientInterceptor) addLsatCredentials(iCtx *interceptContext) error {
|
||||
// addL402Credentials adds an L402 token to the given intercept context.
|
||||
func (i *ClientInterceptor) addL402Credentials(iCtx *interceptContext) error {
|
||||
if iCtx.token == nil {
|
||||
return fmt.Errorf("cannot add nil token to context")
|
||||
}
|
||||
@@ -330,10 +330,10 @@ func (i *ClientInterceptor) addLsatCredentials(iCtx *interceptContext) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// payLsatToken reads the payment challenge from the response metadata and tries
|
||||
// to pay the invoice encoded in them, returning a paid LSAT token if
|
||||
// payL402Token reads the payment challenge from the response metadata and tries
|
||||
// to pay the invoice encoded in them, returning a paid L402 token if
|
||||
// successful.
|
||||
func (i *ClientInterceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
|
||||
func (i *ClientInterceptor) payL402Token(ctx context.Context, md *metadata.MD) (
|
||||
*Token, error) {
|
||||
|
||||
// First parse the authentication header that was stored in the
|
||||
@@ -364,7 +364,7 @@ func (i *ClientInterceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
|
||||
// Check that the charged amount does not exceed our maximum cost.
|
||||
maxCostMsat := lnwire.NewMSatFromSatoshis(i.maxCost)
|
||||
if invoice.MilliSat != nil && *invoice.MilliSat > maxCostMsat {
|
||||
return nil, fmt.Errorf("cannot pay for LSAT automatically, "+
|
||||
return nil, fmt.Errorf("cannot pay for L402 automatically, "+
|
||||
"cost of %d msat exceeds configured max cost of %d "+
|
||||
"msat", *invoice.MilliSat, maxCostMsat)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -219,7 +219,7 @@ var (
|
||||
},
|
||||
expectLndCall: false,
|
||||
expectToken: false,
|
||||
expectInterceptErr: "cannot pay for LSAT automatically, cost " +
|
||||
expectInterceptErr: "cannot pay for L402 automatically, cost " +
|
||||
"of 500000 msat exceeds configured max cost of " +
|
||||
"100000 msat",
|
||||
expectBackendCalls: 1,
|
||||
@@ -262,7 +262,7 @@ func invoker(opts []grpc.CallOption) error {
|
||||
return backendErr
|
||||
}
|
||||
|
||||
// TestUnaryInterceptor tests that the interceptor can handle LSAT protocol
|
||||
// TestUnaryInterceptor tests that the interceptor can handle L402 protocol
|
||||
// responses for unary calls and pay the token.
|
||||
func TestUnaryInterceptor(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||
@@ -290,7 +290,7 @@ func TestUnaryInterceptor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestStreamInterceptor tests that the interceptor can handle LSAT protocol
|
||||
// TestStreamInterceptor tests that the interceptor can handle L402 protocol
|
||||
// responses in streams and pay the token.
|
||||
func TestStreamInterceptor(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||
@@ -1,10 +1,10 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// ContextKey is the type that we use to identify LSAT specific values in the
|
||||
// ContextKey is the type that we use to identify L402 specific values in the
|
||||
// request context. We wrap the string inside a struct because of this comment
|
||||
// in the context API: "The provided key must be comparable and should not be of
|
||||
// type string or any other built-in type to avoid collisions between packages
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
@@ -14,15 +14,15 @@ import (
|
||||
|
||||
const (
|
||||
// HeaderAuthorization is the HTTP header field name that is used to
|
||||
// send the LSAT by REST clients.
|
||||
// send the L402 by REST clients.
|
||||
HeaderAuthorization = "Authorization"
|
||||
|
||||
// HeaderMacaroonMD is the HTTP header field name that is used to send
|
||||
// the LSAT by certain REST and gRPC clients.
|
||||
// the L402 by certain REST and gRPC clients.
|
||||
HeaderMacaroonMD = "Grpc-Metadata-Macaroon"
|
||||
|
||||
// HeaderMacaroon is the HTTP header field name that is used to send the
|
||||
// LSAT by our own gRPC clients.
|
||||
// L402 by our own gRPC clients.
|
||||
HeaderMacaroon = "Macaroon"
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
// FromHeader tries to extract authentication information from HTTP headers.
|
||||
// There are two supported formats that can be sent in three different header
|
||||
// fields:
|
||||
// 1. Authorization: LSAT <macBase64>:<preimageHex>
|
||||
// 1. Authorization: L402 <macBase64>:<preimageHex>
|
||||
// 2. Grpc-Metadata-Macaroon: <macHex>
|
||||
// 3. Macaroon: <macHex>
|
||||
//
|
||||
@@ -126,7 +126,7 @@ func FromHeader(header *http.Header) (*macaroon.Macaroon, lntypes.Preimage, erro
|
||||
}
|
||||
|
||||
// SetHeader sets the provided authentication elements as the default/standard
|
||||
// HTTP header for the LSAT protocol.
|
||||
// HTTP header for the L402 protocol.
|
||||
func SetHeader(header *http.Header, mac *macaroon.Macaroon,
|
||||
preimage fmt.Stringer) error {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
@@ -11,14 +11,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// LatestVersion is the latest version used for minting new LSATs.
|
||||
// LatestVersion is the latest version used for minting new L402s.
|
||||
LatestVersion = 0
|
||||
|
||||
// SecretSize is the size in bytes of a LSAT's secret, also known as
|
||||
// SecretSize is the size in bytes of a L402's secret, also known as
|
||||
// the root key of the macaroon.
|
||||
SecretSize = 32
|
||||
|
||||
// TokenIDSize is the size in bytes of an LSAT's ID encoded in its
|
||||
// TokenIDSize is the size in bytes of an L402's ID encoded in its
|
||||
// macaroon identifier.
|
||||
TokenIDSize = 32
|
||||
)
|
||||
@@ -29,11 +29,11 @@ var (
|
||||
byteOrder = binary.BigEndian
|
||||
|
||||
// ErrUnknownVersion is an error returned when attempting to decode an
|
||||
// LSAT identifier with an unknown version.
|
||||
ErrUnknownVersion = errors.New("unknown LSAT version")
|
||||
// L402 identifier with an unknown version.
|
||||
ErrUnknownVersion = errors.New("unknown L402 version")
|
||||
)
|
||||
|
||||
// TokenID is the type that stores the token identifier of an LSAT token.
|
||||
// TokenID is the type that stores the token identifier of an L402 token.
|
||||
type TokenID [TokenIDSize]byte
|
||||
|
||||
// String returns the hex encoded representation of the token ID as a string.
|
||||
@@ -58,24 +58,24 @@ func MakeIDFromString(newID string) (TokenID, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Identifier contains the static identifying details of an LSAT. This is
|
||||
// intended to be used as the identifier of the macaroon within an LSAT.
|
||||
// Identifier contains the static identifying details of an L402. This is
|
||||
// intended to be used as the identifier of the macaroon within an L402.
|
||||
type Identifier struct {
|
||||
// Version is the version of an LSAT. Having a version allows us to
|
||||
// Version is the version of an L402. Having a version allows us to
|
||||
// introduce new fields to the identifier in a backwards-compatible
|
||||
// manner.
|
||||
Version uint16
|
||||
|
||||
// PaymentHash is the payment hash linked to an LSAT. Verification of
|
||||
// an LSAT depends on a valid payment, which is enforced by ensuring a
|
||||
// PaymentHash is the payment hash linked to an L402. Verification of
|
||||
// an L402 depends on a valid payment, which is enforced by ensuring a
|
||||
// preimage is provided that hashes to our payment hash.
|
||||
PaymentHash lntypes.Hash
|
||||
|
||||
// TokenID is the unique identifier of an LSAT.
|
||||
// TokenID is the unique identifier of an L402.
|
||||
TokenID TokenID
|
||||
}
|
||||
|
||||
// EncodeIdentifier encodes an LSAT's identifier according to its version.
|
||||
// EncodeIdentifier encodes an L402's identifier according to its version.
|
||||
func EncodeIdentifier(w io.Writer, id *Identifier) error {
|
||||
if err := binary.Write(w, byteOrder, id.Version); err != nil {
|
||||
return err
|
||||
@@ -96,7 +96,7 @@ func EncodeIdentifier(w io.Writer, id *Identifier) error {
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeIdentifier decodes an LSAT's identifier according to its version.
|
||||
// DecodeIdentifier decodes an L402's identifier according to its version.
|
||||
func DecodeIdentifier(r io.Reader) (*Identifier, error) {
|
||||
var version uint16
|
||||
if err := binary.Read(r, byteOrder, &version); err != nil {
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -18,19 +18,19 @@ type Satisfier struct {
|
||||
// condition can be used multiple times as long as they enforce more
|
||||
// permissions than the previous.
|
||||
//
|
||||
// For example, we have a caveat that only allows us to use an LSAT for
|
||||
// For example, we have a caveat that only allows us to use an L402 for
|
||||
// 7 more days. We can add another caveat that only allows for 3 more
|
||||
// days of use and lend it to another party.
|
||||
SatisfyPrevious func(previous Caveat, current Caveat) error
|
||||
|
||||
// SatisfyFinal satisfies the final caveat of an LSAT. If multiple
|
||||
// SatisfyFinal satisfies the final caveat of an L402. If multiple
|
||||
// caveats with the same condition exist, this will only be executed
|
||||
// once all previous caveats are also satisfied.
|
||||
SatisfyFinal func(Caveat) error
|
||||
}
|
||||
|
||||
// NewServicesSatisfier implements a satisfier to determine whether the target
|
||||
// service is authorized for a given LSAT.
|
||||
// service is authorized for a given L402.
|
||||
//
|
||||
// TODO(wilmer): Add tier verification?
|
||||
func NewServicesSatisfier(targetService string) Satisfier {
|
||||
@@ -80,7 +80,7 @@ func NewServicesSatisfier(targetService string) Satisfier {
|
||||
}
|
||||
|
||||
// NewCapabilitiesSatisfier implements a satisfier to determine whether the
|
||||
// target capability for a service is authorized for a given LSAT.
|
||||
// target capability for a service is authorized for a given L402.
|
||||
func NewCapabilitiesSatisfier(service string,
|
||||
targetCapability string) Satisfier {
|
||||
|
||||
@@ -120,7 +120,7 @@ func NewCapabilitiesSatisfier(service string,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTimeoutSatisfier checks if an LSAT is expired or not. The Satisfier takes
|
||||
// NewTimeoutSatisfier checks if an L402 is expired or not. The Satisfier takes
|
||||
// a service name to set as the condition prefix and currentTimestamp to
|
||||
// compare against the expiration(s) in the caveats. The expiration time is
|
||||
// retrieved from the caveat values themselves. The satisfier will also make
|
||||
@@ -174,7 +174,7 @@ func NewTimeoutSatisfier(service string, now func() time.Time) Satisfier {
|
||||
}
|
||||
|
||||
return fmt.Errorf("not authorized to access " +
|
||||
"service. LSAT has expired")
|
||||
"service. L402 has expired")
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
)
|
||||
|
||||
// ServerInterceptor is a gRPC server interceptor that extracts the token ID
|
||||
// from the request context if an LSAT is present.
|
||||
// from the request context if an L402 is present.
|
||||
type ServerInterceptor struct{}
|
||||
|
||||
// UnaryInterceptor is an unary gRPC server interceptor that inspects incoming
|
||||
// calls for authentication tokens. If an LSAT authentication token is found in
|
||||
// calls for authentication tokens. If an L402 authentication token is found in
|
||||
// the request, its token ID is extracted and treated as client ID. The
|
||||
// extracted ID is then attached to the request context in a format that is easy
|
||||
// to extract by request handlers.
|
||||
@@ -53,7 +53,7 @@ func (w *wrappedStream) Context() context.Context {
|
||||
}
|
||||
|
||||
// StreamInterceptor is an stream gRPC server interceptor that inspects incoming
|
||||
// streams for authentication tokens. If an LSAT authentication token is found
|
||||
// streams for authentication tokens. If an L402 authentication token is found
|
||||
// in the initial stream establishment request, its token ID is extracted and
|
||||
// treated as client ID. The extracted ID is then attached to the request
|
||||
// context in a format that is easy to extract by request handlers.
|
||||
@@ -81,7 +81,7 @@ func (i *ServerInterceptor) StreamInterceptor(srv interface{},
|
||||
return handler(srv, wrappedStream)
|
||||
}
|
||||
|
||||
// tokenFromContext tries to extract the LSAT from a context.
|
||||
// tokenFromContext tries to extract the L402 from a context.
|
||||
func tokenFromContext(ctx context.Context) (*TokenID, error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
@@ -97,7 +97,7 @@ func tokenFromContext(ctx context.Context) (*TokenID, error) {
|
||||
return nil, fmt.Errorf("auth header extraction failed: %v", err)
|
||||
}
|
||||
|
||||
// If there is an LSAT, decode and add it to the context.
|
||||
// If there is an L402, decode and add it to the context.
|
||||
identifier, err := DecodeIdentifier(bytes.NewBuffer(macaroon.Id()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("token ID decoding failed: %v", err)
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -33,26 +33,26 @@ var (
|
||||
"\"name:tier\"")
|
||||
)
|
||||
|
||||
// ServiceTier represents the different possible tiers of an LSAT-enabled
|
||||
// ServiceTier represents the different possible tiers of an L402-enabled
|
||||
// service.
|
||||
type ServiceTier uint8
|
||||
|
||||
const (
|
||||
// BaseTier is the base tier of an LSAT-enabled service. This tier
|
||||
// should be used for any new LSATs that are not part of a service tier
|
||||
// BaseTier is the base tier of an L402-enabled service. This tier
|
||||
// should be used for any new L402s that are not part of a service tier
|
||||
// upgrade.
|
||||
BaseTier ServiceTier = iota
|
||||
)
|
||||
|
||||
// Service contains the details of an LSAT-enabled service.
|
||||
// Service contains the details of an L402-enabled service.
|
||||
type Service struct {
|
||||
// Name is the name of the LSAT-enabled service.
|
||||
// Name is the name of the L402-enabled service.
|
||||
Name string
|
||||
|
||||
// Tier is the tier of the LSAT-enabled service.
|
||||
// Tier is the tier of the L402-enabled service.
|
||||
Tier ServiceTier
|
||||
|
||||
// Price of service LSAT in satoshis.
|
||||
// Price of service L402 in satoshis.
|
||||
Price int64
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -15,11 +15,11 @@ var (
|
||||
|
||||
// storeFileName is the name of the file where we store the final,
|
||||
// valid, token to.
|
||||
storeFileName = "lsat.token"
|
||||
storeFileName = "l402.token"
|
||||
|
||||
// storeFileNamePending is the name of the file where we store a pending
|
||||
// token until it was successfully paid for.
|
||||
storeFileNamePending = "lsat.token.pending"
|
||||
storeFileNamePending = "l402.token.pending"
|
||||
|
||||
// errNoReplace is the error that is returned if a new token is
|
||||
// being written to a store that already contains a paid token.
|
||||
@@ -27,7 +27,7 @@ var (
|
||||
"new token. " + manualRetryHint)
|
||||
)
|
||||
|
||||
// Store is an interface that allows users to store and retrieve an LSAT token.
|
||||
// Store is an interface that allows users to store and retrieve an L402 token.
|
||||
type Store interface {
|
||||
// CurrentToken returns the token that is currently contained in the
|
||||
// store or an error if there is none.
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func TestFileStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tempDirName, err := os.MkdirTemp("", "lsatstore")
|
||||
tempDirName, err := os.MkdirTemp("", "l402store")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsat
|
||||
package l402
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -17,9 +17,9 @@ var (
|
||||
zeroPreimage lntypes.Preimage
|
||||
)
|
||||
|
||||
// Token is the main type to store an LSAT token in.
|
||||
// Token is the main type to store an L402 token in.
|
||||
type Token struct {
|
||||
// PaymentHash is the hash of the LSAT invoice that needs to be paid.
|
||||
// PaymentHash is the hash of the L402 invoice that needs to be paid.
|
||||
// Knowing the preimage to this hash is seen as proof of payment by the
|
||||
// authentication server.
|
||||
PaymentHash lntypes.Hash
|
||||
@@ -47,7 +47,7 @@ type Token struct {
|
||||
}
|
||||
|
||||
// tokenFromChallenge parses the parts that are present in the challenge part
|
||||
// of the LSAT auth protocol which is the macaroon and the payment hash.
|
||||
// of the L402 auth protocol which is the macaroon and the payment hash.
|
||||
func tokenFromChallenge(baseMac []byte, paymentHash *[32]byte) (*Token, error) {
|
||||
// First, validate that the macaroon is valid and can be unmarshaled.
|
||||
mac := &macaroon.Macaroon{}
|
||||
@@ -92,11 +92,11 @@ func (t *Token) PaidMacaroon() (*macaroon.Macaroon, error) {
|
||||
// yet expired.
|
||||
func (t *Token) IsValid() bool {
|
||||
// TODO(guggero): Extract and validate from caveat once we add an
|
||||
// expiration date to the LSAT.
|
||||
// expiration date to the L402.
|
||||
return true
|
||||
}
|
||||
|
||||
// isPending returns true if the payment for the LSAT is still in flight and we
|
||||
// isPending returns true if the payment for the L402 is still in flight and we
|
||||
// haven't received the preimage yet.
|
||||
func (t *Token) isPending() bool {
|
||||
return t.Preimage == zeroPreimage
|
||||
4
log.go
4
log.go
@@ -3,7 +3,7 @@ package aperture
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/proxy"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightningnetwork/lnd"
|
||||
@@ -27,7 +27,7 @@ func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) {
|
||||
|
||||
lnd.SetSubLogger(root, Subsystem, log)
|
||||
lnd.AddSubLogger(root, auth.Subsystem, intercept, auth.UseLogger)
|
||||
lnd.AddSubLogger(root, lsat.Subsystem, intercept, lsat.UseLogger)
|
||||
lnd.AddSubLogger(root, l402.Subsystem, intercept, l402.UseLogger)
|
||||
lnd.AddSubLogger(root, proxy.Subsystem, intercept, proxy.UseLogger)
|
||||
lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger)
|
||||
}
|
||||
|
||||
106
mint/mint.go
106
mint/mint.go
@@ -9,7 +9,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
@@ -20,8 +20,8 @@ var (
|
||||
ErrSecretNotFound = errors.New("secret not found")
|
||||
)
|
||||
|
||||
// Challenger is an interface used to present requesters of LSATs with a
|
||||
// challenge that must be satisfied before an LSAT can be validated. This
|
||||
// Challenger is an interface used to present requesters of L402s with a
|
||||
// challenge that must be satisfied before an L402 can be validated. This
|
||||
// challenge takes the form of a Lightning payment request.
|
||||
type Challenger interface {
|
||||
// NewChallenge returns a new challenge in the form of a Lightning
|
||||
@@ -34,18 +34,18 @@ type Challenger interface {
|
||||
Stop()
|
||||
}
|
||||
|
||||
// SecretStore is the store responsible for storing LSAT secrets. These secrets
|
||||
// are required for proper verification of each minted LSAT.
|
||||
// SecretStore is the store responsible for storing L402 secrets. These secrets
|
||||
// are required for proper verification of each minted L402.
|
||||
type SecretStore interface {
|
||||
// NewSecret creates a new cryptographically random secret which is
|
||||
// keyed by the given hash.
|
||||
NewSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte,
|
||||
NewSecret(context.Context, [sha256.Size]byte) ([l402.SecretSize]byte,
|
||||
error)
|
||||
|
||||
// GetSecret returns the cryptographically random secret that
|
||||
// corresponds to the given hash. If there is no secret, then
|
||||
// ErrSecretNotFound is returned.
|
||||
GetSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte,
|
||||
GetSecret(context.Context, [sha256.Size]byte) ([l402.SecretSize]byte,
|
||||
error)
|
||||
|
||||
// RevokeSecret removes the cryptographically random secret that
|
||||
@@ -55,38 +55,38 @@ type SecretStore interface {
|
||||
}
|
||||
|
||||
// ServiceLimiter abstracts the source of caveats that should be applied to an
|
||||
// LSAT for a particular service.
|
||||
// L402 for a particular service.
|
||||
type ServiceLimiter interface {
|
||||
// ServiceCapabilities returns the capabilities caveats for each
|
||||
// service. This determines which capabilities of each service can be
|
||||
// accessed.
|
||||
ServiceCapabilities(context.Context, ...lsat.Service) ([]lsat.Caveat,
|
||||
ServiceCapabilities(context.Context, ...l402.Service) ([]l402.Caveat,
|
||||
error)
|
||||
|
||||
// ServiceConstraints returns the constraints for each service. This
|
||||
// enforces additional constraints on a particular service/service
|
||||
// capability.
|
||||
ServiceConstraints(context.Context, ...lsat.Service) ([]lsat.Caveat,
|
||||
ServiceConstraints(context.Context, ...l402.Service) ([]l402.Caveat,
|
||||
error)
|
||||
|
||||
// ServiceTimeouts returns the timeout caveat for each service. This
|
||||
// will determine if and when service access can expire.
|
||||
ServiceTimeouts(context.Context, ...lsat.Service) ([]lsat.Caveat,
|
||||
ServiceTimeouts(context.Context, ...l402.Service) ([]l402.Caveat,
|
||||
error)
|
||||
}
|
||||
|
||||
// Config packages all of the required dependencies to instantiate a new LSAT
|
||||
// Config packages all of the required dependencies to instantiate a new L402
|
||||
// mint.
|
||||
type Config struct {
|
||||
// Secrets is our source for LSAT secrets which will be used for
|
||||
// Secrets is our source for L402 secrets which will be used for
|
||||
// verification purposes.
|
||||
Secrets SecretStore
|
||||
|
||||
// Challenger is our source of new challenges to present requesters of
|
||||
// an LSAT with.
|
||||
// an L402 with.
|
||||
Challenger Challenger
|
||||
|
||||
// ServiceLimiter provides us with how we should limit a new LSAT based
|
||||
// ServiceLimiter provides us with how we should limit a new L402 based
|
||||
// on its target services.
|
||||
ServiceLimiter ServiceLimiter
|
||||
|
||||
@@ -94,27 +94,27 @@ type Config struct {
|
||||
Now func() time.Time
|
||||
}
|
||||
|
||||
// Mint is an entity that is able to mint and verify LSATs for a set of
|
||||
// Mint is an entity that is able to mint and verify L402s for a set of
|
||||
// services.
|
||||
type Mint struct {
|
||||
cfg Config
|
||||
}
|
||||
|
||||
// New creates a new LSAT mint backed by its given dependencies.
|
||||
// New creates a new L402 mint backed by its given dependencies.
|
||||
func New(cfg *Config) *Mint {
|
||||
return &Mint{cfg: *cfg}
|
||||
}
|
||||
|
||||
// MintLSAT mints a new LSAT for the target services.
|
||||
func (m *Mint) MintLSAT(ctx context.Context,
|
||||
services ...lsat.Service) (*macaroon.Macaroon, string, error) {
|
||||
// MintL402 mints a new L402 for the target services.
|
||||
func (m *Mint) MintL402(ctx context.Context,
|
||||
services ...l402.Service) (*macaroon.Macaroon, string, error) {
|
||||
|
||||
// Let the LSAT value as the price of the most expensive of the
|
||||
// Let the L402 value as the price of the most expensive of the
|
||||
// services.
|
||||
price := maximumPrice(services)
|
||||
|
||||
// We'll start by retrieving a new challenge in the form of a Lightning
|
||||
// payment request to present the requester of the LSAT with.
|
||||
// payment request to present the requester of the L402 with.
|
||||
paymentRequest, paymentHash, err := m.cfg.Challenger.NewChallenge(price)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
@@ -122,7 +122,7 @@ func (m *Mint) MintLSAT(ctx context.Context,
|
||||
|
||||
// TODO(wilmer): remove invoice if any of the operations below fail?
|
||||
|
||||
// We can then proceed to mint the LSAT with a unique identifier that is
|
||||
// We can then proceed to mint the L402 with a unique identifier that is
|
||||
// mapped to a unique secret.
|
||||
id, err := createUniqueIdentifier(paymentHash)
|
||||
if err != nil {
|
||||
@@ -143,8 +143,8 @@ func (m *Mint) MintLSAT(ctx context.Context,
|
||||
}
|
||||
|
||||
// Include any restrictions that should be immediately applied to the
|
||||
// LSAT.
|
||||
var caveats []lsat.Caveat
|
||||
// L402.
|
||||
var caveats []l402.Caveat
|
||||
if len(services) > 0 {
|
||||
var err error
|
||||
caveats, err = m.caveatsForServices(ctx, services...)
|
||||
@@ -154,7 +154,7 @@ func (m *Mint) MintLSAT(ctx context.Context,
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
if err := lsat.AddFirstPartyCaveats(mac, caveats...); err != nil {
|
||||
if err := l402.AddFirstPartyCaveats(mac, caveats...); err != nil {
|
||||
// Attempt to revoke the secret to save space.
|
||||
_ = m.cfg.Secrets.RevokeSecret(ctx, idHash)
|
||||
return nil, "", err
|
||||
@@ -165,7 +165,7 @@ func (m *Mint) MintLSAT(ctx context.Context,
|
||||
|
||||
// maximumPrice determines the necessary price to use for a collection
|
||||
// of services.
|
||||
func maximumPrice(services []lsat.Service) int64 {
|
||||
func maximumPrice(services []l402.Service) int64 {
|
||||
var max int64
|
||||
|
||||
for _, service := range services {
|
||||
@@ -177,7 +177,7 @@ func maximumPrice(services []lsat.Service) int64 {
|
||||
return max
|
||||
}
|
||||
|
||||
// createUniqueIdentifier creates a new LSAT identifier bound to a payment hash
|
||||
// createUniqueIdentifier creates a new L402 identifier bound to a payment hash
|
||||
// and a randomly generated ID.
|
||||
func createUniqueIdentifier(paymentHash lntypes.Hash) ([]byte, error) {
|
||||
tokenID, err := generateTokenID()
|
||||
@@ -185,32 +185,32 @@ func createUniqueIdentifier(paymentHash lntypes.Hash) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id := &lsat.Identifier{
|
||||
Version: lsat.LatestVersion,
|
||||
id := &l402.Identifier{
|
||||
Version: l402.LatestVersion,
|
||||
PaymentHash: paymentHash,
|
||||
TokenID: tokenID,
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := lsat.EncodeIdentifier(&buf, id); err != nil {
|
||||
if err := l402.EncodeIdentifier(&buf, id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// generateTokenID generates a new random LSAT ID.
|
||||
func generateTokenID() ([lsat.TokenIDSize]byte, error) {
|
||||
var tokenID [lsat.TokenIDSize]byte
|
||||
// generateTokenID generates a new random L402 ID.
|
||||
func generateTokenID() ([l402.TokenIDSize]byte, error) {
|
||||
var tokenID [l402.TokenIDSize]byte
|
||||
_, err := rand.Read(tokenID[:])
|
||||
return tokenID, err
|
||||
}
|
||||
|
||||
// caveatsForServices returns all of the caveats that should be applied to an
|
||||
// LSAT for the target services.
|
||||
// L402 for the target services.
|
||||
func (m *Mint) caveatsForServices(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
servicesCaveat, err := lsat.NewServicesCaveat(services...)
|
||||
servicesCaveat, err := l402.NewServicesCaveat(services...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -231,34 +231,34 @@ func (m *Mint) caveatsForServices(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caveats := []lsat.Caveat{servicesCaveat}
|
||||
caveats := []l402.Caveat{servicesCaveat}
|
||||
caveats = append(caveats, capabilities...)
|
||||
caveats = append(caveats, constraints...)
|
||||
caveats = append(caveats, timeouts...)
|
||||
return caveats, nil
|
||||
}
|
||||
|
||||
// VerificationParams holds all of the requirements to properly verify an LSAT.
|
||||
// VerificationParams holds all of the requirements to properly verify an L402.
|
||||
type VerificationParams struct {
|
||||
// Macaroon is the macaroon as part of the LSAT we'll attempt to verify.
|
||||
// Macaroon is the macaroon as part of the L402 we'll attempt to verify.
|
||||
Macaroon *macaroon.Macaroon
|
||||
|
||||
// Preimage is the preimage that should correspond to the LSAT's payment
|
||||
// Preimage is the preimage that should correspond to the L402's payment
|
||||
// hash.
|
||||
Preimage lntypes.Preimage
|
||||
|
||||
// TargetService is the target service a user of an LSAT is attempting
|
||||
// TargetService is the target service a user of an L402 is attempting
|
||||
// to access.
|
||||
TargetService string
|
||||
}
|
||||
|
||||
// VerifyLSAT attempts to verify an LSAT with the given parameters.
|
||||
func (m *Mint) VerifyLSAT(ctx context.Context,
|
||||
// VerifyL402 attempts to verify an L402 with the given parameters.
|
||||
func (m *Mint) VerifyL402(ctx context.Context,
|
||||
params *VerificationParams) error {
|
||||
|
||||
// We'll first perform a quick check to determine if a valid preimage
|
||||
// was provided.
|
||||
id, err := lsat.DecodeIdentifier(bytes.NewReader(params.Macaroon.Id()))
|
||||
id, err := l402.DecodeIdentifier(bytes.NewReader(params.Macaroon.Id()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -267,7 +267,7 @@ func (m *Mint) VerifyLSAT(ctx context.Context,
|
||||
id.PaymentHash)
|
||||
}
|
||||
|
||||
// If there was, then we'll ensure the LSAT was minted by us.
|
||||
// If there was, then we'll ensure the L402 was minted by us.
|
||||
secret, err := m.cfg.Secrets.GetSecret(
|
||||
ctx, sha256.Sum256(params.Macaroon.Id()),
|
||||
)
|
||||
@@ -279,21 +279,21 @@ func (m *Mint) VerifyLSAT(ctx context.Context,
|
||||
return err
|
||||
}
|
||||
|
||||
// With the LSAT verified, we'll now inspect its caveats to ensure the
|
||||
// With the L402 verified, we'll now inspect its caveats to ensure the
|
||||
// target service is authorized.
|
||||
caveats := make([]lsat.Caveat, 0, len(rawCaveats))
|
||||
caveats := make([]l402.Caveat, 0, len(rawCaveats))
|
||||
for _, rawCaveat := range rawCaveats {
|
||||
// LSATs can contain third-party caveats that we're not aware
|
||||
// L402s can contain third-party caveats that we're not aware
|
||||
// of, so just skip those.
|
||||
caveat, err := lsat.DecodeCaveat(rawCaveat)
|
||||
caveat, err := l402.DecodeCaveat(rawCaveat)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
caveats = append(caveats, caveat)
|
||||
}
|
||||
return lsat.VerifyCaveats(
|
||||
return l402.VerifyCaveats(
|
||||
caveats,
|
||||
lsat.NewServicesSatisfier(params.TargetService),
|
||||
lsat.NewTimeoutSatisfier(params.TargetService, m.cfg.Now),
|
||||
l402.NewServicesSatisfier(params.TargetService),
|
||||
l402.NewTimeoutSatisfier(params.TargetService, m.cfg.Now),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,21 +7,21 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
testService = lsat.Service{
|
||||
testService = l402.Service{
|
||||
Name: "lightning_loop",
|
||||
Tier: lsat.BaseTier,
|
||||
Tier: l402.BaseTier,
|
||||
}
|
||||
)
|
||||
|
||||
// TestBasicLSAT ensures that an LSAT can only access the services it's
|
||||
// TestBasicL402 ensures that an L402 can only access the services it's
|
||||
// authorized to.
|
||||
func TestBasicLSAT(t *testing.T) {
|
||||
func TestBasicL402(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -32,10 +32,10 @@ func TestBasicLSAT(t *testing.T) {
|
||||
Now: time.Now,
|
||||
})
|
||||
|
||||
// Mint a basic LSAT which is only able to access the given service.
|
||||
macaroon, _, err := mint.MintLSAT(ctx, testService)
|
||||
// Mint a basic L402 which is only able to access the given service.
|
||||
macaroon, _, err := mint.MintL402(ctx, testService)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to mint LSAT: %v", err)
|
||||
t.Fatalf("unable to mint L402: %v", err)
|
||||
}
|
||||
|
||||
params := VerificationParams{
|
||||
@@ -43,22 +43,22 @@ func TestBasicLSAT(t *testing.T) {
|
||||
Preimage: testPreimage,
|
||||
TargetService: testService.Name,
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, ¶ms); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, ¶ms); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
|
||||
// It should not be able to access an unknown service.
|
||||
unknownParams := params
|
||||
unknownParams.TargetService = "unknown"
|
||||
err = mint.VerifyLSAT(ctx, &unknownParams)
|
||||
err = mint.VerifyL402(ctx, &unknownParams)
|
||||
if !strings.Contains(err.Error(), "not authorized") {
|
||||
t.Fatal("expected LSAT to not be authorized")
|
||||
t.Fatal("expected L402 to not be authorized")
|
||||
}
|
||||
}
|
||||
|
||||
// TestAdminLSAT ensures that an admin LSAT (one without a services caveat) is
|
||||
// TestAdminL402 ensures that an admin L402 (one without a services caveat) is
|
||||
// authorized to access any service.
|
||||
func TestAdminLSAT(t *testing.T) {
|
||||
func TestAdminL402(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -69,10 +69,10 @@ func TestAdminLSAT(t *testing.T) {
|
||||
Now: time.Now,
|
||||
})
|
||||
|
||||
// Mint an admin LSAT by not including any services.
|
||||
macaroon, _, err := mint.MintLSAT(ctx)
|
||||
// Mint an admin L402 by not including any services.
|
||||
macaroon, _, err := mint.MintL402(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to mint LSAT: %v", err)
|
||||
t.Fatalf("unable to mint L402: %v", err)
|
||||
}
|
||||
|
||||
// It should be able to access any service as it doesn't have a services
|
||||
@@ -82,13 +82,13 @@ func TestAdminLSAT(t *testing.T) {
|
||||
Preimage: testPreimage,
|
||||
TargetService: testService.Name,
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, params); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, params); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRevokedLSAT ensures that we can no longer verify a revoked LSAT.
|
||||
func TestRevokedLSAT(t *testing.T) {
|
||||
// TestRevokedL402 ensures that we can no longer verify a revoked L402.
|
||||
func TestRevokedL402(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -99,33 +99,33 @@ func TestRevokedLSAT(t *testing.T) {
|
||||
Now: time.Now,
|
||||
})
|
||||
|
||||
// Mint an LSAT and verify it.
|
||||
lsat, _, err := mint.MintLSAT(ctx)
|
||||
// Mint an L402 and verify it.
|
||||
l402, _, err := mint.MintL402(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to mint LSAT: %v", err)
|
||||
t.Fatalf("unable to mint L402: %v", err)
|
||||
}
|
||||
params := &VerificationParams{
|
||||
Macaroon: lsat,
|
||||
Macaroon: l402,
|
||||
Preimage: testPreimage,
|
||||
TargetService: testService.Name,
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, params); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, params); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
|
||||
// Proceed to revoke it. We should no longer be able to verify it after.
|
||||
idHash := sha256.Sum256(lsat.Id())
|
||||
idHash := sha256.Sum256(l402.Id())
|
||||
if err := mint.cfg.Secrets.RevokeSecret(ctx, idHash); err != nil {
|
||||
t.Fatalf("unable to revoke LSAT: %v", err)
|
||||
t.Fatalf("unable to revoke L402: %v", err)
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, params); err != ErrSecretNotFound {
|
||||
if err := mint.VerifyL402(ctx, params); err != ErrSecretNotFound {
|
||||
t.Fatalf("expected ErrSecretNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTamperedLSAT ensures that an LSAT that has been tampered with by
|
||||
// TestTamperedL402 ensures that an L402 that has been tampered with by
|
||||
// modifying its signature results in its verification failing.
|
||||
func TestTamperedLSAT(t *testing.T) {
|
||||
func TestTamperedL402(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -136,21 +136,21 @@ func TestTamperedLSAT(t *testing.T) {
|
||||
Now: time.Now,
|
||||
})
|
||||
|
||||
// Mint a new LSAT and verify it is valid.
|
||||
mac, _, err := mint.MintLSAT(ctx, testService)
|
||||
// Mint a new L402 and verify it is valid.
|
||||
mac, _, err := mint.MintL402(ctx, testService)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to mint LSAT: %v", err)
|
||||
t.Fatalf("unable to mint L402: %v", err)
|
||||
}
|
||||
params := VerificationParams{
|
||||
Macaroon: mac,
|
||||
Preimage: testPreimage,
|
||||
TargetService: testService.Name,
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, ¶ms); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, ¶ms); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
|
||||
// Create a tampered LSAT from the valid one.
|
||||
// Create a tampered L402 from the valid one.
|
||||
macBytes, err := mac.MarshalBinary()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to serialize macaroon: %v", err)
|
||||
@@ -161,19 +161,19 @@ func TestTamperedLSAT(t *testing.T) {
|
||||
t.Fatalf("unable to deserialize macaroon: %v", err)
|
||||
}
|
||||
|
||||
// Attempting to verify the tampered LSAT should fail.
|
||||
// Attempting to verify the tampered L402 should fail.
|
||||
tamperedParams := params
|
||||
tamperedParams.Macaroon = &tampered
|
||||
err = mint.VerifyLSAT(ctx, &tamperedParams)
|
||||
err = mint.VerifyL402(ctx, &tamperedParams)
|
||||
if !strings.Contains(err.Error(), "signature mismatch") {
|
||||
t.Fatal("expected tampered LSAT to be invalid")
|
||||
t.Fatal("expected tampered L402 to be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
// TestDemotedServicesLSAT ensures that an LSAT which originally was authorized
|
||||
// TestDemotedServicesL402 ensures that an L402 which originally was authorized
|
||||
// to access a service, but was then demoted to no longer be the case, is no
|
||||
// longer authorized.
|
||||
func TestDemotedServicesLSAT(t *testing.T) {
|
||||
func TestDemotedServicesL402(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -187,11 +187,11 @@ func TestDemotedServicesLSAT(t *testing.T) {
|
||||
unauthorizedService := testService
|
||||
unauthorizedService.Name = "unauthorized"
|
||||
|
||||
// Mint an LSAT that is able to access two services, one of which will
|
||||
// Mint an L402 that is able to access two services, one of which will
|
||||
// be denied later on.
|
||||
mac, _, err := mint.MintLSAT(ctx, testService, unauthorizedService)
|
||||
mac, _, err := mint.MintL402(ctx, testService, unauthorizedService)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to mint LSAT: %v", err)
|
||||
t.Fatalf("unable to mint L402: %v", err)
|
||||
}
|
||||
|
||||
// It should be able to access both services.
|
||||
@@ -200,41 +200,41 @@ func TestDemotedServicesLSAT(t *testing.T) {
|
||||
Preimage: testPreimage,
|
||||
TargetService: testService.Name,
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, &authorizedParams); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, &authorizedParams); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
unauthorizedParams := VerificationParams{
|
||||
Macaroon: mac,
|
||||
Preimage: testPreimage,
|
||||
TargetService: unauthorizedService.Name,
|
||||
}
|
||||
if err := mint.VerifyLSAT(ctx, &unauthorizedParams); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, &unauthorizedParams); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
|
||||
// Demote the second service by including an additional services caveat
|
||||
// that only includes the first service.
|
||||
services, err := lsat.NewServicesCaveat(testService)
|
||||
services, err := l402.NewServicesCaveat(testService)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create services caveat: %v", err)
|
||||
}
|
||||
err = lsat.AddFirstPartyCaveats(mac, services)
|
||||
err = l402.AddFirstPartyCaveats(mac, services)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to demote LSAT: %v", err)
|
||||
t.Fatalf("unable to demote L402: %v", err)
|
||||
}
|
||||
|
||||
// It should now only be able to access the first, but not the second.
|
||||
if err := mint.VerifyLSAT(ctx, &authorizedParams); err != nil {
|
||||
t.Fatalf("unable to verify LSAT: %v", err)
|
||||
if err := mint.VerifyL402(ctx, &authorizedParams); err != nil {
|
||||
t.Fatalf("unable to verify L402: %v", err)
|
||||
}
|
||||
err = mint.VerifyLSAT(ctx, &unauthorizedParams)
|
||||
err = mint.VerifyL402(ctx, &unauthorizedParams)
|
||||
if !strings.Contains(err.Error(), "not authorized") {
|
||||
t.Fatal("expected macaroon to be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
// TestExpiredServicesLSAT asserts the behavior of the Timeout caveat.
|
||||
func TestExpiredServicesLSAT(t *testing.T) {
|
||||
// TestExpiredServicesL402 asserts the behavior of the Timeout caveat.
|
||||
func TestExpiredServicesL402(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
initialTime := int64(1000)
|
||||
@@ -248,8 +248,8 @@ func TestExpiredServicesLSAT(t *testing.T) {
|
||||
Now: mockTime.now,
|
||||
})
|
||||
|
||||
// Mint a new lsat for accessing a test service.
|
||||
mac, _, err := mint.MintLSAT(ctx, testService)
|
||||
// Mint a new l402 for accessing a test service.
|
||||
mac, _, err := mint.MintL402(ctx, testService)
|
||||
require.NoError(t, err)
|
||||
|
||||
authorizedParams := VerificationParams{
|
||||
@@ -259,22 +259,22 @@ func TestExpiredServicesLSAT(t *testing.T) {
|
||||
}
|
||||
|
||||
// It should be able to access the service if no timeout caveat added.
|
||||
require.NoError(t, mint.VerifyLSAT(ctx, &authorizedParams))
|
||||
require.NoError(t, mint.VerifyL402(ctx, &authorizedParams))
|
||||
|
||||
// Add a timeout caveat that expires in the future.
|
||||
timeout := lsat.NewTimeoutCaveat(testService.Name, 1000, mockTime.now)
|
||||
require.NoError(t, lsat.AddFirstPartyCaveats(mac, timeout))
|
||||
timeout := l402.NewTimeoutCaveat(testService.Name, 1000, mockTime.now)
|
||||
require.NoError(t, l402.AddFirstPartyCaveats(mac, timeout))
|
||||
|
||||
// Make sure that the LSAT is still valid after timeout is added since
|
||||
// Make sure that the L402 is still valid after timeout is added since
|
||||
// the timeout has not yet been reached.
|
||||
require.NoError(t, mint.VerifyLSAT(ctx, &authorizedParams))
|
||||
require.NoError(t, mint.VerifyL402(ctx, &authorizedParams))
|
||||
|
||||
// Force time to pass such that the LSAT should no longer be valid.
|
||||
// Force time to pass such that the L402 should no longer be valid.
|
||||
mockTime.setTime(initialTime + 1001)
|
||||
|
||||
// Assert that the LSAT is no longer valid due to the timeout being
|
||||
// Assert that the L402 is no longer valid due to the timeout being
|
||||
// reached.
|
||||
err = mint.VerifyLSAT(ctx, &authorizedParams)
|
||||
err = mint.VerifyL402(ctx, &authorizedParams)
|
||||
require.Contains(t, err.Error(), "not authorized")
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
)
|
||||
|
||||
@@ -41,15 +41,15 @@ func (d *mockChallenger) NewChallenge(price int64) (string, lntypes.Hash,
|
||||
}
|
||||
|
||||
type mockSecretStore struct {
|
||||
secrets map[[sha256.Size]byte][lsat.SecretSize]byte
|
||||
secrets map[[sha256.Size]byte][l402.SecretSize]byte
|
||||
}
|
||||
|
||||
var _ SecretStore = (*mockSecretStore)(nil)
|
||||
|
||||
func (s *mockSecretStore) NewSecret(ctx context.Context,
|
||||
id [sha256.Size]byte) ([lsat.SecretSize]byte, error) {
|
||||
id [sha256.Size]byte) ([l402.SecretSize]byte, error) {
|
||||
|
||||
var secret [lsat.SecretSize]byte
|
||||
var secret [l402.SecretSize]byte
|
||||
if _, err := rand.Read(secret[:]); err != nil {
|
||||
return secret, err
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func (s *mockSecretStore) NewSecret(ctx context.Context,
|
||||
}
|
||||
|
||||
func (s *mockSecretStore) GetSecret(ctx context.Context,
|
||||
id [sha256.Size]byte) ([lsat.SecretSize]byte, error) {
|
||||
id [sha256.Size]byte) ([l402.SecretSize]byte, error) {
|
||||
|
||||
secret, ok := s.secrets[id]
|
||||
if !ok {
|
||||
@@ -76,30 +76,30 @@ func (s *mockSecretStore) RevokeSecret(ctx context.Context,
|
||||
|
||||
func newMockSecretStore() *mockSecretStore {
|
||||
return &mockSecretStore{
|
||||
secrets: make(map[[sha256.Size]byte][lsat.SecretSize]byte),
|
||||
secrets: make(map[[sha256.Size]byte][l402.SecretSize]byte),
|
||||
}
|
||||
}
|
||||
|
||||
type mockServiceLimiter struct {
|
||||
capabilities map[lsat.Service]lsat.Caveat
|
||||
constraints map[lsat.Service][]lsat.Caveat
|
||||
timeouts map[lsat.Service]lsat.Caveat
|
||||
capabilities map[l402.Service]l402.Caveat
|
||||
constraints map[l402.Service][]l402.Caveat
|
||||
timeouts map[l402.Service]l402.Caveat
|
||||
}
|
||||
|
||||
var _ ServiceLimiter = (*mockServiceLimiter)(nil)
|
||||
|
||||
func newMockServiceLimiter() *mockServiceLimiter {
|
||||
return &mockServiceLimiter{
|
||||
capabilities: make(map[lsat.Service]lsat.Caveat),
|
||||
constraints: make(map[lsat.Service][]lsat.Caveat),
|
||||
timeouts: make(map[lsat.Service]lsat.Caveat),
|
||||
capabilities: make(map[l402.Service]l402.Caveat),
|
||||
constraints: make(map[l402.Service][]l402.Caveat),
|
||||
timeouts: make(map[l402.Service]l402.Caveat),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *mockServiceLimiter) ServiceCapabilities(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
res := make([]lsat.Caveat, 0, len(services))
|
||||
res := make([]l402.Caveat, 0, len(services))
|
||||
for _, service := range services {
|
||||
capabilities, ok := l.capabilities[service]
|
||||
if !ok {
|
||||
@@ -111,9 +111,9 @@ func (l *mockServiceLimiter) ServiceCapabilities(ctx context.Context,
|
||||
}
|
||||
|
||||
func (l *mockServiceLimiter) ServiceConstraints(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
res := make([]lsat.Caveat, 0, len(services))
|
||||
res := make([]l402.Caveat, 0, len(services))
|
||||
for _, service := range services {
|
||||
constraints, ok := l.constraints[service]
|
||||
if !ok {
|
||||
@@ -125,9 +125,9 @@ func (l *mockServiceLimiter) ServiceConstraints(ctx context.Context,
|
||||
}
|
||||
|
||||
func (l *mockServiceLimiter) ServiceTimeouts(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
res := make([]lsat.Caveat, 0, len(services))
|
||||
res := make([]l402.Caveat, 0, len(services))
|
||||
for _, service := range services {
|
||||
timeouts, ok := l.timeouts[service]
|
||||
if !ok {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
@@ -300,12 +300,12 @@ func (p *Proxy) director(req *http.Request) {
|
||||
|
||||
// Make sure we always forward the authorization in the correct/
|
||||
// default format so the backend knows what to do with it.
|
||||
mac, preimage, err := lsat.FromHeader(&req.Header)
|
||||
mac, preimage, err := l402.FromHeader(&req.Header)
|
||||
if err == nil {
|
||||
// It could be that there is no auth information because
|
||||
// none is needed for this particular request. So we
|
||||
// only continue if no error is set.
|
||||
err := lsat.SetHeader(&req.Header, mac, preimage)
|
||||
err := l402.SetHeader(&req.Header, mac, preimage)
|
||||
if err != nil {
|
||||
log.Errorf("could not set header: %v", err)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/proxy"
|
||||
proxytest "github.com/lightninglabs/aperture/proxy/testdata"
|
||||
"github.com/lightningnetwork/lnd/cert"
|
||||
@@ -87,7 +87,7 @@ func (s *helloServer) SayHelloNoAuth(_ context.Context,
|
||||
}
|
||||
|
||||
// TestProxyHTTP tests that the proxy can forward HTTP requests to a backend
|
||||
// service and handle LSAT authentication correctly.
|
||||
// service and handle L402 authentication correctly.
|
||||
func TestProxyHTTP(t *testing.T) {
|
||||
testCases := []*testCase{{
|
||||
name: "no whitelist",
|
||||
@@ -108,7 +108,7 @@ func TestProxyHTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestProxyHTTP tests that the proxy can forward HTTP requests to a backend
|
||||
// service and handle LSAT authentication correctly.
|
||||
// service and handle L402 authentication correctly.
|
||||
func runHTTPTest(t *testing.T, tc *testCase) {
|
||||
// Create a list of services to proxy between.
|
||||
services := []*proxy.Service{{
|
||||
@@ -196,7 +196,7 @@ func runHTTPTest(t *testing.T, tc *testCase) {
|
||||
}
|
||||
|
||||
// TestProxyHTTP tests that the proxy can forward gRPC requests to a backend
|
||||
// service and handle LSAT authentication correctly.
|
||||
// service and handle L402 authentication correctly.
|
||||
func TestProxyGRPC(t *testing.T) {
|
||||
testCases := []*testCase{{
|
||||
name: "no whitelist",
|
||||
@@ -234,7 +234,7 @@ func TestProxyGRPC(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestProxyHTTP tests that the proxy can forward gRPC requests to a backend
|
||||
// service and handle LSAT authentication correctly.
|
||||
// service and handle L402 authentication correctly.
|
||||
func runGRPCTest(t *testing.T, tc *testCase) {
|
||||
// Since gRPC only really works over TLS, we need to generate a
|
||||
// certificate and key pair first.
|
||||
@@ -309,9 +309,9 @@ func runGRPCTest(t *testing.T, tc *testCase) {
|
||||
grpc.Trailer(&captureMetadata),
|
||||
)
|
||||
require.Error(t, err)
|
||||
require.True(t, lsat.IsPaymentRequired(err))
|
||||
require.True(t, l402.IsPaymentRequired(err))
|
||||
|
||||
// We expect the WWW-Authenticate header field to be set to an LSAT
|
||||
// We expect the WWW-Authenticate header field to be set to an L402
|
||||
// auth response.
|
||||
expectedHeaderContent, _ := mockAuth.FreshChallengeHeader(&http.Request{
|
||||
Header: map[string][]string{},
|
||||
|
||||
@@ -34,8 +34,8 @@ const (
|
||||
// Service generically specifies configuration data for backend services to the
|
||||
// Aperture proxy.
|
||||
type Service struct {
|
||||
// Name is the name of the LSAT-enabled service.
|
||||
Name string `long:"name" description:"Name of the LSAT-enabled service"`
|
||||
// Name is the name of the L402-enabled service.
|
||||
Name string `long:"name" description:"Name of the L402-enabled service"`
|
||||
|
||||
// TLSCertPath is the optional path to the service's TLS certificate.
|
||||
TLSCertPath string `long:"tlscertpath" description:"Path to the service's TLS certificate"`
|
||||
@@ -75,7 +75,7 @@ type Service struct {
|
||||
// Timeout is an optional value that indicates in how many seconds the
|
||||
// service's caveat should time out relative to the time of creation. So
|
||||
// if a value of 100 is set, then the timeout will be 100 seconds
|
||||
// after creation of the LSAT.
|
||||
// after creation of the L402.
|
||||
Timeout int64 `long:"timeout" description:"An integer value that indicates the number of seconds until the service access expires"`
|
||||
|
||||
// Capabilities is the list of capabilities authorized for the service
|
||||
@@ -87,9 +87,9 @@ type Service struct {
|
||||
// correspond to the caveat's condition.
|
||||
Constraints map[string]string `long:"constraints" description:"The service constraints to enforce at the base tier"`
|
||||
|
||||
// Price is the custom LSAT value in satoshis to be used for the
|
||||
// Price is the custom L402 value in satoshis to be used for the
|
||||
// service's endpoint.
|
||||
Price int64 `long:"price" description:"Static LSAT value in satoshis to be used for this service"`
|
||||
Price int64 `long:"price" description:"Static L402 value in satoshis to be used for this service"`
|
||||
|
||||
// DynamicPrice holds the config options needed for initialising
|
||||
// the pricer if a gPRC server is to be used for price data.
|
||||
@@ -99,7 +99,7 @@ type Service struct {
|
||||
// are matched against the path of the URL of a request. If the request
|
||||
// URL matches any of those regular expressions, the call is treated as
|
||||
// if Auth was set to "off". This allows certain RPC methods to not
|
||||
// require an LSAT token. E.g. the path for a gRPC call looks like this:
|
||||
// require an L402 token. E.g. the path for a gRPC call looks like this:
|
||||
// /package_name.ServiceName/MethodName
|
||||
AuthWhitelistPaths []string `long:"authwhitelistpaths" description:"List of regular expressions for paths that don't require authentication'"`
|
||||
|
||||
@@ -217,7 +217,7 @@ func prepareServices(services []*Service) error {
|
||||
// satoshi is to be used.
|
||||
switch {
|
||||
case service.Price == 0:
|
||||
log.Debugf("Using default LSAT price of %v satoshis for "+
|
||||
log.Debugf("Using default L402 price of %v satoshis for "+
|
||||
"service %s.", defaultServicePrice, service.Name)
|
||||
service.Price = defaultServicePrice
|
||||
case service.Price < 0:
|
||||
|
||||
@@ -139,11 +139,11 @@ services:
|
||||
# but would not have any effect without additional support added.
|
||||
"valid_until": 1682483169
|
||||
|
||||
# a caveat will be added that expires the LSAT after this many seconds,
|
||||
# a caveat will be added that expires the L402 after this many seconds,
|
||||
# 31557600 = 1 year.
|
||||
timeout: 31557600
|
||||
|
||||
# The LSAT value in satoshis for the service. It is ignored if
|
||||
# The L402 value in satoshis for the service. It is ignored if
|
||||
# dynamicprice.enabled is set to true.
|
||||
price: 0
|
||||
|
||||
|
||||
26
secrets.go
26
secrets.go
@@ -8,18 +8,18 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
// secretsPrefix is the key we'll use to prefix all LSAT identifiers
|
||||
// secretsPrefix is the key we'll use to prefix all L402 identifiers
|
||||
// with when storing secrets in an etcd cluster.
|
||||
secretsPrefix = "secrets"
|
||||
)
|
||||
|
||||
// idKey returns the full key to store in the database for an LSAT identifier.
|
||||
// idKey returns the full key to store in the database for an L402 identifier.
|
||||
// The identifier is hex-encoded in order to prevent conflicts with the etcd key
|
||||
// delimeter.
|
||||
//
|
||||
@@ -32,7 +32,7 @@ func idKey(id [sha256.Size]byte) string {
|
||||
)
|
||||
}
|
||||
|
||||
// secretStore is a store of LSAT secrets backed by an etcd cluster.
|
||||
// secretStore is a store of L402 secrets backed by an etcd cluster.
|
||||
type secretStore struct {
|
||||
*clientv3.Client
|
||||
}
|
||||
@@ -40,7 +40,7 @@ type secretStore struct {
|
||||
// A compile-time constraint to ensure secretStore implements mint.SecretStore.
|
||||
var _ mint.SecretStore = (*secretStore)(nil)
|
||||
|
||||
// newSecretStore instantiates a new LSAT secrets store backed by an etcd
|
||||
// newSecretStore instantiates a new L402 secrets store backed by an etcd
|
||||
// cluster.
|
||||
func newSecretStore(client *clientv3.Client) *secretStore {
|
||||
return &secretStore{Client: client}
|
||||
@@ -49,9 +49,9 @@ func newSecretStore(client *clientv3.Client) *secretStore {
|
||||
// NewSecret creates a new cryptographically random secret which is keyed by the
|
||||
// given hash.
|
||||
func (s *secretStore) NewSecret(ctx context.Context,
|
||||
id [sha256.Size]byte) ([lsat.SecretSize]byte, error) {
|
||||
id [sha256.Size]byte) ([l402.SecretSize]byte, error) {
|
||||
|
||||
var secret [lsat.SecretSize]byte
|
||||
var secret [l402.SecretSize]byte
|
||||
if _, err := rand.Read(secret[:]); err != nil {
|
||||
return secret, err
|
||||
}
|
||||
@@ -63,21 +63,21 @@ func (s *secretStore) NewSecret(ctx context.Context,
|
||||
// GetSecret returns the cryptographically random secret that corresponds to the
|
||||
// given hash. If there is no secret, then mint.ErrSecretNotFound is returned.
|
||||
func (s *secretStore) GetSecret(ctx context.Context,
|
||||
id [sha256.Size]byte) ([lsat.SecretSize]byte, error) {
|
||||
id [sha256.Size]byte) ([l402.SecretSize]byte, error) {
|
||||
|
||||
resp, err := s.Get(ctx, idKey(id))
|
||||
if err != nil {
|
||||
return [lsat.SecretSize]byte{}, err
|
||||
return [l402.SecretSize]byte{}, err
|
||||
}
|
||||
if len(resp.Kvs) == 0 {
|
||||
return [lsat.SecretSize]byte{}, mint.ErrSecretNotFound
|
||||
return [l402.SecretSize]byte{}, mint.ErrSecretNotFound
|
||||
}
|
||||
if len(resp.Kvs[0].Value) != lsat.SecretSize {
|
||||
return [lsat.SecretSize]byte{}, fmt.Errorf("invalid secret "+
|
||||
if len(resp.Kvs[0].Value) != l402.SecretSize {
|
||||
return [l402.SecretSize]byte{}, fmt.Errorf("invalid secret "+
|
||||
"size %v", len(resp.Kvs[0].Value))
|
||||
}
|
||||
|
||||
var secret [lsat.SecretSize]byte
|
||||
var secret [l402.SecretSize]byte
|
||||
copy(secret[:], resp.Kvs[0].Value)
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/server/v3/embed"
|
||||
@@ -64,7 +64,7 @@ func etcdSetup(t *testing.T) (*clientv3.Client, func()) {
|
||||
// identifier exists in the store. If it exists, its value is compared against
|
||||
// the expected secret.
|
||||
func assertSecretExists(t *testing.T, store *secretStore, id [sha256.Size]byte,
|
||||
expSecret *[lsat.SecretSize]byte) {
|
||||
expSecret *[l402.SecretSize]byte) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
|
||||
36
services.go
36
services.go
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/aperture/l402"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightninglabs/aperture/proxy"
|
||||
)
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
//
|
||||
// TODO(wilmer): use etcd instead.
|
||||
type staticServiceLimiter struct {
|
||||
capabilities map[lsat.Service]lsat.Caveat
|
||||
constraints map[lsat.Service][]lsat.Caveat
|
||||
timeouts map[lsat.Service]lsat.Caveat
|
||||
capabilities map[l402.Service]l402.Caveat
|
||||
constraints map[l402.Service][]l402.Caveat
|
||||
timeouts map[l402.Service]l402.Caveat
|
||||
}
|
||||
|
||||
// A compile-time constraint to ensure staticServiceLimiter implements
|
||||
@@ -27,30 +27,30 @@ var _ mint.ServiceLimiter = (*staticServiceLimiter)(nil)
|
||||
func newStaticServiceLimiter(
|
||||
proxyServices []*proxy.Service) *staticServiceLimiter {
|
||||
|
||||
capabilities := make(map[lsat.Service]lsat.Caveat)
|
||||
constraints := make(map[lsat.Service][]lsat.Caveat)
|
||||
timeouts := make(map[lsat.Service]lsat.Caveat)
|
||||
capabilities := make(map[l402.Service]l402.Caveat)
|
||||
constraints := make(map[l402.Service][]l402.Caveat)
|
||||
timeouts := make(map[l402.Service]l402.Caveat)
|
||||
|
||||
for _, proxyService := range proxyServices {
|
||||
s := lsat.Service{
|
||||
s := l402.Service{
|
||||
Name: proxyService.Name,
|
||||
Tier: lsat.BaseTier,
|
||||
Tier: l402.BaseTier,
|
||||
Price: proxyService.Price,
|
||||
}
|
||||
|
||||
if proxyService.Timeout > 0 {
|
||||
timeouts[s] = lsat.NewTimeoutCaveat(
|
||||
timeouts[s] = l402.NewTimeoutCaveat(
|
||||
proxyService.Name,
|
||||
proxyService.Timeout,
|
||||
time.Now,
|
||||
)
|
||||
}
|
||||
|
||||
capabilities[s] = lsat.NewCapabilitiesCaveat(
|
||||
capabilities[s] = l402.NewCapabilitiesCaveat(
|
||||
proxyService.Name, proxyService.Capabilities,
|
||||
)
|
||||
for cond, value := range proxyService.Constraints {
|
||||
caveat := lsat.Caveat{Condition: cond, Value: value}
|
||||
caveat := l402.Caveat{Condition: cond, Value: value}
|
||||
constraints[s] = append(constraints[s], caveat)
|
||||
}
|
||||
}
|
||||
@@ -65,9 +65,9 @@ func newStaticServiceLimiter(
|
||||
// ServiceCapabilities returns the capabilities caveats for each service. This
|
||||
// determines which capabilities of each service can be accessed.
|
||||
func (l *staticServiceLimiter) ServiceCapabilities(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
res := make([]lsat.Caveat, 0, len(services))
|
||||
res := make([]l402.Caveat, 0, len(services))
|
||||
for _, service := range services {
|
||||
capabilities, ok := l.capabilities[service]
|
||||
if !ok {
|
||||
@@ -82,9 +82,9 @@ func (l *staticServiceLimiter) ServiceCapabilities(ctx context.Context,
|
||||
// ServiceConstraints returns the constraints for each service. This enforces
|
||||
// additional constraints on a particular service/service capability.
|
||||
func (l *staticServiceLimiter) ServiceConstraints(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
res := make([]lsat.Caveat, 0, len(services))
|
||||
res := make([]l402.Caveat, 0, len(services))
|
||||
for _, service := range services {
|
||||
constraints, ok := l.constraints[service]
|
||||
if !ok {
|
||||
@@ -99,9 +99,9 @@ func (l *staticServiceLimiter) ServiceConstraints(ctx context.Context,
|
||||
// ServiceTimeouts returns the timeout caveat for each service. This enforces
|
||||
// an expiration time for service access if enabled.
|
||||
func (l *staticServiceLimiter) ServiceTimeouts(ctx context.Context,
|
||||
services ...lsat.Service) ([]lsat.Caveat, error) {
|
||||
services ...l402.Service) ([]l402.Caveat, error) {
|
||||
|
||||
res := make([]lsat.Caveat, 0, len(services))
|
||||
res := make([]l402.Caveat, 0, len(services))
|
||||
for _, service := range services {
|
||||
timeout, ok := l.timeouts[service]
|
||||
if !ok {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>LSAT proxy demo page</title>
|
||||
<title>L402 proxy demo page</title>
|
||||
<style>
|
||||
.row:after {
|
||||
content: "";
|
||||
|
||||
Reference in New Issue
Block a user