diff --git a/resources/charts/bitcoincore/charts/lnd/templates/configmap.yaml b/resources/charts/bitcoincore/charts/lnd/templates/configmap.yaml index 096c764ff..b43ca8933 100644 --- a/resources/charts/bitcoincore/charts/lnd/templates/configmap.yaml +++ b/resources/charts/bitcoincore/charts/lnd/templates/configmap.yaml @@ -20,25 +20,27 @@ data: tlsextradomain={{ include "lnd.fullname" . }} tls.cert: | -----BEGIN CERTIFICATE----- - MIIB8TCCAZagAwIBAgIUJDsR6mmY+TaO9pCfjtotlbOkzJMwCgYIKoZIzj0EAwIw + MIIB+DCCAZ6gAwIBAgIUSbyK/9viFWS3cLoPkmxZsW8fcH8wCgYIKoZIzj0EAwIw MjEfMB0GA1UECgwWbG5kIGF1dG9nZW5lcmF0ZWQgY2VydDEPMA0GA1UEAwwGd2Fy - bmV0MB4XDTI0MTExMTE2NTM1MFoXDTM0MTEwOTE2NTM1MFowMjEfMB0GA1UECgwW + bmV0MB4XDTI1MDkwMzE1NDgzNFoXDTM1MDkwMTE1NDgzNFowMjEfMB0GA1UECgwW bG5kIGF1dG9nZW5lcmF0ZWQgY2VydDEPMA0GA1UEAwwGd2FybmV0MFkwEwYHKoZI - zj0CAQYIKoZIzj0DAQcDQgAEBVltIvaTlAQI/3FFatTqVflZuZdRJ0SmRMSJrFLP - tp0fxE7hmteSt6gjQriy90fP8j9OJXBNAjt915kLY4zVvqOBiTCBhjAOBgNVHQ8B + zj0CAQYIKoZIzj0DAQcDQgAENIGvS4bQr/zzUQnIqgJIYrPEdPMXVkv3yEyJRCFg + PyZTvxWUJy7AI3VKb7ubIXawYcnPBe7K1sgBAbTPz1c8sqOBkTCBjjAOBgNVHQ8B Af8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAd - BgNVHQ4EFgQU5d8QMrwhLgTkDjWA+eXZGz+dybUwLwYDVR0RBCgwJoIJbG9jYWxo - b3N0ggEqhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMAoGCCqGSM49BAMCA0kAMEYC - IQDPofN0fEl5gTwCYhk3nZbjMqJhZ8BsSJ6K8XRhxr7zbwIhAPsgQCFOqUWg632O - NEO53OQ6CIqnpxSskjsFNH4ZBQOE + BgNVHQ4EFgQUNhDWW7rajlA9sNGI/1Q5BDLH/rMwNwYDVR0RBDAwLoIJbG9jYWxo + b3N0ggkqLmRlZmF1bHSHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwCgYIKoZIzj0E + AwIDSAAwRQIhAOFm85wvwPZMJg0+16Sh0FkKqAuGVmllHnriWHQJ1NhuAiAfoxzE + 9ooZuDwKy0Y3dP4DfJCrOlFNTHfp3abG7VQ+VQ== -----END CERTIFICATE----- + tls.key: | -----BEGIN EC PRIVATE KEY----- - MHcCAQEEIIcFtWTLQv5JaRRxdkPKkO98OrvgeztbZ7h8Ev/4UbE4oAoGCCqGSM49 - AwEHoUQDQgAEBVltIvaTlAQI/3FFatTqVflZuZdRJ0SmRMSJrFLPtp0fxE7hmteS - t6gjQriy90fP8j9OJXBNAjt915kLY4zVvg== + MHcCAQEEIEKlsxGkakClpHqXbr6tqEey634Xc364DgGMJxLdiLHIoAoGCCqGSM49 + AwEHoUQDQgAENIGvS4bQr/zzUQnIqgJIYrPEdPMXVkv3yEyJRCFgPyZTvxWUJy7A + I3VKb7ubIXawYcnPBe7K1sgBAbTPz1c8sg== -----END EC PRIVATE KEY----- - MACAROON_HEX: 0201036c6e6402f801030a1062beabbf2a614b112128afa0c0b4fdd61201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620b17be53e367290871681055d0de15587f6d1cd47d1248fe2662ae27f62cfbdc6 + + MACAROON_HEX: {{ .Values.adminMacaroon }} --- apiVersion: v1 kind: ConfigMap diff --git a/resources/charts/bitcoincore/charts/lnd/templates/pod.yaml b/resources/charts/bitcoincore/charts/lnd/templates/pod.yaml index 2199f556b..f801aa8ef 100644 --- a/resources/charts/bitcoincore/charts/lnd/templates/pod.yaml +++ b/resources/charts/bitcoincore/charts/lnd/templates/pod.yaml @@ -14,6 +14,7 @@ metadata: chain: {{ .Values.global.chain }} annotations: kubectl.kubernetes.io/default-container: "lnd" + adminMacaroon: {{ .Values.adminMacaroon }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: @@ -40,9 +41,20 @@ spec: livenessProbe: {{- toYaml .Values.livenessProbe | nindent 8 }} readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 8 }} + {{- toYaml .Values.readinessProbe | nindent 8 }} startupProbe: - {{- toYaml .Values.startupProbe | nindent 8 }} + failureThreshold: 10 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 60 + exec: + command: + - /bin/sh + - -c + - | + PHRASE=`curl --silent --insecure https://localhost:8080/v1/genseed | grep -o '\[[^]]*\]'` + curl --insecure https://localhost:8080/v1/initwallet --data "{\"macaroon_root_key\":\"{{ .Values.macaroonRootKey }}\", \"wallet_password\":\"AAAAAAAAAAA=\", \"cipher_seed_mnemonic\": $PHRASE}" + resources: {{- toYaml .Values.resources | nindent 8 }} volumeMounts: diff --git a/resources/charts/bitcoincore/charts/lnd/values.yaml b/resources/charts/bitcoincore/charts/lnd/values.yaml index 212707472..1940f4684 100644 --- a/resources/charts/bitcoincore/charts/lnd/values.yaml +++ b/resources/charts/bitcoincore/charts/lnd/values.yaml @@ -81,18 +81,6 @@ readinessProbe: tcpSocket: port: 10009 timeoutSeconds: 1 -startupProbe: - failureThreshold: 10 - periodSeconds: 30 - successThreshold: 1 - timeoutSeconds: 60 - exec: - command: - - /bin/sh - - -c - - | - PHRASE=`curl --silent --insecure https://localhost:8080/v1/genseed | grep -o '\[[^]]*\]'` - curl --insecure https://localhost:8080/v1/initwallet --data "{\"macaroon_root_key\":\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\", \"wallet_password\":\"AAAAAAAAAAA=\", \"cipher_seed_mnemonic\": $PHRASE}" # Additional volumes on the output Deployment definition. volumes: [] @@ -113,6 +101,9 @@ tolerations: [] affinity: {} +macaroonRootKey: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +adminMacaroon: 0201036c6e6402f801030a1062beabbf2a614b112128afa0c0b4fdd61201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620b17be53e367290871681055d0de15587f6d1cd47d1248fe2662ae27f62cfbdc6 + baseConfig: | norest=false restlisten=0.0.0.0:8080 diff --git a/resources/plugins/simln/charts/simln/templates/configmap.yaml b/resources/plugins/simln/charts/simln/templates/configmap.yaml index 9df3f0543..8ea50e676 100644 --- a/resources/plugins/simln/charts/simln/templates/configmap.yaml +++ b/resources/plugins/simln/charts/simln/templates/configmap.yaml @@ -5,18 +5,19 @@ metadata: data: tls.cert: | -----BEGIN CERTIFICATE----- - MIIB8TCCAZagAwIBAgIUJDsR6mmY+TaO9pCfjtotlbOkzJMwCgYIKoZIzj0EAwIw + MIIB+DCCAZ6gAwIBAgIUSbyK/9viFWS3cLoPkmxZsW8fcH8wCgYIKoZIzj0EAwIw MjEfMB0GA1UECgwWbG5kIGF1dG9nZW5lcmF0ZWQgY2VydDEPMA0GA1UEAwwGd2Fy - bmV0MB4XDTI0MTExMTE2NTM1MFoXDTM0MTEwOTE2NTM1MFowMjEfMB0GA1UECgwW + bmV0MB4XDTI1MDkwMzE1NDgzNFoXDTM1MDkwMTE1NDgzNFowMjEfMB0GA1UECgwW bG5kIGF1dG9nZW5lcmF0ZWQgY2VydDEPMA0GA1UEAwwGd2FybmV0MFkwEwYHKoZI - zj0CAQYIKoZIzj0DAQcDQgAEBVltIvaTlAQI/3FFatTqVflZuZdRJ0SmRMSJrFLP - tp0fxE7hmteSt6gjQriy90fP8j9OJXBNAjt915kLY4zVvqOBiTCBhjAOBgNVHQ8B + zj0CAQYIKoZIzj0DAQcDQgAENIGvS4bQr/zzUQnIqgJIYrPEdPMXVkv3yEyJRCFg + PyZTvxWUJy7AI3VKb7ubIXawYcnPBe7K1sgBAbTPz1c8sqOBkTCBjjAOBgNVHQ8B Af8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAd - BgNVHQ4EFgQU5d8QMrwhLgTkDjWA+eXZGz+dybUwLwYDVR0RBCgwJoIJbG9jYWxo - b3N0ggEqhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMAoGCCqGSM49BAMCA0kAMEYC - IQDPofN0fEl5gTwCYhk3nZbjMqJhZ8BsSJ6K8XRhxr7zbwIhAPsgQCFOqUWg632O - NEO53OQ6CIqnpxSskjsFNH4ZBQOE + BgNVHQ4EFgQUNhDWW7rajlA9sNGI/1Q5BDLH/rMwNwYDVR0RBDAwLoIJbG9jYWxo + b3N0ggkqLmRlZmF1bHSHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwCgYIKoZIzj0E + AwIDSAAwRQIhAOFm85wvwPZMJg0+16Sh0FkKqAuGVmllHnriWHQJ1NhuAiAfoxzE + 9ooZuDwKy0Y3dP4DfJCrOlFNTHfp3abG7VQ+VQ== -----END CERTIFICATE----- + {{- $configMaps := lookup "v1" "ConfigMap" .Release.Namespace "" }} {{- range $configMaps.items }} {{- if and .metadata.labels (hasKey .metadata.labels "role") (eq (index .metadata.labels "role") "macaroon-ref") }} diff --git a/resources/scenarios/commander.py b/resources/scenarios/commander.py index 4a44ab4a7..067cd4cc1 100644 --- a/resources/scenarios/commander.py +++ b/resources/scenarios/commander.py @@ -70,9 +70,13 @@ ) if pod.metadata.labels["mission"] == "lightning": - lnnode = LND(pod.metadata.name, pod.status.pod_ip) + if "lnd" in pod.metadata.labels["app.kubernetes.io/name"]: + lnnode = LND( + pod.metadata.name, pod.status.pod_ip, pod.metadata.annotations["adminMacaroon"] + ) if "cln" in pod.metadata.labels["app.kubernetes.io/name"]: lnnode = CLN(pod.metadata.name, pod.status.pod_ip) + assert lnnode WARNET["lightning"].append(lnnode) for cm in cmaps.items: diff --git a/resources/scenarios/ln_framework/ln.py b/resources/scenarios/ln_framework/ln.py index 89b435014..f11c28cbf 100644 --- a/resources/scenarios/ln_framework/ln.py +++ b/resources/scenarios/ln_framework/ln.py @@ -8,8 +8,6 @@ import requests -# hard-coded deterministic lnd credentials -ADMIN_MACAROON_HEX = "0201036c6e6402f801030a1062beabbf2a614b112128afa0c0b4fdd61201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620b17be53e367290871681055d0de15587f6d1cd47d1248fe2662ae27f62cfbdc6" # Don't worry about lnd's self-signed certificates INSECURE_CONTEXT = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) INSECURE_CONTEXT.check_hostname = False @@ -286,13 +284,14 @@ def update(self, txid_hex: str, policy: dict, capacity: int) -> dict: class LND(LNNode): - def __init__(self, pod_name, ip_address): + def __init__(self, pod_name, ip_address, admin_macaroon_hex): super().__init__(pod_name, ip_address) self.conn = http.client.HTTPSConnection( host=pod_name, port=8080, timeout=5, context=INSECURE_CONTEXT ) + self.admin_macaroon_hex = admin_macaroon_hex self.headers = { - "Grpc-Metadata-macaroon": ADMIN_MACAROON_HEX, + "Grpc-Metadata-macaroon": admin_macaroon_hex, "Connection": "close", } self.impl = "lnd" diff --git a/resources/scripts/ssl/openssl-config.cnf b/resources/scripts/ssl/openssl-config.cnf index db4e4a162..2a7539ecf 100644 --- a/resources/scripts/ssl/openssl-config.cnf +++ b/resources/scripts/ssl/openssl-config.cnf @@ -23,6 +23,6 @@ subjectAltName = @alt_names [ alt_names ] DNS.1 = localhost -DNS.2 = * +DNS.2 = *.default IP.1 = 127.0.0.1 IP.2 = ::1 diff --git a/resources/scripts/ssl/tls.cert b/resources/scripts/ssl/tls.cert index 6cf6e306a..4dfc97a8a 100644 --- a/resources/scripts/ssl/tls.cert +++ b/resources/scripts/ssl/tls.cert @@ -1,13 +1,13 @@ -----BEGIN CERTIFICATE----- -MIIB8TCCAZagAwIBAgIUJDsR6mmY+TaO9pCfjtotlbOkzJMwCgYIKoZIzj0EAwIw +MIIB+DCCAZ6gAwIBAgIUSbyK/9viFWS3cLoPkmxZsW8fcH8wCgYIKoZIzj0EAwIw MjEfMB0GA1UECgwWbG5kIGF1dG9nZW5lcmF0ZWQgY2VydDEPMA0GA1UEAwwGd2Fy -bmV0MB4XDTI0MTExMTE2NTM1MFoXDTM0MTEwOTE2NTM1MFowMjEfMB0GA1UECgwW +bmV0MB4XDTI1MDkwMzE1NDgzNFoXDTM1MDkwMTE1NDgzNFowMjEfMB0GA1UECgwW bG5kIGF1dG9nZW5lcmF0ZWQgY2VydDEPMA0GA1UEAwwGd2FybmV0MFkwEwYHKoZI -zj0CAQYIKoZIzj0DAQcDQgAEBVltIvaTlAQI/3FFatTqVflZuZdRJ0SmRMSJrFLP -tp0fxE7hmteSt6gjQriy90fP8j9OJXBNAjt915kLY4zVvqOBiTCBhjAOBgNVHQ8B +zj0CAQYIKoZIzj0DAQcDQgAENIGvS4bQr/zzUQnIqgJIYrPEdPMXVkv3yEyJRCFg +PyZTvxWUJy7AI3VKb7ubIXawYcnPBe7K1sgBAbTPz1c8sqOBkTCBjjAOBgNVHQ8B Af8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQU5d8QMrwhLgTkDjWA+eXZGz+dybUwLwYDVR0RBCgwJoIJbG9jYWxo -b3N0ggEqhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMAoGCCqGSM49BAMCA0kAMEYC -IQDPofN0fEl5gTwCYhk3nZbjMqJhZ8BsSJ6K8XRhxr7zbwIhAPsgQCFOqUWg632O -NEO53OQ6CIqnpxSskjsFNH4ZBQOE +BgNVHQ4EFgQUNhDWW7rajlA9sNGI/1Q5BDLH/rMwNwYDVR0RBDAwLoIJbG9jYWxo +b3N0ggkqLmRlZmF1bHSHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwCgYIKoZIzj0E +AwIDSAAwRQIhAOFm85wvwPZMJg0+16Sh0FkKqAuGVmllHnriWHQJ1NhuAiAfoxzE +9ooZuDwKy0Y3dP4DfJCrOlFNTHfp3abG7VQ+VQ== -----END CERTIFICATE----- diff --git a/resources/scripts/ssl/tls.key b/resources/scripts/ssl/tls.key index ca0118123..1f27900aa 100644 --- a/resources/scripts/ssl/tls.key +++ b/resources/scripts/ssl/tls.key @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEIIcFtWTLQv5JaRRxdkPKkO98OrvgeztbZ7h8Ev/4UbE4oAoGCCqGSM49 -AwEHoUQDQgAEBVltIvaTlAQI/3FFatTqVflZuZdRJ0SmRMSJrFLPtp0fxE7hmteS -t6gjQriy90fP8j9OJXBNAjt915kLY4zVvg== +MHcCAQEEIEKlsxGkakClpHqXbr6tqEey634Xc364DgGMJxLdiLHIoAoGCCqGSM49 +AwEHoUQDQgAENIGvS4bQr/zzUQnIqgJIYrPEdPMXVkv3yEyJRCFgPyZTvxWUJy7A +I3VKb7ubIXawYcnPBe7K1sgBAbTPz1c8sg== -----END EC PRIVATE KEY----- diff --git a/test/data/ln/network.yaml b/test/data/ln/network.yaml index 18ef86932..e0761f8f5 100644 --- a/test/data/ln/network.yaml +++ b/test/data/ln/network.yaml @@ -24,6 +24,10 @@ nodes: circuitbreaker: enabled: true httpPort: 9235 + # Just 32 bytes of entropy encoded in base64 + macaroonRootKey: nmPScpcYkBBUXvEryzpYfjgY27j8hO9SiXO9qNQAJFs= + # Derived from root key with `lncli bakemacaroon --root_key=...` + adminMacaroon: 0201036c6e6402f801030a10b676fd9c5cbdfccedb1b932865ad57451201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620cff489a728f1be62c41db20607e78e3b3173f5b51679b4489e429cc83648dac4 - name: tank-0004 addnode: @@ -36,6 +40,11 @@ nodes: target: tank-0005-ln capacity: 50000 push_amt: 25000 + # Just 32 bytes of entropy encoded in base64 + macaroonRootKey: FmEMD2X1hKzxR5yAWgbAT5CbQWPOW+OdyztMMCTBThU= + # Derived from root key with `lncli bakemacaroon --root_key=...` + adminMacaroon: 0201036c6e6402f801030a102616e41d07f5df28869fe8f8147ed2861201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620e40032ba0d91a7f046ed4596da67aa129cca0ff162e51444df2ce68fa6d16944 + - name: tank-0005 addnode: - tank-0000 \ No newline at end of file diff --git a/test/ln_basic_test.py b/test/ln_basic_test.py index c1d9792ad..d21e1a45d 100755 --- a/test/ln_basic_test.py +++ b/test/ln_basic_test.py @@ -34,6 +34,9 @@ def run_test(self): # Wait for all nodes to wake up. ln_init will start automatically self.setup_network() + # Test manually configured macroons + self.test_admin_macaroons() + # Test circuit breaker API self.test_circuit_breaker_api() @@ -53,6 +56,42 @@ def setup_network(self): self.log.info("Setting up network") stream_command(f"warnet deploy {self.network_dir}") + def test_admin_macaroons(self): + self.log.info("Testing lnd nodes with same macaroon root key can query each other") + # These tanks all use the same default macaroon root key, meaning the macaroons + # generated at ~/.lnd/.../admin.macaroon in each lnd container are authorized + # to make requests to each other. + info = json.loads( + self.warnet("ln rpc tank-0000-ln --rpcserver=tank-0001-ln.default:10009 getinfo") + ) + info["alias"] = "tank-0001-ln" + info = json.loads( + self.warnet("ln rpc tank-0001-ln --rpcserver=tank-0002-ln.default:10009 getinfo") + ) + info["alias"] = "tank-0002-ln" + info = json.loads( + self.warnet("ln rpc tank-0002-ln --rpcserver=tank-0005-ln.default:10009 getinfo") + ) + info["alias"] = "tank-0005-ln" + + self.log.info("Testing lnd nodes with unique macaroon root key can NOT query each other") + # These tanks are configured with unique macaroon root keys + try: + self.warnet("ln rpc tank-0000-ln --rpcserver=tank-0003-ln.default:10009 getinfo") + raise AssertionError("That should not have worked!") + except Exception as e: + assert "verification failed: signature mismatch after caveat verification" in str(e) + try: + self.warnet("ln rpc tank-0000-ln --rpcserver=tank-0004-ln.default:10009 getinfo") + raise AssertionError("That should not have worked!") + except Exception as e: + assert "verification failed: signature mismatch after caveat verification" in str(e) + try: + self.warnet("ln rpc tank-0003-ln --rpcserver=tank-0004-ln.default:10009 getinfo") + raise AssertionError("That should not have worked!") + except Exception as e: + assert "verification failed: signature mismatch after caveat verification" in str(e) + def fund_wallets(self): for ln in self.lns: addr = json.loads(self.warnet(f"ln rpc {ln} newaddress p2wkh"))["address"]