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:
Boris Nagaev
2024-04-15 13:14:51 -03:00
parent 208798569b
commit a4431801ef
38 changed files with 353 additions and 353 deletions

View File

@@ -47,7 +47,7 @@ import (
const ( const (
// topLevelKey is the top level key for an etcd cluster where we'll // 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" topLevelKey = "lsat/proxy"
// etcdKeyDelimeter is the delimeter we'll use for all etcd keys to // 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), ServiceLimiter: newStaticServiceLimiter(cfg.Services),
Now: time.Now, Now: time.Now,
}) })
authenticator := auth.NewLsatAuthenticator(minter, challenger) authenticator := auth.NewL402Authenticator(minter, challenger)
// By default the static file server only returns 404 answers for // By default the static file server only returns 404 answers for
// security reasons. Serving files from the staticRoot directory has to // security reasons. Serving files from the staticRoot directory has to

View File

@@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"github.com/lightninglabs/aperture/aperturedb/sqlc" "github.com/lightninglabs/aperture/aperturedb/sqlc"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
"github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/clock"
) )
@@ -81,11 +81,11 @@ func NewSecretsStore(db BatchedSecretsDB) *SecretsStore {
// NewSecret creates a new cryptographically random secret which is // NewSecret creates a new cryptographically random secret which is
// keyed by the given hash. // keyed by the given hash.
func (s *SecretsStore) NewSecret(ctx context.Context, 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 { if _, err := rand.Read(secret[:]); err != nil {
return [lsat.SecretSize]byte{}, err return [l402.SecretSize]byte{}, err
} }
var writeTxOpts SecretsDBTxOptions var writeTxOpts SecretsDBTxOptions
@@ -103,7 +103,7 @@ func (s *SecretsStore) NewSecret(ctx context.Context,
}) })
if err != nil { 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) "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 // corresponds to the given hash. If there is no secret, then
// ErrSecretNotFound is returned. // ErrSecretNotFound is returned.
func (s *SecretsStore) GetSecret(ctx context.Context, 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() readOpts := NewSecretsDBReadTx()
err := s.db.ExecTx(ctx, &readOpts, func(db SecretsDB) error { err := s.db.ExecTx(ctx, &readOpts, func(db SecretsDB) error {
secretRow, err := db.GetSecretByHash(ctx, hash[:]) secretRow, err := db.GetSecretByHash(ctx, hash[:])
@@ -134,7 +134,7 @@ func (s *SecretsStore) GetSecret(ctx context.Context,
}) })
if err != nil { 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) "secret for hash(%x): %w", hash, err)
} }

View File

