Skip to content

Commit

Permalink
feat(sdk): Adds TLS Certificate Exchange Flow (#667)
Browse files Browse the repository at this point in the history
This PR Introduces a way to Authenticate from IDP using TLS
Certificates.
- TLS Config Option to Authenticate from SDK
- Fixtures that add the X509 Certificate Authentication Flow in IDP
- Updated OAuth Testing to ensure Exchange Works
- Adds Init Certificates Setup for docker compose
- Updates Docker Compose to require HTTPS
  • Loading branch information
imdominicreed committed Apr 29, 2024
1 parent 655d527 commit 0e59213
Show file tree
Hide file tree
Showing 19 changed files with 666 additions and 35 deletions.
18 changes: 18 additions & 0 deletions .github/scripts/init-temp-keys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,21 @@ if [ "$opt_hsm" = true ]; then
pkcs11-tool --module "${OPENTDF_SERVER_CRYPTOPROVIDER_HSM_MODULEPATH}" --login --pin "${OPENTDF_SERVER_CRYPTOPROVIDER_HSM_PIN}" --write-object kas-ec-private.pem --type privkey --label "${OPENTDF_SERVER_CRYPTOPROVIDER_HSM_KEYS_EC_LABEL}" --usage-derive
pkcs11-tool --module "${OPENTDF_SERVER_CRYPTOPROVIDER_HSM_MODULEPATH}" --login --pin "${OPENTDF_SERVER_CRYPTOPROVIDER_HSM_PIN}" --write-object kas-ec-cert.pem --type cert --label "${OPENTDF_SERVER_CRYPTOPROVIDER_HSM_KEYS_EC_LABEL}"
fi

mkdir -p keys
openssl req -x509 -nodes -newkey RSA:2048 -subj "/CN=ca" -keyout keys/keycloak-ca-private.pem -out keys/keycloak-ca.pem -days 365
printf "subjectAltName=DNS:localhost,IP:127.0.0.1" > keys/sanX509.conf
printf "[req]\ndistinguished_name=req_distinguished_name\n[req_distinguished_name]\n[alt_names]\nDNS.1=localhost\nIP.1=127.0.0.1" > keys/req.conf
openssl req -new -nodes -newkey rsa:2048 -keyout keys/localhost.key -out keys/localhost.req -batch -subj "/CN=localhost" -config keys/req.conf
openssl x509 -req -in keys/localhost.req -CA keys/keycloak-ca.pem -CAkey keys/keycloak-ca-private.pem -CAcreateserial -out keys/localhost.crt -days 3650 -sha256 -extfile keys/sanX509.conf
openssl req -new -nodes -newkey rsa:2048 -keyout keys/sampleuser.key -out keys/sampleuser.req -batch -subj "/CN=sampleuser"
openssl x509 -req -in keys/sampleuser.req -CA keys/keycloak-ca.pem -CAkey keys/keycloak-ca-private.pem -CAcreateserial -out keys/sampleuser.crt -days 3650

openssl pkcs12 -export -in keys/keycloak-ca.pem -inkey keys/keycloak-ca-private.pem -out keys/ca.p12 -nodes -passout pass:password
docker run -v $(pwd)/keys:/keys openjdk:latest keytool -importkeystore -srckeystore /keys/ca.p12 \
-srcstoretype PKCS12 \
-destkeystore /keys/ca.jks \
-deststoretype JKS \
-srcstorepass "password" \
-deststorepass "password" \
-noprompt
8 changes: 7 additions & 1 deletion .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ jobs:
echo "directories.tokendir = $(pwd)/.tmp/tokens" > softhsm2.conf
echo "log.level = DEBUG" >> softhsm2.conf
echo "SOFTHSM2_CONF=$(pwd)/softhsm2.conf" >> "$GITHUB_ENV"
- run: docker compose up -d --wait --wait-timeout 240
- run: |
.github/scripts/init-temp-keys.sh --hsm
cp opentdf-with-hsm.yaml opentdf.yaml
Expand All @@ -118,6 +117,13 @@ jobs:
.github/scripts/init-temp-keys.sh
cp opentdf-dev.yaml opentdf.yaml
if: matrix.crypto == 'standard'
- name: Added Trusted Certs
run: |
sudo chmod -R 777 ./keys
sudo apt-get install -y ca-certificates
sudo cp ./keys/localhost.crt /usr/local/share/ca-certificates
sudo update-ca-certificates
- run: docker compose up -d --wait --wait-timeout 240
- run: go run ./service provision keycloak
- uses: JarvusInnovations/background-action@2428e7b970a846423095c79d43f759abf979a635
name: start server in background
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ tmp-gen/

*.zip
sensitive.txt.tdf
keys/
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,17 @@

### Setting up pre-requisites

1. Stand up the local Postgres database and Keycloak instances using `docker-compose up -d --wait`.
2. Copy the `opentdf-example.yaml` file to `opentdf.yaml` and update the [configuration](./docs/configuration.md) as needed.
3. Bootstrap Keycloak
1. Initialize KAS Keys ```.github/scripts/init-temp-keys.sh -o kas-keys```
2. Stand up the local Postgres database and Keycloak instances using `docker-compose up -d --wait`.
3. Copy the `opentdf-example.yaml` file to `opentdf.yaml` and update the [configuration](./docs/configuration.md) as needed.
Bootstrap Keycloak

```sh
docker run --network opentdf_platform \
-v ./opentdf.yaml:/home/nonroot/.opentdf/opentdf.yaml \
-it registry.opentdf.io/platform:nightly provision keycloak -e http://keycloak:8888/auth
```

4. Initialize KAS Keys ```.github/scripts/init-temp-keys.sh -o kas-keys```
5. Start the platform
4. Start the platform

```sh
docker run --network opentdf_platform \
Expand Down Expand Up @@ -64,12 +63,13 @@ brew install buf go golangci-lint goose grpcurl openssl
> needed. They can also be run manually using the `migrate` command
> (`go run github.com/opentdf/platform/service migrate up`).
1. `docker-compose up`. Starts both the local Postgres database (contains the ABAC policy configuration data) and Keycloak (the local IdP).
2. Create an OpenTDF config file: `opentdf.yaml`
1. Configure KAS and Keycloak keys: `.github/scripts/init-temp-keys.sh`. Creates temporary keys for the local KAS and Keycloak Certificate Exchange.
2. `docker-compose up`. Starts both the local Postgres database (contains the ABAC policy configuration data) and Keycloak (the local IdP).
1. Note: You will have to add the ``localhost.crt`` as a trusted certificate to do TLS authentication at ``localhost:8443``.
3. Create an OpenTDF config file: `opentdf.yaml`
1. The `opentdf-dev.yaml` file is the more secure starting point, but you will likely need to modify it to match your environment. This configuration is recommended as it is more secure but it does require valid development keypairs.
2. The `opentdf-example-no-kas.yaml` file is simpler to run but less secure. This file configures the platform to startup without a KAS instances and without endpoint authentication.
3. Provision keycloak: `go run github.com/opentdf/platform/service provision keycloak`. Updates the local Keycloak configuration for local testing and development by creating a realm, roles, a client, and users.
4. Configure KAS keys: `.github/scripts/init-temp-keys.sh`. Creates temporary keys for the local KAS. This step can be ignored if you are running the 'opentdf-example-no-kas' configuration in step 2.
4. Provision keycloak: `go run github.com/opentdf/platform/service provision keycloak`. Updates the local Keycloak configuration for local testing and development by creating a realm, roles, a client, and users.
5. Run the server: `go run github.com/opentdf/platform/service start`. Runs the OpenTDF platform capabilities as a monolithic service.
1. _Alt_ use the hot-reload development environment `air`
6. The server is now running on `localhost:8080` (or the port specified in the config file)
Expand Down
21 changes: 19 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@ networks:
name: opentdf_platform
services:
keycloak:
volumes:
- ./keys/localhost.crt:/etc/x509/tls/localhost.crt
- ./keys/localhost.key:/etc/x509/tls/localhost.key
- ./keys/ca.jks:/truststore/truststore.jks
# This is kc 24.0.1 with opentdf protocol mapper on board
image: ghcr.io/opentdf/keycloak:sha-8a6d35a
restart: always
command: ["start-dev"]
command:
- "start-dev"
- "--verbose"
- "-Djavax.net.ssl.trustStorePassword=password"
- "-Djavax.net.ssl.HostnameVerifier=AllowAll"
- "-Djavax.net.ssl.trustStore=/truststore/truststore.jks"
- "--spi-truststore-file-hostname-verification-policy=ANY"
environment:
KC_HTTP_RELATIVE_PATH: /auth
KC_DB_VENDOR: postgres
Expand All @@ -15,18 +25,25 @@ services:
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: changeme
KC_HOSTNAME_PORT: "8888"
KC_HOSTNAME_STRICT: "false"
KC_HOSTNAME_STRICT_BACKCHANNEL: "false"
KC_HOSTNAME_STRICT_HTTPS: "false"
KC_HTTP_ENABLED: "true"
KC_HTTP_PORT: "8888"
KC_HTTPS_PORT: "8443"
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: changeme
KC_HOSTNAME_URL: http://localhost:8888/auth
KC_FEATURES: "preview,token-exchange"
KC_HEALTH_ENABLED: "true"
KC_HTTPS_KEY_STORE_PASSWORD: "password"
KC_HTTPS_KEY_STORE_FILE: "/truststore/truststore.jks"
KC_HTTPS_CERTIFICATE_FILE: "/etc/x509/tls/localhost.crt"
KC_HTTPS_CERTIFICATE_KEY_FILE: "/etc/x509/tls/localhost.key"
KC_HTTPS_CLIENT_AUTH: "request"
ports:
- "8888:8888"
- "8443:8443"
healthcheck:
test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:8888/auth/health/live']
interval: 5s
Expand Down

0 comments on commit 0e59213

Please sign in to comment.