Skip to content

Commit

Permalink
Merge pull request #2782 from HHS/key-cleanup-and-docs
Browse files Browse the repository at this point in the history
remove dead code;add documentation for generating keys
  • Loading branch information
johndeange committed Sep 12, 2024
2 parents 47226a7 + d61bdf7 commit 5eaabe4
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 142 deletions.
51 changes: 30 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,33 @@ At a bare minimum, you need [Docker](https://www.docker.com) and
development, you will also need to install [Python](https://www.python.org), [Node.js](https://nodejs.org), and
[pre-commit](https://pre-commit.com/#installation).

## RSA Key Generation

The backend uses RSA keys to sign and verify JWTs. You can generate these keys by running the following commands...

```shell
mkdir ~/ops-keys
openssl genrsa -out ~/ops-keys/keypair.pem 2048
openssl rsa -in ~/ops-keys/keypair.pem -pubout -out ~/ops-keys/public.pem
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in ~/ops-keys/keypair.pem -out ~/ops-keys/private.pem
```

Then place the private/public keys in your shell environment...

```shell
export JWT_PRIVATE_KEY=$(cat ~/ops-keys/private.pem)
export JWT_PUBLIC_KEY=$(cat ~/ops-keys/public.pem)
```

Also, replace the public key file contents in the following locations...

```
cat ~/ops-keys/public.pem > ./public.pub
cat ~/ops-keys/public.pem > ./backend/ops_api/ops/static/public.pem
```

N.B. The public key files above are deprecated and will be replaced with the `JWT_PUBLIC_KEY` environment variable in the future.

## Install

### Backend
Expand Down Expand Up @@ -86,7 +113,7 @@ To run them...

```shell
cd ./backend/ops_api
pytest
pipenv run pytest
```

Note: All backend API endpoints have the ability to simulate an error response, for testing purposes for the frontend. This is accomplished
Expand Down Expand Up @@ -137,10 +164,8 @@ or Interactively via:
bun run test:e2e:interactive
```

The E2E uses it's own TEST keys for generating and validating JWT Signatures, as it bypasses any live OAuth providers.
The test-private-key is currently configured within the `cypress.config.js` directly (base64url encoded). The `backend`, then requires the test-public-key in order to validate the signatures of the JWT. This is configured within the `/ops/environment/local/e2e.py` (path); which points to the `/static/test-public-key.pem`.
These keys are ONLY used for End-to-end testing, and are not pushed to any LIVE system outside of local testing.
N.B. Running the E2E tests multiple times using the same containers and volumes can lead to unexpected results.
It is recommended to run `docker system prune --volumes` between test runs.

### Linting

Expand Down Expand Up @@ -203,26 +228,10 @@ TBD
TBD
~~This environment can be deployed to manually as well by authorized committers in the repository. You accomplish this by force pushingan existing commit to the `development` branch.~~

```shell
git branch -d development # deletes the development branch if it was already checked out locally
git checkout -b development
git push --force --set-upstream origin development
```

### Staging Environment
TBD
~~This environment can be deployed to by authorized committers in the repository. You accomplish this by force pushing an existing commit to the `staging` branch.~~

```shell
git branch -d staging # deletes the staging branch if it was already checked out locally
git checkout -b staging
git push --force --set-upstream origin staging
```

### Production Environment
TBD
Expand Down
37 changes: 0 additions & 37 deletions backend/ops_api/ops/environment/local/e2e.py

This file was deleted.

9 changes: 0 additions & 9 deletions backend/ops_api/ops/static/test-public-key.pem

This file was deleted.

4 changes: 0 additions & 4 deletions frontend/cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export default defineConfig({
video: false,
viewportHeight: 768,
viewportWidth: 1024,
env: {
testkey:
"LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRRHcrZE96M3oxMjFaZ2oKTzBVRklnZHZtNy9ZRFJJMUZic2ZaNjJqS2dpN3FGNG5BSzdjWGJYNiswUjh0OUtkSUR3UHRuSlRmTFA0bldIawpLL01pc2NoYUNIemhmU3dJSU1qSkZxaHV0L1E0MFFsVTJobDlFQmsvTXhZNnRpb2dKYXhlN1kySkJQSUkxZkRICjJnZzgvdHNXZFRiS3VFd0NxS2d3OUQwZU13VFFVaEhiZUlhb2RCeWI4Y2h6NXBYZW5zZ1BvemVTd3VOdlhYM04KLzYyZFVJQVZOaVNZamptRndwY3puWmV3NnpZWXBXTUY5akZwQmw4VjJzNmR1NnBIWmhMc05LSTYrVlFmTE9WaApZN1NDcU1lVm9KUDd3ZjhDNTFxT2FCWmF5V3E1VGhZNE12Q29veVlHMzNXMzRZYWZrVWo1OE9OQ3VCdDN6WEZGCnhMdUMxMEtyQWdNQkFBRUNnZ0VCQU94Q0pGdVFIZlRxaVpUUlFXUTg3c2x3REhGSXIzYzRiUlBuVkloS1ovR0UKcTNyVjRwclBqZUlhaEJVN0xOVThpMlprWEVhYVZ1RURmTHgya3BTTGRZRkFIUi8rMXpMSTRkSzEwa0ZyUFppTwo2ZlUxT0JRenVtMEtLMXM0eXFobUIwK3kzRGRnaitRMXpUSkVCQnU1U3hnRHA4cXRVbWl3N3VYQU1FUHhoV0N2Cmp3SGMwN2NvZ0g2d0ljUE1HeDJWcGowdUFtb1VpNU1OcWtFVjZDRDhHUmlqdGtUb1RPaTRoZlVpZ3ZRaklaM0QKYnB1STFoUzB3SDRTV1lOcDdHNHpGTlVLT1Rjak1WamFMaTdGeTZYemNNMkQyV1RmakczeDQ5ZnlibDIwWWVzZAppbWRTWVAwbUNVR1NRM2FsOUFtdjY1V2dDZkZ2bzZhNTJ2TExadlpUbGNFQ2dZRUEvbmFsNkhEMHBwa1p2enJWCnNxbFJpSzg4YlZYME90T1d6VncwdXp0YmZ3UDhXbnhYTTVkaGxsSkE1b254eGk2eVI3TENXZmFkcWRNNE01Z0oKMHlzcEdUQUhTMFNaQ0ZMM2ZHNElzYVJwTXhVRlpuWWdPWnJicm5FbytHQUozU1lrbXFoaWI5c3M2aVUwaGw4TwplWGFQRGlqUVVJZEVzMnVLMUFLbC9HSGJrYnNDZ1lFQThtNVVaSWFiYUU4STljVzdjbXpRZXJ6WGR1VmJ4Wjk1Cit2NWV4WElIUW1ldjl3Qm5MVUpOMmt4K3VYNFhuMUozZGNFV3I5UjQ5WEU1RU9wUlRkU2s3MC9iMkpvNmJhM1YKeHdGcGJLQWRWa1A2N0JVenpXYVdDMFBvYzZteTdMWVc3eWZTOU1hMVk3KzFXbnh5Qkl3OU10bXYwSDArVFFTSQphUjFUSDZxeXk5RUNnWUJUdVVBUFFaTU5lWlJDR2g2VHdTZ0ZlL3E2MHF3ZjZ0eFVSMEZHVlZwZWFUWlBvMWVoCnJ1NDU0bWhlTWdidHVSR0ppNlJzcXpybTFJdEtWbnp0RU9kZDFUS2hMam5YeGt5TmtUcWxFRDVZdzFMYWlvVkIKenRUM0NWNThra1RNa2E4N2Y2bWJ1aGFHRjZXM2pIRWJ2OG1EMUNQdVN3TnNzVGFsV1JXNSs0eWQzd0tCZ1FEQwpxOW5VeDBwdjNsZGhsQ0JMYUJtWkZaOG5lRkhUUlpaYitIcjlyZTBxWTd5bmFZbHdqSGVidmlWY3FtWXBwNzBKCnI3MlovOUlKdFp1UGU3bEIrR2xoU2cxTng3cjNhOG5vZmJlOFpHNXFZVGhTNzB1anVxYnQ4Ti91VU95K3JCR0sKaGI0ZWxKbi91V2ZWZTJ6TFBobStoWk5xcGNlcmJPSmxGZ2t6dW96TW9RS0JnUUQwTDZhK04vQ09rdXZKcldocAp4V2YwckVvS25UYUR5Rmo0K1FlQzR6WitNWDJDTlBWT2M4OFg4ZDA3b0I0cWlvTHlwa0pKTWNZRFlFZVdWdHFFCkNzclVSalJGQUtQVHdpcVEvYS9lTHpFVzZub3l1NUI5RGtyRXU4VTEwN1l3WFNaZkxBTXRETlJCeVVtZ0lLUlAKaHFteXVqT3U0RGl3eXJlWW9aSUJnbWdhQXc9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg"
},
retries: {
// Configure retry attempts for `cypress run`
// Default is 0
Expand Down
72 changes: 1 addition & 71 deletions frontend/cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,65 +16,8 @@
import "cypress-localstorage-commands";
import "cypress-axe";
import "./commands";
import * as jose from "jose";
import { login } from "../../src/components/Auth/authSlice";

const users = [
{
name: "admin",
first_name: "Emily",
last_name: "Ball",
division: 1,
email: "[email protected]",
role: "Admin",
oidc_id: "00000000-0000-1111-a111-000000000001"
},
{
name: "director",
first_name: "Bethanne",
last_name: "Barnes",
division: 4,
email: "[email protected]",
role: "Division Director",
oidc_id: "00000000-0000-1111-a111-000000000002"
},
{
name: "cor",
first_name: "Meryl",
last_name: "Barofsky",
division: 1,
email: "[email protected]",
role: "COR",
oidc_id: "00000000-0000-1111-a111-000000000003"
},
{
name: "basic",
first_name: "Anne",
last_name: "Bergan",
division: 3,
email: "[email protected]",
role: "View-Only",
oidc_id: "00000000-0000-1111-a111-000000000004"
}
];

const generateJWT = async (name) => {
const alg = "RS256";
const keyBase64 = Cypress.env("testkey");
const key = Buffer.from(keyBase64, "base64");
const privateKey = await jose.importPKCS8(key.toString(), "RS256");
let user = users.find((u) => u.name === name);

const jwt = await new jose.SignJWT({ type: "access" })
.setProtectedHeader({ alg })
.setIssuedAt()
.setSubject(user.oidc_id)
.setExpirationTime("2h")
.sign(privateKey);

return jwt;
};

Cypress.Commands.add("login", () => {
window.localStorage.setItem("access_token", "123");
});
Expand All @@ -88,7 +31,7 @@ Cypress.Commands.add("FakeAuth", (user) => {
} else if (user === "basic") {
cy.contains("Basic User").click();
}
// eslint-disable-next-line cypress/no-unnecessary-waiting

cy.wait(100);
cy.logLocalStorage();
// TODO: Figure out why the below tests are required for this to complete.\
Expand All @@ -113,19 +56,6 @@ Cypress.Commands.add("FakeAuth", (user) => {
});
});

Cypress.Commands.add("fakeLogin", (name) => {
cy.session([name], async () => {
cy.visit("/");
const jwt = await generateJWT(name);
window.localStorage.setItem("access_token", jwt);
//win.store.dispatch(login());
});
});

Cypress.Commands.add("setIsLoggedIn", (win) => {
win.store.dispatch(login());
});

Cypress.Commands.add("logLocalStorage", () => {
cy.window().then((window) => {
console.log("localStorage contents:", window.localStorage);
Expand Down

0 comments on commit 5eaabe4

Please sign in to comment.