diff --git a/backend/src/routes/v3/secrets.ts b/backend/src/routes/v3/secrets.ts index 1f3e239be..56573dd9f 100644 --- a/backend/src/routes/v3/secrets.ts +++ b/backend/src/routes/v3/secrets.ts @@ -23,7 +23,6 @@ import { router.get( "/raw", query("workspaceId").exists().isString().trim(), - query("workspaceId").exists().isString().trim(), query("environment").exists().isString().trim(), query("secretPath").default("/").isString().trim(), validateRequest, diff --git a/docs/api-reference/overview/authentication.mdx b/docs/api-reference/overview/authentication.mdx index 8bad0114f..5fa4fbc30 100644 --- a/docs/api-reference/overview/authentication.mdx +++ b/docs/api-reference/overview/authentication.mdx @@ -3,32 +3,29 @@ title: "Authentication" description: "How to authenticate with the Infisical Public API" --- -## Essentials +The Public API accepts multiple modes of authentication being via [Infisical Token](/documentation/platform/token) or API Key. -The Public API accepts multiple modes of authentication being via API Key or [Infisical Token](/documentation/platform/token). - -- API Key: Provides full access to all endpoints representing the user without ability to encrypt/decrypt secrets in **E2EE** mode. - [Infisical Token](/documentation/platform/token): Provides short-lived, scoped CRUD access to the secrets of a specific project and environment. +- API Key: Provides full access to all endpoints representing the user without ability to encrypt/decrypt secrets for **E2EE** endpoints. - - -The API key mode uses an API key to authenticate with the API. + + + The Infisical Token mode uses an Infisical Token to authenticate with the API. -To authenticate requests with Infisical using the API Key, you must include an API key in the `X-API-KEY` header of HTTP requests made to the platform. + To authenticate requests with Infisical using the Infisical Token, you must include your Infisical Token in the `Authorization` header of HTTP requests made to the platform with the value `Bearer `. -You can obtain an API key in User Settings > API Keys + You can obtain an Infisical Token in Project Settings > Service Tokens. -![API key dashboard](../../images/api-key-dashboard.png) -![API key in personal settings](../../images/api-key-settings.png) - - + ![token add](../../images/project-token-add.png) + + + The API key mode uses an API key to authenticate with the API. -The Infisical Token mode uses an Infisical Token to authenticate with the API. + To authenticate requests with Infisical using the API Key, you must include an API key in the `X-API-KEY` header of HTTP requests made to the platform. -To authenticate requests with Infisical using the Infisical Token, you must include your Infisical Token in the `Authorization` header of HTTP requests made to the platform with the value `Bearer `. + You can obtain an API key in User Settings > API Keys -You can obtain an Infisical Token in Project Settings > Service Tokens. - -![token add](../../images/project-token-add.png) - - \ No newline at end of file + ![API key dashboard](../../images/api-key-dashboard.png) + ![API key in personal settings](../../images/api-key-settings.png) + + \ No newline at end of file diff --git a/docs/api-reference/overview/encryption-modes/es-mode.mdx b/docs/api-reference/overview/encryption-modes/es-mode.mdx deleted file mode 100644 index 2756980ac..000000000 --- a/docs/api-reference/overview/encryption-modes/es-mode.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: "ES Mode" ---- - -Encrypted Standard (ES) mode is the easiest way to use Infisical's API. With it, you can make HTTP calls to Infisical -to read/write secrets in plaintext. - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](/documentation/platform/token) for your project and environment with write access enabled. -- [Ensure that your project is blind-indexed](../blind-indices). - -Below, we showcase how to execute common CRUD operations to manage secrets in **ES** mode: - - - - - - ```bash - curl --location --request GET 'http://localhost:8080/api/v3/secrets/raw?environment=dev&workspaceId=xxx' \ - --header 'Authorization: Bearer st.xxx' - - ``` - - - - - - - ```bash - curl --location --request POST 'http://localhost:8080/api/v3/secrets/raw/SECRET_NAME' \ - --header 'Authorization: Bearer st.xxx' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "workspaceId": "xxx", - "environment": "dev", - "type": "shared", - "secretValue": "SECRET_VALUE", - "secretPath": "/" - }' - ``` - - - - - - - ```bash - curl --location --request GET 'http://localhost:8080/api/v3/secrets/raw/SECRET_NAME?workspaceId=xxx&environment=dev&secretPath=/' \ - --header 'Authorization: Bearer st.xxx' - ``` - - - - - - - ```bash - curl --location --request PATCH 'http://localhost:8080/api/v3/secrets/raw/SECRET_NAME' \ - --header 'Authorization: Bearer st.xxx' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "workspaceId": "xxx", - "environment": "dev", - "type": "shared", - "secretValue": "SECRET_VALUE", - "secretPath": "/" - }' - ``` - - - - - - - ```bash - curl --location --request DELETE 'http://localhost:8080/api/v3/secrets/raw/SECRET_NAME' \ - --header 'Authorization: Bearer st.xxx' \ - --header 'Content-Type: application/json' \ - --data-raw '{ - "workspaceId": "xxx", - "environment": "dev", - "type": "shared", - "secretValue": "SECRET_VALUE", - "secretPath": "/" - }' - ``` - - - - diff --git a/docs/api-reference/overview/encryption-modes/overview.mdx b/docs/api-reference/overview/encryption-modes/overview.mdx deleted file mode 100644 index 84606d114..000000000 --- a/docs/api-reference/overview/encryption-modes/overview.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "Preface" ---- - -Each project in Infisical can be used either in **End-to-End Encrypted (E2EE)** mode or **Encrypted Standard (ES)** mode which dictates how it can be interacted with via the Infisical API. - - - - Secret operations without client-side encryption/decryption - - - Secret operations with client-side encryption/decryption - - - -By default, all projects are initialized in **E2EE** mode which means the server is not able to decrypt any values because all secret encryption/decryption operations occur on the client-side. However, this has limitations around functionality and ease-of-use: - -- You cannot make HTTP calls to Infisical to read/write secrets in plaintext. -- You cannot leverage non-E2EE features like native integrations and in-platform automations like dynamic secrets and secret rotation. - -For this reason, Infisical also provides the **ES** mode of operation to unlock the above limitations by enabling the server to decrypt your values. You can optionally switch a project to using **ES** mode -in your Project Settings. - - - Make no mistake, the limitations of **E2EE** mode do not prevent you from syncing secrets from Infisical to platforms like GitLab. They just imply - that you have to do things the "E2EE-way" such as by embedding the Infisical CLI into your GitLab CI/CD pipelines to fetch and decrypt - secrets on the client-side. - - -## FAQ - - - - We recommend starting with **E2EE** mode and switching to **ES** mode when: - - - Your team needs more power out of non-E2EE features available in **ES** mode such as secret rotation, dynamic secrets, etc. - - Your team wants an easier way to read/write secrets with Infisical. - - - - By default, all projects in Infisical are initialized to **E2EE** mode and can be switched to **ES** mode in the Project Settings by disabling end-to-end encryption. - - - **ES** mode is secure and in fact what most vendors in the secret management industry are doing at the moment. In this mode, secrets are encrypted at rest by - a series of keys, secured ultimately by a top-level `ROOT_ENCRYPTION_KEY` located on the server. - - If you're concerned about Infisical Cloud's ability to read your secrets if using **ES** mode in Infisical Cloud, then you may wish to - use Infisical Cloud in **E2EE** mode or self-host Infisical on your own infrastructure and then use **ES** mode; this of course which means setting up firewalls and securing the instance yourself. - - As an organization, we prohibit reading any customer secrets without explicit permission; access to the `ROOT_ENCRYPTION_KEY` is restricted to one individual in the organization. - - \ No newline at end of file diff --git a/docs/api-reference/overview/examples/create-secret.mdx b/docs/api-reference/overview/examples/create-secret.mdx deleted file mode 100644 index 4ea787ff0..000000000 --- a/docs/api-reference/overview/examples/create-secret.mdx +++ /dev/null @@ -1,233 +0,0 @@ ---- -title: "Create secret" -description: "How to add a secret using an Infisical Token scoped to a project and environment" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](/documentation/platform/token) for your project and environment with write access enabled. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). -- [Ensure that your project is blind-indexed](../blind-indices). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. Decrypt the (encrypted) project key with the key from your Infisical Token. -3. Encrypt your secret with the project key -4. [Send (encrypted) secret to Infisical](/api-reference/endpoints/secrets/create) - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); -const nacl = require('tweetnacl'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; -const BLOCK_SIZE_BYTES = 16; - -const encrypt = ({ text, secret }) => { - const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); - const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); - - let ciphertext = cipher.update(text, 'utf8', 'base64'); - ciphertext += cipher.final('base64'); - return { - ciphertext, - iv: iv.toString('base64'), - tag: cipher.getAuthTag().toString('base64') - }; -} - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const createSecrets = async () => { - const serviceToken = ''; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - const secretType = 'shared'; // 'shared' or 'personal' - const secretKey = 'some_key'; - const secretValue = 'some_value'; - const secretComment = 'some_comment'; - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 3. Encrypt your secret with the project key - const { - ciphertext: secretKeyCiphertext, - iv: secretKeyIV, - tag: secretKeyTag - } = encrypt({ - text: secretKey, - secret: projectKey - }); - - const { - ciphertext: secretValueCiphertext, - iv: secretValueIV, - tag: secretValueTag - } = encrypt({ - text: secretValue, - secret: projectKey - }); - - const { - ciphertext: secretCommentCiphertext, - iv: secretCommentIV, - tag: secretCommentTag - } = encrypt({ - text: secretComment, - secret: projectKey - }); - - // 4. Send (encrypted) secret to Infisical - await axios.post( - `${BASE_URL}/api/v3/secrets/${secretKey}`, - { - workspaceId: serviceTokenData.workspace, - environment: serviceTokenData.environment, - type: secretType, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag - }, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); -} - -createSecrets(); -``` - - - -```Python -import base64 -import requests -from Cryptodome.Cipher import AES -from Cryptodome.Random import get_random_bytes - - -BASE_URL = "https://app.infisical.com" -BLOCK_SIZE_BYTES = 16 - - -def encrypt(text, secret): - iv = get_random_bytes(BLOCK_SIZE_BYTES) - secret = bytes(secret, "utf-8") - cipher = AES.new(secret, AES.MODE_GCM, iv) - ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8")) - return { - "ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"), - "tag": base64.standard_b64encode(tag).decode("utf-8"), - "iv": base64.standard_b64encode(iv).decode("utf-8"), - } - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def create_secrets(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - secret_type = "shared" # "shared or "personal" - secret_key = "some_key" - secret_value = "some_value" - secret_comment = "some_comment" - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 3. Encrypt your secret with the project key - encrypted_key_data = encrypt(text=secret_key, secret=project_key) - encrypted_value_data = encrypt(text=secret_value, secret=project_key) - encrypted_comment_data = encrypt(text=secret_comment, secret=project_key) - - # 4. Send (encrypted) secret to Infisical - requests.post( - f"{BASE_URL}/api/v3/secrets/{secret_key}", - json={ - "workspaceId": service_token_data["workspace"], - "environment": service_token_data["environment"], - "type": secret_type, - "secretKeyCiphertext": encrypted_key_data["ciphertext"], - "secretKeyIV": encrypted_key_data["iv"], - "secretKeyTag": encrypted_key_data["tag"], - "secretValueCiphertext": encrypted_value_data["ciphertext"], - "secretValueIV": encrypted_value_data["iv"], - "secretValueTag": encrypted_value_data["tag"], - "secretCommentCiphertext": encrypted_comment_data["ciphertext"], - "secretCommentIV": encrypted_comment_data["iv"], - "secretCommentTag": encrypted_comment_data["tag"] - }, - headers={"Authorization": f"Bearer {service_token}"}, - ) - - -create_secrets() - -``` - - \ No newline at end of file diff --git a/docs/api-reference/overview/examples/delete-secret.mdx b/docs/api-reference/overview/examples/delete-secret.mdx deleted file mode 100644 index ff2ec687c..000000000 --- a/docs/api-reference/overview/examples/delete-secret.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: "Delete secret" -description: "How to delete a secret using an Infisical Token scoped to a project and environment" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create either an [API Key](/api-reference/overview/authentication) or [Infisical Token](/documentation/platform/token) for your project and environment with write access enabled. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). -- [Ensure that your project is blind-indexed](../blind-indices). - -## Example - - - -```js -const axios = require('axios'); -const BASE_URL = 'https://app.infisical.com'; - -const deleteSecrets = async () => { - const serviceToken = 'your_service_token'; - const secretType = 'shared' // 'shared' or 'personal' - const secretKey = 'some_key' - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Delete secret from Infisical - await axios.delete( - `${BASE_URL}/api/v3/secrets/${secretKey}`, - { - workspaceId: serviceTokenData.workspace, - environment: serviceTokenData.environment, - type: secretType - }, - { - headers: { - Authorization: `Bearer ${serviceToken}` - }, - } - ); -}; - -deleteSecrets(); -``` - - - -```Python -import requests - -BASE_URL = "https://app.infisical.com" - - -def delete_secrets(): - service_token = "" - secret_type = "shared" # "shared" or "personal" - secret_key = "some_key" - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Delete secret from Infisical - requests.delete( - f"{BASE_URL}/api/v2/secrets/{secret_key}", - json={ - "workspaceId": service_token_data["workspace"], - "environment": service_token_data["environment"], - "type": secret_type - }, - headers={"Authorization": f"Bearer {service_token}"}, - ) - - -delete_secrets() - -``` - - - - If using an `API_KEY` to authenticate with the Infisical API, then you should include it in the `X_API_KEY` header. - - diff --git a/docs/api-reference/overview/examples/e2ee-disabled.mdx b/docs/api-reference/overview/examples/e2ee-disabled.mdx new file mode 100644 index 000000000..9864a1ff5 --- /dev/null +++ b/docs/api-reference/overview/examples/e2ee-disabled.mdx @@ -0,0 +1,176 @@ +--- +title: "E2EE Disabled" +--- + +Using Infisical's API to read/write secrets with E2EE disabled allows you to create, update, and retrieve secrets +in plaintext. Effectively, this means each such secret operation only requires 1 HTTP call. + + + + Retrieve all secrets for an Infisical project and environment. + + + + ```bash + curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw?environment=environment&workspaceId=workspaceId' \ + --header 'Authorization: Bearer serviceToken' + + ``` + + + + + The ID of the workspace + + + The environment slug + + + Path to secrets in workspace + + + + Create a secret in Infisical. + + + + ```bash + curl --location --request POST 'https://app.infisical.com/api/v3/secrets/raw/secretName' \ + --header 'Authorization: Bearer serviceToken' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "workspaceId": "workspaceId", + "environment": "environment", + "type": "shared", + "secretValue": "secretValue", + "secretPath": "/" + }' + ``` + + + + + Name of secret to create + + + The ID of the workspace + + + The environment slug + + + Value of secret + + + Comment of secret + + + Path to secret in workspace + + + The type of the secret. Valid options are “shared” or “personal” + + + + Retrieve a secret from Infisical. + + + + ```bash + curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw/secretName?workspaceId=workspaceId&environment=environment' \ + --header 'Authorization: Bearer serviceToken' + ``` + + + + + Name of secret to retrieve + + + The ID of the workspace + + + The environment slug + + + Path to secrets in workspace + + + The type of the secret. Valid options are “shared” or “personal” + + + + Update an existing secret in Infisical. + + + + ```bash + curl --location --request PATCH 'https://app.infisical.com/api/v3/secrets/raw/secretName' \ + --header 'Authorization: Bearer serviceToken' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "workspaceId": "workspaceId", + "environment": "environment", + "type": "shared", + "secretValue": "secretValue", + "secretPath": "/" + }' + ``` + + + + + Name of secret to update + + + The ID of the workspace + + + The environment slug + + + Value of secret + + + Path to secret in workspace. + + + The type of the secret. Valid options are “shared” or “personal” + + + + Delete a secret in Infisical. + + + + ```bash + curl --location --request DELETE 'https://app.infisical.com/api/v3/secrets/raw/secretName' \ + --header 'Authorization: Bearer serviceToken' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "workspaceId": "workspaceId", + "environment": "environment", + "type": "shared", + "secretPath": "/" + }' + ``` + + + + + Name of secret to update + + + The ID of the workspace + + + The environment slug + + + Path to secret in workspace. + + + The type of the secret. Valid options are “shared” or “personal” + + + \ No newline at end of file diff --git a/docs/api-reference/overview/encryption-modes/e2ee-mode.mdx b/docs/api-reference/overview/examples/e2ee-enabled.mdx similarity index 97% rename from docs/api-reference/overview/encryption-modes/e2ee-mode.mdx rename to docs/api-reference/overview/examples/e2ee-enabled.mdx index b24ec9fb7..0cbeaabcf 100644 --- a/docs/api-reference/overview/encryption-modes/e2ee-mode.mdx +++ b/docs/api-reference/overview/examples/e2ee-enabled.mdx @@ -1,23 +1,16 @@ --- -title: "E2EE Mode" +title: "E2EE Enabled" --- -End-to-End Encrypted (E2EE) mode is the default way to use Infisical's API. With it, you must perform client-side encryption/decryption -when reading/writing secrets via HTTP call to Infisical. - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](/documentation/platform/token) for your project and environment with write access enabled. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). -- [Ensure that your project is blind-indexed](../blind-indices). - -Below, we showcase how to execute common CRUD operations to manage secrets in **E2EE** mode: +Using Infisical's API to read/write secrets with E2EE enabled allows you to create, update, and retrieve secrets +but requires you to perform client-side encryption/decryption operations. For this reason, we recommend using one of the available +SDKs instead. + Retrieve all secrets for an Infisical project and environment. ```js const crypto = require('crypto'); const axios = require('axios'); @@ -194,6 +187,7 @@ get_secrets() +Create a secret in Infisical. ```js const crypto = require('crypto'); const axios = require('axios'); @@ -408,6 +402,7 @@ create_secrets() + Retrieve a secret from Infisical. ```js const crypto = require('crypto'); const axios = require('axios'); @@ -569,6 +564,7 @@ get_secret() +Update an existing secret in Infisical. ```js const crypto = require('crypto'); const axios = require('axios'); @@ -779,6 +775,7 @@ update_secret() + Delete a secret in Infisical. ```js const axios = require('axios'); const BASE_URL = 'https://app.infisical.com'; diff --git a/docs/api-reference/overview/examples/note.mdx b/docs/api-reference/overview/examples/note.mdx new file mode 100644 index 000000000..8491dfaae --- /dev/null +++ b/docs/api-reference/overview/examples/note.mdx @@ -0,0 +1,54 @@ +--- +title: "Note on E2EE" +--- + +Each project in Infisical can have **End-to-End Encryption (E2EE)** enabled or disabled. + +By default, all projects have **E2EE** enabled which means the server is not able to decrypt any values because all secret encryption/decryption operations occur on the client-side; this can be (optionally) disabled. However, this has limitations around functionality and ease-of-use: + +- You cannot make HTTP calls to Infisical to read/write secrets in plaintext. +- You cannot leverage non-E2EE features like native integrations and in-platform automations like dynamic secrets and secret rotation. + + + + Example read/write secrets without client-side encryption/decryption + + + Example read/write secrets with client-side encryption/decryption + + + +## FAQ + + + + We recommend starting with having **E2EE** enabled and disabling it if: + + - You're self-hosting Infisical, so having your instance of Infisical be able to read your secrets isn't an issue. + - You want an easier way to read/write secrets with Infisical. + - You need more power out of non-E2EE features such as secret rotation, dynamic secrets, etc. + + + + You can enable/disable E2EE for your project in Infisical in the Project Settings. + + + It is secure and in fact how most vendors in our industry are able to offer features like secret rotation. In this mode, secrets are encrypted at rest by + a series of keys, secured ultimately by a top-level `ROOT_ENCRYPTION_KEY` located on the server. + + If you're concerned about Infisical Cloud's ability to read your secrets, then you may wish to + use it with **E2EE** enabled or self-host Infisical on your own infrastructure and disable E2EE there. + + As an organization, we do not read any customer secrets without explicit permission; access to the `ROOT_ENCRYPTION_KEY` is restricted to one individual in the organization. + + \ No newline at end of file diff --git a/docs/api-reference/overview/examples/retrieve-secret.mdx b/docs/api-reference/overview/examples/retrieve-secret.mdx deleted file mode 100644 index a65876253..000000000 --- a/docs/api-reference/overview/examples/retrieve-secret.mdx +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: "Retrieve secret" -description: "How to get a secret using an Infisical Token scoped to a project and environment" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](/documentation/platform/token) for your project and environment. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). -- [Ensure that your project is blind-indexed](../blind-indices). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. [Get the secret from your project and environment](/api-reference/endpoints/secrets/read-one). -3. Decrypt the (encrypted) project key with the key from your Infisical Token. -4. Decrypt the (encrypted) secret - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const getSecret = async () => { - const serviceToken = 'your_service_token'; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - const secretType = 'shared' // 'shared' or 'personal' - const secretKey = 'some_key'; - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Get the secret from your project and environment - const { data } = await axios.get( - `${BASE_URL}/api/v3/secrets/${secretKey}?${new URLSearchParams({ - environment: serviceTokenData.environment, - workspaceId: serviceTokenData.workspace, - type: secretType // optional, defaults to 'shared' - })}`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - const encryptedSecret = data.secret; - - // 3. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 4. Decrypt the (encrypted) secret value - - const secretValue = decrypt({ - ciphertext: encryptedSecret.secretValueCiphertext, - iv: encryptedSecret.secretValueIV, - tag: encryptedSecret.secretValueTag, - secret: projectKey - }); - - console.log('secret: ', ({ - secretKey, - secretValue - })); -} - -getSecret(); - -``` - - - -```Python -import requests -import base64 -from Cryptodome.Cipher import AES - - -BASE_URL = "http://app.infisical.com" - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def get_secret(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - secret_type = "shared" # "shared" or "personal" - secret_key = "some_key" - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Get secret from your project and environment - data = requests.get( - f"{BASE_URL}/api/v3/secrets/{secret_key}", - params={ - "environment": service_token_data["environment"], - "workspaceId": service_token_data["workspace"], - "type": secret_type # optional, defaults to "shared" - }, - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - encrypted_secret = data["secret"] - - # 3. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 4. Decrypt the (encrypted) secret value - secret_value = decrypt( - ciphertext=encrypted_secret["secretValueCiphertext"], - iv=encrypted_secret["secretValueIV"], - tag=encrypted_secret["secretValueTag"], - secret=project_key, - ) - - print("secret: ", { - "secret_key": secret_key, - "secret_value": secret_value - }) - - -get_secret() - -``` - - \ No newline at end of file diff --git a/docs/api-reference/overview/examples/retrieve-secrets.mdx b/docs/api-reference/overview/examples/retrieve-secrets.mdx deleted file mode 100644 index f237822aa..000000000 --- a/docs/api-reference/overview/examples/retrieve-secrets.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: "Retrieve secrets" -description: "How to get all secrets using an Infisical Token scoped to a project and environment" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](/documentation/platform/token) for your project and environment. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). -- [Ensure that your project is blind-indexed](../blind-indices). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. [Get secrets for your project and environment](/api-reference/endpoints/secrets/read). -3. Decrypt the (encrypted) project key with the key from your Infisical Token. -4. Decrypt the (encrypted) secrets - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const getSecrets = async () => { - const serviceToken = 'your_service_token'; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Get secrets for your project and environment - const { data } = await axios.get( - `${BASE_URL}/api/v3/secrets?${new URLSearchParams({ - environment: serviceTokenData.environment, - workspaceId: serviceTokenData.workspace - })}`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - const encryptedSecrets = data.secrets; - - // 3. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 4. Decrypt the (encrypted) secrets - const secrets = encryptedSecrets.map((secret) => { - const secretKey = decrypt({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - secret: projectKey - }); - - const secretValue = decrypt({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - secret: projectKey - }); - - return ({ - secretKey, - secretValue - }); - }); - - console.log('secrets: ', secrets); -} - -getSecrets(); - -``` - - - -```Python -import requests -import base64 -from Cryptodome.Cipher import AES - - -BASE_URL = "http://app.infisical.com" - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def get_secrets(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Get secrets for your project and environment - data = requests.get( - f"{BASE_URL}/api/v3/secrets", - params={ - "environment": service_token_data["environment"], - "workspaceId": service_token_data["workspace"], - }, - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - encrypted_secrets = data["secrets"] - - # 3. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 4. Decrypt the (encrypted) secrets - secrets = [] - for secret in encrypted_secrets: - secret_key = decrypt( - ciphertext=secret["secretKeyCiphertext"], - iv=secret["secretKeyIV"], - tag=secret["secretKeyTag"], - secret=project_key, - ) - - secret_value = decrypt( - ciphertext=secret["secretValueCiphertext"], - iv=secret["secretValueIV"], - tag=secret["secretValueTag"], - secret=project_key, - ) - - secrets.append( - { - "secret_key": secret_key, - "secret_value": secret_value, - } - ) - - print("secrets:", secrets) - - -get_secrets() - -``` - - \ No newline at end of file diff --git a/docs/api-reference/overview/examples/update-secret.mdx b/docs/api-reference/overview/examples/update-secret.mdx deleted file mode 100644 index 49255aa79..000000000 --- a/docs/api-reference/overview/examples/update-secret.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "Update secret" -description: "How to update a secret using an Infisical Token scoped to a project and environment" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](/documentation/platform/token) for your project and environment with write access enabled. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). -- [Ensure that your project is blind-indexed](../blind-indices). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. Decrypt the (encrypted) project key with the key from your Infisical Token. -3. Encrypt your updated secret with the project key -4. [Send (encrypted) updated secret to Infical](/api-reference/endpoints/secrets/update) - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; -const BLOCK_SIZE_BYTES = 16; - -const encrypt = ({ text, secret }) => { - const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); - const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); - - let ciphertext = cipher.update(text, 'utf8', 'base64'); - ciphertext += cipher.final('base64'); - return { - ciphertext, - iv: iv.toString('base64'), - tag: cipher.getAuthTag().toString('base64') - }; -} - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const updateSecrets = async () => { - const serviceToken = 'your_service_token'; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - const secretType = 'shared' // 'shared' or 'personal' - const secretKey = 'some_key'; - const secretValue = 'updated_value'; - const secretComment = 'updated_comment'; - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 3. Encrypt your updated secret with the project key - const { - ciphertext: secretKeyCiphertext, - iv: secretKeyIV, - tag: secretKeyTag - } = encrypt({ - text: secretKey, - secret: projectKey - }); - - const { - ciphertext: secretValueCiphertext, - iv: secretValueIV, - tag: secretValueTag - } = encrypt({ - text: secretValue, - secret: projectKey - }); - - const { - ciphertext: secretCommentCiphertext, - iv: secretCommentIV, - tag: secretCommentTag - } = encrypt({ - text: secretComment, - secret: projectKey - }); - - // 4. Send (encrypted) updated secret to Infisical - await axios.patch( - `${BASE_URL}/api/v3/secrets/${secretKey}`, - { - workspaceId: serviceTokenData.workspace, - environment: serviceTokenData.environment, - type: secretType, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag - }, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); -} - -updateSecrets(); -``` - - - -```Python -import base64 -import requests -from Cryptodome.Cipher import AES -from Cryptodome.Random import get_random_bytes - - -BASE_URL = "https://app.infisical.com" -BLOCK_SIZE_BYTES = 16 - - -def encrypt(text, secret): - iv = get_random_bytes(BLOCK_SIZE_BYTES) - secret = bytes(secret, "utf-8") - cipher = AES.new(secret, AES.MODE_GCM, iv) - ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8")) - return { - "ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"), - "tag": base64.standard_b64encode(tag).decode("utf-8"), - "iv": base64.standard_b64encode(iv).decode("utf-8"), - } - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def update_secret(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - secret_type = "shared" # "shared" or "personal" - secret_key = "some_key" - secret_value = "updated_value" - secret_comment = "updated_comment" - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 3. Encrypt your updated secret with the project key - encrypted_key_data = encrypt(text=secret_key, secret=project_key) - encrypted_value_data = encrypt(text=secret_value, secret=project_key) - encrypted_comment_data = encrypt(text=secret_comment, secret=project_key) - - # 4. Send (encrypted) updated secret to Infisical - requests.patch( - f"{BASE_URL}/api/v3/secrets/{secret_key}", - json={ - "workspaceId": service_token_data["workspace"], - "environment": service_token_data["environment"], - "type": secret_type, - "secretKeyCiphertext": encrypted_key_data["ciphertext"], - "secretKeyIV": encrypted_key_data["iv"], - "secretKeyTag": encrypted_key_data["tag"], - "secretValueCiphertext": encrypted_value_data["ciphertext"], - "secretValueIV": encrypted_value_data["iv"], - "secretValueTag": encrypted_value_data["tag"], - "secretCommentCiphertext": encrypted_comment_data["ciphertext"], - "secretCommentIV": encrypted_comment_data["iv"], - "secretCommentTag": encrypted_comment_data["tag"] - }, - headers={"Authorization": f"Bearer {service_token}"}, - ) - - -update_secret() - -``` - - \ No newline at end of file diff --git a/docs/mint.json b/docs/mint.json index 7be970770..9dba735e6 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -250,9 +250,9 @@ { "group": "Examples", "pages": [ - "api-reference/overview/encryption-modes/overview", - "api-reference/overview/encryption-modes/es-mode", - "api-reference/overview/encryption-modes/e2ee-mode" + "api-reference/overview/examples/note", + "api-reference/overview/examples/e2ee-disabled", + "api-reference/overview/examples/e2ee-enabled" ] }, "api-reference/overview/blind-indices"