From cb48df2fa9f486f45ff160116e27826a91d2cbf6 Mon Sep 17 00:00:00 2001 From: Erik Taubeneck Date: Wed, 5 Jun 2024 12:55:51 -0700 Subject: [PATCH] make user auth optional for local dev --- .gitignore | 2 +- README.md | 238 +++++++++++++++++---------------------- server/.env.development | 11 ++ server/middleware.ts | 8 ++ server/supabase/seed.sql | 12 ++ 5 files changed, 136 insertions(+), 135 deletions(-) create mode 100644 server/.env.development diff --git a/.gitignore b/.gitignore index fa86c33..ca32a63 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ IGNORE-ME* .draft # local env files -.env* +.env*.local # local certs local_dev/config/cert.pem diff --git a/README.md b/README.md index e69b077..29a9676 100644 --- a/README.md +++ b/README.md @@ -6,34 +6,95 @@ draft is a project designed to help test [IPA](https://github.com/private-attrib 1. draft-server: a web front end and service that starts queries an displays logs from the MPC helper servers 2. draft-sidecar: a sidecar back end API that runs next to the IPA binary on helper servers. This includes a CLI for setup and running. -# Get started -## Local Dev +# Get started +## Deploying a Helper Party -### Running Locally +### Requirements -Make sure the repo is cloned and you're working in the root directory of the repo: +*Instructions for AWS Linux 2023* +1. Provision an EC2 instance. Download the provided `ssh_connect.pem` key and add it to `~/.ssh`. +2. Point a subdomain of a domain you control to the public IP address. +3. Add the host to your `~/.ssh/config` file: ``` -git clone https://github.com/eriktaubeneck/draft.git -cd draft +Host ipa + Hostname + User ec2-user + IdentityFile ~/.ssh/ssh_connect.pem ``` +4. Update the `draft/ansible/inventory.ini` file to only include a single host. (Unless you are running all 4 servers.) +5. Provision your machine: `ansible-playbook -i ansible/inventory.ini ansible/provision.yaml` + +To deploy new changes in draft, run: `ansible-playbook -i ansible/inventory.ini ansible/deploy.yaml` + +### Generating TLS certs with Let's Encrypt + +You will need a domain name and TLS certificates for the sidecar to properly run over HTTPS. The following instructions assume your domain is `example.com`, please replace with the domain you'd like to use. You will need to create two sub-domains, `sidecar.example.com` and `helper.example.com`. (Note, you could also use a sub-domain as your base domain, e.g., `test.example.com` with two sub-domains of that: `sidecar.test.example.com` and `helper.test.example.com`.) +1. Set up DNS records for `sidecar.example.com` and `helper.example.com` pointing to a server you control. +2. Make sure you've installed the requirements above, and are using the virtual environment. +3. Install `certbot`: `pip install certbot` +4. `sudo .venv/bin/certbot certonly --standalone -m cert-renewal@example.com -d "sidecar.example.com,helper.example.com"` + 1. Note that you must point directly to `.venv/bin/certbot` as `sudo` does not operate in the virtualenv. +5. Accept the [Let's Encrypt terms](https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf). -Assuming all requirements are installed, start prerequisites: + +### Make Configuration + +For this stage, you'll need to know a few things about the other parties involved: +1. Their root domain +2. Their public keys +3. Everyone's *identity* (e.g., 0, 1, 2, 3) + + +One you know these: +1. Make a config directory `mkdir config` +2. Copy the default network config: `cp local_dev/config/network.toml config/.` +3. Update that file. + 1. Replace `helper0.draft.test` and `sidecar0.draft.test` with the respective domains for party with identity=0. + 2. Repeat for identity= 1, 2, and 3. + 3. Replace respective certificates with their public keys. +4. Move your Let's Encrypt key and cert into place: `sudo ln -s /etc/letsencrypt/live/sidecar.example.com/fullchain.pem config/cert.pem` and `sudo ln -s /etc/letsencrypt/live/sidecar.example.com/privkey.pem key.pem` +5. Generate IPA specific keys: + 1. Compile `ipa` with `cargo build --bin helper --features="web-app real-world-infra compact-gate stall-detection multi-threading" --no-default-features --release` + 2. Make the keys with `target/release/helper keygen --name localhost --tls-key h1.key --tls-cert h1.pem --mk-public-key h1_mk.pub --mk-private-key h1_mk.key` (replace h1 with for each helper) + 3. Add the public keys content into `network.toml` + 4. Add the public keys to `config/pub` (all helpers need all helper public keys). + 4. For each helper, put their private keys in `config`. + + +### Run draft ``` -colima start -supabase start --workdir server +draft start-helper-sidecar --identity --root_domain example.com --config_path config ``` -Start `draft` for local dev: +This will start the sidecar in the background. To confirm, visit `example.com/status`. + + +## Local Dev + +`draft` provides a fully functional local development setup, to work on both the frontend web interface, as well as the sidecar. + +### Running local development + +If `draft` and the other prerequisites are already installed, run: ``` draft start-local-dev ``` -### Requirements +You can follow the logs with: +``` +draft follow-local-dev-logs +``` + +And you can view the front end at [https://draft.test](https://draft.test). + + + +### Prerequisites Requirements: 1. Python 3.11 @@ -41,7 +102,12 @@ Requirements: 3. [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started) 4. Docker -#### macOS install +#### macOS install prerequisites + +```brew install python3``` +```brew install node``` +```brew install supabase/tap/supabase``` +```brew install traefik``` **Docker** @@ -51,73 +117,39 @@ There are multiple options to run Docker locally. One such option is [colima](ht ``` brew install docker brew install colima -colima start ln -sf ~/.colima/docker.sock /var/run/docker.sock ``` The `ln` at the end is because Supabase requires interacting with the local Docker API. See [this Supabase issue](https://github.com/supabase/cli/issues/153) and [this colima issue.](https://github.com/abiosoft/colima/issues/144) This likely requires `sudo`. +### Installation -**Github App** - -The `draft` web front end uses Github for authentication. In order to login locally, you'll need to create a new application for development. Visit [https://github.com/settings/apps/new](https://github.com/settings/apps/new) to create a new Github app using the following parameters: -1. *name*: draft-local-dev (recommended, but not required) -2. *Homepage URL:* http://localhost:54321 -3. *Callback URL:* http://localhost:54321/auth/v1/callback -4. *Request user authorization (OAuth) during installation:* yes -5. *Webhook active:* false -6. *Permissions:* Read-only access to email address -7. *Where can this GitHub App be installed?:* Only on this account - -Once you have created the app, you'll need to create a file `server/.env` and add both the `CLIENT_ID` and a generated `CLIENT_SECRET`. - -``` -SUPABASE_AUTH_GITHUB_CLIENT_ID="" -SUPABASE_AUTH_GITHUB_SECRET="" -``` - - -**Supabase CLI** +Make sure the repo is cloned and you're working in the root directory of the repo: ``` -brew install supabase/tap/supabase +git clone https://github.com/eriktaubeneck/draft.git +cd draft ``` -After installing, run +**Start colima and supabse:** ``` +colima start supabase start --workdir server ``` - -In the output, you'll find an `ANON_KEY`. Update the `server/.env` file one more time to include two new variables: +In the output, you'll find an `ANON_KEY`. Create the file `server/.env.development.local` and add: ``` -NEXT_PUBLIC_SUPABASE_URL="http://localhost:54321" NEXT_PUBLIC_SUPABASE_ANON_KEY="" -NEXT_PUBLIC_SITE_URL="https://draft.test" -SUPABASE_AUTH_GITHUB_CLIENT_ID="" -SUPABASE_AUTH_GITHUB_SECRET="" ``` -**Traefik** - -install traefik - -``` -brew install traefik -``` - -update /etc/hosts with (requires sudo) +**Add local draft.test domain to `/etc/hosts`:** ``` -127.0.0.1 draft.test -127.0.0.1 sidecar0.draft.test -127.0.0.1 sidecar1.draft.test -127.0.0.1 sidecar2.draft.test -127.0.0.1 sidecar3.draft.test +echo "#draft local domains\n127.0.0.1 draft.test\n127.0.0.1 sidecar0.draft.test\n127.0.0.1 sidecar1.draft.test\n127.0.0.1 sidecar2.draft.test\n127.0.0.1 sidecar3.draft.test" | sudo tee -a /etc/hosts ``` -make local certs +**make local certs** install mkcert with @@ -136,33 +168,16 @@ If you get a warning about the cert not being installed (i.e., it's the first ti mkcert -install ``` -**Run local dev** - -You're now ready to install, run, and develop on `draft`! - -To start the local development environment: - -``` -draft start-local-dev -``` - -(Make sure `draft` is installed, see next section.) - ### Install draft -If needed, clone this repo: -``` -git clone https://github.com/private-attribution/draft.git -cd draft -``` - -**Install `draft`** ``` -python -m virtualenv .venv +python -m venv .venv source .venv/bin/activate pip install --editable . ``` +## Appendix + ### IPA specific certs We check in self signed certs that are only for local development (and are not secure! They are in a public repo!) @@ -177,70 +192,25 @@ target/release/helper keygen --name helper3.draft.test --tls-key local_dev/confi The public content will also need to be pasted into `local_dev/config/network.toml` for each helper. -## Deployment - -### Requirements - -*Instructions for AWS Linux 2023* - -1. Provision an EC2 instance. Download the provided `ssh_connect.pem` key and add it to `~/.ssh`. -2. Point a subdomain of a domain you control to the public IP address. -3. Add the host to your `~/.ssh/config` file: -``` -Host ipa - Hostname - User ec2-user - IdentityFile ~/.ssh/ssh_connect.pem -``` -4. Update the `draft/ansible/inventory.ini` file to only include a single host. (Unless you are running all 4 servers.) -5. Provision your machine: `ansible-playbook -i ansible/inventory.ini ansible/provision.yaml` - -To deploy new changes in draft, run: `ansible-playbook -i ansible/inventory.ini ansible/deploy.yaml` - -### Generating TLS certs with Let's Encrypt - -You will need a domain name and TLS certificates for the sidecar to properly run over HTTPS. The following instructions assume your domain is `example.com`, please replace with the domain you'd like to use. You will need to create two sub-domains, `sidecar.example.com` and `helper.example.com`. (Note, you could also use a sub-domain as your base domain, e.g., `test.example.com` with two sub-domains of that: `sidecar.test.example.com` and `helper.test.example.com`.) - -1. Set up DNS records for `sidecar.example.com` and `helper.example.com` pointing to a server you control. -2. Make sure you've installed the requirements above, and are using the virtual environment. -3. Install `certbot`: `pip install certbot` -4. `sudo .venv/bin/certbot certonly --standalone -m cert-renewal@example.com -d "sidecar.example.com,helper.example.com"` - 1. Note that you must point directly to `.venv/bin/certbot` as `sudo` does not operate in the virtualenv. -5. Accept the [Let's Encrypt terms](https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf). - - -### Make Configuration - -For this stage, you'll need to know a few things about the other parties involved: -1. Their root domain -2. Their public keys -3. Everyone's *identity* (e.g., 0, 1, 2, 3) - - -One you know these: -1. Make a config directory `mkdir config` -2. Copy the default network config: `cp local_dev/config/network.toml config/.` -3. Update that file. - 1. Replace `helper0.draft.test` and `sidecar0.draft.test` with the respective domains for party with identity=0. - 2. Repeat for identity= 1, 2, and 3. - 3. Replace respective certificates with their public keys. -4. Move your Let's Encrypt key and cert into place: `sudo ln -s /etc/letsencrypt/live/sidecar.example.com/fullchain.pem config/cert.pem` and `sudo ln -s /etc/letsencrypt/live/sidecar.example.com/privkey.pem key.pem` -5. Generate IPA specific keys: - 1. Compile `ipa` with `cargo build --bin helper --features="web-app real-world-infra compact-gate stall-detection multi-threading" --no-default-features --release` - 2. Make the keys with `target/release/helper keygen --name localhost --tls-key h1.key --tls-cert h1.pem --mk-public-key h1_mk.pub --mk-private-key h1_mk.key` (replace h1 with for each helper) - 3. Add the public keys content into `network.toml` - 4. Add the public keys to `config/pub` (all helpers need all helper public keys). - 4. For each helper, put their private keys in `config`. +### Local Github Authentication +By default, local authentication is turned off (technically, you're automatically logged in as a demo user.) If you want to test Github authentication locally, you'll need to create a new application for development. Visit [https://github.com/settings/apps/new](https://github.com/settings/apps/new) to create a new Github app using the following parameters: +1. *name*: draft-local-dev (recommended, but not required) +2. *Homepage URL:* http://localhost:54321 +3. *Callback URL:* http://localhost:54321/auth/v1/callback +4. *Request user authorization (OAuth) during installation:* yes +5. *Webhook active:* false +6. *Permissions:* Read-only access to email address +7. *Where can this GitHub App be installed?:* Only on this account -### Run draft +Once you have created the app, you'll need to update `server/.env.development.local` to include both the `CLIENT_ID` and a generated `CLIENT_SECRET`, and set the `BYPASS_AUTH` flag. ``` -draft start-helper-sidecar --identity --root_domain example.com --config_path config +SUPABASE_AUTH_GITHUB_CLIENT_ID="" +SUPABASE_AUTH_GITHUB_SECRET="" +BYPASS_AUTH=false ``` -This will start the sidecar in the background. To confirm, visit `example.com/status`. - # Credit diff --git a/server/.env.development b/server/.env.development new file mode 100644 index 0000000..e3061c8 --- /dev/null +++ b/server/.env.development @@ -0,0 +1,11 @@ +# DO NOT ADD SECRETS TO THIS FILE. This is a good place for defaults. +# If you want to add secrets use `.env.development.local` instead. + +# for local dev, we turn off auth, unless specifically working on auth +BYPASS_AUTH=true +SUPABASE_AUTH_GITHUB_CLIENT_ID="foo" +SUPABASE_AUTH_GITHUB_SECRET="bar" + +# default supabase variables +NEXT_PUBLIC_SUPABASE_URL="http://localhost:54321" +NEXT_PUBLIC_SITE_URL="https://draft.test" diff --git a/server/middleware.ts b/server/middleware.ts index 4fecfbd..48567d0 100644 --- a/server/middleware.ts +++ b/server/middleware.ts @@ -54,6 +54,14 @@ export async function middleware(request: NextRequest) { }, ); + if (process.env.NODE_ENV === "development" && process.env.BYPASS_AUTH === "true") { + const { data, error } = await supabase.auth.signInWithPassword({ + email: 'demo@draft.test', + password: 'password', + }) + console.log(data); + return response + } const { data: { user }, } = await supabase.auth.getUser(); diff --git a/server/supabase/seed.sql b/server/supabase/seed.sql index e69de29..da409dc 100644 --- a/server/supabase/seed.sql +++ b/server/supabase/seed.sql @@ -0,0 +1,12 @@ +-- +-- Data for Name: users; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin +-- + +INSERT INTO auth.users (instance_id, id, aud, role, email, encrypted_password, email_confirmed_at, invited_at, confirmation_token, confirmation_sent_at, recovery_token, recovery_sent_at, email_change_token_new, email_change, email_change_sent_at, last_sign_in_at, raw_app_meta_data, raw_user_meta_data, is_super_admin, created_at, updated_at, phone, phone_confirmed_at, phone_change, phone_change_token, phone_change_sent_at, email_change_token_current, email_change_confirm_status, banned_until, reauthentication_token, reauthentication_sent_at, is_sso_user, deleted_at, is_anonymous) VALUES ('00000000-0000-0000-0000-000000000000', '547cc447-046e-4eb9-9f1a-3ccf2ff61f4d', 'authenticated', 'authenticated', 'demo@draft.test', '$2a$10$wsNGVOHGOr1cIlo61ZmZB.u3jccbX.YPSN0P8g/dPDxfOtFFjAwvy', '2024-06-05 19:04:10.138363+00', NULL, '', NULL, '', NULL, '', '', NULL, '2024-06-05 19:09:51.248495+00', '{"provider": "email", "providers": ["email"]}', '{}', NULL, '2024-06-05 19:04:10.134596+00', '2024-06-05 19:09:51.251084+00', NULL, NULL, '', '', NULL, '', 0, NULL, '', NULL, false, NULL, false); + + +-- +-- Data for Name: identities; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin +-- + +INSERT INTO auth.identities (provider_id, user_id, identity_data, provider, last_sign_in_at, created_at, updated_at, id) VALUES ('547cc447-046e-4eb9-9f1a-3ccf2ff61f4d', '547cc447-046e-4eb9-9f1a-3ccf2ff61f4d', '{"sub": "547cc447-046e-4eb9-9f1a-3ccf2ff61f4d", "email": "demo@draft.test", "email_verified": false, "phone_verified": false}', 'email', '2024-06-05 19:04:10.136163+00', '2024-06-05 19:04:10.136185+00', '2024-06-05 19:04:10.136185+00', '9db62519-e822-42ec-b2ed-6c7e18f2915a');