Skip to content

Commit

Permalink
Update README #28
Browse files Browse the repository at this point in the history
  • Loading branch information
VKTB committed Feb 12, 2024
1 parent 67e5992 commit 6f196f7
Showing 1 changed file with 113 additions and 22 deletions.
135 changes: 113 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,115 @@
# LDAP-JWT Authentication Service
This is a Python microservice that provides user authentication against an LDAP server and returns a JSON Web Token
(JWT).

This is a Python microservice created using FastAPI that provides user authentication against an LDAP server and returns
a JSON Web Token (JWT).

## How to Run
This microservice requires an LDAP server to run against.

### Prerequisites
- Docker installed (if you want to run the microservice inside Docker)
- Python 3.10 (or above) and an LDAP server to connect to
- Docker and Docker Compose installed (if you want to run the microservice inside Docker)
- LDAP server to connect to
- Python 3.10 (or above) (if you are not using Docker)
- Private and public key pair (must be OpenSSH encoded) for encrypting and decrypting the JWTs
- A list of active usernames, defining who can use this service
- This repository cloned

### Docker Setup
The easiest way to run the application with Docker for local development is using the `docker-compose.yml` file. It is
configured to start the application in a reload mode using the `Dockerfile`. You can also use the `Dockerfile` directly
to run the application in a container. Please do not use the `Dockerfile` in production.

Ensure that Docker is installed and running on your machine before proceeding.

1. Create a `.env` file alongside the `.env.example` file. Use the example file as a reference and modify the values accordingly.
1. Create a `.env` file alongside the `.env.example` file. Use the example file as a reference and modify the values
accordingly.
```bash
cp ldap_jwt_auth/.env.example ldap_jwt_auth/.env
```

2. Create a `logging.ini` file alongside the `logging.example.ini` file. Use the example file as a reference and modify it accordingly.
2. Create a `logging.ini` file alongside the `logging.example.ini` file. Use the example file as a reference and modify
it accordingly:
```bash
cp ldap_jwt_auth/logging.example.ini ldap_jwt_auth/logging.ini
```

3. Create a `keys` directory in the root of the project directory, navigate to it, and generate OpenSSH encoded private and public key pair:
3. Create a `keys` directory in the root of the project directory, navigate to it, and generate OpenSSH encoded private
and public key pair:
```bash
mkdir keys
cd keys/
ssh-keygen -b 2048 -t rsa -f jwt-key -q -N ""
ssh-keygen -b 2048 -t rsa -f jwt-key -q -N "" -C ""
```

4. Create a `active_usernames.txt` file alongside the `active_usernames.example.txt` file and add all the usernames that
can use this system. The usernames are the Federal IDs and each one should be stored on a separate line.
```bash
cp active_usernames.example.txt active_usernames.txt
```

4. Create a `active_usernames.txt` file alongside the `active_usernames.example.txt` file and add all the usernames (each one on a seperate line) that are active/can access the system.
#### Using `docker-compose.yml`
The easiest way to run the application with Docker for local development is using the `docker-compose.yml` file. It is
configured to start the application in a reload mode using the `Dockerfile`.

#### Using Docker Compose File
1. Build and start the Docker container:
```bash
docker-compose up
```
The microservice should now be running inside Docker at http://localhost:8000 and its Swagger UI could be accessed
at http://localhost:8000/docs.

#### Using Dockerfile
#### Using `Dockerfile`
Use the `Dockerfile` to run just the application itself in a container. Use this only for local development (not
production)!

1. Build an image using the `Dockerfile` from the root of the project directory:
```bash
docker build -f Dockerfile -t ldap_jwt_auth_image .
```

2. Start the container using the image built and map it to port `8000` locally:
```bash
docker run -p 8000:8000 --name ldap_jwt_auth_container ldap_jwt_auth_image
docker run -p 8000:8000 --name ldap_jwt_auth_container -v ./keys/jwt-key:/ldap-jwt-auth-run/keys/jwt-key -v ./keys/jwt-key.pub:/ldap-jwt-auth-run/keys/jwt-key.pub -v ./active_usernames.txt:/ldap-jwt-auth-run/active_usernames.txt -v ./logs:/ldap-jwt-auth-run/logs ldap_jwt_auth_image
```
or with values for the environment variables:
```bash
docker run -p 8000:8000 --name ldap_jwt_auth_container --env AUTHENTICATION__ACCESS_TOKEN_VALIDITY_MINUTES=10 -v ./keys/jwt-key:/ldap-jwt-auth-run/keys/jwt-key -v ./keys/jwt-key.pub:/ldap-jwt-auth-run/keys/jwt-key.pub -v ./active_usernames.txt:/ldap-jwt-auth-run/active_usernames.txt -v ./logs:/ldap-jwt-auth-run/logs ldap_jwt_auth_image
```
The microservice should now be running inside Docker at http://localhost:8000 and its Swagger UI could be accessed
at http://localhost:8000/docs.

#### Using `Dockerfile.prod`
Use the `Dockerfile.prod` to run just the application itself in a container. This can be used for production.

1. While in root of the project directory, change the permissions of the `logs` directory so that it is writable by
other users. This allows the container to save the application logs to it.
```bash
sudo chmod -R 0777 logs/
```

2. Private keys are only readable by the owner. Given that the private key is generated on the host machine and the
container runs with a different user, it means that the key is not readable by the user in the container because the
ownership belongs to the user on the host. This can be solved by transferring the ownership to the user in the
container and setting the permissions.
```bash
sudo chown 500:500 keys/jwt-key
sudo chmod 0400 keys/jwt-key
```

