diff --git a/Dockerfile b/Dockerfile index 6333f9b..5ac808d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,16 +13,11 @@ COPY auth /usr/share/nginx/recovery COPY export /usr/share/nginx/export COPY import /usr/share/nginx/import -# prod EXPOSE 8080/tcp EXPOSE 8081/tcp EXPOSE 8082/tcp EXPOSE 8083/tcp -# preprod -EXPOSE 7070/tcp -EXPOSE 7071/tcp -EXPOSE 7072/tcp -EXPOSE 7073/tcp +WORKDIR /usr/share/nginx CMD ["nginx"] diff --git a/auth/index.preprod.html b/auth/index.preprod.html deleted file mode 100644 index 24a4cd4..0000000 --- a/auth/index.preprod.html +++ /dev/null @@ -1,1047 +0,0 @@ - - - - - - - Turnkey Recovery and Auth - - - - - -

Init Recovery or Auth

-

This public key will be sent along with your email inside of a new INIT_USER_EMAIL_RECOVERY or EMAIL_AUTH activity

-
- - - -
-
-
-
-

Inject Credential Bundle

-

The credential bundle will come from your email. This bundle can then be used for email recovery or auth. We can simulate this locally: see instructions here. A credential bundle is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on HPKE (RFC 9180).

-
- - - -
-
-
-
-

Stamp

-

Once you've injected the credential bundle, the credential is ready to sign. A new RECOVER activity for example. This iframe doesn't know anything about Turnkey activity however, it's a simple stamper!

-
- - - -
-
-
-
-

Message log

-

Below we display a log of the messages sent / received. The forms above send messages, and the code communicates results by sending events via the postMessage API.

-
- - - - - - - - diff --git a/export/index.preprod.html b/export/index.preprod.html deleted file mode 100644 index f82ba48..0000000 --- a/export/index.preprod.html +++ /dev/null @@ -1,845 +0,0 @@ - - - - - - - Turnkey Export - - - - - -

Export Key Material

-

This public key will be sent along with a private key ID or wallet ID inside of a new EXPORT_PRIVATE_KEY or EXPORT_WALLET activity

-
- - - -
-
-
-
-

Inject Key Export Bundle

-

The export bundle comes from the parent page and is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on HPKE (RFC 9180).

-
- - - -
- - -
- - -
-
-

Inject Wallet Export Bundle

-

The export bundle comes from the parent page and is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on HPKE (RFC 9180).

-
- - - -
- - -
-
-
-

Message log

-

Below we display a log of the messages sent / received. The forms above send messages, and the code communicates results by sending events via the postMessage API.

-
- - - - - - - - diff --git a/export/index.html b/export/index.template.html similarity index 97% rename from export/index.html rename to export/index.template.html index 768467b..0180a09 100644 --- a/export/index.html +++ b/export/index.template.html @@ -330,8 +330,15 @@

Message log

