Skip to content

Commit

Permalink
Merge pull request #40 from icebreakerone/kip/certificates
Browse files Browse the repository at this point in the history
Improve self-signed certificate script and docs
  • Loading branch information
kipparker authored Jul 30, 2024
2 parents 6638017 + 0f13738 commit 0d2dd84
Show file tree
Hide file tree
Showing 7 changed files with 839 additions and 388 deletions.
8 changes: 4 additions & 4 deletions .github/templates/test/action.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: test
description: Run python tests
inputs:
folder:
description: 'The folder to run tests in'
folder:
description: "The folder to run tests in"
required: true

runs:
Expand All @@ -19,10 +19,10 @@ runs:
run: |
# stop the build if there are Python syntax errors or undefined names
cd ${{ inputs.folder }}
pipenv run ruff .
pipenv run ruff check .
- name: Run ${{ inputs.folder }} tests
shell: bash
run: |
# stop the build if there are Python syntax errors or undefined names
cd ${{ inputs.folder }}
pipenv run pytest .
pipenv run pytest .
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,23 @@ pipenv run uvicorn api.main:app --reload

## Creating self-signed certificates

The docker compose and client.py scripts require a set of self-signed certificates in a certs/ folder. These can be generated using the `certmaker.sh` script in the `scripts` directory.
The docker compose and client.py scripts require a set of self-signed certificates in a certs/ folder. `certmaker.sh` generates a set of certificates suitable for emulating the certificates issued by the Perseus Scheme, and are used by the development server and client testing scripts.

```bash
cd scripts
./certmaker.sh
```

By default, the certmaker script will create a server certificate for the local host it is run on (ie. using the output of `hostname`). This value can be changed by setting the SERVER_HOSTNAME environment variable, eg.

```bash
SERVER_HOSTNAME="perseus-demo-authentication.ib1.org" ./certmaker.sh
```

You will need to create a "certs" directory in the root of the project, and move the generated certificates into it.

**nb** The generated certificates include reasonable values suitable for testing, but in production certificates will be issued by the Perseus directory service.

### Using client certificates

