Homework 5 - Deployment




Learning Objective - HTTPS with Nginx


Set up your app to listen for HTTPS requests on port 443 using a self-signed certificate and nginx running in a separate docker container. All features from the previous learning objectives must still be functional (With some reasonable exceptions. For example, it's ok if guest chat isn't working now that you have authenticated chat). You must include the following:

  • Your server should listen for HTTP (Unencrypted) requests on port 80. Whenever a requests is received on port 80, you should redirect the user to the same path on port 443 using HTTPS
  • Be sure to test your WebSocket features and make sure they use WSS. The front end will detect that HTTPS is being used and will attempt to establish a WSS connection
  • Update your auth token cookie to include the "secure" directive

When this objective is complete, you should be able to run your app using docker and navigate to https://localhost to use your app. Since you are now using default ports, you don't have to specify the port. You should also be able to visit http://localhost and see a redirect to https://localhost. When visiting your app for the first time, you should expect the browser to give you a warning about using a self-signed certificate.

You will need to generate a private key and a self-signed certificate to enable HTTPS. For this objective, you may use an additional script to accomplish this. You should name this script "setup.sh" and save it in the root directory of your project. If this file exists, we will run it before starting your app while grading. The intent is for this script to generate your encryption keys, though you have the freedom to do whatever setup you'd like in this script. You may also choose to not include a script and set up your keys in your Dockerfile if you prefer. You may assume this script will be executed in a *nix environment with openssl installed.

When we test your app we will:

  1. Run "setup.sh" if it exists
  2. Run "docker compose up"
  3. Test the features of your app at https://locahost and http://localhost

Security: Do not include any private encryption keys in your submission.

Security: Your auth token must use the secure directive.



Application Objective 1 - DoS Slow Send


For this objective, you will both launch a DoS slow send attack and protect against such an attack.

Attack: In the root directory of your project, write a python script named "dos.py" that will launch your slow send attack. Your attack must meet the following criteria:

  • It must be a slow send attack. Writing a script that successfully launches a different style of DoS attack will not complete this objective
  • You may assume the target site is accepting HTTP requests on both port 80 and 8080 as well as HTTPS requests on port 443
  • The attack is considered successful if the app experiences notable slow down (100's of milliseconds is sufficient) after running dos.py a single time. This slowdown should last for a significant amount (Minutes) of time while the attack continues. To measure the slowdown, you can check the roundtrip times of you app running without the attack and compare them to the times while your attack is running. The app doesn't have to completely shut down, but you should experience at least several 100 milliseconds of additional roundtrip time
  • The attack will be tested on a typical CSE312 HW server that has all the features you would expect, including buffering, without any DoS protection

Countermeasure: Protect against this attack. Any method of prevention is acceptable, though the intended approach is to add a timeout to your buffering code. When you detect that your app has been buffering for a while, close the connection. Your countermeasure must meet the following criteria:

  • After a slow send attack is launched, your app recovers in a reasonable amount of time (seconds). It is ok to experience slowdown when the attack first begins (eg. before your timeout is reached)
  • Your countermeasure must protect against this family of attacks, not just your implementation from this objective (eg. We will use our own attack during grading)
  • All features must still work for users who are not launching a DoS attack on your server. Specifically, make sure your WebSocket connections do not time out


Application Objective 2 - JWTs and Authentication Servers


Create a separate authentication (auth) server that will issue JWTs when a user logs in. This auth server must run in a 4th container using docker compose. This server will handle all registration and login requests for your app. When a user connects to an endpoint of your app that requires authentication, it will use the self-contained JWT to verify the user. You have some freedom in your design as long as your app meets the following criteria:

  • Use nginx to route all authentication requests (/register, /login, /logout) to your auth server, and all other requests to your app server
  • The JWT's issues by your auth server must be cryptographically signed using a private key that is only accessible by the auth server. These must be different keys than the ones used by nginx for TLS
  • Your app must verify JWTs without communicating with the auth server
  • Your app must verify JWTs without a database lookup

You will have to solve the problem of generating a public/private key pair, storing the private key only on the auth server, and sharing the public key with your app server. There are several ways to solve this problem with the intended approach being to add to your setup.sh script and handle it there. Note that you call a Python script from setup.sh if you prefer to do this in Python. Alternatively, you may generate these keys in your auth server and provide an endpoint for your app to ask the auth server for the public key. This is the only direct communication allowed between the two servers.

You are allowed to use libraries to sign and verify JWTs.

Security: Do not include any private encryption keys in your submission.

Security: Your JWT's must use the secure and httpOnly directives set.

Security: Your JWT's must be cryptographically signed in a way that they cannot be forged.

Security: Any private key(s) must only be known to you auth server. Not even your app server should have access to this key.



Submission


Submit all files for your server to Autolab in a .zip file

If you used any external libraries, be sure to add them to your requirements.txt. Autolab will install all dependencies in this file, and no other dependencies, before starting your server.

It is strongly recommended that you download and test your submission after submitting. To do this, download your zip file into a new directory, unzip your zip file, enter the directory where the files were unzipped, run docker compose up, then navigate to localhost:8080 in your browser and test all of your features. This simulates exactly what the TAs will do during grading.

If you ignore this recommendation, don't be surprised when you do not earn credit for either Application Objective even if your code functions properly when running server.py


Grading


Each objective will be scored on a 0-3 scale as follows:

3 (Complete) Clearly correct
2 (Complete) Mostly correct, but with some minor issues
1 (Incomplete) Not all features outlined in this document are functional, but an honest attempt was made to complete the objective
0.3 (Incomplete) The objective would earn a 3, but a security risk was found while testing
0.2 (Incomplete) The objective would earn a 2, but a security risk was found while testing
0.1 (Incomplete) The objective would earn a 1, but a security risk was found while testing
0 (Incomplete) No attempt to complete the objective or violation of the assignment (Ex. Using an HTTP library)

Note that for your final grade there is no difference between a 2 and 3, or a 0 and a 1. The numeric score is meant to give you more feedback on your work.

3 Objective Complete
2 Objective Complete
1 Objective Not Complete
0 Objective Not Complete

Autograded objectives are graded on a pass/fail basis with grades of 3.0 or 0.0.



Security Essay


For each objective for which you earned a 0.3 or 0.2, you will still have an opportunity to earn credit for the objective by submitting an essay about the security issue you exposed. These essays must:

  • Be at least 1000 words in length
  • Explain the security issue from your submission with specific details about your code
  • Describe how you fixed the issue in your submission with specific details about the code you changed
  • Explain why this security issue is a concern and the damage that could be done if you exposed this issue in production code with live users

Any submission that does not meet all these criteria will be rejected and your objective will remain incomplete.

Due Date: Security essays are due 1-week after grades are released.

Any essay may be subject to an interview with the course staff to verify that you understand the importance of the security issue that you exposed. If an interview is required, you will be contacted by the course staff for scheduling. Decisions of whether or not an interview is required will be made at the discretion of the course staff.

When you don't have to write an essay:

  • If you never submit a security violation, you never have to write an essay for this course. Be safe. Be secure
  • If you earn a 0.1, there's no need to write an essay since you would not complete the objective anyway