* Function to verify enclave signature on import bundle received from the server. */ async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, publicKey) { - /** Turnkey Signer enclave's public key */ - const TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY = "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569"; + /** Turnkey Signer enclave's public keys */ + const TURNKEY_SIGNERS_ENCLAVES = { + "prod": "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569", + "preprod": "04f3422b8afbe425d6ece77b8d2469954715a2ff273ab7ac89f1ed70e0a9325eaa1698b4351fd1b23734e65c0b6a86b62dd49d70b37c94606aac402cbd84353212" + } + const TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY = TURNKEY_SIGNERS_ENCLAVES["${TURNKEY_SIGNER_ENVIRONMENT}"]; + if (TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY === undefined) { + throw new Error("Configuration error: TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY is undefined") + } // todo(olivia): throw error if enclave quorum public is null once server changes are deployed if (enclaveQuorumPublic) { diff --git a/export/index.test.js b/export/index.test.js index 915e903..ca7793b 100644 --- a/export/index.test.js +++ b/export/index.test.js @@ -4,7 +4,7 @@ import fs from "fs" import path from "path" import * as crypto from "crypto"; -const html = fs.readFileSync(path.resolve(__dirname, "./index.html"), "utf8"); +const html = fs.readFileSync(path.resolve(__dirname, "./index.template.html"), "utf8").replace("${TURNKEY_SIGNER_ENVIRONMENT}", "prod"); let dom; let TKHQ; @@ -234,4 +234,4 @@ describe("TKHQ", () => { TKHQ.verifyEnclaveSignature(null, "30440220773382ac39085f58a584fd5ad8c8b91b50993ad480af2c5eaefe0b09447b6dca02205201c8e20a92bce524caac08a956b0c2e7447de9c68f91ab1e09fd58988041b5", "") ).rejects.toThrow('cannot create uint8array from invalid hex string: ""'); }) -}); \ No newline at end of file +}); diff --git a/import/index.html b/import/index.html deleted file mode 100644 index 36a038b..0000000 --- a/import/index.html +++ /dev/null @@ -1,708 +0,0 @@ - - - - - - - - Turnkey Import - - - - - -
- -
- - - - - - - - \ No newline at end of file diff --git a/import/index.preprod.html b/import/index.template.html similarity index 97% rename from import/index.preprod.html rename to import/index.template.html index fc0d552..5d5f5c7 100644 --- a/import/index.preprod.html +++ b/import/index.template.html @@ -287,8 +287,15 @@ * Function to verify enclave signature on import bundle received from the server. */ async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, publicKey) { - /** Turnkey Signer enclave's public key (preprod) */ - const TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY = "04f3422b8afbe425d6ece77b8d2469954715a2ff273ab7ac89f1ed70e0a9325eaa1698b4351fd1b23734e65c0b6a86b62dd49d70b37c94606aac402cbd84353212"; + /** Turnkey Signer enclave's public keys */ + const TURNKEY_SIGNERS_ENCLAVES = { + "prod": "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569", + "preprod": "04f3422b8afbe425d6ece77b8d2469954715a2ff273ab7ac89f1ed70e0a9325eaa1698b4351fd1b23734e65c0b6a86b62dd49d70b37c94606aac402cbd84353212" + } + const TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY = TURNKEY_SIGNERS_ENCLAVES["${TURNKEY_SIGNER_ENVIRONMENT}"]; + if (TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY === undefined) { + throw new Error("Configuration error: TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY is undefined") + } // todo(olivia): throw error if enclave quorum public is null once server changes are deployed if (enclaveQuorumPublic) { @@ -705,4 +712,4 @@ } - \ No newline at end of file + diff --git a/import/index.test.js b/import/index.test.js index 7cda000..857fd15 100644 --- a/import/index.test.js +++ b/import/index.test.js @@ -4,7 +4,7 @@ import fs from "fs" import path from "path" import * as crypto from "crypto"; -const html = fs.readFileSync(path.resolve(__dirname, "./index.html"), "utf8"); +const html = fs.readFileSync(path.resolve(__dirname, "./index.template.html"), "utf8").replace("${TURNKEY_SIGNER_ENVIRONMENT}", "prod"); let dom; let TKHQ; diff --git a/import/standalone.html b/import/standalone.template.html similarity index 97% rename from import/standalone.html rename to import/standalone.template.html index 933b10c..203ef76 100644 --- a/import/standalone.html +++ b/import/standalone.template.html @@ -339,8 +339,15 @@

Message log

* Function to verify enclave signature on import bundle received from the server. */ async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, publicKey) { - /** Turnkey Signer enclave's public key */ - const TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY = "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569"; + /** Turnkey Signer enclave's public keys */ + const TURNKEY_SIGNERS_ENCLAVES = { + "prod": "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569", + "preprod": "04f3422b8afbe425d6ece77b8d2469954715a2ff273ab7ac89f1ed70e0a9325eaa1698b4351fd1b23734e65c0b6a86b62dd49d70b37c94606aac402cbd84353212" + } + const TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY = TURNKEY_SIGNERS_ENCLAVES["${TURNKEY_SIGNER_ENVIRONMENT}"]; + if (TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY === undefined) { + throw new Error("Configuration error: TURNKEY_SIGNER_ENCLAVE_QUORUM_PUBLIC_KEY is undefined") + } // todo(olivia): throw error if enclave quorum public is null once server changes are deployed if (enclaveQuorumPublic) { @@ -683,4 +690,4 @@

Message log

} - \ No newline at end of file + diff --git a/kustomize/resources.yaml b/kustomize/resources.yaml index 57f68aa..c24526b 100644 --- a/kustomize/resources.yaml +++ b/kustomize/resources.yaml @@ -10,6 +10,30 @@ metadata: spec: template: spec: + initContainers: + - name: template-quorum-key + image: ghcr.io/tkhq/frames + env: + - name: TURNKEY_SIGNER_ENVIRONMENT + value: "prod" + command: + - sh + - -c + - | + mkdir -p templated/export templated/import; + envsubst '${TURNKEY_SIGNER_ENVIRONMENT}' < import/index.template.html > templated/import/index.html; + envsubst '${TURNKEY_SIGNER_ENVIRONMENT}' < import/standalone.template.html > templated/import/standalone.html; + envsubst '${TURNKEY_SIGNER_ENVIRONMENT}' < export/index.template.html > templated/export/index.html; + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsUser: 1000 + volumeMounts: + - name: templated + mountPath: /usr/share/nginx/templated containers: - name: frames image: ghcr.io/tkhq/frames @@ -36,7 +60,14 @@ spec: - ALL runAsNonRoot: true runAsUser: 1000 + volumeMounts: + - name: templated + mountPath: /usr/share/nginx/templated + readOnly: true serviceAccountName: frames + volumes: + - name: templated + emptyDir: {} --- apiVersion: v1 kind: Service diff --git a/nginx.conf b/nginx.conf index a046f76..1ade501 100644 --- a/nginx.conf +++ b/nginx.conf @@ -40,20 +40,23 @@ http { # Prod server { - listen 8080; - root /usr/share/nginx/auth; + listen 8080; + root /usr/share/nginx/auth; # Health endpoint for k8s - location = /health { + location = /health { access_log off; add_header 'Content-Type' 'application/json'; return 200 '{"status":"UP"}'; - } + } } server { listen 8081; - root /usr/share/nginx/export; + root /usr/share/nginx; + location / { + try_files /export/$uri /templated/export/$uri /templated/export/$uri/index.html =404; + } } server { @@ -63,38 +66,9 @@ http { server { listen 8083; - root /usr/share/nginx/import; - } - - # Preprod - server { - listen 7070; - root /usr/share/nginx/auth; - index index.preprod.html; - - # Health endpoint for k8s - location = /health { - access_log off; - add_header 'Content-Type' 'application/json'; - return 200 '{"status":"UP"}'; - } - } - - server { - listen 7071; - root /usr/share/nginx/export; - index index.preprod.html; - } - - server { - listen 7072; - root /usr/share/nginx/recovery; - index index.preprod.html; - } - - server { - listen 7073; - root /usr/share/nginx/import; - index index.preprod.html; + root /usr/share/nginx; + location / { + try_files /import/$uri /templated/import/$uri /templated/import/$uri/index.html =404; + } } }