Use the shared secret registration API directly (#7774)

* Use the shared secret registration API directly

rather than invoking the synapse module to do it. It's probably
a bit simpler, if anything, and allows for synapse to be run in
a separate container (or rather, avoids the javascript having to have
a copy of synapse source & server config).

* Make registration secret required

Update commander (8 major versions!) to get requiredOption

* Wrong options object :/
This commit is contained in:
David Baker 2022-02-11 17:03:22 +00:00 committed by GitHub
parent 0e3b559671
commit 1c3507bc11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 49 deletions

View file

@ -11,7 +11,7 @@
"license": "ISC",
"dependencies": {
"cheerio": "^1.0.0-rc.2",
"commander": "^2.19.0",
"commander": "^9",
"puppeteer": "10.0.0",
"request": "^2.88.0",
"request-promise-native": "^1.0.7",

View file

@ -32,9 +32,10 @@ handle_error() {
trap 'handle_error' ERR
./synapse/start.sh
reg_secret=`./synapse/getcfg.sh registration_shared_secret`
if [ $has_custom_app -ne "1" ]; then
./element/start.sh
fi
yarn build
node lib/start.js $@
node lib/start.js --registration-shared-secret=$reg_secret $@
stop_servers

View file

@ -15,29 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { exec } from 'child_process';
import request = require('request-promise-native');
import * as crypto from 'crypto';
import { RestSession } from './session';
import { RestMultiSession } from './multi';
interface ExecResult {
stdout: string;
stderr: string;
}
function execAsync(command: string, options: Parameters<typeof exec>[1]): Promise<ExecResult> {
return new Promise((resolve, reject) => {
exec(command, options, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve({ stdout, stderr });
}
});
});
}
export interface Credentials {
accessToken: string;
homeServer: string;
@ -47,7 +30,7 @@ export interface Credentials {
}
export class RestSessionCreator {
constructor(private readonly synapseSubdir: string, private readonly hsUrl: string, private readonly cwd: string) {}
constructor(private readonly hsUrl: string, private readonly regSecret: string) {}
public async createSessionRange(usernames: string[], password: string,
groupName: string): Promise<RestMultiSession> {
@ -64,21 +47,25 @@ export class RestSessionCreator {
}
private async register(username: string, password: string): Promise<void> {
const registerArgs = [
'-c homeserver.yaml',
`-u ${username}`,
`-p ${password}`,
'--no-admin',
this.hsUrl,
];
const registerCmd = `./register_new_matrix_user ${registerArgs.join(' ')}`;
const allCmds = [
`cd ${this.synapseSubdir}`,
". ./activate",
registerCmd,
].join(' && ');
// get a nonce
const regUrl = `${this.hsUrl}/_synapse/admin/v1/register`;
const nonceResp = await request.get({ uri: regUrl, json: true });
await execAsync(allCmds, { cwd: this.cwd, encoding: 'utf-8' });
const mac = crypto.createHmac('sha1', this.regSecret).update(
`${nonceResp.nonce}\0${username}\0${password}\0notadmin`,
).digest('hex');
await request.post({
uri: regUrl,
json: true,
body: {
nonce: nonceResp.nonce,
username,
password,
mac,
admin: false,
},
});
}
private async authenticate(username: string, password: string): Promise<Credentials> {

View file

@ -15,12 +15,14 @@ limitations under the License.
*/
import * as fs from "fs";
import program = require('commander');
import { Command } from "commander";
import { ElementSession } from './src/session';
import { scenario } from './src/scenario';
import { RestSessionCreator } from './src/rest/creator';
const program = new Command();
program
.option('--no-logs', "don't output logs, document html on error", false)
.option('--app-url [url]', "url to test", "http://localhost:5000")
@ -30,6 +32,7 @@ program
.option('--throttle-cpu [factor]', "factor to slow down the cpu with", parseFloat, 1.0)
.option('--no-sandbox', "same as puppeteer arg", false)
.option('--log-directory <dir>', 'a directory to dump html and network logs in when the tests fail')
.requiredOption('--registration-shared-secret <secret>', 'the secret to use for registering users')
.parse(process.argv);
const hsUrl = 'http://localhost:5005';
@ -37,12 +40,12 @@ const hsUrl = 'http://localhost:5005';
async function runTests() {
const sessions = [];
const options = {
slowMo: program.slowMo ? 20 : undefined,
devtools: program.devTools,
headless: !program.windowed,
slowMo: program.opts().slowMo ? 20 : undefined,
devtools: program.opts().devTools,
headless: !program.opts().windowed,
args: [],
};
if (!program.sandbox) {
if (!program.opts().sandbox) {
options.args.push('--no-sandbox', '--disable-setuid-sandbox');
}
if (process.env.CHROME_PATH) {
@ -52,13 +55,14 @@ async function runTests() {
}
const restCreator = new RestSessionCreator(
'../synapse/installations/consent/env/bin',
hsUrl,
__dirname,
program.opts().registrationSharedSecret,
);
async function createSession(username) {
const session = await ElementSession.create(username, options, program.appUrl, hsUrl, program.throttleCpu);
const session = await ElementSession.create(
username, options, program.opts().appUrl, hsUrl, program.opts().throttleCpu,
);
sessions.push(session);
return session;
}
@ -69,8 +73,8 @@ async function runTests() {
} catch (err) {
failure = true;
console.log('failure: ', err);
if (program.logDirectory) {
await writeLogs(sessions, program.logDirectory);
if (program.opts().logDirectory) {
await writeLogs(sessions, program.opts().logDirectory);
}
}

View file

@ -0,0 +1,17 @@
#!/bin/bash
set -e
if [ $# -eq 0 ]
then
echo "Prints a configuration directive from the synapse installation"
echo "Usage: getcfg.sh <synapse config file directive>"
exit 1
fi
# activate the virtualenv so we have pyyaml
BASE_DIR=$(cd $(dirname $0) && pwd)
cd $BASE_DIR
cd installations/consent/env/bin/
source activate
python -c "from yaml import load, Loader; import sys; print(load(sys.stdin, Loader=Loader)['$1'])" < homeserver.yaml

View file

@ -146,10 +146,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
commander@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
commander@^9:
version "9.0.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.0.0.tgz#86d58f24ee98126568936bd1d3574e0308a99a40"
integrity sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==
concat-map@0.0.1:
version "0.0.1"