From 79a8b81babe567efb0ef93a83c44f5b182b32cce Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sun, 17 Dec 2023 14:39:20 -0500 Subject: [PATCH] Start setting up the account server This is about the minimum required to make the account server start. It doesn't fully work yet. --- .gitignore | 2 + compose.yml | 74 +++++++++ environment/account.env | 9 ++ environment/minio.env | 0 nginx/Dockerfile | 6 + nginx/account.conf | 9 ++ patches/account/dockerfile-run-build.patch | 14 ++ patches/account/entrypoint-fix-exec.patch | 10 ++ .../entrypoint-no-check-missing-config.patch | 20 +++ .../account/generate-keys-logger-fix.patch | 151 ++++++++++++++++++ .../configure-local-pretendo-host.patch | 14 ++ repos/mitmproxy-pretendo | 2 +- scripts/setup-environment.sh | 27 ++++ scripts/setup-submodule-patches.sh | 27 ++++ 14 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 compose.yml create mode 100644 environment/account.env create mode 100644 environment/minio.env create mode 100644 nginx/Dockerfile create mode 100644 nginx/account.conf create mode 100644 patches/account/dockerfile-run-build.patch create mode 100644 patches/account/entrypoint-fix-exec.patch create mode 100644 patches/account/entrypoint-no-check-missing-config.patch create mode 100644 patches/account/generate-keys-logger-fix.patch create mode 100644 patches/mitmproxy-pretendo/configure-local-pretendo-host.patch create mode 100755 scripts/setup-environment.sh create mode 100755 scripts/setup-submodule-patches.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c1cfe2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Local environment variables (used for secrets) +/environment/*.local.env diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..f03f104 --- /dev/null +++ b/compose.yml @@ -0,0 +1,74 @@ +name: pretendo-network +version: "3.8" +services: + mitmproxy-pretendo: + build: ./repos/mitmproxy-pretendo + ports: + # Proxy server + - 8080:8080 + # Mitmweb interface + - 127.0.0.1:8081:8081 + volumes: + - type: volume + source: mitmproxy-pretendo-data + target: /home/mitmproxy/.mitmproxy + command: mitmweb --web-host 0.0.0.0 + tty: true + + nginx: + build: ./nginx + ports: + - 80:80 + - 443:443 + + mongodb: + image: mongo:latest + ports: + # For connecting with mongosh or MongoDB Compass + - 127.0.0.1:27017:27017 + volumes: + - type: volume + source: mongodb-database + target: /data/db + + minio: + image: minio/minio:latest + ports: + # Web console + - 127.0.0.1:9090:9090 + env_file: + - ./environment/minio.env + - ./environment/minio.local.env + volumes: + - type: volume + source: minio-s3-data + target: /data + command: server /data --console-address ":9090" + + # redis: + # image: redis:latest + # volumes: + # - type: volume + # source: redis-data + # target: /data + # command: redis-server --save 60 1 --appendonly yes + + account: + build: ./repos/account + depends_on: + - mongodb + - minio + env_file: + - ./environment/account.env + - ./environment/account.local.env + volumes: + - type: volume + source: account-certificates + target: /app/certs + +volumes: + mitmproxy-pretendo-data: + mongodb-database: + minio-s3-data: + redis-data: + account-certificates: diff --git a/environment/account.env b/environment/account.env new file mode 100644 index 0000000..9240858 --- /dev/null +++ b/environment/account.env @@ -0,0 +1,9 @@ +GENERATE_NEW_KEYS=true +PN_ACT_PREFER_ENV_CONFIG=true +PN_ACT_CONFIG_HTTP_PORT=8080 +PN_ACT_CONFIG_MONGO_CONNECTION_STRING=mongodb://mongodb:27017/pretendo_account +PN_ACT_CONFIG_MONGOOSE_OPTION_useNewUrlParser=true +PN_ACT_CONFIG_MONGOOSE_OPTION_useUnifiedTopology=true +PN_ACT_CONFIG_S3_ENDPOINT=http://minio:9000 +PN_ACT_CONFIG_CDN_BASE_URL=https://account-cdn.pretendo.cc +PN_ACT_CONFIG_GRPC_PORT=5000 diff --git a/environment/minio.env b/environment/minio.env new file mode 100644 index 0000000..e69de29 diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000..01a0121 --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,6 @@ +FROM nginx:mainline-alpine + +RUN rm /etc/nginx/conf.d/default.conf +COPY * /etc/nginx/conf.d/ + +EXPOSE 80 443 diff --git a/nginx/account.conf b/nginx/account.conf new file mode 100644 index 0000000..035fc15 --- /dev/null +++ b/nginx/account.conf @@ -0,0 +1,9 @@ +server { + listen 80; + server_name account.pretendo.cc; + + location / { + proxy_pass http://account:8080; + proxy_set_header Host $host; + } +} diff --git a/patches/account/dockerfile-run-build.patch b/patches/account/dockerfile-run-build.patch new file mode 100644 index 0000000..1f5fcb6 --- /dev/null +++ b/patches/account/dockerfile-run-build.patch @@ -0,0 +1,14 @@ +diff --git i/Dockerfile w/Dockerfile +index a810a90..93c8f2a 100644 +--- i/Dockerfile ++++ w/Dockerfile +@@ -11,6 +11,8 @@ RUN npm install + + COPY . ./ + +-VOLUME [ "/app/config.json", "/app/certs" ] ++RUN npm run build ++ ++VOLUME [ "/app/certs" ] + + CMD ["sh", "entrypoint.sh"] diff --git a/patches/account/entrypoint-fix-exec.patch b/patches/account/entrypoint-fix-exec.patch new file mode 100644 index 0000000..76eb92f --- /dev/null +++ b/patches/account/entrypoint-fix-exec.patch @@ -0,0 +1,10 @@ +diff --git i/docker/entrypoint.sh w/docker/entrypoint.sh +index 2c6aa02..c9d3234 100644 +--- i/docker/entrypoint.sh ++++ w/docker/entrypoint.sh +@@ -25,4 +25,4 @@ for file in $keys; do + fi + done + +-exec node src/server.js ++exec node dist/server.js diff --git a/patches/account/entrypoint-no-check-missing-config.patch b/patches/account/entrypoint-no-check-missing-config.patch new file mode 100644 index 0000000..6f3d8e8 --- /dev/null +++ b/patches/account/entrypoint-no-check-missing-config.patch @@ -0,0 +1,20 @@ +diff --git i/docker/entrypoint.sh w/docker/entrypoint.sh +index 2c6aa02..b8c8d5a 100644 +--- i/docker/entrypoint.sh ++++ w/docker/entrypoint.sh +@@ -1,15 +1,5 @@ + #!/bin/sh + +-# this doesnt check game server specific certs, only static file paths +-files='config.json' +- +-for file in $files; do +- if [ ! -f $file ]; then +- echo "$PWD/$file file does not exist. Please mount and try again." +- exit 1 +- fi +-done +- + # check for keys + keys='certs/nex/datastore/secret.key certs/service/account/secret.key certs/service/account/aes.key certs/service/account/private.pem certs/service/account/public.pem' + for file in $keys; do diff --git a/patches/account/generate-keys-logger-fix.patch b/patches/account/generate-keys-logger-fix.patch new file mode 100644 index 0000000..3d6538b --- /dev/null +++ b/patches/account/generate-keys-logger-fix.patch @@ -0,0 +1,151 @@ +diff --git i/generate-keys.js w/generate-keys.js +index b1a311b..df80793 100644 +--- i/generate-keys.js ++++ w/generate-keys.js +@@ -2,7 +2,7 @@ const NodeRSA = require('node-rsa'); + const crypto = require('crypto'); + const fs = require('fs-extra'); + const yesno = require('yesno'); +-const logger = require('./logger'); ++const logger = require('./dist/logger'); + require('colors'); + + const ALLOWED_CHARS_REGEX = /[^a-zA-Z0-9_-]/g; +@@ -11,7 +11,7 @@ async function main() { + const args = process.argv.slice(2); + + if (args.length < 1) { +- logger.error('Must pass in type and optional name'); ++ logger.LOG_ERROR('Must pass in type and optional name'); + usage(); + return; + } +@@ -24,25 +24,25 @@ async function main() { + name = name.toLowerCase().trim(); + + if (ALLOWED_CHARS_REGEX.test(name)) { +- logger.error(`Invalid name. Names must only contain [^a-zA-Z0-9_-]. Got ${name}`); ++ logger.LOG_ERROR(`Invalid name. Names must only contain [^a-zA-Z0-9_-]. Got ${name}`); + return; + } + } + + if (!['nex', 'service', 'account'].includes(type)) { +- logger.error(`Invalid type. Expected nex, service, or account. Got ${type}`); ++ logger.LOG_ERROR(`Invalid type. Expected nex, service, or account. Got ${type}`); + usage(); + return; + } + + if (type !== 'account' && (!name || name === '')) { +- logger.error('If type is not account, a name MUST be passed'); ++ logger.LOG_ERROR('If type is not account, a name MUST be passed'); + usage(); + return; + } + + if (type === 'service' && name === 'account') { +- logger.error('Cannot use service name \'account\'. Reserved'); ++ logger.LOG_ERROR('Cannot use service name \'account\'. Reserved'); + usage(); + return; + } +@@ -61,7 +61,7 @@ async function main() { + }); + + if (!overwrite) { +- logger.info('Not overwriting existing keys. Exiting program'); ++ logger.LOG_INFO('Not overwriting existing keys. Exiting program'); + return; + } + } +@@ -72,9 +72,9 @@ async function main() { + const secretKeyPath = `${path}/secret.key`; + + // Ensure the output directories exist +- logger.info('Creating output directories...'); ++ logger.LOG_INFO('Creating output directories...'); + fs.ensureDirSync(path); +- logger.success('Created output directories!'); ++ logger.LOG_SUCCESS('Created output directories!'); + + const key = new NodeRSA({ b: 1024 }, null, { + environment: 'browser', +@@ -84,50 +84,49 @@ async function main() { + }); + + // Generate new key pair +- logger.info('Generating RSA key pair...'); +- logger.warn('(this may take a while)') ++ logger.LOG_INFO('Generating RSA key pair...'); + key.generateKeyPair(1024); +- logger.success('Generated RSA key pair!'); ++ logger.LOG_SUCCESS('Generated RSA key pair!'); + + // Export the keys +- logger.info('Exporting public key...'); ++ logger.LOG_INFO('Exporting public key...'); + const publicKey = key.exportKey('public'); +- logger.success('Exported public key!'); ++ logger.LOG_SUCCESS('Exported public key!'); + + // Saving public key +- logger.info('Saving public key to disk...'); ++ logger.LOG_INFO('Saving public key to disk...'); + fs.writeFileSync(publicKeyPath, publicKey); +- logger.success(`Saved public key to ${publicKeyPath}!`); ++ logger.LOG_SUCCESS(`Saved public key to ${publicKeyPath}!`); + +- logger.info('Exporting private key...'); ++ logger.LOG_INFO('Exporting private key...'); + const privateKey = key.exportKey('private'); +- logger.success('Exported private key!'); ++ logger.LOG_SUCCESS('Exported private key!'); + + // Saving private key +- logger.info('Saving private key to disk...'); ++ logger.LOG_INFO('Saving private key to disk...'); + fs.writeFileSync(privateKeyPath, privateKey); +- logger.success(`Saved private key to ${privateKeyPath}!`); ++ logger.LOG_SUCCESS(`Saved private key to ${privateKeyPath}!`); + + // Generate new AES key +- logger.info('Generating AES key...'); ++ logger.LOG_INFO('Generating AES key...'); + const aesKey = crypto.randomBytes(16); +- logger.success('Generated AES key!'); ++ logger.LOG_SUCCESS('Generated AES key!'); + + // Saving AES key +- logger.info('Saving AES key to disk...'); ++ logger.LOG_INFO('Saving AES key to disk...'); + fs.writeFileSync(aesKeyPath, aesKey.toString('hex')); +- logger.success(`Saved AES key to ${aesKeyPath}!`); ++ logger.LOG_SUCCESS(`Saved AES key to ${aesKeyPath}!`); + + // Create HMAC secret key +- logger.info('Generating HMAC secret...'); ++ logger.LOG_INFO('Generating HMAC secret...'); + const secret = crypto.randomBytes(16); +- logger.success('Generated RSA key pair!'); ++ logger.LOG_SUCCESS('Generated RSA key pair!'); + +- logger.info('Saving HMAC secret to disk...'); ++ logger.LOG_INFO('Saving HMAC secret to disk...'); + fs.writeFileSync(secretKeyPath, secret.toString('hex')); +- logger.success(`Saved HMAC secret to ${secretKeyPath}!`); ++ logger.LOG_SUCCESS(`Saved HMAC secret to ${secretKeyPath}!`); + +- logger.success('Keys generated successfully'); ++ logger.LOG_SUCCESS('Keys generated successfully'); + } + + // Display usage information +@@ -142,4 +141,4 @@ function usage() { + console.log('Name: Service or NEX server name. Not used in account type'); + } + +-main().catch(logger.error); +\ No newline at end of file ++main().catch(logger.LOG_ERROR); +\ No newline at end of file diff --git a/patches/mitmproxy-pretendo/configure-local-pretendo-host.patch b/patches/mitmproxy-pretendo/configure-local-pretendo-host.patch new file mode 100644 index 0000000..09fcb15 --- /dev/null +++ b/patches/mitmproxy-pretendo/configure-local-pretendo-host.patch @@ -0,0 +1,14 @@ +diff --git i/mitmproxy-config.yaml w/mitmproxy-config.yaml +index b9a4877..2e157a4 100644 +--- i/mitmproxy-config.yaml ++++ w/mitmproxy-config.yaml +@@ -10,6 +10,9 @@ confdir: ./.mitmproxy + # Enable the Pretendo redirection script + scripts: ["../pretendo_addon.py"] + pretendo_redirect: true ++pretendo_http: true ++pretendo_host: nginx ++pretendo_host_port: 80 + + # Allow self-signed certificates + ssl_insecure: true diff --git a/repos/mitmproxy-pretendo b/repos/mitmproxy-pretendo index adeacbb..7a20b5e 160000 --- a/repos/mitmproxy-pretendo +++ b/repos/mitmproxy-pretendo @@ -1 +1 @@ -Subproject commit adeacbb57efd9b6751acde57021c71fda27c6671 +Subproject commit 7a20b5e6d9c0fa77b579959145d1c4e30bdab9f6 diff --git a/scripts/setup-environment.sh b/scripts/setup-environment.sh new file mode 100755 index 0000000..9986b57 --- /dev/null +++ b/scripts/setup-environment.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +set -eu + +echo "Setting up local environment variables..." + +rm environment/*.local.env || true + +# Generate an AES-256-CBC key for account server tokens +account_aes_key=$(openssl rand -hex 32) +echo "PN_ACT_CONFIG_AES_KEY=$account_aes_key" >>./environment/account.local.env + +# Generate master API keys for the account gRPC server +account_api_key_account=$(openssl rand -base64 32) +account_api_key_api=$(openssl rand -base64 32) +echo "PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT=$account_api_key_account" >>./environment/account.local.env +echo "PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API=$account_api_key_api" >>./environment/account.local.env + +# Generate access and secret keys for MinIO +minio_access_key=$(openssl rand -base64 32) +echo "PN_ACT_CONFIG_S3_ACCESS_KEY=$minio_access_key" >>./environment/account.local.env +echo "MINIO_ACCESS_KEY=$minio_access_key" >>./environment/minio.local.env +minio_secret_key=$(openssl rand -base64 32) +echo "PN_ACT_CONFIG_S3_ACCESS_SECRET=$minio_secret_key" >>./environment/account.local.env +echo "MINIO_SECRET_KEY=$minio_secret_key" >>./environment/minio.local.env + +echo "Successfully set up environment." diff --git a/scripts/setup-submodule-patches.sh b/scripts/setup-submodule-patches.sh new file mode 100755 index 0000000..04d5c92 --- /dev/null +++ b/scripts/setup-submodule-patches.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +set -eu + +echo "Resetting all submodules..." +git submodule sync --recursive +git submodule foreach --recursive "git reset --hard" +git submodule update --init --recursive --checkout --force + +git_base=$(git rev-parse --show-toplevel) + +echo "Applying patches..." +num_patches=0 +for dir in "$git_base/patches/"*; do + if [ -d "$dir" ]; then + subdir=$(basename "$dir") + + cd "$git_base/repos/$subdir" + + for patch in "$git_base/patches/$subdir"/*; do + echo "Applying patch $patch..." + git apply "$patch" -v + num_patches=$((num_patches + 1)) + done + fi +done +echo "Successfully applied $num_patches patches."