diff --git a/docker/Dockerfile b/docker/Dockerfile index 75846aef..ea941b0a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -20,12 +20,14 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Run python with jemalloc ENV LD_PRELOAD /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 -# Install Jasmin SMS gateway -RUN mkdir -p /etc/jasmin/resource \ - /etc/jasmin/store \ - /var/log/jasmin \ - && chown jasmin:jasmin /etc/jasmin/store \ - /var/log/jasmin +ENV ROOT_PATH / +ENV CONFIG_PATH /etc/jasmin +ENV RESOURCE_PATH /etc/jasmin/resource +ENV STORE_PATH /etc/jasmin/store +ENV LOG_PATH /var/log/jasmin + +RUN mkdir -p ${RESOURCE_PATH} ${STORE_PATH} ${LOG_PATH} +RUN chown jasmin:jasmin ${CONFIG_PATH} ${RESOURCE_PATH} ${STORE_PATH} ${LOG_PATH} WORKDIR /build @@ -35,21 +37,25 @@ RUN pip install . ENV UNICODEMAP_JP unicode-ascii -ENV ROOT_PATH / -ENV CONFIG_PATH /etc/jasmin -ENV RESOURCE_PATH /etc/jasmin/resource -ENV STORE_PATH /etc/jasmin/store -ENV LOG_PATH /var/log/jasmin - COPY misc/config/*.cfg ${CONFIG_PATH}/ COPY misc/config/resource ${RESOURCE_PATH} -WORKDIR /usr/jasmin - -# Change binding host for jcli, redis, and amqp -RUN sed -i '/\[jcli\]/a bind=0.0.0.0' /etc/jasmin/jasmin.cfg -RUN sed -i '/\[redis-client\]/a host=redis' /etc/jasmin/jasmin.cfg -RUN sed -i '/\[amqp-broker\]/a host=rabbitmq' /etc/jasmin/jasmin.cfg +WORKDIR /etc/jasmin + +# Default Redis and RabbitMQ connections +ENV AMQP_BROKER_HOST 'rabbitmq' +ENV AMQP_BROKER_PORT 5672 +ENV REDIS_CLIENT_HOST 'redis' +ENV REDIS_CLIENT_PORT 6379 + +# Change binding host for jcli +RUN sed -i '/\[jcli\]/a bind=0.0.0.0' ${CONFIG_PATH}/jasmin.cfg +# Change binding port for redis, and amqp +RUN sed -i "/\[redis-client\]/a port=$REDIS_CLIENT_PORT" ${CONFIG_PATH}/jasmin.cfg +RUN sed -i "/\[amqp-broker\]/a port=$AMQP_BROKER_PORT" ${CONFIG_PATH}/jasmin.cfg +# Change binding host for redis, and amqp +RUN sed -i "/\[redis-client\]/a host=$REDIS_CLIENT_HOST" ${CONFIG_PATH}/jasmin.cfg +RUN sed -i "/\[amqp-broker\]/a host=$AMQP_BROKER_HOST" ${CONFIG_PATH}/jasmin.cfg EXPOSE 2775 8990 1401 VOLUME ["/var/log/jasmin", "/etc/jasmin", "/etc/jasmin/store"] diff --git a/docker/Dockerfile.restapi b/docker/Dockerfile.restapi index 750a421e..83c18cd1 100644 --- a/docker/Dockerfile.restapi +++ b/docker/Dockerfile.restapi @@ -1,4 +1,4 @@ -FROM python:3-buster +FROM python:3.11-slim-bullseye MAINTAINER Jookies LTD @@ -9,22 +9,24 @@ RUN groupadd -r jasmin && useradd -r -g jasmin jasmin RUN apt-get update && apt-get install -y \ libffi-dev \ libssl-dev \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* + # Run python with jemalloc + # More on this: + # - https://zapier.com/engineering/celery-python-jemalloc/ + # - https://paste.pics/581cc286226407ab0be400b94951a7d9 + libjemalloc2 -# For RestAPI MODE -ENV RESTAPI_MODE 0 -ENV RESTAPI_OLD_HTTP_HOST '127.0.0.1' +RUN apt-get clean && rm -rf /var/lib/apt/lists/* -ENV ENABLE_PUBLISH_SUBMIT_SM_RESP 0 +# Run python with jemalloc +ENV LD_PRELOAD /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ENV ROOT_PATH / ENV CONFIG_PATH /etc/jasmin -ENV RESOURCE_PATH /etc/jasmin/resource -ENV STORE_PATH /etc/jasmin/store +ENV RESOURCE_PATH ${CONFIG_PATH}/resource +ENV STORE_PATH ${CONFIG_PATH}/store ENV LOG_PATH /var/log/jasmin -RUN mkdir -p ${CONFIG_PATH} ${RESOURCE_PATH} ${STORE_PATH} ${LOG_PATH} +RUN mkdir -p ${RESOURCE_PATH} ${STORE_PATH} ${LOG_PATH} RUN chown jasmin:jasmin ${CONFIG_PATH} ${RESOURCE_PATH} ${STORE_PATH} ${LOG_PATH} WORKDIR /build @@ -39,10 +41,22 @@ RUN pip install gunicorn ENV UNICODEMAP_JP unicode-ascii COPY misc/config/*.cfg ${CONFIG_PATH}/ -COPY misc/config/resource/*.xml ${RESOURCE_PATH}/ +COPY misc/config/resource ${RESOURCE_PATH} WORKDIR /etc/jasmin +# Default Redis and RabbitMQ connections +ENV AMQP_BROKER_HOST 'rabbitmq' +ENV AMQP_BROKER_PORT 5672 +ENV REDIS_CLIENT_HOST 'redis' +ENV REDIS_CLIENT_PORT 6379 + +# For RestAPI MODE +ENV RESTAPI_MODE 0 +ENV RESTAPI_OLD_HTTP_HOST '127.0.0.1' + +ENV ENABLE_PUBLISH_SUBMIT_SM_RESP 0 + # Change binding host for jcli RUN sed -i '/\[jcli\]/a bind=0.0.0.0' ${CONFIG_PATH}/jasmin.cfg # Change binding port for redis, and amqp diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 3be0ad3c..cbe1e71e 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -1,6 +1,16 @@ #!/bin/bash set -e +# Change binding host:port for redis, and amqp +sed -i "/\[redis-client\]/,/host=/ s/host=.*/host=$REDIS_CLIENT_HOST/" ${CONFIG_PATH}/jasmin.cfg +sed -i "/\[redis-client\]/,/port=/ s/port=.*/port=$REDIS_CLIENT_PORT/" ${CONFIG_PATH}/jasmin.cfg +sed -i "/\[amqp-broker\]/,/host=/ s/host=.*/host=$AMQP_BROKER_HOST/" ${CONFIG_PATH}/jasmin.cfg +sed -i "/\[amqp-broker\]/,/port=/ s/port=.*/port=$AMQP_BROKER_PORT/" ${CONFIG_PATH}/jasmin.cfg + +echo 'Cleaning lock files' +rm -f /tmp/*.lock + + if [ "$2" = "--enable-interceptor-client" ]; then echo 'Starting interceptord' interceptord.py & diff --git a/docker/restapi-docker-entrypoint.sh b/docker/restapi-docker-entrypoint.sh index 9ece3310..68db4a22 100755 --- a/docker/restapi-docker-entrypoint.sh +++ b/docker/restapi-docker-entrypoint.sh @@ -2,10 +2,10 @@ set -e # Change binding host:port for redis, and amqp -sed -i "/\[redis-client\]/,/host=/ s/host=.*/host=$REDIS_CLIENT_HOST/" /etc/jasmin/jasmin.cfg -sed -i "/\[redis-client\]/,/port=/ s/port=.*/port=$REDIS_CLIENT_PORT/" /etc/jasmin/jasmin.cfg -sed -i "/\[amqp-broker\]/,/host=/ s/host=.*/host=$AMQP_BROKER_HOST/" /etc/jasmin/jasmin.cfg -sed -i "/\[amqp-broker\]/,/port=/ s/port=.*/port=$AMQP_BROKER_PORT/" /etc/jasmin/jasmin.cfg +sed -i "/\[redis-client\]/,/host=/ s/host=.*/host=$REDIS_CLIENT_HOST/" ${CONFIG_PATH}/jasmin.cfg +sed -i "/\[redis-client\]/,/port=/ s/port=.*/port=$REDIS_CLIENT_PORT/" ${CONFIG_PATH}/jasmin.cfg +sed -i "/\[amqp-broker\]/,/host=/ s/host=.*/host=$AMQP_BROKER_HOST/" ${CONFIG_PATH}/jasmin.cfg +sed -i "/\[amqp-broker\]/,/port=/ s/port=.*/port=$AMQP_BROKER_PORT/" ${CONFIG_PATH}/jasmin.cfg echo 'Cleaning lock files' rm -f /tmp/*.lock @@ -23,11 +23,11 @@ else if [ "$ENABLE_PUBLISH_SUBMIT_SM_RESP" = 1 ]; then # Enable publish_submit_sm_resp echo 'Enabling publish_submit_sm_resp' - sed -i "s/.*publish_submit_sm_resp\s*=.*/publish_submit_sm_resp=True/g" /etc/jasmin/jasmin.cfg + sed -i "s/.*publish_submit_sm_resp\s*=.*/publish_submit_sm_resp=True/g" ${CONFIG_PATH}/jasmin.cfg else # Disable publish_submit_sm_resp echo 'Disabling publish_submit_sm_resp' - sed -i "s/.*publish_submit_sm_resp\s*=.*/publish_submit_sm_resp=False/g" /etc/jasmin/jasmin.cfg + sed -i "s/.*publish_submit_sm_resp\s*=.*/publish_submit_sm_resp=False/g" ${CONFIG_PATH}/jasmin.cfg fi if [ "$2" = "--enable-interceptor-client" ]; then diff --git a/jasmin/bin/jasmind.py b/jasmin/bin/jasmind.py index 46fdf567..00745a36 100755 --- a/jasmin/bin/jasmind.py +++ b/jasmin/bin/jasmind.py @@ -60,9 +60,9 @@ class Options(usage.Options): ['enable-dlr-thrower', None, 'Enable DLR Thrower service (not recommended: start the dlrd daemon instead)'], ['enable-dlr-lookup', None, 'Enable DLR Lookup service (not recommended: start the dlrlookupd daemon instead)'], # @TODO: deliver-thrower must be executed as a standalone process, just like dlr-thrower - ['disable-deliver-thrower', None, 'Do not DeliverSm Thrower service'], - ['disable-http-api', None, 'Do not HTTP API'], - ['disable-jcli', None, 'Do not jCli console'], + ['disable-deliver-thrower', None, 'Do not start DeliverSm Thrower service'], + ['disable-http-api', None, 'Do not start HTTP API'], + ['disable-jcli', None, 'Do not start jCli console'], ['enable-interceptor-client', None, 'Start Interceptor client'], ] diff --git a/jasmin/protocols/cli/mointerceptorm.py b/jasmin/protocols/cli/mointerceptorm.py index ba52a89e..42df11f8 100644 --- a/jasmin/protocols/cli/mointerceptorm.py +++ b/jasmin/protocols/cli/mointerceptorm.py @@ -2,6 +2,7 @@ import re import inspect import pickle +import urllib.parse, urllib.request, urllib.error from jasmin.protocols.cli.managers import PersistableManager, Session from jasmin.protocols.cli.filtersm import MOFILTERS from jasmin.routing.jasminApi import MOInterceptorScript @@ -133,9 +134,20 @@ def parse_args_and_call_with_instance(self, *args, **kwargs): stype, script_path = validate_typed_script(arg) if stype == 'python3': - # Open file and get its content - with open(script_path, 'r') as content_file: - pyCode = content_file.read() + pathscheme = urllib.parse.urlparse(script_path).scheme + if pathscheme == '': + # Open file and get its content + with open(script_path, 'r') as content_file: + pyCode = content_file.read() + elif pathscheme in ['https', 'http', 'ftp', 'file']: + try: + with urllib.request.urlopen(script_path) as content_file: + pyCode = content_file.read().decode('utf-8') + except urllib.error.URLError as e: + # Handle errors that may occur while reading the file from a URL + return self.protocol.sendData('[URL]: %s' % str(e)) + else: + raise NotImplementedError("Not implemented yet !") # Test compilation of the script compile(pyCode, '', 'exec') diff --git a/jasmin/protocols/cli/mtinterceptorm.py b/jasmin/protocols/cli/mtinterceptorm.py index 29a2ef28..ae734351 100644 --- a/jasmin/protocols/cli/mtinterceptorm.py +++ b/jasmin/protocols/cli/mtinterceptorm.py @@ -2,6 +2,7 @@ import re import inspect import pickle +import urllib.parse, urllib.request, urllib.error from jasmin.protocols.cli.managers import PersistableManager, Session from jasmin.protocols.cli.filtersm import MTFILTERS from jasmin.routing.jasminApi import MTInterceptorScript @@ -133,9 +134,20 @@ def parse_args_and_call_with_instance(self, *args, **kwargs): stype, script_path = validate_typed_script(arg) if stype == 'python3': - # Open file and get its content - with open(script_path, 'r') as content_file: - pyCode = content_file.read() + pathscheme = urllib.parse.urlparse(script_path).scheme + if pathscheme == '': + # Open file and get its content + with open(script_path, 'r') as content_file: + pyCode = content_file.read() + elif pathscheme in ['https', 'http', 'ftp', 'file']: + try: + with urllib.request.urlopen(script_path) as content_file: + pyCode = content_file.read().decode('utf-8') + except urllib.error.URLError as e: + # Handle errors that may occur while reading the file from a URL + return self.protocol.sendData('[URL]: %s' % str(e)) + else: + raise NotImplementedError("Not implemented yet !") # Test compilation of the script compile(pyCode, '', 'exec') diff --git a/jasmin/protocols/cli/smppccm.py b/jasmin/protocols/cli/smppccm.py index 956b8333..3d48cafc 100644 --- a/jasmin/protocols/cli/smppccm.py +++ b/jasmin/protocols/cli/smppccm.py @@ -67,7 +67,7 @@ def castInputToBuiltInType(key, value): return replace_if_present_flap_value_map[value] elif key == 'priority': return priority_flag_value_map[value] - elif key in ['con_fail_retry', 'con_loss_retry', 'ssl']: + elif key in ['con_fail_retry', 'con_loss_retry', 'ssl', 'logprivacy']: if value == 'yes': return True elif value == 'no': diff --git a/jasmin/protocols/http/endpoints/send.py b/jasmin/protocols/http/endpoints/send.py index 5da155b2..804a2d5b 100644 --- a/jasmin/protocols/http/endpoints/send.py +++ b/jasmin/protocols/http/endpoints/send.py @@ -126,6 +126,13 @@ def route_routable(self, updated_request): # Update SubmitSmPDU by default values from user MtMessagingCredential SubmitSmPDU = v.updatePDUWithUserDefaults(SubmitSmPDU) + + # Force same default values on subPDU while multipart + _pdu = SubmitSmPDU + while hasattr(_pdu, 'nextPdu'): + _pdu = _pdu.nextPdu + _pdu = v.updatePDUWithUserDefaults(_pdu) + # Prepare for interception then routing routedConnector = None # init diff --git a/jasmin/protocols/smpp/factory.py b/jasmin/protocols/smpp/factory.py index 3c4c07ff..1c3ad8b0 100644 --- a/jasmin/protocols/smpp/factory.py +++ b/jasmin/protocols/smpp/factory.py @@ -298,6 +298,12 @@ def submit_sm_event_interceptor(self, system_id, *args): # Update SubmitSmPDU by default values from user MtMessagingCredential SubmitSmPDU = v.updatePDUWithUserDefaults(SubmitSmPDU) + + # Force same default values on subPDU while multipart + _pdu = SubmitSmPDU + while hasattr(_pdu, 'nextPdu'): + _pdu = _pdu.nextPdu + _pdu = v.updatePDUWithUserDefaults(_pdu) if self.RouterPB is None: self.log.error('(submit_sm_event_interceptor/%s) RouterPB not set: submit_sm will not be routed', diff --git a/misc/doc/sources/management/jcli/modules.rst b/misc/doc/sources/management/jcli/modules.rst index f2cf1960..67c3beda 100644 --- a/misc/doc/sources/management/jcli/modules.rst +++ b/misc/doc/sources/management/jcli/modules.rst @@ -736,6 +736,12 @@ Here's an example of adding a **DefaultInterceptor** to a python script:: .. note:: As of now, only **python3** script is permitted. +.. note:: The path to the script can be any of the fallowing: + + * **python3(/path/to/script.py)** or **python3(file://path/to/script.py)**: The path must be absolute, relative path is not supported + * **python3(https://example.com/path/to/script.py)**: The script is a remote python3 script. The script will be + downloaded and copied to Jasmin core. Accepts http, https, and ftp protocols. + .. note:: Pay attention that the given script is copied to Jasmin core, do not expect Jasmin to refresh the script code when you update it, you'll need to redefine the *mointerceptor* rule again so Jasmin will refresh the script.