Skip to content

Commit

Permalink
clnrest: remove global variables used for plugin options.
Browse files Browse the repository at this point in the history
Global variables are not needed in that case because `plugin` instance
is already global and we can access plugin options with `plugin.options`.

Remove `shared.py` file and `set_config` function.

Also fix the doc.
  • Loading branch information
tonyaldon committed Oct 13, 2023
1 parent 4b6096a commit cfeea69
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 51 deletions.
2 changes: 1 addition & 1 deletion doc/developers-guide/app-development/rest.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ Specifically, two things can happen if you try to use
Example CSP:

```
rest-csp=default-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'; style-src 'self'; script-src 'self';
default-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'; style-src 'self'; script-src 'self';
```

- `--rest-cors-origins`: Define multiple origins which are allowed
Expand Down
62 changes: 31 additions & 31 deletions plugins/clnrest/clnrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from multiprocessing import Process, Queue
from flask_socketio import SocketIO, disconnect
from utilities.generate_certs import generate_certs
from utilities.shared import set_config
from utilities.rpc_routes import rpcns
from utilities.rpc_plugin import plugin
except ModuleNotFoundError as err:
Expand All @@ -34,12 +33,12 @@


def check_origin(origin):
from utilities.shared import REST_CORS_ORIGINS
rest_cors_origins = plugin.options["rest-cors-origins"]["value"]
is_whitelisted = False
if REST_CORS_ORIGINS[0] == "*":
if rest_cors_origins[0] == "*":
is_whitelisted = True
else:
for whitelisted_origin in REST_CORS_ORIGINS:
for whitelisted_origin in rest_cors_origins:
try:
does_match = bool(re.compile(whitelisted_origin).match(origin))
is_whitelisted = is_whitelisted or does_match
Expand Down Expand Up @@ -93,13 +92,12 @@ def ws_connect():


def create_app():
from utilities.shared import REST_CORS_ORIGINS
global app
app.config["SECRET_KEY"] = os.urandom(24).hex()
authorizations = {
"rune": {"type": "apiKey", "in": "header", "name": "Rune"}
}
CORS(app, resources={r"/*": {"origins": REST_CORS_ORIGINS}})
CORS(app, resources={r"/*": {"origins": plugin.options["rest-cors-origins"]["value"]}})
blueprint = Blueprint("api", __name__)
api = Api(blueprint, version="1.0", title="Core Lightning Rest", description="Core Lightning REST API Swagger", authorizations=authorizations, security=["rune"])
app.register_blueprint(blueprint)
Expand All @@ -109,57 +107,61 @@ def create_app():
@app.after_request
def add_csp_headers(response):
try:
from utilities.shared import REST_CSP
response.headers['Content-Security-Policy'] = REST_CSP.replace('\\', '').replace("[\"", '').replace("\"]", '')
response.headers['Content-Security-Policy'] = plugin.options["rest-csp"]["value"]
return response
except Exception as err:
plugin.log(f"Error from rest-csp config: {err}", "info")