3. Build an image using the `Dockerfile.prod` from the root of the project directory:
```bash
docker build -f Dockerfile.prod -t ldap_jwt_auth_image .
```

4. Start the container using the image built and map it to port `8000` locally:
```bash
docker run -p 8000:8000 --name ldap_jwt_auth_container -v ./keys/jwt-key:/ldap-jwt-auth-run/keys/jwt-key -v ./keys/jwt-key.pub:/ldap-jwt-auth-run/keys/jwt-key.pub -v ./active_usernames.txt:/ldap-jwt-auth-run/active_usernames.txt -v ./logs:/ldap-jwt-auth-run/logs ldap_jwt_auth_image
```
or with values for the environment variables:
```bash
docker run -p 8000:8000 --name ldap_jwt_auth_container --env AUTHENTICATION__ACCESS_TOKEN_VALIDITY_MINUTES=10 -v ./keys/jwt-key:/ldap-jwt-auth-run/keys/jwt-key -v ./keys/jwt-key.pub:/ldap-jwt-auth-run/keys/jwt-key.pub -v ./active_usernames.txt:/ldap-jwt-auth-run/active_usernames.txt -v ./logs:/ldap-jwt-auth-run/logs ldap_jwt_auth_image
```
The microservice should now be running inside Docker at http://localhost:8000 and its Swagger UI could be accessed
at http://localhost:8000/docs.

### Local Setup
Ensure that you have an LDAP server to connect to.
Ensure that Python is installed on your machine before proceeding.

1. Create a Python virtual environment and activate it in the root of the project directory:
```bash
Expand All @@ -68,21 +124,31 @@ Ensure that you have an LDAP server to connect to.
```bash
pip install .[dev]
```

4. Create a `.env` file alongside the `.env.example` file. Use the example file as a reference and modify the values
accordingly.
```bash
cp ldap_jwt_auth/.env.example ldap_jwt_auth/.env
```

5. Create a `logging.ini` file alongside the `logging.example.ini` file. Use the example file as a reference and modify
it accordingly.
it accordingly:
```bash
cp ldap_jwt_auth/logging.example.ini ldap_jwt_auth/logging.ini
```

6. Create a `keys` directory in the root of the project directory, navigate to it, and generate OpenSSH encoded private and public key pair:
6. Create a `keys` directory in the root of the project directory, navigate to it, and generate OpenSSH encoded private
and public key pair:
```bash
mkdir keys
cd keys/
ssh-keygen -b 2048 -t rsa -f jwt-key -q -N ""
ssh-keygen -b 2048 -t rsa -f jwt-key -q -N "" -C ""
```

7. Create a `active_usernames.txt` file alongside the `active_usernames.example.txt` file and add all the usernames (each one on a seperate line) that are active/can access the system.
7. Create a `active_usernames.txt` file alongside the `active_usernames.example.txt` file and add all the usernames that
can use this system. The usernames are the Federal IDs and each one should be stored on a separate line.
```bash
cp active_usernames.example.txt active_usernames.txt
```

8. Start the microservice using Uvicorn:
```bash
Expand All @@ -95,3 +161,28 @@ Ensure that you have an LDAP server to connect to.
```bash
pytest -c test/pytest.ini test/unit/
```

## Notes

### Application Configuration
The configuration for the application is handled
using [Pydantic Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). It allows for loading config
values from environment variables or the `.env` file. Please note that even when using the `.env` file, Pydantic will
still read environment variables as well as the `.env` file, environment variables will always take priority over
values loaded from the `.env` file.

Listed below are the environment variables supported by the application.

| Environment Variable | Description | Mandatory | Default Value |
|-------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|-----------|-----------------------------------------------------------|
| `API__TITLE` | The title of the API which is added to the generated OpenAPI. | No | `LDAP-JWT Authentication Service API` |
| `API__DESCRIPTION` | The description of the API which is added to the generated OpenAPI. | No | `This is the API for the LDAP-JWT Authentication Service` |
| `API__ROOT_PATH` | (If using a proxy) The path prefix handled by a proxy that is not seen by the app. | No | ` ` |
| `AUTHENTICATION__PRIVATE_KEY_PATH` | The path to the private key to be used for encoding JWT access and refresh tokens. | Yes | |
| `AUTHENTICATION__PUBLIC_KEY_PATH` | The path to the public key to be used for decoding JWT access and refresh tokens signed by the corresponding private key. | Yes | |
| `AUTHENTICATION__JWT_ALGORITHM` | The algorithm to use to decode the JWT access and refresh tokens. | Yes | |
| `AUTHENTICATION__ACCESS_TOKEN_VALIDITY_MINUTES` | Minutes after which the JWT access token expires. | Yes | |
| `AUTHENTICATION__REFRESH_TOKEN_VALIDITY_DAYS` | Days after which the JWT refresh token expires. | Yes | |
| `AUTHENTICATION__ACTIVE_USERNAMES_PATH` | The path to the `txt` file containing the active usernames and defining who can use this service. | Yes | |
| `LDAP_SERVER__URL` | The URL to the LDAP server to connect to. | Yes | |
| `LDAP_SERVER__REALM` | The realm for the LDAP server. | Yes | |

0 comments on commit 6f196f7

Please sign in to comment.