@@ -6,28 +6,28 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
"github.com/lightningnetwork/lnd/lnrpc" "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. // authenticate requests.
type LsatAuthenticator struct { type L402Authenticator struct {
minter Minter minter Minter
checker InvoiceChecker checker InvoiceChecker
} }
// A compile time flag to ensure the LsatAuthenticator satisfies the // A compile time flag to ensure the L402Authenticator satisfies the
// Authenticator interface. // Authenticator interface.
var _ Authenticator = (*LsatAuthenticator)(nil) var _ Authenticator = (*L402Authenticator)(nil)
// NewLsatAuthenticator creates a new authenticator that authenticates requests // NewL402Authenticator creates a new authenticator that authenticates requests
// based on LSAT tokens. // based on L402 tokens.
func NewLsatAuthenticator(minter Minter, func NewL402Authenticator(minter Minter,
checker InvoiceChecker) *LsatAuthenticator { checker InvoiceChecker) *L402Authenticator {
return &LsatAuthenticator{ return &L402Authenticator{
minter: minter, minter: minter,
checker: checker, checker: checker,
} }
@@ -37,11 +37,11 @@ func NewLsatAuthenticator(minter Minter,
// to a given backend service. // to a given backend service.
// //
// NOTE: This is part of the Authenticator interface. // 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 // Try reading the macaroon and preimage from the HTTP header. This can
// be in different header fields depending on the implementation and/or // be in different header fields depending on the implementation and/or
// protocol. // protocol.
mac, preimage, err := lsat.FromHeader(header) mac, preimage, err := l402.FromHeader(header)
if err != nil { if err != nil {
log.Debugf("Deny: %v", err) log.Debugf("Deny: %v", err)
return false return false
@@ -52,9 +52,9 @@ func (l *LsatAuthenticator) Accept(header *http.Header, serviceName string) bool
Preimage: preimage, Preimage: preimage,
TargetService: serviceName, TargetService: serviceName,
} }
err = l.minter.VerifyLSAT(context.Background(), verificationParams) err = l.minter.VerifyL402(context.Background(), verificationParams)
if err != nil { if err != nil {
log.Debugf("Deny: LSAT validation failed: %v", err) log.Debugf("Deny: L402 validation failed: %v", err)
return false return false
} }
@@ -75,24 +75,24 @@ func (l *LsatAuthenticator) Accept(header *http.Header, serviceName string) bool
// complete. // complete.
// //
// NOTE: This is part of the Authenticator interface. // 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) { serviceName string, servicePrice int64) (http.Header, error) {
service := lsat.Service{ service := l402.Service{
Name: serviceName, Name: serviceName,
Tier: lsat.BaseTier, Tier: l402.BaseTier,
Price: servicePrice, Price: servicePrice,
} }
mac, paymentRequest, err := l.minter.MintLSAT( mac, paymentRequest, err := l.minter.MintL402(
context.Background(), service, context.Background(), service,
) )
if err != nil { if err != nil {
log.Errorf("Error minting LSAT: %v", err) log.Errorf("Error minting L402: %v", err)
return nil, err return nil, err
} }
macBytes, err := mac.MarshalBinary() macBytes, err := mac.MarshalBinary()
if err != nil { 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\"", str := fmt.Sprintf("LSAT macaroon=\"%s\", invoice=\"%s\"",

View File

@@ -8,7 +8,7 @@ import (
"testing" "testing"
"github.com/lightninglabs/aperture/auth" "github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"gopkg.in/macaroon.v2" "gopkg.in/macaroon.v2"
) )
@@ -21,8 +21,8 @@ func createDummyMacHex(preimage string) string {
if err != nil { if err != nil {
panic(err) panic(err)
} }
preimageCaveat := lsat.Caveat{Condition: lsat.PreimageKey, Value: preimage} preimageCaveat := l402.Caveat{Condition: l402.PreimageKey, Value: preimage}
err = lsat.AddFirstPartyCaveats(dummyMac, preimageCaveat) err = l402.AddFirstPartyCaveats(dummyMac, preimageCaveat)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -33,9 +33,9 @@ func createDummyMacHex(preimage string) string {
return hex.EncodeToString(macBytes) 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. // headers and the tokens contained in them.
func TestLsatAuthenticator(t *testing.T) { func TestL402Authenticator(t *testing.T) {
var ( var (
testPreimage = "49349dfea4abed3cd14f6d356afa83de" + testPreimage = "49349dfea4abed3cd14f6d356afa83de" +
"9787b609f088c8df09bacc7b4bd21b39" "9787b609f088c8df09bacc7b4bd21b39"
@@ -65,21 +65,21 @@ func TestLsatAuthenticator(t *testing.T) {
{ {
id: "empty auth header", id: "empty auth header",
header: &http.Header{ header: &http.Header{
lsat.HeaderAuthorization: []string{}, l402.HeaderAuthorization: []string{},
}, },
result: false, result: false,
}, },
{ {
id: "zero length auth header", id: "zero length auth header",
header: &http.Header{ header: &http.Header{
lsat.HeaderAuthorization: []string{""}, l402.HeaderAuthorization: []string{""},
}, },
result: false, result: false,
}, },
{ {
id: "invalid auth header", id: "invalid auth header",
header: &http.Header{ header: &http.Header{
lsat.HeaderAuthorization: []string{ l402.HeaderAuthorization: []string{
"foo", "foo",
}, },
}, },
@@ -88,21 +88,21 @@ func TestLsatAuthenticator(t *testing.T) {
{ {
id: "invalid macaroon metadata header", id: "invalid macaroon metadata header",
header: &http.Header{ header: &http.Header{
lsat.HeaderMacaroonMD: []string{"foo"}, l402.HeaderMacaroonMD: []string{"foo"},
}, },
result: false, result: false,
}, },
{ {
id: "invalid macaroon header", id: "invalid macaroon header",
header: &http.Header{ header: &http.Header{
lsat.HeaderMacaroon: []string{"foo"}, l402.HeaderMacaroon: []string{"foo"},
}, },
result: false, result: false,
}, },
{ {
id: "valid auth header", id: "valid auth header",
header: &http.Header{ header: &http.Header{
lsat.HeaderAuthorization: []string{ l402.HeaderAuthorization: []string{
"LSAT " + testMacBase64 + ":" + "LSAT " + testMacBase64 + ":" +
testPreimage, testPreimage,
}, },
@@ -112,7 +112,7 @@ func TestLsatAuthenticator(t *testing.T) {
{ {
id: "valid macaroon metadata header", id: "valid macaroon metadata header",
header: &http.Header{ header: &http.Header{
lsat.HeaderMacaroonMD: []string{ l402.HeaderMacaroonMD: []string{
testMacHex, testMacHex,
}}, }},
result: true, result: true,
@@ -120,7 +120,7 @@ func TestLsatAuthenticator(t *testing.T) {
{ {
id: "valid macaroon header", id: "valid macaroon header",
header: &http.Header{ header: &http.Header{
lsat.HeaderMacaroon: []string{ l402.HeaderMacaroon: []string{
testMacHex, testMacHex,
}, },
}, },
@@ -129,7 +129,7 @@ func TestLsatAuthenticator(t *testing.T) {
{ {
id: "valid macaroon header, wrong invoice state", id: "valid macaroon header, wrong invoice state",
header: &http.Header{ header: &http.Header{
lsat.HeaderMacaroon: []string{ l402.HeaderMacaroon: []string{
testMacHex, testMacHex,
}, },
}, },
@@ -140,7 +140,7 @@ func TestLsatAuthenticator(t *testing.T) {
) )
c := &mockChecker{} c := &mockChecker{}
a := auth.NewLsatAuthenticator(&mockMint{}, c) a := auth.NewL402Authenticator(&mockMint{}, c)
for _, testCase := range headerTests { for _, testCase := range headerTests {
c.err = testCase.checkErr c.err = testCase.checkErr
result := a.Accept(testCase.header, "test") result := a.Accept(testCase.header, "test")

View File

@@ -5,7 +5,7 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
@@ -30,14 +30,14 @@ type Authenticator interface {
FreshChallengeHeader(*http.Request, string, int64) (http.Header, error) 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. // services.
type Minter interface { type Minter interface {
// MintLSAT mints a new LSAT for the target services. // MintL402 mints a new L402 for the target services.
MintLSAT(context.Context, ...lsat.Service) (*macaroon.Macaroon, string, error) MintL402(context.Context, ...l402.Service) (*macaroon.Macaroon, string, error)
// VerifyLSAT attempts to verify an LSAT with the given parameters. // VerifyL402 attempts to verify an L402 with the given parameters.
VerifyLSAT(context.Context, *mint.VerificationParams) error VerifyL402(context.Context, *mint.VerificationParams) error
} }
// InvoiceChecker is an entity that is able to check the status of an invoice, // InvoiceChecker is an entity that is able to check the status of an invoice,

View File

@@ -5,7 +5,7 @@ import (
"time" "time"
"github.com/lightninglabs/aperture/auth" "github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
@@ -17,13 +17,13 @@ type mockMint struct {
var _ auth.Minter = (*mockMint)(nil) var _ auth.Minter = (*mockMint)(nil)
func (m *mockMint) MintLSAT(_ context.Context, func (m *mockMint) MintL402(_ context.Context,
services ...lsat.Service) (*macaroon.Macaroon, string, error) { services ...l402.Service) (*macaroon.Macaroon, string, error) {
return nil, "", nil 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 return nil
} }

View File

@@ -10,7 +10,7 @@ import (
) )
// LNCChallenger is a challenger that uses LNC to connect to an lnd backend to // 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 { type LNCChallenger struct {
lndChallenger *LndChallenger lndChallenger *LndChallenger
nodeConn *lnc.NodeConn nodeConn *lnc.NodeConn
@@ -61,7 +61,7 @@ func (l *LNCChallenger) Stop() {
l.lndChallenger.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. // request (invoice) and the corresponding payment hash.
// //
// NOTE: This is part of the mint.Challenger interface. // NOTE: This is part of the mint.Challenger interface.

View File

@@ -13,7 +13,7 @@ import (
"github.com/lightningnetwork/lnd/lntypes" "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. // payment challenges.
type LndChallenger struct { type LndChallenger struct {
client InvoiceClient client InvoiceClient
@@ -247,7 +247,7 @@ func (l *LndChallenger) Stop() {
l.wg.Wait() 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. // request (invoice) and the corresponding payment hash.
// //
// NOTE: This is part of the mint.Challenger interface. // NOTE: This is part of the mint.Challenger interface.

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"errors" "errors"
@@ -20,10 +20,10 @@ var (
"\"condition=value\"") "\"condition=value\"")
) )
// Caveat is a predicate that can be applied to an LSAT in order to restrict its // Caveat is a predicate that can be applied to an L402 in order to restrict its
// use in some form. Caveats are evaluated during LSAT verification after the // use in some form. Caveats are evaluated during L402 verification after the
// LSAT's signature is verified. The predicate of each caveat must hold true in // L402's signature is verified. The predicate of each caveat must hold true in
// order to successfully validate an LSAT. // order to successfully validate an L402.
type Caveat struct { type Caveat struct {
// Condition serves as a way to identify a caveat and how to satisfy it. // Condition serves as a way to identify a caveat and how to satisfy it.
Condition string Condition string
@@ -92,11 +92,11 @@ func HasCaveat(m *macaroon.Macaroon, cond string) (string, bool) {
return *value, true 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 // A caveat is considered relevant if a satisfier is provided for it, which is
// what we'll use as their evaluation. // 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. // ensure the correctness of each satisfier's SatisfyPrevious.
func VerifyCaveats(caveats []Caveat, satisfiers ...Satisfier) error { func VerifyCaveats(caveats []Caveat, satisfiers ...Satisfier) error {
// Construct a set of our satisfiers to determine which caveats we know // Construct a set of our satisfiers to determine which caveats we know

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"errors" "errors"
@@ -79,7 +79,7 @@ func TestHasCaveat(t *testing.T) {
t.Fatal("found unexpected caveat with unknown condition") 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 // We'll test that we're still able to determine the macaroon contains
// the valid caveat even though there is one that is invalid. // the valid caveat even though there is one that is invalid.
invalidCaveat := []byte("invalid") invalidCaveat := []byte("invalid")

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"context" "context"
@@ -44,12 +44,12 @@ const (
AuthHeader = "WWW-Authenticate" AuthHeader = "WWW-Authenticate"
// DefaultMaxCostSats is the default maximum amount in satoshis that we // 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. // fees.
DefaultMaxCostSats = 1000 DefaultMaxCostSats = 1000
// DefaultMaxRoutingFeeSats is the default maximum routing fee in // 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 DefaultMaxRoutingFeeSats = 10
// PaymentTimeout is the maximum time we allow a payment to take before // PaymentTimeout is the maximum time we allow a payment to take before
@@ -76,7 +76,7 @@ var (
"failure state") "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 // authentication challenges with embedded payment requests. It uses a
// connection to lnd to automatically pay for an authentication token. // connection to lnd to automatically pay for an authentication token.
type ClientInterceptor struct { type ClientInterceptor struct {
@@ -90,7 +90,7 @@ type ClientInterceptor struct {
} }
// NewInterceptor creates a new gRPC client interceptor that uses the provided // 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. // indicated store already contains a usable token.
func NewInterceptor(lnd *lndclient.LndServices, store Store, func NewInterceptor(lnd *lndclient.LndServices, store Store,
rpcCallTimeout time.Duration, maxCost, 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 // 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) rpcCtx, cancel := context.WithTimeout(ctx, i.callTimeout)
defer cancel() defer cancel()
err = invoker(rpcCtx, method, req, reply, cc, iCtx.opts...) err = invoker(rpcCtx, method, req, reply, cc, iCtx.opts...)
@@ -155,7 +155,7 @@ func (i *ClientInterceptor) UnaryInterceptor(ctx context.Context, method string,
return err 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. // token added as an RPC credential.
rpcCtx2, cancel2 := context.WithTimeout(ctx, i.callTimeout) rpcCtx2, cancel2 := context.WithTimeout(ctx, i.callTimeout)
defer cancel2() defer cancel2()
@@ -188,7 +188,7 @@ func (i *ClientInterceptor) StreamInterceptor(ctx context.Context,
} }
// Try establishing the stream now. If anything goes wrong, we only // 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 // 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. // it, so we can't really clamp down on the initial call with a timeout.
stream, err := streamer(ctx, desc, cc, method, iCtx.opts...) stream, err := streamer(ctx, desc, cc, method, iCtx.opts...)
@@ -203,7 +203,7 @@ func (i *ClientInterceptor) StreamInterceptor(ctx context.Context,
return nil, err 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. // as an RPC credential.
return streamer(ctx, desc, cc, method, iCtx.opts...) 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 // this call. We also never send a pending payment to the server since
// we know it's not valid. // we know it's not valid.
case !iCtx.token.isPending(): 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) log.Errorf("Adding macaroon to request failed: %v", err)
return nil, fmt.Errorf("adding macaroon failed: %v", return nil, fmt.Errorf("adding macaroon failed: %v",
err) 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. // We need a way to extract the response headers sent by the server.
// This can only be done through the experimental grpc.Trailer call // This can only be done through the experimental grpc.Trailer call
// option. We execute the request and inspect the error. If it's the // option. We execute the request and inspect the error. If it's the
// LSAT specific payment required error, we might execute the same // L402 specific payment required error, we might execute the same
// method again later with the paid LSAT token. // method again later with the paid L402 token.
iCtx.opts = append(iCtx.opts, grpc.Trailer(iCtx.metadata)) iCtx.opts = append(iCtx.opts, grpc.Trailer(iCtx.metadata))
return iCtx, nil return iCtx, nil
} }
@@ -262,8 +262,8 @@ func (i *ClientInterceptor) handlePayment(iCtx *interceptContext) error {
switch { switch {
// Resume/track a pending payment if it was interrupted for some reason. // Resume/track a pending payment if it was interrupted for some reason.
case iCtx.token != nil && iCtx.token.isPending(): case iCtx.token != nil && iCtx.token.isPending():
log.Infof("Payment of LSAT token is required, resuming/" + log.Infof("Payment of L402 token is required, resuming/" +
"tracking previous payment from pending LSAT token") "tracking previous payment from pending L402 token")
err := i.trackPayment(iCtx.mainCtx, iCtx.token) err := i.trackPayment(iCtx.mainCtx, iCtx.token)
// If the payment failed for good, it will never come back to a // 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. // 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 var err error
iCtx.token, err = i.payLsatToken( iCtx.token, err = i.payL402Token(
iCtx.mainCtx, iCtx.metadata, iCtx.mainCtx, iCtx.metadata,
) )
if err != nil { 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. // We don't have a token yet, try to get a new one.
case iCtx.token == nil: case iCtx.token == nil:
// We don't have a token yet, get a new one. // 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 var err error
iCtx.token, err = i.payLsatToken(iCtx.mainCtx, iCtx.metadata) iCtx.token, err = i.payL402Token(iCtx.mainCtx, iCtx.metadata)
if err != nil { if err != nil {
return err return err
} }
// We have a token and it's valid, nothing more to do here. // We have a token and it's valid, nothing more to do here.
default: 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) log.Errorf("Adding macaroon to request failed: %v", err)
return fmt.Errorf("adding macaroon failed: %v", err) return fmt.Errorf("adding macaroon failed: %v", err)
} }
return nil return nil
} }
// addLsatCredentials adds an LSAT token to the given intercept context. // addL402Credentials adds an L402 token to the given intercept context.
func (i *ClientInterceptor) addLsatCredentials(iCtx *interceptContext) error { func (i *ClientInterceptor) addL402Credentials(iCtx *interceptContext) error {
if iCtx.token == nil { if iCtx.token == nil {
return fmt.Errorf("cannot add nil token to context") return fmt.Errorf("cannot add nil token to context")
} }
@@ -330,10 +330,10 @@ func (i *ClientInterceptor) addLsatCredentials(iCtx *interceptContext) error {
return nil return nil
} }
// payLsatToken reads the payment challenge from the response metadata and tries // payL402Token reads the payment challenge from the response metadata and tries
// to pay the invoice encoded in them, returning a paid LSAT token if // to pay the invoice encoded in them, returning a paid L402 token if
// successful. // successful.
func (i *ClientInterceptor) payLsatToken(ctx context.Context, md *metadata.MD) ( func (i *ClientInterceptor) payL402Token(ctx context.Context, md *metadata.MD) (
*Token, error) { *Token, error) {
// First parse the authentication header that was stored in the // 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. // Check that the charged amount does not exceed our maximum cost.
maxCostMsat := lnwire.NewMSatFromSatoshis(i.maxCost) maxCostMsat := lnwire.NewMSatFromSatoshis(i.maxCost)
if invoice.MilliSat != nil && *invoice.MilliSat > maxCostMsat { 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 "+ "cost of %d msat exceeds configured max cost of %d "+
"msat", *invoice.MilliSat, maxCostMsat) "msat", *invoice.MilliSat, maxCostMsat)
} }

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"context" "context"
@@ -219,7 +219,7 @@ var (
}, },
expectLndCall: false, expectLndCall: false,
expectToken: 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 " + "of 500000 msat exceeds configured max cost of " +
"100000 msat", "100000 msat",
expectBackendCalls: 1, expectBackendCalls: 1,
@@ -262,7 +262,7 @@ func invoker(opts []grpc.CallOption) error {
return backendErr 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. // responses for unary calls and pay the token.
func TestUnaryInterceptor(t *testing.T) { func TestUnaryInterceptor(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout) 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. // responses in streams and pay the token.
func TestStreamInterceptor(t *testing.T) { func TestStreamInterceptor(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout) ctx, cancel := context.WithTimeout(context.Background(), testTimeout)

View File

@@ -1,10 +1,10 @@
package lsat package l402
import ( import (
"context" "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 // 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 // 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 // type string or any other built-in type to avoid collisions between packages

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"context" "context"

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"encoding/base64" "encoding/base64"
@@ -14,15 +14,15 @@ import (
const ( const (
// HeaderAuthorization is the HTTP header field name that is used to // 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" HeaderAuthorization = "Authorization"
// HeaderMacaroonMD is the HTTP header field name that is used to send // 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" HeaderMacaroonMD = "Grpc-Metadata-Macaroon"
// HeaderMacaroon is the HTTP header field name that is used to send the // 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" HeaderMacaroon = "Macaroon"
) )
@@ -34,7 +34,7 @@ var (
// FromHeader tries to extract authentication information from HTTP headers. // FromHeader tries to extract authentication information from HTTP headers.
// There are two supported formats that can be sent in three different header // There are two supported formats that can be sent in three different header
// fields: // fields:
// 1. Authorization: LSAT <macBase64>:<preimageHex> // 1. Authorization: L402 <macBase64>:<preimageHex>
// 2. Grpc-Metadata-Macaroon: <macHex> // 2. Grpc-Metadata-Macaroon: <macHex>
// 3. 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 // 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, func SetHeader(header *http.Header, mac *macaroon.Macaroon,
preimage fmt.Stringer) error { preimage fmt.Stringer) error {

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"encoding/binary" "encoding/binary"
@@ -11,14 +11,14 @@ import (
) )
const ( const (
// LatestVersion is the latest version used for minting new LSATs. // LatestVersion is the latest version used for minting new L402s.
LatestVersion = 0 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. // the root key of the macaroon.
SecretSize = 32 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. // macaroon identifier.
TokenIDSize = 32 TokenIDSize = 32
) )
@@ -29,11 +29,11 @@ var (
byteOrder = binary.BigEndian byteOrder = binary.BigEndian
// ErrUnknownVersion is an error returned when attempting to decode an // ErrUnknownVersion is an error returned when attempting to decode an
// LSAT identifier with an unknown version. // L402 identifier with an unknown version.
ErrUnknownVersion = errors.New("unknown LSAT 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 type TokenID [TokenIDSize]byte
// String returns the hex encoded representation of the token ID as a string. // 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 return id, nil
} }
// Identifier contains the static identifying details of an LSAT. This is // Identifier contains the static identifying details of an L402. This is
// intended to be used as the identifier of the macaroon within an LSAT. // intended to be used as the identifier of the macaroon within an L402.
type Identifier struct { 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 // introduce new fields to the identifier in a backwards-compatible
// manner. // manner.
Version uint16 Version uint16
// PaymentHash is the payment hash linked to an LSAT. Verification of // PaymentHash is the payment hash linked to an L402. Verification of
// an LSAT depends on a valid payment, which is enforced by ensuring a // an L402 depends on a valid payment, which is enforced by ensuring a
// preimage is provided that hashes to our payment hash. // preimage is provided that hashes to our payment hash.
PaymentHash lntypes.Hash PaymentHash lntypes.Hash
// TokenID is the unique identifier of an LSAT. // TokenID is the unique identifier of an L402.
TokenID TokenID 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 { func EncodeIdentifier(w io.Writer, id *Identifier) error {
if err := binary.Write(w, byteOrder, id.Version); err != nil { if err := binary.Write(w, byteOrder, id.Version); err != nil {
return err 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) { func DecodeIdentifier(r io.Reader) (*Identifier, error) {
var version uint16 var version uint16
if err := binary.Read(r, byteOrder, &version); err != nil { if err := binary.Read(r, byteOrder, &version); err != nil {

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"bytes" "bytes"

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"github.com/btcsuite/btclog" "github.com/btcsuite/btclog"

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"fmt" "fmt"
@@ -18,19 +18,19 @@ type Satisfier struct {
// condition can be used multiple times as long as they enforce more // condition can be used multiple times as long as they enforce more
// permissions than the previous. // 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 // 7 more days. We can add another caveat that only allows for 3 more
// days of use and lend it to another party. // days of use and lend it to another party.
SatisfyPrevious func(previous Caveat, current Caveat) error 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 // caveats with the same condition exist, this will only be executed
// once all previous caveats are also satisfied. // once all previous caveats are also satisfied.
SatisfyFinal func(Caveat) error SatisfyFinal func(Caveat) error
} }
// NewServicesSatisfier implements a satisfier to determine whether the target // 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? // TODO(wilmer): Add tier verification?
func NewServicesSatisfier(targetService string) Satisfier { func NewServicesSatisfier(targetService string) Satisfier {
@@ -80,7 +80,7 @@ func NewServicesSatisfier(targetService string) Satisfier {
} }
// NewCapabilitiesSatisfier implements a satisfier to determine whether the // 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, func NewCapabilitiesSatisfier(service string,
targetCapability string) Satisfier { 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 // a service name to set as the condition prefix and currentTimestamp to
// compare against the expiration(s) in the caveats. The expiration time is // compare against the expiration(s) in the caveats. The expiration time is
// retrieved from the caveat values themselves. The satisfier will also make // 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 " + return fmt.Errorf("not authorized to access " +
"service. LSAT has expired") "service. L402 has expired")
}, },
} }
} }

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"fmt" "fmt"

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"bytes" "bytes"
@@ -11,11 +11,11 @@ import (
) )
// ServerInterceptor is a gRPC server interceptor that extracts the token ID // 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{} type ServerInterceptor struct{}
// UnaryInterceptor is an unary gRPC server interceptor that inspects incoming // 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 // 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 // extracted ID is then attached to the request context in a format that is easy
// to extract by request handlers. // 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 // 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 // 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 // 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. // 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) 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) { func tokenFromContext(ctx context.Context) (*TokenID, error) {
md, ok := metadata.FromIncomingContext(ctx) md, ok := metadata.FromIncomingContext(ctx)
if !ok { if !ok {
@@ -97,7 +97,7 @@ func tokenFromContext(ctx context.Context) (*TokenID, error) {
return nil, fmt.Errorf("auth header extraction failed: %v", err) 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())) identifier, err := DecodeIdentifier(bytes.NewBuffer(macaroon.Id()))
if err != nil { if err != nil {
return nil, fmt.Errorf("token ID decoding failed: %v", err) return nil, fmt.Errorf("token ID decoding failed: %v", err)

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"errors" "errors"
@@ -33,26 +33,26 @@ var (
"\"name:tier\"") "\"name:tier\"")
) )
// ServiceTier represents the different possible tiers of an LSAT-enabled // ServiceTier represents the different possible tiers of an L402-enabled
// service. // service.
type ServiceTier uint8 type ServiceTier uint8
const ( const (
// BaseTier is the base tier of an LSAT-enabled service. This tier // BaseTier is the base tier of an L402-enabled service. This tier
// should be used for any new LSATs that are not part of a service tier // should be used for any new L402s that are not part of a service tier
// upgrade. // upgrade.
BaseTier ServiceTier = iota BaseTier ServiceTier = iota
) )
// Service contains the details of an LSAT-enabled service. // Service contains the details of an L402-enabled service.
type Service struct { type Service struct {
// Name is the name of the LSAT-enabled service. // Name is the name of the L402-enabled service.
Name string Name string
// Tier is the tier of the LSAT-enabled service. // Tier is the tier of the L402-enabled service.
Tier ServiceTier Tier ServiceTier
// Price of service LSAT in satoshis. // Price of service L402 in satoshis.
Price int64 Price int64
} }

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"errors" "errors"

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"errors" "errors"
@@ -15,11 +15,11 @@ var (
// storeFileName is the name of the file where we store the final, // storeFileName is the name of the file where we store the final,
// valid, token to. // valid, token to.
storeFileName = "lsat.token" storeFileName = "l402.token"
// storeFileNamePending is the name of the file where we store a pending // storeFileNamePending is the name of the file where we store a pending
// token until it was successfully paid for. // 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 // errNoReplace is the error that is returned if a new token is
// being written to a store that already contains a paid token. // being written to a store that already contains a paid token.
@@ -27,7 +27,7 @@ var (
"new token. " + manualRetryHint) "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 { type Store interface {
// CurrentToken returns the token that is currently contained in the // CurrentToken returns the token that is currently contained in the
// store or an error if there is none. // store or an error if there is none.

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"os" "os"
@@ -12,7 +12,7 @@ import (
func TestFileStore(t *testing.T) { func TestFileStore(t *testing.T) {
t.Parallel() t.Parallel()
tempDirName, err := os.MkdirTemp("", "lsatstore") tempDirName, err := os.MkdirTemp("", "l402store")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@@ -1,4 +1,4 @@
package lsat package l402
import ( import (
"bytes" "bytes"
@@ -17,9 +17,9 @@ var (
zeroPreimage lntypes.Preimage 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 { 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 // Knowing the preimage to this hash is seen as proof of payment by the
// authentication server. // authentication server.
PaymentHash lntypes.Hash PaymentHash lntypes.Hash
@@ -47,7 +47,7 @@ type Token struct {
} }
// tokenFromChallenge parses the parts that are present in the challenge part // 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) { func tokenFromChallenge(baseMac []byte, paymentHash *[32]byte) (*Token, error) {
// First, validate that the macaroon is valid and can be unmarshaled. // First, validate that the macaroon is valid and can be unmarshaled.
mac := &macaroon.Macaroon{} mac := &macaroon.Macaroon{}
@@ -92,11 +92,11 @@ func (t *Token) PaidMacaroon() (*macaroon.Macaroon, error) {
// yet expired. // yet expired.
func (t *Token) IsValid() bool { func (t *Token) IsValid() bool {
// TODO(guggero): Extract and validate from caveat once we add an // TODO(guggero): Extract and validate from caveat once we add an
// expiration date to the LSAT. // expiration date to the L402.
return true 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. // haven't received the preimage yet.
func (t *Token) isPending() bool { func (t *Token) isPending() bool {
return t.Preimage == zeroPreimage return t.Preimage == zeroPreimage

4
log.go
View File

@@ -3,7 +3,7 @@ package aperture
import ( import (
"github.com/btcsuite/btclog" "github.com/btcsuite/btclog"
"github.com/lightninglabs/aperture/auth" "github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/proxy" "github.com/lightninglabs/aperture/proxy"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd"
@@ -27,7 +27,7 @@ func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) {
lnd.SetSubLogger(root, Subsystem, log) lnd.SetSubLogger(root, Subsystem, log)
lnd.AddSubLogger(root, auth.Subsystem, intercept, auth.UseLogger) 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, proxy.Subsystem, intercept, proxy.UseLogger)
lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger) lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger)
} }

View File

@@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"gopkg.in/macaroon.v2" "gopkg.in/macaroon.v2"
) )
@@ -20,8 +20,8 @@ var (
ErrSecretNotFound = errors.New("secret not found") ErrSecretNotFound = errors.New("secret not found")
) )
// Challenger is an interface used to present requesters of LSATs with a // Challenger is an interface used to present requesters of L402s with a
// challenge that must be satisfied before an LSAT can be validated. This // challenge that must be satisfied before an L402 can be validated. This
// challenge takes the form of a Lightning payment request. // challenge takes the form of a Lightning payment request.
type Challenger interface { type Challenger interface {
// NewChallenge returns a new challenge in the form of a Lightning // NewChallenge returns a new challenge in the form of a Lightning
@@ -34,18 +34,18 @@ type Challenger interface {
Stop() Stop()
} }
// SecretStore is the store responsible for storing LSAT secrets. These secrets // SecretStore is the store responsible for storing L402 secrets. These secrets
// are required for proper verification of each minted LSAT. // are required for proper verification of each minted L402.
type SecretStore interface { type SecretStore interface {
// NewSecret creates a new cryptographically random secret which is // NewSecret creates a new cryptographically random secret which is
// keyed by the given hash. // keyed by the given hash.
NewSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte, NewSecret(context.Context, [sha256.Size]byte) ([l402.SecretSize]byte,
error) error)
// GetSecret returns the cryptographically random secret that // GetSecret returns the cryptographically random secret that
// corresponds to the given hash. If there is no secret, then // corresponds to the given hash. If there is no secret, then
// ErrSecretNotFound is returned. // ErrSecretNotFound is returned.
GetSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte, GetSecret(context.Context, [sha256.Size]byte) ([l402.SecretSize]byte,
error) error)
// RevokeSecret removes the cryptographically random secret that // 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 // 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 { type ServiceLimiter interface {
// ServiceCapabilities returns the capabilities caveats for each // ServiceCapabilities returns the capabilities caveats for each
// service. This determines which capabilities of each service can be // service. This determines which capabilities of each service can be
// accessed. // accessed.
ServiceCapabilities(context.Context, ...lsat.Service) ([]lsat.Caveat, ServiceCapabilities(context.Context, ...l402.Service) ([]l402.Caveat,
error) error)
// ServiceConstraints returns the constraints for each service. This // ServiceConstraints returns the constraints for each service. This
// enforces additional constraints on a particular service/service // enforces additional constraints on a particular service/service
// capability. // capability.
ServiceConstraints(context.Context, ...lsat.Service) ([]lsat.Caveat, ServiceConstraints(context.Context, ...l402.Service) ([]l402.Caveat,
error) error)
// ServiceTimeouts returns the timeout caveat for each service. This // ServiceTimeouts returns the timeout caveat for each service. This
// will determine if and when service access can expire. // will determine if and when service access can expire.
ServiceTimeouts(context.Context, ...lsat.Service) ([]lsat.Caveat, ServiceTimeouts(context.Context, ...l402.Service) ([]l402.Caveat,
error) 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. // mint.
type Config struct { 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. // verification purposes.
Secrets SecretStore Secrets SecretStore
// Challenger is our source of new challenges to present requesters of // Challenger is our source of new challenges to present requesters of
// an LSAT with. // an L402 with.
Challenger Challenger 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. // on its target services.
ServiceLimiter ServiceLimiter ServiceLimiter ServiceLimiter
@@ -94,27 +94,27 @@ type Config struct {
Now func() time.Time 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. // services.
type Mint struct { type Mint struct {
cfg Config 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 { func New(cfg *Config) *Mint {
return &Mint{cfg: *cfg} return &Mint{cfg: *cfg}
} }
// MintLSAT mints a new LSAT for the target services. // MintL402 mints a new L402 for the target services.
func (m *Mint) MintLSAT(ctx context.Context, func (m *Mint) MintL402(ctx context.Context,
services ...lsat.Service) (*macaroon.Macaroon, string, error) { 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. // services.
price := maximumPrice(services) price := maximumPrice(services)
// We'll start by retrieving a new challenge in the form of a Lightning // 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) paymentRequest, paymentHash, err := m.cfg.Challenger.NewChallenge(price)
if err != nil { if err != nil {
return nil, "", err 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? // 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. // mapped to a unique secret.
id, err := createUniqueIdentifier(paymentHash) id, err := createUniqueIdentifier(paymentHash)
if err != nil { if err != nil {
@@ -143,8 +143,8 @@ func (m *Mint) MintLSAT(ctx context.Context,
} }
// Include any restrictions that should be immediately applied to the // Include any restrictions that should be immediately applied to the
// LSAT. // L402.
var caveats []lsat.Caveat var caveats []l402.Caveat
if len(services) > 0 { if len(services) > 0 {
var err error var err error
caveats, err = m.caveatsForServices(ctx, services...) caveats, err = m.caveatsForServices(ctx, services...)
@@ -154,7 +154,7 @@ func (m *Mint) MintLSAT(ctx context.Context,
return nil, "", err 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. // Attempt to revoke the secret to save space.
_ = m.cfg.Secrets.RevokeSecret(ctx, idHash) _ = m.cfg.Secrets.RevokeSecret(ctx, idHash)
return nil, "", err return nil, "", err
@@ -165,7 +165,7 @@ func (m *Mint) MintLSAT(ctx context.Context,
// maximumPrice determines the necessary price to use for a collection // maximumPrice determines the necessary price to use for a collection
// of services. // of services.
func maximumPrice(services []lsat.Service) int64 { func maximumPrice(services []l402.Service) int64 {
var max int64 var max int64
for _, service := range services { for _, service := range services {
@@ -177,7 +177,7 @@ func maximumPrice(services []lsat.Service) int64 {
return max 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. // and a randomly generated ID.
func createUniqueIdentifier(paymentHash lntypes.Hash) ([]byte, error) { func createUniqueIdentifier(paymentHash lntypes.Hash) ([]byte, error) {
tokenID, err := generateTokenID() tokenID, err := generateTokenID()
@@ -185,32 +185,32 @@ func createUniqueIdentifier(paymentHash lntypes.Hash) ([]byte, error) {
return nil, err return nil, err
} }
id := &lsat.Identifier{ id := &l402.Identifier{
Version: lsat.LatestVersion, Version: l402.LatestVersion,
PaymentHash: paymentHash, PaymentHash: paymentHash,
TokenID: tokenID, TokenID: tokenID,
} }
var buf bytes.Buffer var buf bytes.Buffer
if err := lsat.EncodeIdentifier(&buf, id); err != nil { if err := l402.EncodeIdentifier(&buf, id); err != nil {
return nil, err return nil, err
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }
// generateTokenID generates a new random LSAT ID. // generateTokenID generates a new random L402 ID.
func generateTokenID() ([lsat.TokenIDSize]byte, error) { func generateTokenID() ([l402.TokenIDSize]byte, error) {
var tokenID [lsat.TokenIDSize]byte var tokenID [l402.TokenIDSize]byte
_, err := rand.Read(tokenID[:]) _, err := rand.Read(tokenID[:])
return tokenID, err return tokenID, err
} }
// caveatsForServices returns all of the caveats that should be applied to an // 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, 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 { if err != nil {
return nil, err return nil, err
} }
@@ -231,34 +231,34 @@ func (m *Mint) caveatsForServices(ctx context.Context,
return nil, err return nil, err
} }
caveats := []lsat.Caveat{servicesCaveat} caveats := []l402.Caveat{servicesCaveat}
caveats = append(caveats, capabilities...) caveats = append(caveats, capabilities...)
caveats = append(caveats, constraints...) caveats = append(caveats, constraints...)
caveats = append(caveats, timeouts...) caveats = append(caveats, timeouts...)
return caveats, nil 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 { 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 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. // hash.
Preimage lntypes.Preimage 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. // to access.
TargetService string TargetService string
} }
// VerifyLSAT attempts to verify an LSAT with the given parameters. // VerifyL402 attempts to verify an L402 with the given parameters.
func (m *Mint) VerifyLSAT(ctx context.Context, func (m *Mint) VerifyL402(ctx context.Context,
params *VerificationParams) error { params *VerificationParams) error {
// We'll first perform a quick check to determine if a valid preimage // We'll first perform a quick check to determine if a valid preimage
// was provided. // was provided.
id, err := lsat.DecodeIdentifier(bytes.NewReader(params.Macaroon.Id())) id, err := l402.DecodeIdentifier(bytes.NewReader(params.Macaroon.Id()))
if err != nil { if err != nil {
return err return err
} }
@@ -267,7 +267,7 @@ func (m *Mint) VerifyLSAT(ctx context.Context,
id.PaymentHash) 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( secret, err := m.cfg.Secrets.GetSecret(
ctx, sha256.Sum256(params.Macaroon.Id()), ctx, sha256.Sum256(params.Macaroon.Id()),
) )
@@ -279,21 +279,21 @@ func (m *Mint) VerifyLSAT(ctx context.Context,
return err 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. // target service is authorized.
caveats := make([]lsat.Caveat, 0, len(rawCaveats)) caveats := make([]l402.Caveat, 0, len(rawCaveats))
for _, rawCaveat := range 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. // of, so just skip those.
caveat, err := lsat.DecodeCaveat(rawCaveat) caveat, err := l402.DecodeCaveat(rawCaveat)
if err != nil { if err != nil {
continue continue
} }
caveats = append(caveats, caveat) caveats = append(caveats, caveat)
} }
return lsat.VerifyCaveats( return l402.VerifyCaveats(
caveats, caveats,
lsat.NewServicesSatisfier(params.TargetService), l402.NewServicesSatisfier(params.TargetService),
lsat.NewTimeoutSatisfier(params.TargetService, m.cfg.Now), l402.NewTimeoutSatisfier(params.TargetService, m.cfg.Now),
) )
} }

View File

@@ -7,21 +7,21 @@ import (
"testing" "testing"
"time" "time"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/macaroon.v2" "gopkg.in/macaroon.v2"
) )
var ( var (
testService = lsat.Service{ testService = l402.Service{
Name: "lightning_loop", 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. // authorized to.
func TestBasicLSAT(t *testing.T) { func TestBasicL402(t *testing.T) {
t.Parallel() t.Parallel()
ctx := context.Background() ctx := context.Background()
@@ -32,10 +32,10 @@ func TestBasicLSAT(t *testing.T) {
Now: time.Now, Now: time.Now,
}) })
// Mint a basic LSAT which is only able to access the given service. // Mint a basic L402 which is only able to access the given service.
macaroon, _, err := mint.MintLSAT(ctx, testService) macaroon, _, err := mint.MintL402(ctx, testService)
if err != nil { if err != nil {
t.Fatalf("unable to mint LSAT: %v", err) t.Fatalf("unable to mint L402: %v", err)
} }
params := VerificationParams{ params := VerificationParams{
@@ -43,22 +43,22 @@ func TestBasicLSAT(t *testing.T) {
Preimage: testPreimage, Preimage: testPreimage,
TargetService: testService.Name, TargetService: testService.Name,
} }
if err := mint.VerifyLSAT(ctx, &params); err != nil { if err := mint.VerifyL402(ctx, &params); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) t.Fatalf("unable to verify L402: %v", err)
} }
// It should not be able to access an unknown service. // It should not be able to access an unknown service.
unknownParams := params unknownParams := params
unknownParams.TargetService = "unknown" unknownParams.TargetService = "unknown"
err = mint.VerifyLSAT(ctx, &unknownParams) err = mint.VerifyL402(ctx, &unknownParams)
if !strings.Contains(err.Error(), "not authorized") { 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. // authorized to access any service.
func TestAdminLSAT(t *testing.T) { func TestAdminL402(t *testing.T) {
t.Parallel() t.Parallel()
ctx := context.Background() ctx := context.Background()
@@ -69,10 +69,10 @@ func TestAdminLSAT(t *testing.T) {
Now: time.Now, Now: time.Now,
}) })
// Mint an admin LSAT by not including any services. // Mint an admin L402 by not including any services.
macaroon, _, err := mint.MintLSAT(ctx) macaroon, _, err := mint.MintL402(ctx)
if err != nil { 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 // 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, Preimage: testPreimage,
TargetService: testService.Name, TargetService: testService.Name,
} }
if err := mint.VerifyLSAT(ctx, params); err != nil { if err := mint.VerifyL402(ctx, params); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) t.Fatalf("unable to verify L402: %v", err)
} }
} }
// TestRevokedLSAT ensures that we can no longer verify a revoked LSAT. // TestRevokedL402 ensures that we can no longer verify a revoked L402.
func TestRevokedLSAT(t *testing.T) { func TestRevokedL402(t *testing.T) {
t.Parallel() t.Parallel()
ctx := context.Background() ctx := context.Background()
@@ -99,33 +99,33 @@ func TestRevokedLSAT(t *testing.T) {
Now: time.Now, Now: time.Now,
}) })
// Mint an LSAT and verify it. // Mint an L402 and verify it.
lsat, _, err := mint.MintLSAT(ctx) l402, _, err := mint.MintL402(ctx)
if err != nil { if err != nil {
t.Fatalf("unable to mint LSAT: %v", err) t.Fatalf("unable to mint L402: %v", err)
} }
params := &VerificationParams{ params := &VerificationParams{
Macaroon: lsat, Macaroon: l402,
Preimage: testPreimage, Preimage: testPreimage,
TargetService: testService.Name, TargetService: testService.Name,
} }
if err := mint.VerifyLSAT(ctx, params); err != nil { if err := mint.VerifyL402(ctx, params); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) t.Fatalf("unable to verify L402: %v", err)
} }
// Proceed to revoke it. We should no longer be able to verify it after. // 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 { 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) 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. // modifying its signature results in its verification failing.
func TestTamperedLSAT(t *testing.T) { func TestTamperedL402(t *testing.T) {
t.Parallel() t.Parallel()
ctx := context.Background() ctx := context.Background()
@@ -136,21 +136,21 @@ func TestTamperedLSAT(t *testing.T) {
Now: time.Now, Now: time.Now,
}) })
// Mint a new LSAT and verify it is valid. // Mint a new L402 and verify it is valid.
mac, _, err := mint.MintLSAT(ctx, testService) mac, _, err := mint.MintL402(ctx, testService)
if err != nil { if err != nil {
t.Fatalf("unable to mint LSAT: %v", err) t.Fatalf("unable to mint L402: %v", err)
} }
params := VerificationParams{ params := VerificationParams{
Macaroon: mac, Macaroon: mac,
Preimage: testPreimage, Preimage: testPreimage,
TargetService: testService.Name, TargetService: testService.Name,
} }
if err := mint.VerifyLSAT(ctx, &params); err != nil { if err := mint.VerifyL402(ctx, &params); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) 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() macBytes, err := mac.MarshalBinary()
if err != nil { if err != nil {
t.Fatalf("unable to serialize macaroon: %v", err) 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) 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 := params
tamperedParams.Macaroon = &tampered tamperedParams.Macaroon = &tampered
err = mint.VerifyLSAT(ctx, &tamperedParams) err = mint.VerifyL402(ctx, &tamperedParams)
if !strings.Contains(err.Error(), "signature mismatch") { 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 // to access a service, but was then demoted to no longer be the case, is no
// longer authorized. // longer authorized.
func TestDemotedServicesLSAT(t *testing.T) { func TestDemotedServicesL402(t *testing.T) {
t.Parallel() t.Parallel()
ctx := context.Background() ctx := context.Background()
@@ -187,11 +187,11 @@ func TestDemotedServicesLSAT(t *testing.T) {
unauthorizedService := testService unauthorizedService := testService
unauthorizedService.Name = "unauthorized" 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. // be denied later on.
mac, _, err := mint.MintLSAT(ctx, testService, unauthorizedService) mac, _, err := mint.MintL402(ctx, testService, unauthorizedService)
if err != nil { 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. // It should be able to access both services.
@@ -200,41 +200,41 @@ func TestDemotedServicesLSAT(t *testing.T) {
Preimage: testPreimage, Preimage: testPreimage,
TargetService: testService.Name, TargetService: testService.Name,
} }
if err := mint.VerifyLSAT(ctx, &authorizedParams); err != nil { if err := mint.VerifyL402(ctx, &authorizedParams); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) t.Fatalf("unable to verify L402: %v", err)
} }
unauthorizedParams := VerificationParams{ unauthorizedParams := VerificationParams{
Macaroon: mac, Macaroon: mac,
Preimage: testPreimage, Preimage: testPreimage,
TargetService: unauthorizedService.Name, TargetService: unauthorizedService.Name,
} }
if err := mint.VerifyLSAT(ctx, &unauthorizedParams); err != nil { if err := mint.VerifyL402(ctx, &unauthorizedParams); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) t.Fatalf("unable to verify L402: %v", err)
} }
// Demote the second service by including an additional services caveat // Demote the second service by including an additional services caveat
// that only includes the first service. // that only includes the first service.
services, err := lsat.NewServicesCaveat(testService) services, err := l402.NewServicesCaveat(testService)
if err != nil { if err != nil {
t.Fatalf("unable to create services caveat: %v", err) t.Fatalf("unable to create services caveat: %v", err)
} }
err = lsat.AddFirstPartyCaveats(mac, services) err = l402.AddFirstPartyCaveats(mac, services)
if err != nil { 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. // It should now only be able to access the first, but not the second.
if err := mint.VerifyLSAT(ctx, &authorizedParams); err != nil { if err := mint.VerifyL402(ctx, &authorizedParams); err != nil {
t.Fatalf("unable to verify LSAT: %v", err) 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") { if !strings.Contains(err.Error(), "not authorized") {
t.Fatal("expected macaroon to be invalid") t.Fatal("expected macaroon to be invalid")
} }
} }
// TestExpiredServicesLSAT asserts the behavior of the Timeout caveat. // TestExpiredServicesL402 asserts the behavior of the Timeout caveat.
func TestExpiredServicesLSAT(t *testing.T) { func TestExpiredServicesL402(t *testing.T) {
t.Parallel() t.Parallel()
initialTime := int64(1000) initialTime := int64(1000)
@@ -248,8 +248,8 @@ func TestExpiredServicesLSAT(t *testing.T) {
Now: mockTime.now, Now: mockTime.now,
}) })
// Mint a new lsat for accessing a test service. // Mint a new l402 for accessing a test service.
mac, _, err := mint.MintLSAT(ctx, testService) mac, _, err := mint.MintL402(ctx, testService)
require.NoError(t, err) require.NoError(t, err)
authorizedParams := VerificationParams{ authorizedParams := VerificationParams{
@@ -259,22 +259,22 @@ func TestExpiredServicesLSAT(t *testing.T) {
} }
// It should be able to access the service if no timeout caveat added. // 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. // Add a timeout caveat that expires in the future.
timeout := lsat.NewTimeoutCaveat(testService.Name, 1000, mockTime.now) timeout := l402.NewTimeoutCaveat(testService.Name, 1000, mockTime.now)
require.NoError(t, lsat.AddFirstPartyCaveats(mac, timeout)) 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. // 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) 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. // reached.
err = mint.VerifyLSAT(ctx, &authorizedParams) err = mint.VerifyL402(ctx, &authorizedParams)
require.Contains(t, err.Error(), "not authorized") require.Contains(t, err.Error(), "not authorized")
} }

View File

@@ -5,7 +5,7 @@ import (
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
) )
@@ -41,15 +41,15 @@ func (d *mockChallenger) NewChallenge(price int64) (string, lntypes.Hash,
} }
type mockSecretStore struct { type mockSecretStore struct {
secrets map[[sha256.Size]byte][lsat.SecretSize]byte secrets map[[sha256.Size]byte][l402.SecretSize]byte
} }
var _ SecretStore = (*mockSecretStore)(nil) var _ SecretStore = (*mockSecretStore)(nil)
func (s *mockSecretStore) NewSecret(ctx context.Context, 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 { if _, err := rand.Read(secret[:]); err != nil {
return secret, err return secret, err
} }
@@ -58,7 +58,7 @@ func (s *mockSecretStore) NewSecret(ctx context.Context,
} }
func (s *mockSecretStore) GetSecret(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] secret, ok := s.secrets[id]
if !ok { if !ok {
@@ -76,30 +76,30 @@ func (s *mockSecretStore) RevokeSecret(ctx context.Context,
func newMockSecretStore() *mockSecretStore { func newMockSecretStore() *mockSecretStore {
return &mockSecretStore{ return &mockSecretStore{
secrets: make(map[[sha256.Size]byte][lsat.SecretSize]byte), secrets: make(map[[sha256.Size]byte][l402.SecretSize]byte),
} }
} }
type mockServiceLimiter struct { type mockServiceLimiter struct {
capabilities map[lsat.Service]lsat.Caveat capabilities map[l402.Service]l402.Caveat
constraints map[lsat.Service][]lsat.Caveat constraints map[l402.Service][]l402.Caveat
timeouts map[lsat.Service]lsat.Caveat timeouts map[l402.Service]l402.Caveat
} }
var _ ServiceLimiter = (*mockServiceLimiter)(nil) var _ ServiceLimiter = (*mockServiceLimiter)(nil)
func newMockServiceLimiter() *mockServiceLimiter { func newMockServiceLimiter() *mockServiceLimiter {
return &mockServiceLimiter{ return &mockServiceLimiter{
capabilities: make(map[lsat.Service]lsat.Caveat), capabilities: make(map[l402.Service]l402.Caveat),
constraints: make(map[lsat.Service][]lsat.Caveat), constraints: make(map[l402.Service][]l402.Caveat),
timeouts: make(map[lsat.Service]lsat.Caveat), timeouts: make(map[l402.Service]l402.Caveat),
} }
} }
func (l *mockServiceLimiter) ServiceCapabilities(ctx context.Context, 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 { for _, service := range services {
capabilities, ok := l.capabilities[service] capabilities, ok := l.capabilities[service]
if !ok { if !ok {
@@ -111,9 +111,9 @@ func (l *mockServiceLimiter) ServiceCapabilities(ctx context.Context,
} }
func (l *mockServiceLimiter) ServiceConstraints(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 { for _, service := range services {
constraints, ok := l.constraints[service] constraints, ok := l.constraints[service]
if !ok { if !ok {
@@ -125,9 +125,9 @@ func (l *mockServiceLimiter) ServiceConstraints(ctx context.Context,
} }
func (l *mockServiceLimiter) ServiceTimeouts(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 { for _, service := range services {
timeouts, ok := l.timeouts[service] timeouts, ok := l.timeouts[service]
if !ok { if !ok {

View File

@@ -12,7 +12,7 @@ import (
"strings" "strings"
"github.com/lightninglabs/aperture/auth" "github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"google.golang.org/grpc/codes" "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/ // Make sure we always forward the authorization in the correct/
// default format so the backend knows what to do with it. // 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 { if err == nil {
// It could be that there is no auth information because // It could be that there is no auth information because
// none is needed for this particular request. So we // none is needed for this particular request. So we
// only continue if no error is set. // only continue if no error is set.
err := lsat.SetHeader(&req.Header, mac, preimage) err := l402.SetHeader(&req.Header, mac, preimage)
if err != nil { if err != nil {
log.Errorf("could not set header: %v", err) log.Errorf("could not set header: %v", err)
} }

View File

@@ -15,7 +15,7 @@ import (
"time" "time"
"github.com/lightninglabs/aperture/auth" "github.com/lightninglabs/aperture/auth"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/proxy" "github.com/lightninglabs/aperture/proxy"
proxytest "github.com/lightninglabs/aperture/proxy/testdata" proxytest "github.com/lightninglabs/aperture/proxy/testdata"
"github.com/lightningnetwork/lnd/cert" "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 // 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) { func TestProxyHTTP(t *testing.T) {
testCases := []*testCase{{ testCases := []*testCase{{
name: "no whitelist", name: "no whitelist",
@@ -108,7 +108,7 @@ func TestProxyHTTP(t *testing.T) {
} }
// TestProxyHTTP tests that the proxy can forward HTTP requests to a backend // 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) { func runHTTPTest(t *testing.T, tc *testCase) {
// Create a list of services to proxy between. // Create a list of services to proxy between.
services := []*proxy.Service{{ 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 // 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) { func TestProxyGRPC(t *testing.T) {
testCases := []*testCase{{ testCases := []*testCase{{
name: "no whitelist", name: "no whitelist",
@@ -234,7 +234,7 @@ func TestProxyGRPC(t *testing.T) {
} }
// TestProxyHTTP tests that the proxy can forward gRPC requests to a backend // 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) { func runGRPCTest(t *testing.T, tc *testCase) {
// Since gRPC only really works over TLS, we need to generate a // Since gRPC only really works over TLS, we need to generate a
// certificate and key pair first. // certificate and key pair first.
@@ -309,9 +309,9 @@ func runGRPCTest(t *testing.T, tc *testCase) {
grpc.Trailer(&captureMetadata), grpc.Trailer(&captureMetadata),
) )
require.Error(t, err) 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. // auth response.
expectedHeaderContent, _ := mockAuth.FreshChallengeHeader(&http.Request{ expectedHeaderContent, _ := mockAuth.FreshChallengeHeader(&http.Request{
Header: map[string][]string{}, Header: map[string][]string{},

View File

@@ -34,8 +34,8 @@ const (
// Service generically specifies configuration data for backend services to the // Service generically specifies configuration data for backend services to the
// Aperture proxy. // Aperture proxy.
type Service struct { type Service struct {
// Name is the name of the LSAT-enabled service. // Name is the name of the L402-enabled service.
Name string `long:"name" description:"Name of the LSAT-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 is the optional path to the service's TLS certificate.
TLSCertPath string `long:"tlscertpath" description:"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 // 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 // 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 // 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"` 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 // Capabilities is the list of capabilities authorized for the service
@@ -87,9 +87,9 @@ type Service struct {
// correspond to the caveat's condition. // correspond to the caveat's condition.
Constraints map[string]string `long:"constraints" description:"The service constraints to enforce at the base tier"` 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. // 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 // DynamicPrice holds the config options needed for initialising
// the pricer if a gPRC server is to be used for price data. // 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 // 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 // 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 // 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 // /package_name.ServiceName/MethodName
AuthWhitelistPaths []string `long:"authwhitelistpaths" description:"List of regular expressions for paths that don't require authentication'"` 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. // satoshi is to be used.
switch { switch {
case service.Price == 0: 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 %s.", defaultServicePrice, service.Name)
service.Price = defaultServicePrice service.Price = defaultServicePrice
case service.Price < 0: case service.Price < 0:

View File

@@ -139,11 +139,11 @@ services:
# but would not have any effect without additional support added. # but would not have any effect without additional support added.
"valid_until": 1682483169 "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. # 31557600 = 1 year.
timeout: 31557600 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. # dynamicprice.enabled is set to true.
price: 0 price: 0

View File

@@ -8,18 +8,18 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
clientv3 "go.etcd.io/etcd/client/v3" clientv3 "go.etcd.io/etcd/client/v3"
) )
var ( 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. // with when storing secrets in an etcd cluster.
secretsPrefix = "secrets" 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 // The identifier is hex-encoded in order to prevent conflicts with the etcd key
// delimeter. // 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 { type secretStore struct {
*clientv3.Client *clientv3.Client
} }
@@ -40,7 +40,7 @@ type secretStore struct {
// A compile-time constraint to ensure secretStore implements mint.SecretStore. // A compile-time constraint to ensure secretStore implements mint.SecretStore.
var _ mint.SecretStore = (*secretStore)(nil) 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. // cluster.
func newSecretStore(client *clientv3.Client) *secretStore { func newSecretStore(client *clientv3.Client) *secretStore {
return &secretStore{Client: client} 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 // NewSecret creates a new cryptographically random secret which is keyed by the
// given hash. // given hash.
func (s *secretStore) NewSecret(ctx context.Context, 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 { if _, err := rand.Read(secret[:]); err != nil {
return secret, err return secret, err
} }
@@ -63,21 +63,21 @@ func (s *secretStore) NewSecret(ctx context.Context,
// GetSecret returns the cryptographically random secret that corresponds to the // GetSecret returns the cryptographically random secret that corresponds to the
// given hash. If there is no secret, then mint.ErrSecretNotFound is returned. // given hash. If there is no secret, then mint.ErrSecretNotFound is returned.
func (s *secretStore) GetSecret(ctx context.Context, 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)) resp, err := s.Get(ctx, idKey(id))
if err != nil { if err != nil {
return [lsat.SecretSize]byte{}, err return [l402.SecretSize]byte{}, err
} }
if len(resp.Kvs) == 0 { 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 { if len(resp.Kvs[0].Value) != l402.SecretSize {
return [lsat.SecretSize]byte{}, fmt.Errorf("invalid secret "+ return [l402.SecretSize]byte{}, fmt.Errorf("invalid secret "+
"size %v", len(resp.Kvs[0].Value)) "size %v", len(resp.Kvs[0].Value))
} }
var secret [lsat.SecretSize]byte var secret [l402.SecretSize]byte
copy(secret[:], resp.Kvs[0].Value) copy(secret[:], resp.Kvs[0].Value)
return secret, nil return secret, nil
} }

View File

@@ -9,7 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
clientv3 "go.etcd.io/etcd/client/v3" clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/server/v3/embed" "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 // identifier exists in the store. If it exists, its value is compared against
// the expected secret. // the expected secret.
func assertSecretExists(t *testing.T, store *secretStore, id [sha256.Size]byte, func assertSecretExists(t *testing.T, store *secretStore, id [sha256.Size]byte,
expSecret *[lsat.SecretSize]byte) { expSecret *[l402.SecretSize]byte) {
t.Helper() t.Helper()

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/aperture/mint" "github.com/lightninglabs/aperture/mint"
"github.com/lightninglabs/aperture/proxy" "github.com/lightninglabs/aperture/proxy"
) )
@@ -13,9 +13,9 @@ import (
// //
// TODO(wilmer): use etcd instead. // TODO(wilmer): use etcd instead.
type staticServiceLimiter struct { type staticServiceLimiter struct {
capabilities map[lsat.Service]lsat.Caveat capabilities map[l402.Service]l402.Caveat
constraints map[lsat.Service][]lsat.Caveat constraints map[l402.Service][]l402.Caveat
timeouts map[lsat.Service]lsat.Caveat timeouts map[l402.Service]l402.Caveat
} }
// A compile-time constraint to ensure staticServiceLimiter implements // A compile-time constraint to ensure staticServiceLimiter implements
@@ -27,30 +27,30 @@ var _ mint.ServiceLimiter = (*staticServiceLimiter)(nil)
func newStaticServiceLimiter( func newStaticServiceLimiter(
proxyServices []*proxy.Service) *staticServiceLimiter { proxyServices []*proxy.Service) *staticServiceLimiter {
capabilities := make(map[lsat.Service]lsat.Caveat) capabilities := make(map[l402.Service]l402.Caveat)
constraints := make(map[lsat.Service][]lsat.Caveat) constraints := make(map[l402.Service][]l402.Caveat)
timeouts := make(map[lsat.Service]lsat.Caveat) timeouts := make(map[l402.Service]l402.Caveat)
for _, proxyService := range proxyServices { for _, proxyService := range proxyServices {
s := lsat.Service{ s := l402.Service{
Name: proxyService.Name, Name: proxyService.Name,
Tier: lsat.BaseTier, Tier: l402.BaseTier,
Price: proxyService.Price, Price: proxyService.Price,
} }
if proxyService.Timeout > 0 { if proxyService.Timeout > 0 {
timeouts[s] = lsat.NewTimeoutCaveat( timeouts[s] = l402.NewTimeoutCaveat(
proxyService.Name, proxyService.Name,
proxyService.Timeout, proxyService.Timeout,
time.Now, time.Now,
) )
} }
capabilities[s] = lsat.NewCapabilitiesCaveat( capabilities[s] = l402.NewCapabilitiesCaveat(
proxyService.Name, proxyService.Capabilities, proxyService.Name, proxyService.Capabilities,
) )
for cond, value := range proxyService.Constraints { 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) constraints[s] = append(constraints[s], caveat)
} }
} }
@@ -65,9 +65,9 @@ func newStaticServiceLimiter(
// ServiceCapabilities returns the capabilities caveats for each service. This // ServiceCapabilities returns the capabilities caveats for each service. This
// determines which capabilities of each service can be accessed. // determines which capabilities of each service can be accessed.
func (l *staticServiceLimiter) ServiceCapabilities(ctx context.Context, 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 { for _, service := range services {
capabilities, ok := l.capabilities[service] capabilities, ok := l.capabilities[service]
if !ok { if !ok {
@@ -82,9 +82,9 @@ func (l *staticServiceLimiter) ServiceCapabilities(ctx context.Context,
// ServiceConstraints returns the constraints for each service. This enforces // ServiceConstraints returns the constraints for each service. This enforces
// additional constraints on a particular service/service capability. // additional constraints on a particular service/service capability.
func (l *staticServiceLimiter) ServiceConstraints(ctx context.Context, 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 { for _, service := range services {
constraints, ok := l.constraints[service] constraints, ok := l.constraints[service]
if !ok { if !ok {
@@ -99,9 +99,9 @@ func (l *staticServiceLimiter) ServiceConstraints(ctx context.Context,
// ServiceTimeouts returns the timeout caveat for each service. This enforces // ServiceTimeouts returns the timeout caveat for each service. This enforces
// an expiration time for service access if enabled. // an expiration time for service access if enabled.
func (l *staticServiceLimiter) ServiceTimeouts(ctx context.Context, 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 { for _, service := range services {
timeout, ok := l.timeouts[service] timeout, ok := l.timeouts[service]
if !ok { if !ok {

View File

@@ -1,6 +1,6 @@
<html> <html>
<head> <head>
<title>LSAT proxy demo page</title> <title>L402 proxy demo page</title>
<style> <style>
.row:after { .row:after {
content: ""; content: "";