def set_application_options(plugin):
from utilities.shared import CERTS_PATH, REST_PROTOCOL, REST_HOST, REST_PORT
plugin.log(f"REST Server is starting at {REST_PROTOCOL}://{REST_HOST}:{REST_PORT}", "debug")
if REST_PROTOCOL == "http":
rest_port = plugin.options["rest-port"]["value"]
rest_host = plugin.options["rest-host"]["value"]
rest_protocol = plugin.options["rest-protocol"]["value"]
rest_certs = plugin.options["rest-certs"]["value"]
plugin.log(f"REST Server is starting at {rest_protocol}://{rest_host}:{rest_port}", "debug")
if rest_protocol == "http":
# Assigning only one worker due to added complexity between gunicorn's multiple worker process forks
# and websocket connection's persistance with a single worker.
options = {
"bind": f"{REST_HOST}:{REST_PORT}",
"bind": f"{rest_host}:{rest_port}",
"workers": 1,
"worker_class": "geventwebsocket.gunicorn.workers.GeventWebSocketWorker",
"timeout": 60,
"loglevel": "warning",
}
else:
cert_file = Path(f"{CERTS_PATH}/client.pem")
key_file = Path(f"{CERTS_PATH}/client-key.pem")
cert_file = Path(f"{rest_certs}/client.pem")
key_file = Path(f"{rest_certs}/client-key.pem")
if not cert_file.is_file() or not key_file.is_file():
plugin.log(f"Certificate not found at {CERTS_PATH}. Generating a new certificate!", "debug")
generate_certs(plugin, REST_HOST, CERTS_PATH)
plugin.log(f"Certificate not found at {rest_certs}. Generating a new certificate!", "debug")
generate_certs(plugin, rest_host, rest_certs)
try:
plugin.log(f"Certs Path: {CERTS_PATH}", "debug")
plugin.log(f"Certs Path: {rest_certs}", "debug")
except Exception as err:
raise Exception(f"{err}: Certificates do not exist at {CERTS_PATH}")
raise Exception(f"{err}: Certificates do not exist at {rest_certs}")
# Assigning only one worker due to added complexity between gunicorn's multiple worker process forks
# and websocket connection's persistance with a single worker.
options = {
"bind": f"{REST_HOST}:{REST_PORT}",
"bind": f"{rest_host}:{rest_port}",
"workers": 1,
"worker_class": "geventwebsocket.gunicorn.workers.GeventWebSocketWorker",
"timeout": 60,
"loglevel": "warning",
"certfile": f"{CERTS_PATH}/client.pem",
"keyfile": f"{CERTS_PATH}/client-key.pem",
"certfile": cert_file.as_posix(),
"keyfile": key_file.as_posix(),
"ssl_version": ssl.PROTOCOL_TLSv1_2
}
return options


class CLNRestApplication(BaseApplication):
def __init__(self, app, options=None):
from utilities.shared import REST_PROTOCOL, REST_HOST, REST_PORT
rest_port = plugin.options["rest-port"]["value"]
rest_host = plugin.options["rest-host"]["value"]
rest_protocol = plugin.options["rest-protocol"]["value"]
self.application = app
self.options = options or {}
plugin.log(f"REST server running at {REST_PROTOCOL}://{REST_HOST}:{REST_PORT}", "info")
plugin.log(f"REST server running at {rest_protocol}://{rest_host}:{rest_port}", "info")
super().__init__()

def load_config(self):
Expand All @@ -181,26 +183,24 @@ def worker():

def start_server():
global jobs
from utilities.shared import REST_PORT
if REST_PORT in jobs:
rest_port = plugin.options["rest-port"]["value"]
if rest_port in jobs:
return False, "server already running"
p = Process(
target=worker,
args=[],
name="server on port {}".format(REST_PORT),
name="server on port {}".format(rest_port),
)
p.daemon = True
jobs[REST_PORT] = p
jobs[rest_port] = p
p.start()
return True


@plugin.init()
def init(options, configuration, plugin):
# We require options before we open a port.
err = set_config(options)
if err:
return {'disable': err}
if "rest-port" not in options:
return {"disable": "`rest-port` option is not configured"}
start_server()


Expand Down
2 changes: 1 addition & 1 deletion plugins/clnrest/utilities/rpc_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
plugin.add_option(name="rest-host", default="127.0.0.1", description="REST server host", opt_type="string", deprecated=False)
plugin.add_option(name="rest-port", default=None, description="REST server port to listen", opt_type="int", deprecated=False)
plugin.add_option(name="rest-cors-origins", default="*", description="Cross origin resource sharing origins", opt_type="string", deprecated=False, multi=True)
plugin.add_option(name="rest-csp", default="default-src 'self'; font-src 'self'; img-src 'self' data:; frame-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline';", description="Content security policy (CSP) for the server", opt_type="string", deprecated=False, multi=True)
plugin.add_option(name="rest-csp", default="default-src 'self'; font-src 'self'; img-src 'self' data:; frame-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline';", description="Content security policy (CSP) for the server", opt_type="string", deprecated=False)
18 changes: 0 additions & 18 deletions plugins/clnrest/utilities/shared.py

This file was deleted.

0 comments on commit cfeea69

Please sign in to comment.