Most of the endpoints require a client certificate to be presented. As the directory service is not yet available, the contents of the certificate will not be checked with an external CA, so any valid certificate will be acceptable. The certificate **is** used to confirm identity, so the same one must be presented in all requests.
Expand Down
1,147 changes: 799 additions & 348 deletions authentication/Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion authentication/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ async def token(
redirect_uri: Annotated[str, Form()],
code_verifier: Annotated[str, Form()],
code: Annotated[str, Form()],
x_amzn_mtls_clientcert: Annotated[str, Header()],
x_amzn_mtls_clientcert: Annotated[str | None, Header()],
) -> models.TokenResponse:
"""
Token issuing endpoint
Expand Down
2 changes: 1 addition & 1 deletion client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
RESOURCE_API = os.environ.get("RESOURCE_API", "https://0.0.0.0:8010")

ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
CLIENT_CERTIFICATE = f"{ROOT_PATH}/certs/client-cert.pem"
CLIENT_CERTIFICATE = f"{ROOT_PATH}/certs/client-bundle.pem"
CLIENT_PRIVATE_KEY = f"{ROOT_PATH}/certs/client-key.pem"


Expand Down
7 changes: 3 additions & 4 deletions nginx/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ server {
server_name localhost;
# add hosts your domain for local requests
# server certificate
ssl_certificate /etc/nginx/certs/server-cert.pem;
ssl_certificate /etc/nginx/certs/server-cert-bundle.pem;
ssl_certificate_key /etc/nginx/certs/server-key.pem;
# CA certificate
ssl_client_certificate /etc/nginx/certs/ca-cert.pem;
# need to validate client certificate(if this flag optional_no_ca it won't validate client certificates)
ssl_verify_client optional_no_ca;
ssl_client_certificate /etc/nginx/certs/client-ca-cert.pem;
ssl_verify_client optional;
location / {
# remote ip and forwarding ip
proxy_set_header X-Real-IP $remote_addr;
Expand Down
51 changes: 22 additions & 29 deletions scripts/certmaker.sh
Original file line number Diff line number Diff line change
@@ -1,42 +1,35 @@
# Generate CA private key
openssl genpkey -algorithm RSA -out ca-key.pem

# Generate CA self-signed certificate
openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -subj "/C=GB/ST=London/O=Perseus CA/CN=perseus-demo-fapi.ib1.org"
# Perseus Trust Framework CA
openssl genpkey -algorithm RSA -out server-ca-key.pem
openssl req -new -x509 -key server-ca-key.pem -out server-ca-cert.pem -days 3560 \
-subj "/C=GB/O=Perseus Trust Framework/CN=Perseus Trust Framework Server CA"

# Generate server private key
openssl genpkey -algorithm RSA -out server-key.pem

# Generate server CSR
openssl req -new -key server-key.pem -out server-csr.pem -subj "/C=GB/ST=London/O=Perseus Demo Authentication/CN=perseus-demo-authentication.ib1.org"
openssl req -new -key server-key.pem -out server-csr.pem \
-subj "/C=GB/ST=London/O=Perseus Trust Framework/CN=${SERVER_HOSTNAME:-`hostname`}"

# Sign the server CSR with CA key and certificate
openssl x509 -req -in server-csr.pem -out server-cert.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -days 365

# Generate client private key
openssl genpkey -algorithm RSA -out client-key.pem

# Generate client CSR
openssl req -new -key client-key.pem -out client-csr.pem -subj "/C=GB/ST=London/O=Perseus Demo Accountancy/CN=perseus-demo-accountancy.ib1.org"
openssl x509 -req -in server-csr.pem -out server-cert.pem -CA server-ca-cert.pem \
-CAkey server-ca-key.pem -days 365

# Sign the client CSR with CA key and certificate
openssl x509 -req -in client-csr.pem -out client-cert.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -days 365
# Bundle server and CA certificates
cat server-cert.pem server-ca-cert.pem > server-cert-bundle.pem


# # Generate private key for the server
# openssl genpkey -algorithm RSA -out server-key.pem
# Perseus Trust Framework Client CA
openssl genpkey -algorithm RSA -out client-ca-key.pem
openssl req -new -x509 -key client-ca-key.pem -out client-ca-cert.pem -days 3560 \
-subj "/C=GB/O=Perseus Trust Framework/CN=Perseus Trust Framework Client CA"

# # Generate CSR for the server with subject information
# openssl req -new -key server-key.pem -out server-csr.pem -subj "/C=GB/ST=London/O=Perseus Demo Authentication/CN=perseus-demo-authentication.ib1.org"

# # Create PEM
# openssl x509 -req -days 365 -in server-csr.pem -signkey server-key.pem -out server-cert.pem

# # Generate private key for the client
# openssl genpkey -algorithm RSA -out client-key.pem
# Client Key
openssl genpkey -algorithm RSA -out client-key.pem

# # Generate CSR for the client with subject information
# openssl req -new -key client-key.pem -out client-csr.pem -subj "/C=GB/ST=London/O=Perseus Demo Accountancy/CN=perseus-demo-accountancy.ib1.org"
# Client CSR
openssl req -new -key client-key.pem -out client-csr.pem \
-subj "/C=GB/ST=London/O=Application One/OU=carbon-accounting@perseus/CN=https:\/\/directory.core.demo.ib1.org\/member\/81524"
openssl x509 -req -in client-csr.pem -out client-cert.pem \
-CA client-ca-cert.pem -CAkey client-ca-key.pem -days 365
cat client-cert.pem client-ca-cert.pem > client-bundle.pem

# # Create PEM
# openssl x509 -req -days 365 -in client-csr.pem -signkey client-key.pem -out client-cert.pem

0 comments on commit 0d2dd84

Please sign in to comment.