Loading scripts/authdb-bootstrap.sh +5 −2 Changes for scripts/authdb-bootstrap.sh: 5 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -10,8 +10,10 @@ # proxyplus.auditor proxyplus.readonly_operator # proxyplus.http_proxy_user proxyplus.smtp_relay_user # # Usage: authdb-bootstrap.sh <authdb-url> <admin-username> <data-dir> # Usage: [CLIENT_NAME=<name>] authdb-bootstrap.sh <authdb-url> <admin-username> <data-dir> # Example: authdb-bootstrap.sh http://127.0.0.1:8080/api/<domainid> admin /var/lib/proxyplus # CLIENT_NAME names ProxyPlus's service client in authdb (default: proxyplus-service); if # that name is taken, proxyplus-bootstrap asks for another one. set -eu Loading @@ -30,4 +32,5 @@ mkdir -p "$DATA_DIR" # Creates the proxyplus-service Client-Credential, creates one authdb GPO per permission in # docs/ROLES.md, and registers permission->GPO-id into ProxyPlus's own ConfigStore at # $DATA_DIR -- see tools/proxyplus-bootstrap.cpp for exactly what each step does. exec ./proxyplus-bootstrap "$AUTHDB_URL" "$ADMIN_USER" "$ADMIN_PASSWORD" "$DATA_DIR" exec ./proxyplus-bootstrap ${CLIENT_NAME:+--client-name "$CLIENT_NAME"} \ "$AUTHDB_URL" "$ADMIN_USER" "$ADMIN_PASSWORD" "$DATA_DIR" tools/proxyplus-bootstrap.cpp +59 −8 Changes for tools/proxyplus-bootstrap.cpp: 59 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -15,14 +15,23 @@ // ProxyPlus's own binary ConfigStore at <data-dir> (never into authdb itself). // // Usage: // proxyplus-bootstrap <authdb-url> <admin-username> <admin-password> <data-dir> // proxyplus-bootstrap [--insecure] [--client-name <name>] // <authdb-url> <admin-username> <admin-password> <data-dir> // // The service client is named "proxyplus-service" unless --client-name says otherwise. // If authdb already has a client of that name (an earlier run, another ProxyPlus instance), // the tool asks for another one when run on a terminal, and aborts otherwise. #include <algorithm> #include <cctype> #include <fstream> #include <iostream> #include <map> #include <string> #include <vector> #include <unistd.h> #include <authdb/client.h> #include <uuidp.h> Loading Loading @@ -111,27 +120,56 @@ const std::vector<PermissionSpec> kPermissions = { {"proxyplus.super_admin", "proxyplus.security_admin"}}, }; // authdb's addConnection() error for a taken client name ("Create Client: Clientname // already Exists aborting!"), matched loosely so a reworded message still counts. bool isNameTaken(const std::string &error) { std::string lower(error); std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c) { return std::tolower(c); }); return lower.find("already exist") != std::string::npos; } // Asks for another client name on the terminal; empty if there is none (not // interactive, EOF, or an empty answer). std::string askOtherClientName(const std::string &taken) { if (!isatty(STDIN_FILENO)) return ""; std::cerr << "authdb already has a client named '" << taken << "'." << std::endl << "Another name for this ProxyPlus service client (empty to abort): " << std::flush; std::string name; if (!std::getline(std::cin, name)) return ""; name.erase(0, name.find_first_not_of(" \t")); name.erase(name.find_last_not_of(" \t\r") + 1); return name; } } // namespace int main(int argc, char **argv) { // --insecure may appear anywhere among the positional args; strip it out first so the // remaining argv indices below stay fixed regardless of where the caller put it. // The options may appear anywhere among the positional args; strip them out first so the // remaining argv indices below stay fixed regardless of where the caller put them. std::vector<std::string> args; bool tlsVerify = true; std::string serviceClientName = "proxyplus-service"; for (int i = 1; i < argc; ++i) { if (std::string(argv[i]) == "--insecure") { std::string arg = argv[i]; if (arg == "--insecure") { tlsVerify = false; } else if (arg == "--client-name" && i + 1 < argc) { serviceClientName = argv[++i]; } else { args.push_back(argv[i]); args.push_back(arg); } } if (args.size() < 4) { if (args.size() < 4 || serviceClientName.empty()) { std::cerr << "usage: " << argv[0] << " [--insecure] <authdb-url> <admin-username> <admin-password> <data-dir>" << " [--insecure] [--client-name <name>]" " <authdb-url> <admin-username> <admin-password> <data-dir>" << std::endl; std::cerr << " --insecure skip TLS peer verification (needed when authdb is reached" " by an IP not covered by its certificate's SAN)" << std::endl; std::cerr << " --client-name name of the service client to create in authdb" " (default: proxyplus-service)" << std::endl; return 1; } std::string url = args[0], username = args[1], password = args[2], dataDir = args[3]; Loading @@ -153,18 +191,31 @@ int main(int argc, char **argv) { return 1; } const std::string serviceClientName = "proxyplus-service"; uuid::uuid secretSeed; secretSeed.generate(); std::string serviceClientSecret = secretSeed.c_str(); std::string clientId; for (;;) { try { clientId = admin.addConnection(serviceClientName, serviceClientSecret); break; } catch (const std::exception &e) { if (isNameTaken(e.what())) { std::string other = askOtherClientName(serviceClientName); if (!other.empty()) { serviceClientName = other; continue; } std::cerr << "addConnection failed: client name '" << serviceClientName << "' already exists in authdb -- choose another with --client-name" << std::endl; return 1; } std::cerr << "addConnection failed: " << e.what() << std::endl; return 1; } } std::cerr << "created service client '" << serviceClientName << "' (id=" << clientId << ")" << std::endl; Loading Loading
scripts/authdb-bootstrap.sh +5 −2 Changes for scripts/authdb-bootstrap.sh: 5 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -10,8 +10,10 @@ # proxyplus.auditor proxyplus.readonly_operator # proxyplus.http_proxy_user proxyplus.smtp_relay_user # # Usage: authdb-bootstrap.sh <authdb-url> <admin-username> <data-dir> # Usage: [CLIENT_NAME=<name>] authdb-bootstrap.sh <authdb-url> <admin-username> <data-dir> # Example: authdb-bootstrap.sh http://127.0.0.1:8080/api/<domainid> admin /var/lib/proxyplus # CLIENT_NAME names ProxyPlus's service client in authdb (default: proxyplus-service); if # that name is taken, proxyplus-bootstrap asks for another one. set -eu Loading @@ -30,4 +32,5 @@ mkdir -p "$DATA_DIR" # Creates the proxyplus-service Client-Credential, creates one authdb GPO per permission in # docs/ROLES.md, and registers permission->GPO-id into ProxyPlus's own ConfigStore at # $DATA_DIR -- see tools/proxyplus-bootstrap.cpp for exactly what each step does. exec ./proxyplus-bootstrap "$AUTHDB_URL" "$ADMIN_USER" "$ADMIN_PASSWORD" "$DATA_DIR" exec ./proxyplus-bootstrap ${CLIENT_NAME:+--client-name "$CLIENT_NAME"} \ "$AUTHDB_URL" "$ADMIN_USER" "$ADMIN_PASSWORD" "$DATA_DIR"
tools/proxyplus-bootstrap.cpp +59 −8 Changes for tools/proxyplus-bootstrap.cpp: 59 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -15,14 +15,23 @@ // ProxyPlus's own binary ConfigStore at <data-dir> (never into authdb itself). // // Usage: // proxyplus-bootstrap <authdb-url> <admin-username> <admin-password> <data-dir> // proxyplus-bootstrap [--insecure] [--client-name <name>] // <authdb-url> <admin-username> <admin-password> <data-dir> // // The service client is named "proxyplus-service" unless --client-name says otherwise. // If authdb already has a client of that name (an earlier run, another ProxyPlus instance), // the tool asks for another one when run on a terminal, and aborts otherwise. #include <algorithm> #include <cctype> #include <fstream> #include <iostream> #include <map> #include <string> #include <vector> #include <unistd.h> #include <authdb/client.h> #include <uuidp.h> Loading Loading @@ -111,27 +120,56 @@ const std::vector<PermissionSpec> kPermissions = { {"proxyplus.super_admin", "proxyplus.security_admin"}}, }; // authdb's addConnection() error for a taken client name ("Create Client: Clientname // already Exists aborting!"), matched loosely so a reworded message still counts. bool isNameTaken(const std::string &error) { std::string lower(error); std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c) { return std::tolower(c); }); return lower.find("already exist") != std::string::npos; } // Asks for another client name on the terminal; empty if there is none (not // interactive, EOF, or an empty answer). std::string askOtherClientName(const std::string &taken) { if (!isatty(STDIN_FILENO)) return ""; std::cerr << "authdb already has a client named '" << taken << "'." << std::endl << "Another name for this ProxyPlus service client (empty to abort): " << std::flush; std::string name; if (!std::getline(std::cin, name)) return ""; name.erase(0, name.find_first_not_of(" \t")); name.erase(name.find_last_not_of(" \t\r") + 1); return name; } } // namespace int main(int argc, char **argv) { // --insecure may appear anywhere among the positional args; strip it out first so the // remaining argv indices below stay fixed regardless of where the caller put it. // The options may appear anywhere among the positional args; strip them out first so the // remaining argv indices below stay fixed regardless of where the caller put them. std::vector<std::string> args; bool tlsVerify = true; std::string serviceClientName = "proxyplus-service"; for (int i = 1; i < argc; ++i) { if (std::string(argv[i]) == "--insecure") { std::string arg = argv[i]; if (arg == "--insecure") { tlsVerify = false; } else if (arg == "--client-name" && i + 1 < argc) { serviceClientName = argv[++i]; } else { args.push_back(argv[i]); args.push_back(arg); } } if (args.size() < 4) { if (args.size() < 4 || serviceClientName.empty()) { std::cerr << "usage: " << argv[0] << " [--insecure] <authdb-url> <admin-username> <admin-password> <data-dir>" << " [--insecure] [--client-name <name>]" " <authdb-url> <admin-username> <admin-password> <data-dir>" << std::endl; std::cerr << " --insecure skip TLS peer verification (needed when authdb is reached" " by an IP not covered by its certificate's SAN)" << std::endl; std::cerr << " --client-name name of the service client to create in authdb" " (default: proxyplus-service)" << std::endl; return 1; } std::string url = args[0], username = args[1], password = args[2], dataDir = args[3]; Loading @@ -153,18 +191,31 @@ int main(int argc, char **argv) { return 1; } const std::string serviceClientName = "proxyplus-service"; uuid::uuid secretSeed; secretSeed.generate(); std::string serviceClientSecret = secretSeed.c_str(); std::string clientId; for (;;) { try { clientId = admin.addConnection(serviceClientName, serviceClientSecret); break; } catch (const std::exception &e) { if (isNameTaken(e.what())) { std::string other = askOtherClientName(serviceClientName); if (!other.empty()) { serviceClientName = other; continue; } std::cerr << "addConnection failed: client name '" << serviceClientName << "' already exists in authdb -- choose another with --client-name" << std::endl; return 1; } std::cerr << "addConnection failed: " << e.what() << std::endl; return 1; } } std::cerr << "created service client '" << serviceClientName << "' (id=" << clientId << ")" << std::endl; Loading