mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
firewall: changes to initial structure
This commit is contained in:
parent
f1d65e51e5
commit
edf195ebd9
4 changed files with 73 additions and 52 deletions
|
|
@ -52,6 +52,9 @@ type InterceptMetaInfo struct {
|
|||
// that is issuing this request.
|
||||
ActorName string `json:"actor_name"`
|
||||
|
||||
// Feature is the feature that caused the actor to execute this action.
|
||||
Feature string `json:"feature"`
|
||||
|
||||
// Trigger is the action or condition that triggered this intercepted
|
||||
// request to be made.
|
||||
Trigger string `json:"trigger"`
|
||||
|
|
@ -59,6 +62,10 @@ type InterceptMetaInfo struct {
|
|||
// Intent is the desired outcome or end condition this request aims to
|
||||
// arrive at.
|
||||
Intent string `json:"intent"`
|
||||
|
||||
// StructuredJsonData is extra, structured, info that the Autopilot can
|
||||
// send to Lit. It is a json serialised string.
|
||||
StructuredJsonData string `json:"structured_json_data"`
|
||||
}
|
||||
|
||||
// ToCaveat returns the full custom caveat string representation of the
|
||||
|
|
@ -96,23 +103,24 @@ func ParseMetaInfoCaveat(caveat string) (*InterceptMetaInfo, error) {
|
|||
return i, nil
|
||||
}
|
||||
|
||||
// InterceptRule is the JSON serializable struct containing all the rules and
|
||||
// InterceptRules is the JSON serializable struct containing all the rules and
|
||||
// their limits/settings that need to be enforced on a request made by an
|
||||
// automated node management software against LiT. The rule information is added
|
||||
// as a custom macaroon caveat.
|
||||
type InterceptRule struct {
|
||||
// Name is the name of the rule. It must correspond to a
|
||||
Name string `json:"name"`
|
||||
type InterceptRules struct {
|
||||
// SessionRules are rules that apply session wide. The map is rule
|
||||
// name to rule value.
|
||||
SessionRules map[string]string `json:"session_rules"`
|
||||
|
||||
// Restrictions is a key/value map of all the parameters that apply to
|
||||
// this rule.
|
||||
Restrictions map[string]string `json:"restrictions"`
|
||||
// Feature rules are rules that apply to a specific feature. The map is
|
||||
// feature name to a map of rule name to rule value.
|
||||
FeatureRules map[string]map[string]string `json:"feature_rules"`
|
||||
}
|
||||
|
||||
// RulesToCaveat encodes a list of rules as a full custom caveat string
|
||||
// representation in this format:
|
||||
// lnd-custom lit-mac-fw rules:[<array_of_JSON_encoded_rules>]
|
||||
func RulesToCaveat(rules []*InterceptRule) (string, error) {
|
||||
func RulesToCaveat(rules *InterceptRules) (string, error) {
|
||||
jsonBytes, err := json.Marshal(rules)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error JSON marshaling: %v", err)
|
||||
|
|
@ -122,7 +130,7 @@ func RulesToCaveat(rules []*InterceptRule) (string, error) {
|
|||
}
|
||||
|
||||
// ParseRuleCaveat tries to parse the given caveat string as a rule struct.
|
||||
func ParseRuleCaveat(caveat string) ([]*InterceptRule, error) {
|
||||
func ParseRuleCaveat(caveat string) (*InterceptRules, error) {
|
||||
if !strings.HasPrefix(caveat, MetaRulesFullCaveatPrefix) {
|
||||
return nil, ErrNoRulesCaveat
|
||||
}
|
||||
|
|
@ -134,11 +142,11 @@ func ParseRuleCaveat(caveat string) ([]*InterceptRule, error) {
|
|||
|
||||
// There's a colon after the prefix that we need to skip as well.
|
||||
jsonData := caveat[len(MetaRulesFullCaveatPrefix)+1:]
|
||||
var rules []*InterceptRule
|
||||
var rules InterceptRules
|
||||
|
||||
if err := json.Unmarshal([]byte(jsonData), &rules); err != nil {
|
||||
return nil, fmt.Errorf("error unmarshaling JSON: %v", err)
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
return &rules, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,25 +9,27 @@ import (
|
|||
|
||||
const (
|
||||
testMetaCaveat = "lnd-custom lit-mac-fw meta:{\"actor_name\":" +
|
||||
"\"re-balancer\",\"trigger\":\"channel 7413345453234435345 " +
|
||||
"depleted\",\"intent\":\"increase outbound liquidity by " +
|
||||
"2000000 sats\"}"
|
||||
"\"autopilot\",\"feature\":\"re-balance\",\"trigger\":" +
|
||||
"\"channel 7413345453234435345 depleted\",\"intent\":" +
|
||||
"\"increase outbound liquidity by 2000000 sats\"," +
|
||||
"\"structured_json_data\":\"{}\"}"
|
||||
|
||||
testRulesCaveat = "lnd-custom lit-mac-fw rules:[{\"name\":" +
|
||||
"\"re-balance-limits\",\"restrictions\":" +
|
||||
"{\"first-hop-ignore-list\":\"03abcd...,02badb01...\"," +
|
||||
"\"max-hops\":\"4\",\"off-chain-fees-sats\":\"10\"}}," +
|
||||
"{\"name\":\"time-limits\",\"restrictions\":" +
|
||||
"{\"re-balance-min-interval-seconds\":\"3600\"}}]"
|
||||
testRulesCaveat = "lnd-custom lit-mac-fw rules:{\"session_rules\":{" +
|
||||
"\"rate-limit\":\"1/10\"},\"feature_rules\":{\"AutoFees\":{" +
|
||||
"\"first-hop-ignore-list\":\"03abcd...,02badb01...\"," +
|
||||
"\"max-hops\":\"4\"},\"Rebalance\":{\"off-chain-fees-sats\":" +
|
||||
"\"10\",\"re-balance-min-interval-seconds\":\"3600\"}}}"
|
||||
)
|
||||
|
||||
// TestInterceptMetaInfo makes sure that a meta information struct can be
|
||||
// formatted as a caveat and then parsed again successfully.
|
||||
func TestInterceptMetaInfo(t *testing.T) {
|
||||
info := &InterceptMetaInfo{
|
||||
ActorName: "re-balancer",
|
||||
Trigger: "channel 7413345453234435345 depleted",
|
||||
Intent: "increase outbound liquidity by 2000000 sats",
|
||||
ActorName: "autopilot",
|
||||
Feature: "re-balance",
|
||||
Trigger: "channel 7413345453234435345 depleted",
|
||||
Intent: "increase outbound liquidity by 2000000 sats",
|
||||
StructuredJsonData: "{}",
|
||||
}
|
||||
|
||||
caveat, err := info.ToCaveat()
|
||||
|
|
@ -90,19 +92,21 @@ func TestParseMetaInfoCaveat(t *testing.T) {
|
|||
// TestInterceptRule makes sure that a rules list struct can be formatted as a
|
||||
// caveat and then parsed again successfully.
|
||||
func TestInterceptRule(t *testing.T) {
|
||||
rules := []*InterceptRule{{
|
||||
Name: "re-balance-limits",
|
||||
Restrictions: map[string]string{
|
||||
"off-chain-fees-sats": "10",
|
||||
"max-hops": "4",
|
||||
"first-hop-ignore-list": "03abcd...,02badb01...",
|
||||
rules := &InterceptRules{
|
||||
FeatureRules: map[string]map[string]string{
|
||||
"AutoFees": {
|
||||
"first-hop-ignore-list": "03abcd...,02badb01...",
|
||||
"max-hops": "4",
|
||||
},
|
||||
"Rebalance": {
|
||||
"off-chain-fees-sats": "10",
|
||||
"re-balance-min-interval-seconds": "3600",
|
||||
},
|
||||
},
|
||||
}, {
|
||||
Name: "time-limits",
|
||||
Restrictions: map[string]string{
|
||||
"re-balance-min-interval-seconds": "3600",
|
||||
SessionRules: map[string]string{
|
||||
"rate-limit": "1/10",
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
caveat, err := RulesToCaveat(rules)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -122,7 +126,7 @@ func TestParseRulesCaveat(t *testing.T) {
|
|||
name string
|
||||
input string
|
||||
err error
|
||||
result []*InterceptRule
|
||||
result *InterceptRules
|
||||
}{{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
|
|
@ -138,23 +142,25 @@ func TestParseRulesCaveat(t *testing.T) {
|
|||
"'b' looking for beginning of value"),
|
||||
}, {
|
||||
name: "empty JSON",
|
||||
input: "lnd-custom lit-mac-fw rules:[]",
|
||||
result: []*InterceptRule{},
|
||||
}, {
|
||||
name: "empty rules",
|
||||
input: "lnd-custom lit-mac-fw rules:[{}, {}]",
|
||||
result: []*InterceptRule{{}, {}},
|
||||
input: "lnd-custom lit-mac-fw rules:{}",
|
||||
result: &InterceptRules{},
|
||||
}, {
|
||||
name: "valid rules",
|
||||
input: "lnd-custom lit-mac-fw rules:[{\"name\":\"foo\"}, " +
|
||||
"{\"restrictions\":{\"foo\":\"bar\"}}]",
|
||||
result: []*InterceptRule{{
|
||||
Name: "foo",
|
||||
}, {
|
||||
Restrictions: map[string]string{
|
||||
"foo": "bar",
|
||||
input: "lnd-custom lit-mac-fw rules:{\"session_rules\":" +
|
||||
"{\"rate-limit\":\"2000\"}, \"feature_rules\":" +
|
||||
"{\"Autofees\":{\"foo\":\"bar\", \"rate-limit\":" +
|
||||
"\"1000\"}}}",
|
||||
result: &InterceptRules{
|
||||
FeatureRules: map[string]map[string]string{
|
||||
"Autofees": {
|
||||
"foo": "bar",
|
||||
"rate-limit": "1000",
|
||||
},
|
||||
},
|
||||
}},
|
||||
SessionRules: map[string]string{
|
||||
"rate-limit": "2000",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@ type RequestInfo struct {
|
|||
MWRequestType string
|
||||
URI string
|
||||
GRPCMessageType string
|
||||
IsError bool
|
||||
Serialized []byte
|
||||
Streaming bool
|
||||
Macaroon *macaroon.Macaroon
|
||||
Caveats []string
|
||||
MetaInfo *InterceptMetaInfo
|
||||
Rules []*InterceptRule
|
||||
Rules *InterceptRules
|
||||
}
|
||||
|
||||
// NewInfoFromRequest parses the given RPC middleware interception request and
|
||||
|
|
@ -54,6 +56,8 @@ func NewInfoFromRequest(req *lnrpc.RPCMiddlewareRequest) (*RequestInfo, error) {
|
|||
MWRequestType: MWRequestTypeRequest,
|
||||
URI: t.Request.MethodFullUri,
|
||||
GRPCMessageType: t.Request.TypeName,
|
||||
IsError: t.Request.IsError,
|
||||
Serialized: t.Request.Serialized,
|
||||
Streaming: t.Request.StreamRpc,
|
||||
}
|
||||
|
||||
|
|
@ -62,6 +66,8 @@ func NewInfoFromRequest(req *lnrpc.RPCMiddlewareRequest) (*RequestInfo, error) {
|
|||
MWRequestType: MWRequestTypeResponse,
|
||||
URI: t.Response.MethodFullUri,
|
||||
GRPCMessageType: t.Response.TypeName,
|
||||
IsError: t.Response.IsError,
|
||||
Serialized: t.Response.Serialized,
|
||||
Streaming: t.Response.StreamRpc,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,9 +53,10 @@ func (r *RuleEnforcer) Intercept(_ context.Context,
|
|||
log.Infof("Enforcing rule %v", ri)
|
||||
|
||||
// Enforce actual rules.
|
||||
if len(ri.Rules) > 0 {
|
||||
numRules := len(ri.Rules.SessionRules) + len(ri.Rules.FeatureRules)
|
||||
if numRules > 0 {
|
||||
// TODO(guggero): Implement rules and their enforcement.
|
||||
log.Debugf("There are %d rules to enforce", len(ri.Rules))
|
||||
log.Debugf("There are %d rules to enforce", numRules)
|
||||
}
|
||||
|
||||
// Send empty response, accepting the request.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue