From 6a4875c5ec17bb48200b7a340ce4be8f0dc25699 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sun, 8 Nov 2020 18:27:24 +0100 Subject: [PATCH] Add bootstrap generate-user-token command Add command to generate a user token for connecting to the master server web interface. This servers as an alternative to generating a control config for use with clusterioctl. --- packages/master/README.md | 7 +++++++ packages/master/master.js | 10 ++++++++++ test/integration/clusterio.js | 16 +++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/master/README.md b/packages/master/README.md index 99e76433..8e22c08c 100644 --- a/packages/master/README.md +++ b/packages/master/README.md @@ -110,6 +110,13 @@ exist in the cluster and grant it full cluster admin permission. You should be using your own Factorio multiplayer username here. +#### `bootstrap generate-user-token ` + +Generate an access token for logging in and possibly managing the +cluster from the given user account. This can be used both in the web +interface and as the `master_token` to connect with clusterioctl. + + #### `bootstrap create-ctl-config ` Creates a clusterioctl config for the given user with url and token set diff --git a/packages/master/master.js b/packages/master/master.js index f880e59d..37efa82c 100755 --- a/packages/master/master.js +++ b/packages/master/master.js @@ -1578,6 +1578,7 @@ async function startServer() { .command("bootstrap", "Bootstrap access to cluster", yargs => { yargs .command("create-admin ", "Create a cluster admin") + .command("generate-user-token ", "Generate authentication token for the given user") .command("create-ctl-config ", "Create clusterioctl config for the given user", yargs => { yargs.option("output", { describe: "Path to output config (- for stdout)", type: "string", @@ -1664,6 +1665,15 @@ async function startServer() { admin.isAdmin = true; await saveUsers(masterConfig.get("master.database_directory"), "users.json"); + } else if (subCommand === "generate-user-token") { + let user = db.users.get(args.name); + if (!user) { + console.error(`No user named '${args.name}'`); + process.exitCode = 1; + return; + } + console.log(user.createToken(masterConfig.get("master.auth_secret"))); + } else if (subCommand === "create-ctl-config") { let admin = db.users.get(args.name); if (!admin) { diff --git a/test/integration/clusterio.js b/test/integration/clusterio.js index b84f60ff..e9d80333 100644 --- a/test/integration/clusterio.js +++ b/test/integration/clusterio.js @@ -5,7 +5,7 @@ const path = require("path"); const libLink = require("@clusterio/lib/link"); -const { slowTest, get, execCtl, sendRcon, getControl, instancesDir } = require("./index"); +const { slowTest, get, exec, execCtl, sendRcon, getControl, instancesDir } = require("./index"); async function getInstances() { @@ -19,6 +19,20 @@ async function checkInstanceStatus(id, status) { } describe("Integration of Clusterio", function() { + describe("clusteriomaster", function() { + describe("bootstrap generate-user-token", function() { + it("work for existing user", async function() { + await exec("node ../../packages/master bootstrap generate-user-token test"); + }); + + it("fails if user does not exist", async function() { + await assert.rejects( + exec("node ../../packages/master bootstrap generate-user-token invalid") + ); + }); + }); + }); + describe("clusterioctl", function() { describe("slave list", function() { it("runs", async function() {