Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

WIP: Policy enforcement framework #23

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ RUN cd /root && \
wget https://bitcoincore.org/bin/bitcoin-core-$bitcoind/bitcoin-${bitcoind}-${cplatform}-linux-gnu.tar.gz && \
tar xfz bitcoin-$bitcoind-$cplatform-linux-gnu.tar.gz && \
mv bitcoin-$bitcoind/bin/* /usr/local/bin/ && \
wget https://github.com/lightningnetwork/lnd/releases/download/$lnd/lnd-linux-$goplatform-$lnd.tar.gz && \
tar xfz lnd-linux-$goplatform-$lnd.tar.gz && \
mv lnd-linux-$goplatform-$lnd/* /usr/local/bin/ && \
#wget https://github.com/lightningnetwork/lnd/releases/download/$lnd/lnd-linux-$goplatform-$lnd.tar.gz && \
#tar xfz lnd-linux-$goplatform-$lnd.tar.gz && \
#mv lnd-linux-$goplatform-$lnd/* /usr/local/bin/ && \
git clone https://github.com/aakselrod/lnd && cd lnd && \
git checkout add-psbt-derivation-info && go install ./cmd/... && cd .. && \
wget https://releases.hashicorp.com/vault/$vault/vault_${vault}_linux_${goplatform}.zip && \
unzip vault_${vault}_linux_${goplatform}.zip && \
mv vault /usr/local/bin/ && \
Expand Down
44 changes: 27 additions & 17 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,33 @@ import (
)

const (
defaultConfigFilename = "signer.conf"
defaultTLSCertFilename = "tls.cert"
defaultTLSKeyFilename = "tls.key"
defaultRPCPort = 10009
defaultRPCHost = "localhost"
defaultConfigFilename = "signer.conf"
defaultChanBackupFilename = "channel.backup"
defaultTLSCertFilename = "tls.cert"
defaultTLSKeyFilename = "tls.key"
defaultRPCPort = 10009
defaultRPCHost = "localhost"
)

var (
// DefaultSignerDir is the default directory where lndsignerd tries to
// defaultSignerDir is the default directory where lndsignerd tries to
// find its configuration file and store its data. This is a directory
// in the user's application data, for example:
// C:\Users\<username>\AppData\Local\Lndsigner on Windows
// ~/.lndsigner on Linux
// ~/Library/Application Support/Lndsigner on MacOS
DefaultSignerDir = btcutil.AppDataDir("lndsigner", false)
defaultSignerDir = btcutil.AppDataDir("lndsigner", false)

// DefaultConfigFile is the default full path of lndsignerd's
// defaultConfigFile is the default full path of lndsignerd's
// configuration file.
DefaultConfigFile = filepath.Join(DefaultSignerDir, defaultConfigFilename)
defaultConfigFile = filepath.Join(defaultSignerDir, defaultConfigFilename)

defaultTLSCertPath = filepath.Join(DefaultSignerDir, defaultTLSCertFilename)
defaultTLSKeyPath = filepath.Join(DefaultSignerDir, defaultTLSKeyFilename)
defaultTLSCertPath = filepath.Join(defaultSignerDir, defaultTLSCertFilename)
defaultTLSKeyPath = filepath.Join(defaultSignerDir, defaultTLSKeyFilename)

// defaultChanBackup is the default full path of the channel backup
// file for the node.
defaultChanBackupFile = filepath.Join(defaultSignerDir, defaultChanBackupFilename)
)

// Config defines the configuration options for lndsignerd.
Expand All @@ -56,6 +61,8 @@ type Config struct {
TLSCertPath string `long:"tlscertpath" description:"Path to write the TLS certificate for lndsignerd's RPC services"`
TLSKeyPath string `long:"tlskeypath" description:"Path to write the TLS private key for lndsignerd's RPC services"`

ChanBackup string `long:"chanbackup" description:"Path to channel.backup file for the watch-only node"`

// We'll parse these 'raw' string arguments into real net.Addrs in the
// loadConfig function. We need to expose the 'raw' strings so the
// command line library can access them.
Expand All @@ -75,8 +82,9 @@ type Config struct {
// DefaultConfig returns all default values for the Config struct.
func DefaultConfig() Config {
return Config{
SignerDir: DefaultSignerDir,
ConfigFile: DefaultConfigFile,
SignerDir: defaultSignerDir,
ChanBackup: defaultChanBackupFile,
ConfigFile: defaultConfigFile,
TLSCertPath: defaultTLSCertPath,
TLSKeyPath: defaultTLSKeyPath,
Network: "regtest",
Expand Down Expand Up @@ -114,16 +122,16 @@ func LoadConfig() (*Config, error) {
// User specified --signerdir but no --configfile. Update the config
// file path to the lndsignerd config directory, but don't require it
// to exist.
case configFileDir != DefaultSignerDir &&
configFilePath == DefaultConfigFile:
case configFileDir != defaultSignerDir &&
configFilePath == defaultConfigFile:

configFilePath = filepath.Join(
configFileDir, defaultConfigFilename,
)

// User did specify an explicit --configfile, so we check that it does
// exist under that path to avoid surprises.
case configFilePath != DefaultConfigFile:
case configFilePath != defaultConfigFile:
if !fileExists(configFilePath) {
return nil, fmt.Errorf("specified config file does "+
"not exist in %s", configFilePath)
Expand Down Expand Up @@ -211,7 +219,7 @@ func ValidateConfig(cfg Config, fileParser, flagParser *flags.Parser) (
// modify the path to all of the files and directories that will live
// within it.
signerDir := CleanAndExpandPath(cfg.SignerDir)
if signerDir != DefaultSignerDir {
if signerDir != defaultSignerDir {
cfg.TLSCertPath = filepath.Join(signerDir, defaultTLSCertFilename)
cfg.TLSKeyPath = filepath.Join(signerDir, defaultTLSKeyFilename)
}
Expand Down Expand Up @@ -281,6 +289,8 @@ func ValidateConfig(cfg Config, fileParser, flagParser *flags.Parser) (
return nil, mkErr("error normalizing RPC listen addrs: %v", err)
}

cfg.ChanBackup = CleanAndExpandPath(cfg.ChanBackup)

// All good, return the sanitized result.
return &cfg, nil
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/btcsuite/btcd/btcutil v1.1.2
github.com/btcsuite/btcd/btcutil/psbt v1.1.8
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1
github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
github.com/hashicorp/go-hclog v1.3.1
github.com/hashicorp/vault/api v1.8.0
Expand All @@ -27,7 +28,6 @@ require (
github.com/benbjohnson/clock v1.1.0 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/evanphx/json-patch/v5 v5.5.0 // indirect
github.com/fatih/color v1.13.0 // indirect
Expand Down
4 changes: 3 additions & 1 deletion itest/itest_lndharness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ func (l *lndHarness) Start() {
l.lndSignerCmd = exec.CommandContext(ctx, l.tctx.lndSignerPath,
"--rpclisten="+fullSignerAddr, "--nodepubkey="+l.idPubKey,
"--tlscertpath="+certPath, "--tlskeypath="+keyPath,
"--network=regtest",
"--network=regtest", "--chanbackup="+
path.Join(l.lndDir,
"data/chain/bitcoin/regtest/channel.backup"),
)

l.lndSignerCmd.Env = append(l.lndSignerCmd.Env,
Expand Down
2 changes: 1 addition & 1 deletion itest/lndsigner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (tctx *testContext) testSweepToP2TR(t *testing.T) {
// testing both direct and chained payments.
func (tctx *testContext) testEachPaysEachOther(t *testing.T) {
tctx.testEachPair(func(lnd1, lnd2 *lndHarness) {
resp := lnd1.Lncli("addinvoice", "5000")
resp := lnd1.Lncli("addinvoice", "10")
invoice := resp["payment_request"].(string)

resp = lnd2.Lncli("payinvoice", "--timeout=10s", "--json",
Expand Down
15 changes: 11 additions & 4 deletions keyring/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ func NewKeyRing(client logicalWriter, node string, coin uint32) *KeyRing {
}
}

// Node returns the node's pubkey as a hex-encoded string.
func (k *KeyRing) Node() string {
return k.node
}

// Coin returns the node's HDCoinType as an int. It must be converted to a
// uint32 and hardened before use in a derivation path.
func (k *KeyRing) Coin() uint32 {
return k.coin
}

// ECDH performs a scalar multiplication (ECDH-like operation) between the
// target key descriptor and remote public key. The output returned will be
// the sha256 of the resulting shared point serialized in compressed format. If
Expand Down Expand Up @@ -570,10 +581,6 @@ func (k *KeyRing) signSegWitV1ScriptSpend(in *psbt.PInput, tx *wire.MsgTx,
// depending on the type of input that should be signed.
func prepareScriptsV0(in *psbt.PInput) []byte {
switch {
// It's a NP2WKH input:
//case len(in.RedeemScript) > 0:
// return in.RedeemScript

// It's a P2WSH input:
case len(in.WitnessScript) > 0:
return in.WitnessScript
Expand Down
35 changes: 31 additions & 4 deletions lndsigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"syscall"

"github.com/hashicorp/vault/api"
"github.com/nydig-oss/lndsigner/policy"
"github.com/nydig-oss/lndsigner/vault"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
Expand Down Expand Up @@ -64,6 +65,26 @@ func Main(cfg *Config, lisCfg ListenerCfg) error {

signerClient := vaultClient.Logical()

listAcctsResp, err := signerClient.ReadWithData(
"lndsigner/lnd-nodes/accounts",
map[string][]string{
"node": []string{cfg.NodePubKey},
},
)
if err != nil {
return mkErr("error listing accounts: %v", err)
}

acctList, ok := listAcctsResp.Data["acctList"].(string)
if !ok {
return mkErr("accounts not returned")
}

accounts, err := GetAccounts(acctList)
if err != nil {
return mkErr("couldn't parse account list: %v", err)
}

serverOpts, err := getTLSConfig(cfg)
if err != nil {
return mkErr("unable to load TLS credentials: %v", err)
Expand All @@ -78,7 +99,7 @@ func Main(cfg *Config, lisCfg ListenerCfg) error {
for _, grpcEndpoint := range cfg.RPCListeners {
// Start a gRPC server listening for HTTP/2
// connections.
lis, err := ListenOnAddress(grpcEndpoint)
lis, err := listenOnAddress(grpcEndpoint)
if err != nil {
return mkErr("unable to listen on %s: %v",
grpcEndpoint, err)
Expand All @@ -96,7 +117,13 @@ func Main(cfg *Config, lisCfg ListenerCfg) error {

// Initialize the rpcServer and add its interceptor to the server
// options.
rpcServer := newRPCServer(cfg, signerClient)
policyEngine, err := policy.NewPolicyEngine(accounts,
cfg.ActiveNetParams.HDCoinType, cfg.ChanBackup)
if err != nil {
return mkErr("unable to initialize policy engine: %v", err)
}

rpcServer := newRPCServer(cfg, signerClient, policyEngine)
serverOpts = append(
serverOpts,
grpc.ChainUnaryInterceptor(rpcServer.intercept),
Expand Down Expand Up @@ -224,8 +251,8 @@ func parseNetwork(addr net.Addr) string {
}
}

// ListenOnAddress creates a listener that listens on the given address.
func ListenOnAddress(addr net.Addr) (net.Listener, error) {
// listenOnAddress creates a listener that listens on the given address.
func listenOnAddress(addr net.Addr) (net.Listener, error) {
return net.Listen(parseNetwork(addr), addr.String())
}

Expand Down
3 changes: 3 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package lndsigner

import (
"github.com/nydig-oss/lndsigner/keyring"
"github.com/nydig-oss/lndsigner/policy"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
Expand All @@ -19,5 +20,7 @@ func init() {
config.EncoderConfig.EncodeCaller = nil
rawLog := zap.Must(config.Build())
signerLog = rawLog.Sugar()

keyring.UseLogger(signerLog.With(zap.Any("pkg", "keyring")))
policy.UseLogger(signerLog.With(zap.Any("pkg", "policy")))
}
Loading