mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
Move the MacaroonBaker type to the new macaroons package to avoid import cycles in future.
179 lines
5.4 KiB
Go
179 lines
5.4 KiB
Go
package session
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/lightninglabs/lightning-node-connect/mailbox"
|
|
"github.com/lightninglabs/lightning-terminal/macaroons"
|
|
"gopkg.in/macaroon-bakery.v2/bakery"
|
|
"gopkg.in/macaroon.v2"
|
|
)
|
|
|
|
// Type represents the type of session.
|
|
type Type uint8
|
|
|
|
const (
|
|
TypeMacaroonReadonly Type = 0
|
|
TypeMacaroonAdmin Type = 1
|
|
TypeMacaroonCustom Type = 2
|
|
TypeUIPassword Type = 3
|
|
TypeAutopilot Type = 4
|
|
TypeMacaroonAccount Type = 5
|
|
)
|
|
|
|
// State represents the state of a session.
|
|
type State uint8
|
|
|
|
const (
|
|
StateCreated State = 0
|
|
StateInUse State = 1
|
|
StateRevoked State = 2
|
|
StateExpired State = 3
|
|
)
|
|
|
|
// MacaroonRecipe defines the permissions and caveats that should be used
|
|
// to bake a macaroon.
|
|
type MacaroonRecipe struct {
|
|
Permissions []bakery.Op
|
|
Caveats []macaroon.Caveat
|
|
}
|
|
|
|
// FeaturesConfig is a map from feature name to a raw byte array which stores
|
|
// any config feature config options.
|
|
type FeaturesConfig map[string][]byte
|
|
|
|
// Session is a struct representing a long-term Terminal Connect session.
|
|
type Session struct {
|
|
ID ID
|
|
Label string
|
|
State State
|
|
Type Type
|
|
Expiry time.Time
|
|
CreatedAt time.Time
|
|
RevokedAt time.Time
|
|
ServerAddr string
|
|
DevServer bool
|
|
MacaroonRootKey uint64
|
|
MacaroonRecipe *MacaroonRecipe
|
|
PairingSecret [mailbox.NumPassphraseEntropyBytes]byte
|
|
LocalPrivateKey *btcec.PrivateKey
|
|
LocalPublicKey *btcec.PublicKey
|
|
RemotePublicKey *btcec.PublicKey
|
|
FeatureConfig *FeaturesConfig
|
|
WithPrivacyMapper bool
|
|
PrivacyFlags PrivacyFlags
|
|
|
|
// GroupID is the Session ID of the very first Session in the linked
|
|
// group of sessions. If this is the very first session in the group
|
|
// then this will be the same as ID.
|
|
GroupID ID
|
|
}
|
|
|
|
// NewSession creates a new session with the given user-defined parameters.
|
|
func NewSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
|
|
expiry time.Time, serverAddr string, devServer bool, perms []bakery.Op,
|
|
caveats []macaroon.Caveat, featureConfig FeaturesConfig,
|
|
privacy bool, linkedGroupID *ID, flags PrivacyFlags) (*Session, error) {
|
|
|
|
_, pairingSecret, err := mailbox.NewPassphraseEntropy()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error deriving pairing secret: %v", err)
|
|
}
|
|
|
|
macRootKey := macaroons.NewSuperMacaroonRootKeyID(id)
|
|
|
|
// The group ID will by default be the same as the Session ID
|
|
// unless this session links to a previous session.
|
|
groupID := id
|
|
if linkedGroupID != nil {
|
|
// If this session is linked to a previous session, then the
|
|
// group ID is the same as the linked session's group ID.
|
|
groupID = *linkedGroupID
|
|
}
|
|
|
|
sess := &Session{
|
|
ID: id,
|
|
Label: label,
|
|
State: StateCreated,
|
|
Type: typ,
|
|
Expiry: expiry,
|
|
CreatedAt: time.Now(),
|
|
ServerAddr: serverAddr,
|
|
DevServer: devServer,
|
|
MacaroonRootKey: macRootKey,
|
|
PairingSecret: pairingSecret,
|
|
LocalPrivateKey: localPrivKey,
|
|
LocalPublicKey: localPrivKey.PubKey(),
|
|
RemotePublicKey: nil,
|
|
WithPrivacyMapper: privacy,
|
|
PrivacyFlags: flags,
|
|
GroupID: groupID,
|
|
}
|
|
|
|
if perms != nil || caveats != nil {
|
|
sess.MacaroonRecipe = &MacaroonRecipe{
|
|
Permissions: perms,
|
|
Caveats: caveats,
|
|
}
|
|
}
|
|
|
|
if len(featureConfig) != 0 {
|
|
sess.FeatureConfig = &featureConfig
|
|
}
|
|
|
|
return sess, nil
|
|
}
|
|
|
|
// IDToGroupIndex defines an interface for the session ID to group ID index.
|
|
type IDToGroupIndex interface {
|
|
// GetGroupID will return the group ID for the given session ID.
|
|
GetGroupID(sessionID ID) (ID, error)
|
|
|
|
// GetSessionIDs will return the set of session IDs that are in the
|
|
// group with the given ID.
|
|
GetSessionIDs(groupID ID) ([]ID, error)
|
|
}
|
|
|
|
// Store is the interface a persistent storage must implement for storing and
|
|
// retrieving Terminal Connect sessions.
|
|
type Store interface {
|
|
// CreateSession adds a new session to the store. If a session with the
|
|
// same local public key already exists an error is returned. This
|
|
// can only be called with a Session with an ID that the Store has
|
|
// reserved.
|
|
CreateSession(*Session) error
|
|
|
|
// GetSession fetches the session with the given key.
|
|
GetSession(key *btcec.PublicKey) (*Session, error)
|
|
|
|
// ListSessions returns all sessions currently known to the store.
|
|
ListSessions(filterFn func(s *Session) bool) ([]*Session, error)
|
|
|
|
// RevokeSession updates the state of the session with the given local
|
|
// public key to be revoked.
|
|
RevokeSession(*btcec.PublicKey) error
|
|
|
|
// UpdateSessionRemotePubKey can be used to add the given remote pub key
|
|
// to the session with the given local pub key.
|
|
UpdateSessionRemotePubKey(localPubKey,
|
|
remotePubKey *btcec.PublicKey) error
|
|
|
|
// GetUnusedIDAndKeyPair can be used to generate a new, unused, local
|
|
// private key and session ID pair. Care must be taken to ensure that no
|
|
// other thread calls this before the returned ID and key pair from this
|
|
// method are either used or discarded.
|
|
GetUnusedIDAndKeyPair() (ID, *btcec.PrivateKey, error)
|
|
|
|
// GetSessionByID fetches the session with the given ID.
|
|
GetSessionByID(id ID) (*Session, error)
|
|
|
|
// CheckSessionGroupPredicate iterates over all the sessions in a group
|
|
// and checks if each one passes the given predicate function. True is
|
|
// returned if each session passes.
|
|
CheckSessionGroupPredicate(groupID ID,
|
|
fn func(s *Session) bool) (bool, error)
|
|
|
|
IDToGroupIndex
|
|
}
|