diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 483ac68..dc310ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - name: Checkout submodules - uses: textbook/git-checkout-submodule-action@master + - name: Checkout repository and submodules + uses: actions/checkout@v2 + with: + submodules: recursive - name: install python3-venv run: sudo apt-get install python3-venv diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a8a49f..ea1e879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,74 @@ ## Unreleased -* Nothing +### 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 diff --git a/Dockerfile b/Dockerfile index 3dbaca3..22c805b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,14 @@ -FROM debian:bullseye-slim +FROM debian:bookworm-slim ARG BUILD_DATE ARG VCS_REF ARG VERSION -ARG LUAROCKS_VERSION=3.7.0 -ARG PROSODY_VERSION=0.11.10 +ARG LUAROCKS_VERSION=3.11.1 +ARG PROSODY_VERSION=0.12.5 -ARG LUAROCKS_SHA256=9255d97fee95cec5b54fc6ac718b11bf5029e45bed7873e053314919cd448551 -ARG PROSODY_DOWNLOAD_SHA256=c6d714e6d4a6ddd1db1266b205d9d8a3ed91818f42755c9268ffb18359d204e1 +ARG LUAROCKS_SHA256="c3fb3d960dffb2b2fe9de7e3cb004dc4d0b34bb3d342578af84f84325c669102" +ARG PROSODY_DOWNLOAD_SHA256="778fb7707a0f10399595ba7ab9c66dd2a2288c0ae3a7fe4ab78f97d462bd399f" LABEL luarocks.version="${LUAROCKS_VERSION}" LABEL org.opencontainers.image.authors="Sara Smiseth" @@ -26,21 +26,25 @@ 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 \ + lua-unbound \ wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -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/* \ @@ -68,7 +72,6 @@ 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-postgresql POSTGRES_INCDIR=/usr/include/postgresql/ \ && luarocks install luadbi-sqlite3 \ && luarocks install stringy \ \ @@ -84,7 +87,7 @@ 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"] @@ -96,15 +99,10 @@ 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" diff --git a/conf.d/02-storage.cfg.lua b/conf.d/02-storage.cfg.lua index 549573a..29b0711 100644 --- a/conf.d/02-storage.cfg.lua +++ b/conf.d/02-storage.cfg.lua @@ -1,8 +1,8 @@ default_storage = "sql" sql = { - driver = os.getenv("DB_DRIVER"); - database = os.getenv("DB_DATABASE"); + 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"); @@ -20,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 88a7ca8..19fab10 100644 --- a/conf.d/03-e2e-policy.cfg.lua +++ b/conf.d/03-e2e-policy.cfg.lua @@ -1,8 +1,11 @@ local stringy = require "stringy" -e2e_policy_chat = os.getenv("E2E_POLICY_CHAT") -e2e_policy_muc = os.getenv("E2E_POLICY_MUC") -e2e_policy_whitelist = stringy.split(os.getenv("E2E_POLICY_WHITELIST"), ", ") +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." diff --git a/conf.d/04-server_contact_info.cfg.lua b/conf.d/04-server_contact_info.cfg.lua index 52437e7..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 = stringy.split(os.getenv("SERVER_CONTACT_INFO_ABUSE"), ", "); - admin = stringy.split(os.getenv("SERVER_CONTACT_INFO_ADMIN"), ", "); - feedback = stringy.split(os.getenv("SERVER_CONTACT_INFO_FEEDBACK"), ", "); - sales = stringy.split(os.getenv("SERVER_CONTACT_INFO_SALES"), ", "); - security = stringy.split(os.getenv("SERVER_CONTACT_INFO_SECURITY"), ", "); - support = stringy.split(os.getenv("SERVER_CONTACT_INFO_SUPPORT"), ", "); + 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/docker-entrypoint.bash b/docker-entrypoint.bash index dd317e0..3d85187 100755 --- a/docker-entrypoint.bash +++ b/docker-entrypoint.bash @@ -1,28 +1,6 @@ #!/bin/bash set -e -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 DB_DRIVER=${DB_DRIVER:-"SQLite3"} -export DB_DATABASE=${DB_DATABASE:-"prosody.sqlite"} -export E2E_POLICY_CHAT=${E2E_POLICY_CHAT:-"required"} -export E2E_POLICY_MUC=${E2E_POLICY_MUC:-"required"} -export E2E_POLICY_WHITELIST=${E2E_POLICY_WHITELIST:-""} -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 SERVER_CONTACT_INFO_ABUSE=${SERVER_CONTACT_INFO_ABUSE:-"xmpp:abuse@$DOMAIN"} -export SERVER_CONTACT_INFO_ADMIN=${SERVER_CONTACT_INFO_ADMIN:-"xmpp:admin@$DOMAIN"} -export SERVER_CONTACT_INFO_FEEDBACK=${SERVER_CONTACT_INFO_FEEDBACK:-"xmpp:feedback@$DOMAIN"} -export SERVER_CONTACT_INFO_SALES=${SERVER_CONTACT_INFO_SALES:-"xmpp:sales@$DOMAIN"} -export SERVER_CONTACT_INFO_SECURITY=${SERVER_CONTACT_INFO_SECURITY:-"xmpp:security@$DOMAIN"} -export SERVER_CONTACT_INFO_SUPPORT=${SERVER_CONTACT_INFO_SUPPORT:-"xmpp:support@$DOMAIN"} -export PROSODY_ADMINS=${PROSODY_ADMINS:-""} - if [[ "$1" != "prosody" ]]; then exec prosodyctl $* exit 0; diff --git a/prosody.cfg.lua b/prosody.cfg.lua index f0b0f3c..b53faeb 100644 --- a/prosody.cfg.lua +++ b/prosody.cfg.lua @@ -3,22 +3,31 @@ local stringy = require "stringy" -admins = stringy.split(os.getenv("PROSODY_ADMINS"), ", "); +local prosody_admins = os.getenv("PROSODY_ADMINS") or ""; +admins = stringy.split(prosody_admins, ", "); pidfile = "/var/run/prosody/prosody.pid" -use_libevent = true; -- improves performance +allow_registration = os.getenv("ALLOW_REGISTRATION") or "true"; -allow_registration = os.getenv("ALLOW_REGISTRATION"); +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"; -c2s_require_encryption = os.getenv("C2S_REQUIRE_ENCRYPTION"); -s2s_require_encryption = os.getenv("S2S_REQUIRE_ENCRYPTION"); -s2s_secure_auth = os.getenv("S2S_SECURE_AUTH"); +authentication = os.getenv("AUTHENTICATION") or "internal_hashed"; -authentication = "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 f33af0e..de5ab62 100644 --- a/readme.md +++ b/readme.md @@ -2,14 +2,12 @@ ![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 image](https://images.microbadger.com/badges/image/sarasmiseth/prosody:latest.svg)](https://microbadger.com/images/sarasmiseth/prosody:latest) -[![Docker version](https://images.microbadger.com/badges/version/sarasmiseth/prosody.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/) [![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. @@ -169,9 +167,9 @@ 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 @@ -197,34 +195,47 @@ sudo chown 999:999 ./data #### 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** | -| **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* | | -| **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* | "" | +| 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 @@ -254,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 index e0de84e..397c735 160000 --- a/tests/bats/bats-assert +++ b/tests/bats/bats-assert @@ -1 +1 @@ -Subproject commit e0de84e9c011223e7f88b7ccf1c929f4327097ba +Subproject commit 397c735212bf1a06cfdd0cb7806c5a6ea79582bf diff --git a/tests/bats/bats-core b/tests/bats/bats-core index 49b377a..410dd22 160000 --- a/tests/bats/bats-core +++ b/tests/bats/bats-core @@ -1 +1 @@ -Subproject commit 49b377a751e6f9379abfdfb3dfa3aafabd8495a1 +Subproject commit 410dd229a5ed005c68167cc90ed0712ad2a1c909 diff --git a/tests/bats/bats-support b/tests/bats/bats-support index d140a65..3c8fadc 160000 --- a/tests/bats/bats-support +++ b/tests/bats/bats-support @@ -1 +1 @@ -Subproject commit d140a65044b2d6810381935ae7f0c94c7023c8c3 +Subproject commit 3c8fadc5097c9acfc96d836dced2bb598e48b009 diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 8c59053..b67723b 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.7' - services: prosody: image: prosody @@ -11,10 +9,10 @@ services: - "5269:5269" - "5281:5281" environment: - DOMAIN: localhost - E2E_POLICY_WHITELIST: "admin@localhost, user1@localhost" + DOMAIN: example.com + E2E_POLICY_WHITELIST: "admin@example.com, user1@example.com" LOG_LEVEL: debug - PROSODY_ADMINS: "admin@localhost, admin2@localhost" + PROSODY_ADMINS: "admin@example.com, admin2@example.com" volumes: - ./certs:/usr/local/etc/prosody/certs @@ -28,10 +26,10 @@ services: - "5269:5269" - "5281:5281" environment: - DOMAIN: localhost - E2E_POLICY_WHITELIST: "admin@localhost, user1@localhost" + DOMAIN: example.com + E2E_POLICY_WHITELIST: "admin@example.com, user1@example.com" LOG_LEVEL: debug - PROSODY_ADMINS: "admin@localhost, admin2@localhost" + PROSODY_ADMINS: "admin@example.com, admin2@example.com" #DB_DRIVER: "MySQL" DB_DRIVER: "PostgreSQL" DB_DATABASE: "prosody" @@ -45,9 +43,38 @@ services: - postgres postgres: - image: postgres:13-alpine + 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/requirements.txt b/tests/requirements.txt index 7bb2363..dbe0b29 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,4 @@ -aioxmpp==0.12.2 -pip-chill==1.0.1 -pytest-asyncio==0.15.1 +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 index 7b1e436..33a374b 100755 --- a/tests/test.bash +++ b/tests/test.bash @@ -5,7 +5,7 @@ set -e # generate certs for testing generateCert() { - DOMAIN="$1" + local DOMAIN="$1" if [[ ! -d certs/"$DOMAIN" ]] ; then mkdir -p certs/"$DOMAIN" cd certs/"$DOMAIN" @@ -18,7 +18,8 @@ generateCert() { registerTestUser() { local userName="$1" local containerName="$2" - sudo docker exec "$containerName" /bin/bash -c "/entrypoint.bash register $userName localhost 12345678" + echo "Registering TestUser '$userName' in container '$containerName'" + sudo docker compose exec "$containerName" /bin/bash -c "prosodyctl register $userName example.com 12345678" } registerTestUsers() { @@ -41,31 +42,36 @@ runTests() { && pytest \ && deactivate \ && sleep 5 \ - && sudo docker-compose logs "$containerName" \ + && sudo docker compose logs "$containerName" \ && export batsContainerName="$containerName" \ && ./bats/bats-core/bin/bats tests.bats \ && ./bats/bats-core/bin/bats tests-"$containerName".bats } -generateCert "localhost" -generateCert "conference.localhost" -generateCert "proxy.localhost" -generateCert "pubsub.localhost" -generateCert "upload.localhost" +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 +sudo docker compose down +sudo docker compose up -d postgres +sleep 10 +sudo docker compose up -d prosody_postgres -registerTestUsers tests_prosody_postgres_1 +registerTestUsers prosody_postgres runTests prosody_postgres -sudo docker-compose down +sudo docker compose down # Run tests for second container with SQLite -sudo docker-compose up -d prosody -registerTestUsers tests_prosody_1 +sudo docker compose up -d prosody +registerTestUsers prosody runTests prosody -sudo docker-compose down +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 index e6c39bc..b7b13fa 100644 --- a/tests/test_prosody.py +++ b/tests/test_prosody.py @@ -15,6 +15,7 @@ def client(client_username, password): password, no_verify=True ), + override_peer=[("localhost", 5222, aioxmpp.connector.STARTTLSConnector())], ) return client @@ -39,9 +40,9 @@ def client_with_message_dispatcher(client): return client @pytest.mark.asyncio -@pytest.mark.parametrize("client_username, password", [("admin@localhost", "12345678")]) +@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@localhost") + recipient_jid = aioxmpp.JID.fromstr("user1@example.com") async with client.connected() as stream: msg = aioxmpp.Message( to=recipient_jid, @@ -53,9 +54,9 @@ async def test_send_message_from_admin_to_user1(client): await client.send(msg) @pytest.mark.asyncio -@pytest.mark.parametrize("client_username, password", [("admin@localhost", "12345678")]) +@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@localhost") + recipient_jid = aioxmpp.JID.fromstr("user2@example.com") async with client.connected() as stream: msg = aioxmpp.Message( to=recipient_jid, @@ -66,9 +67,9 @@ async def test_send_message_from_admin_to_user2(client): await client.send(msg) @pytest.mark.asyncio -@pytest.mark.parametrize("client_username, password", [("user1@localhost", "12345678")]) +@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@localhost") + recipient_jid = aioxmpp.JID.fromstr("user2@example.com") async with client.connected() as stream: msg = aioxmpp.Message( to=recipient_jid, @@ -79,9 +80,9 @@ async def test_send_message_from_user1_to_user2(client): await client.send(msg) @pytest.mark.asyncio -@pytest.mark.parametrize("client_username, password", [("user2@localhost", "12345678")]) +@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@localhost") + recipient_jid = aioxmpp.JID.fromstr("user3@example.com") async with client.connected() as stream: msg = aioxmpp.Message( to=recipient_jid, @@ -92,9 +93,9 @@ async def test_send_message_from_user2_to_user3(client): await client.send(msg) @pytest.mark.asyncio -@pytest.mark.parametrize("client_username, password", [("user2@localhost", "12345678")]) +@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@localhost") + recipient_jid = aioxmpp.JID.fromstr("nonexisting@example.com") async with client.connected() as stream: msg = aioxmpp.Message( to=recipient_jid, @@ -105,10 +106,10 @@ async def test_send_message_from_user2_to_nonexisting(client): await client.send(msg) @pytest.mark.asyncio -@pytest.mark.parametrize("client_username, password", [("user2@localhost", "wrong password")]) +@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@localhost") + recipient_jid = aioxmpp.JID.fromstr("nonexisting@example.com") async with client.connected() as stream: msg = aioxmpp.Message( to=recipient_jid, diff --git a/tests/tests-prosody.bats b/tests/tests-prosody.bats index 74ddc22..e2efe54 100644 --- a/tests/tests-prosody.bats +++ b/tests/tests-prosody.bats @@ -4,7 +4,7 @@ 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\.\.\.\"" + 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 index 2a1d1d0..f33fecb 100644 --- a/tests/tests-prosody_postgres.bats +++ b/tests/tests-prosody_postgres.bats @@ -4,7 +4,7 @@ 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\.\.\.\"" + 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 index 31dac1e..3655520 100644 --- a/tests/tests.bats +++ b/tests/tests.bats @@ -3,93 +3,96 @@ load 'bats/bats-support/load' load 'bats/bats-assert/load' -# group alternation in regex because the xml properties switch around. sometimes 'type=...' comes after 'to=...' and sometimes before @test "Should send 5 messages" { - run bash -c "sudo docker-compose logs $batsContainerName | grep -E \"Received\[c2s\]: \" | wc -l" + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"Received\[c2s\]: - Ensure this can be reached by users\"" + run bash -c "sudo docker compose logs $batsContainerName | grep \"Serving 'file_share' at https:\/\/upload.example.com:5281\/file_share\"" assert_success assert_output } + +@test "Should not use deprecated config" { + run bash -c "sudo docker compose exec $batsContainerName /bin/bash -c \"/entrypoint.bash check\" | grep 'deprecated' -A 3" + assert_failure +} + +@test "Should not have warnings in log" { + run bash -c "sudo docker compose logs $batsContainerName | grep -E \"warn\"" + assert_failure +} diff --git a/update-dependencies.sh b/update-dependencies.sh new file mode 100755 index 0000000..2dc6188 --- /dev/null +++ b/update-dependencies.sh @@ -0,0 +1,14 @@ +#!/bin/zsh + +update_luarocks() { + # Get latest luarocks version and calculate sha256 hash of the tarball + local LUAROCKS_VER=$(wget -q -O - 'https://api.github.com/repos/luarocks/luarocks/tags' | jq -r ".[0].name") + local LUAROCKS_VER=${LUAROCKS_VER#v} + local LUAROCKS_SHA256_HASH=$(wget -q -O - "https://luarocks.org/releases/luarocks-$LUAROCKS_VER.tar.gz" | sha256sum --zero | perl -lane 'print $F[0]') + + # Update Dockerfile + perl -pi -e "s/LUAROCKS_VERSION=\K.*/$LUAROCKS_VER/" Dockerfile + perl -pi -e "s/LUAROCKS_SHA256=\K.*/\"$LUAROCKS_SHA256_HASH\"/" Dockerfile +} + +update_luarocks