diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index ef92ef7..f598ec0 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -2,11 +2,11 @@ name: Docker on: schedule: - - cron: '0 1 * * *' + - cron: "0 1 * * *" pull_request: - branches: master + branches: dev push: - branches: master + branches: dev tags: - v* @@ -18,8 +18,7 @@ jobs: steps: - uses: actions/checkout@v2 - - - name: Prepare + - name: Prepare id: prepare run: | DOCKER_IMAGE=sarasmiseth/prosody @@ -46,30 +45,25 @@ jobs: id: buildx uses: crazy-max/ghaction-docker-buildx@v3.1.0 - - - name: Docker Buildx (build) + - name: Docker Buildx (build) run: | docker buildx build --output "type=image,push=false" ${{ steps.prepare.outputs.buildx_args }} - - - name: Docker Login + - name: Docker Login if: success() && github.event_name != 'pull_request' env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: | echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin - - - name: Docker Buildx (push) + - name: Docker Buildx (push) if: success() && github.event_name != 'pull_request' run: | docker buildx build --output "type=image,push=true" ${{ steps.prepare.outputs.buildx_args }} - - - name: Docker Check Manifest + - name: Docker Check Manifest if: always() && github.event_name != 'pull_request' run: | docker run --rm mplatform/mquery ${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }} - - - name: Clear + - name: Clear if: always() && github.event_name != 'pull_request' run: | rm -f ${HOME}/.docker/config.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..dc310ab --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,26 @@ +name: Test + +on: + pull_request: + branches: dev + push: + branches: dev + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository and submodules + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: install python3-venv + run: sudo apt-get install python3-venv + + - name: build test image + run: docker build . -t prosody + + - name: run tests + run: cd ./tests/ && ./test.bash diff --git a/.gitignore b/.gitignore index 07f43b8..9f0f847 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -data/* \ No newline at end of file +data/* +tests/certs/ +tests/venv/ +tests/__pycache__/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4608d8c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "tests/bats/bats-support"] + path = tests/bats/bats-support + url = https://github.com/bats-core/bats-support.git +[submodule "tests/bats/bats-core"] + path = tests/bats/bats-core + url = https://github.com/bats-core/bats-core.git +[submodule "tests/bats/bats-assert"] + path = tests/bats/bats-assert + url = https://github.com/bats-core/bats-assert.git diff --git a/CHANGELOG.md b/CHANGELOG.md index a10c92e..ea1e879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,133 @@ ## Unreleased +### Adjust config + +* Replace deprecated legacy_ssl with c2s_direct_tls. +* Removed use_libevent = true. This means the default is now used which is epoll. + +### Test + +Added a test to check that no deprecated config settings are used. + +## v1.3.0 + +* Updated to Prosody version [0.12.4](https://blog.prosody.im/prosody-0.12.4-released/) + +### Breaking Change + +Switched from [http_upload](https://modules.prosody.im/mod_http_upload) to [http_file_share](https://prosody.im/doc/modules/mod_http_file_share). +This means that previous uploads will NOT work after upgrading. +ENV variable `HTTP_UPLOAD_FILE_SIZE_LIMIT` was removed. + +The new module uses the following variables: + +* HTTP_FILE_SHARE_SIZE_LIMIT +* HTTP_FILE_SHARE_DAILY_QUOTA + +See [readme.md](readme.md) for explanations and defaults. + +## v1.2.10 + +* Update docker base image to debian bookworm +* [Add LDAP authentication support](https://github.com/SaraSmiseth/prosody/pull/50) +* Add environment variable HTTP_MAX_CONTENT_SIZE for setting http_max_content_size. +* Add environment variable HTTP_UPLOAD_FILE_SIZE_LIMIT for setting http_upload_file_size_limit. +* Add domain_http_upload to disco_items to support http_upload on some clients and if http_upload is not a subdomain. + +## v1.2.9 + +* Update prosody to version 0.12.3 +* Update luarocks to version 3.9.2 + +## v1.2.8 + +* Updated to Prosody version [0.12.1](https://blog.prosody.im/prosody-0.12.1-released/). + +## v1.2.7 + +* Updated to Prosody version [0.12.0](https://blog.prosody.im/prosody-0.12.0-released/). +* Updated luarocks to version 3.9.0. + +## v1.2.6 + +* Updated to Prosody version [0.11.13](https://blog.prosody.im/prosody-0.11.13-released/). + +## v1.2.5 + +* Updated to Prosody version [0.11.12](https://blog.prosody.im/prosody-0.11.12-released/). + +## v1.2.4 + +* Updated to Prosody version [0.11.11](https://blog.prosody.im/prosody-0.11.11-released/). +* Updated luarocks to version 3.8.0. + +## v1.2.3 + +* Updated to Prosody version [0.11.10](https://blog.prosody.im/prosody-0.11.10-released/). + +## v1.2.2 + +- Update debian from buster-slim to bullseye-slim (#27) + +## v1.2.1 + +* Updated to Prosody version [0.11.9](https://blog.prosody.im/prosody-0.11.9-released/). + +## v1.2.0 + +### New features + +* New environment variables for database settings. It is now possible to use MariaDB or Postgres instead of SQLite. SQLite is the default. See [README](https://github.com/SaraSmiseth/prosody#environment-variables). + +### Updates + +* Updated luarocks to version 3.7.0. + +## v1.1.4 + +### Updates + +* Updated to Prosody version [0.11.8](https://blog.prosody.im/prosody-0.11.8-released/). +* Updated luarocks to version 3.5.0. + +## v1.1.3 + +### New features + +* Set pidfile in prosody.cfg.lua. +* Created a tests folder which contains pytest and bats tests. + +### Bug fixes + +* Fixed using list ENV variables with multiple values. + +## v1.1.2 + +### Updates + +* Updated to Prosody version [0.11.7](https://blog.prosody.im/prosody-0.11.7-released/). +* Updated luarocks to version 3.4.0. + +### New features + +* Made 04-server_contact_info.cfg.lua configurable with ENV variables. Fixes [#4](https://github.com/SaraSmiseth/prosody/issues/4). +* Made 03-e2e-policy.cfg.lua configurable with ENV variables. Fixes [#9](https://github.com/SaraSmiseth/prosody/issues/9). +* Added E2E_POLICY_WHITELIST ENV variable to configure e2e_policy_whitelist. Fixes [#10](https://github.com/SaraSmiseth/prosody/issues/10). + +### Bug fixes + +* Cherry picked [commit](https://github.com/zipizap/prosody/commit/fa13a990a1b87745ae5f5fe8297cb0669f9e8779) from [zipizap/prosody](https://github.com/zipizap/prosody) which fixes a bug with env-vars not beeing initialized. + +### Other changes + +* Changed hashing of downloaded packages in Dockerfile to sha256. + +## v1.1.1 + +* Updated to Prosody version [0.11.6](https://blog.prosody.im/prosody-0.11.6-released/). +* Replace "master" with "dev". + ## v1.1.0 ### New features diff --git a/Dockerfile b/Dockerfile index fcedc52..22c805b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,32 +1,56 @@ -FROM debian:buster-slim +FROM debian:bookworm-slim + +ARG BUILD_DATE +ARG VCS_REF +ARG VERSION + +ARG LUAROCKS_VERSION=3.11.1 +ARG PROSODY_VERSION=0.12.5 + +ARG LUAROCKS_SHA256="c3fb3d960dffb2b2fe9de7e3cb004dc4d0b34bb3d342578af84f84325c669102" +ARG PROSODY_DOWNLOAD_SHA256="778fb7707a0f10399595ba7ab9c66dd2a2288c0ae3a7fe4ab78f97d462bd399f" + +LABEL luarocks.version="${LUAROCKS_VERSION}" +LABEL org.opencontainers.image.authors="Sara Smiseth" +LABEL org.opencontainers.image.created="${BUILD_DATE}" +LABEL org.opencontainers.image.description="This docker image provides you with a configured Prosody XMPP server." +LABEL org.opencontainers.image.documentation="https://github.com/SaraSmiseth/prosody/blob/dev/readme.md" +LABEL org.opencontainers.image.revision="${VCS_REF}" +LABEL org.opencontainers.image.source="https://github.com/SaraSmiseth/prosody/archive/dev.zip" +LABEL org.opencontainers.image.title="prosody" +LABEL org.opencontainers.image.url="https://github.com/SaraSmiseth/prosody" +LABEL org.opencontainers.image.vendor="Sara Smiseth" +LABEL org.opencontainers.image.version="${VERSION}" +LABEL prosody.version="${PROSODY_VERSION}" RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y \ libevent-dev `# this is no build dependency, but needed for luaevent` \ - libidn11 \ + libicu72 \ + libidn2-0 \ + libpq-dev \ + libsqlite3-0 \ lua5.2 \ lua-bitop \ + lua-dbi-mysql \ + lua-dbi-postgresql \ lua-expat \ lua-filesystem \ + lua-ldap \ lua-socket \ lua-sec \ - sqlite3 \ + lua-unbound \ wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -ENV PROSODY_VERSION 0.11.5 -ENV PROSODY_DOWNLOAD_URL https://prosody.im/downloads/source/prosody-${PROSODY_VERSION}.tar.gz -ENV PROSODY_DOWNLOAD_SHA1 fbe27d3203671a6ecd5ba8233dc4c113fd76cd2e -ENV LUAROCKS_VERSION 3.3.1 - -RUN buildDeps='gcc git libc6-dev libidn11-dev liblua5.2-dev libsqlite3-dev libssl-dev make unzip' \ +RUN buildDeps='gcc git libc6-dev libidn2-dev liblua5.2-dev libsqlite3-dev libssl-dev libicu-dev make unzip' \ && set -x \ && apt-get update && apt-get install -y $buildDeps --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ \ - && wget -O prosody.tar.gz "${PROSODY_DOWNLOAD_URL}" \ - && echo "${PROSODY_DOWNLOAD_SHA1} *prosody.tar.gz" | sha1sum -c - \ + && wget -O prosody.tar.gz "https://prosody.im/downloads/source/prosody-${PROSODY_VERSION}.tar.gz" \ + && echo "${PROSODY_DOWNLOAD_SHA256} *prosody.tar.gz" | sha256sum -c - \ && mkdir -p /usr/src/prosody \ && tar -xzf prosody.tar.gz -C /usr/src/prosody --strip-components=1 \ && rm prosody.tar.gz \ @@ -38,6 +62,7 @@ RUN buildDeps='gcc git libc6-dev libidn11-dev liblua5.2-dev libsqlite3-dev libss && mkdir /usr/src/luarocks \ && cd /usr/src/luarocks \ && wget https://luarocks.org/releases/luarocks-${LUAROCKS_VERSION}.tar.gz \ + && echo "${LUAROCKS_SHA256} luarocks-${LUAROCKS_VERSION}.tar.gz" | sha256sum -c - \ && tar zxpf luarocks-${LUAROCKS_VERSION}.tar.gz \ && cd luarocks-${LUAROCKS_VERSION} \ && ./configure \ @@ -46,7 +71,9 @@ RUN buildDeps='gcc git libc6-dev libidn11-dev liblua5.2-dev libsqlite3-dev libss \ && luarocks install luaevent \ && luarocks install luadbi \ + `#&& luarocks install luadbi-mysql MYSQL_INCDIR=/usr/include/mariadb/` \ && luarocks install luadbi-sqlite3 \ + && luarocks install stringy \ \ && apt-get purge -y --auto-remove $buildDeps @@ -56,33 +83,31 @@ RUN groupadd -r prosody \ && useradd -r -g prosody prosody \ && chown prosody:prosody /usr/local/var/lib/prosody +RUN mkdir -p /var/run/prosody/ \ + && chown prosody:prosody /var/run/prosody/ + # https://github.com/prosody/prosody-docker/issues/25 -ENV __FLUSH_LOG yes +ENV __FLUSH_LOG=yes VOLUME ["/usr/local/var/lib/prosody"] COPY prosody.cfg.lua /usr/local/etc/prosody/prosody.cfg.lua -COPY docker-entrypoint.sh /entrypoint.sh +COPY docker-entrypoint.bash /entrypoint.bash COPY conf.d/*.cfg.lua /usr/local/etc/prosody/conf.d/ COPY *.bash /usr/local/bin/ RUN download-prosody-modules.bash \ && docker-prosody-module-install.bash \ - bookmarks `# XEP-0411: Bookmarks Conversion` \ - carbons `# message carbons (XEP-0280)` \ cloud_notify `# XEP-0357: Push Notifications` \ - csi `# client state indication (XEP-0352)` \ e2e_policy `# require end-2-end encryption` \ filter_chatstates `# disable "X is typing" type messages` \ - smacks `# stream management (XEP-0198)` \ throttle_presence `# presence throttling in CSI` \ - http_upload `# file sharing (XEP-0363)` \ vcard_muc `# XEP-0153: vCard-Based Avatar (MUC)` \ && rm -rf "/usr/src/prosody-modules" USER prosody -ENTRYPOINT ["/entrypoint.sh"] +ENTRYPOINT ["/entrypoint.bash"] CMD ["prosody", "-F"] diff --git a/conf.d/02-storage.cfg.lua b/conf.d/02-storage.cfg.lua index b8cb6d7..29b0711 100644 --- a/conf.d/02-storage.cfg.lua +++ b/conf.d/02-storage.cfg.lua @@ -1,7 +1,12 @@ default_storage = "sql" + sql = { - driver = "SQLite3"; - database = "prosody.sqlite"; + driver = os.getenv("DB_DRIVER") or "SQLite3"; + database = os.getenv("DB_DATABASE") or "prosody.sqlite"; + host = os.getenv("DB_HOST"); + port = os.getenv("DB_PORT"); + username = os.getenv("DB_USERNAME"); + password = os.getenv("DB_PASSWORD"); } -- make 0.10-distributed mod_mam use sql store @@ -15,3 +20,4 @@ storage = { -- https://modules.prosody.im/mod_mam.html archive_expires_after = "1y" +http_max_content_size = os.getenv("HTTP_MAX_CONTENT_SIZE") or 1024 * 1024 * 10 -- Default is 10MB diff --git a/conf.d/03-e2e-policy.cfg.lua b/conf.d/03-e2e-policy.cfg.lua index ba094e5..19fab10 100644 --- a/conf.d/03-e2e-policy.cfg.lua +++ b/conf.d/03-e2e-policy.cfg.lua @@ -1,7 +1,12 @@ -e2e_policy_chat = "required" -e2e_policy_muc = "required" -e2e_policy_whitelist = {} +local stringy = require "stringy" + +e2e_policy_chat = os.getenv("E2E_POLICY_CHAT") or "required" +e2e_policy_muc = os.getenv("E2E_POLICY_MUC") or "required" + +local whitelist = os.getenv("E2E_POLICY_WHITELIST") or "" +e2e_policy_whitelist = stringy.split(whitelist, ", ") + e2e_policy_message_optional_chat = "For security reasons, OMEMO, OTR or PGP encryption is STRONGLY recommended for conversations on this server." e2e_policy_message_required_chat = "For security reasons, OMEMO, OTR or PGP encryption is required for conversations on this server." e2e_policy_message_optional_muc = "For security reasons, OMEMO, OTR or PGP encryption is STRONGLY recommended for MUC on this server." -e2e_policy_message_required_muc = "For security reasons, OMEMO, OTR or PGP encryption is required for MUC on this server." \ No newline at end of file +e2e_policy_message_required_muc = "For security reasons, OMEMO, OTR or PGP encryption is required for MUC on this server." diff --git a/conf.d/04-server_contact_info.cfg.lua b/conf.d/04-server_contact_info.cfg.lua index a1f0d40..971392d 100644 --- a/conf.d/04-server_contact_info.cfg.lua +++ b/conf.d/04-server_contact_info.cfg.lua @@ -1,10 +1,18 @@ +local stringy = require "stringy" + local domain = os.getenv("DOMAIN") +local abuse = os.getenv("SERVER_CONTACT_INFO_ABUSE") or "xmpp:abuse@" .. domain +local admin = os.getenv("SERVER_CONTACT_INFO_ADMIN") or "xmpp:admin@" .. domain +local feedback = os.getenv("SERVER_CONTACT_INFO_FEEDBACK") or "xmpp:feedback@" .. domain +local sales = os.getenv("SERVER_CONTACT_INFO_SALES") or "xmpp:sales@" .. domain +local security = os.getenv("SERVER_CONTACT_INFO_SECURITY") or "xmpp:security@" .. domain +local support = os.getenv("SERVER_CONTACT_INFO_SUPPORT") or "xmpp:support@" .. domain contact_info = { - abuse = { "xmpp:abuse@" .. domain }; - admin = { "xmpp:admin@" .. domain }; - feedback = { "xmpp:feedback@" .. domain }; - sales = { "xmpp:sales@" .. domain }; - security = { "xmpp:security@" .. domain }; - support = { "xmpp:support@" .. domain }; + abuse = stringy.split(abuse, ", "); + admin = stringy.split(admin, ", "); + feedback = stringy.split(feedback, ", "); + sales = stringy.split(sales, ", "); + security = stringy.split(security, ", "); + support = stringy.split(support, ", "); } diff --git a/conf.d/05-vhost.cfg.lua b/conf.d/05-vhost.cfg.lua index e4fe3f1..1f5bcec 100644 --- a/conf.d/05-vhost.cfg.lua +++ b/conf.d/05-vhost.cfg.lua @@ -1,16 +1,16 @@ local domain = os.getenv("DOMAIN") -local domain_http_upload = os.getenv("DOMAIN_HTTP_UPLOAD") -local domain_muc = os.getenv("DOMAIN_MUC") -local domain_proxy = os.getenv("DOMAIN_PROXY") -local domain_pubsub = os.getenv("DOMAIN_PUBSUB") +local domain_http_upload = os.getenv("DOMAIN_HTTP_UPLOAD") or "upload." .. domain +local domain_muc = os.getenv("DOMAIN_MUC") or "conference." .. domain +local domain_proxy = os.getenv("DOMAIN_PROXY") or "proxy." .. domain +local domain_pubsub = os.getenv("DOMAIN_PUBSUB") or "pubsub." .. domain -- XEP-0368: SRV records for XMPP over TLS -- https://compliance.conversations.im/test/xep0368/ -legacy_ssl_ssl = { +c2s_direct_tls_ssl = { certificate = "certs/" .. domain .. "/fullchain.pem"; key = "certs/" .. domain .. "/privkey.pem"; } -legacy_ssl_ports = { 5223 } +c2s_direct_tls_ports = { 5223 } -- https://prosody.im/doc/certificates#service_certificates -- https://prosody.im/doc/ports#ssl_configuration @@ -20,10 +20,16 @@ https_ssl = { } VirtualHost (domain) +disco_items = { + { domain_http_upload }, +} -- Set up a http file upload because proxy65 is not working in muc -Component (domain_http_upload) "http_upload" - http_upload_expire_after = 60 * 60 * 24 * 7 -- a week in seconds +Component (domain_http_upload) "http_file_share" + http_file_share_expires_after = 60 * 60 * 24 * 7 -- a week in seconds + local size_limit = os.getenv("HTTP_FILE_SHARE_SIZE_LIMIT") or 10 * 1024 * 1024 -- Default is 10MB + http_file_share_size_limit = size_limit + http_file_share_daily_quota = os.getenv("HTTP_FILE_SHARE_DAILY_QUOTA") or 10 * size_limit -- Default is 10x the size limit Component (domain_muc) "muc" name = "Prosody Chatrooms" diff --git a/data/.gitkeep b/data/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/docker-entrypoint.bash b/docker-entrypoint.bash new file mode 100755 index 0000000..3d85187 --- /dev/null +++ b/docker-entrypoint.bash @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +if [[ "$1" != "prosody" ]]; then + exec prosodyctl $* + exit 0; +fi + +if [ "$LOCAL" -a "$PASSWORD" -a "$DOMAIN" ] ; then + prosodyctl register $LOCAL $DOMAIN $PASSWORD +fi + +if [ -z "$DOMAIN" ]; then + echo "[ERROR] DOMAIN must be set!" + exit 1 +fi + +exec "$@" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index 4d614f7..0000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -set -e - -if [[ "$1" != "prosody" ]]; then - exec prosodyctl $* - exit 0; -fi - -if [ "$LOCAL" -a "$PASSWORD" -a "$DOMAIN" ] ; then - prosodyctl register $LOCAL $DOMAIN $PASSWORD -fi - -if [ -z "$DOMAIN" ]; then - echo "[ERROR] DOMAIN must be set!" - exit 1 -fi - -export ALLOW_REGISTRATION=${ALLOW_REGISTRATION:-true} -export DOMAIN_HTTP_UPLOAD=${DOMAIN_HTTP_UPLOAD:-"upload.$DOMAIN"} -export DOMAIN_MUC=${DOMAIN_MUC:-"conference.$DOMAIN"} -export DOMAIN_PROXY=${DOMAIN_PROXY:-"proxy.$DOMAIN"} -export DOMAIN_PUBSUB=${DOMAIN_PUBSUB:-"pubsub.$DOMAIN"} -export LOG_LEVEL=${LOG_LEVEL:-"info"} -export C2S_REQUIRE_ENCRYPTION=${C2S_REQUIRE_ENCRYPTION:-true} -export S2S_REQUIRE_ENCRYPTION=${S2S_REQUIRE_ENCRYPTION:-true} -export S2S_SECURE_AUTH=${S2S_SECURE_AUTH:-true} -export PROSODY_ADMINS=${PROSODY_ADMINS:-""} - -exec "$@" diff --git a/prosody.cfg.lua b/prosody.cfg.lua index 9b887b8..b53faeb 100644 --- a/prosody.cfg.lua +++ b/prosody.cfg.lua @@ -1,20 +1,33 @@ -- see example config at https://hg.prosody.im/0.9/file/0.9.10/prosody.cfg.lua.dist -- easily extendable by putting into different config files within conf.d folder -admins = { os.getenv("PROSODY_ADMINS") }; +local stringy = require "stringy" -use_libevent = true; -- improves performance +local prosody_admins = os.getenv("PROSODY_ADMINS") or ""; +admins = stringy.split(prosody_admins, ", "); -allow_registration = os.getenv("ALLOW_REGISTRATION"); +pidfile = "/var/run/prosody/prosody.pid" -c2s_require_encryption = os.getenv("C2S_REQUIRE_ENCRYPTION"); -s2s_require_encryption = os.getenv("S2S_REQUIRE_ENCRYPTION"); -s2s_secure_auth = os.getenv("S2S_SECURE_AUTH"); +allow_registration = os.getenv("ALLOW_REGISTRATION") or "true"; -authentication = "internal_hashed"; +c2s_require_encryption = os.getenv("C2S_REQUIRE_ENCRYPTION") or "true"; +s2s_require_encryption = os.getenv("S2S_REQUIRE_ENCRYPTION") or "true"; +s2s_secure_auth = os.getenv("S2S_SECURE_AUTH") or "true"; + +authentication = os.getenv("AUTHENTICATION") or "internal_hashed"; + +ldap_base = os.getenv("LDAP_BASE"); +ldap_server = os.getenv("LDAP_SERVER") or "localhost"; +ldap_rootdn = os.getenv("LDAP_ROOTDN") or ""; +ldap_password = os.getenv("LDAP_PASSWORD") or ""; +ldap_filter = os.getenv("LDAP_FILTER") or "(uid=$user)"; +ldap_scope = os.getenv("LDAP_SCOPE") or "subtree"; +ldap_tls = os.getenv("LDAP_TLS") or "false"; +ldap_mode = os.getenv("LDAP_MODE") or "bind"; +ldap_admin_filter = os.getenv("LDAP_ADMIN_FILTER") or ""; log = { - {levels = {min = os.getenv("LOG_LEVEL")}, to = "console"}; + {levels = {min = os.getenv("LOG_LEVEL") or "info"}, to = "console"}; }; Include "conf.d/*.cfg.lua"; diff --git a/readme.md b/readme.md index 59a8541..de5ab62 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,13 @@ # Prosody XMPP Docker image -![Docker](https://github.com/SaraSmiseth/prosody/workflows/Docker/badge.svg?branch=master) -[![docker image](https://images.microbadger.com/badges/image/sarasmiseth/prosody:latest.svg)](https://microbadger.com/images/sarasmiseth/prosody:latest) -[![docker pulls](https://img.shields.io/docker/pulls/sarasmiseth/prosody.svg)](https://hub.docker.com/r/sarasmiseth/prosody/) -[![docker stars](https://img.shields.io/docker/stars/sarasmiseth/prosody.svg)](https://hub.docker.com/r/sarasmiseth/prosody/) +![Docker](https://github.com/SaraSmiseth/prosody/workflows/Docker/badge.svg?branch=dev) +![Git repository size](https://img.shields.io/github/repo-size/SaraSmiseth/prosody) +[![Docker pulls](https://img.shields.io/docker/pulls/sarasmiseth/prosody.svg)](https://hub.docker.com/r/sarasmiseth/prosody/) +[![Docker stars](https://img.shields.io/docker/stars/sarasmiseth/prosody.svg)](https://hub.docker.com/r/sarasmiseth/prosody/) +[![Github open issues](https://img.shields.io/github/issues-raw/SaraSmiseth/prosody)](https://github.com/SaraSmiseth/prosody/issues) +[![Github open pull requests](https://img.shields.io/github/issues-pr-raw/SaraSmiseth/prosody)](https://github.com/SaraSmiseth/prosody/pulls) -This docker image provides you with a configured [Prosody](https://prosody.im/) XMPP server. The image is based on `debian:buster-slim`. +This docker image provides you with a configured [Prosody](https://prosody.im/) XMPP server. The image is based on `debian:bookworm-slim`. The server was tested using the Android App [Conversations](https://conversations.im/) and the Desktop client [Gajim](https://gajim.org). Multiple [architectures](https://hub.docker.com/r/sarasmiseth/prosody/tags) are supported. I use it on my raspberry pi 4. @@ -34,11 +36,11 @@ While Conversations got everything set-up out-of-the-box, Gajim was used with th - [Symlinks](#symlinks) - [Permissions](#permissions) - [Run](#run) + - [Volumes permissions](#volumes-permissions) - [Docker tags](#docker-tags) - [Configuration](#configuration) - [Environment variables](#environment-variables) - [DNS](#dns) - - [server_contact_info](#server_contact_info) - [Extend](#extend) - [Upgrade](#upgrade) - [Test your server](#test-your-server) @@ -139,6 +141,7 @@ For example ```cp -L src dest```. ##### Permissions See official [documentation](https://prosody.im/doc/certificates#permissions) for more information. +Check [Volumes permissions](#volumes-permissions) as well. ### Run @@ -149,7 +152,7 @@ version: '3.7' services: server: - image: sarasmiseth/prosody:v1.0.0 + image: sarasmiseth/prosody:latest restart: unless-stopped ports: - "5000:5000" @@ -164,38 +167,75 @@ services: - ./data:/usr/local/var/lib/prosody ``` -Boot it via: ```docker-compose up -d```. +Boot it via: ```docker compose up -d```. -Inspect logs: ```docker-compose logs -f```. +Inspect logs: ```docker compose logs -f```. + +### Volumes permissions + +The prosody user inside the container has the `uid=999` and `gid=999`. If you use the example `docker-compose.yml` from above make sure, that the `./data` folder and the `./certs` folder have the correct permissions. + +``` shell +sudo chown 999:999 ./certs +sudo chown 999:999 ./data +``` ### Docker tags -| Tag | Description | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| edge | This tag points to the latest version build from the newest [commit](https://github.com/SaraSmiseth/prosody/commits/master) in the master branch. | -| nightly | This tag points to the latest version build from the newest [commit](https://github.com/SaraSmiseth/prosody/commits/master) in the master branch. It gets rebuild every night. | -| latest | This tag points to the latest version build from the latest commit that is tagged in git. See [releases](https://github.com/SaraSmiseth/prosody/releases). | -| *vX.Y.Z* | There is a tag for each [release](https://github.com/SaraSmiseth/prosody/releases). | +| Tag | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| edge | This tag points to the latest version build from the newest [commit](https://github.com/SaraSmiseth/prosody/commits/dev) in the dev branch. | +| nightly | This tag points to the latest version build from the newest [commit](https://github.com/SaraSmiseth/prosody/commits/dev) in the dev branch. It gets rebuild every night. | +| latest | This tag points to the latest version build from the latest commit that is tagged in git. See [releases](https://github.com/SaraSmiseth/prosody/releases). | +| *vX.Y.Z* | There is a tag for each [release](https://github.com/SaraSmiseth/prosody/releases). | ### Configuration #### Environment variables -| Variable | Description | Type | Default value | -| -------------------------- | ------------------------------------------------------------------------------------------------------- | ------------ | --------------------- | -| **ALLOW_REGISTRATION** | Whether to allow registration of new accounts via Jabber clients | *optional* | true | -| **DOMAIN** | domain | **required** | null | -| **DOMAIN_HTTP_UPLOAD** | Domain which lets clients upload files over HTTP | *optional* | upload.**DOMAIN** | -| **DOMAIN_MUC** | Domain for Multi-user chat (MUC) for allowing you to create hosted chatrooms/conferences for XMPP users | *optional* | conference.**DOMAIN** | -| **DOMAIN_PROXY** | Domain for SOCKS5 bytestream proxy for server-proxied file transfers | *optional* | proxy.**DOMAIN** | -| **DOMAIN_PUBSUB** | Domain for a XEP-0060 pubsub service | *optional* | pubsub.**DOMAIN** | -| **LOG_LEVEL** | Min log level. Change to debug for more information | *optional* | info | -| **C2S_REQUIRE_ENCRYPTION** | Whether to force all client-to-server connections to be encrypted or not | *optional* | true | -| **S2S_REQUIRE_ENCRYPTION** | Whether to force all server-to-server connections to be encrypted or not | *optional* | true | -| **S2S_SECURE_AUTH** | Require encryption and certificate authentication | *optional* | true | -| **PROSODY_ADMINS** | Specify who is an administrator. List of adresses. Eg. "me@example.com", "admin@example.net" | *optional* | "" | +| Variable | Description | Type | Default value | +| -------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | -------------------------- | +| **ALLOW_REGISTRATION** | Whether to allow registration of new accounts via Jabber clients | *optional* | true | +| **DOMAIN** | domain | **required** | null | +| **DOMAIN_HTTP_UPLOAD** | Domain which lets clients upload files over HTTP | *optional* | upload.**DOMAIN** | +| **DOMAIN_MUC** | Domain for Multi-user chat (MUC) for allowing you to create hosted chatrooms/conferences for XMPP users | *optional* | conference.**DOMAIN** | +| **DOMAIN_PROXY** | Domain for SOCKS5 bytestream proxy for server-proxied file transfers | *optional* | proxy.**DOMAIN** | +| **DOMAIN_PUBSUB** | Domain for a XEP-0060 pubsub service | *optional* | pubsub.**DOMAIN** | +| **AUTHENTICATION** | authentication | *optional* | "internal_hashed" | +| **LDAP_BASE** | LDAP base directory which stores user accounts | **required** if **AUTHENTICATION** is "ldap" | | +| **LDAP_SERVER** | Space-separated list of hostnames or IPs, optionally with port numbers (e.g. “localhost:8389”) | *optional* | "localhost" | +| **LDAP_ROOTDN** | The distinguished name to auth against | *optional* | "" | +| **LDAP_PASSWORD** | Password for rootdn | *optional* | "" | +| **LDAP_FILTER** | Search filter, with $user and $host substituted for user- and hostname | *optional* | "(uid=$user)" | +| **LDAP_SCOPE** | Search scope. other values: “base” and “onelevel” | *optional* | "subtree" | +| **LDAP_TLS** | Enable TLS (StartTLS) to connect to LDAP (can be true or false). The non-standard ‘LDAPS’ protocol is not supported. | *optional* | "false" | +| **LDAP_MODE** | How passwords are validated. | *optional* | "bind" | +| **LDAP_ADMIN_FILTER** | Search filter to match admins, works like ldap_filter | *optional* | "" | +| **DB_DRIVER** | May also be "PostgreSQL" or "MySQL" or "SQLite3" (case sensitive!) | *optional* | SQLite3 | +| **DB_DATABASE** | The database name to use. For SQLite3 this the database filename (relative to the data storage directory). | *optional* | prosody.sqlite | +| **DB_HOST** | The address of the database server | *optional* | | +| **DB_PORT** | Port on which the database is listening | *optional* | | +| **DB_USERNAME** | The username to authenticate to the database | *optional* | | +| **DB_PASSWORD** | The password to authenticate to the database | *optional* | | +| **HTTP_MAX_CONTENT_SIZE** | Max http content size in bytes | *optional* | 10485760 | +| **HTTP_FILE_SHARE_SIZE_LIMIT** | Max http file share size in bytes | *optional* | 10485760 | +| **HTTP_FILE_SHARE_DAILY_QUOTA** | Daily quota in bytes | *optional* | 10 times share size limit | +| **E2E_POLICY_CHAT** | Policy for chat messages. Possible values: "none", "optional" and "required". | *optional* | "required" | +| **E2E_POLICY_MUC** | Policy for MUC messages. Possible values: "none", "optional" and "required". | *optional* | "required" | +| **E2E_POLICY_WHITELIST** | Make this module ignore messages sent to and from this JIDs or MUCs. | *optional* | "" | +| **LOG_LEVEL** | Min log level. Change to debug for more information | *optional* | info | +| **C2S_REQUIRE_ENCRYPTION** | Whether to force all client-to-server connections to be encrypted or not | *optional* | true | +| **S2S_REQUIRE_ENCRYPTION** | Whether to force all server-to-server connections to be encrypted or not | *optional* | true | +| **S2S_SECURE_AUTH** | Require encryption and certificate authentication | *optional* | true | +| **SERVER_CONTACT_INFO_ABUSE** | A list of strings. Each string should be an URI. See [here](https://prosody.im/doc/modules/mod_server_contact_info). | *optional* | "xmpp:abuse@**DOMAIN**" | +| **SERVER_CONTACT_INFO_ADMIN** | A list of strings. Each string should be an URI. See [here](https://prosody.im/doc/modules/mod_server_contact_info). | *optional* | "xmpp:admin@**DOMAIN**" | +| **SERVER_CONTACT_INFO_FEEDBACK** | A list of strings. Each string should be an URI. See [here](https://prosody.im/doc/modules/mod_server_contact_info). | *optional* | "xmpp:feedback@**DOMAIN**" | +| **SERVER_CONTACT_INFO_SALES** | A list of strings. Each string should be an URI. See [here](https://prosody.im/doc/modules/mod_server_contact_info). | *optional* | "xmpp:sales@**DOMAIN**" | +| **SERVER_CONTACT_INFO_SECURITY** | A list of strings. Each string should be an URI. See [here](https://prosody.im/doc/modules/mod_server_contact_info). | *optional* | "xmpp:security@**DOMAIN**" | +| **SERVER_CONTACT_INFO_SUPPORT** | A list of strings. Each string should be an URI. See [here](https://prosody.im/doc/modules/mod_server_contact_info). | *optional* | "xmpp:support@**DOMAIN**" | +| **PROSODY_ADMINS** | Specify who is an administrator. List of adresses. Eg. "me@example.com", "admin@example.net" | *optional* | "" | #### DNS @@ -210,20 +250,6 @@ You need these DNS record pointing to your server: where domain.tld is the environment variable DOMAIN. -#### server_contact_info - -This module lets you advertise various contact addresses for your XMPP service via XEP-0157. -It is configured for the following contacts: - -* abuse -* admin -* feedback -* sales -* security -* support - -You can change them in [05-server_contact_info.cfg.lua](./conf.d/04-server_contact_info.cfg.lua). - ### Extend There is a helper script that eases installing additional prosody modules: ```docker-prosody-module-install``` @@ -239,7 +265,7 @@ If you need additional configuration just overwrite the respective _cfg.lua_ fil When migrating from prosody 0.10, you need to update the database once: ```bash -docker-compose exec server bash +docker compose exec server bash prosodyctl mod_storage_sql upgrade ``` diff --git a/tests/bats/bats-assert b/tests/bats/bats-assert new file mode 160000 index 0000000..397c735 --- /dev/null +++ b/tests/bats/bats-assert @@ -0,0 +1 @@ +Subproject commit 397c735212bf1a06cfdd0cb7806c5a6ea79582bf diff --git a/tests/bats/bats-core b/tests/bats/bats-core new file mode 160000 index 0000000..410dd22 --- /dev/null +++ b/tests/bats/bats-core @@ -0,0 +1 @@ +Subproject commit 410dd229a5ed005c68167cc90ed0712ad2a1c909 diff --git a/tests/bats/bats-support b/tests/bats/bats-support new file mode 160000 index 0000000..3c8fadc --- /dev/null +++ b/tests/bats/bats-support @@ -0,0 +1 @@ +Subproject commit 3c8fadc5097c9acfc96d836dced2bb598e48b009 diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100644 index 0000000..b67723b --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,80 @@ +services: + prosody: + image: prosody + restart: unless-stopped + ports: + - "5000:5000" + - "5222:5222" + - "5223:5223" + - "5269:5269" + - "5281:5281" + environment: + DOMAIN: example.com + E2E_POLICY_WHITELIST: "admin@example.com, user1@example.com" + LOG_LEVEL: debug + PROSODY_ADMINS: "admin@example.com, admin2@example.com" + volumes: + - ./certs:/usr/local/etc/prosody/certs + + prosody_postgres: + image: prosody + restart: unless-stopped + ports: + - "5000:5000" + - "5222:5222" + - "5223:5223" + - "5269:5269" + - "5281:5281" + environment: + DOMAIN: example.com + E2E_POLICY_WHITELIST: "admin@example.com, user1@example.com" + LOG_LEVEL: debug + PROSODY_ADMINS: "admin@example.com, admin2@example.com" + #DB_DRIVER: "MySQL" + DB_DRIVER: "PostgreSQL" + DB_DATABASE: "prosody" + DB_HOST: "postgres" + DB_PORT: "5432" + DB_USERNAME: "prosody" + DB_PASSWORD: "prosody" + volumes: + - ./certs:/usr/local/etc/prosody/certs + depends_on: + - postgres + + postgres: + image: postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_DB: prosody + POSTGRES_USER: prosody + POSTGRES_PASSWORD: prosody + + prosody_ldap: + image: prosody + restart: unless-stopped + ports: + - "5000:5000" + - "5222:5222" + - "5223:5223" + - "5269:5269" + - "5281:5281" + environment: + DOMAIN: example.com + E2E_POLICY_WHITELIST: "admin@example.com, user1@example.com" + LOG_LEVEL: debug + PROSODY_ADMINS: "admin@example.com, admin2@example.com" + AUTHENTICATION: "ldap" + LDAP_BASE: "dc=example,dc=com" + LDAP_SERVER: "glauth" + LDAP_ROOTDN: "cn=svc,dc=example,dc=com" + LDAP_PASSWORD: "12345678" + volumes: + - ./certs:/usr/local/etc/prosody/certs + depends_on: + - glauth + + glauth: + image: glauth/glauth + volumes: + - "./glauth/config.cfg:/app/config/config.cfg" diff --git a/tests/glauth/config.cfg b/tests/glauth/config.cfg new file mode 100644 index 0000000..f180ac4 --- /dev/null +++ b/tests/glauth/config.cfg @@ -0,0 +1,52 @@ +[ldap] + enabled = true + listen = "0.0.0.0:389" + +[ldaps] + enabled = false + +[backend] + datastore = "config" + baseDN = "dc=example,dc=com" + +[[groups]] + name = "svc" + gidnumber = 5500 + +[[groups]] + name = "people" + gidnumber = 5501 + +[[users]] + name = "svc" + uidnumber = 5000 + primarygroup = 5500 + passsha256 = "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f" + +[[users.capabilities]] + action = "search" + object = "*" + +[[users]] + name = "admin" + uidnumber = 5001 + primarygroup = 5501 + passsha256 = "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f" + +[[users]] + name = "user1" + uidnumber = 5002 + primarygroup = 5501 + passsha256 = "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f" + +[[users]] + name = "user2" + uidnumber = 5003 + primarygroup = 5501 + passsha256 = "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f" + +[[users]] + name = "user3" + uidnumber = 5004 + primarygroup = 5501 + passsha256 = "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f" diff --git a/tests/readme.md b/tests/readme.md new file mode 100644 index 0000000..af1c31b --- /dev/null +++ b/tests/readme.md @@ -0,0 +1,28 @@ +# Tests + +Pytest is used to login and send messages to other accounts. +Bats is used to check the log for debug messages. + +## Dependencies + +* docker +* docker-compose +* python 3 + +## Run tests + +Execute [`test.bash`](test.bash). + +## Upgrade python packages + +The following will install the newest version of packages in requirements.txt. + +``` bash +cat requirements.txt | sed 's/==.*//g' | xargs pip install -U +``` + +If updates are available --> update and create new version with: + +``` bash +pip-chill > requirements.txt +``` diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..dbe0b29 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,4 @@ +aioxmpp==0.13.3 +pip-chill==1.0.3 +pytest-asyncio==0.21.0 +pytz==2023.3 diff --git a/tests/test.bash b/tests/test.bash new file mode 100755 index 0000000..33a374b --- /dev/null +++ b/tests/test.bash @@ -0,0 +1,77 @@ +#!/bin/bash + +set -e + +# generate certs for testing + +generateCert() { + local DOMAIN="$1" + if [[ ! -d certs/"$DOMAIN" ]] ; then + mkdir -p certs/"$DOMAIN" + cd certs/"$DOMAIN" + openssl req -x509 -newkey rsa:4096 -keyout privkey.pem -out fullchain.pem -days 365 -subj "/CN=$DOMAIN" -nodes + chmod 777 *.pem + cd ../../ + fi +} + +registerTestUser() { + local userName="$1" + local containerName="$2" + echo "Registering TestUser '$userName' in container '$containerName'" + sudo docker compose exec "$containerName" /bin/bash -c "prosodyctl register $userName example.com 12345678" +} + +registerTestUsers() { + local containerName="$1" + registerTestUser admin "$containerName" + registerTestUser user1 "$containerName" + registerTestUser user2 "$containerName" + registerTestUser user3 "$containerName" +} + +runTests() { + local containerName="$1" + python --version \ + && python3 --version \ + && python3 -m venv venv \ + && source venv/bin/activate \ + && python --version \ + && pip --version \ + && pip install -r requirements.txt \ + && pytest \ + && deactivate \ + && sleep 5 \ + && sudo docker compose logs "$containerName" \ + && export batsContainerName="$containerName" \ + && ./bats/bats-core/bin/bats tests.bats \ + && ./bats/bats-core/bin/bats tests-"$containerName".bats +} + +generateCert "example.com" +generateCert "conference.example.com" +generateCert "proxy.example.com" +generateCert "pubsub.example.com" +generateCert "upload.example.com" + +# Run tests for first container with postgres +# Start postgres first and wait for 10 seconds before starting prosody. +sudo docker compose down +sudo docker compose up -d postgres +sleep 10 +sudo docker compose up -d prosody_postgres + +registerTestUsers prosody_postgres +runTests prosody_postgres +sudo docker compose down + +# Run tests for second container with SQLite +sudo docker compose up -d prosody +registerTestUsers prosody +runTests prosody +sudo docker compose down + +# Run tests for prosody with ldap +sudo docker compose up -d prosody_ldap +runTests prosody_ldap +sudo docker compose down diff --git a/tests/test_prosody.py b/tests/test_prosody.py new file mode 100644 index 0000000..b7b13fa --- /dev/null +++ b/tests/test_prosody.py @@ -0,0 +1,120 @@ +import aiosasl +import aioxmpp +import aioxmpp.dispatcher +import asyncio +import pytest + +@pytest.fixture +def client(client_username, password): + + jid = aioxmpp.JID.fromstr(client_username) + + client = aioxmpp.PresenceManagedClient( + jid, + aioxmpp.make_security_layer( + password, + no_verify=True + ), + override_peer=[("localhost", 5222, aioxmpp.connector.STARTTLSConnector())], + ) + return client + +@pytest.fixture +def client_with_message_dispatcher(client): + def message_received(msg): + print(msg) + print(msg.body) + assert msg.body == "Hello World!" + + # obtain an instance of the service + message_dispatcher = client.summon( + aioxmpp.dispatcher.SimpleMessageDispatcher + ) + + # register a message callback here + message_dispatcher.register_callback( + aioxmpp.MessageType.CHAT, + None, + message_received, + ) + return client + +@pytest.mark.asyncio +@pytest.mark.parametrize("client_username, password", [("admin@example.com", "12345678")]) +async def test_send_message_from_admin_to_user1(client): + recipient_jid = aioxmpp.JID.fromstr("user1@example.com") + async with client.connected() as stream: + msg = aioxmpp.Message( + to=recipient_jid, + type_=aioxmpp.MessageType.CHAT, + ) + # None is for "default language" + msg.body[None] = "Hello World!" + + await client.send(msg) + +@pytest.mark.asyncio +@pytest.mark.parametrize("client_username, password", [("admin@example.com", "12345678")]) +async def test_send_message_from_admin_to_user2(client): + recipient_jid = aioxmpp.JID.fromstr("user2@example.com") + async with client.connected() as stream: + msg = aioxmpp.Message( + to=recipient_jid, + type_=aioxmpp.MessageType.CHAT, + ) + msg.body[None] = "Hello World!" + + await client.send(msg) + +@pytest.mark.asyncio +@pytest.mark.parametrize("client_username, password", [("user1@example.com", "12345678")]) +async def test_send_message_from_user1_to_user2(client): + recipient_jid = aioxmpp.JID.fromstr("user2@example.com") + async with client.connected() as stream: + msg = aioxmpp.Message( + to=recipient_jid, + type_=aioxmpp.MessageType.CHAT, + ) + msg.body[None] = "Hello World!" + + await client.send(msg) + +@pytest.mark.asyncio +@pytest.mark.parametrize("client_username, password", [("user2@example.com", "12345678")]) +async def test_send_message_from_user2_to_user3(client): + recipient_jid = aioxmpp.JID.fromstr("user3@example.com") + async with client.connected() as stream: + msg = aioxmpp.Message( + to=recipient_jid, + type_=aioxmpp.MessageType.CHAT, + ) + msg.body[None] = "Hello World!" + + await client.send(msg) + +@pytest.mark.asyncio +@pytest.mark.parametrize("client_username, password", [("user2@example.com", "12345678")]) +async def test_send_message_from_user2_to_nonexisting(client): + recipient_jid = aioxmpp.JID.fromstr("nonexisting@example.com") + async with client.connected() as stream: + msg = aioxmpp.Message( + to=recipient_jid, + type_=aioxmpp.MessageType.CHAT, + ) + msg.body[None] = "Hello World!" + + await client.send(msg) + +@pytest.mark.asyncio +@pytest.mark.parametrize("client_username, password", [("user2@example.com", "wrong password")]) +async def test_can_not_log_in_with_wrong_password(client): + with pytest.raises(aiosasl.AuthenticationFailure): + recipient_jid = aioxmpp.JID.fromstr("nonexisting@example.com") + async with client.connected() as stream: + msg = aioxmpp.Message( + to=recipient_jid, + type_=aioxmpp.MessageType.CHAT, + ) + msg.body[None] = "Hello World!" + + await client.send(msg) diff --git a/tests/tests-prosody.bats b/tests/tests-prosody.bats new file mode 100644 index 0000000..e2efe54 --- /dev/null +++ b/tests/tests-prosody.bats @@ -0,0 +1,10 @@ +# For tests with pipes see: https://github.com/sstephenson/bats/issues/10 + +load 'bats/bats-support/load' +load 'bats/bats-assert/load' + +@test "Should use sqlite" { + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"Connecting to \[SQLite3\] \/usr\/local\/var\/lib\/prosody\/prosody\.sqlite\.\.\.\"" + assert_success + assert_output +} diff --git a/tests/tests-prosody_ldap.bats b/tests/tests-prosody_ldap.bats new file mode 100644 index 0000000..64c92b2 --- /dev/null +++ b/tests/tests-prosody_ldap.bats @@ -0,0 +1,16 @@ +# For tests with pipes see: https://github.com/sstephenson/bats/issues/10 + +load 'bats/bats-support/load' +load 'bats/bats-assert/load' + +@test "Should use sqlite" { + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"Connecting to \[SQLite3\] \/usr\/local\/var\/lib\/prosody\/prosody\.sqlite\.\.\.\"" + assert_success + assert_output +} + +@test "Should use ldap" { + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"Host 'example.com' now set to use user provider 'ldap'\"" + assert_success + assert_output +} diff --git a/tests/tests-prosody_postgres.bats b/tests/tests-prosody_postgres.bats new file mode 100644 index 0000000..f33fecb --- /dev/null +++ b/tests/tests-prosody_postgres.bats @@ -0,0 +1,10 @@ +# For tests with pipes see: https://github.com/sstephenson/bats/issues/10 + +load 'bats/bats-support/load' +load 'bats/bats-assert/load' + +@test "Should use postgres" { + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"Connecting to \[PostgreSQL\] prosody\.\.\.\"" + assert_success + assert_output +} diff --git a/tests/tests.bats b/tests/tests.bats new file mode 100644 index 0000000..3655520 --- /dev/null +++ b/tests/tests.bats @@ -0,0 +1,98 @@ +# For tests with pipes see: https://github.com/sstephenson/bats/issues/10 + +load 'bats/bats-support/load' +load 'bats/bats-assert/load' + +@test "Should send 5 messages" { + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"Received\[c2s\]: