diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a0cc4493..5f1322a8 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -25,7 +25,7 @@ jobs: needs: build steps: - name: Add hosts for integration tests - run: sudo echo "127.0.0.1 localhost auth.example.com matrix.example.com matrix1.example.com matrix2.example.com matrix3.example.com federation.example.com" | sudo tee -a /etc/hosts + run: sudo echo "127.0.0.1 localhost auth.example.com matrix.example.com matrix1.example.com matrix2.example.com matrix3.example.com federation.example.com matrix.external.com" | sudo tee -a /etc/hosts - uses: actions/checkout@v3 - name: Set up Node LTS uses: actions/setup-node@v3 diff --git a/docker.md b/docker.md index 455ee516..e23ecafc 100644 --- a/docker.md +++ b/docker.md @@ -26,7 +26,7 @@ $ docker run -d -p 3000:3000 \ -e JITSI_PREFERRED_DOMAIN=meet.tom-dev.xyz \ -e MATRIX_SERVER=matrix.example.com \ -e MATRIX_DATABASE_ENGINE=pg \ - -e MATRIX_DATABASE_HOST=synapse-db \ + -e MATRIX_DATABASE_HOST=synapsedb \ -e MATRIX_DATABASE_NAME=synapse \ -e MATRIX_DATABASE_PASSWORD=synapse!1 \ -e MATRIX_DATABASE_USER=synapse \ diff --git a/package-lock.json b/package-lock.json index e0fbaf7b..b4d7dae4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4959,9 +4959,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.2.tgz", - "integrity": "sha512-VGodkwtEuZ+ENPz/CpDSl091koMv8ao5jHVMbG1vNK+sbx/48/wVzP84M5xSfDAC69mAKKoEkSo+ym9bXYRK9w==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.3.tgz", + "integrity": "sha512-1ACInKIT0pXmTYuPoJAL8sOT0lV3PEACFSVxnD03hGIojJ1CmbzZmLJyk2xew+yxqTlmx7xydkiJcBzdp0V+AQ==", "cpu": [ "arm" ], @@ -4972,9 +4972,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.2.tgz", - "integrity": "sha512-5/W1xyIdc7jw6c/f1KEtg1vYDBWnWCsLiipK41NiaWGLG93eH2edgE6EgQJ3AGiPERhiOLUqlDSfjRK08C9xFg==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.3.tgz", + "integrity": "sha512-vGl+Bny8cawCM7ExugzqEB8ke3t7Pm9/mo+ciA9kJh6pMuNyM+31qhewMwHwseDZ/LtdW0SCocW1CsMxcq1Lsg==", "cpu": [ "arm64" ], @@ -4985,9 +4985,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.2.tgz", - "integrity": "sha512-vOAKMqZSTbPfyPVu1jBiy+YniIQd3MG7LUnqV0dA6Q5tyhdqYtxacTHP1+S/ksKl6qCtMG1qQ0grcIgk/19JEA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.3.tgz", + "integrity": "sha512-Lj8J9WzQRvfWO4GfI+bBkIThUFV1PtI+es/YH/3cwUQ+edXu8Mre0JRJfRrAeRjPiHDPFFZaX51zfgHHEhgRAg==", "cpu": [ "arm64" ], @@ -4998,9 +4998,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.2.tgz", - "integrity": "sha512-aIJVRUS3Dnj6MqocBMrcXlatKm64O3ITeQAdAxVSE9swyhNyV1dwnRgw7IGKIkDQofatd8UqMSyUxuFEa42EcA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.3.tgz", + "integrity": "sha512-NPPOXMTIWJk50lgZmRReEYJFvLG5rgMDzaVauWNB2MgFQYm9HuNXQdVVg3iEZ3A5StIzxhMlPjVyS5fsv4PJmg==", "cpu": [ "x64" ], @@ -5011,9 +5011,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.2.tgz", - "integrity": "sha512-/bjfUiXwy3P5vYr6/ezv//Yle2Y0ak3a+Av/BKoi76nFryjWCkki8AuVoPR7ZU/ckcvAWFo77OnFK14B9B5JsA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.3.tgz", + "integrity": "sha512-ij4tv1XtWcDScaTgoMnvDEYZ2Wjl2ZhDFEyftjBKu6sNNLHIkKuXBol/bVSh+md5zSJ6em9hUXyPO3cVPCsl4Q==", "cpu": [ "arm" ], @@ -5024,9 +5024,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.2.tgz", - "integrity": "sha512-S24b+tJHwpq2TNRz9T+r71FjMvyBBApY8EkYxz8Cwi/rhH6h+lu/iDUxyc9PuHf9UvyeBFYkWWcrDahai/NCGw==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.3.tgz", + "integrity": "sha512-MTMAl30dzcfYB+smHe1sJuS2P1/hB8pqylkCe0/8/Lo8CADjy/eM8x43nBoR5eqcYgpOtCh7IgHpvqSMAE38xw==", "cpu": [ "arm" ], @@ -5037,9 +5037,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.2.tgz", - "integrity": "sha512-UN7VAXLyeyGbCQWiOtQN7BqmjTDw1ON2Oos4lfk0YR7yNhFEJWZiwGtvj9Ay4lsT/ueT04sh80Sg2MlWVVZ+Ug==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.3.tgz", + "integrity": "sha512-vY3fAg6JLDoNh781HHHMPvt8K6RWG3OmEj3xI9BOFSQTD5PNaGKvCB815MyGlDnFYUw7lH+WvvQqoBwLtRDR1A==", "cpu": [ "arm64" ], @@ -5050,9 +5050,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.2.tgz", - "integrity": "sha512-ZBKvz3+rIhQjusKMccuJiPsStCrPOtejCHxTe+yWp3tNnuPWtyCh9QLGPKz6bFNFbwbw28E2T6zDgzJZ05F1JQ==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.3.tgz", + "integrity": "sha512-61SpQGBSb8QkfV/hUYWezlEig4ro55t8NcE5wWmy1bqRsRVHCEDkF534d+Lln/YeLUoSWtJHvvG3bx9lH/S6uA==", "cpu": [ "arm64" ], @@ -5063,9 +5063,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.2.tgz", - "integrity": "sha512-LjMMFiVBRL3wOe095vHAekL4b7nQqf4KZEpdMWd3/W+nIy5o9q/8tlVKiqMbfieDypNXLsxM9fexOxd9Qcklyg==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.3.tgz", + "integrity": "sha512-4XGexJthsNhEEgv/zK4/NnAOjYKoeCsIoT+GkqTY2u3rse0lbJ8ft1bpDCdlkvifsLDL2uwe4fn8PLR4IMTKQQ==", "cpu": [ "ppc64" ], @@ -5076,9 +5076,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.2.tgz", - "integrity": "sha512-ohkPt0lKoCU0s4B6twro2aft+QROPdUiWwOjPNTzwTsBK5w+2+iT9kySdtOdq0gzWJAdiqsV4NFtXOwGZmIsHA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.3.tgz", + "integrity": "sha512-/pArXjqnEdhbQ1qe4CTTlJ6/GjWGdWNRucKAp4fqKnKf7QC0BES3QEV34ACumHHQ4uEGt4GctF2ISCMRhkli0A==", "cpu": [ "riscv64" ], @@ -5089,9 +5089,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.2.tgz", - "integrity": "sha512-jm2lvLc+/gqXfndlpDw05jKvsl/HKYxUEAt1h5UXcMFVpO4vGpoWmJVUfKDtTqSaHcCNw1his1XjkgR9aort3w==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.3.tgz", + "integrity": "sha512-vu4f3Y8iwjtRfSZdmtP8nC1jmRx1IrRVo2cLQlQfpFZ0e2AE9YbPgfIzpuK+i3C4zFETaLLNGezbBns2NuS/uA==", "cpu": [ "s390x" ], @@ -5102,9 +5102,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.2.tgz", - "integrity": "sha512-oc5/SlITI/Vj/qL4UM+lXN7MERpiy1HEOnrE+SegXwzf7WP9bzmZd6+MDljCEZTdSY84CpvUv9Rq7bCaftn1+g==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.3.tgz", + "integrity": "sha512-n4HEgIJulNSmAKT3SYF/1wuzf9od14woSBseNkzur7a+KJIbh2Jb+J9KIsdGt3jJnsLW0BT1Sj6MiwL4Zzku6Q==", "cpu": [ "x64" ], @@ -5115,9 +5115,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.2.tgz", - "integrity": "sha512-/2VWEBG6mKbS2itm7hzPwhIPaxfZh/KLWrYg20pCRLHhNFtF+epLgcBtwy3m07bl/k86Q3PFRAf2cX+VbZbwzQ==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.3.tgz", + "integrity": "sha512-guO/4N1884ig2AzTKPc6qA7OTnFMUEg/X2wiesywRO1eRD7FzHiaiTQQOLFmnUXWj2pgQXIT1g5g3e2RpezXcQ==", "cpu": [ "x64" ], @@ -5128,9 +5128,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.2.tgz", - "integrity": "sha512-Wg7ANh7+hSilF0lG3e/0Oy8GtfTIfEk1327Bw8juZOMOoKmJLs3R+a4JDa/4cHJp2Gs7QfCDTepXXcyFD0ubBg==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.3.tgz", + "integrity": "sha512-+rxD3memdkhGz0NhNqbYHXBoA33MoHBK4uubZjF1IeQv1Psi6tqgsCcC6vwQjxBM1qoCqOQQBy0cgNbbZKnGUg==", "cpu": [ "arm64" ], @@ -5141,9 +5141,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.2.tgz", - "integrity": "sha512-J/jCDKVMWp0Y2ELnTjpQFYUCUWv1Jr+LdFrJVZtdqGyjDo0PHPa7pCamjHvJel6zBFM3doFFqAr7cmXYWBAbfw==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.3.tgz", + "integrity": "sha512-0NxVbLhBXmwANWWbgZY/RdSkeuHEgF+u8Dc0qBowUVBYsR2y2vwVGjKgUcj1wtu3jpjs057io5g9HAPr3Icqjg==", "cpu": [ "ia32" ], @@ -5154,9 +5154,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.2.tgz", - "integrity": "sha512-3nIf+SJMs2ZzrCh+SKNqgLVV9hS/UY0UjT1YU8XQYFGLiUfmHYJ/5trOU1XSvmHjV5gTF/K3DjrWxtyzKKcAHA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.3.tgz", + "integrity": "sha512-hutnZavtOx/G4uVdgoZz5279By9NVbgmxOmGGgnzUjZYuwp2+NzGq6KXQmHXBWz7W/vottXn38QmKYAdQLa/vQ==", "cpu": [ "x64" ], @@ -6945,9 +6945,9 @@ } }, "node_modules/@vanilla-extract/integration/node_modules/rollup": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.2.tgz", - "integrity": "sha512-sxDP0+pya/Yi5ZtptF4p3avI+uWCIf/OdrfdH2Gbv1kWddLKk0U7WE3PmQokhi5JrektxsK3sK8s4hzAmjqahw==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.3.tgz", + "integrity": "sha512-Ygm4fFO4usWcAG3Ud36Lmif5nudoi0X6QPLC+kRgrRjulAbmFkaTawP7fTIkRDnCNSf/4IAQzXM1T8e691kRtw==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -6960,22 +6960,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.16.2", - "@rollup/rollup-android-arm64": "4.16.2", - "@rollup/rollup-darwin-arm64": "4.16.2", - "@rollup/rollup-darwin-x64": "4.16.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.16.2", - "@rollup/rollup-linux-arm-musleabihf": "4.16.2", - "@rollup/rollup-linux-arm64-gnu": "4.16.2", - "@rollup/rollup-linux-arm64-musl": "4.16.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.16.2", - "@rollup/rollup-linux-riscv64-gnu": "4.16.2", - "@rollup/rollup-linux-s390x-gnu": "4.16.2", - "@rollup/rollup-linux-x64-gnu": "4.16.2", - "@rollup/rollup-linux-x64-musl": "4.16.2", - "@rollup/rollup-win32-arm64-msvc": "4.16.2", - "@rollup/rollup-win32-ia32-msvc": "4.16.2", - "@rollup/rollup-win32-x64-msvc": "4.16.2", + "@rollup/rollup-android-arm-eabi": "4.16.3", + "@rollup/rollup-android-arm64": "4.16.3", + "@rollup/rollup-darwin-arm64": "4.16.3", + "@rollup/rollup-darwin-x64": "4.16.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.16.3", + "@rollup/rollup-linux-arm-musleabihf": "4.16.3", + "@rollup/rollup-linux-arm64-gnu": "4.16.3", + "@rollup/rollup-linux-arm64-musl": "4.16.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.16.3", + "@rollup/rollup-linux-riscv64-gnu": "4.16.3", + "@rollup/rollup-linux-s390x-gnu": "4.16.3", + "@rollup/rollup-linux-x64-gnu": "4.16.3", + "@rollup/rollup-linux-x64-musl": "4.16.3", + "@rollup/rollup-win32-arm64-msvc": "4.16.3", + "@rollup/rollup-win32-ia32-msvc": "4.16.3", + "@rollup/rollup-win32-x64-msvc": "4.16.3", "fsevents": "~2.3.2" } }, @@ -17935,9 +17935,9 @@ "dev": true }, "node_modules/node-abi": { - "version": "3.60.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.60.0.tgz", - "integrity": "sha512-zcGgwoXbzw9NczqbGzAWL/ToDYAxv1V8gL1D67ClbdkIfeeDBbY0GelZtC25ayLvVjr2q2cloHeQV1R0QAWqRQ==", + "version": "3.61.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.61.0.tgz", + "integrity": "sha512-dYDO1rxzvMXjEMi37PBeFuYgwh3QZpsw/jt+qOmnRSwiV4z4c+OLoRlTa3V8ID4TrkSQpzCVc9OI2sstFaINfQ==", "optional": true, "dependencies": { "semver": "^7.3.5" @@ -26457,9 +26457,9 @@ } }, "node_modules/vite-node/node_modules/rollup": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.2.tgz", - "integrity": "sha512-sxDP0+pya/Yi5ZtptF4p3avI+uWCIf/OdrfdH2Gbv1kWddLKk0U7WE3PmQokhi5JrektxsK3sK8s4hzAmjqahw==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.3.tgz", + "integrity": "sha512-Ygm4fFO4usWcAG3Ud36Lmif5nudoi0X6QPLC+kRgrRjulAbmFkaTawP7fTIkRDnCNSf/4IAQzXM1T8e691kRtw==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -26472,22 +26472,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.16.2", - "@rollup/rollup-android-arm64": "4.16.2", - "@rollup/rollup-darwin-arm64": "4.16.2", - "@rollup/rollup-darwin-x64": "4.16.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.16.2", - "@rollup/rollup-linux-arm-musleabihf": "4.16.2", - "@rollup/rollup-linux-arm64-gnu": "4.16.2", - "@rollup/rollup-linux-arm64-musl": "4.16.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.16.2", - "@rollup/rollup-linux-riscv64-gnu": "4.16.2", - "@rollup/rollup-linux-s390x-gnu": "4.16.2", - "@rollup/rollup-linux-x64-gnu": "4.16.2", - "@rollup/rollup-linux-x64-musl": "4.16.2", - "@rollup/rollup-win32-arm64-msvc": "4.16.2", - "@rollup/rollup-win32-ia32-msvc": "4.16.2", - "@rollup/rollup-win32-x64-msvc": "4.16.2", + "@rollup/rollup-android-arm-eabi": "4.16.3", + "@rollup/rollup-android-arm64": "4.16.3", + "@rollup/rollup-darwin-arm64": "4.16.3", + "@rollup/rollup-darwin-x64": "4.16.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.16.3", + "@rollup/rollup-linux-arm-musleabihf": "4.16.3", + "@rollup/rollup-linux-arm64-gnu": "4.16.3", + "@rollup/rollup-linux-arm64-musl": "4.16.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.16.3", + "@rollup/rollup-linux-riscv64-gnu": "4.16.3", + "@rollup/rollup-linux-s390x-gnu": "4.16.3", + "@rollup/rollup-linux-x64-gnu": "4.16.3", + "@rollup/rollup-linux-x64-musl": "4.16.3", + "@rollup/rollup-win32-arm64-msvc": "4.16.3", + "@rollup/rollup-win32-ia32-msvc": "4.16.3", + "@rollup/rollup-win32-x64-msvc": "4.16.3", "fsevents": "~2.3.2" } }, diff --git a/packages/federation-server/src/__testData__/docker-compose.yml b/packages/federation-server/src/__testData__/docker-compose.yml index ddb51bf3..df75879e 100644 --- a/packages/federation-server/src/__testData__/docker-compose.yml +++ b/packages/federation-server/src/__testData__/docker-compose.yml @@ -3,6 +3,7 @@ version: '3.8' services: postgresql: image: postgres:13-bullseye + container_name: postgresql volumes: - ./synapse-data/matrix.example.com.log.config:/data/matrix.example.com.log.config - ./db/init-synapse-db.sh:/docker-entrypoint-initdb.d/init-synapse-db.sh @@ -23,6 +24,7 @@ services: synapse-federation: &synapse_template image: matrixdotorg/synapse:v1.89.0 + container_name: synapse-federation volumes: - ./synapse-data:/data - ./nginx/ssl/ca.pem:/etc/ssl/certs/ca.pem @@ -44,6 +46,7 @@ services: synapse-1: <<: *synapse_template + container_name: synapse-1 environment: - UID=${MYUID} - VIRTUAL_PORT=8008 @@ -52,6 +55,7 @@ services: synapse-2: <<: *synapse_template + container_name: synapse-2 environment: - UID=${MYUID} - VIRTUAL_PORT=8008 @@ -60,6 +64,7 @@ services: synapse-3: <<: *synapse_template + container_name: synapse-3 environment: - UID=${MYUID} - VIRTUAL_PORT=8008 @@ -93,6 +98,7 @@ services: federation-server: image: federation-server + container_name: federation-server build: context: ../../../.. dockerfile: ./packages/federation-server/Dockerfile @@ -117,6 +123,7 @@ services: identity-server-1: &identity-server-template image: identity-server + container_name: identity-server-1 build: context: ../../../.. dockerfile: ./packages/federation-server/src/__testData__/identity-server/Dockerfile @@ -139,6 +146,7 @@ services: identity-server-2: <<: *identity-server-template + container_name: identity-server-2 depends_on: annuaire: condition: service_started @@ -156,6 +164,7 @@ services: identity-server-3: <<: *identity-server-template + container_name: identity-server-3 depends_on: annuaire: condition: service_started @@ -173,6 +182,7 @@ services: nginx-proxy: image: nginxproxy/nginx-proxy + container_name: nginx-proxy ports: - 443:443 volumes: diff --git a/packages/federation-server/src/index.test.ts b/packages/federation-server/src/index.test.ts index d374d670..0a149ff5 100644 --- a/packages/federation-server/src/index.test.ts +++ b/packages/federation-server/src/index.test.ts @@ -1,5 +1,4 @@ import { Hash } from '@twake/crypto' -import dockerComposeV1, { v2 as dockerComposeV2 } from 'docker-compose' import express from 'express' import fs from 'fs' import type * as http from 'http' @@ -57,7 +56,6 @@ describe('Federation server', () => { }) describe('Integration tests', () => { - let containerNameSuffix: string let startedCompose: StartedDockerComposeEnvironment let identity1IPAddress: string let identity2IPAddress: string @@ -172,43 +170,17 @@ describe('Federation server', () => { syswideCas.addCAs( path.join(pathToTestDataFolder, 'nginx', 'ssl', 'ca.pem') ) - Promise.allSettled([dockerComposeV1.version(), dockerComposeV2.version()]) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((results) => { - const promiseSucceededIndex = results.findIndex( - (res) => res.status === 'fulfilled' - ) - if (promiseSucceededIndex === -1) { - throw new Error('Docker compose is not installed') - } - containerNameSuffix = promiseSucceededIndex === 0 ? '_' : '-' - return new DockerComposeEnvironment( - path.join(pathToTestDataFolder), - 'docker-compose.yml' - ) - .withEnvironment({ MYUID: os.userInfo().uid.toString() }) - .withWaitStrategy( - `postgresql${containerNameSuffix}1`, - Wait.forHealthCheck() - ) - .withWaitStrategy( - `synapse-federation${containerNameSuffix}1`, - Wait.forHealthCheck() - ) - .withWaitStrategy( - `synapse-1${containerNameSuffix}1`, - Wait.forHealthCheck() - ) - .withWaitStrategy( - `synapse-2${containerNameSuffix}1`, - Wait.forHealthCheck() - ) - .withWaitStrategy( - `synapse-3${containerNameSuffix}1`, - Wait.forHealthCheck() - ) - .up() - }) + new DockerComposeEnvironment( + path.join(pathToTestDataFolder), + 'docker-compose.yml' + ) + .withEnvironment({ MYUID: os.userInfo().uid.toString() }) + .withWaitStrategy('postgresql', Wait.forHealthCheck()) + .withWaitStrategy('synapse-federation', Wait.forHealthCheck()) + .withWaitStrategy('synapse-1', Wait.forHealthCheck()) + .withWaitStrategy('synapse-2', Wait.forHealthCheck()) + .withWaitStrategy('synapse-3', Wait.forHealthCheck()) + .up() // eslint-disable-next-line @typescript-eslint/promise-function-async .then((upResult) => { startedCompose = upResult @@ -275,10 +247,10 @@ describe('Federation server', () => { beforeAll((done) => { identity1IPAddress = startedCompose - .getContainer(`identity-server-1${containerNameSuffix}1`) + .getContainer(`identity-server-1`) .getIpAddress('test') identity2IPAddress = startedCompose - .getContainer(`identity-server-2${containerNameSuffix}1`) + .getContainer(`identity-server-2`) .getIpAddress('test') confOriginalContent = fs.readFileSync( @@ -295,9 +267,8 @@ describe('Federation server', () => { 'utf-8' ) - federationServerContainer = startedCompose.getContainer( - `federation-server${containerNameSuffix}1` - ) + federationServerContainer = + startedCompose.getContainer('federation-server') federationServerContainer .restart() @@ -746,25 +717,19 @@ describe('Federation server', () => { 'Certificates files for federation server has not been created' ) return Promise.all([ - startedCompose - .getContainer(`identity-server-1${containerNameSuffix}1`) - .restart(), - startedCompose - .getContainer(`identity-server-2${containerNameSuffix}1`) - .restart(), - startedCompose - .getContainer(`identity-server-3${containerNameSuffix}1`) - .restart() + startedCompose.getContainer('identity-server-1').restart(), + startedCompose.getContainer('identity-server-2').restart(), + startedCompose.getContainer('identity-server-3').restart() ]) }) // eslint-disable-next-line @typescript-eslint/promise-function-async .then(() => { identity1IPAddress = startedCompose - .getContainer(`identity-server-1${containerNameSuffix}1`) + .getContainer(`identity-server-1`) .getIpAddress('test') identity2IPAddress = startedCompose - .getContainer(`identity-server-2${containerNameSuffix}1`) + .getContainer(`identity-server-2`) .getIpAddress('test') const testConfig: Config = { @@ -776,16 +741,16 @@ describe('Federation server', () => { database_user: 'twake', database_password: 'twake!1', database_host: `${startedCompose - .getContainer(`postgresql${containerNameSuffix}1`) + .getContainer(`postgresql`) .getHost()}:5432`, database_name: 'federation', ldap_base: 'dc=example,dc=com', ldap_uri: `ldap://${startedCompose - .getContainer(`postgresql${containerNameSuffix}1`) + .getContainer(`postgresql`) .getHost()}:389`, matrix_database_engine: 'pg', matrix_database_host: `${startedCompose - .getContainer(`postgresql${containerNameSuffix}1`) + .getContainer(`postgresql`) .getHost()}:5432`, matrix_database_name: 'synapsefederation', matrix_database_user: 'synapse', diff --git a/packages/matrix-application-server/src/routes/index.ts b/packages/matrix-application-server/src/routes/index.ts index 53980fde..fb1db0c3 100644 --- a/packages/matrix-application-server/src/routes/index.ts +++ b/packages/matrix-application-server/src/routes/index.ts @@ -78,16 +78,14 @@ export default class MASRouter { * 500: * $ref: '#/components/responses/InternalServerError' */ - this.routes - .route('/_matrix/app/v1/transactions/:txnId') - .put( - this._middlewares( - transaction(this._appServer), - validation(Endpoints.TRANSACTIONS), - this.defaultAuthMiddleware - ) - ) - .all(allowCors, methodNotAllowed, errorMiddleware) + this.addRoute( + this.routes, + '/_matrix/app/v1/transactions/:txnId', + EHttpMethod.PUT, + transaction(this._appServer), + validation(Endpoints.TRANSACTIONS), + this.defaultAuthMiddleware + ) /** * @openapi @@ -119,16 +117,14 @@ export default class MASRouter { * 500: * $ref: '#/components/responses/InternalServerError' */ - this.routes - .route('/_matrix/app/v1/users/:userId') - .get( - this._middlewares( - query, - validation(Endpoints.USERS), - this.defaultAuthMiddleware - ) - ) - .all(allowCors, methodNotAllowed, errorMiddleware) + this.addRoute( + this.routes, + '/_matrix/app/v1/users/:userId', + EHttpMethod.GET, + query, + validation(Endpoints.USERS), + this.defaultAuthMiddleware + ) /** * @openapi @@ -160,16 +156,14 @@ export default class MASRouter { * 500: * $ref: '#/components/responses/InternalServerError' */ - this.routes - .route('/_matrix/app/v1/rooms/:roomAlias') - .get( - this._middlewares( - query, - validation(Endpoints.ROOMS), - this.defaultAuthMiddleware - ) - ) - .all(allowCors, methodNotAllowed, errorMiddleware) + this.addRoute( + this.routes, + '/_matrix/app/v1/rooms/:roomAlias', + EHttpMethod.GET, + query, + validation(Endpoints.ROOMS), + this.defaultAuthMiddleware + ) this.routes .route(/^\/(users|rooms|transactions)\/[a-zA-Z0-9]*/g) @@ -195,13 +189,14 @@ export default class MASRouter { } public addRoute( + router: Router, path: string, method: EHttpMethod, controller: expressAppHandler, validators: ValidationChain[], authMiddleware?: expressAppHandler ): void { - const route: IRoute = this.routes.route(path) + const route: IRoute = router.route(path) switch (method) { case EHttpMethod.DELETE: route.delete(this._middlewares(controller, validators, authMiddleware)) diff --git a/packages/matrix-application-server/src/routes/routes.test.ts b/packages/matrix-application-server/src/routes/routes.test.ts index 7747d121..295cda60 100644 --- a/packages/matrix-application-server/src/routes/routes.test.ts +++ b/packages/matrix-application-server/src/routes/routes.test.ts @@ -73,6 +73,7 @@ describe('MASRouter', () => { const keys = Object.keys(newRoutes) keys.forEach((method) => { router.addRoute( + router.routes, newRoutes[method].path, method as EHttpMethod, (req, res, next) => {}, diff --git a/packages/matrix-identity-server/src/matrixDb/index.ts b/packages/matrix-identity-server/src/matrixDb/index.ts index dc8d4766..34cd466a 100644 --- a/packages/matrix-identity-server/src/matrixDb/index.ts +++ b/packages/matrix-identity-server/src/matrixDb/index.ts @@ -25,10 +25,16 @@ type Match = ( */ type GetAll = (table: Collections, fields: string[]) => Promise +type Insert = ( + table: Collections, + values: Record +) => Promise + export interface MatrixDBBackend { ready: Promise get: Get getAll: GetAll + insert: Insert // match: Match close: () => void } @@ -79,6 +85,11 @@ class MatrixDB implements MatrixDBBackend { return await this.db.get(table, fields, filterFields) } + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/promise-function-async + insert(table: Collections, values: Record) { + return this.db.insert(table, values) + } + close(): void { this.db.close() } diff --git a/packages/matrix-identity-server/src/matrixDb/sql/sqlite.ts b/packages/matrix-identity-server/src/matrixDb/sql/sqlite.ts index 6e6fbba2..4a130d46 100644 --- a/packages/matrix-identity-server/src/matrixDb/sql/sqlite.ts +++ b/packages/matrix-identity-server/src/matrixDb/sql/sqlite.ts @@ -1,7 +1,7 @@ -import { type Collections } from '../../db' import { type MatrixDBBackend } from '../' -import { type Config } from '../../types' +import { type Collections } from '../../db' import SQLite from '../../db/sql/sqlite' +import { type Config } from '../../types' class MatrixDBSQLite extends SQLite implements MatrixDBBackend { // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -21,8 +21,7 @@ class MatrixDBSQLite extends SQLite implements MatrixDBBackend { /* istanbul ignore next */ // @ts-ignore if (sqlite3.Database == null) sqlite3 = sqlite3.default const db = (this.db = new sqlite3.Database( - conf.matrix_database_host as string, - sqlite3.OPEN_READONLY + conf.matrix_database_host as string )) /* istanbul ignore if */ if (db == null) { diff --git a/packages/tom-server/src/administration-console-api/__testData__/build-userdb.ts b/packages/tom-server/src/administration-console-api/__testData__/build-userdb.ts new file mode 100644 index 00000000..83d68032 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/build-userdb.ts @@ -0,0 +1,79 @@ +import sqlite3 from 'sqlite3' +import { type Config } from '../../types' + +let created = false + +const createQuery = + 'CREATE TABLE users (uid varchar(8), mobile varchar(12), mail varchar(32), sn varchar(32))' +const insertQueries = [ + "INSERT INTO users VALUES('dwho', '33612345678', 'dwho@company.com', 'Dwho')", + "INSERT INTO users VALUES('rtyler', '33687654321', 'rtyler@company.com', 'Rtyler')" +] + +// eslint-disable-next-line @typescript-eslint/promise-function-async +export const buildUserDB = (conf: Config): Promise => { + if (created) return Promise.resolve() + return new Promise((resolve, reject) => { + const matrixDb = new sqlite3.Database(conf.matrix_database_host) + matrixDb.run( + 'CREATE TABLE users (name text, desactivated text, admin integer)', + (err) => { + if (err != null) { + reject(err) + } else { + matrixDb.run( + "INSERT INTO users VALUES('@dwho:example.com', '', 0)", + (err) => { + if (err != null) { + reject(err) + } else { + matrixDb.close((err) => { + /* istanbul ignore if */ + if (err != null) { + console.error(err) + reject(err) + } else { + const userDb = new sqlite3.Database( + conf.userdb_host as string + ) + userDb.run(createQuery, (err) => { + if (err != null) { + reject(err) + } else { + Promise.all( + insertQueries.map( + // eslint-disable-next-line @typescript-eslint/promise-function-async + (query) => + new Promise((_resolve, _reject) => { + userDb.run(query, (err) => { + err != null ? _reject(err) : _resolve(true) + }) + }) + ) + ) + .then(() => { + userDb.close((err) => { + /* istanbul ignore if */ + if (err != null) { + console.error(err) + reject(err) + } else { + created = true + resolve() + } + }) + }) + + .catch(reject) + } + }) + } + }) + } + } + ) + } + } + ) + }) +} \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/db/init-llng-db.sh b/packages/tom-server/src/administration-console-api/__testData__/db/init-llng-db.sh new file mode 100644 index 00000000..ba2e587e --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/db/init-llng-db.sh @@ -0,0 +1,95 @@ +#!/bin/sh +set -e + +DATABASE=${PG_DATABASE:-lemonldapng} +USER=${PG_USER:-lemonldap} +PASSWORD=${PG_PASSWORD:-lemonldap} +TABLE=${PG_TABLE:-lmConfig} +PTABLE=${PG_PERSISTENT_SESSIONS_TABLE:-psessions} +STABLE=${PG_SESSIONS_TABLE:-sessions} +SAMLTABLE=${PG_SAML_TABLE:-samlsessions} +OIDCTABLE=${PG_OIDC_TABLE:-oidcsessions} +CASTABLE=${PG_CAS_TABLE:-cassessions} + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE USER $USER PASSWORD '$PASSWORD'; + CREATE DATABASE $DATABASE; +EOSQL +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE" <<-EOSQL + CREATE TABLE $TABLE ( + cfgNum integer not null primary key, + data text + ); + GRANT ALL PRIVILEGES ON TABLE $TABLE TO $USER; + + CREATE TABLE $PTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_p__session_kind ON psessions ((a_session ->> '_session_kind')); + CREATE INDEX i_p__httpSessionType ON psessions ((a_session ->> '_httpSessionType')); + CREATE INDEX i_p__session_uid ON psessions ((a_session ->> '_session_uid')); + CREATE INDEX i_p_ipAddr ON psessions ((a_session ->> 'ipAddr')); + CREATE INDEX i_p__whatToTrace ON psessions ((a_session ->> '_whatToTrace')); + GRANT ALL PRIVILEGES ON TABLE $PTABLE TO $USER; + + CREATE UNLOGGED TABLE $STABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_s__whatToTrace ON sessions ((a_session ->> '_whatToTrace')); + CREATE INDEX i_s__session_kind ON sessions ((a_session ->> '_session_kind')); + CREATE INDEX i_s__utime ON sessions ((cast (a_session ->> '_utime' as bigint))); + CREATE INDEX i_s_ipAddr ON sessions ((a_session ->> 'ipAddr')); + CREATE INDEX i_s__httpSessionType ON sessions ((a_session ->> '_httpSessionType')); + CREATE INDEX i_s_user ON sessions ((a_session ->> 'user')); + GRANT ALL PRIVILEGES ON TABLE $STABLE TO $USER; + + CREATE UNLOGGED TABLE $SAMLTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_a__session_kind ON $SAMLTABLE ((a_session ->> '_session_kind')); + CREATE INDEX i_a__utime ON $SAMLTABLE ((cast(a_session ->> '_utime' as bigint))); + CREATE INDEX i_a_ProxyID ON $SAMLTABLE ((a_session ->> 'ProxyID')); + CREATE INDEX i_a__nameID ON $SAMLTABLE ((a_session ->> '_nameID')); + CREATE INDEX i_a__assert_id ON $SAMLTABLE ((a_session ->> '_assert_id')); + CREATE INDEX i_a__art_id ON $SAMLTABLE ((a_session ->> '_art_id')); + CREATE INDEX i_a__saml_id ON $SAMLTABLE ((a_session ->> '_saml_id')); + GRANT ALL PRIVILEGES ON TABLE $SAMLTABLE TO $USER; + + CREATE UNLOGGED TABLE $OIDCTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_o__session_kind ON $OIDCTABLE ((a_session ->> '_session_kind')); + CREATE INDEX i_o__utime ON $OIDCTABLE ((cast(a_session ->> '_utime' as bigint ))); + GRANT ALL PRIVILEGES ON TABLE $OIDCTABLE TO $USER; + + CREATE UNLOGGED TABLE $CASTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_c__session_kind ON $CASTABLE ((a_session ->> '_session_kind')); + CREATE INDEX i_c__utime ON $CASTABLE ((cast(a_session ->> '_utime' as bigint))); + CREATE INDEX i_c__cas_id ON $CASTABLE ((a_session ->> '_cas_id')); + CREATE INDEX i_c_pgtIou ON $CASTABLE ((a_session ->> 'pgtIou')); + GRANT ALL PRIVILEGES ON TABLE $CASTABLE TO $USER; +EOSQL + +if test -e /llng-conf/conf.json; then + SERIALIZED=`perl -MJSON -e '$/=undef; + open F, "/llng-conf/conf.json" or die $!; + $a=JSON::from_json(); + $a->{cfgNum}=1; + $a=JSON::to_json($a); + $a=~s/'\''/'\'\''/g; + $a =~ s/\\\\/\\\\\\\\/g; + print $a;'` + echo "set val '$SERIALIZED'" >&2 + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE" <<-EOSQL + \\set val '$SERIALIZED' + INSERT INTO $TABLE (cfgNum, data) VALUES (1, :'val'); + \\unset val +EOSQL +fi \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/db/init-synapse-and-create-users-table.sh b/packages/tom-server/src/administration-console-api/__testData__/db/init-synapse-and-create-users-table.sh new file mode 100644 index 00000000..86991a34 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/db/init-synapse-and-create-users-table.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +psql -U postgres <<-EOSQL + CREATE USER synapse PASSWORD 'synapse!1'; + CREATE DATABASE synapse TEMPLATE='template0' LOCALE='C' ENCODING='UTF8' OWNER='synapse'; +EOSQL +psql -v ON_ERROR_STOP=1 --username "synapse" --dbname "synapse" <<-EOSQL + CREATE TABLE users ( + name text, + password_hash text, + creation_ts bigint, + admin smallint DEFAULT 0 NOT NULL, + upgrade_ts bigint, + is_guest smallint DEFAULT 0 NOT NULL, + appservice_id text, + consent_version text, + consent_server_notice_sent text, + user_type text, + deactivated smallint DEFAULT 0 NOT NULL, + shadow_banned boolean, + consent_ts bigint + ); +EOSQL \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/db/init-synapse-db.sh b/packages/tom-server/src/administration-console-api/__testData__/db/init-synapse-db.sh new file mode 100644 index 00000000..2a6f1859 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/db/init-synapse-db.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +psql -U postgres <<-EOSQL + CREATE USER synapse PASSWORD 'synapse!1'; + CREATE DATABASE synapse TEMPLATE='template0' LOCALE='C' ENCODING='UTF8' OWNER='synapse'; +EOSQL \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/db/init-twake-db.sh b/packages/tom-server/src/administration-console-api/__testData__/db/init-twake-db.sh new file mode 100644 index 00000000..54c55708 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/db/init-twake-db.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +psql -U postgres <<-EOSQL + CREATE USER twake PASSWORD 'twake!1'; + CREATE DATABASE twakedb TEMPLATE='template0' LOCALE='C' ENCODING='UTF8' OWNER='twake'; +EOSQL \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/docker-compose.yml b/packages/tom-server/src/administration-console-api/__testData__/docker-compose.yml new file mode 100644 index 00000000..a6065b36 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/docker-compose.yml @@ -0,0 +1,86 @@ +version: '3.8' + +networks: + admin-console-test: + +services: + postgresql: + image: postgres:13-bullseye + volumes: + - ./synapse-data/matrix.example.com.log.config:/data/matrix.example.com.log.config + - ./db/init-synapse-db.sh:/docker-entrypoint-initdb.d/init-synapse-db.sh + - ./db/init-llng-db.sh:/docker-entrypoint-initdb.d/init-llng-db.sh + - ./db/init-twake-db.sh:/docker-entrypoint-initdb.d/init-twake-db.sh + - ./llng/lmConf-1.json:/llng-conf/conf.json + environment: + - POSTGRES_PASSWORD=synapse!! + healthcheck: + test: ['CMD-SHELL', 'pg_isready'] + interval: 10s + timeout: 5s + retries: 5 + ports: + - 5434:5432 + networks: + - admin-console-test + + synapse: + image: matrixdotorg/synapse:v1.89.0 + container_name: synapse-tom-1 + volumes: + - ./synapse-data:/data + - ./nginx/ssl/ca.pem:/etc/ssl/certs/ca.pem + - ./nginx/ssl/9da13359.0:/etc/ssl/certs/9da13359.0 + - ./nginx/ssl/matrix.example.com.crt:/etc/ssl/certs/matrix.example.com.crt + - ./nginx/ssl/matrix.example.com.key:/etc/ssl/certs/matrix.example.com.key + depends_on: + - auth + environment: + - UID=${MYUID} + - VIRTUAL_PORT=8448 + - VIRTUAL_HOST=matrix.example.com + - VIRTUAL_PROTO=https + healthcheck: + test: ["CMD", "curl", "-fSsk", "https://localhost:8448/health"] + interval: 10s + timeout: 10s + retries: 3 + extra_hosts: + - "host.docker.internal:host-gateway" + networks: + admin-console-test: + aliases: + - matrix.example.com + + auth: + image: yadd/lemonldap-ng-portal:2.18.2-9 + volumes: + - ./llng/lmConf-1.json:/var/lib/lemonldap-ng/conf/lmConf-1.json + - ./llng/ssl.conf:/etc/nginx/sites-enabled/0000default.conf + - ./nginx/ssl/auth.example.com.crt:/etc/nginx/ssl/auth.example.com.crt + - ./nginx/ssl/auth.example.com.key:/etc/nginx/ssl/auth.example.com.key + environment: + - PORTAL=https://auth.example.com + - VIRTUAL_HOST=auth.example.com + - PG_SERVER=postgresql + depends_on: + postgresql: + condition: service_healthy + extra_hosts: + - "host.docker.internal:host-gateway" + networks: + admin-console-test: + aliases: + - auth.example.com + + nginx-proxy: + image: nginxproxy/nginx-proxy + ports: + - 444:444 + environment: + - HTTPS_PORT=444 + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./nginx/ssl:/etc/nginx/certs + networks: + - admin-console-test \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/generate-self-signed-certificate.sh b/packages/tom-server/src/administration-console-api/__testData__/generate-self-signed-certificate.sh new file mode 100755 index 00000000..0477197f --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/generate-self-signed-certificate.sh @@ -0,0 +1,50 @@ +#!/bin/sh +SCRIPT_PARENT_PATH=$( cd "$(dirname "$0")" ; pwd -P ) +ADDITIONAL_PARAMS="" +COMMON_NAME=$1 +if [ "$1" = "-ip" ]; then + COMMON_NAME=$2 + echo "subjectAltName = IP:$COMMON_NAME" > $SCRIPT_PARENT_PATH/openssl-ext.cnf + ADDITIONAL_PARAMS="-extfile $SCRIPT_PARENT_PATH/openssl-ext.cnf" +fi + +CERTIFICATE_KEY=$COMMON_NAME.key +CERTIFICATE_CRT=$COMMON_NAME.crt +CA_CRT_PATH=$SCRIPT_PARENT_PATH/nginx/ssl/ca.pem +CA_KEY_PATH=$SCRIPT_PARENT_PATH/nginx/ssl/ca.key + +cd $SCRIPT_PARENT_PATH +openssl genrsa -out $CERTIFICATE_KEY 4096 +openssl req \ + -new \ + -key $CERTIFICATE_KEY \ + -nodes \ + -out server.csr \ + -subj "/C=FR/ST=Centre/L=Paris/O=Linagora/OU=IT/CN=$COMMON_NAME" +if [ ! -f "$CA_CRT_PATH" ]; then + openssl genrsa -out ca.key 4096 + openssl req \ + -new \ + -x509 \ + -nodes \ + -days 36500 \ + -key ca.key \ + -out ca.pem \ + -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd" + mv ca.pem ca.key $SCRIPT_PARENT_PATH/nginx/ssl +fi +openssl x509 \ + -req \ + -in server.csr \ + -CAkey $CA_KEY_PATH \ + -CA $CA_CRT_PATH \ + -set_serial -01 \ + -out $CERTIFICATE_CRT \ + -days 36500 \ + -sha256 $ADDITIONAL_PARAMS +openssl verify -CAfile $CA_CRT_PATH $CERTIFICATE_CRT +mv $CERTIFICATE_KEY $CERTIFICATE_CRT $SCRIPT_PARENT_PATH/nginx/ssl +rm server.csr +if [ -f "openssl-ext.cnf" ]; then + rm openssl-ext.cnf +fi \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/integration-tests-config.json b/packages/tom-server/src/administration-console-api/__testData__/integration-tests-config.json new file mode 100644 index 00000000..a1215012 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/integration-tests-config.json @@ -0,0 +1,33 @@ +{ + "additional_features": true, + "base_url": "http://host.docker.internal:3001/", + "cron_service": true, + "database_vacuum_delay": 7200, + "key_delay": 3600, + "keys_depth": 5, + "mail_link_delay": 7200, + "rate_limiting_window": 10000, + "server_name": "example.com", + "smtp_server": "localhost", + "userdb_engine": "ldap", + "template_dir": "./templates", + "ldap_base": "dc=example,dc=com", + "ldap_uri": "ldap://localhost:21389/", + "matrix_server": "matrix.example.com:444", + "registration_file_path": "./src/administration-console-api/__testData__/synapse-data/registration.yaml", + "namespaces": { + "aliases": [{ "exclusive": false, "regex": "#_twake_.*" }], + "users": [{ "exclusive": false, "regex": "@.*" }] + }, + "push_ephemeral": true, + "database_engine": "pg", + "database_host": "localhost:5434", + "database_name": "twakedb", + "database_user": "twake", + "database_password": "twake!1", + "matrix_database_engine": "pg", + "matrix_database_host": "localhost:5434", + "matrix_database_name": "synapse", + "matrix_database_password": "synapse!1", + "matrix_database_user": "synapse" +} \ No newline at end of file diff --git a/packages/tom-server/src/application-server/__testData__/ldap/Dockerfile b/packages/tom-server/src/administration-console-api/__testData__/ldap/Dockerfile similarity index 100% rename from packages/tom-server/src/application-server/__testData__/ldap/Dockerfile rename to packages/tom-server/src/administration-console-api/__testData__/ldap/Dockerfile diff --git a/packages/tom-server/src/application-server/__testData__/ldap/ldif/base_ldap_users.ldif b/packages/tom-server/src/administration-console-api/__testData__/ldap/ldif/base_ldap_users.ldif similarity index 100% rename from packages/tom-server/src/application-server/__testData__/ldap/ldif/base_ldap_users.ldif rename to packages/tom-server/src/administration-console-api/__testData__/ldap/ldif/base_ldap_users.ldif diff --git a/packages/tom-server/src/application-server/__testData__/ldap/ldif/config-20230322180123.ldif b/packages/tom-server/src/administration-console-api/__testData__/ldap/ldif/config-20230322180123.ldif similarity index 100% rename from packages/tom-server/src/application-server/__testData__/ldap/ldif/config-20230322180123.ldif rename to packages/tom-server/src/administration-console-api/__testData__/ldap/ldif/config-20230322180123.ldif diff --git a/packages/tom-server/src/administration-console-api/__testData__/llng/lmConf-1.json b/packages/tom-server/src/administration-console-api/__testData__/llng/lmConf-1.json new file mode 100644 index 00000000..e187c211 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/llng/lmConf-1.json @@ -0,0 +1,456 @@ +{ + "ADPwdExpireWarning": 0, + "ADPwdMaxAge": 0, + "SMTPServer": "", + "SMTPTLS": "", + "SSLAuthnLevel": 5, + "SSLIssuerVar": "SSL_CLIENT_I_DN", + "SSLVar": "SSL_CLIENT_S_DN_Email", + "SSLVarIf": {}, + "activeTimer": 1, + "apacheAuthnLevel": 3, + "applicationList": {}, + "authChoiceParam": "lmAuth", + "authentication": "LDAP", + "available2F": "UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius,Password", + "available2FSelfRegistration": "Password,TOTP,U2F,WebAuthn,Yubikey", + "bruteForceProtectionLockTimes": "15, 30, 60, 300, 600", + "bruteForceProtectionMaxAge": 300, + "bruteForceProtectionMaxFailed": 3, + "bruteForceProtectionMaxLockTime": 900, + "bruteForceProtectionTempo": 30, + "captcha_mail_enabled": 1, + "captcha_register_enabled": 1, + "captcha_size": 6, + "casAccessControlPolicy": "none", + "casAuthnLevel": 1, + "casTicketExpiration": 0, + "certificateResetByMailCeaAttribute": "description", + "certificateResetByMailCertificateAttribute": "userCertificate;binary", + "certificateResetByMailURL": "https://auth.example.com/certificateReset", + "certificateResetByMailValidityDelay": 0, + "cfgAuthor": "The LemonLDAP::NG team", + "cfgDate": "1627287638", + "cfgNum": "1", + "cfgVersion": "2.0.16", + "checkDevOpsCheckSessionAttributes": 1, + "checkDevOpsDisplayNormalizedHeaders": 1, + "checkDevOpsDownload": 1, + "checkHIBPRequired": 1, + "checkHIBPURL": "https://api.pwnedpasswords.com/range/", + "checkTime": 600, + "checkUserDisplayComputedSession": 1, + "checkUserDisplayEmptyHeaders": 0, + "checkUserDisplayEmptyValues": 0, + "checkUserDisplayHiddenAttributes": 0, + "checkUserDisplayHistory": 0, + "checkUserDisplayNormalizedHeaders": 0, + "checkUserDisplayPersistentInfo": 0, + "checkUserHiddenAttributes": "_loginHistory, _session_id, hGroups", + "checkUserIdRule": 1, + "checkXSS": 1, + "confirmFormMethod": "post", + "contextSwitchingIdRule": 1, + "contextSwitchingPrefix": "switching", + "contextSwitchingRule": 0, + "contextSwitchingStopWithLogout": 1, + "cookieName": "lemonldap", + "corsAllow_Credentials": "true", + "corsAllow_Headers": "*", + "corsAllow_Methods": "POST,GET", + "corsAllow_Origin": "*", + "corsEnabled": 1, + "corsExpose_Headers": "*", + "corsMax_Age": "86400", + "crowdsecAction": "reject", + "cspConnect": "'self'", + "cspDefault": "'self'", + "cspFont": "'self'", + "cspFormAction": "*", + "cspFrameAncestors": "", + "cspImg": "'self' data:", + "cspScript": "'self'", + "cspStyle": "'self'", + "dbiAuthnLevel": 2, + "dbiExportedVars": {}, + "decryptValueRule": 0, + "demoExportedVars": { + "cn": "cn", + "mail": "mail", + "uid": "uid" + }, + "displaySessionId": 1, + "domain": "example.com", + "exportedHeaders": {}, + "exportedVars": {}, + "ext2fActivation": 0, + "ext2fCodeActivation": "\\d{6}", + "facebookAuthnLevel": 1, + "facebookExportedVars": {}, + "facebookUserField": "id", + "failedLoginNumber": 5, + "findUserControl": "^[*\\w]+$", + "findUserWildcard": "*", + "formTimeout": 120, + "githubAuthnLevel": 1, + "githubScope": "user:email", + "githubUserField": "login", + "globalLogoutRule": 0, + "globalLogoutTimer": 1, + "globalStorage": "Apache::Session::File", + "globalStorageOptions": { + "Directory": "/var/lib/lemonldap-ng/sessions", + "LockDirectory": "/var/lib/lemonldap-ng/sessions/lock", + "generateModule": "Lemonldap::NG::Common::Apache::Session::Generate::SHA256" + }, + "gpgAuthnLevel": 5, + "gpgDb": "", + "grantSessionRules": {}, + "groups": {}, + "handlerInternalCache": 15, + "handlerServiceTokenTTL": 30, + "hiddenAttributes": "_password, _2fDevices", + "httpOnly": 1, + "https": -1, + "impersonationHiddenAttributes": "_2fDevices, _loginHistory", + "impersonationIdRule": 1, + "impersonationMergeSSOgroups": 0, + "impersonationPrefix": "real_", + "impersonationRule": 0, + "impersonationSkipEmptyValues": 1, + "infoFormMethod": "get", + "issuerDBCASPath": "^/cas/", + "issuerDBCASRule": 1, + "issuerDBGetParameters": {}, + "issuerDBGetPath": "^/get/", + "issuerDBGetRule": 1, + "issuerDBOpenIDConnectActivation": 1, + "issuerDBOpenIDConnectPath": "^/oauth2/", + "issuerDBOpenIDConnectRule": 1, + "issuerDBOpenIDPath": "^/openidserver/", + "issuerDBOpenIDRule": 1, + "issuerDBSAMLPath": "^/saml/", + "issuerDBSAMLRule": 1, + "issuersTimeout": 120, + "jsRedirect": 0, + "key": "^vmTGvh{+]5!ToB?", + "krbAuthnLevel": 3, + "krbRemoveDomain": 1, + "ldapServer": "host.docker.internal:21389", + "ldapAuthnLevel": 2, + "ldapBase": "dc=example,dc=com", + "ldapExportedVars": { + "cn": "cn", + "mail": "mail", + "uid": "uid" + }, + "ldapGroupAttributeName": "member", + "ldapGroupAttributeNameGroup": "dn", + "ldapGroupAttributeNameSearch": "cn", + "ldapGroupAttributeNameUser": "dn", + "ldapGroupObjectClass": "groupOfNames", + "ldapIOTimeout": 10, + "ldapPasswordResetAttribute": "pwdReset", + "ldapPasswordResetAttributeValue": "TRUE", + "ldapPwdEnc": "utf-8", + "ldapSearchDeref": "find", + "ldapTimeout": 10, + "ldapUsePasswordResetAttribute": 1, + "ldapVerify": "require", + "ldapVersion": 3, + "linkedInAuthnLevel": 1, + "linkedInFields": "id,first-name,last-name,email-address", + "linkedInScope": "r_liteprofile r_emailaddress", + "linkedInUserField": "emailAddress", + "localSessionStorage": "Cache::FileCache", + "localSessionStorageOptions": { + "cache_depth": 3, + "cache_root": "/var/lib/lemonldap-ng/cache", + "default_expires_in": 600, + "directory_umask": "007", + "namespace": "lemonldap-ng-sessions" + }, + "locationDetectGeoIpLanguages": "en, fr", + "locationRules": { + "auth.example.com": { + "(?#checkUser)^/checkuser": "inGroup(\"timelords\")", + "(?#errors)^/lmerror/": "accept", + "default": "accept" + } + }, + "loginHistoryEnabled": 1, + "logoutServices": {}, + "macros": { + "UA": "$ENV{HTTP_USER_AGENT}", + "_whatToTrace": "$_auth eq 'SAML' ? lc($_user.'@'.$_idpConfKey) : $_auth eq 'OpenIDConnect' ? lc($_user.'@'.$_oidc_OP) : lc($_user)" + }, + "mail2fActivation": 0, + "mail2fCodeRegex": "\\d{6}", + "mailCharset": "utf-8", + "mailFrom": "noreply@example.com", + "mailSessionKey": "mail", + "mailTimeout": 0, + "mailUrl": "https://auth.example.com/resetpwd", + "managerDn": "", + "managerPassword": "", + "max2FDevices": 10, + "max2FDevicesNameLength": 20, + "multiValuesSeparator": "; ", + "mySessionAuthorizedRWKeys": [ + "_appsListOrder", + "_oidcConnectedRP", + "_oidcConsents" + ], + "newLocationWarningLocationAttribute": "ipAddr", + "newLocationWarningLocationDisplayAttribute": "", + "newLocationWarningMaxValues": "0", + "notification": 0, + "notificationDefaultCond": "", + "notificationServerPOST": 1, + "notificationServerSentAttributes": "uid reference date title subtitle text check", + "notificationStorage": "File", + "notificationStorageOptions": { + "dirName": "/var/lib/lemonldap-ng/notifications" + }, + "notificationWildcard": "allusers", + "notificationsMaxRetrieve": 3, + "notifyDeleted": 1, + "nullAuthnLevel": 0, + "oidcAuthnLevel": 1, + "oidcOPMetaDataExportedVars": {}, + "oidcOPMetaDataJSON": {}, + "oidcOPMetaDataJWKS": {}, + "oidcOPMetaDataOptions": {}, + "oidcRPCallbackGetParam": "openidconnectcallback", + "oidcRPMetaDataExportedVars": { + "matrix1": { + "email": "mail", + "family_name": "cn", + "given_name": "cn", + "name": "cn", + "nickname": "uid", + "preferred_username": "uid" + } + }, + "oidcRPMetaDataMacros": null, + "oidcRPMetaDataOptions": { + "matrix1": { + "oidcRPMetaDataOptionsAccessTokenClaims": 0, + "oidcRPMetaDataOptionsAccessTokenJWT": 0, + "oidcRPMetaDataOptionsAccessTokenSignAlg": "RS256", + "oidcRPMetaDataOptionsAllowClientCredentialsGrant": 0, + "oidcRPMetaDataOptionsAllowOffline": 0, + "oidcRPMetaDataOptionsAllowPasswordGrant": 0, + "oidcRPMetaDataOptionsBypassConsent": 1, + "oidcRPMetaDataOptionsClientID": "matrix1", + "oidcRPMetaDataOptionsClientSecret": "matrix1*", + "oidcRPMetaDataOptionsIDTokenForceClaims": 0, + "oidcRPMetaDataOptionsIDTokenSignAlg": "RS256", + "oidcRPMetaDataOptionsLogoutBypassConfirm": 0, + "oidcRPMetaDataOptionsLogoutSessionRequired": 1, + "oidcRPMetaDataOptionsLogoutType": "back", + "oidcRPMetaDataOptionsPublic": 0, + "oidcRPMetaDataOptionsRedirectUris": "https://matrix.example.com:444/_synapse/client/oidc/callback", + "oidcRPMetaDataOptionsRefreshToken": 0, + "oidcRPMetaDataOptionsRequirePKCE": 0 + } + }, + "oidcRPMetaDataOptionsExtraClaims": null, + "oidcRPMetaDataScopeRules": null, + "oidcRPStateTimeout": 600, + "oidcServiceAccessTokenExpiration": 3600, + "oidcServiceAllowAuthorizationCodeFlow": 1, + "oidcServiceAllowImplicitFlow": 0, + "oidcServiceAuthorizationCodeExpiration": 60, + "oidcServiceDynamicRegistrationExportedVars": {}, + "oidcServiceDynamicRegistrationExtraClaims": {}, + "oidcServiceIDTokenExpiration": 3600, + "oidcServiceIgnoreScopeForClaims": 1, + "oidcServiceKeyIdSig": "oMGHInscAW3Nsa0FcnCnDA", + "oidcServiceMetaDataAuthnContext": { + "loa-1": 1, + "loa-2": 2, + "loa-3": 3, + "loa-4": 4, + "loa-5": 5 + }, + "oidcServiceMetaDataAuthorizeURI": "authorize", + "oidcServiceMetaDataBackChannelURI": "blogout", + "oidcServiceMetaDataCheckSessionURI": "checksession.html", + "oidcServiceMetaDataEndSessionURI": "logout", + "oidcServiceMetaDataFrontChannelURI": "flogout", + "oidcServiceMetaDataIntrospectionURI": "introspect", + "oidcServiceMetaDataJWKSURI": "jwks", + "oidcServiceMetaDataRegistrationURI": "register", + "oidcServiceMetaDataTokenURI": "token", + "oidcServiceMetaDataUserInfoURI": "userinfo", + "oidcServiceOfflineSessionExpiration": 2592000, + "oidcServicePrivateKeySig": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDywteBzIOlhKc4\nO+vhMStDYOpPYrWDOodkUZ7OsxlWVNZ/b/lqIFS56+MHPkKNQuT4zZCyO8bEKmmR\nZ6kPFJoGbO1zJCPQ/RKjimX4J/5gDb1BAlo+6agJi55e3Bw0zKNJDU0mRyedcIzW\n7ywTgyj6B35pl/Sfloi4Q1XEizHar+26h66SOEtnppMxGvwsxO8gFWz26CPmalvY\n5GNYR0txbXUZn7I4kDa4mMWgNfeocWc78Qbt4RV5EuQdbRh1sou4tL9Nn4EuGhg0\nmfsSI0xVAj7f82Wn3kW6qEbhuejrY7aqmZjN7yrMKtCBuV7o4hVrjYLuM2j0mInY\nMy5nRNOVAgMBAAECggEAJ145nK8R2lG83H27LvXOUkrxNJaJYRKoyjgCTPr2bO2t\nK1V5WSCNHOmIE7ChEk962m5bvMu83CsUm6P34p4wrEIV78o4lLe1whe7mZbCxcj0\nnApJoFI8EfA2aqO/X0CgakRh8ocvgXSzIlf/CdsHViTI907ROOAso9Unn4wDNbdp\nMrhi3H2SnA+ewzj85WygBVTNQmVBjJSSLXTQRkfHye0ztvQm59gqqaJaM2rkBjvA\nlPWAVsgakOk4pgClKElCsIjWPJwdYtcd8VJrwnro5J9KhMwB//AArGgqOaXUHnLH\nv5aZZp6FjV/M3BxbSp4cG6hXmK1hrDFLecRddYP1gQKBgQD+Y4/ee57Z0E2V8833\nYfrK3F23sfxmZ7zUwEbgFXUfRy3RVW7Hbc7PAJzxzrk+LYk/zaZrrfEJguqG2O6m\nVNYkqxKu69Nn964CMdV15JGxVzpzsN5adKlcvKVVv9gx2rF3SMUOHiRutj2BlUtO\niCq0G3jFsXWIRzePig9PbWP6CQKBgQD0TG2DeDDUgKbeJYIzXfmCvGxlm5MZqCc/\nK7d8P9U0svG//jJRTsa9hcLjk7N24CzhLNHyJmT7dh1Xy1oLyHNPZ4nQRmCe+HUf\nu0SK10WZ2K55ekUmqS+xSuDFWJtWa5SE46cKg0fKu7YkiDKI1s6I3qrF4lew2aDE\n2p8GJRrgLQKBgCh2PZPtpb6PW0fWl5QZiYJqup1VOggvx+EvFBbgUti+wZLiO9SM\nqrBSMKRldSFmrMXxN984s3YH1LXOG2dpZwY+D6Ky79VBl/PRaVpvGJ1Uen+cSkGo\n/Kc7ejDBaunDFycZ8/3i3Xiek/ngfTHohqJPHE6Vg1RBv5ydIQJJK/XBAoGAU1XO\n9c4GOjc4tQbuhz9DYgmMoIyVfWcTHEV5bfUIcdWpCelYmMval8QNWzyDN8X5CUcU\nxxm50N3V3KENsn9KdofHRzj6tL/klFJ5azNMFtMHkYDYHfwQvNXiHu++7Zf9LefK\nj5eA4fNuir+7HVrJUX9DmgVADJ/wa7Z4EMyPgnECgYA/NLUs4920h10ie5lFffpM\nqq6CRcBjsQ7eGK9UI1Z2KZUh94eqIENSJ7whBjXKvJJvhAlH4//lVFMMRs7oJePY\nThg+8In7PB64yMOIJZLc5Fekn9aGG6YtErPzePQkXSYCKZxWl5EpjQZGgPRVkNtD\n2nflyJLjiCbTjeNgWIOZlw==\n-----END PRIVATE KEY-----\n", + "oidcServicePublicKeySig": "-----BEGIN CERTIFICATE-----\nMIICuDCCAaCgAwIBAgIEFU77HjANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDDBNt\nYXRyaXgubGluYWdvcmEuY29tMB4XDTIzMDIxNTAzMTk0NloXDTQzMDIxMDAzMTk0\nNlowHjEcMBoGA1UEAwwTbWF0cml4LmxpbmFnb3JhLmNvbTCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAPLC14HMg6WEpzg76+ExK0Ng6k9itYM6h2RRns6z\nGVZU1n9v+WogVLnr4wc+Qo1C5PjNkLI7xsQqaZFnqQ8UmgZs7XMkI9D9EqOKZfgn\n/mANvUECWj7pqAmLnl7cHDTMo0kNTSZHJ51wjNbvLBODKPoHfmmX9J+WiLhDVcSL\nMdqv7bqHrpI4S2emkzEa/CzE7yAVbPboI+ZqW9jkY1hHS3FtdRmfsjiQNriYxaA1\n96hxZzvxBu3hFXkS5B1tGHWyi7i0v02fgS4aGDSZ+xIjTFUCPt/zZafeRbqoRuG5\n6OtjtqqZmM3vKswq0IG5XujiFWuNgu4zaPSYidgzLmdE05UCAwEAATANBgkqhkiG\n9w0BAQsFAAOCAQEArNmGxZVvmvdOLctv+zQ+npzQtOTaJcf+r/1xYuM4FZVe4yLc\ny9ElDskoDWjvQU7jKeJeaDOYgMJQNrek8Doj8uHPWNe6jYFa62Csg9aPz6e8qbtq\nWI+sXds5GJd6xZ8mi2L4MdT/tf8dBgcgybuoRyhBtJwG1rLNAYkeXMxkBzOFcU7K\nR/SZ0q9ToLAWFDhn42MTjPN3t6GwKDzGNsM/SI/3WvUwpQbtK91hjPnNDwKiAtGG\nfUteuigfXY+0hEcQwJdR0St/FQ8UYYcAB5YT9IkT1wCcU5LfPHCBf3OXNpbnQsHh\netQMKLibM6wWdXNwmsd1szO66ft3QZ4h4EG3Vw==\n-----END CERTIFICATE-----\n", + "oidcStorageOptions": {}, + "openIdAuthnLevel": 1, + "openIdExportedVars": {}, + "openIdIDPList": "0;", + "openIdSPList": "0;", + "openIdSreg_email": "mail", + "openIdSreg_fullname": "cn", + "openIdSreg_nickname": "uid", + "openIdSreg_timezone": "_timezone", + "pamAuthnLevel": 2, + "pamService": "login", + "password2fActivation": 0, + "password2fSelfRegistration": 0, + "password2fUserCanRemoveKey": 1, + "passwordDB": "Demo", + "passwordPolicyActivation": 1, + "passwordPolicyMinDigit": 0, + "passwordPolicyMinLower": 0, + "passwordPolicyMinSize": 0, + "passwordPolicyMinSpeChar": 0, + "passwordPolicyMinUpper": 0, + "passwordPolicySpecialChar": "__ALL__", + "passwordResetAllowedRetries": 3, + "persistentSessionAttributes": "_loginHistory _2fDevices notification_", + "persistentStorage": "Apache::Session::File", + "persistentStorageOptions": { + "Directory": "/var/lib/lemonldap-ng/psessions", + "LockDirectory": "/var/lib/lemonldap-ng/psessions/lock" + }, + "port": -1, + "portal": "https://auth.example.com", + "portalAntiFrame": 1, + "portalCheckLogins": 1, + "portalDisplayAppslist": 1, + "portalDisplayChangePassword": "$_auth =~ /^(LDAP|DBI|Demo)$/", + "portalDisplayGeneratePassword": 1, + "portalDisplayLoginHistory": 1, + "portalDisplayLogout": 1, + "portalDisplayOidcConsents": "$_oidcConsents && $_oidcConsents =~ /\\w+/", + "portalDisplayOrder": "Appslist ChangePassword LoginHistory OidcConsents Logout", + "portalDisplayRefreshMyRights": 1, + "portalDisplayRegister": 1, + "portalErrorOnExpiredSession": 1, + "portalFavicon": "common/favicon.ico", + "portalForceAuthnInterval": 5, + "portalMainLogo": "common/logos/logo_llng_400px.png", + "portalPingInterval": 60000, + "portalRequireOldPassword": 1, + "portalSkin": "bootstrap", + "portalSkinBackground": "1280px-Cedar_Breaks_National_Monument_partially.jpg", + "portalUserAttr": "_user", + "proxyAuthServiceChoiceParam": "lmAuth", + "proxyAuthnLevel": 2, + "radius2fActivation": 0, + "radius2fTimeout": 20, + "radiusAuthnLevel": 3, + "radiusExportedVars": {}, + "randomPasswordRegexp": "[A-Z]{3}[a-z]{5}.\\d{2}", + "redirectFormMethod": "get", + "registerDB": "Null", + "registerTimeout": 0, + "registerUrl": "https://auth.example.com/register", + "reloadTimeout": 5, + "reloadUrls": { + "localhost": "https://reload.example.com/reload" + }, + "rememberAuthChoiceRule": 0, + "rememberCookieName": "llngrememberauthchoice", + "rememberCookieTimeout": 31536000, + "rememberTimer": 5, + "remoteGlobalStorage": "Lemonldap::NG::Common::Apache::Session::SOAP", + "remoteGlobalStorageOptions": { + "ns": "https://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService", + "proxy": "https://auth.example.com/sessions" + }, + "requireToken": 1, + "rest2fActivation": 0, + "restAuthnLevel": 2, + "restClockTolerance": 15, + "sameSite": "", + "samlAttributeAuthorityDescriptorAttributeServiceSOAP": "urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;", + "samlAuthnContextMapKerberos": 4, + "samlAuthnContextMapPassword": 2, + "samlAuthnContextMapPasswordProtectedTransport": 3, + "samlAuthnContextMapTLSClient": 5, + "samlEntityID": "#PORTAL#/saml/metadata", + "samlIDPSSODescriptorArtifactResolutionServiceArtifact": "1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact", + "samlIDPSSODescriptorSingleLogoutServiceHTTPPost": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn", + "samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn", + "samlIDPSSODescriptorSingleLogoutServiceSOAP": "urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/singleLogoutSOAP;", + "samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/singleSignOnArtifact;", + "samlIDPSSODescriptorSingleSignOnServiceHTTPPost": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleSignOn;", + "samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleSignOn;", + "samlIDPSSODescriptorWantAuthnRequestsSigned": 1, + "samlMetadataForceUTF8": 1, + "samlNameIDFormatMapEmail": "mail", + "samlNameIDFormatMapKerberos": "uid", + "samlNameIDFormatMapWindows": "uid", + "samlNameIDFormatMapX509": "mail", + "samlOrganizationDisplayName": "Example", + "samlOrganizationName": "Example", + "samlOrganizationURL": "https://www.example.com", + "samlOverrideIDPEntityID": "", + "samlRelayStateTimeout": 600, + "samlSPSSODescriptorArtifactResolutionServiceArtifact": "1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact", + "samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact": "0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact", + "samlSPSSODescriptorAssertionConsumerServiceHTTPPost": "1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost", + "samlSPSSODescriptorAuthnRequestsSigned": 1, + "samlSPSSODescriptorSingleLogoutServiceHTTPPost": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn", + "samlSPSSODescriptorSingleLogoutServiceHTTPRedirect": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn", + "samlSPSSODescriptorSingleLogoutServiceSOAP": "urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/proxySingleLogoutSOAP;", + "samlSPSSODescriptorWantAssertionsSigned": 1, + "samlServiceSignatureMethod": "RSA_SHA256", + "scrollTop": 400, + "securedCookie": 0, + "sessionDataToRemember": {}, + "sfEngine": "::2F::Engines::Default", + "sfManagerRule": 1, + "sfRemovedMsgRule": 0, + "sfRemovedNotifMsg": "_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!", + "sfRemovedNotifRef": "RemoveSF", + "sfRemovedNotifTitle": "Second factor notification", + "sfRequired": 0, + "showLanguages": 1, + "singleIP": 0, + "singleSession": 0, + "singleUserByIP": 0, + "slaveAuthnLevel": 2, + "slaveExportedVars": {}, + "soapProxyUrn": "urn:Lemonldap/NG/Common/PSGI/SOAPService", + "stayConnected": 0, + "stayConnectedCookieName": "llngconnection", + "stayConnectedTimeout": 2592000, + "successLoginNumber": 5, + "timeout": 72000, + "timeoutActivity": 0, + "timeoutActivityInterval": 60, + "totp2fActivation": 0, + "totp2fDigits": 6, + "totp2fInterval": 30, + "totp2fRange": 1, + "totp2fSelfRegistration": 0, + "totp2fUserCanRemoveKey": 1, + "twitterAuthnLevel": 1, + "twitterUserField": "screen_name", + "u2fActivation": 0, + "u2fSelfRegistration": 0, + "u2fUserCanRemoveKey": 1, + "upgradeSession": 1, + "useRedirectOnError": 1, + "useSafeJail": 1, + "userControl": "^[\\w\\.\\-@]+$", + "userDB": "Same", + "utotp2fActivation": 0, + "viewerHiddenKeys": "samlIDPMetaDataNodes, samlSPMetaDataNodes", + "webIDAuthnLevel": 1, + "webIDExportedVars": {}, + "webauthn2fActivation": 0, + "webauthn2fSelfRegistration": 0, + "webauthn2fUserCanRemoveKey": 1, + "webauthn2fUserVerification": "preferred", + "whatToTrace": "_whatToTrace", + "yubikey2fActivation": 0, + "yubikey2fPublicIDSize": 12, + "yubikey2fSelfRegistration": 0, + "yubikey2fUserCanRemoveKey": 1 +} diff --git a/packages/tom-server/src/application-server/__testData__/llng/ssl.conf b/packages/tom-server/src/administration-console-api/__testData__/llng/ssl.conf similarity index 100% rename from packages/tom-server/src/application-server/__testData__/llng/ssl.conf rename to packages/tom-server/src/administration-console-api/__testData__/llng/ssl.conf diff --git a/packages/tom-server/src/application-server/__testData__/config.json b/packages/tom-server/src/administration-console-api/__testData__/mock-tests-config.json similarity index 54% rename from packages/tom-server/src/application-server/__testData__/config.json rename to packages/tom-server/src/administration-console-api/__testData__/mock-tests-config.json index ac6e4d47..9a1bb228 100644 --- a/packages/tom-server/src/application-server/__testData__/config.json +++ b/packages/tom-server/src/administration-console-api/__testData__/mock-tests-config.json @@ -1,9 +1,7 @@ { "additional_features": true, - "base_url": "http://host.docker.internal:3001/", + "base_url": "http://localhost:3001/", "cron_service": true, - "database_engine": "sqlite", - "database_host": "./src/application-server/__testData__/test.db", "database_vacuum_delay": 7200, "key_delay": 3600, "keys_depth": 5, @@ -11,17 +9,18 @@ "rate_limiting_window": 10000, "server_name": "example.com", "smtp_server": "localhost", - "userdb_engine": "ldap", + "userdb_engine": "sqlite", + "userdb_host": "./src/administration-console-api/__testData__/user.db", "template_dir": "./templates", - "ldap_base": "dc=example,dc=com", - "ldap_uri": "ldap://localhost:21389/", "matrix_server": "matrix.example.com", - "registration_file_path": "./src/application-server/__testData__/synapse-data/registration.yaml", - "matrix_database_engine": "sqlite", - "matrix_database_host": "./src/application-server/__testData__/synapse-data/homeserver.db", + "registration_file_path": "./src/administration-console-api/__testData__/registration-mock.yaml", "namespaces": { "aliases": [{ "exclusive": false, "regex": "#_twake_.*" }], "users": [{ "exclusive": false, "regex": "@.*" }] }, - "push_ephemeral": true -} + "push_ephemeral": true, + "database_engine": "sqlite", + "database_host": "./src/administration-console-api/__testData__/twake.db", + "matrix_database_engine": "sqlite", + "matrix_database_host": "./src/administration-console-api/__testData__/matrix.db" +} \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/9da13359.0 b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/9da13359.0 new file mode 120000 index 00000000..e375f5ab --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/9da13359.0 @@ -0,0 +1 @@ +ca.pem \ No newline at end of file diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/auth.example.com.crt b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/auth.example.com.crt new file mode 100644 index 00000000..4f8fcb7b --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/auth.example.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFJDCCAwwCAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yNDA0MTExODI5MTBaGA8yMTI0MDMxODE4MjkxMFowaTELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQYXV0aC5leGFtcGxlLmNvbTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALz58JVeJXCzNLwN/Tj55WR6 +dZBOtuAMMzuMrpFhcqczWaptEAOwnMMMhX9FzEv7Zu/+grAc9XdbWnTrWg6/AR+a +cEvrxNAwT+LMaipY+JxuW6NMUPxN9sNDKCcON1v58ma8cGze8ZX29k+k4t4D5PMp +cPpCS8Fh5ffOk+jwleKxS6csO47W9/jOsfkRxweOivxnU7oOTEvZNRmszJIZkuOV +0W7qKhfRAmpeZLCLY1cvCkFBOT5PcTBjZclq1h3XynbY7gestU3aw5TYITf6kkjj +G0E/Z5BuOL8DVKKoE58nx8OYxqKPsrvI0tjcKqxFlsaMfGelqGtE7/9rN3wMhvjv +Q0AeR3qEiu+phSq1pDa+2hohcV2I8FRKF2JgrtqjXJ1R4pLEta4rwryjtJ8KqCLm +OAOqDZpHV/jkBfmAeZgZx4HppI5SVplzZ2CBm4mAdM4YTWJpTvrgJFiQLmLorxFe +ttUk1g9EyngAICfGXcNfCNBNJ2QRyHfPlr+cRYPeQWkn0cqxsy9IcmQkadtwowUp +UzqRHYCvadvSeRvCJnsJGCYotMH/4UhbQqQxjKgGFTnvQR1CYRLPUUaT0PKJKxM8 +o0QdU0F73Lb7ovRqMjWfJXcUL3nylfTRivGqodaaSRNdhbmZnVLLpsPULwFWFsyg +UPbOl1PX4JOzvpVEA1ujAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAFHQYRxesrRe +8E5JumE2M5IpMu67YspQbqfaj5KZapIi0jAl5+OB9snnxicQUfV8HPFxzQxIkyL2 +MNZWG0O/4ThzDIXyOykMRycubeR+TchUmJGbp9RBl3dBSdkTcC+CwjiJfTuoAj3o +bq+Gkho37osjJGMBz4L4cGxH39R+MZTtqJ+8INf+/h7kpXp8x+USoJPVkMc63r7U +UboVtW4jNJGQzTwWd8s/bdjjWEh0VD+B2JHLjuM84D6Y5FwHWN+HYrzPlkYJ120Z +orThk02t8H//17g9x9+GI0N9CvcbyN5+gHn5VV7aVUqTkMbigoNmgGfsYy7TNoq5 +LanqJAviidzuyD1pod0KEHzEcYYNs9Kdq14rastDNgmHZOAXAE72oTRQQ14mvnhy +UYC1b9GIMa+uRlG5v20E5ykwcmthv6wbt1Jbcan26WJFJFkubtdowc6z2ncqRSV1 +sL8nudEK8SGHrWsmM+USkRu/NEZLje7lo/uE/ZSw99I8SKjYwmjtGW+XleLQ859b +5Kj67+znUGyLqvK1L3OofmhTMcLhrnyr5mLTpdG7cMT1abfekHXyNgLsr/la/V2P +pEz/bbalQQdeYfSTaaeellwJNNxYIuneF0wu4BBhwHV1U6crhImnnDVzeju4PdzQ +8Eq5F9RX4f9Q/cixo1P9vVMVR/eKDlik +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/auth.example.com.key b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/auth.example.com.key new file mode 100644 index 00000000..21362724 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/auth.example.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +cDHJ8L9Rvjaoy/cn2TLLLEUhrMRG +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/ca.key b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/ca.key new file mode 100644 index 00000000..01008886 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +6eU0pFTOVKg9IStsPXBFo2S2Yj7heA== +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/ca.pem b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/ca.pem new file mode 100644 index 00000000..0b6bdd00 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFbTCCA1WgAwIBAgIUBCvMwoaNwM+d9pxsLYR1CYTkPh8wDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yNDA0MTExODI5MDRaGA8yMTI0 +MDMxODE4MjkwNFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANyGP2wu42cwE/ClqzcaiS9peFNhYkx/fV6db5W6 +cGTaqDLPn+tJB0HrlbVn2rhV3tHEPGkBNWFFWnq/3CJNCn8JaUKF+UX8rJCIgvPV +fIIOoSAq7lSmZ6plWVgNE4LRUjoJh399MteAW7YVxWuGtF6DxtgMH9fRAQVTcE2j +sjulHfKeJDe3z2+RrP/m5P0PA3tn2TCdE4xba8SMMwuxR36BLLetJK88yCLxBOW8 +ITcDXCWyspj0uKq/B/SVCp7gHb2Lr+ulQ9oL3YimJOEF8md4jdmasDcWMp89YDlY +eAcIN6mTN6YYraJFFLmOgXk1vbJffrETLj4RaB2ulCYWta3Hvl/sNb60EyXDIysv +E3+vubp4G3EEjd0t3MsjBcAd4d+LH+0WyaQSvBAMTwnKFptyFzwEUHCGwhtUQGhp +w0SPWkPtsFlBqksd+jSS6zPiC2YDwQWLD9BFo1A+7LMrtkMyIIKqp2Sx2nS4CDpc +ilxEGaKlWgjJXMXnpV5uMvkr4xQ8McXw6BQh3yogb7ujTO5SG93bl2qRFYPIVLqd +ElcYkSGSRQuJMNM86On+Q5DtWET6i7oZCrIDMZAS0G90pduP9uRVggHXVeCUfkMR +WAB72ulcMfys5tGqj3soHoIIiYXnOWffvmVcnLwG9DKaj4L2d+AV9XloM3bClsTK +vinVAgMBAAGjUzBRMB0GA1UdDgQWBBQmM+Aa+L3/+jxzHbdoeeU2ZrnCYjAfBgNV +HSMEGDAWgBQmM+Aa+L3/+jxzHbdoeeU2ZrnCYjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQDWFgzjNjnwtMBYeJeISEFzZztOGTW5EkH/TCockq48 +R6X4gtDLCH2c+rGyaDpu3k2LP39siVwR26uBAlEhUSQbkYqrHghLvcxHsSL+j+J+ +yChXdzj/tu4bJJDvlRWZ2Xi3V93YTkqi/mMNKNJxB9uRPTSv44TtScS6qxJKwtty +N5iumeOSl2lwS7wqCYk813ScXpV7EAT3vuikR/YRM7MfD6Q7G1xMboF78r563eOI +TXhl8enHPHWCe3RuK7PMDzDHiGGF6v6I4HEClyG8iMKdtL1QPKk/B+48i3glliKQ +Ztedq22k99nH2tYEa+lBuPgCAJQdUpPIJj/oXqD+OiZ9Y/Pu659KNAkXakwYJdLd +LV3CiMJRM4zC1nuokGukLu/TFlE+CLhCZYvITzjgtTOX8vHDdL/G2tfiNTmv+6di +f7nJBtqJsh1de7e8xjdtJMNu4G8+h84mZxs5x7RVXe0aLQoKSFwdSABZiyuVQ37l +QruPNhyp+/kKo2Q7lKfwHk5ZhpDPEze3J52dhGYZJGjrqnpMZYWSEsl6/auCfWdR +30TnfhsNYJtVki9IuBkRlGrjmCIInQOIIrsY3k2GKdE2sAbLZLDSRljJnZGit++d +uCbjE/jeKr/dr4g2Bm4rriBtf14q/5j/S8RmWlIQrDOEj6f2yAo0AS3sqoFvAduz +Kg== +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/matrix.example.com.crt b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/matrix.example.com.crt new file mode 100644 index 00000000..a5634c55 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/matrix.example.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFJjCCAw4CAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yNDA0MTExODI5MDRaGA8yMTI0MDMxODE4MjkwNFowazELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEbMBkGA1UEAwwSbWF0cml4LmV4YW1wbGUuY29t +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuU8NP9FfGFLhbvZId0kz +OmeQo4XZ6EBwHXSMcoqEnlr+C1EM+uCrhToqgwBCLKGY7RjOdF3P5djtexvAZKRZ +Vjwnl3eXuwTbxoTqbeIz77XfuQsVI1eFhCVzdUPcmHrEstij+kX8aMWleBZIMXqS +x0dT8fLc2kblgNznAp2YNwkReQ4w4TvtNoyy4PrZDcKjKKSbqHZdN1z/nM18cO9X +cRss+lxOlhoR6V+ygADdRNvlz0gg1oWtQj3AHXazGTpEXWd4fP84Ut/nkBFCY0yl +hEZollE7nAIqCLodPyn/7gZ8vYAAirMkH2lUtJzKkYEI3rpcgc3rhw6clAYsr0Pm +KXAYvP6SsTBkhvr6JbyD9Gmp6tb8HdV7UL4bTBj06eTKvyVEEgDXZR8ZHI4OsbqF +RMwPkD3LyrkOCkimSxYkEn+yuMkFby1lMZuku1DHRquRGGUpebXB5iDLDoXKDkMs +pxrG2nBOrnL4jCe0l49KYXeIMUKhGxUxwdkmeVfw4tEX1/o7hlQNFSvaw01V7lN/ +QGQtLOr1XlDr3CdAJ4t+svC2Beu8lW+LCIP1l05BTByU7L/bEfh+IbmbPlT/z3E0 +VtgScm4xUE9wmopaWFZrquYRgQoiQ/6s5KmwCK/0/6vB6Iu0Y2gQh2YDe6A9gfbz +lcsVaYXiF+Fmv5/JFk3/Sg0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAv3lEuZH+ +rXb707vWDY5ua2tTvJ2KO6HH7D0rZFkdlRsm8aOrd4Xj9YzNRAC1JwjHWitDQKN9 +6bRgjO0hPVIibWgEeGyjIfVzIdTOpEtYMRSvDEl2ucgOZ0YEOIkQOUic6swPhKGG +vpgzbn/5Lz2B95gRnwNQJsUSCeYv0xuZxfHvjz6sEjz7xMjlPO4ZCLWr3sry5l8X +T7BC+Jq+5eSSdcTrGx27U3Ban4fQnQiDeQDB0Nh1kfk3G3myYxss98ymVaXdDtyc +Ri8Ft/JReqOTR5aQ5UtSThlszWLm7tuYGWMljpq53IGupMLMAOqipLEW5RNK5NJZ +IKsBvXy0cbSMBDvD5e9Vmv5blLP2YwoB3CHYJpzriJZVF/BfMHyrdB06+orz/SBI +q2Yh/fa1Ng3LC3dnsv9+UJk21XuXoeMql76uH7sIvRg5zJDI4FZMj22tKcnimg9+ +C1LBxP7yzlRR7wo6QaALWwifNo705c9/aGEj6rve4zUY5feDkNxFAiiZ+6JrT41u +Bz8bjnze16sc0HwKDPaftwr5sBq2gYU0HqbBkuevuB3GxPUsRRGLPVOOnkGdHNXu +hyzxSEiDs+nxVktsPMvdMwUY1IWnDxQ08r/jZMpLnBAfUR3t7vsQ0F79zZLGyG3c +WHGpB0gxN3WtGYaKGwSx5iXrszt9AIStIfE= +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/matrix.example.com.key b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/matrix.example.com.key new file mode 100644 index 00000000..a09ef60a --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/nginx/ssl/matrix.example.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +Bj/jSS+F6WEJLg3riqjNEkHToj5nsQ== +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/administration-console-api/__testData__/registration-mock.yaml b/packages/tom-server/src/administration-console-api/__testData__/registration-mock.yaml new file mode 100644 index 00000000..8f8f1597 --- /dev/null +++ b/packages/tom-server/src/administration-console-api/__testData__/registration-mock.yaml @@ -0,0 +1,10 @@ +id: lpqhjc6nyj7sfir56es9yjkasbcigz9l7dkcgkt66kaolp8dqcffwkghqpahd9o3 +hs_token: rr7d9j1cezgdmdjgcxew7wdofsplp85poy7azc86bgfkkhsm8kqarhouebh6ofk4 +as_token: 7ok8e79fchomqbgxf7lkk4krjgoilas8j2ggch4hb8pcnigo595jemkomioha7f4 +url: http://localhost:3001/ +sender_localpart: twake +namespaces: + users: + - exclusive: false + regex: '@.*' +de.sorunome.msc2409.push_ephemeral: true diff --git a/packages/tom-server/src/application-server/__testData__/synapse-data/homeserver.yaml b/packages/tom-server/src/administration-console-api/__testData__/synapse-data/homeserver.yaml similarity index 80% rename from packages/tom-server/src/application-server/__testData__/synapse-data/homeserver.yaml rename to packages/tom-server/src/administration-console-api/__testData__/synapse-data/homeserver.yaml index fb19c796..a699c330 100644 --- a/packages/tom-server/src/application-server/__testData__/synapse-data/homeserver.yaml +++ b/packages/tom-server/src/administration-console-api/__testData__/synapse-data/homeserver.yaml @@ -10,20 +10,30 @@ # each option, go to docs/usage/configuration/config_documentation.md or # https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html server_name: "example.com" -public_baseurl: "https://matrix.example.com/" +public_baseurl: "https://matrix.example.com:444/" pid_file: /data/homeserver.pid listeners: - - port: 8008 - tls: false + - port: 8448 + tls: true type: http x_forwarded: true resources: - names: [client, federation] compress: false +tls_certificate_path: "etc/ssl/certs/matrix.example.com.crt" +tls_private_key_path: "etc/ssl/certs/matrix.example.com.key" database: - name: sqlite3 + name: psycopg2 args: - database: /data/homeserver.db + user: synapse + password: 'synapse!1' + database: synapse + host: postgresql + cp_min: 2 + cp_max: 4 + keepalives_idle: 10 + keepalives_interval: 10 + keepalives_count: 3 log_config: "/data/matrix.example.com.log.config" media_store_path: /data/media_store registration_shared_secret: "u+Q^i6&*Y9azZ*~pID^.a=qrvd+mUIBX9SAreEPGJ=xzP&c+Sk" @@ -31,9 +41,6 @@ report_stats: false macaroon_secret_key: "=0ws-1~ztzXm&xh+As;7YL5.-U~r-T,F4zR3mW#E;6Y::Rb7&G" form_secret: "&YFO.XSc*2^2ZsW#hmoR+t:wf03~u#fin#O.R&erFcl9_mEayv" signing_key_path: "/data/matrix.example.com.signing.key" -trusted_key_servers: - - server_name: "matrix.org" - accept_keys_insecurely: true accept_keys_insecurely: true app_service_config_files: - /data/registration.yaml diff --git a/packages/tom-server/src/application-server/__testData__/synapse-data/matrix.example.com.log.config b/packages/tom-server/src/administration-console-api/__testData__/synapse-data/matrix.example.com.log.config similarity index 100% rename from packages/tom-server/src/application-server/__testData__/synapse-data/matrix.example.com.log.config rename to packages/tom-server/src/administration-console-api/__testData__/synapse-data/matrix.example.com.log.config diff --git a/packages/tom-server/src/application-server/controllers/room.ts b/packages/tom-server/src/administration-console-api/controllers/room.ts similarity index 80% rename from packages/tom-server/src/application-server/controllers/room.ts rename to packages/tom-server/src/administration-console-api/controllers/room.ts index 337a2de7..2838324b 100644 --- a/packages/tom-server/src/application-server/controllers/room.ts +++ b/packages/tom-server/src/administration-console-api/controllers/room.ts @@ -1,16 +1,20 @@ +import { type TwakeLogger } from '@twake/logger' +import type MatrixApplicationServer from '@twake/matrix-application-server' import { AppServerAPIError, validationErrorHandler, type expressAppHandler } from '@twake/matrix-application-server' -import { type DbGetResult } from '@twake/matrix-identity-server' +import { + type DbGetResult, + type MatrixDB, + type UserDB +} from '@twake/matrix-identity-server' import { type NextFunction, type Request, type Response } from 'express' import lodash from 'lodash' import fetch, { type Response as FetchResponse } from 'node-fetch' -import type TwakeApplicationServer from '..' -import type TwakeServer from '../..' import { type TwakeDB } from '../../db' -import { allMatrixErrorCodes } from '../../types' +import { allMatrixErrorCodes, type Config } from '../../types' import { TwakeRoom } from '../models/room' const { intersection } = lodash @@ -21,8 +25,12 @@ const portRe = const hostnameRe = new RegExp(`^${domainRe}(:${portRe})?$`, 'i') export const createRoom = ( - appServer: TwakeApplicationServer, - twakeServer: TwakeServer + appServer: MatrixApplicationServer, + db: TwakeDB, + userDb: UserDB, + matrixDb: MatrixDB, + conf: Config, + logger: TwakeLogger ): expressAppHandler => { // eslint-disable-next-line @typescript-eslint/no-misused-promises return async ( @@ -33,13 +41,13 @@ export const createRoom = ( try { let newRoomId: string | null = null validationErrorHandler(req) - if (!hostnameRe.test(twakeServer.conf.matrix_server)) { + if (!hostnameRe.test(conf.matrix_server)) { throw Error('Bad matrix_server_name') } - const appServiceMatrixId = `@${appServer.appServiceRegistration.senderLocalpart}:${twakeServer.conf.server_name}` + const appServiceMatrixId = `@${appServer.appServiceRegistration.senderLocalpart}:${conf.server_name}` // eslint-disable-next-line @typescript-eslint/restrict-template-expressions const roomAliasName = `_twake_${req.body.aliasName}` - const rooms = await twakeServer.matrixDb.get('room_aliases', undefined, { + const rooms = await matrixDb.get('room_aliases', undefined, { room_alias: roomAliasName }) if (rooms.length > 1) { @@ -62,7 +70,7 @@ export const createRoom = ( const response = await fetch( encodeURI( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/createRoom` + `https://${conf.matrix_server}/_matrix/client/v3/createRoom` ), { method: 'POST', @@ -103,40 +111,32 @@ export const createRoom = ( } newRoomId = body.room_id } - const twakeRoom = await TwakeRoom.getRoom( - twakeServer.db as TwakeDB, - newRoomId - ) + const twakeRoom = await TwakeRoom.getRoom(db, newRoomId) if (twakeRoom != null && rooms.length > 0) { throw new AppServerAPIError({ status: 409, message: 'This room already exits in Twake database' }) } else if (twakeRoom != null) { - await twakeRoom.updateRoom( - twakeServer.db as TwakeDB, - req.body.ldapFilter - ) + await twakeRoom.updateRoom(db, req.body.ldapFilter) } else { - await new TwakeRoom(newRoomId, req.body.ldapFilter).saveRoom( - twakeServer.db as TwakeDB - ) + await new TwakeRoom(newRoomId, req.body.ldapFilter).saveRoom(db) } const [ldapUsers, matrixUsers] = await Promise.all< Array> >([ - twakeServer.idServer.userDB.get( + userDb.get( 'users', - [twakeServer.conf.ldap_uid_field as string], + [conf.ldap_uid_field as string], req.body.ldapFilter ), - twakeServer.matrixDb.getAll('users', ['name']) + matrixDb.getAll('users', ['name']) ]) const ldapUsersIds = ldapUsers.map( (user) => - `@${user[twakeServer.conf.ldap_uid_field as string] as string}:${ - twakeServer.conf.server_name + `@${user[conf.ldap_uid_field as string] as string}:${ + conf.server_name }` ) const matrixUsersIds = matrixUsers.map((user) => user.name as string) @@ -152,7 +152,7 @@ export const createRoom = ( return fetch( encodeURI( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/join/${newRoomId}?user_id=${id}` + `https://${conf.matrix_server}/_matrix/client/v3/join/${newRoomId}?user_id=${id}` ), { method: 'POST', @@ -174,8 +174,7 @@ export const createRoom = ( > if ('errcode' in body) { joinErrors.push({ - [twakeServer.conf.ldap_uid_field as string]: - usersIdsMatchingFilter[index], + [conf.ldap_uid_field as string]: usersIdsMatchingFilter[index], ...body }) } @@ -183,8 +182,7 @@ export const createRoom = ( } case 'rejected': joinErrors.push({ - [twakeServer.conf.ldap_uid_field as string]: - usersIdsMatchingFilter[index], + [conf.ldap_uid_field as string]: usersIdsMatchingFilter[index], errcode: allMatrixErrorCodes.unknown, error: response.reason ?? 'Internal server error' }) @@ -195,7 +193,7 @@ export const createRoom = ( } joinErrors.length > 0 ? res.json(joinErrors) : res.send() } catch (error) { - appServer.logger.error(error) + logger.error(error) next(error) } } diff --git a/packages/tom-server/src/application-server/index.test.ts b/packages/tom-server/src/administration-console-api/index.test.ts similarity index 57% rename from packages/tom-server/src/application-server/index.test.ts rename to packages/tom-server/src/administration-console-api/index.test.ts index 07c204a7..cc7a8fa2 100644 --- a/packages/tom-server/src/application-server/index.test.ts +++ b/packages/tom-server/src/administration-console-api/index.test.ts @@ -1,7 +1,5 @@ -import { type TwakeLogger } from '@twake/logger' import { type AppServiceOutput } from '@twake/matrix-application-server/src/utils' import { type DbGetResult } from '@twake/matrix-identity-server' -import dockerComposeV1, { v2 as dockerComposeV2 } from 'docker-compose' import express from 'express' import fs from 'fs' import type * as http from 'http' @@ -18,12 +16,12 @@ import { type StartedDockerComposeEnvironment, type StartedTestContainer } from 'testcontainers' -import AppServiceAPI from '.' import TwakeServer from '..' import JEST_PROCESS_ROOT_PATH from '../../jest.globals' import { allMatrixErrorCodes, type Collections, type Config } from '../types' -import { addUser, buildUserDB, deleteUserDB } from './__testData__/build-userdb' -import defaultConfig from './__testData__/config.json' +import { buildUserDB } from './__testData__/build-userdb' +import integrationTestsConfig from './__testData__/integration-tests-config.json' +import mockTestsConfig from './__testData__/mock-tests-config.json' import { TwakeRoom } from './models/room' // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -32,7 +30,7 @@ const syswideCas = require('@small-tech/syswide-cas') const pathToTestDataFolder = path.join( JEST_PROCESS_ROOT_PATH, 'src', - 'application-server', + 'administration-console-api', '__testData__' ) const pathToSynapseDataFolder = path.join(pathToTestDataFolder, 'synapse-data') @@ -42,266 +40,96 @@ const authToken = jest.unmock('node-fetch') -const mockLogger: Partial = { - debug: jest.fn(), - error: jest.fn(), - warn: jest.fn(), - info: jest.fn() -} - -describe('ApplicationServer', () => { - const ldapHostPort = 21389 +describe('Administration Console API', () => { const twakeServerPort = 3001 let twakeServer: TwakeServer let app: express.Application let expressTwakeServer: http.Server - let startedLdap: StartedTestContainer - let startedCompose: StartedDockerComposeEnvironment - let testConfig = defaultConfig as Partial - - const simulationConnection = async ( - username: string, - password: string - ): Promise => { - try { - let response = await fetch.default( - encodeURI( - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/login` - ) - ) - let body = (await response.json()) as any - const providerId = body.flows[0].identity_providers[0].id - response = await fetch.default( - encodeURI( - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `https://${twakeServer.conf.matrix_server}/_matrix/client/r0/login/sso/redirect/${providerId}?redirectUrl=http://localhost:9876` - ), - { - redirect: 'manual' - } - ) - let location = response.headers.get('location') as string - const matrixCookies = response.headers.get('set-cookie') - response = await fetch.default(location) - body = await response.text() - const hiddenInputFieldsWithValue = [ - ...(body as string).matchAll(/ `${matchElt[1]}=${matchElt[2]}&`) - .join('') - const formWithToken = `${hiddenInputFieldsWithValue}user=${username}&password=${password}` - response = await fetch.default(location, { - method: 'POST', - body: new URLSearchParams(formWithToken), - redirect: 'manual' - }) - location = response.headers.get('location') as string - response = await fetch.default(location, { - headers: { - cookie: matrixCookies as string - } - }) - body = await response.text() - const loginTokenValue = [ - ...(body as string).matchAll(/loginToken=(\S+?)"/g) - ][0][1] - response = await fetch.default( - encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/login` - ), - { - method: 'POST', - body: JSON.stringify({ - initial_device_display_name: 'Jest Test Client', - token: loginTokenValue, - type: 'm.login.token' - }) - } - ) - return ((await response.json()) as any).access_token as string - } catch (e) { - console.log(e) - } - } - beforeAll((done) => { - GenericContainer.fromDockerfile(path.join(pathToTestDataFolder, 'ldap')) - .build() - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((builtContainer) => { - return builtContainer - .withExposedPorts({ - container: 389, - host: ldapHostPort - }) - .start() - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((startedContainer) => { - const interfaces = os.networkInterfaces() - const hostNetworkInterface = Object.keys(interfaces) - .reduce((acc, key) => { - return interfaces[key] != null - ? [...acc, ...(interfaces[key] as os.NetworkInterfaceInfo[])] - : acc - }, []) - .find( - (networkInterface) => - networkInterface.family === 'IPv4' && !networkInterface.internal - ) as os.NetworkInterfaceInfo - startedLdap = startedContainer - testConfig = { - ...testConfig, - userdb_engine: 'ldap', - base_url: `http://${hostNetworkInterface.address}:${twakeServerPort}/`, - ldap_uri: `ldap://${startedLdap.getHost()}:${ldapHostPort}/` - } - return buildUserDB(testConfig) - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - twakeServer = new TwakeServer(testConfig) - app = express() - return twakeServer.ready - }) - .then(() => { - app.use(twakeServer.endpoints) - expressTwakeServer = app.listen(twakeServerPort, () => { - done() - }) - }) - .catch((e) => { - console.log(e) - done(e) - }) - }) - - afterAll((done) => { + describe('Integration tests', () => { + let appServiceToken: string const filesToDelete = [ - path.join(pathToTestDataFolder, 'test.db'), - path.join(pathToSynapseDataFolder, 'registration.yaml'), - path.join(pathToSynapseDataFolder, 'homeserver.db'), - path.join(pathToSynapseDataFolder, 'matrix.example.com.signing.key') + path.join(pathToSynapseDataFolder, 'homeserver.log'), + path.join(pathToSynapseDataFolder, 'homeserver.db-shm'), + path.join(pathToSynapseDataFolder, 'homeserver.db-wal'), + path.join(pathToSynapseDataFolder, 'matrix.example.com.signing.key'), + path.join(pathToSynapseDataFolder, 'media_store'), + path.join(pathToSynapseDataFolder, 'registration.yaml') ] - filesToDelete.forEach((path: string) => { - if (fs.existsSync(path)) fs.unlinkSync(path) - }) - if (twakeServer != null) twakeServer.cleanJobs() - if (startedLdap != null) { - startedLdap - .stop() - .then(() => { - if (expressTwakeServer != null) { - expressTwakeServer.close((e) => { - if (e != null) { - console.log(e) - done(e) - } - done() - }) - } - }) - .catch((e) => { - console.log(e) - done(e) - }) - } else { - done() - } - }) + const ldapHostPort = 21389 + let startedLdap: StartedTestContainer + let startedCompose: StartedDockerComposeEnvironment + let startedPostgresql: StartedTestContainer - describe('Integration tests', () => { - let appServiceToken: string - let newRoomId: string - let rSkywalkerMatrixToken: string - let containerNameSuffix: string + let testConfig = integrationTestsConfig as Partial - beforeAll((done) => { - syswideCas.addCAs( - path.join( - pathToTestDataFolder, - 'nginx', - 'ssl', - 'matrix.example.com.crt' - ) - ) - syswideCas.addCAs( - path.join(pathToTestDataFolder, 'nginx', 'ssl', 'auth.example.com.crt') - ) - appServiceToken = ( - load( - fs.readFileSync(testConfig.registration_file_path as string, { - encoding: 'utf8' - }) - ) as AppServiceOutput - ).as_token - deleteUserDB(testConfig) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((_) => - Promise.allSettled([ - dockerComposeV1.version(), - dockerComposeV2.version() - ]) - ) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((results) => { - const promiseSucceededIndex = results.findIndex( - (res) => res.status === 'fulfilled' + const simulationConnection = async ( + username: string, + password: string, + matrixServer = twakeServer.conf.matrix_server + ): Promise => { + try { + let response = await fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixServer}/_matrix/client/v3/login` ) - if (promiseSucceededIndex === -1) { - throw new Error('Docker compose is not installed') + ) + let body = (await response.json()) as any + const providerId = body.flows[0].identity_providers[0].id + response = await fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixServer}/_matrix/client/r0/login/sso/redirect/${providerId}?redirectUrl=http://localhost:9876` + ), + { + redirect: 'manual' } - containerNameSuffix = promiseSucceededIndex === 0 ? '_' : '-' - return new DockerComposeEnvironment( - path.join(pathToTestDataFolder), - 'docker-compose.yml' - ) - .withEnvironment({ MYUID: os.userInfo().uid.toString() }) - .withWaitStrategy( - `synapse${containerNameSuffix}1`, - Wait.forHealthCheck() - ) - .up() - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((upResult) => { - startedCompose = upResult - return addUser(testConfig, [ - '@askywalker:example.com', - '@dwho:example.com' - ]) + ) + let location = (response.headers.get('location') as string).replace( + 'auth.example.com', + 'auth.example.com:444' + ) + const matrixCookies = response.headers.get('set-cookie') + response = await fetch.default(location) + body = await response.text() + const hiddenInputFieldsWithValue = [ + ...(body as string).matchAll(/ `${matchElt[1]}=${matchElt[2]}&`) + .join('') + const formWithToken = `${hiddenInputFieldsWithValue}user=${username}&password=${password}` + response = await fetch.default(location, { + method: 'POST', + body: new URLSearchParams(formWithToken), + redirect: 'manual' }) - .then(done) - .catch((e) => { - console.log(e) - done(e) + location = response.headers.get('location') as string + response = await fetch.default(location, { + headers: { + cookie: matrixCookies as string + } }) - }) - - afterAll((done) => { - const filesToDelete = [ - path.join(pathToSynapseDataFolder, 'homeserver.log'), - path.join(pathToSynapseDataFolder, 'homeserver.db-shm'), - path.join(pathToSynapseDataFolder, 'homeserver.db-wal') - ] - filesToDelete.forEach((path: string) => { - if (fs.existsSync(path)) fs.unlinkSync(path) - }) - if (startedCompose != null) { - startedCompose - .down() - .then(() => { - done() - }) - .catch((e) => { - console.log(e) - done(e) - }) - } else { - done() + body = await response.text() + const loginTokenValue = [ + ...(body as string).matchAll(/loginToken=(\S+?)"/g) + ][0][1] + response = await fetch.default( + encodeURI(`https://${matrixServer}/_matrix/client/v3/login`), + { + method: 'POST', + body: JSON.stringify({ + initial_device_display_name: 'Jest Test Client', + token: loginTokenValue, + type: 'm.login.token' + }) + } + ) + return ((await response.json()) as any).access_token as string + } catch (e) { + console.log(e) } - }) + } // eslint-disable-next-line @typescript-eslint/promise-function-async const getUserRoomMembership = ( @@ -326,324 +154,612 @@ describe('ApplicationServer', () => { }) } - it('should create room and force users matching the filter to join the new room', async () => { - const response = await request(app) - .post('/_twake/app/v1/rooms') - .set('Accept', 'application/json') - .set('Authorization', `Bearer ${authToken}`) - .send({ - name: 'room1', - visibility: 'public', - aliasName: 'r1', - topic: 'test room', - ldapFilter: { - mail: ['*skywalker@example.com', 'dwho@example.com'] - } - }) - expect(response.statusCode).toBe(200) - expect(response.body).toEqual({}) - const rooms = await twakeServer.db?.getAll( - 'rooms' as unknown as Collections, - ['*'] - ) - expect(rooms).not.toBeUndefined() - expect((rooms as DbGetResult).length).toEqual(1) - const newRoom = (rooms as DbGetResult)[0] - newRoomId = newRoom.id as string - expect(newRoom.filter).toEqual( - JSON.stringify({ - mail: ['*skywalker@example.com', 'dwho@example.com'] - }) - ) - const membersIds = await twakeServer.matrixDb.get( - 'room_memberships', - ['user_id'], - { room_id: newRoomId } - ) - expect(membersIds).not.toBeUndefined() - expect(membersIds.length).toEqual(3) - const userIds = membersIds.map((ids) => ids.user_id) - expect(userIds).toEqual( - expect.arrayContaining([ - '@twake:example.com', - '@dwho:example.com', - '@askywalker:example.com' - ]) - ) - }) - - it('should force user to join room on login', (done) => { - twakeServer.matrixDb - .get('room_memberships', ['user_id'], { - room_id: newRoomId + beforeAll((done) => { + GenericContainer.fromDockerfile(path.join(pathToTestDataFolder, 'ldap')) + .build() + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((builtContainer) => { + return builtContainer + .withExposedPorts({ + container: 389, + host: ldapHostPort + }) + .start() }) // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((membersIds) => { - expect(membersIds.length).toEqual(3) - const userIds = membersIds.map((ids) => ids.user_id) - expect(userIds).toEqual( - expect.arrayContaining([ - '@twake:example.com', - '@dwho:example.com', - '@askywalker:example.com' + .then((startedContainer) => { + const interfaces = os.networkInterfaces() + const hostNetworkInterface = Object.keys(interfaces) + .reduce((acc, key) => { + return interfaces[key] != null + ? [...acc, ...(interfaces[key] as os.NetworkInterfaceInfo[])] + : acc + }, []) + .find( + (networkInterface) => + networkInterface.family === 'IPv4' && !networkInterface.internal + ) as os.NetworkInterfaceInfo + startedLdap = startedContainer + testConfig = { + ...testConfig, + userdb_engine: 'ldap', + base_url: `http://${hostNetworkInterface.address}:${twakeServerPort}/`, + ldap_uri: `ldap://${startedLdap.getHost()}:${ldapHostPort}/` + } + return new GenericContainer('postgres:13-bullseye') + .withName('postgresql') + .withExposedPorts({ + container: 5432, + host: 5434 + }) + .withCopyFilesToContainer([ + { + source: path.join( + pathToSynapseDataFolder, + 'matrix.example.com.log.config' + ), + target: '/data/matrix.example.com.log.config' + } ]) - ) - const client = ldapjs.createClient({ - url: `ldap://${startedLdap.getHost()}:${ldapHostPort}/` - }) - client.bind('cn=admin,dc=example,dc=com', 'admin', (err) => { - if (err != null) { - console.error(err) - } - }) - client.add( - 'uid=rskywalker,ou=users,dc=example,dc=com', - { - objectClass: 'inetOrgPerson', - uid: 'rskywalker', - cn: 'Rey Skywalker', - sn: 'Rskywalker', - mail: 'rskywalker@example.com', - userPassword: 'rskywalker' - }, - (err) => { - if (err != null) { - console.error(err) + .withCopyFilesToContainer([ + { + source: path.join( + pathToTestDataFolder, + 'db', + 'init-synapse-and-create-users-table.sh' + ), + target: + '/docker-entrypoint-initdb.d/init-synapse-and-create-users-table.sh' } - client.destroy() - } - ) - return simulationConnection('rskywalker', 'rskywalker') - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((token) => { - rSkywalkerMatrixToken = token as string - return fetch.default( - encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/sync` - ), - { - headers: { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - Authorization: `Bearer ${token}` + ]) + .withCopyFilesToContainer([ + { + source: path.join( + pathToTestDataFolder, + 'db', + 'init-llng-db.sh' + ), + target: '/docker-entrypoint-initdb.d/init-llng-db.sh' } - } - ) + ]) + .withCopyFilesToContainer([ + { + source: path.join( + pathToTestDataFolder, + 'db', + 'init-twake-db.sh' + ), + target: '/docker-entrypoint-initdb.d/init-twake-db.sh' + } + ]) + .withCopyFilesToContainer([ + { + source: path.join( + pathToTestDataFolder, + 'llng', + 'lmConf-1.json' + ), + target: '/llng-conf/conf.json' + } + ]) + .withEnvironment({ POSTGRES_PASSWORD: 'synapse!!' }) + .withHealthCheck({ + test: ['CMD-SHELL', 'pg_isready'], + interval: 1000, + timeout: 5000, + retries: 5 + }) + .start() }) // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return new Promise((resolve, reject) => { - setTimeout(() => { - twakeServer.matrixDb - .get('room_memberships', ['user_id'], { - room_id: newRoomId - }) - .then((memberships) => { - resolve(memberships) - }) - .catch((e) => { - console.log(e) - reject(e) - }) - }, 3000) - }) + .then((started) => { + startedPostgresql = started + twakeServer = new TwakeServer(testConfig) + return twakeServer.ready }) - .then((membersIds) => { - expect(membersIds.length).toEqual(4) - expect(membersIds[3].user_id).toEqual('@rskywalker:example.com') - done() + .then(() => { + if (twakeServer != null) twakeServer.cleanJobs() + if (startedPostgresql != null) { + startedPostgresql + .stop() + .then(() => { + done() + }) + .catch((e) => { + done(e) + }) + } else { + done() + } }) .catch((e) => { - console.log(e) done(e) }) }) - it('should join again room if user tries to leave', (done) => { - fetch - .default( - encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/leave` - ), - { - method: 'POST', - headers: { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - Authorization: `Bearer ${rSkywalkerMatrixToken}` + afterAll((done) => { + if (startedLdap != null) { + startedLdap + .stop() + .then(() => { + if (expressTwakeServer != null) { + expressTwakeServer.close((e) => { + if (e != null) { + done(e) + } + done() + }) } - } - ) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return getUserRoomMembership(newRoomId, '@rskywalker:example.com') - }) - .then((memberships) => { - expect(memberships.length).toEqual(3) - expect(memberships[0].membership).toEqual('join') - expect(memberships[1].membership).toEqual('leave') - expect(memberships[2].membership).toEqual('join') - done() - }) - .catch((e) => { - console.log(e) - done(e) - }) + }) + .catch((e) => { + done(e) + }) + } else { + done() + } }) - it("should not be able to kick another member if he is not the room's creator", (done) => { - fetch - .default( - encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/kick` - ), - { - method: 'POST', - headers: { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - Authorization: `Bearer ${rSkywalkerMatrixToken}` - }, - body: JSON.stringify({ - user_id: '@askywalker:example.com' + describe('Automatic subscription', () => { + let newRoomId: string + let rSkywalkerMatrixToken: string + + beforeAll((done) => { + syswideCas.addCAs( + path.join(pathToTestDataFolder, 'nginx', 'ssl', 'ca.pem') + ) + appServiceToken = ( + load( + fs.readFileSync(testConfig.registration_file_path as string, { + encoding: 'utf8' }) - } + ) as AppServiceOutput + ).as_token + new DockerComposeEnvironment( + path.join(pathToTestDataFolder), + 'docker-compose.yml' ) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return getUserRoomMembership(newRoomId, '@askywalker:example.com') - }) - .then((memberships) => { - expect(memberships.length).toEqual(1) - expect(memberships[0].membership).toEqual('join') - done() - }) - .catch((e) => { - console.log(e) - done(e) + .withEnvironment({ MYUID: os.userInfo().uid.toString() }) + .withWaitStrategy('synapse-tom-1', Wait.forHealthCheck()) + .up() + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((upResult) => { + startedCompose = upResult + twakeServer = new TwakeServer(testConfig) + app = express() + return twakeServer.ready + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return Promise.all([ + twakeServer.matrixDb.insert('users', { + name: '@askywalker:example.com', + password_hash: '', + creation_ts: Math.floor(Date.now() / 1000), + admin: 0, + upgrade_ts: 1, + is_guest: 0, + appservice_id: '', + consent_version: '', + consent_server_notice_sent: '', + user_type: '', + deactivated: 0, + shadow_banned: 'false', + consent_ts: 1 + }), + twakeServer.matrixDb.insert('users', { + name: '@dwho:example.com', + password_hash: '', + creation_ts: Math.floor(Date.now() / 1000), + admin: 0, + upgrade_ts: 1, + is_guest: 0, + appservice_id: '', + consent_version: '', + consent_server_notice_sent: '', + user_type: '', + deactivated: 0, + shadow_banned: 'false', + consent_ts: 1 + }) + ]).then(() => { + app.use(twakeServer.endpoints) + expressTwakeServer = app.listen(twakeServerPort, () => { + done() + }) + }) + }) + .catch((e) => { + console.log(e) + done(e) + }) + }) + + afterAll((done) => { + filesToDelete.forEach((path: string) => { + if (fs.existsSync(path)) { + const isDir = fs.statSync(path).isDirectory() + isDir + ? fs.rmSync(path, { recursive: true, force: true }) + : fs.unlinkSync(path) + } }) - }) - it("should not join room on login if user has been kicked by room's creator", (done) => { - fetch - .default( - encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/kick` - ), - { - method: 'POST', - headers: { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - Authorization: `Bearer ${appServiceToken}` - }, - body: JSON.stringify({ - user_id: '@rskywalker:example.com' + if (twakeServer != null) twakeServer.cleanJobs() + if (startedCompose != null) { + startedCompose + .down() + .then(() => { + done() }) - } + .catch((e) => { + done(e) + }) + } else { + done() + } + }) + + it('should create room and force users matching the filter to join the new room', async () => { + const response = await request(app) + .post('/_twake/app/v1/rooms') + .set('Accept', 'application/json') + .set('Authorization', `Bearer ${authToken}`) + .send({ + name: 'room1', + visibility: 'public', + aliasName: 'r1', + topic: 'test room', + ldapFilter: { + mail: ['*skywalker@example.com', 'dwho@example.com'] + } + }) + expect(response.statusCode).toBe(200) + expect(response.body).toEqual({}) + const rooms = await twakeServer.db?.getAll( + 'rooms' as unknown as Collections, + ['*'] ) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return getUserRoomMembership(newRoomId, '@rskywalker:example.com') - }) - .then((memberships) => { - expect(memberships.length).toEqual(4) - expect(memberships[0].membership).toEqual('join') - expect(memberships[1].membership).toEqual('leave') - expect(memberships[2].membership).toEqual('join') - expect(memberships[3].membership).toEqual('leave') - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return fetch.default( + expect(rooms).not.toBeUndefined() + expect((rooms as DbGetResult).length).toEqual(1) + const newRoom = (rooms as DbGetResult)[0] + newRoomId = newRoom.id as string + expect(newRoom.filter).toEqual( + JSON.stringify({ + mail: ['*skywalker@example.com', 'dwho@example.com'] + }) + ) + const membersIds = await twakeServer.matrixDb.get( + 'room_memberships', + ['user_id'], + { room_id: newRoomId } + ) + expect(membersIds).not.toBeUndefined() + expect(membersIds.length).toEqual(3) + const userIds = membersIds.map((ids) => ids.user_id) + expect(userIds).toEqual( + expect.arrayContaining([ + '@twake:example.com', + '@dwho:example.com', + '@askywalker:example.com' + ]) + ) + }) + + it('should force user to join room on login', (done) => { + twakeServer.matrixDb + .get('room_memberships', ['user_id'], { + room_id: newRoomId + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((membersIds) => { + expect(membersIds.length).toEqual(3) + const userIds = membersIds.map((ids) => ids.user_id) + expect(userIds).toEqual( + expect.arrayContaining([ + '@twake:example.com', + '@dwho:example.com', + '@askywalker:example.com' + ]) + ) + const client = ldapjs.createClient({ + url: `ldap://${startedLdap.getHost()}:${ldapHostPort}/` + }) + client.bind('cn=admin,dc=example,dc=com', 'admin', (err) => { + if (err != null) { + console.error(err) + } + }) + client.add( + 'uid=rskywalker,ou=users,dc=example,dc=com', + { + objectClass: 'inetOrgPerson', + uid: 'rskywalker', + cn: 'Rey Skywalker', + sn: 'Rskywalker', + mail: 'rskywalker@example.com', + userPassword: 'rskywalker' + }, + (err) => { + if (err != null) { + console.error(err) + } + client.destroy() + } + ) + return simulationConnection('rskywalker', 'rskywalker') + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((token) => { + rSkywalkerMatrixToken = token as string + return fetch.default( + encodeURI( + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/sync` + ), + { + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${token}` + } + } + ) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return new Promise((resolve, reject) => { + setTimeout(() => { + twakeServer.matrixDb + .get('room_memberships', ['user_id'], { + room_id: newRoomId + }) + .then((memberships) => { + resolve(memberships) + }) + .catch((e) => { + console.log(e) + reject(e) + }) + }, 3000) + }) + }) + .then((membersIds) => { + expect(membersIds.length).toEqual(4) + expect(membersIds[3].user_id).toEqual('@rskywalker:example.com') + done() + }) + .catch((e) => { + console.log(e) + done(e) + }) + }) + + it('should join again room if user tries to leave', (done) => { + fetch + .default( encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/sync` + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/leave` ), { + method: 'POST', headers: { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions Authorization: `Bearer ${rSkywalkerMatrixToken}` } } ) - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return getUserRoomMembership(newRoomId, '@rskywalker:example.com') - }) - .then((memberships) => { - expect(memberships.length).toEqual(4) - expect(memberships[0].membership).toEqual('join') - expect(memberships[1].membership).toEqual('leave') - expect(memberships[2].membership).toEqual('join') - expect(memberships[3].membership).toEqual('leave') - done() - }) - .catch((e) => { - console.log(e) - done(e) - }) - }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return getUserRoomMembership(newRoomId, '@rskywalker:example.com') + }) + .then((memberships) => { + expect(memberships.length).toEqual(3) + expect(memberships[0].membership).toEqual('join') + expect(memberships[1].membership).toEqual('leave') + expect(memberships[2].membership).toEqual('join') + done() + }) + .catch((e) => { + console.log(e) + done(e) + }) + }) - it("should not join room on login if user has been banned by room's creator", (done) => { - fetch - .default( - encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/ban` - ), - { - method: 'POST', - headers: { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - Authorization: `Bearer ${appServiceToken}` - }, - body: JSON.stringify({ - user_id: '@askywalker:example.com' - }) - } - ) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => { - return getUserRoomMembership(newRoomId, '@askywalker:example.com') - }) - .then((memberships) => { - expect(memberships.length).toEqual(2) - expect(memberships[0].membership).toEqual('join') - expect(memberships[1].membership).toEqual('ban') - }) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then(() => simulationConnection('askywalker', 'askywalker')) - // eslint-disable-next-line @typescript-eslint/promise-function-async - .then((token) => { - return fetch.default( + it("should not be able to kick another member if he is not the room's creator", (done) => { + fetch + .default( + encodeURI( + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/kick` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${rSkywalkerMatrixToken}` + }, + body: JSON.stringify({ + user_id: '@askywalker:example.com' + }) + } + ) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return getUserRoomMembership(newRoomId, '@askywalker:example.com') + }) + .then((memberships) => { + expect(memberships.length).toEqual(1) + expect(memberships[0].membership).toEqual('join') + done() + }) + .catch((e) => { + console.log(e) + done(e) + }) + }) + + it("should not join room on login if user has been kicked by room's creator", (done) => { + fetch + .default( encodeURI( - `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/sync` + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/kick` ), { + method: 'POST', headers: { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - Authorization: `Bearer ${token}` + Authorization: `Bearer ${appServiceToken}` + }, + body: JSON.stringify({ + user_id: '@rskywalker:example.com' + }) + } + ) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return getUserRoomMembership(newRoomId, '@rskywalker:example.com') + }) + .then((memberships) => { + expect(memberships.length).toEqual(4) + expect(memberships[0].membership).toEqual('join') + expect(memberships[1].membership).toEqual('leave') + expect(memberships[2].membership).toEqual('join') + expect(memberships[3].membership).toEqual('leave') + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return fetch.default( + encodeURI( + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/sync` + ), + { + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${rSkywalkerMatrixToken}` + } } + ) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return getUserRoomMembership(newRoomId, '@rskywalker:example.com') + }) + .then((memberships) => { + expect(memberships.length).toEqual(4) + expect(memberships[0].membership).toEqual('join') + expect(memberships[1].membership).toEqual('leave') + expect(memberships[2].membership).toEqual('join') + expect(memberships[3].membership).toEqual('leave') + done() + }) + .catch((e) => { + console.log(e) + done(e) + }) + }) + + it("should not join room on login if user has been banned by room's creator", (done) => { + fetch + .default( + encodeURI( + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/rooms/${newRoomId}/ban` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${appServiceToken}` + }, + body: JSON.stringify({ + user_id: '@askywalker:example.com' + }) } ) - }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return getUserRoomMembership(newRoomId, '@askywalker:example.com') + }) + .then((memberships) => { + expect(memberships.length).toEqual(2) + expect(memberships[0].membership).toEqual('join') + expect(memberships[1].membership).toEqual('ban') + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => simulationConnection('askywalker', 'askywalker')) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((token) => { + return fetch.default( + encodeURI( + `https://${twakeServer.conf.matrix_server}/_matrix/client/v3/sync` + ), + { + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${token}` + } + } + ) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return getUserRoomMembership(newRoomId, '@askywalker:example.com') + }) + .then((memberships) => { + expect(memberships.length).toEqual(2) + expect(memberships[0].membership).toEqual('join') + expect(memberships[1].membership).toEqual('ban') + done() + }) + .catch((e) => { + console.log(e) + done(e) + }) + }) + }) + }) + + describe('Tests with mocks', () => { + beforeEach(() => { + jest.restoreAllMocks() + }) + + beforeAll((done) => { + buildUserDB(mockTestsConfig as Config) // eslint-disable-next-line @typescript-eslint/promise-function-async .then(() => { - return getUserRoomMembership(newRoomId, '@askywalker:example.com') + twakeServer = new TwakeServer(mockTestsConfig as Config) + app = express() + return twakeServer.ready }) - .then((memberships) => { - expect(memberships.length).toEqual(2) - expect(memberships[0].membership).toEqual('join') - expect(memberships[1].membership).toEqual('ban') - done() + .then(() => { + app.use(twakeServer.endpoints) + expressTwakeServer = app.listen(twakeServerPort, () => { + done() + }) }) .catch((e) => { - console.log(e) done(e) }) }) - }) - describe('Tests with mocks', () => { - beforeEach(() => { - jest.restoreAllMocks() + afterAll((done) => { + const filesToDelete = [ + path.join(pathToTestDataFolder, 'matrix.db'), + path.join(pathToTestDataFolder, 'twake.db'), + path.join(pathToTestDataFolder, 'user.db') + ] + filesToDelete.forEach((path) => { + if (fs.existsSync(path)) fs.unlinkSync(path) + }) + + if (twakeServer != null) twakeServer.cleanJobs() + if (expressTwakeServer != null) { + expressTwakeServer.close((e) => { + if (e != null) { + done(e) + } + done() + }) + } else { + done() + } }) describe('On create room', () => { @@ -1188,15 +1304,11 @@ describe('ApplicationServer', () => { describe('on login', () => { it('should log an error when m.presence event sender is not found in user database', (done) => { const ldapUid = 'test' - const appService = new AppServiceAPI( - twakeServer, - undefined, - mockLogger as TwakeLogger - ) + const spyOnLoggerError = jest.spyOn(twakeServer.logger, 'error') jest.spyOn(twakeServer.idServer.userDB, 'get').mockResolvedValue([]) jest.spyOn(TwakeRoom, 'getAllRooms').mockResolvedValue([]) jest.spyOn(twakeServer.matrixDb, 'get').mockResolvedValue([]) - appService.emit('ephemeral_type: m.presence', { + twakeServer.applicationServer.emit('ephemeral_type: m.presence', { content: { avatar_url: 'mxc://localhost/wefuiwegh8742w', currently_active: false, @@ -1208,8 +1320,8 @@ describe('ApplicationServer', () => { type: 'm.presence' }) setTimeout(() => { - expect(mockLogger.error).toHaveBeenCalledTimes(1) - expect(mockLogger.error).toHaveBeenCalledWith( + expect(spyOnLoggerError).toHaveBeenCalledTimes(1) + expect(spyOnLoggerError).toHaveBeenCalledWith( new Error( `User with ${ twakeServer.conf.ldap_uid_field as string @@ -1221,11 +1333,7 @@ describe('ApplicationServer', () => { }) it('should complete all join requests even if an error occurs', (done) => { - const appService = new AppServiceAPI( - twakeServer, - undefined, - mockLogger as TwakeLogger - ) + const spyOnLoggerError = jest.spyOn(twakeServer.logger, 'error') jest .spyOn(fetch, 'default') .mockResolvedValueOnce(new fetch.Response()) @@ -1249,7 +1357,7 @@ describe('ApplicationServer', () => { new TwakeRoom('room3', { uid: 'bb8' }) ]) jest.spyOn(twakeServer.matrixDb, 'get').mockResolvedValue([]) - appService.emit('ephemeral_type: m.presence', { + twakeServer.applicationServer.emit('ephemeral_type: m.presence', { content: { avatar_url: 'mxc://localhost/wefuiwegh8742w', currently_active: false, @@ -1261,13 +1369,12 @@ describe('ApplicationServer', () => { type: 'm.presence' }) setTimeout(() => { - expect(mockLogger.error).not.toHaveBeenCalled() + expect(spyOnLoggerError).not.toHaveBeenCalled() done() }, 3000) }) it('should force join only to rooms whose sender is not member yet', (done) => { - const appService = new AppServiceAPI(twakeServer) const spyOnFetch = jest .spyOn(fetch, 'default') .mockResolvedValue(new fetch.Response()) @@ -1299,7 +1406,7 @@ describe('ApplicationServer', () => { membership: 'invite' } ]) - appService.emit('ephemeral_type: m.presence', { + twakeServer.applicationServer.emit('ephemeral_type: m.presence', { content: { avatar_url: 'mxc://localhost/wefuiwegh8742w', currently_active: false, diff --git a/packages/tom-server/src/application-server/index.ts b/packages/tom-server/src/administration-console-api/index.ts similarity index 53% rename from packages/tom-server/src/application-server/index.ts rename to packages/tom-server/src/administration-console-api/index.ts index 14ef984b..faa70a23 100644 --- a/packages/tom-server/src/application-server/index.ts +++ b/packages/tom-server/src/administration-console-api/index.ts @@ -1,32 +1,39 @@ -import { type ConfigDescription } from '@twake/config-parser' import { type TwakeLogger } from '@twake/logger' -import MatrixApplicationServer, { - type AppService, - type ClientEvent -} from '@twake/matrix-application-server' -import { type DbGetResult } from '@twake/matrix-identity-server' +import type MatrixApplicationServer from '@twake/matrix-application-server' +import { type ClientEvent } from '@twake/matrix-application-server' +import { + type DbGetResult, + type MatrixDB, + type UserDB +} from '@twake/matrix-identity-server' +import { type Router } from 'express' import lodash from 'lodash' import fetch from 'node-fetch' -import type TwakeServer from '..' -import defaultConfig from '../config.json' +import { type TwakeDB } from '../db' +import { type Config } from '../types' import { TwakeRoom } from './models/room' -import { extendRoutes } from './routes' +import setRoutes from './routes' const { groupBy } = lodash -export default class TwakeApplicationServer - extends MatrixApplicationServer - implements AppService -{ +export default class AdministrationConsoleAPI { + endpoints: Router constructor( - parent: TwakeServer, - confDesc?: ConfigDescription, - logger?: TwakeLogger + applicationServer: MatrixApplicationServer, + db: TwakeDB, + userDb: UserDB, + matrixDb: MatrixDB, + conf: Config, + logger: TwakeLogger ) { - if (confDesc == null) confDesc = defaultConfig - super(parent.conf, confDesc, logger) - extendRoutes(this, parent) - - this.on('ephemeral_type: m.presence', (event: ClientEvent) => { + this.endpoints = setRoutes( + applicationServer, + db, + userDb, + matrixDb, + conf, + logger + ) + applicationServer.on('ephemeral_type: m.presence', (event: ClientEvent) => { if ( event.type === 'm.presence' && 'presence' in event.content && @@ -40,13 +47,13 @@ export default class TwakeApplicationServer ldapUid = match[1] } } - if (matrixUserId != null && ldapUid != null && parent.db != null) { + if (matrixUserId != null && ldapUid != null && db != null) { Promise.all([ - parent.idServer.userDB.get('users', undefined, { - [parent.conf.ldap_uid_field as string]: ldapUid + userDb.get('users', undefined, { + [conf.ldap_uid_field as string]: ldapUid }), - TwakeRoom.getAllRooms(parent.db), - parent.matrixDb.get('room_memberships', ['room_id'], { + TwakeRoom.getAllRooms(db), + matrixDb.get('room_memberships', ['room_id'], { user_id: matrixUserId }) ]) @@ -54,7 +61,7 @@ export default class TwakeApplicationServer .then(([user, rooms, roomMemberships]) => { if (user.length !== 1) { throw new Error( - `User with ${parent.conf.ldap_uid_field as string} ${ + `User with ${conf.ldap_uid_field as string} ${ ldapUid as string } not found` ) @@ -94,12 +101,12 @@ export default class TwakeApplicationServer return fetch( encodeURI( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `https://${parent.conf.matrix_server}/_matrix/client/v3/join/${room.id}?user_id=${matrixUserId}` + `https://${conf.matrix_server}/_matrix/client/v3/join/${room.id}?user_id=${matrixUserId}` ), { method: 'POST', headers: { - Authorization: `Bearer ${this.appServiceRegistration.asToken}` + Authorization: `Bearer ${applicationServer.appServiceRegistration.asToken}` } } ) @@ -107,42 +114,45 @@ export default class TwakeApplicationServer ) }) .catch((e) => { - this.logger.error(e) + logger.error(e) }) } } }) - this.on('state event | type: m.room.member', (event: ClientEvent) => { - if ( - event.type === 'm.room.member' && - 'membership' in event.content && - event.content.membership === 'leave' - ) { - const matrixUserId = event.sender - const targetUserId = event.state_key + applicationServer.on( + 'state event | type: m.room.member', + (event: ClientEvent) => { if ( - matrixUserId != null && - targetUserId != null && - targetUserId === matrixUserId + event.type === 'm.room.member' && + 'membership' in event.content && + event.content.membership === 'leave' ) { - fetch( - encodeURI( - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `https://${parent.conf.matrix_server}/_matrix/client/v3/join/${event.room_id}?user_id=${matrixUserId}` - ), - { - method: 'POST', - headers: { - Authorization: `Bearer ${this.appServiceRegistration.asToken}` + const matrixUserId = event.sender + const targetUserId = event.state_key + if ( + matrixUserId != null && + targetUserId != null && + targetUserId === matrixUserId + ) { + fetch( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${conf.matrix_server}/_matrix/client/v3/join/${event.room_id}?user_id=${matrixUserId}` + ), + { + method: 'POST', + headers: { + Authorization: `Bearer ${applicationServer.appServiceRegistration.asToken}` + } } - } - ).catch((e) => { - // istanbul ignore next - this.logger.error(e) - }) + ).catch((e) => { + // istanbul ignore next + logger.error(e) + }) + } } } - }) + ) } } diff --git a/packages/tom-server/src/application-server/middlewares/auth.test.ts b/packages/tom-server/src/administration-console-api/middlewares/auth.test.ts similarity index 100% rename from packages/tom-server/src/application-server/middlewares/auth.test.ts rename to packages/tom-server/src/administration-console-api/middlewares/auth.test.ts diff --git a/packages/tom-server/src/application-server/middlewares/auth.ts b/packages/tom-server/src/administration-console-api/middlewares/auth.ts similarity index 100% rename from packages/tom-server/src/application-server/middlewares/auth.ts rename to packages/tom-server/src/administration-console-api/middlewares/auth.ts diff --git a/packages/tom-server/src/application-server/middlewares/validation.test.ts b/packages/tom-server/src/administration-console-api/middlewares/validation.test.ts similarity index 100% rename from packages/tom-server/src/application-server/middlewares/validation.test.ts rename to packages/tom-server/src/administration-console-api/middlewares/validation.test.ts diff --git a/packages/tom-server/src/application-server/middlewares/validation.ts b/packages/tom-server/src/administration-console-api/middlewares/validation.ts similarity index 100% rename from packages/tom-server/src/application-server/middlewares/validation.ts rename to packages/tom-server/src/administration-console-api/middlewares/validation.ts diff --git a/packages/tom-server/src/application-server/models/room.ts b/packages/tom-server/src/administration-console-api/models/room.ts similarity index 100% rename from packages/tom-server/src/application-server/models/room.ts rename to packages/tom-server/src/administration-console-api/models/room.ts diff --git a/packages/tom-server/src/application-server/routes/index.ts b/packages/tom-server/src/administration-console-api/routes/index.ts similarity index 87% rename from packages/tom-server/src/application-server/routes/index.ts rename to packages/tom-server/src/administration-console-api/routes/index.ts index 1f59192c..962edb70 100644 --- a/packages/tom-server/src/application-server/routes/index.ts +++ b/packages/tom-server/src/administration-console-api/routes/index.ts @@ -1,14 +1,23 @@ +import { type TwakeLogger } from '@twake/logger' +import type MatrixApplicationServer from '@twake/matrix-application-server' import { EHttpMethod } from '@twake/matrix-application-server' -import type TwakeApplicationServer from '..' -import type TwakeServer from '../..' +import { type MatrixDB, type UserDB } from '@twake/matrix-identity-server' +import { Router } from 'express' +import { type TwakeDB } from '../../db' +import { type Config } from '../../types' import { createRoom } from '../controllers/room' import { auth } from '../middlewares/auth' import validation from '../middlewares/validation' -export const extendRoutes = ( - appServer: TwakeApplicationServer, - twakeServer: TwakeServer -): void => { +export default ( + appServer: MatrixApplicationServer, + db: TwakeDB, + userDb: UserDB, + matrixDb: MatrixDB, + conf: Config, + logger: TwakeLogger +): Router => { + const router = Router() /** * @openapi * '/_twake/app/v1/rooms': @@ -115,10 +124,13 @@ export const extendRoutes = ( * $ref: '#/components/responses/InternalServerError' */ appServer.router.addRoute( + router, '/_twake/app/v1/rooms', EHttpMethod.POST, - createRoom(appServer, twakeServer), + createRoom(appServer, db, userDb, matrixDb, conf, logger), validation(), auth ) + + return router } diff --git a/packages/tom-server/src/application-server/types.ts b/packages/tom-server/src/administration-console-api/types.ts similarity index 100% rename from packages/tom-server/src/application-server/types.ts rename to packages/tom-server/src/administration-console-api/types.ts diff --git a/packages/tom-server/src/application-server/__testData__/build-userdb.ts b/packages/tom-server/src/application-server/__testData__/build-userdb.ts deleted file mode 100644 index 9261216f..00000000 --- a/packages/tom-server/src/application-server/__testData__/build-userdb.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* istanbul ignore file */ -import sqlite3 from 'sqlite3' - -interface Config { - database_host: string - [k: string]: any -} - -let created = false - -// eslint-disable-next-line @typescript-eslint/promise-function-async -export const buildUserDB = (conf: Partial): Promise => { - if (created) return Promise.resolve() - return new Promise((resolve, reject) => { - const matrixDb = new sqlite3.Database(conf.matrix_database_host) - - matrixDb.run( - 'CREATE TABLE users (name text, desactivated text, admin integer)', - (err) => { - if (err != null) { - reject(err) - } else { - created = true - resolve() - } - } - ) - }) -} - -// eslint-disable-next-line @typescript-eslint/promise-function-async -export const deleteUserDB = (conf: Partial): Promise => { - return new Promise((resolve, reject) => { - const matrixDb = new sqlite3.Database(conf.matrix_database_host) - matrixDb.run( - 'DROP TABLE users', - (err) => { - if (err != null) { - reject(err) - } else { - resolve() - } - } - ) - }) -} - -// eslint-disable-next-line @typescript-eslint/promise-function-async -export const addUser = (conf: Partial, usersIds: string[]): Promise => { - return new Promise((resolve, reject) => { - const matrixDb = new sqlite3.Database(conf.matrix_database_host) - usersIds.forEach((userId) => { - matrixDb.run( - // columns headers: name|password_hash|creation_ts(seconds)|admin|upgrade_ts|is_guest|appservice_id|consent_version|consent_server_notice_sent|user_type|deactivated|shadow_banned|consent_ts|approved - `INSERT INTO users VALUES('${userId}', '', ${Math.floor(Date.now() / 1000)}, 0, '', 0, '', '', '', '', 0, 0, '', 1)`, - (err) => { - if (err != null) { - reject(err) - } else { - resolve() - } - } - ) - }) - }) -} diff --git a/packages/tom-server/src/application-server/__testData__/docker-compose.yml b/packages/tom-server/src/application-server/__testData__/docker-compose.yml deleted file mode 100644 index 2fc27899..00000000 --- a/packages/tom-server/src/application-server/__testData__/docker-compose.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: '3.8' - -services: - synapse: - image: matrixdotorg/synapse:v1.89.0 - volumes: - - ./synapse-data:/data - - ./nginx/ssl/auth.example.com.crt:/etc/ssl/certs/ca-certificates.crt - depends_on: - - auth - environment: - - UID=${MYUID} - - VIRTUAL_PORT=8008 - - VIRTUAL_HOST=matrix.example.com - healthcheck: - test: ["CMD", "curl", "-fSs", "http://localhost:8008/health"] - interval: 10s - timeout: 10s - retries: 3 - extra_hosts: - - "host.docker.internal:host-gateway" - - auth: - image: yadd/lemonldap-ng-portal:2.18.2-9 - hostname: auth.example.com - volumes: - - ./llng/lmConf-1.json:/var/lib/lemonldap-ng/conf/lmConf-1.json - - ./llng/ssl.conf:/etc/nginx/sites-enabled/0000default.conf - - ./nginx/ssl/auth.example.com.crt:/etc/nginx/ssl/auth.example.com.crt - - ./nginx/ssl/auth.example.com.key:/etc/nginx/ssl/auth.example.com.key - environment: - - PORTAL=https://auth.example.com - - VIRTUAL_HOST=auth.example.com - extra_hosts: - - "host.docker.internal:host-gateway" - - nginx-proxy: - image: nginxproxy/nginx-proxy - ports: - - 443:443 - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./nginx/ssl:/etc/nginx/certs \ No newline at end of file diff --git a/packages/tom-server/src/application-server/__testData__/nginx/ssl/auth.example.com.crt b/packages/tom-server/src/application-server/__testData__/nginx/ssl/auth.example.com.crt deleted file mode 100644 index af15717e..00000000 --- a/packages/tom-server/src/application-server/__testData__/nginx/ssl/auth.example.com.crt +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEETCCAvmgAwIBAgIUOVvatcBdUi71/U3VpkjRrG8jz84wDQYJKoZIhvcNAQEL -BQAwgZcxCzAJBgNVBAYTAkZSMRIwEAYDVQQIDAlPY2NpdGFuaWUxETAPBgNVBAcM -CFRvdWxvdXNlMREwDwYDVQQKDAhMaW5hZ29yYTEMMAoGA1UECwwDR1NPMRkwFwYD -VQQDDBBhdXRoLmV4YW1wbGUuY29tMSUwIwYJKoZIhvcNAQkBFhZqY2FiYW5uZXNA -bGluYWdvcmEuY29tMB4XDTIzMDYyMjE2MTIyOFoXDTI3MDYyMTE2MTIyOFowgZcx -CzAJBgNVBAYTAkZSMRIwEAYDVQQIDAlPY2NpdGFuaWUxETAPBgNVBAcMCFRvdWxv -dXNlMREwDwYDVQQKDAhMaW5hZ29yYTEMMAoGA1UECwwDR1NPMRkwFwYDVQQDDBBh -dXRoLmV4YW1wbGUuY29tMSUwIwYJKoZIhvcNAQkBFhZqY2FiYW5uZXNAbGluYWdv -cmEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxYbEvomrozhN -Sfz0Ue0MF92nzB/YPuDSjLAlnmXUdV8/p55z5KJQD8DygOn/qj0DiZP7lt3jWJaa -X/xLtpwdJayzJs87uTzlwnRNrZDcgAbcguGhrarOVgVYpgtn8f7lQNypGp+Z8uGJ -koaag2jJaUhmlxx04PwYEfELdYkYrss/G0Uw04ffvRVQ4jneBXVF8gMR92+GtyiE -0EKDWGLaVPb15VlFkbNO8TuBZjEf+fNVzlTJ2tlnJ8R6rTxrLPmj2ffvAN6bjmvg -q1KlLKSZrwVud0wx0kSAgXxOMLjaQl8PLRz+SHwHbXjqkMokRadgsLEbKHEorpFc -i+3mTwV0HQIDAQABo1MwUTAdBgNVHQ4EFgQUtsUDkrerAfI36cp9NRpShfK72skw -HwYDVR0jBBgwFoAUtsUDkrerAfI36cp9NRpShfK72skwDwYDVR0TAQH/BAUwAwEB -/zANBgkqhkiG9w0BAQsFAAOCAQEAjiVXoW8sIbO1jIklRePYoZmj0gICiLo9eqVS -xHeWIjRaRkVnkLAtDRkWtYisI4nSja6VDtJjE6XUsUG8oLbwBvps4b7a9LY+sVXE -UkSNxC7d5Ln6sutpcj6EnF7L1Lfi8zqoQb3q7dPqiTsbi1Yu/J8K0ybEhtZ6ueLR -0msy4Byhf6dSFi9BmkFjdArtEhP7p1n0VOX2uvjMQXLhmzO0pQMVFXU1pM4WOlHx -GuxQtuoZhdtktYGGlMOZ1qtJt/y9enTSZuHx4w1M/3cBzOQEBAVkA4tTkPR858JZ -8n5d5wjzLhjn0j3ayYw1nCubKtF0Qy3j3tp/84t/NEAJKCsgGw== ------END CERTIFICATE----- diff --git a/packages/tom-server/src/application-server/__testData__/nginx/ssl/auth.example.com.key b/packages/tom-server/src/application-server/__testData__/nginx/ssl/auth.example.com.key deleted file mode 100644 index e2620fd6..00000000 --- a/packages/tom-server/src/application-server/__testData__/nginx/ssl/auth.example.com.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDFhsS+iaujOE1J -/PRR7QwX3afMH9g+4NKMsCWeZdR1Xz+nnnPkolAPwPKA6f+qPQOJk/uW3eNYlppf -/Eu2nB0lrLMmzzu5POXCdE2tkNyABtyC4aGtqs5WBVimC2fx/uVA3Kkan5ny4YmS -hpqDaMlpSGaXHHTg/BgR8Qt1iRiuyz8bRTDTh9+9FVDiOd4FdUXyAxH3b4a3KITQ -QoNYYtpU9vXlWUWRs07xO4FmMR/581XOVMna2WcnxHqtPGss+aPZ9+8A3puOa+Cr -UqUspJmvBW53TDHSRICBfE4wuNpCXw8tHP5IfAdteOqQyiRFp2CwsRsocSiukVyL -7eZPBXQdAgMBAAECggEAYmHHqKdlZ7xpMordHdkVhuWN5+uMh3TvKceqVQSfF37D -c7dGPgBiJBaUMoVaI+6Tznh4fSIzVDJe3aQKCgAjvFoSOShKtO6R+ZJ4BhT63oGM -X1wGbTt/3fR3vOw9b5jnkrDVQT9xLDoNjX+hggY1G01GW8l+pXiqfHU0oewQ8S3G -RzPmLLrDgV8eyu0WXTNohGnL/8UDT2tLYQWNdRu6Z/jujSkKeScLi9kAeJOOjKvg -pxaLzlt2nzszNj+omzPEZTOz6lBccRjVYLIAuVoplPmmPueit2cKptGJyQCx0Q1K -iQWhRTk+wNmZUuQ6x4PYgu6cxC9joS3WWA1psqluuQKBgQDb8L5ORJEp1g6K7HVN -5b9riHvX3LgQifUNd3VIytQpKYxBdrQ/kPM7QMmDoVEmwakwkrYwD04QRKDsOi4W -dUxiYJM6WZDOsDHUh/3GCBZ+j9cmcME0ZAPaVKa7eTCxCt6sLmM2tY4h9H1Wfsxj -3u8wDLYc/Bwkd7moFOYs7jtHBwKBgQDl6UZMObjsnJxEyoY8MILYxEPrBbzJQh7Z -dL7fdpGxF/DbcNwE30AQR01lG3Eh29ZIiG/R9QWhTwIYoC0BM76jY9dLN3ssBPmj -yY28R4bCBTI9ew3rEhpscEeVvW0A2ERsy79EZBbBvZ5wCYpTb/gLcc9b0uyx5Kvi -SFpDIDxeuwKBgH5+SzVAgiyJi/uiWyTeCeWSrYdMzh/U+DcyiSXAYZz65EuSNcCJ -YRqm/D7UPJQJtYDWICor4z2/+r1iCLep5rB90q8wa/QzqbUOMYn/hNBtcdQN7VBw -ZTbgkLQp0zM/iSmF1FHWwVQOBTgF3Q9jXDVKWkL5TEY9BW4B9w/IRBdpAoGAFx1t -+OnwwrE4MN5fwptp/Fs3LODlyyI/scNAEX19Rl3O1HEzXbYIXdqdWGX66NmOYLp+ -65AD4eTspAcunylRqGG4WpKYaqORabsw6dYTIVyeYXoGuzSVvYNIXzCtTeFwd7PA -ZiLd+tqSnFcJNjxSpuvpWiUJsRT5hwWZNZh/GVMCgYA31Wm0wYIlVlecJoUza3// -J0jnK6VhJpqrMgttJG5AR6C6btBeXzTJ5kYqAh8tXB6u+Puqx9aYqZGDVeRj0wo1 -I206lsmsd27RZLUgyLpJDexY1oQ8s/DBS5VWh96K4Gmw9P+TV/5E858x7MdttDHs -dvnxHWJMiidxraymkgqJNQ== ------END PRIVATE KEY----- diff --git a/packages/tom-server/src/application-server/__testData__/nginx/ssl/matrix.example.com.crt b/packages/tom-server/src/application-server/__testData__/nginx/ssl/matrix.example.com.crt deleted file mode 100644 index dfb44e9c..00000000 --- a/packages/tom-server/src/application-server/__testData__/nginx/ssl/matrix.example.com.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF+TCCA+GgAwIBAgIUH+DSOlr56iJQYZhck11PfoyJ/fAwDQYJKoZIhvcNAQEL -BQAwgYsxCzAJBgNVBAYTAkZSMRIwEAYDVQQIDAlPY2NpdGFuaWUxETAPBgNVBAcM -CFRvdWxvdXNlMREwDwYDVQQKDAhMaW5hZ29yYTEbMBkGA1UEAwwSbWF0cml4LmV4 -YW1wbGUuY29tMSUwIwYJKoZIhvcNAQkBFhZqY2FiYW5uZXNAbGluYWdvcmEuY29t -MB4XDTIzMDYwNzEzMjMxOVoXDTI3MDYwNjEzMjMxOVowgYsxCzAJBgNVBAYTAkZS -MRIwEAYDVQQIDAlPY2NpdGFuaWUxETAPBgNVBAcMCFRvdWxvdXNlMREwDwYDVQQK -DAhMaW5hZ29yYTEbMBkGA1UEAwwSbWF0cml4LmV4YW1wbGUuY29tMSUwIwYJKoZI -hvcNAQkBFhZqY2FiYW5uZXNAbGluYWdvcmEuY29tMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEAtrlLmRxV9MaivjOBFsG30DSOQqBs3uvuve3SvS1jQrj9 -dpiuV9Cj5LdTR2nFOqguwKP66/ehufIOry+gEcr+N6e215O6djWYpCqAwoHBb4u4 -4B0xaoZmIqZ+E46wW1pBNreunZ/jcjU6dCvGJ+zfBkafKrA33ft1pUCwzNjP9Gkt -iYZBB43ba8q9CUV3p9NHLHkiahKXHPra9rptTyZ8BEmbpLV0lwwt+WrRX3T8eOkC -cd0gKvHn3vggNEUWDIdSyMdMrjLSxjzXrRKa6CQ/VOuvyg7AnoCvQebWbVnRXYoE -mcxb5Ejz4pc97DzORnkky71HzyYus9I0NB/H3+qr/YnFLLEhbUBXFsw4uCNy9nU2 -8FVuVqY4kpf2fEVmxh04cen+yOVoXWXmBMTX8EU7eYuo+oNvxwHUk2clKG/cDNTa -kC3iX4nAff0PlzYDXONRNqCMqFaQbTa5VV8n4g9+2+XZRDm3EWZK2TPl6WvPBnOr -Mn7eFBVD8WPuud7ELKMS+S8p4UfSWPaSB8WN1+QK5a9hjOpmDt0f7Jsk9SCTBE75 -qeFFxngd8dx2LyEBbKOU/s/0cbkkY17A3pwKDMWnXrpcJ9wIflpYXgNZ2HD0/Ku9 -zqaEbP6WRnchAjdwQ/XX2eQWGf5zC3zW31/dCBrJJcw+/bJlF23XK2MHL4og3j8C -AwEAAaNTMFEwHQYDVR0OBBYEFEb5JWdsxBgnFa/EK2y+ghIwyOF2MB8GA1UdIwQY -MBaAFEb5JWdsxBgnFa/EK2y+ghIwyOF2MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI -hvcNAQELBQADggIBAE/Ww8V/td+ilnZ/6fqooQ2586hiSMQvkiz9JVSL/hiQBwe/ -dI1P3aU8qQ7hD+FcGID4QeE2qV1ngOt1iD7+KlErpynpw0f4FHnhC3gp7ReMAOpF -uGhUYYhjUoPeMunkK6OOlV+Ekrs83ZPDa2UoMEtW/5VtbOPwpusU6luoXleJ+qu1 -CK9gsFYG/525S0TzsrxAc0iXlRF/loBBZTmqAsFojfxpmKQPwNSqIj8ioyVZgoed -BRywdJ5cmjnq6TTTCXd+qrs9EjLP0YTEnX81WztYZTj0kmTW/ITzCv42RhPWXBXA -XGcFv1Lb7ahpT10tVylQquxpo0UJMv6Y2sBZLA7TMc5OW4h108R5GELOQKAFTf9S -ufiKwxBfZi3bofetFU1Wl7ZHhsh4I3kcpj+X+K9O+AFNKJY0rMLf+8IcRTnZ5Kq2 -YJC0BgfoR2Yd898l6wmDCUnvJZofuebBs7JlS2eZ9JmLvWgUI+5M7iSqpegFhmuW -T5N1/9GzgkCbSCcO+ZEP9w4oQeSPXTgbbBlrQqA4YcChsHj/xtUXJhivGoKK8D55 -eDnXUPGe9iAFzVmNraLJHMP1d9chuhSFIrGs5kdRIzDLGg+XzPUXa/eHOvR6UtHW -4+X/+wKhvQTV6ZCpsReLzGXYgmKjFh+mSCjv6B+Xpc1HaOw90D0HDK5QVLtR ------END CERTIFICATE----- diff --git a/packages/tom-server/src/application-server/__testData__/nginx/ssl/matrix.example.com.key b/packages/tom-server/src/application-server/__testData__/nginx/ssl/matrix.example.com.key deleted file mode 100644 index 471539eb..00000000 --- a/packages/tom-server/src/application-server/__testData__/nginx/ssl/matrix.example.com.key +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -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 -5V2jaw5UTqb2o/PIIAsHnQzluiitxQ== ------END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/build-user-db-for-error-cases-test.ts b/packages/tom-server/src/hooks/__testData__/build-user-db-for-error-cases-test.ts new file mode 100755 index 00000000..b0e23ca1 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/build-user-db-for-error-cases-test.ts @@ -0,0 +1,81 @@ +import sqlite3 from 'sqlite3' +import { type Config } from '../../types' + +let created = false + +const createQuery = + 'CREATE TABLE users (uid varchar(8), mobile varchar(12), mail varchar(32), sn varchar(32))' +const insertQueries = [ + "INSERT INTO users VALUES('dwho', '33612345678', 'dwho@company.com', 'Dwho')", + "INSERT INTO users VALUES('rtyler', '33687654321', 'rtyler@company.com', 'Rtyler')" +] + +// eslint-disable-next-line @typescript-eslint/promise-function-async +const buildUserDB = (conf: Config): Promise => { + if (created) return Promise.resolve() + return new Promise((resolve, reject) => { + const matrixDb = new sqlite3.Database(conf.matrix_database_host) + matrixDb.run( + 'CREATE TABLE users (name text, desactivated text, admin integer)', + (err) => { + if (err != null) { + reject(err) + } else { + matrixDb.run( + "INSERT INTO users VALUES('@dwho:example.com', '', 0)", + (err) => { + if (err != null) { + reject(err) + } else { + matrixDb.close((err) => { + /* istanbul ignore if */ + if (err != null) { + console.error(err) + reject(err) + } else { + const userDb = new sqlite3.Database( + conf.userdb_host as string + ) + userDb.run(createQuery, (err) => { + if (err != null) { + reject(err) + } else { + Promise.all( + insertQueries.map( + // eslint-disable-next-line @typescript-eslint/promise-function-async + (query) => + new Promise((_resolve, _reject) => { + userDb.run(query, (err) => { + err != null ? _reject(err) : _resolve(true) + }) + }) + ) + ) + .then(() => { + userDb.close((err) => { + /* istanbul ignore if */ + if (err != null) { + console.error(err) + reject(err) + } else { + created = true + resolve() + } + }) + }) + + .catch(reject) + } + }) + } + }) + } + } + ) + } + } + ) + }) +} + +export default buildUserDB diff --git a/packages/tom-server/src/hooks/__testData__/config-error-cases-test.json b/packages/tom-server/src/hooks/__testData__/config-error-cases-test.json new file mode 100755 index 00000000..f89403e3 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/config-error-cases-test.json @@ -0,0 +1,17 @@ +{ + "additional_features": true, + "base_url": "http://localhost:3003/", + "cron_service": true, + "database_engine": "sqlite", + "database_host": "./src/hooks/__testData__/twake.db", + "matrix_database_engine": "sqlite", + "matrix_database_host": "./src/hooks/__testData__/matrix.db", + "namespaces": { + "users": [{ "exclusive": false, "regex": "@.*" }] + }, + "registration_file_path": "./src/hooks/__testData__/registration-error-cases.yaml", + "server_name": "example.com", + "template_dir": "./templates", + "userdb_engine": "sqlite", + "userdb_host": "./src/hooks/__testData__/user.db" +} \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/config-integration-tests.json b/packages/tom-server/src/hooks/__testData__/config-integration-tests.json new file mode 100755 index 00000000..f6720e77 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/config-integration-tests.json @@ -0,0 +1,25 @@ +{ + "additional_features": true, + "base_url": "http://host.docker.internal:3003/", + "cron_service": true, + "database_engine": "pg", + "database_host": "localhost:5435", + "database_name": "twakedb", + "database_user": "twake", + "database_password": "twake!", + "ldap_base": "dc=example,dc=com", + "ldap_uri": "ldap://localhost:21391", + "matrix_database_engine": "pg", + "matrix_database_host": "localhost:5435", + "matrix_database_name": "synapsedb", + "matrix_database_password": "synapse!", + "matrix_database_user": "synapse", + "matrix_server": "matrix.example.com:446", + "namespaces": { + "users": [{ "exclusive": false, "regex": "@.*" }] + }, + "registration_file_path": "./src/hooks/__testData__/synapse-data/registration.yaml", + "server_name": "example.com", + "template_dir": "./templates", + "userdb_engine": "ldap" +} \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/db/init-llng-db.sh b/packages/tom-server/src/hooks/__testData__/db/init-llng-db.sh new file mode 100644 index 00000000..80d7a094 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/db/init-llng-db.sh @@ -0,0 +1,95 @@ +#!/bin/sh +set -e + +DATABASE=${PG_DATABASE:-lemonldapng} +USER=${PG_USER:-lemonldap} +PASSWORD=${PG_PASSWORD:-lemonldap} +TABLE=${PG_TABLE:-lmConfig} +PTABLE=${PG_PERSISTENT_SESSIONS_TABLE:-psessions} +STABLE=${PG_SESSIONS_TABLE:-sessions} +SAMLTABLE=${PG_SAML_TABLE:-samlsessions} +OIDCTABLE=${PG_OIDC_TABLE:-oidcsessions} +CASTABLE=${PG_CAS_TABLE:-cassessions} + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE USER $USER PASSWORD '$PASSWORD'; + CREATE DATABASE $DATABASE; +EOSQL +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE" <<-EOSQL + CREATE TABLE $TABLE ( + cfgNum integer not null primary key, + data text + ); + GRANT ALL PRIVILEGES ON TABLE $TABLE TO $USER; + + CREATE TABLE $PTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_p__session_kind ON psessions ((a_session ->> '_session_kind')); + CREATE INDEX i_p__httpSessionType ON psessions ((a_session ->> '_httpSessionType')); + CREATE INDEX i_p__session_uid ON psessions ((a_session ->> '_session_uid')); + CREATE INDEX i_p_ipAddr ON psessions ((a_session ->> 'ipAddr')); + CREATE INDEX i_p__whatToTrace ON psessions ((a_session ->> '_whatToTrace')); + GRANT ALL PRIVILEGES ON TABLE $PTABLE TO $USER; + + CREATE UNLOGGED TABLE $STABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_s__whatToTrace ON sessions ((a_session ->> '_whatToTrace')); + CREATE INDEX i_s__session_kind ON sessions ((a_session ->> '_session_kind')); + CREATE INDEX i_s__utime ON sessions ((cast (a_session ->> '_utime' as bigint))); + CREATE INDEX i_s_ipAddr ON sessions ((a_session ->> 'ipAddr')); + CREATE INDEX i_s__httpSessionType ON sessions ((a_session ->> '_httpSessionType')); + CREATE INDEX i_s_user ON sessions ((a_session ->> 'user')); + GRANT ALL PRIVILEGES ON TABLE $STABLE TO $USER; + + CREATE UNLOGGED TABLE $SAMLTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_a__session_kind ON $SAMLTABLE ((a_session ->> '_session_kind')); + CREATE INDEX i_a__utime ON $SAMLTABLE ((cast(a_session ->> '_utime' as bigint))); + CREATE INDEX i_a_ProxyID ON $SAMLTABLE ((a_session ->> 'ProxyID')); + CREATE INDEX i_a__nameID ON $SAMLTABLE ((a_session ->> '_nameID')); + CREATE INDEX i_a__assert_id ON $SAMLTABLE ((a_session ->> '_assert_id')); + CREATE INDEX i_a__art_id ON $SAMLTABLE ((a_session ->> '_art_id')); + CREATE INDEX i_a__saml_id ON $SAMLTABLE ((a_session ->> '_saml_id')); + GRANT ALL PRIVILEGES ON TABLE $SAMLTABLE TO $USER; + + CREATE UNLOGGED TABLE $OIDCTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_o__session_kind ON $OIDCTABLE ((a_session ->> '_session_kind')); + CREATE INDEX i_o__utime ON $OIDCTABLE ((cast(a_session ->> '_utime' as bigint ))); + GRANT ALL PRIVILEGES ON TABLE $OIDCTABLE TO $USER; + + CREATE UNLOGGED TABLE $CASTABLE ( + id varchar(64) not null primary key, + a_session jsonb + ); + CREATE INDEX i_c__session_kind ON $CASTABLE ((a_session ->> '_session_kind')); + CREATE INDEX i_c__utime ON $CASTABLE ((cast(a_session ->> '_utime' as bigint))); + CREATE INDEX i_c__cas_id ON $CASTABLE ((a_session ->> '_cas_id')); + CREATE INDEX i_c_pgtIou ON $CASTABLE ((a_session ->> 'pgtIou')); + GRANT ALL PRIVILEGES ON TABLE $CASTABLE TO $USER; +EOSQL + +if test -e /llng-conf/conf.json; then + SERIALIZED=`perl -MJSON -e '$/=undef; + open F, "/llng-conf/conf.json" or die $!; + $a=JSON::from_json(); + $a->{cfgNum}=1; + $a=JSON::to_json($a); + $a=~s/'\''/'\'\''/g; + $a =~ s/\\\\/\\\\\\\\/g; + print $a;'` + echo "set val '$SERIALIZED'" >&2 + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATABASE" <<-EOSQL + \\set val '$SERIALIZED' + INSERT INTO $TABLE (cfgNum, data) VALUES (1, :'val'); + \\unset val +EOSQL +fi diff --git a/packages/tom-server/src/hooks/__testData__/db/init-synapse-db.sh b/packages/tom-server/src/hooks/__testData__/db/init-synapse-db.sh new file mode 100644 index 00000000..2b7616ba --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/db/init-synapse-db.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +psql -U postgres <<-EOSQL + CREATE USER synapse PASSWORD 'synapse!'; + CREATE DATABASE synapsedb TEMPLATE='template0' LOCALE='C' ENCODING='UTF8' OWNER='synapse'; + CREATE DATABASE synapseexternaldb TEMPLATE='template0' LOCALE='C' ENCODING='UTF8' OWNER='synapse'; +EOSQL \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/db/init-twake-db.sh b/packages/tom-server/src/hooks/__testData__/db/init-twake-db.sh new file mode 100644 index 00000000..a4ced99a --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/db/init-twake-db.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +psql -U postgres <<-EOSQL + CREATE USER twake PASSWORD 'twake!'; + CREATE DATABASE twakedb TEMPLATE='template0' LOCALE='C' ENCODING='UTF8' OWNER='twake'; +EOSQL \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/docker-compose.yml b/packages/tom-server/src/hooks/__testData__/docker-compose.yml new file mode 100755 index 00000000..b0113ea7 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/docker-compose.yml @@ -0,0 +1,146 @@ +version: '3.8' + +services: + postgresql: + image: postgres:13-bullseye + container_name: postgresql-tom + volumes: + - ./synapse-data/matrix.example.com.log.config:/data/matrix.example.com.log.config + - ./db/init-synapse-db.sh:/docker-entrypoint-initdb.d/init-synapse-db.sh + - ./db/init-llng-db.sh:/docker-entrypoint-initdb.d/init-llng-db.sh + - ./db/init-twake-db.sh:/docker-entrypoint-initdb.d/init-twake-db.sh + - ./llng/lmConf-1.json:/llng-conf/conf.json + environment: + - POSTGRES_PASSWORD=synapse!! + healthcheck: + test: ['CMD-SHELL', 'pg_isready'] + interval: 10s + timeout: 5s + retries: 5 + ports: + - 5435:5432 + networks: + - hooks-test + + synapse: + image: matrixdotorg/synapse:v1.89.0 + container_name: synapse-tom + volumes: + - ./synapse-data:/data + - ./nginx/ssl/ca.pem:/etc/ssl/certs/ca.pem + - ./nginx/ssl/9da13359.0:/etc/ssl/certs/9da13359.0 + - ./nginx/ssl/matrix.example.com.crt:/etc/ssl/certs/matrix.example.com.crt + - ./nginx/ssl/matrix.example.com.key:/etc/ssl/certs/matrix.example.com.key + depends_on: + - auth + environment: + - UID=${MYUID} + - VIRTUAL_PORT=8448 + - VIRTUAL_HOST=matrix.example.com + - VIRTUAL_PROTO=https + healthcheck: + test: ["CMD", "curl", "-fSsk", "https://localhost:8448/health"] + interval: 10s + timeout: 10s + retries: 3 + extra_hosts: + - "host.docker.internal:host-gateway" + networks: + hooks-test: + aliases: + - matrix.example.com + + external-synapse: + image: matrixdotorg/synapse:v1.89.0 + container_name: external-synapse + volumes: + - ./synapse-external:/data + - ./nginx/ssl/ca.pem:/etc/ssl/certs/ca.pem + - ./nginx/ssl/9da13359.0:/etc/ssl/certs/9da13359.0 + - ./nginx/ssl/matrix.external.com.crt:/etc/ssl/certs/matrix.external.com.crt + - ./nginx/ssl/matrix.external.com.key:/etc/ssl/certs/matrix.external.com.key + depends_on: + - auth + environment: + - UID=${MYUID} + - VIRTUAL_PORT=8448 + - VIRTUAL_HOST=matrix.external.com + - VIRTUAL_PROTO=https + healthcheck: + test: ["CMD", "curl", "-fSsk", "https://localhost:8448/health"] + interval: 10s + timeout: 10s + retries: 3 + extra_hosts: + - "host.docker.internal:host-gateway" + networks: + hooks-test: + aliases: + - matrix.external.com + + auth: + image: yadd/lemonldap-ng-portal:2.16.1-bullseye + volumes: + - ./llng/lmConf-1.json:/var/lib/lemonldap-ng/conf/lmConf-1.json + - ./llng/ssl.conf:/etc/nginx/sites-enabled/0000default.conf + - ./nginx/ssl/auth.example.com.crt:/etc/nginx/ssl/auth.example.com.crt + - ./nginx/ssl/auth.example.com.key:/etc/nginx/ssl/auth.example.com.key + environment: + - PORTAL=https://auth.example.com + - VIRTUAL_HOST=auth.example.com + - PG_SERVER=postgresql + depends_on: + postgresql: + condition: service_healthy + extra_hosts: + - "host.docker.internal:host-gateway" + networks: + hooks-test: + aliases: + - auth.example.com + + annuaire: + image: ldap + build: ./ldap + ports: + - 21391:389 + networks: + - hooks-test + + nginx-proxy-hooks: + image: nginxproxy/nginx-proxy + ports: + - 446:446 + environment: + - HTTPS_PORT=446 + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - ./nginx/ssl:/etc/nginx/certs + networks: + - hooks-test + + nginx-example: + image: nginx + volumes: + - ./nginx/ssl/example.com.ssl.conf:/etc/nginx/nginx.conf + - ./nginx/ssl/example.com.crt:/etc/nginx/ssl/example.com.crt + - ./nginx/ssl/example.com.key:/etc/nginx/ssl/example.com.key + networks: + hooks-test: + aliases: + - example.com + + nginx-external: + image: nginx + volumes: + - ./nginx/ssl/external.com.ssl.conf:/etc/nginx/nginx.conf + - ./nginx/ssl/external.com.crt:/etc/nginx/ssl/external.com.crt + - ./nginx/ssl/external.com.key:/etc/nginx/ssl/external.com.key + networks: + hooks-test: + aliases: + - external.com + +networks: + hooks-test: + name: hooks-test \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/generate-self-signed-certificate.sh b/packages/tom-server/src/hooks/__testData__/generate-self-signed-certificate.sh new file mode 100755 index 00000000..0477197f --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/generate-self-signed-certificate.sh @@ -0,0 +1,50 @@ +#!/bin/sh +SCRIPT_PARENT_PATH=$( cd "$(dirname "$0")" ; pwd -P ) +ADDITIONAL_PARAMS="" +COMMON_NAME=$1 +if [ "$1" = "-ip" ]; then + COMMON_NAME=$2 + echo "subjectAltName = IP:$COMMON_NAME" > $SCRIPT_PARENT_PATH/openssl-ext.cnf + ADDITIONAL_PARAMS="-extfile $SCRIPT_PARENT_PATH/openssl-ext.cnf" +fi + +CERTIFICATE_KEY=$COMMON_NAME.key +CERTIFICATE_CRT=$COMMON_NAME.crt +CA_CRT_PATH=$SCRIPT_PARENT_PATH/nginx/ssl/ca.pem +CA_KEY_PATH=$SCRIPT_PARENT_PATH/nginx/ssl/ca.key + +cd $SCRIPT_PARENT_PATH +openssl genrsa -out $CERTIFICATE_KEY 4096 +openssl req \ + -new \ + -key $CERTIFICATE_KEY \ + -nodes \ + -out server.csr \ + -subj "/C=FR/ST=Centre/L=Paris/O=Linagora/OU=IT/CN=$COMMON_NAME" +if [ ! -f "$CA_CRT_PATH" ]; then + openssl genrsa -out ca.key 4096 + openssl req \ + -new \ + -x509 \ + -nodes \ + -days 36500 \ + -key ca.key \ + -out ca.pem \ + -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd" + mv ca.pem ca.key $SCRIPT_PARENT_PATH/nginx/ssl +fi +openssl x509 \ + -req \ + -in server.csr \ + -CAkey $CA_KEY_PATH \ + -CA $CA_CRT_PATH \ + -set_serial -01 \ + -out $CERTIFICATE_CRT \ + -days 36500 \ + -sha256 $ADDITIONAL_PARAMS +openssl verify -CAfile $CA_CRT_PATH $CERTIFICATE_CRT +mv $CERTIFICATE_KEY $CERTIFICATE_CRT $SCRIPT_PARENT_PATH/nginx/ssl +rm server.csr +if [ -f "openssl-ext.cnf" ]; then + rm openssl-ext.cnf +fi \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/ldap/Dockerfile b/packages/tom-server/src/hooks/__testData__/ldap/Dockerfile new file mode 100644 index 00000000..83adb618 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/ldap/Dockerfile @@ -0,0 +1,44 @@ +FROM debian:bullseye-slim +LABEL maintainer Linagora + +ENV DEBIAN_FRONTEND=noninteractive + +# Update system and install dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + apt-transport-https \ + ca-certificates \ + curl \ + gpg \ + wget && \ + curl https://ltb-project.org/documentation/_static/RPM-GPG-KEY-LTB-project | gpg --dearmor > /usr/share/keyrings/ltb-project-openldap-archive-keyring.gpg && \ + echo "deb [arch=amd64 signed-by=/usr/share/keyrings/ltb-project-openldap-archive-keyring.gpg] https://ltb-project.org/debian/openldap25/bullseye bullseye main" > /etc/apt/sources.list.d/ltb-project.list && \ + apt-get update && \ + apt-get install -y openldap-ltb openldap-ltb-contrib-overlays openldap-ltb-mdb-utils ldap-utils && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Copy configuration files +COPY ./ldif/config-20230322180123.ldif /var/backups/openldap/ +COPY ./ldif/base_ldap_users.ldif /tmp + +# Configure LDAP +RUN rm -rf /usr/local/openldap/var/lib/ldap /usr/local/openldap/etc/openldap/slapd.d && \ + mkdir -p /usr/local/openldap/var/lib/ldap && \ + chown -R ldap:ldap /usr/local/openldap/var/lib/ldap && \ + mkdir -p /usr/local/openldap/etc/openldap/slapd.d && \ + chown -R ldap:ldap /usr/local/openldap/etc/openldap/slapd.d && \ + usr/local/openldap/sbin/slapd-cli restoreconfig -b /var/backups/openldap/config-20230322180123.ldif && \ + mkdir -p /usr/local/openldap/var/lib/ldap/data && \ + chown -R ldap:ldap /usr/local/openldap/var/lib/ldap/data && \ + /usr/local/openldap/sbin/slapadd -F /usr/local/openldap/etc/openldap/slapd.d/ -b "dc=example,dc=com" -l /tmp/base_ldap_users.ldif + +# Expose LDAP port +EXPOSE 389 + +# Define LDAP data volume +VOLUME /usr/local/openldap/var/openldap-data + +# Set the entrypoint script +CMD ["/usr/local/openldap/libexec/slapd", "-h", "ldap://*", "-u", "ldap", "-g", "ldap", "-d", "256"] + diff --git a/packages/tom-server/src/hooks/__testData__/ldap/ldif/base_ldap_users.ldif b/packages/tom-server/src/hooks/__testData__/ldap/ldif/base_ldap_users.ldif new file mode 100644 index 00000000..eb4e7f3f --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/ldap/ldif/base_ldap_users.ldif @@ -0,0 +1,174 @@ +dn: dc=example,dc=com +objectClass: top +objectClass: organization +objectClass: dcObject +dc: example +o: Example + +dn: ou=users,dc=example,dc=com +objectClass: top +objectClass: organizationalUnit +ou: users + +dn: uid=dwho,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: dwho +cn: Dr Who +sn: Dwho +mail: dwho@example.com +mobile: 33671298765 +userPassword: dwho + +dn: uid=rtyler,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: rtyler +cn: Rose Tyler +sn: Rtyler +mail: rtyler@example.com +mobile: 33671298767 +userPassword: rtyler + +dn: uid=msmith,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: msmith +cn: Mr Smith +sn: Msmith +mail: msmith@example.com +userPassword: msmith + +dn: uid=okenobi,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: okenobi +cn: Obi-Wan Kenobi +sn: Okenobi +mail: okenobi@example.com +userPassword: okenobi + +dn: uid=qjinn,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: qjinn +cn: Qui-Gon Jinn +sn: Qgonjinn +mail: qjinn@example.com +userPassword: qjinn + +dn: uid=chewbacca,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: chewbacca +cn: Chewbacca +sn: Chewbacca +mail: chewbacca@example.com +userPassword: chewbacca + +dn: uid=lorgana,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: lorgana +cn: Leia Organa +sn: Lorgana +mail: lorgana@example.com +userPassword: lorgana + +dn: uid=pamidala,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: pamidala +cn: Padme Amidala +sn: Pamidala +mail: pamidala@example.com +userPassword: pamidala + +dn: uid=cdooku,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: cdooku +cn: Comte Dooku +sn: Cdooku +mail: cdooku@example.com +userPassword: cdooku + +dn: uid=kren,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: kren +cn: Kylo Ren +sn: Kren +mail: kren@example.com +userPassword: kren + +dn: uid=dmaul,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: dmaul +cn: Dark Maul +sn: Dmaul +mail: dmaul@example.com +userPassword: dmaul + +dn: uid=askywalker,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: askywalker +cn: Anakin Skywalker +sn: Askywalker +mail: askywalker@example.com +userPassword: askywalker + +dn: uid=jbinks,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: jbinks +cn: Jar Jar Binks +sn: Jbinks +mail: jbinks@example.com +userPassword: jbinks + +dn: uid=bfett,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: bfett +cn: Boba Fett +sn: Bfett +mail: bfett@example.com +userPassword: bfett + +dn: uid=jfett,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: jfett +cn: Jango Ffett +sn: Jfett +mail: jfett@example.com +userPassword: jfett + +dn: uid=lskywalker,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: lskywalker +cn: Luke Skywalker +sn: Lskywalker +mail: lskywalker@example.com +userPassword: lskywalker + +dn: uid=myoda,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: myoda +cn: Master Yoda +sn: Myoda +mail: myoda@example.com +userPassword: myoda + +dn: uid=hsolo,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: hsolo +cn: Han Solo +sn: Hsolo +mail: hsolo@example.com +userPassword: hsolo + +dn: uid=r2d2,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: r2d2 +cn: R2D2 +sn: R2D2 +mail: r2d2@example.com +userPassword: r2d2 + +dn: uid=c3po,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +uid: c3po +cn: C3PO +sn: C3po +mail: c3po@example.com +userPassword: c3po + diff --git a/packages/tom-server/src/hooks/__testData__/ldap/ldif/config-20230322180123.ldif b/packages/tom-server/src/hooks/__testData__/ldap/ldif/config-20230322180123.ldif new file mode 100644 index 00000000..5c566113 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/ldap/ldif/config-20230322180123.ldif @@ -0,0 +1,260 @@ +dn: cn=config +objectClass: olcGlobal +cn: config +olcPidFile: /usr/local/openldap/var/run/slapd.pid + +dn: cn=schema,cn=config +objectClass: olcSchemaConfig +cn: schema +structuralObjectClass: olcSchemaConfig +entryUUID: 713c4cc8-df8a-103c-9770-230a0a7123cd +creatorsName: cn=config +createTimestamp: 20221013213337Z +entryCSN: 20221013213337.589745Z#000000#000#000000 +modifiersName: cn=config +modifyTimestamp: 20221013213337Z + +dn: cn={0}core,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: {0}core +olcAttributeTypes: {0}( 2.5.4.2 NAME 'knowledgeInformation' DESC 'RFC2256: knowledge information' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} ) +olcAttributeTypes: {1}( 2.5.4.4 NAME ( 'sn' 'surname' ) DESC 'RFC2256: last (family) name(s) for which the entity is known by' SUP name ) +olcAttributeTypes: {2}( 2.5.4.5 NAME 'serialNumber' DESC 'RFC2256: serial number of the entity' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} ) +olcAttributeTypes: {3}( 2.5.4.6 NAME ( 'c' 'countryName' ) DESC 'RFC4519: two-letter ISO-3166 country code' SUP name SYNTAX 1.3.6.1.4.1.1466.115.121.1.11 SINGLE-VALUE ) +olcAttributeTypes: {4}( 2.5.4.7 NAME ( 'l' 'localityName' ) DESC 'RFC2256: locality which this object resides in' SUP name ) +olcAttributeTypes: {5}( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' ) DESC 'RFC2256: state or province which this object resides in' SUP name ) +olcAttributeTypes: {6}( 2.5.4.9 NAME ( 'street' 'streetAddress' ) DESC 'RFC2256: street address of this object' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) +olcAttributeTypes: {7}( 2.5.4.10 NAME ( 'o' 'organizationName' ) DESC 'RFC2256: organization this object belongs to' SUP name ) +olcAttributeTypes: {8}( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) DESC 'RFC2256: organizational unit this object belongs to' SUP name ) +olcAttributeTypes: {9}( 2.5.4.12 NAME 'title' DESC 'RFC2256: title associated with the entity' SUP name ) +olcAttributeTypes: {10}( 2.5.4.14 NAME 'searchGuide' DESC 'RFC2256: search guide, deprecated by enhancedSearchGuide' SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 ) +olcAttributeTypes: {11}( 2.5.4.15 NAME 'businessCategory' DESC 'RFC2256: business category' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) +olcAttributeTypes: {12}( 2.5.4.16 NAME 'postalAddress' DESC 'RFC2256: postal address' EQUALITY caseIgnoreListMatch SUBSTR caseIgnoreListSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) +olcAttributeTypes: {13}( 2.5.4.17 NAME 'postalCode' DESC 'RFC2256: postal code' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} ) +olcAttributeTypes: {14}( 2.5.4.18 NAME 'postOfficeBox' DESC 'RFC2256: Post Office Box' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} ) +olcAttributeTypes: {15}( 2.5.4.19 NAME 'physicalDeliveryOfficeName' DESC 'RFC2256: Physical Delivery Office Name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) +olcAttributeTypes: {16}( 2.5.4.20 NAME 'telephoneNumber' DESC 'RFC2256: Telephone Number' EQUALITY telephoneNumberMatch SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} ) +olcAttributeTypes: {17}( 2.5.4.21 NAME 'telexNumber' DESC 'RFC2256: Telex Number' SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 ) +olcAttributeTypes: {18}( 2.5.4.22 NAME 'teletexTerminalIdentifier' DESC 'RFC2256: Teletex Terminal Identifier' SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 ) +olcAttributeTypes: {19}( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' ) DESC 'RFC2256: Facsimile (Fax) Telephone Number' SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 ) +olcAttributeTypes: {20}( 2.5.4.24 NAME 'x121Address' DESC 'RFC2256: X.121 Address' EQUALITY numericStringMatch SUBSTR numericStringSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} ) +olcAttributeTypes: {21}( 2.5.4.25 NAME 'internationaliSDNNumber' DESC 'RFC2256: international ISDN number' EQUALITY numericStringMatch SUBSTR numericStringSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} ) +olcAttributeTypes: {22}( 2.5.4.26 NAME 'registeredAddress' DESC 'RFC2256: registered postal address' SUP postalAddress SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) +olcAttributeTypes: {23}( 2.5.4.27 NAME 'destinationIndicator' DESC 'RFC2256: destination indicator' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} ) +olcAttributeTypes: {24}( 2.5.4.28 NAME 'preferredDeliveryMethod' DESC 'RFC2256: preferred delivery method' SYNTAX 1.3.6.1.4.1.1466.115.121.1.14 SINGLE-VALUE ) +olcAttributeTypes: {25}( 2.5.4.29 NAME 'presentationAddress' DESC 'RFC2256: presentation address' EQUALITY presentationAddressMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 SINGLE-VALUE ) +olcAttributeTypes: {26}( 2.5.4.30 NAME 'supportedApplicationContext' DESC 'RFC2256: supported application context' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 ) +olcAttributeTypes: {27}( 2.5.4.31 NAME 'member' DESC 'RFC2256: member of a group' SUP distinguishedName ) +olcAttributeTypes: {28}( 2.5.4.32 NAME 'owner' DESC 'RFC2256: owner (of the object)' SUP distinguishedName ) +olcAttributeTypes: {29}( 2.5.4.33 NAME 'roleOccupant' DESC 'RFC2256: occupant of role' SUP distinguishedName ) +olcAttributeTypes: {30}( 2.5.4.36 NAME 'userCertificate' DESC 'RFC2256: X.509 user certificate, use ;binary' EQUALITY certificateExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 ) +olcAttributeTypes: {31}( 2.5.4.37 NAME 'cACertificate' DESC 'RFC2256: X.509 CA certificate, use ;binary' EQUALITY certificateExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 ) +olcAttributeTypes: {32}( 2.5.4.38 NAME 'authorityRevocationList' DESC 'RFC2256: X.509 authority revocation list, use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 ) +olcAttributeTypes: {33}( 2.5.4.39 NAME 'certificateRevocationList' DESC 'RFC2256: X.509 certificate revocation list, use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 ) +olcAttributeTypes: {34}( 2.5.4.40 NAME 'crossCertificatePair' DESC 'RFC2256: X.509 cross certificate pair, use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 ) +olcAttributeTypes: {35}( 2.5.4.42 NAME ( 'givenName' 'gn' ) DESC 'RFC2256: first name(s) for which the entity is known by' SUP name ) +olcAttributeTypes: {36}( 2.5.4.43 NAME 'initials' DESC 'RFC2256: initials of some or all of names, but not the surname(s).' SUP name ) +olcAttributeTypes: {37}( 2.5.4.44 NAME 'generationQualifier' DESC 'RFC2256: name qualifier indicating a generation' SUP name ) +olcAttributeTypes: {38}( 2.5.4.45 NAME 'x500UniqueIdentifier' DESC 'RFC2256: X.500 unique identifier' EQUALITY bitStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 ) +olcAttributeTypes: {39}( 2.5.4.46 NAME 'dnQualifier' DESC 'RFC2256: DN qualifier' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 ) +olcAttributeTypes: {40}( 2.5.4.47 NAME 'enhancedSearchGuide' DESC 'RFC2256: enhanced search guide' SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 ) +olcAttributeTypes: {41}( 2.5.4.48 NAME 'protocolInformation' DESC 'RFC2256: protocol information' EQUALITY protocolInformationMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 ) +olcAttributeTypes: {42}( 2.5.4.50 NAME 'uniqueMember' DESC 'RFC2256: unique member of a group' EQUALITY uniqueMemberMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 ) +olcAttributeTypes: {43}( 2.5.4.51 NAME 'houseIdentifier' DESC 'RFC2256: house identifier' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} ) +olcAttributeTypes: {44}( 2.5.4.52 NAME 'supportedAlgorithms' DESC 'RFC2256: supported algorithms' SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 ) +olcAttributeTypes: {45}( 2.5.4.53 NAME 'deltaRevocationList' DESC 'RFC2256: delta revocation list; use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 ) +olcAttributeTypes: {46}( 2.5.4.54 NAME 'dmdName' DESC 'RFC2256: name of DMD' SUP name ) +olcAttributeTypes: {47}( 2.5.4.65 NAME 'pseudonym' DESC 'X.520(4th): pseudonym for the object' SUP name ) +olcAttributeTypes: {48}( 0.9.2342.19200300.100.1.3 NAME ( 'mail' 'rfc822Mailbox' ) DESC 'RFC1274: RFC822 Mailbox' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) +olcAttributeTypes: {49}( 0.9.2342.19200300.100.1.25 NAME ( 'dc' 'domainComponent' ) DESC 'RFC1274/2247: domain component' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {50}( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain' DESC 'RFC1274: domain associated with object' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {51}( 1.2.840.113549.1.9.1 NAME ( 'email' 'emailAddress' 'pkcs9email' ) DESC 'RFC3280: legacy attribute for email addresses in DNs' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) +olcObjectClasses: {0}( 2.5.6.2 NAME 'country' DESC 'RFC2256: a country' SUP top STRUCTURAL MUST c MAY ( searchGuide $ description ) ) +olcObjectClasses: {1}( 2.5.6.3 NAME 'locality' DESC 'RFC2256: a locality' SUP top STRUCTURAL MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) ) +olcObjectClasses: {2}( 2.5.6.4 NAME 'organization' DESC 'RFC2256: an organization' SUP top STRUCTURAL MUST o MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) ) +olcObjectClasses: {3}( 2.5.6.5 NAME 'organizationalUnit' DESC 'RFC2256: an organizational unit' SUP top STRUCTURAL MUST ou MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) ) +olcObjectClasses: {4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) ) +olcObjectClasses: {5}( 2.5.6.7 NAME 'organizationalPerson' DESC 'RFC2256: an organizational person' SUP person STRUCTURAL MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) ) +olcObjectClasses: {6}( 2.5.6.8 NAME 'organizationalRole' DESC 'RFC2256: an organizational role' SUP top STRUCTURAL MUST cn MAY ( x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l $ description ) ) +olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) +olcObjectClasses: {8}( 2.5.6.10 NAME 'residentialPerson' DESC 'RFC2256: an residential person' SUP person STRUCTURAL MUST l MAY ( businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ preferredDeliveryMethod $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l ) ) +olcObjectClasses: {9}( 2.5.6.11 NAME 'applicationProcess' DESC 'RFC2256: an application process' SUP top STRUCTURAL MUST cn MAY ( seeAlso $ ou $ l $ description ) ) +olcObjectClasses: {10}( 2.5.6.12 NAME 'applicationEntity' DESC 'RFC2256: an application entity' SUP top STRUCTURAL MUST ( presentationAddress $ cn ) MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $ description ) ) +olcObjectClasses: {11}( 2.5.6.13 NAME 'dSA' DESC 'RFC2256: a directory system agent (a server)' SUP applicationEntity STRUCTURAL MAY knowledgeInformation ) +olcObjectClasses: {12}( 2.5.6.14 NAME 'device' DESC 'RFC2256: a device' SUP top STRUCTURAL MUST cn MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) ) +olcObjectClasses: {13}( 2.5.6.15 NAME 'strongAuthenticationUser' DESC 'RFC2256: a strong authentication user' SUP top AUXILIARY MUST userCertificate ) +olcObjectClasses: {14}( 2.5.6.16 NAME 'certificationAuthority' DESC 'RFC2256: a certificate authority' SUP top AUXILIARY MUST ( authorityRevocationList $ certificateRevocationList $ cACertificate ) MAY crossCertificatePair ) +olcObjectClasses: {15}( 2.5.6.17 NAME 'groupOfUniqueNames' DESC 'RFC2256: a group of unique names (DN and Unique Identifier)' SUP top STRUCTURAL MUST ( uniqueMember $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) ) +olcObjectClasses: {16}( 2.5.6.18 NAME 'userSecurityInformation' DESC 'RFC2256: a user security information' SUP top AUXILIARY MAY ( supportedAlgorithms ) ) +olcObjectClasses: {17}( 2.5.6.16.2 NAME 'certificationAuthority-V2' SUP certificationAuthority AUXILIARY MAY ( deltaRevocationList ) ) +olcObjectClasses: {18}( 2.5.6.19 NAME 'cRLDistributionPoint' SUP top STRUCTURAL MUST ( cn ) MAY ( certificateRevocationList $ authorityRevocationList $ deltaRevocationList ) ) +olcObjectClasses: {19}( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL MUST ( dmdName ) MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) ) +olcObjectClasses: {20}( 2.5.6.21 NAME 'pkiUser' DESC 'RFC2587: a PKI user' SUP top AUXILIARY MAY userCertificate ) +olcObjectClasses: {21}( 2.5.6.22 NAME 'pkiCA' DESC 'RFC2587: PKI certificate authority' SUP top AUXILIARY MAY ( authorityRevocationList $ certificateRevocationList $ cACertificate $ crossCertificatePair ) ) +olcObjectClasses: {22}( 2.5.6.23 NAME 'deltaCRL' DESC 'RFC4523: X.509 delta CRL' SUP top AUXILIARY MAY deltaRevocationList ) +olcObjectClasses: {23}( 1.3.6.1.4.1.250.3.15 NAME 'labeledURIObject' DESC 'RFC2079: object that contains the URI attribute type' MAY ( labeledURI ) SUP top AUXILIARY ) +olcObjectClasses: {24}( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject' DESC 'RFC1274: simple security object' SUP top AUXILIARY MUST userPassword ) +olcObjectClasses: {25}( 1.3.6.1.4.1.1466.344 NAME 'dcObject' DESC 'RFC2247: domain component object' SUP top AUXILIARY MUST dc ) +olcObjectClasses: {26}( 1.3.6.1.1.3.1 NAME 'uidObject' DESC 'RFC2377: uid object' SUP top AUXILIARY MUST uid ) +structuralObjectClass: olcSchemaConfig +entryUUID: 713c5a24-df8a-103c-9771-230a0a7123cd +creatorsName: cn=config +createTimestamp: 20221013213337Z +entryCSN: 20221013213337.590086Z#000000#000#000000 +modifiersName: cn=config +modifyTimestamp: 20221013213337Z + +dn: cn={1}cosine,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: {1}cosine +olcAttributeTypes: {0}( 0.9.2342.19200300.100.1.2 NAME 'textEncodedORAddress' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {1}( 0.9.2342.19200300.100.1.4 NAME 'info' DESC 'RFC1274: general information' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{2048} ) +olcAttributeTypes: {2}( 0.9.2342.19200300.100.1.5 NAME ( 'drink' 'favouriteDrink' ) DESC 'RFC1274: favorite drink' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {3}( 0.9.2342.19200300.100.1.6 NAME 'roomNumber' DESC 'RFC1274: room number' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {4}( 0.9.2342.19200300.100.1.7 NAME 'photo' DESC 'RFC1274: photo (G3 fax)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.23{25000} ) +olcAttributeTypes: {5}( 0.9.2342.19200300.100.1.8 NAME 'userClass' DESC 'RFC1274: category of user' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {6}( 0.9.2342.19200300.100.1.9 NAME 'host' DESC 'RFC1274: host computer' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {7}( 0.9.2342.19200300.100.1.10 NAME 'manager' DESC 'RFC1274: DN of manager' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {8}( 0.9.2342.19200300.100.1.11 NAME 'documentIdentifier' DESC 'RFC1274: unique identifier of document' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {9}( 0.9.2342.19200300.100.1.12 NAME 'documentTitle' DESC 'RFC1274: title of document' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {10}( 0.9.2342.19200300.100.1.13 NAME 'documentVersion' DESC 'RFC1274: version of document' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {11}( 0.9.2342.19200300.100.1.14 NAME 'documentAuthor' DESC 'RFC1274: DN of author of document' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {12}( 0.9.2342.19200300.100.1.15 NAME 'documentLocation' DESC 'RFC1274: location of document original' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {13}( 0.9.2342.19200300.100.1.20 NAME ( 'homePhone' 'homeTelephoneNumber' ) DESC 'RFC1274: home telephone number' EQUALITY telephoneNumberMatch SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) +olcAttributeTypes: {14}( 0.9.2342.19200300.100.1.21 NAME 'secretary' DESC 'RFC1274: DN of secretary' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {15}( 0.9.2342.19200300.100.1.22 NAME 'otherMailbox' SYNTAX 1.3.6.1.4.1.1466.115.121.1.39 ) +olcAttributeTypes: {16}( 0.9.2342.19200300.100.1.26 NAME 'aRecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {17}( 0.9.2342.19200300.100.1.27 NAME 'mDRecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {18}( 0.9.2342.19200300.100.1.28 NAME 'mXRecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {19}( 0.9.2342.19200300.100.1.29 NAME 'nSRecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {20}( 0.9.2342.19200300.100.1.30 NAME 'sOARecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {21}( 0.9.2342.19200300.100.1.31 NAME 'cNAMERecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {22}( 0.9.2342.19200300.100.1.38 NAME 'associatedName' DESC 'RFC1274: DN of entry associated with domain' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {23}( 0.9.2342.19200300.100.1.39 NAME 'homePostalAddress' DESC 'RFC1274: home postal address' EQUALITY caseIgnoreListMatch SUBSTR caseIgnoreListSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) +olcAttributeTypes: {24}( 0.9.2342.19200300.100.1.40 NAME 'personalTitle' DESC 'RFC1274: personal title' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {25}( 0.9.2342.19200300.100.1.41 NAME ( 'mobile' 'mobileTelephoneNumber' ) DESC 'RFC1274: mobile telephone number' EQUALITY telephoneNumberMatch SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) +olcAttributeTypes: {26}( 0.9.2342.19200300.100.1.42 NAME ( 'pager' 'pagerTelephoneNumber' ) DESC 'RFC1274: pager telephone number' EQUALITY telephoneNumberMatch SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 ) +olcAttributeTypes: {27}( 0.9.2342.19200300.100.1.43 NAME ( 'co' 'friendlyCountryName' ) DESC 'RFC1274: friendly country name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {28}( 0.9.2342.19200300.100.1.44 NAME 'uniqueIdentifier' DESC 'RFC1274: unique identifer' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {29}( 0.9.2342.19200300.100.1.45 NAME 'organizationalStatus' DESC 'RFC1274: organizational status' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {30}( 0.9.2342.19200300.100.1.46 NAME 'janetMailbox' DESC 'RFC1274: Janet mailbox' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) +olcAttributeTypes: {31}( 0.9.2342.19200300.100.1.47 NAME 'mailPreferenceOption' DESC 'RFC1274: mail preference option' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) +olcAttributeTypes: {32}( 0.9.2342.19200300.100.1.48 NAME 'buildingName' DESC 'RFC1274: name of building' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) +olcAttributeTypes: {33}( 0.9.2342.19200300.100.1.49 NAME 'dSAQuality' DESC 'RFC1274: DSA Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.19 SINGLE-VALUE ) +olcAttributeTypes: {34}( 0.9.2342.19200300.100.1.50 NAME 'singleLevelQuality' DESC 'RFC1274: Single Level Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SINGLE-VALUE ) +olcAttributeTypes: {35}( 0.9.2342.19200300.100.1.51 NAME 'subtreeMinimumQuality' DESC 'RFC1274: Subtree Minimum Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SINGLE-VALUE ) +olcAttributeTypes: {36}( 0.9.2342.19200300.100.1.52 NAME 'subtreeMaximumQuality' DESC 'RFC1274: Subtree Maximum Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SINGLE-VALUE ) +olcAttributeTypes: {37}( 0.9.2342.19200300.100.1.53 NAME 'personalSignature' DESC 'RFC1274: Personal Signature (G3 fax)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.23 ) +olcAttributeTypes: {38}( 0.9.2342.19200300.100.1.54 NAME 'dITRedirect' DESC 'RFC1274: DIT Redirect' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {39}( 0.9.2342.19200300.100.1.55 NAME 'audio' DESC 'RFC1274: audio (u-law)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.4{25000} ) +olcAttributeTypes: {40}( 0.9.2342.19200300.100.1.56 NAME 'documentPublisher' DESC 'RFC1274: publisher of document' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcObjectClasses: {0}( 0.9.2342.19200300.100.4.4 NAME ( 'pilotPerson' 'newPilotPerson' ) SUP person STRUCTURAL MAY ( userid $ textEncodedORAddress $ rfc822Mailbox $ favouriteDrink $ roomNumber $ userClass $ homeTelephoneNumber $ homePostalAddress $ secretary $ personalTitle $ preferredDeliveryMethod $ businessCategory $ janetMailbox $ otherMailbox $ mobileTelephoneNumber $ pagerTelephoneNumber $ organizationalStatus $ mailPreferenceOption $ personalSignature ) ) +olcObjectClasses: {1}( 0.9.2342.19200300.100.4.5 NAME 'account' SUP top STRUCTURAL MUST userid MAY ( description $ seeAlso $ localityName $ organizationName $ organizationalUnitName $ host ) ) +olcObjectClasses: {2}( 0.9.2342.19200300.100.4.6 NAME 'document' SUP top STRUCTURAL MUST documentIdentifier MAY ( commonName $ description $ seeAlso $ localityName $ organizationName $ organizationalUnitName $ documentTitle $ documentVersion $ documentAuthor $ documentLocation $ documentPublisher ) ) +olcObjectClasses: {3}( 0.9.2342.19200300.100.4.7 NAME 'room' SUP top STRUCTURAL MUST commonName MAY ( roomNumber $ description $ seeAlso $ telephoneNumber ) ) +olcObjectClasses: {4}( 0.9.2342.19200300.100.4.9 NAME 'documentSeries' SUP top STRUCTURAL MUST commonName MAY ( description $ seeAlso $ telephonenumber $ localityName $ organizationName $ organizationalUnitName ) ) +olcObjectClasses: {5}( 0.9.2342.19200300.100.4.13 NAME 'domain' SUP top STRUCTURAL MUST domainComponent MAY ( associatedName $ organizationName $ description $ businessCategory $ seeAlso $ searchGuide $ userPassword $ localityName $ stateOrProvinceName $ streetAddress $ physicalDeliveryOfficeName $ postalAddress $ postalCode $ postOfficeBox $ streetAddress $ facsimileTelephoneNumber $ internationalISDNNumber $ telephoneNumber $ teletexTerminalIdentifier $ telexNumber $ preferredDeliveryMethod $ destinationIndicator $ registeredAddress $ x121Address ) ) +olcObjectClasses: {6}( 0.9.2342.19200300.100.4.14 NAME 'RFC822localPart' SUP domain STRUCTURAL MAY ( commonName $ surname $ description $ seeAlso $ telephoneNumber $ physicalDeliveryOfficeName $ postalAddress $ postalCode $ postOfficeBox $ streetAddress $ facsimileTelephoneNumber $ internationalISDNNumber $ telephoneNumber $ teletexTerminalIdentifier $ telexNumber $ preferredDeliveryMethod $ destinationIndicator $ registeredAddress $ x121Address ) ) +olcObjectClasses: {7}( 0.9.2342.19200300.100.4.15 NAME 'dNSDomain' SUP domain STRUCTURAL MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ SOARecord $ CNAMERecord ) ) +olcObjectClasses: {8}( 0.9.2342.19200300.100.4.17 NAME 'domainRelatedObject' DESC 'RFC1274: an object related to an domain' SUP top AUXILIARY MUST associatedDomain ) +olcObjectClasses: {9}( 0.9.2342.19200300.100.4.18 NAME 'friendlyCountry' SUP country STRUCTURAL MUST friendlyCountryName ) +olcObjectClasses: {10}( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization' SUP ( organization $ organizationalUnit ) STRUCTURAL MAY buildingName ) +olcObjectClasses: {11}( 0.9.2342.19200300.100.4.21 NAME 'pilotDSA' SUP dsa STRUCTURAL MAY dSAQuality ) +olcObjectClasses: {12}( 0.9.2342.19200300.100.4.22 NAME 'qualityLabelledData' SUP top AUXILIARY MUST dsaQuality MAY ( subtreeMinimumQuality $ subtreeMaximumQuality ) ) +structuralObjectClass: olcSchemaConfig +entryUUID: 713ca97a-df8a-103c-9772-230a0a7123cd +creatorsName: cn=config +createTimestamp: 20221013213337Z +entryCSN: 20221013213337.592117Z#000000#000#000000 +modifiersName: cn=config +modifyTimestamp: 20221013213337Z + +dn: cn={2}inetorgperson,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: {2}inetorgperson +olcAttributeTypes: {0}( 2.16.840.1.113730.3.1.1 NAME 'carLicense' DESC 'RFC2798: vehicle license or registration plate' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {1}( 2.16.840.1.113730.3.1.2 NAME 'departmentNumber' DESC 'RFC2798: identifies a department within an organization' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {2}( 2.16.840.1.113730.3.1.241 NAME 'displayName' DESC 'RFC2798: preferred name to be used when displaying entries' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: {3}( 2.16.840.1.113730.3.1.3 NAME 'employeeNumber' DESC 'RFC2798: numerically identifies an employee within an organization' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: {4}( 2.16.840.1.113730.3.1.4 NAME 'employeeType' DESC 'RFC2798: type of employment for a person' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: {5}( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' DESC 'RFC2798: a JPEG image' SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 ) +olcAttributeTypes: {6}( 2.16.840.1.113730.3.1.39 NAME 'preferredLanguage' DESC 'RFC2798: preferred written or spoken language for a person' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: {7}( 2.16.840.1.113730.3.1.40 NAME 'userSMIMECertificate' DESC 'RFC2798: PKCS#7 SignedData used to support S/MIME' SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 ) +olcAttributeTypes: {8}( 2.16.840.1.113730.3.1.216 NAME 'userPKCS12' DESC 'RFC2798: personal identity information, a PKCS #12 PFX' SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 ) +olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 ) ) +structuralObjectClass: olcSchemaConfig +entryUUID: 713cc81a-df8a-103c-9773-230a0a7123cd +creatorsName: cn=config +createTimestamp: 20221013213337Z +entryCSN: 20221013213337.592900Z#000000#000#000000 +modifiersName: cn=config +modifyTimestamp: 20221013213337Z + +dn: cn={3}nis,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: {3}nis +olcAttributeTypes: {0}( 1.3.6.1.1.1.1.2 NAME 'gecos' DESC 'The GECOS field; the common name' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {1}( 1.3.6.1.1.1.1.3 NAME 'homeDirectory' DESC 'The absolute path to the home directory' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {2}( 1.3.6.1.1.1.1.4 NAME 'loginShell' DESC 'The path to the login shell' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {3}( 1.3.6.1.1.1.1.5 NAME 'shadowLastChange' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {4}( 1.3.6.1.1.1.1.6 NAME 'shadowMin' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {5}( 1.3.6.1.1.1.1.7 NAME 'shadowMax' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {6}( 1.3.6.1.1.1.1.8 NAME 'shadowWarning' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {7}( 1.3.6.1.1.1.1.9 NAME 'shadowInactive' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {8}( 1.3.6.1.1.1.1.10 NAME 'shadowExpire' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {9}( 1.3.6.1.1.1.1.11 NAME 'shadowFlag' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {10}( 1.3.6.1.1.1.1.12 NAME 'memberUid' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {11}( 1.3.6.1.1.1.1.13 NAME 'memberNisNetgroup' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgroup triple' SYNTAX 1.3.6.1.1.1.0.0 ) +olcAttributeTypes: {13}( 1.3.6.1.1.1.1.15 NAME 'ipServicePort' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {14}( 1.3.6.1.1.1.1.16 NAME 'ipServiceProtocol' SUP name ) +olcAttributeTypes: {15}( 1.3.6.1.1.1.1.17 NAME 'ipProtocolNumber' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {16}( 1.3.6.1.1.1.1.18 NAME 'oncRpcNumber' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {17}( 1.3.6.1.1.1.1.19 NAME 'ipHostNumber' DESC 'IP address' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) +olcAttributeTypes: {18}( 1.3.6.1.1.1.1.20 NAME 'ipNetworkNumber' DESC 'IP network' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} SINGLE-VALUE ) +olcAttributeTypes: {19}( 1.3.6.1.1.1.1.21 NAME 'ipNetmaskNumber' DESC 'IP netmask' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} SINGLE-VALUE ) +olcAttributeTypes: {20}( 1.3.6.1.1.1.1.22 NAME 'macAddress' DESC 'MAC address' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) +olcAttributeTypes: {21}( 1.3.6.1.1.1.1.23 NAME 'bootParameter' DESC 'rpc.bootparamd parameter' SYNTAX 1.3.6.1.1.1.0.1 ) +olcAttributeTypes: {22}( 1.3.6.1.1.1.1.24 NAME 'bootFile' DESC 'Boot image name' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {23}( 1.3.6.1.1.1.1.26 NAME 'nisMapName' SUP name ) +olcAttributeTypes: {24}( 1.3.6.1.1.1.1.27 NAME 'nisMapEntry' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{1024} SINGLE-VALUE ) +olcObjectClasses: {0}( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) ) +olcObjectClasses: {1}( 1.3.6.1.1.1.2.1 NAME 'shadowAccount' DESC 'Additional attributes for shadow passwords' SUP top AUXILIARY MUST uid MAY ( userPassword $ shadowLastChange $ shadowMin $ shadowMax $ shadowWarning $ shadowInactive $ shadowExpire $ shadowFlag $ description ) ) +olcObjectClasses: {2}( 1.3.6.1.1.1.2.2 NAME 'posixGroup' DESC 'Abstraction of a group of accounts' SUP top STRUCTURAL MUST ( cn $ gidNumber ) MAY ( userPassword $ memberUid $ description ) ) +olcObjectClasses: {3}( 1.3.6.1.1.1.2.3 NAME 'ipService' DESC 'Abstraction an Internet Protocol service' SUP top STRUCTURAL MUST ( cn $ ipServicePort $ ipServiceProtocol ) MAY description ) +olcObjectClasses: {4}( 1.3.6.1.1.1.2.4 NAME 'ipProtocol' DESC 'Abstraction of an IP protocol' SUP top STRUCTURAL MUST ( cn $ ipProtocolNumber $ description ) MAY description ) +olcObjectClasses: {5}( 1.3.6.1.1.1.2.5 NAME 'oncRpc' DESC 'Abstraction of an ONC/RPC binding' SUP top STRUCTURAL MUST ( cn $ oncRpcNumber $ description ) MAY description ) +olcObjectClasses: {6}( 1.3.6.1.1.1.2.6 NAME 'ipHost' DESC 'Abstraction of a host, an IP device' SUP top AUXILIARY MUST ( cn $ ipHostNumber ) MAY ( l $ description $ manager ) ) +olcObjectClasses: {7}( 1.3.6.1.1.1.2.7 NAME 'ipNetwork' DESC 'Abstraction of an IP network' SUP top STRUCTURAL MUST ( cn $ ipNetworkNumber ) MAY ( ipNetmaskNumber $ l $ description $ manager ) ) +olcObjectClasses: {8}( 1.3.6.1.1.1.2.8 NAME 'nisNetgroup' DESC 'Abstraction of a netgroup' SUP top STRUCTURAL MUST cn MAY ( nisNetgroupTriple $ memberNisNetgroup $ description ) ) +olcObjectClasses: {9}( 1.3.6.1.1.1.2.9 NAME 'nisMap' DESC 'A generic abstraction of a NIS map' SUP top STRUCTURAL MUST nisMapName MAY description ) +olcObjectClasses: {10}( 1.3.6.1.1.1.2.10 NAME 'nisObject' DESC 'An entry in a NIS map' SUP top STRUCTURAL MUST ( cn $ nisMapEntry $ nisMapName ) MAY description ) +olcObjectClasses: {11}( 1.3.6.1.1.1.2.11 NAME 'ieee802Device' DESC 'A device with a MAC address' SUP top AUXILIARY MAY macAddress ) +olcObjectClasses: {12}( 1.3.6.1.1.1.2.12 NAME 'bootableDevice' DESC 'A device with boot parameters' SUP top AUXILIARY MAY ( bootFile $ bootParameter ) ) +structuralObjectClass: olcSchemaConfig +entryUUID: 713cd51c-df8a-103c-9774-230a0a7123cd +creatorsName: cn=config +createTimestamp: 20221013213337Z +entryCSN: 20221013213337.593234Z#000000#000#000000 +modifiersName: cn=config +modifyTimestamp: 20221013213337Z + +dn: olcDatabase=config,cn=config +objectClass: olcDatabaseConfig +olcDatabase: config + +dn: cn=module,cn=config +objectClass: olcModuleList +cn: module +olcModuleLoad: back_mdb + +dn: olcDatabase={1}mdb,cn=config +objectClass: olcDatabaseConfig +objectClass: olcMdbConfig +olcDatabase: {1}mdb +olcSuffix: dc=example,dc=com +olcDbDirectory: /usr/local/openldap/var/openldap-data +olcRootDN: cn=admin,dc=example,dc=com +olcRootPW: admin +olcAccess: to * by * write + diff --git a/packages/tom-server/src/application-server/__testData__/llng/lmConf-1.json b/packages/tom-server/src/hooks/__testData__/llng/lmConf-1.json similarity index 89% rename from packages/tom-server/src/application-server/__testData__/llng/lmConf-1.json rename to packages/tom-server/src/hooks/__testData__/llng/lmConf-1.json index 1aa95886..3ccf4f7f 100644 --- a/packages/tom-server/src/application-server/__testData__/llng/lmConf-1.json +++ b/packages/tom-server/src/hooks/__testData__/llng/lmConf-1.json @@ -136,7 +136,7 @@ "key": "^vmTGvh{+]5!ToB?", "krbAuthnLevel": 3, "krbRemoveDomain": 1, - "ldapServer": "host.docker.internal:21389", + "ldapServer": "annuaire", "ldapAuthnLevel": 2, "ldapBase": "dc=example,dc=com", "ldapExportedVars": { @@ -223,37 +223,65 @@ "oidcOPMetaDataOptions": {}, "oidcRPCallbackGetParam": "openidconnectcallback", "oidcRPMetaDataExportedVars": { - "matrix": { + "matrix1": { "email": "mail", "family_name": "cn", "given_name": "cn", "name": "cn", "nickname": "uid", "preferred_username": "uid" - } + }, + "matrix2": { + "email": "mail", + "family_name": "cn", + "given_name": "cn", + "name": "cn", + "nickname": "uid", + "preferred_username": "uid" + } }, "oidcRPMetaDataMacros": null, "oidcRPMetaDataOptions": { - "matrix": { - "oidcRPMetaDataOptionsAccessTokenClaims": 0, - "oidcRPMetaDataOptionsAccessTokenJWT": 0, - "oidcRPMetaDataOptionsAccessTokenSignAlg": "RS256", - "oidcRPMetaDataOptionsAllowClientCredentialsGrant": 0, - "oidcRPMetaDataOptionsAllowOffline": 0, - "oidcRPMetaDataOptionsAllowPasswordGrant": 0, - "oidcRPMetaDataOptionsBypassConsent": 1, - "oidcRPMetaDataOptionsClientID": "matrix1", - "oidcRPMetaDataOptionsClientSecret": "matrix1*", - "oidcRPMetaDataOptionsIDTokenForceClaims": 0, - "oidcRPMetaDataOptionsIDTokenSignAlg": "RS256", - "oidcRPMetaDataOptionsLogoutBypassConfirm": 0, - "oidcRPMetaDataOptionsLogoutSessionRequired": 1, - "oidcRPMetaDataOptionsLogoutType": "back", - "oidcRPMetaDataOptionsPublic": 0, - "oidcRPMetaDataOptionsRedirectUris": "https://matrix.example.com/_synapse/client/oidc/callback", - "oidcRPMetaDataOptionsRefreshToken": 0, - "oidcRPMetaDataOptionsRequirePKCE": 0 - } + "matrix1": { + "oidcRPMetaDataOptionsAccessTokenClaims": 0, + "oidcRPMetaDataOptionsAccessTokenJWT": 0, + "oidcRPMetaDataOptionsAccessTokenSignAlg": "RS256", + "oidcRPMetaDataOptionsAllowClientCredentialsGrant": 0, + "oidcRPMetaDataOptionsAllowOffline": 0, + "oidcRPMetaDataOptionsAllowPasswordGrant": 0, + "oidcRPMetaDataOptionsBypassConsent": 1, + "oidcRPMetaDataOptionsClientID": "matrix1", + "oidcRPMetaDataOptionsClientSecret": "matrix1*", + "oidcRPMetaDataOptionsIDTokenForceClaims": 0, + "oidcRPMetaDataOptionsIDTokenSignAlg": "RS256", + "oidcRPMetaDataOptionsLogoutBypassConfirm": 0, + "oidcRPMetaDataOptionsLogoutSessionRequired": 1, + "oidcRPMetaDataOptionsLogoutType": "back", + "oidcRPMetaDataOptionsPublic": 0, + "oidcRPMetaDataOptionsRedirectUris": "https://matrix.example.com:446/_synapse/client/oidc/callback", + "oidcRPMetaDataOptionsRefreshToken": 0, + "oidcRPMetaDataOptionsRequirePKCE": 0 + }, + "matrix2": { + "oidcRPMetaDataOptionsAccessTokenClaims": 0, + "oidcRPMetaDataOptionsAccessTokenJWT": 0, + "oidcRPMetaDataOptionsAccessTokenSignAlg": "RS256", + "oidcRPMetaDataOptionsAllowClientCredentialsGrant": 0, + "oidcRPMetaDataOptionsAllowOffline": 0, + "oidcRPMetaDataOptionsAllowPasswordGrant": 0, + "oidcRPMetaDataOptionsBypassConsent": 1, + "oidcRPMetaDataOptionsClientID": "matrix2", + "oidcRPMetaDataOptionsClientSecret": "matrix2*", + "oidcRPMetaDataOptionsIDTokenForceClaims": 0, + "oidcRPMetaDataOptionsIDTokenSignAlg": "RS256", + "oidcRPMetaDataOptionsLogoutBypassConfirm": 0, + "oidcRPMetaDataOptionsLogoutSessionRequired": 1, + "oidcRPMetaDataOptionsLogoutType": "back", + "oidcRPMetaDataOptionsPublic": 0, + "oidcRPMetaDataOptionsRedirectUris": "https://matrix.external.com:446/_synapse/client/oidc/callback", + "oidcRPMetaDataOptionsRefreshToken": 0, + "oidcRPMetaDataOptionsRequirePKCE": 0 + } }, "oidcRPMetaDataOptionsExtraClaims": null, "oidcRPMetaDataScopeRules": null, diff --git a/packages/tom-server/src/hooks/__testData__/llng/ssl.conf b/packages/tom-server/src/hooks/__testData__/llng/ssl.conf new file mode 100644 index 00000000..85afa7cd --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/llng/ssl.conf @@ -0,0 +1,12 @@ +server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/auth.example.com.crt; + ssl_certificate_key /etc/nginx/ssl/auth.example.com.key; + server_name _; + location / { + proxy_pass http://auth.example.com:80/; + proxy_redirect off; + proxy_set_header Host $host; + } +} \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/9da13359.0 b/packages/tom-server/src/hooks/__testData__/nginx/ssl/9da13359.0 new file mode 120000 index 00000000..e375f5ab --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/9da13359.0 @@ -0,0 +1 @@ +ca.pem \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/auth.example.com.crt b/packages/tom-server/src/hooks/__testData__/nginx/ssl/auth.example.com.crt new file mode 100644 index 00000000..0b7ce97b --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/auth.example.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFJDCCAwwCAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yMzA5MjcxNDI3NThaGA8yMTIzMDkwMzE0Mjc1OFowaTELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQYXV0aC5leGFtcGxlLmNvbTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKFOulrNRQzgr6q3hN5jHuA7 +/ohOeZkZKCvWy5E3B21NII7+AQOTE8wQcxvZhOPifjy6lbM6eHl+BlQUwBhvKMBN +074GEwyAsmrSnEWW9cyOaOtdyo6T7B/0P1YTmn2l1py0hmnrQPlewhjpdhAr57RZ +xZOEzGvv+uqbt0McCBMWvPKLvXrUXXd9Jupkl+U9TkuNsayIsWruxWB3vL0SRlVf +5ekqTXMQ73Vs0JMjktD+WXrz6YUAAt0y85tAFUNNSNQHIZu3ctWA7WGCQ9xI8LUA +l7d0CjzqQvrwXCwfCpZW41jfdbWABYnCPw4RXld8OWDyrDmOVeka/vfZMAmf32/n +iRpp0UzrWvTk868gG4SytSyvVy1ZWoQ2AzapolGocQhwi7DgkjsRTnJFyAO7LY6i +iYXBcwc31Rk4ec9VHn3H/u66v4MTCWzmsmpMnnZ2Htho75TeHfDwKtkZsQ/H5QEQ +NI41x7xhrgPBLUSqz1tkSBF6rvAWO2bhEkEKHnNXU5p6q+JQDB/2hbbiE30LDUJj +8YKoelY3J4b0dp1cyIS36fr6JK9R7evqUDTEH+gGYiYEEsLMiu9o5LvalUeVl7XU +pxFDrDwt+Jikqie6Q5wBUTV21WGyAItN6+bpxqBX0HliEC6ylhL/aAqZUyC7P2FN +zjEd97sTNdvJRLEGJWxxAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAAccrDOtveNN +akCdyC8Gb1Jic5kZI52v3qVIXLTYf97KFvQy0oxJGVn/uxYU0tPXqQkdz5oMKVnt +gPPSZ9410LTutqyMrT9y5Rtpaze+0LTf+a6O7gX9HRwEAEa2tabRo1On+48OZqRL +yIYsTHi77ttqGxDU9YY7v1Vgqey3cWJWffQ7WUgOaaNlj+m8Ue2NqnvotXXN8gJt +WquyFfRrlMkvYwOCsOvHdvpSiXVt6XVPVvfjK1B8+zpYOh2FQgTOdd9TMyaUgSd4 +vvIRnFqCqWwoA2YgQNqPCGq4nkpOD35p4X3cwy9h7KxeW5fD6h323jl5VmRgSR5r +0lgELSGpM1JagRM4zEqG3kZMzCLjbe0qf9SLhI4YaLRWf4T6CdcV0bSBYylXZ7uj +xwxlH3G0XP7fpoH4kBGcj0zSiyl3S/UcSlEPE7lbxkSIhMeAAwTd0n27mlgHYvHM +VZ7/R3BiQy5MTtMiBWxHEDhYLuKmyoK6hqv4/o1bqRbjiLheHBWxhauD9bfy4H7K +zM0In9ch3ViVI+DCoCs5GwacXBo80NFyuWTe0IS+c8qMIan/5WSghgQiIw8wtbaO +4r+Wl6gDvk6APYEzTKrpFEolb1P4tD73Kg1v9w7FfMi2ZavZVL/QsP66cNV6xRTt +2O6+bP83DBc6sHNMK3MYiSRle76Rj4eh +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/auth.example.com.key b/packages/tom-server/src/hooks/__testData__/nginx/ssl/auth.example.com.key new file mode 100644 index 00000000..15ca8d7e --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/auth.example.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +Z8Ys1rof4f98l60FQ0A2JhWBCxzH +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/ca.key b/packages/tom-server/src/hooks/__testData__/nginx/ssl/ca.key new file mode 100644 index 00000000..30ce4786 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +AadG09mjAmM8y+lpjinvYXDqgSn8Efc= +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/ca.pem b/packages/tom-server/src/hooks/__testData__/nginx/ssl/ca.pem new file mode 100644 index 00000000..ab582324 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFbTCCA1WgAwIBAgIUalMwUdXLXPZLTp+WiP2lDM4/2bAwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzA5MjcxNDI3NDlaGA8yMTIz +MDkwMzE0Mjc0OVowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAK+lezZWANyhihzp+JGKIAnDazT2f2rZvipZL9Gh +94RWQ49/9RbX9x4t0/smajrlygJVObEeN49xuwRmX/MwWPger8+RROibJ/y7w0qf +jzG6VI2O9R/bhBE3w+ffR3rywXRmH52NfcPz5hc1rySUG0YYDyWvYi2dze4bpsdu +cEFQwOiqeZPlnjDBBMYJFDQJOAVSGYf4QY/A0m6pHSp36wl569l+NnKTXEd5Pgo9 +4CswYobuXAkF/Sxwwr+HU0GZIhjHeoC40+gNAXoZVoympD4q63NXJsncq5Uhe5NZ +rfJgjuPk5Jg4noIWR87eNB3ON5GQ86jrDuDn1ALXuh2UmHJoES9XM7tsSnMCBYJw +axLJeiVme5GIAGPac1c9rMaXWtvI1OroZiLI/XNyBxj0aCZQnJP1OL8/4YZeHS5G +EIwF2KT4G+om8JlglZ0w8OrWJ6skClxr5JHXkgeT+34GX7gkhv8Qrs0D9FJRpuwS +tFsgr6H73oF4rvYbz2t+GzPei4MBFkAXs2ROthwnRhNWAjOjDk4K1YroI14geyUB +W9sxdIMhWWlYLIh6wAVeI5e7Ot04nTmGdAeR6RaoEUhdgKGSI3yrfN5WTGdLtqTn +YR86Sh7myXzIH1T9nApuMm3kDLzxknaIYzvaTBtX41+NC+ipVZ5OPQpTWFRthW3F +TNFzAgMBAAGjUzBRMB0GA1UdDgQWBBSBah28uESfTKuEGnpXqoriwHPoeDAfBgNV +HSMEGDAWgBSBah28uESfTKuEGnpXqoriwHPoeDAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQAqZLn4pI0zhjrE2RsPtKrY4/bDuJQPKpw/EnnQaDWE +R581fzAY7gjCmK2lr8fDdHvabSKAjb4zsE2w1oIaPlydK1LT4KOitTnYc+MFmmBy +Br0E9chKkbRssd9sjvE9PHzA5jW3aM1a/OEos1RMu0hHyn9/GU15VnuMkO2oCj7Z +WeTSWmozw+4lZAFbxdRiblA+ILKwrGQjhKdAMShimweduNEuVNpLAOixO1O2MMeJ +Yj3aVjcsFcQGXJtFCXDZrzyVk2q+HVbSGkxEqtZPf31opIbSS6KOAVniSPp8UPYH +A3t0Hr6+yqjo0DMTJG1kyX+wD+iir3F1tDjnE9v+l7s7YaYGVC7XlxzzdroL81kx +aaPnJiDotjZITBAV8OKo5aWj2867gZrbmtkE7t4wJGcaXzYQgqaEYWTjQZyfrLEA +AWxOEx2p34vi4S3Z3VjzY7UkJ12McUwQQ11xvmLEmE7WSsU7iFjpwCeJgofNpUz0 +dyWY1C51Q3mqJwYhsOBlLazfd88Jrlwmcp74AgQ5ZruJgI4hisi22ac26Y9tgwPH +EGcCzvRHcNAPOup3AC+0vJ+5mYiLNJ41cHE+8YAyYAmae3tMBphKLCbXlk57KUuB +oKZn6qKTQzkHVn0k5LQrf1mEQBjvDFnC+hx6gObF91GAX2nxLMh4OrNRgeE2ad7O +CQ== +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.crt b/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.crt new file mode 100644 index 00000000..1e2d2c30 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFHzCCAwcCAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yNDA0MTAxNDQ2MDlaGA8yMTI0MDMxNzE0NDYwOVowZDELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/nFGkaWn8saphS078wNSHtbvetuQS +1x+KMsOX/9ZbFMU2W+RVPyAyXNX4GiRGeo/QoGX39pn9qQDcVfc3usy6LDzQkGfW +2PCcu1a4OfpFVgZ77VgzkcpDetoZV4WfzFqGY85/kpjxkxzLx4suTzv8sP8Ogxc+ +m9QHXty+dGlkxgSWnnyM1srep9BPXzr7OyDpgYphglp85eyNe/wMjFsVjwFFfyuV +0oC+OXSv0FXfY/RKus4WFtCx4ZGdI8StJu2wpNePiFY1HR8h7kLMJ1f8DECkaXfW +3v8AFnB/e9yKOKM+Pm5j6Ywn1Jvr8eEclmm2zkx+OHG86NgyJt0zZArCXdFv6po/ +otbkNx/Ubmp6WU1m7WpmCCITD6bt9YPEDfiJqaKmedau91hUGuxH4+TuKGOIFzvy +C03P+bHSsNrejp3sow6+HqiNrhMB2R8BMdcxdxTzULxW7L02ww5nvkA+M4P9BQ7g ++2grxAnhVL7uzDJylvsZ3hgUUVJjRfdLxfg3JiIUAonoqSQfUPQ0z6XgpzdWFhKU +3We7RVZj2HWP4ASLJCNXHGIcBdhxAqU9Tcat6L6TvgJyb38iMiLK/Pi/fOn1WKMA +Cky4BIeCHYQS7WF58LOUSO52P15ycQzaCEdddGw3M2jG1cgHWZyYd8n+E+B/qKgx +dakeG3DLE+GRXQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCtVJFotRi5zpJxRpIA +fUUlu3aqgX+D+RyxMvWa2ggSizV36dnOpo8IT4Etqr+E1vDHCBVvvtwpWiDioxYD +9VgQTaoPGCGS1hhNTTpePfA3Jd2UlWugxAKCMmrERM32IsTll8Y6YIyftyQtJv4A +cNBn3ySUlkKyS6t8k9HT8B+VNIt5ADkAZi0dwXgNcVy+L1aghQ/ZQijIr0TT/M/P +51zf4JI3xPmTNeNgCeu+6xyfcYiisuo/Ast+Xnv5SCSNc9ik08iNI3a8rq4YRUsF +1FuGamU0Cb9cxMHhAul1kf90ymJDKh4KyipTI7taowSUAJTAQJUi1xvPAc6FVCQd +VLkj0cSGBF+/EmUge6UpbxIDtZl2wd15qDGpdNVKN91B5ZXhzXSkC/8oE5gefxrL +TuZSxHP4WZnxKcglxL5dQL11NQD/W3t3/m/FTqtg0UAnQWOSGVNZtEtNQispEpCO +Onib/KNirRMD/f3xXFqwsj6NmBYPZkb/064MYs3mbe7hnLPSf3ac8+EX4TA/A3Vd +wRAhXo3XWqCFMfY6mvRJbJlHcvo3UjoC23cTYQ0CDocEU/WEBaVaNntL2V07n9jT +uziY2Gu4xCJzynFXmA1BZinJ8aNKJ+QpwwgZUN0HKLVHsUoo1jRxXcK2G8TfMiWY +GZiU3edbGeKY8wKDU81zG3Drhw== +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.key b/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.key new file mode 100644 index 00000000..68032125 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +hSXT/o9yIYn7YnP/lpIG+iYqcySGUPM= +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.ssl.conf b/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.ssl.conf new file mode 100644 index 00000000..b4c26bdd --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/example.com.ssl.conf @@ -0,0 +1,16 @@ +events { + worker_connections 4096; ## Default: 1024 +} +http { + server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/example.com.crt; + ssl_certificate_key /etc/nginx/ssl/example.com.key; + server_name example.com; + location /.well-known/matrix/server { + default_type application/json; + return 200 '{"m.server": "matrix.example.com"}'; + } + } +} \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.crt b/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.crt new file mode 100644 index 00000000..1a18eaed --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFIDCCAwgCAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yNDA0MTAxNDQ2MTdaGA8yMTI0MDMxNzE0NDYxN1owZTELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEVMBMGA1UEAwwMZXh0ZXJuYWwuY29tMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAshWaKcPRI1brgE5uOJ9/tOpR70KQ +VfwXY1gtGSXFxrQBZhMkNh6e+jRtGp7jbG1SHxGdWc26m93kMKYtfgk0NtbfMgqd +zuCwtMeE6JAfiRJaoSNihhBouA/gfVtaemfyzwkPQTMVMWfg9+3NN2m4Xb/9JJqX +ZrsI/NsXegFbOvHEU4ozqgtLpfU6zTx5zUUQeltnOvwzBBIszZkhSV237D7fLorW +3jPI8IBdROwMRF7nMEmM6cdtMfjYTOM/rScospu3VpmYFoYWusVFo4cShbnGwWXP +fOs/iNhl0roX9W56Kwowl3dYz2PRKed6PP0tGcgRQftSp+AF3841dpzxFZ6fYQG+ +DD43f0ead2BFHnvCsHO1/LqKteHi2d4YuTD3+/vQyCiay6MAF4/KZzoW+fZy3LGZ +aHltTysJWVBAecezgQUIS8MOY6Otvn0B+6DbB73HgzMo6Av5aKjS6Ojo6YYlR99J +cpLyNxwJoMCENpVmtFaybM9tguQILDJ8S5+bf5e6D4obp3fNEqnS8R+n7aX7TQES +v6VTdlSNsmvgPWB4so5r1hmMIYsXno6wY+kcL8TYnrp/nJg7boZk7COO+SuCP081 +MP8CC9XLAvyHfDvWiVXlSYcx0+jbrQIVw1TAGgs/wzhOZ6wzr6/Fv1vJjNndTbVQ +5eI/JK5NTAzIIfcCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAeJFx/8h1Vi98+ZrR +Hr5ow1qHwft8HwrMe2rNdNugT4QIOr39a7bYYGZqh/sQTHiZGpvWwhgPCv1p2UPr +motmn6NIPDtWdMtUb5i/iLpqNlCBWcxFnIc/dJ339nhN41xVogVM5k4yqT3kqehI +L7tR8of5OA0b8/9NmbcYVg2EIq27qfrIyQi8eehU5K60EqMG1OhoGRZ4NcBVc0zU +AQFAi995nQMYeLBu1rTDe4+V/PcEUfvSZbUZ5/naC0yD2L4NdgmeHacEVnDCbdx9 +sdsAmw05cvu5+cScs9zLo+PAVMdcooL9Qg3LkJPaBuUII7v6HyUbnnvRdJvB8l07 +6YJewEjaFuTDtL2SBqZVHJgePCrHdd3b7UH2as7X598XsbuMkZ2SkeQiuX8d/ykW +oA+13p3rw4HA3QClHnARPBf4iZNsPQ9f7ZNrYP9snpTkHFIp6w25TEQVG6Kg3P8v +B5MlqwuLP9hDWxg3yJU9fo9sZsKBw398O4sbz0/4k0pMRjzjZzS5Dh+JsOefW82c +nABGRch6DWLe3qBa8qCbNObMR0SE8MoXQZvpK+E+Sl2WvIDwkJTfTTuRFP3za+iJ +wGsoeLezAm+NqWLEuDIQQfJPFfbCm/F1Zx+pFPRyoPeF6nQNq5HXP8WNC5cYqRB4 +0JIvbtuvVQwhfZqAykZdpqGRyVc= +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.key b/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.key new file mode 100644 index 00000000..82d07157 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +4gW05uhlD2kSmuHVpY2RAycdrtnJ +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.ssl.conf b/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.ssl.conf new file mode 100644 index 00000000..fa0db77c --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/external.com.ssl.conf @@ -0,0 +1,16 @@ +events { + worker_connections 4096; ## Default: 1024 +} +http { + server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/external.com.crt; + ssl_certificate_key /etc/nginx/ssl/external.com.key; + server_name external.com; + location /.well-known/matrix/server { + default_type application/json; + return 200 '{"m.server": "matrix.external.com"}'; + } + } +} \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.example.com.crt b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.example.com.crt new file mode 100644 index 00000000..18a489b9 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.example.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFJjCCAw4CAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yMzA5MjcxNDI4NDJaGA8yMTIzMDkwMzE0Mjg0MlowazELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEbMBkGA1UEAwwSbWF0cml4LmV4YW1wbGUuY29t +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAznlYOj03At3HN/EhoYcg +n4qmrLskVW81Y/3TI06PifmU/uJpJ03rdufaIww21zlAxwlYD3UNKkkPK9oFFKZe +EBzlADFIomsOCsjwGatdmL3U/bFgU8lXNRn8FeGbCDnG1I0iPnjFNpwMe3VwLT31 +60HvvZOOuCj3ps2dxCk8a9NXDpzex1dBLk92m+2n+Fapyyfrt2xzyyzTlhIXofb7 +ZhdvBx567KWrOlEqiwNl6E4a0Eg2MekcbNIf1d8xcRQH+Pqewszf3ww+mqsHoiXS +0o4F1FAK++3TuQ1zjgPtqF/+Z+aTdDO3/YXdOUTbKZWm9Cozkh2t32UNk/TDcskQ +6LBBONYYPaYo4VJa/10Hv9s+3AqK7DLtxi3uh1plPYHDvKM0QaqOzxCrNq2sBN+i +9IRmFJUfCjWtR34WROlA73mmgDkAWugseLpjEwAdq8A6kpMYElSDll5hbVuWjJ6m +4iGyH3aTOFrufPGDmOac/8FOTSHWl/1dabfdSnO+97fJcmrWH5WXyTDNP+/42I2M +/qLIj5EYKWdbysTJ5EfInsFY2pAtPIe6Vti31ziJ8lrXihjELzWkiu7xpv+JpSj7 +1JMZgEVtI3VxzDXXeSB+MZI+hQVyZL4cCB5wTzl2qIWteMi7lnTqkPhS4B3QKrX3 +aOvxZ1QrbT0ZJvf/b9sMshsCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEASCs3hmVA ++FGYm+E8RwhROBy/gQiKh0lNjyu6hV98cpG2zboO0YDa+8c5kiBiEoXu/oUkA3ST +f5ApYT0vOVO72C58ZVqiOCNeB2vB3lDH9d3vmmDOxuCrsd+b34YXpZ9rC5Yiu8wr +AZN7q4LKt4mpP7+W3C7yUdOoIp7trwIYREb2jq7eHZoHrRSWeHbloLfxMNk0M1HK +Zr9Ke2SvmVjlTIz6Itu0WrRhhazxczvUKquNS1sLR5CXS/zdPqmBxNdN+HpL0RLP +171oQSnOQo1BUCsGjEjAybSCAfkKHbD24M8lpYRI5C6bKmzqHYHUpohxMqqGSg1s +j6YE2z6k9q9AvZ8WEE3UUeuVIDGFdin4mQsUJErglZbPprTmN8J1pvu6nAYWeito +a/iOdOB4Gay+p2xWMSqZ+AfFCw+1T9RrKdl9gBNj1VY5z2TwsQwKrCRfHffKXDOl ++yHLBn5qCAIUzcXdn3LRul4EWle4n7fKFgi5gXgXi7VdWaRKXsY212wmhegdZmAs +26AIXxtI6MPF4wblXynSD3vBlJ8CqQV+eI7XgtiVpZx+9RGXqP3TPpdcea0x33Yh +M00khmnmYA8UtuQHVBAR21Eap9/pVsXmqhnInwqx3joWKLZHxObKA96uMx2cmNWR +ciX42z7/oDuIn/7DJE9ID66J1gJ7iqr9Q90= +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.example.com.key b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.example.com.key new file mode 100644 index 00000000..f430285d --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.example.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +wWLMyRVpXRgJKSYxEvhKHAc/8Y0i6Q== +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.external.com.crt b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.external.com.crt new file mode 100644 index 00000000..cd3c6446 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.external.com.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFJzCCAw8CAf8wDQYJKoZIhvcNAQELBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAgFw0yNDA0MTAwODM1MjdaGA8yMTI0MDMxNzA4MzUyN1owbDELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBkNlbnRyZTEOMAwGA1UEBwwFUGFyaXMxETAPBgNVBAoMCExp +bmFnb3JhMQswCQYDVQQLDAJJVDEcMBoGA1UEAwwTbWF0cml4LmV4dGVybmFsLmNv +bTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANaIqvh8aZasEL9ufHB9 +IRNF/3K9igZSdQsjDPxuUhran8GtvGgdIb2CiwN/RB2lHV76lPWxbstfnfY/VtBS +8UT+EBi9GyqANQVx3uRvt8rS7V64JC3WDDgBpOTRWPXPV20uldksayPW6VMJ4X3a +lmKHZFDcTsmyfkeDFoeC8zY8oHX+2JpqSiP+aNvkrAhmEvImtNn38mHvSNjR61+g +vR0rfL9+pl9LvibXb1+195q4aMEtT5wOVJwmY4jQtroaTQTATWoHM8wbyK/N5crC +NMxnoaeRRVBQc1iydG2e58Wi6W3r/eaUjOL+//Qs13mDLIsb17saRRtOyKbc9/R/ +hrUk/nsmyb2HZpPUCB7qSaSYnIuRSDQl+UEnApqR5+GijEEdifRtMVFirGL0M2Dq +yDKumnSnhgvRbxYaedTcHJKRbCma0REufalr8C748JQeXNekiboX7tbsZGvpgCP1 +wZbqPwepADAKlmqkx7taBc3Usp0lvl6jNyR07q2DEdaEUAr84wfL8pBb7YmTk6bn +wosMJT7AmNRah5V4t9n2jG9D4aBfrTdCR/YJUkA/KjrojTzuT9/75CIDfOQybWEo +Fu2mKffU36DhEM2kLebR/tovVYrOHhCVNOQ/4m8qjsu1By77592MzoE+DxfPLd+C +AxAM69mUa5AHJrNp6Df+MJoLAgMBAAEwDQYJKoZIhvcNAQELBQADggIBACIOthnH +X50tJSzEREWchCd0zVn8U8Y5GTgNRkXzTSGPikcpr7J6Op4h8kheaveO2nd+qbc1 +k9QxSDdEjrnpiGG+iAxybmx8Y2cZkJEWPer8tZqSp85G4+EWS1JIWBGMSn0WIjO2 +NJvfmCR9vFVuOL5sCPTRJJdt0EJkRXtVVdxAlwTSTLvaAu+7z/+1n3ifZgeCohao +z2eUv67idDs1UZhyqRAbOm2ZXZlBwWz5XK/4cgjhwtyUu38g7V6qJXwwWFoeUsst +ZcMTO9JgnsAg4PIgT4aZcd3hdLZJq6jgUwaWi4AHADfojterJHUWYOGZzC6Sp08x +PyMMtb8CLTqC1D3xc/rYrT6AqxOcQSDg7G36TnrFsME13Yz23o22YXuHT5lhiHzv +ZczTuiXPGWikkWNwkBcgkxiweoUMpNrJlFKN7eCGGdSuPFseWUOqZWbI3hJxgIgE +CSGjHlCzR+yUa6B4cCPj5ITvaUOzxIUOBRR3yIWAOCg0mfSmC0NR7KNarLBqtXdT +jwP0S0+BI60VsnIrrHtm+Arzr05HnZq3HXjf3+wNVrWWoKn9siF1boqWdVJH6CkU +qYVFjccSrglrMc+m/McXr19Gi6vyp76kyMsI1rBhbWjW6AqVGnjJISOayH4NW5Y5 +DoHM3Z6/KLDkJJnhmez2kUNlEgO8RFPFLgQL +-----END CERTIFICATE----- diff --git a/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.external.com.key b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.external.com.key new file mode 100644 index 00000000..fd7a1178 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/nginx/ssl/matrix.external.com.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +7QY3x9rBvpiq4EmqXgm2ob8tLxaiYw== +-----END PRIVATE KEY----- diff --git a/packages/tom-server/src/hooks/__testData__/registration-error-cases.yaml b/packages/tom-server/src/hooks/__testData__/registration-error-cases.yaml new file mode 100755 index 00000000..247b1be3 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/registration-error-cases.yaml @@ -0,0 +1,10 @@ +id: lpqhjc6nyj7sfir56es9yjkasbcigz9l7dkcgkt66kaolp8dqcffwkghqpahd9o3 +hs_token: rr7d9j1cezgdmdjgcxew7wdofsplp85poy7azc86bgfkkhsm8kqarhouebh6ofk4 +as_token: 7ok8e79fchomqbgxf7lkk4krjgoilas8j2ggch4hb8pcnigo595jemkomioha7f4 +url: http://localhost:3003/ +sender_localpart: twake +namespaces: + users: + - exclusive: false + regex: '@.*' +de.sorunome.msc2409.push_ephemeral: true diff --git a/packages/tom-server/src/hooks/__testData__/synapse-data/homeserver.yaml b/packages/tom-server/src/hooks/__testData__/synapse-data/homeserver.yaml new file mode 100644 index 00000000..4a3f2b14 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/synapse-data/homeserver.yaml @@ -0,0 +1,62 @@ +# Configuration file for Synapse. +# +# This is a YAML file: see [1] for a quick introduction. Note in particular +# that *indentation is important*: all the elements of a list or dictionary +# should have the same indentation. +# +# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html +# +# For more information on how to configure Synapse, including a complete accounting of +# each option, go to docs/usage/configuration/config_documentation.md or +# https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html +server_name: "example.com" +public_baseurl: "https://matrix.example.com:446/" +pid_file: /data/homeserve.pid +listeners: + - port: 8448 + tls: true + type: http + x_forwarded: true + resources: + - names: [client, federation] + compress: false +tls_certificate_path: "etc/ssl/certs/matrix.example.com.crt" +tls_private_key_path: "etc/ssl/certs/matrix.example.com.key" +database: + name: psycopg2 + args: + user: synapse + password: 'synapse!' + database: synapsedb + host: postgresql + cp_min: 2 + cp_max: 4 + keepalives_idle: 10 + keepalives_interval: 10 + keepalives_count: 3 +log_config: "/data/matrix.example.com.log.config" +media_store_path: /data/media_store +registration_shared_secret: "u+Q^i6&*Y9azZ*~pID^.a=qrvd+mUIBX9SAreEPGJ=xzP&c+Sk" +report_stats: false +macaroon_secret_key: "=0ws-1~ztzXm&xh+As;7YL5.-U~r-T,F4zR3mW#E;6Y::Rb7&G" +form_secret: "&YFO.XSc*2^2ZsW#hmoR+t:wf03~u#fin#O.R&erFcl9_mEayv" +signing_key_path: "/data/matrix.example.com.signing.key" +accept_keys_insecurely: true +app_service_config_files: + - /data/registration.yaml +oidc_config: + idp_id: lemonldap + idp_name: lemonldap + enabled: true + issuer: "https://auth.example.com/" + client_id: "matrix1" + client_secret: "matrix1*" + scopes: ["openid", "profile"] + discover: true + user_profile_method: "userinfo_endpoint" + user_mapping_provider: + config: + subject_claim: "sub" + localpart_template: "{{ user.preferred_username }}" + display_name_template: "{{ user.name }}" +ip_range_blacklist: \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/synapse-data/matrix.example.com.log.config b/packages/tom-server/src/hooks/__testData__/synapse-data/matrix.example.com.log.config new file mode 100644 index 00000000..3e1efccc --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/synapse-data/matrix.example.com.log.config @@ -0,0 +1,77 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + file: + class: logging.handlers.TimedRotatingFileHandler + formatter: precise + filename: /data/homeserver.log + when: midnight + backupCount: 3 # Does not include the current log file. + encoding: utf8 + + # Default to buffering writes to log file for efficiency. + # WARNING/ERROR logs will still be flushed immediately, but there will be a + # delay (of up to `period` seconds, or until the buffer is full with + # `capacity` messages) before INFO/DEBUG logs get written. + buffer: + class: synapse.logging.handlers.PeriodicallyFlushingMemoryHandler + target: file + + # The capacity is the maximum number of log lines that are buffered + # before being written to disk. Increasing this will lead to better + # performance, at the expensive of it taking longer for log lines to + # be written to disk. + # This parameter is required. + capacity: 10 + + # Logs with a level at or above the flush level will cause the buffer to + # be flushed immediately. + # Default value: 40 (ERROR) + # Other values: 50 (CRITICAL), 30 (WARNING), 20 (INFO), 10 (DEBUG) + flushLevel: 30 # Flush immediately for WARNING logs and higher + + # The period of time, in seconds, between forced flushes. + # Messages will not be delayed for longer than this time. + # Default value: 5 seconds + period: 5 + + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + +root: + level: INFO + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [buffer] + +disable_existing_loggers: false diff --git a/packages/tom-server/src/hooks/__testData__/synapse-data/registration.yaml b/packages/tom-server/src/hooks/__testData__/synapse-data/registration.yaml new file mode 100644 index 00000000..a0f99e4b --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/synapse-data/registration.yaml @@ -0,0 +1,10 @@ +id: lpqhjc6nyj7sfir56es9yjkasbcigz9l7dkcgkt66kaolp8dqcffwkghqpahd9o3 +hs_token: rr7d9j1cezgdmdjgcxew7wdofsplp85poy7azc86bgfkkhsm8kqarhouebh6ofk4 +as_token: 7ok8e79fchomqbgxf7lkk4krjgoilas8j2ggch4hb8pcnigo595jemkomioha7f4 +url: http://host.docker.internal:3003/ +sender_localpart: twake +namespaces: + users: + - exclusive: false + regex: '@.*' +de.sorunome.msc2409.push_ephemeral: true diff --git a/packages/tom-server/src/hooks/__testData__/synapse-external/homeserver.yaml b/packages/tom-server/src/hooks/__testData__/synapse-external/homeserver.yaml new file mode 100644 index 00000000..acbe7cf6 --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/synapse-external/homeserver.yaml @@ -0,0 +1,49 @@ +server_name: "external.com" +public_baseurl: "https://matrix.external.com:446/" +pid_file: /data/homeserver.pid +listeners: + - port: 8448 + tls: true + type: http + x_forwarded: true + resources: + - names: [client, federation] + compress: false +tls_certificate_path: "etc/ssl/certs/matrix.external.com.crt" +tls_private_key_path: "etc/ssl/certs/matrix.external.com.key" +database: + name: psycopg2 + args: + user: synapse + password: 'synapse!' + database: synapseexternaldb + host: postgresql + cp_min: 2 + cp_max: 4 + keepalives_idle: 10 + keepalives_interval: 10 + keepalives_count: 3 +log_config: "/data/matrix.external.com.log.config" +media_store_path: /data/media_store +registration_shared_secret: "u+Q^i6&*Y9azZ*~pID^.a=qrvd+mUIBX9SAreEPGJ=xzP&c+Sk" +report_stats: false +macaroon_secret_key: "=0ws-1~ztzXm&xh+As;7YL5.-U~r-T,F4zR3mW#E;6Y::Rb7&G" +form_secret: "&YFO.XSc*2^2ZsW#hmoR+t:wf03~u#fin#O.R&erFcl9_mEayv" +signing_key_path: "/data/matrix.external.com.signing.key" +accept_keys_insecurely: true +oidc_config: + idp_id: lemonldap + idp_name: lemonldap + enabled: true + issuer: "https://auth.example.com/" + client_id: "matrix2" + client_secret: "matrix2*" + scopes: ["openid", "profile"] + discover: true + user_profile_method: "userinfo_endpoint" + user_mapping_provider: + config: + subject_claim: "sub" + localpart_template: "{{ user.preferred_username }}" + display_name_template: "{{ user.name }}" +ip_range_blacklist: \ No newline at end of file diff --git a/packages/tom-server/src/hooks/__testData__/synapse-external/matrix.external.com.log.config b/packages/tom-server/src/hooks/__testData__/synapse-external/matrix.external.com.log.config new file mode 100644 index 00000000..3e1efccc --- /dev/null +++ b/packages/tom-server/src/hooks/__testData__/synapse-external/matrix.external.com.log.config @@ -0,0 +1,77 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + file: + class: logging.handlers.TimedRotatingFileHandler + formatter: precise + filename: /data/homeserver.log + when: midnight + backupCount: 3 # Does not include the current log file. + encoding: utf8 + + # Default to buffering writes to log file for efficiency. + # WARNING/ERROR logs will still be flushed immediately, but there will be a + # delay (of up to `period` seconds, or until the buffer is full with + # `capacity` messages) before INFO/DEBUG logs get written. + buffer: + class: synapse.logging.handlers.PeriodicallyFlushingMemoryHandler + target: file + + # The capacity is the maximum number of log lines that are buffered + # before being written to disk. Increasing this will lead to better + # performance, at the expensive of it taking longer for log lines to + # be written to disk. + # This parameter is required. + capacity: 10 + + # Logs with a level at or above the flush level will cause the buffer to + # be flushed immediately. + # Default value: 40 (ERROR) + # Other values: 50 (CRITICAL), 30 (WARNING), 20 (INFO), 10 (DEBUG) + flushLevel: 30 # Flush immediately for WARNING logs and higher + + # The period of time, in seconds, between forced flushes. + # Messages will not be delayed for longer than this time. + # Default value: 5 seconds + period: 5 + + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + +root: + level: INFO + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [buffer] + +disable_existing_loggers: false diff --git a/packages/tom-server/src/hooks/callback/on-room-membership-event.ts b/packages/tom-server/src/hooks/callback/on-room-membership-event.ts new file mode 100644 index 00000000..46d24a97 --- /dev/null +++ b/packages/tom-server/src/hooks/callback/on-room-membership-event.ts @@ -0,0 +1,59 @@ +import { type TwakeLogger } from '@twake/logger' +import type MatrixApplicationServer from '@twake/matrix-application-server' +import { type ClientEvent } from '@twake/matrix-application-server' +import fetch from 'node-fetch' +import { type Config } from '../../types' +import { type IMatrixDBRepository } from '../repositories/interfaces/matrix-db-repository.interface' + +export class OnRoomMembershipEvent { + constructor( + private readonly _applicationServer: MatrixApplicationServer, + matrixDb: IMatrixDBRepository, + conf: Config, + logger: TwakeLogger + ) { + this._applicationServer.on( + 'state event | type: m.room.member', + (event: ClientEvent) => { + if (event.content.membership === 'leave') { + let statusCode: number + const deleteRequestUrl = `https://${conf.matrix_server}/_synapse/admin/v1/rooms/${event.room_id}` + matrixDb + .hasRoomLocalServerUsers(event.room_id) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((hasLocalServerUsers) => { + if (!hasLocalServerUsers) { + return fetch(encodeURI(deleteRequestUrl), { + method: 'DELETE', + headers: { + Authorization: `Bearer ${this._applicationServer.appServiceRegistration.asToken}` + }, + body: JSON.stringify({}) + }) + } + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((response) => { + if (response != null) { + statusCode = response.status + return response.json() + } + }) + .then((body) => { + if (body != null) { + logger.info(JSON.stringify(body), { + matrixUserId: `@${this._applicationServer.appServiceRegistration.senderLocalpart}:${conf.server_name}`, + httpMethod: 'DELETE', + requestUrl: deleteRequestUrl, + status: statusCode + }) + } + }) + .catch((e) => { + logger.error(e) + }) + } + } + ) + } +} diff --git a/packages/tom-server/src/hooks/index.test.ts b/packages/tom-server/src/hooks/index.test.ts new file mode 100644 index 00000000..d0b0def6 --- /dev/null +++ b/packages/tom-server/src/hooks/index.test.ts @@ -0,0 +1,677 @@ +import { MatrixDB } from '@twake/matrix-identity-server' +import express from 'express' +import fs from 'fs' +import type * as http from 'http' +import * as fetch from 'node-fetch' +import os from 'os' +import path from 'path' +import { + DockerComposeEnvironment, + Wait, + type StartedDockerComposeEnvironment +} from 'testcontainers' +import TwakeServer from '..' +import JEST_PROCESS_ROOT_PATH from '../../jest.globals' +import { type Config } from '../types' +import buildUserDB from './__testData__/build-user-db-for-error-cases-test' +import errorCasesConfig from './__testData__/config-error-cases-test.json' +import integrationTestsConfig from './__testData__/config-integration-tests.json' + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const syswideCas = require('@small-tech/syswide-cas') + +const pathToTestDataFolder = path.join( + JEST_PROCESS_ROOT_PATH, + 'src', + 'hooks', + '__testData__' +) +const pathToSynapseDataFolder = path.join(pathToTestDataFolder, 'synapse-data') +const pathToExternalSynapseDataFolder = path.join( + pathToTestDataFolder, + 'synapse-external' +) + +jest.unmock('node-fetch') + +describe('ToM Server hooks', () => { + let twakeServer: TwakeServer + let app: express.Application + let expressTwakeServer: http.Server + + describe('Integration tests', () => { + const matrixExampleServer = (integrationTestsConfig as Config).matrix_server + const matrixExternalServer = 'matrix.external.com:446' + let startedCompose: StartedDockerComposeEnvironment + let tokens = { + askywalker: '', + lskywalker: '', + okenobi: '' + } + let tokensExternal = { + myoda: '', + hsolo: '' + } + + const simulationConnection = async ( + username: string, + password: string, + matrixServer: string + ): Promise => { + let response = await fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixServer}/_matrix/client/v3/login` + ) + ) + let body = (await response.json()) as any + const providerId = body.flows[0].identity_providers[0].id + response = await fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixServer}/_matrix/client/r0/login/sso/redirect/${providerId}?redirectUrl=http://localhost:9876` + ), + { + redirect: 'manual' + } + ) + let location = (response.headers.get('location') as string).replace( + 'auth.example.com', + 'auth.example.com:446' + ) + const matrixCookies = response.headers.get('set-cookie') + response = await fetch.default(location) + body = await response.text() + const hiddenInputFieldsWithValue = [ + ...(body as string).matchAll(/ `${matchElt[1]}=${matchElt[2]}&`) + .join('') + const formWithToken = `${hiddenInputFieldsWithValue}user=${username}&password=${password}` + response = await fetch.default(location, { + method: 'POST', + body: new URLSearchParams(formWithToken), + redirect: 'manual' + }) + location = response.headers.get('location') as string + response = await fetch.default(location, { + headers: { + cookie: matrixCookies as string + } + }) + body = await response.text() + const loginTokenValue = [ + ...(body as string).matchAll(/loginToken=(\S+?)"/g) + ][0][1] + response = await fetch.default( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + encodeURI(`https://${matrixServer}/_matrix/client/v3/login`), + { + method: 'POST', + body: JSON.stringify({ + initial_device_display_name: 'Jest Test Client', + token: loginTokenValue, + type: 'm.login.token' + }) + } + ) + body = (await response.json()) as any + return body.access_token as string + } + + const connectMultipleUsers = async ( + usersCredentials: Array<{ username: string; password: string }>, + matrixServer: string + ): Promise => { + const tokens: string[] = [] + for (let i = 0; i < usersCredentials.length; i++) { + const token = await simulationConnection( + usersCredentials[i].username, + usersCredentials[i].password, + matrixServer + ) + tokens.push(token as string) + } + return tokens + } + + const createRoom = async ( + token: string, + invitations: string[] = [], + name: string + ): Promise => { + let requestBody = {} + requestBody = name != null ? { ...requestBody, name } : requestBody + requestBody = + invitations != null + ? { ...requestBody, invite: invitations } + : requestBody + const response = await fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixExampleServer}/_matrix/client/v3/createRoom` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${token}` + }, + body: JSON.stringify(requestBody) + } + ) + const responseBody = (await response.json()) as Record + return responseBody.room_id + } + + const joinRoom = async ( + roomId: string, + token: string, + matrixServer: string + ): Promise => { + await fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixServer}/_matrix/client/v3/join/${roomId}` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${token}` + } + } + ) + } + + beforeAll((done) => { + syswideCas.addCAs( + path.join(pathToTestDataFolder, 'nginx', 'ssl', 'ca.pem') + ) + new DockerComposeEnvironment( + path.join(pathToTestDataFolder), + 'docker-compose.yml' + ) + .withEnvironment({ MYUID: os.userInfo().uid.toString() }) + .withWaitStrategy('postgresql-tom', Wait.forHealthCheck()) + .withWaitStrategy('synapse-tom', Wait.forHealthCheck()) + .withWaitStrategy('external-synapse', Wait.forHealthCheck()) + .up() + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((upResult) => { + startedCompose = upResult + twakeServer = new TwakeServer(integrationTestsConfig as Config) + app = express() + return twakeServer.ready + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + app.use(twakeServer.endpoints) + return new Promise((resolve, reject) => { + expressTwakeServer = app.listen(3003, () => { + resolve() + }) + }) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + return connectMultipleUsers( + [ + { username: 'askywalker', password: 'askywalker' }, + { username: 'lskywalker', password: 'lskywalker' }, + { username: 'okenobi', password: 'okenobi' } + ], + matrixExampleServer + ) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((usersTokens) => { + if (usersTokens == null || usersTokens.some((t) => t == null)) { + throw new Error('Error during user authentication') + } + const usersTokensChecked = usersTokens + tokens = { + askywalker: usersTokensChecked[0], + lskywalker: usersTokensChecked[1], + okenobi: usersTokensChecked[2] + } + return connectMultipleUsers( + [ + { username: 'myoda', password: 'myoda' }, + { username: 'hsolo', password: 'hsolo' } + ], + matrixExternalServer + ) + }) + .then((usersTokens) => { + if (usersTokens == null || usersTokens.some((t) => t == null)) { + throw new Error('Error during user authentication') + } + const usersTokensChecked = usersTokens + tokensExternal = { + myoda: usersTokensChecked[0], + hsolo: usersTokensChecked[1] + } + done() + }) + .catch((e) => { + done(e) + }) + }) + + afterAll((done) => { + const filesToDelete: string[] = [ + path.join(pathToSynapseDataFolder, 'matrix.example.com.signing.key'), + path.join(pathToSynapseDataFolder, 'homeserver.log'), + path.join(pathToSynapseDataFolder, 'media_store'), + path.join( + pathToExternalSynapseDataFolder, + 'matrix.external.com.signing.key' + ), + path.join(pathToExternalSynapseDataFolder, 'homeserver.log'), + path.join(pathToExternalSynapseDataFolder, 'media_store') + ] + filesToDelete.forEach((path: string) => { + if (fs.existsSync(path)) { + const isDir = fs.statSync(path).isDirectory() + isDir + ? fs.rmSync(path, { recursive: true, force: true }) + : fs.unlinkSync(path) + } + }) + if (twakeServer != null) twakeServer.cleanJobs() + if (expressTwakeServer != null) { + expressTwakeServer.close((err) => { + if (startedCompose != null) { + startedCompose + .down() + .then(() => { + err != null ? done(err) : done() + }) + .catch((e) => { + done(e) + }) + } else if (err != null) { + done(err) + } else { + done() + } + }) + } else { + done() + } + }) + + describe('Room membership event', () => { + let spyOnLoggerInfo: jest.SpyInstance + + let roomIdOnlyLocalUsers: string + const localUsersRoomInvitations = [ + '@lskywalker:example.com', + '@okenobi:example.com' + ] + const externalUsersRoomInvitations = [ + '@myoda:external.com', + '@hsolo:external.com' + ] + let roomIdWithExternalUsers: string + + beforeAll((done) => { + spyOnLoggerInfo = jest.spyOn(twakeServer.logger, 'info') + createRoom( + tokens.askywalker, + localUsersRoomInvitations, + 'room only local users' + ) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((roomId) => { + roomIdOnlyLocalUsers = roomId + + return Promise.all( + // eslint-disable-next-line @typescript-eslint/promise-function-async + localUsersRoomInvitations.map((matrixUserId) => { + const ldapUid = ( + matrixUserId.match(/^@(.*):/) as RegExpMatchArray + )[1] + return joinRoom( + roomId, + tokens[ldapUid as keyof typeof tokens], + matrixExampleServer + ) + }) + ) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((_) => { + return createRoom( + tokens.askywalker, + localUsersRoomInvitations.concat(externalUsersRoomInvitations), + 'room with external users' + ) + }) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then((roomId) => { + roomIdWithExternalUsers = roomId + return Promise.all( + localUsersRoomInvitations + // eslint-disable-next-line @typescript-eslint/promise-function-async + .map((matrixUserId) => { + const ldapUid = ( + matrixUserId.match(/^@(.*):/) as RegExpMatchArray + )[1] + return joinRoom( + roomId, + tokens[ldapUid as keyof typeof tokens], + matrixExampleServer + ) + }) + .concat( + // eslint-disable-next-line @typescript-eslint/promise-function-async + externalUsersRoomInvitations.map((matrixUserId) => { + const ldapUid = ( + matrixUserId.match(/^@(.*):/) as RegExpMatchArray + )[1] + return joinRoom( + roomId, + tokensExternal[ldapUid as keyof typeof tokensExternal], + matrixExternalServer + ) + }) + ) + ) + }) + .then((_) => { + done() + }) + .catch((e) => { + done(e) + }) + }) + + it('should not remove room if it still contains local users members', async () => { + const response = fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixExampleServer}/_matrix/client/v3/rooms/${roomIdOnlyLocalUsers}/leave` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${tokens.lskywalker}` + } + } + ) + expect((await response).status).toEqual(200) + await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve() + }, 3000) + }) + const rooms = await twakeServer.matrixDb.get('rooms' as any, ['*'], { + room_id: roomIdOnlyLocalUsers + }) + expect(rooms.length).toEqual(1) + }) + + it('should remove room after all local users members left it', async () => { + let rooms = await twakeServer.matrixDb.get('rooms' as any, ['*'], { + room_id: roomIdOnlyLocalUsers + }) + expect(rooms.length).toEqual(1) + + await Promise.all( + // eslint-disable-next-line @typescript-eslint/promise-function-async + ['askywalker', 'okenobi'].map((ldapUid) => + fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixExampleServer}/_matrix/client/v3/rooms/${roomIdOnlyLocalUsers}/leave` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${ + tokens[ldapUid as keyof typeof tokens] + }` + } + } + ) + ) + ) + await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve() + }, 3000) + }) + rooms = await twakeServer.matrixDb.get('rooms' as any, ['*'], { + room_id: roomIdOnlyLocalUsers + }) + expect(rooms.length).toEqual(0) + expect(spyOnLoggerInfo).toHaveBeenCalledTimes(1) + expect(spyOnLoggerInfo).toHaveBeenCalledWith( + '{"kicked_users":[],"failed_to_kick_users":[],"local_aliases":[],"new_room_id":null}', + { + matrixUserId: '@twake:example.com', + httpMethod: 'DELETE', + requestUrl: `https://matrix.example.com:446/_synapse/admin/v1/rooms/${roomIdOnlyLocalUsers}`, + status: 200 + } + ) + }) + + it('should remove room after all local users members left it even if there still are external users as members', async () => { + let rooms = await twakeServer.matrixDb.get('rooms' as any, ['*'], { + room_id: roomIdWithExternalUsers + }) + expect(rooms.length).toEqual(1) + + await Promise.all( + // eslint-disable-next-line @typescript-eslint/promise-function-async + ['askywalker', 'okenobi', 'lskywalker'].map((ldapUid) => + fetch.default( + encodeURI( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `https://${matrixExampleServer}/_matrix/client/v3/rooms/${roomIdWithExternalUsers}/leave` + ), + { + method: 'POST', + headers: { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + Authorization: `Bearer ${ + tokens[ldapUid as keyof typeof tokens] + }` + } + } + ) + ) + ) + await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve() + }, 3000) + }) + rooms = await twakeServer.matrixDb.get('rooms' as any, ['*'], { + room_id: roomIdWithExternalUsers + }) + expect(rooms.length).toEqual(0) + expect(spyOnLoggerInfo).toHaveBeenCalledTimes(1) + expect(spyOnLoggerInfo).toHaveBeenCalledWith( + '{"kicked_users":[],"failed_to_kick_users":[],"local_aliases":[],"new_room_id":null}', + { + matrixUserId: '@twake:example.com', + httpMethod: 'DELETE', + requestUrl: `https://matrix.example.com:446/_synapse/admin/v1/rooms/${roomIdWithExternalUsers}`, + status: 200 + } + ) + }) + }) + }) + + describe('Error cases tests', () => { + let spyOnLoggerError: jest.SpyInstance + + beforeAll((done) => { + buildUserDB(errorCasesConfig as Config) + // eslint-disable-next-line @typescript-eslint/promise-function-async + .then(() => { + done() + }) + .catch((e) => { + done(e) + }) + }) + + afterAll(() => { + const filesToDelete: string[] = [ + path.join(pathToTestDataFolder, 'matrix.db'), + path.join(pathToTestDataFolder, 'twake.db'), + path.join(pathToTestDataFolder, 'user.db') + ] + filesToDelete.forEach((path: string) => { + if (fs.existsSync(path)) { + fs.unlinkSync(path) + } + }) + }) + + describe('Hooks initialization', () => { + let twakeServerDown: TwakeServer + + afterEach(() => { + jest.restoreAllMocks() + twakeServerDown.cleanJobs() + }) + + it('should log an error if insert application server account as homeserver admin throws an error', async () => { + const error = new Error('Insert failed') + jest.spyOn(MatrixDB.prototype, 'insert').mockRejectedValue(error) + try { + twakeServerDown = new TwakeServer(errorCasesConfig as Config) + spyOnLoggerError = jest.spyOn(twakeServerDown.logger, 'error') + await twakeServerDown.ready + } catch (e) { + expect(spyOnLoggerError).toHaveBeenCalledTimes(1) + expect(spyOnLoggerError).toHaveBeenCalledWith( + 'Unable to initialize server', + { error } + ) + } + }) + + it('should log an error if insert application server account as homeserver does not return results', async () => { + jest.spyOn(MatrixDB.prototype, 'insert').mockResolvedValue([]) + try { + twakeServerDown = new TwakeServer(errorCasesConfig as Config) + spyOnLoggerError = jest.spyOn(twakeServerDown.logger, 'error') + await twakeServerDown.ready + } catch (e) { + expect(spyOnLoggerError).toHaveBeenCalledTimes(1) + expect(spyOnLoggerError).toHaveBeenCalledWith( + 'Unable to initialize server', + { + error: new Error( + 'Set @twake:example.com as Matrix homeserver admin failed' + ) + } + ) + } + }) + }) + + describe('Room membership event', () => { + beforeAll((done) => { + twakeServer = new TwakeServer(errorCasesConfig as Config) + spyOnLoggerError = jest.spyOn(twakeServer.logger, 'error') + app = express() + twakeServer.ready + .then(() => { + app.use(twakeServer.endpoints) + expressTwakeServer = app.listen(3003, () => { + done() + }) + }) + .catch((e) => { + done(e) + }) + }) + + afterEach(() => { + jest.clearAllMocks() + }) + + afterAll((done) => { + if (twakeServer != null) twakeServer.cleanJobs() + if (expressTwakeServer != null) { + expressTwakeServer.close((err) => { + if (err != null) { + done(err) + } else { + done() + } + }) + } else { + done() + } + }) + + it("should log an error if getting room's memberships throws an error when a member leaves the room", async () => { + const error = new Error('Get room memberships failed') + jest.spyOn(twakeServer.matrixDb, 'get').mockRejectedValue(error) + + twakeServer.applicationServer.emit( + 'state event | type: m.room.member', + { content: { membership: 'leave' } } + ) + await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve() + }, 3000) + }) + expect(spyOnLoggerError).toHaveBeenCalledTimes(1) + expect(spyOnLoggerError).toHaveBeenCalledWith(error) + }) + + it('should log an error if delete empty room request throws an error', async () => { + const error = new Error('Delete room request failed') + jest.spyOn(twakeServer.matrixDb, 'get').mockResolvedValue([]) + jest.spyOn(fetch, 'default').mockRejectedValue(error) + twakeServer.applicationServer.emit( + 'state event | type: m.room.member', + { content: { membership: 'leave' } } + ) + await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve() + }, 3000) + }) + expect(spyOnLoggerError).toHaveBeenCalledTimes(1) + expect(spyOnLoggerError).toHaveBeenCalledWith(error) + }) + + it('should log an error if parsing delete empty room request body throws an error', async () => { + const error = new Error('error on parsing response body') + jest.spyOn(twakeServer.matrixDb, 'get').mockResolvedValue([]) + jest.spyOn(fetch, 'default').mockResolvedValue({ + json: async () => { + throw error + }, + status: 200 + } as unknown as fetch.Response) + twakeServer.applicationServer.emit( + 'state event | type: m.room.member', + { content: { membership: 'leave' } } + ) + await new Promise((resolve, _reject) => { + setTimeout(() => { + resolve() + }, 3000) + }) + expect(spyOnLoggerError).toHaveBeenCalledTimes(1) + expect(spyOnLoggerError).toHaveBeenCalledWith(error) + }) + }) + }) +}) diff --git a/packages/tom-server/src/hooks/index.ts b/packages/tom-server/src/hooks/index.ts new file mode 100644 index 00000000..b9a7f5a1 --- /dev/null +++ b/packages/tom-server/src/hooks/index.ts @@ -0,0 +1,45 @@ +import { type TwakeLogger } from '@twake/logger' +import type MatrixApplicationServer from '@twake/matrix-application-server' +import { type MatrixDB } from '@twake/matrix-identity-server' +import { type Config } from '../types' +import { OnRoomMembershipEvent } from './callback/on-room-membership-event' +import { MatrixDBRepository } from './repositories/matrix-db.repository' + +export type CallbackHooks = OnRoomMembershipEvent + +export class TwakeServerHooks { + callbackHooks: CallbackHooks[] + ready: Promise + constructor( + applicationServer: MatrixApplicationServer, + matrixDb: MatrixDB, + conf: Config, + logger: TwakeLogger + ) { + this.callbackHooks = [] + const matrixDbRepository = new MatrixDBRepository( + matrixDb, + conf.server_name + ) + this.ready = new Promise((resolve, reject) => { + matrixDbRepository + .addMatrixUserAdmin( + `@${applicationServer.appServiceRegistration.senderLocalpart}:${conf.server_name}` + ) + .then(() => { + this.callbackHooks.push( + new OnRoomMembershipEvent( + applicationServer, + matrixDbRepository, + conf, + logger + ) + ) + resolve() + }) + .catch((e) => { + reject(e) + }) + }) + } +} diff --git a/packages/tom-server/src/hooks/repositories/interfaces/matrix-db-repository.interface.ts b/packages/tom-server/src/hooks/repositories/interfaces/matrix-db-repository.interface.ts new file mode 100644 index 00000000..0c6a5738 --- /dev/null +++ b/packages/tom-server/src/hooks/repositories/interfaces/matrix-db-repository.interface.ts @@ -0,0 +1,6 @@ +import { type DbGetResult } from '@twake/matrix-identity-server' + +export interface IMatrixDBRepository { + addMatrixUserAdmin: (matrixAddress: string) => Promise + hasRoomLocalServerUsers: (roomId: string) => Promise +} diff --git a/packages/tom-server/src/hooks/repositories/matrix-db.repository.ts b/packages/tom-server/src/hooks/repositories/matrix-db.repository.ts new file mode 100644 index 00000000..c32fff3a --- /dev/null +++ b/packages/tom-server/src/hooks/repositories/matrix-db.repository.ts @@ -0,0 +1,47 @@ +import { type DbGetResult, type MatrixDB } from '@twake/matrix-identity-server' +import lodash from 'lodash' +import { type IMatrixDBRepository } from './interfaces/matrix-db-repository.interface' + +const { groupBy, mapValues, escapeRegExp } = lodash + +export class MatrixDBRepository implements IMatrixDBRepository { + constructor( + private readonly _matrixDb: MatrixDB, + private readonly _matrixServer: string + ) {} + + async addMatrixUserAdmin(matrixAddress: string): Promise { + const result = await this._matrixDb.insert('users', { + name: matrixAddress, + admin: 1 + }) + if (result.length === 0) { + throw new Error(`Set ${matrixAddress} as Matrix homeserver admin failed`) + } + return result + } + + async hasRoomLocalServerUsers(roomId: string): Promise { + const userIdLocalServerRegExp = new RegExp( + `^@[^:]*:${escapeRegExp(this._matrixServer)}$` + ) + const localServerUsers = ( + (await this._matrixDb.get('room_memberships', ['user_id', 'membership'], { + room_id: roomId + })) as Array<{ user_id: string; membership: string }> + ).filter( + (membershipDetail) => + membershipDetail.user_id.match(userIdLocalServerRegExp) != null + ) + + const currentMembershipByUserId = mapValues( + groupBy(localServerUsers, 'user_id'), + (membershipsDetails) => + membershipsDetails.map((detail) => detail.membership).pop() + ) + + return Object.keys(currentMembershipByUserId).some( + (userId) => currentMembershipByUserId[userId] !== 'leave' + ) + } +} diff --git a/packages/tom-server/src/index.test.ts b/packages/tom-server/src/index.test.ts index 78214706..1c224516 100644 --- a/packages/tom-server/src/index.test.ts +++ b/packages/tom-server/src/index.test.ts @@ -139,12 +139,9 @@ describe('Tom-server', () => { }) }) - describe('Application server', () => { - test('application server endpoint should not be available', async () => { - let response = await request(app).post('/_twake/app/v1/rooms') - expect(response.statusCode).toBe(404) - - response = await request(app).put('/_matrix/app/v1/transactions/1') + describe('Administration Console API', () => { + test('administration console endpoint should not be available', async () => { + const response = await request(app).post('/_twake/app/v1/rooms') expect(response.statusCode).toBe(404) }) }) diff --git a/packages/tom-server/src/index.ts b/packages/tom-server/src/index.ts index ee9dd5b5..12826e8a 100644 --- a/packages/tom-server/src/index.ts +++ b/packages/tom-server/src/index.ts @@ -4,12 +4,14 @@ import { type Config as LoggerConfig, type TwakeLogger } from '@twake/logger' +import MatrixApplicationServer from '@twake/matrix-application-server' import { MatrixDB } from '@twake/matrix-identity-server' import { Router } from 'express' import fs from 'fs' -import AppServiceAPI from './application-server' +import AdministrationConsoleAPI from './administration-console-api' import defaultConfig from './config.json' import initializeDb, { type TwakeDB } from './db' +import { TwakeServerHooks } from './hooks' import IdServer from './identity-server' import mutualRoomsAPIRouter from './mutual-rooms-api' import privateNoteApiRouter from './private-note-api' @@ -28,6 +30,8 @@ export default class TwakeServer { matrixDb: MatrixDB ready!: Promise idServer!: TwakeIdentityServer + applicationServer: MatrixApplicationServer + hooks!: TwakeServerHooks constructor( conf?: Partial, @@ -40,6 +44,11 @@ export default class TwakeServer { this._getConfigurationFile(conf) ) as Config this.logger = logger ?? getLogger(this.conf as unknown as LoggerConfig) + this.applicationServer = new MatrixApplicationServer( + this.conf, + confDesc, + this.logger + ) this.matrixDb = new MatrixDB(this.conf, this.logger) this.idServer = new IdServer( this.matrixDb, @@ -49,14 +58,21 @@ export default class TwakeServer { ) this.endpoints = Router() this.ready = new Promise((resolve, reject) => { - this._initServer(confDesc) + this._initServer() .then(() => { if ( process.env.ADDITIONAL_FEATURES === 'true' || (this.conf.additional_features as boolean) ) { - const appServiceApi = new AppServiceAPI(this, confDesc, this.logger) - this.endpoints.use(appServiceApi.router.routes) + const adminConsoleApi = new AdministrationConsoleAPI( + this.applicationServer, + this.idServer.db, + this.idServer.userDB, + this.matrixDb, + this.conf, + this.logger + ) + this.endpoints.use(adminConsoleApi.endpoints) } resolve(true) }) @@ -95,72 +111,68 @@ export default class TwakeServer { return undefined } - private async _initServer(confDesc?: ConfigDescription): Promise { - try { - await this.idServer.ready - await this.matrixDb.ready - await initializeDb(this) + private async _initServer(): Promise { + await this.idServer.ready + await this.matrixDb.ready + await initializeDb(this) - const vaultServer = new VaultServer( - this.idServer.db, - this.idServer.authenticate - ) - const wellKnown = new WellKnown(this.conf) - const privateNoteApi = privateNoteApiRouter( - this.idServer.db, - this.conf, - this.idServer.authenticate, - this.logger - ) - const mutualRoolsApi = mutualRoomsAPIRouter( - this.conf, - this.matrixDb.db, - this.idServer.authenticate, - this.logger - ) - const roomTagsApi = roomTagsAPIRouter( - this.idServer.db, - this.matrixDb.db, - this.conf, - this.idServer.authenticate, - this.logger - ) - const userInfoApi = userInfoAPIRouter( - this.idServer, - this.conf, - this.logger - ) - - const smsApi = smsApiRouter( - this.conf, - this.idServer.authenticate, - this.logger - ) + const vaultServer = new VaultServer( + this.idServer.db, + this.idServer.authenticate + ) + const wellKnown = new WellKnown(this.conf) + const privateNoteApi = privateNoteApiRouter( + this.idServer.db, + this.conf, + this.idServer.authenticate, + this.logger + ) + const mutualRoolsApi = mutualRoomsAPIRouter( + this.conf, + this.matrixDb.db, + this.idServer.authenticate, + this.logger + ) + const roomTagsApi = roomTagsAPIRouter( + this.idServer.db, + this.matrixDb.db, + this.conf, + this.idServer.authenticate, + this.logger + ) + const userInfoApi = userInfoAPIRouter(this.idServer, this.conf, this.logger) - this.endpoints.use(privateNoteApi) - this.endpoints.use(mutualRoolsApi) - this.endpoints.use(vaultServer.endpoints) - this.endpoints.use(roomTagsApi) - this.endpoints.use(userInfoApi) - this.endpoints.use(smsApi) + const smsApi = smsApiRouter( + this.conf, + this.idServer.authenticate, + this.logger + ) - Object.keys(this.idServer.api.get).forEach((k) => { - this.endpoints.get(k, this.idServer.api.get[k]) - }) - Object.keys(this.idServer.api.post).forEach((k) => { - this.endpoints.post(k, this.idServer.api.post[k]) - }) - this.endpoints.use(vaultServer.endpoints) - Object.keys(wellKnown.api.get).forEach((k) => { - this.endpoints.get(k, wellKnown.api.get[k]) - }) + this.endpoints.use(this.applicationServer.router.routes) + this.endpoints.use(privateNoteApi) + this.endpoints.use(mutualRoolsApi) + this.endpoints.use(vaultServer.endpoints) + this.endpoints.use(roomTagsApi) + this.endpoints.use(userInfoApi) + this.endpoints.use(smsApi) - return true - } catch (error) { - /* istanbul ignore next */ - this.logger.error(`Unable to initialize server`, { error }) - /* istanbul ignore next */ - throw Error('Unable to initialize server', { cause: error }) - } + Object.keys(this.idServer.api.get).forEach((k) => { + this.endpoints.get(k, this.idServer.api.get[k]) + }) + Object.keys(this.idServer.api.post).forEach((k) => { + this.endpoints.post(k, this.idServer.api.post[k]) + }) + this.endpoints.use(vaultServer.endpoints) + Object.keys(wellKnown.api.get).forEach((k) => { + this.endpoints.get(k, wellKnown.api.get[k]) + }) + this.hooks = new TwakeServerHooks( + this.applicationServer, + this.matrixDb, + this.conf, + this.logger + ) + await this.hooks.ready + return true } } diff --git a/packages/tom-server/src/vault-api/__testData__/buildTokenTable.ts b/packages/tom-server/src/vault-api/__testData__/buildTokenTable.ts index ae1f0b07..52245c36 100644 --- a/packages/tom-server/src/vault-api/__testData__/buildTokenTable.ts +++ b/packages/tom-server/src/vault-api/__testData__/buildTokenTable.ts @@ -1,6 +1,6 @@ +import sqlite3 from 'sqlite3' import { type Config } from '../../types' import { type tokenDetail } from '../middlewares/auth' -import sqlite3 from 'sqlite3' const token: tokenDetail = { value: 'accessTokenddddddddddddddddddddddddddddddddddddddddddddddddddddd', @@ -36,7 +36,7 @@ const buildTokenTable = (conf: Config): Promise => { ) ) - matrixDbManager.run('CREATE TABLE users (uid varchar(8), name varchar(32), mobile varchar(12), mail varchar(32))') + matrixDbManager.run('CREATE TABLE users (uid varchar(8), name varchar(32), mobile varchar(12), mail varchar(32), admin SMALLINT DEFAULT 0 NOT NULL)') }) }