From b21cb521dadcb32e3445ab7f3848acb00ae81274 Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Sun, 4 Dec 2022 23:03:57 -0500 Subject: [PATCH 1/6] Tranforming more components to typescript (#47) --- .../basic/dialog/AddServiceTokenDialog.js | 2 +- frontend/components/basic/layout.js | 6 ++-- frontend/components/basic/table/UserTable.js | 2 +- frontend/components/navigation/NavHeader.tsx | 4 +-- .../secrets/{pushKeys.js => pushKeys.ts} | 28 +++++++++++++------ .../{GetOrgUsers.js => GetOrgUsers.ts} | 4 +-- ...{createWorkspace.js => createWorkspace.ts} | 9 +++--- ...etLatestFileKey.js => getLatestFileKey.ts} | 6 ++-- ...etWorkspaceKeys.js => getWorkspaceKeys.ts} | 9 +++--- ...WorkspaceUsers.js => getWorkspaceUsers.ts} | 9 +++--- .../{getWorkspaces.js => getWorkspaces.ts} | 8 ++---- frontend/pages/dashboard/[id].js | 4 +-- 12 files changed, 49 insertions(+), 42 deletions(-) rename frontend/components/utilities/secrets/{pushKeys.js => pushKeys.ts} (69%) rename frontend/pages/api/organization/{GetOrgUsers.js => GetOrgUsers.ts} (85%) rename frontend/pages/api/workspace/{createWorkspace.js => createWorkspace.ts} (61%) rename frontend/pages/api/workspace/{getLatestFileKey.js => getLatestFileKey.ts} (79%) rename frontend/pages/api/workspace/{getWorkspaceKeys.js => getWorkspaceKeys.ts} (73%) rename frontend/pages/api/workspace/{getWorkspaceUsers.js => getWorkspaceUsers.ts} (69%) rename frontend/pages/api/workspace/{getWorkspaces.js => getWorkspaces.ts} (69%) diff --git a/frontend/components/basic/dialog/AddServiceTokenDialog.js b/frontend/components/basic/dialog/AddServiceTokenDialog.js index 8147253b5..7ff1789b8 100644 --- a/frontend/components/basic/dialog/AddServiceTokenDialog.js +++ b/frontend/components/basic/dialog/AddServiceTokenDialog.js @@ -37,7 +37,7 @@ const AddServiceTokenDialog = ({ const [serviceTokenCopied, setServiceTokenCopied] = useState(false); const generateServiceToken = async () => { - const latestFileKey = await getLatestFileKey(workspaceId); + const latestFileKey = await getLatestFileKey({ workspaceId }); const key = decryptAssymmetric({ ciphertext: latestFileKey.latestKey.encryptedKey, diff --git a/frontend/components/basic/layout.js b/frontend/components/basic/layout.js index 6482c57ac..effe38942 100644 --- a/frontend/components/basic/layout.js +++ b/frontend/components/basic/layout.js @@ -56,10 +56,10 @@ export default function Layout({ children }) { const workspaces = await getWorkspaces(); const currentWorkspaces = workspaces.map((workspace) => workspace.name); if (!currentWorkspaces.includes(workspaceName)) { - const newWorkspace = await createWorkspace( + const newWorkspace = await createWorkspace({ workspaceName, - localStorage.getItem("orgData.id") - ); + organizationId: localStorage.getItem("orgData.id") + }); let newWorkspaceId; try { newWorkspaceId = newWorkspace._id; diff --git a/frontend/components/basic/table/UserTable.js b/frontend/components/basic/table/UserTable.js index 5b2634d94..881556b70 100644 --- a/frontend/components/basic/table/UserTable.js +++ b/frontend/components/basic/table/UserTable.js @@ -88,7 +88,7 @@ const UserTable = ({ }, [userData, myUser]); const grantAccess = async (id, publicKey) => { - let result = await getLatestFileKey(router.query.id); + let result = await getLatestFileKey({workspaceId: router.query.id}); const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); diff --git a/frontend/components/navigation/NavHeader.tsx b/frontend/components/navigation/NavHeader.tsx index d6d8713ba..3d64c2eda 100644 --- a/frontend/components/navigation/NavHeader.tsx +++ b/frontend/components/navigation/NavHeader.tsx @@ -25,12 +25,12 @@ export default function NavHeader({ pageName, isProjectRelated } : { pageName: s useEffect(() => { (async () => { const orgId = localStorage.getItem("orgData.id") - let org = await getOrganization({ + const org = await getOrganization({ orgId: orgId ? orgId : "", }); setOrgName(org.name); - let workspace = await getProjectInfo({ + const workspace = await getProjectInfo({ projectId: String(router.query.id), }); setWorkspaceName(workspace.name); diff --git a/frontend/components/utilities/secrets/pushKeys.js b/frontend/components/utilities/secrets/pushKeys.ts similarity index 69% rename from frontend/components/utilities/secrets/pushKeys.js rename to frontend/components/utilities/secrets/pushKeys.ts index fde5b45a4..a4954e8c3 100644 --- a/frontend/components/utilities/secrets/pushKeys.js +++ b/frontend/components/utilities/secrets/pushKeys.ts @@ -7,20 +7,30 @@ import { envMapping } from "../../../public/data/frequentConstants"; const crypto = require("crypto"); const { decryptAssymmetric, - decryptSymmetric, encryptSymmetric, encryptAssymmetric, } = require("../cryptography/crypto"); const nacl = require("tweetnacl"); nacl.util = require("tweetnacl-util"); +export interface IK { + publicKey: string; + userId: string; +} -const pushKeys = async (obj, workspaceId, env) => { - let sharedKey = await getLatestFileKey(workspaceId); +/** + * This function pushes the keys to the database after decrypting them end-to-end + * @param {object} obj + * @param {object} obj.obj - object with all the key pairs + * @param {object} obj.workspaceId - the id of a project to which a user is pushing + * @param {object} obj.env - which environment a user is pushing to + */ +const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: string; env: string; }) => { + let sharedKey = await getLatestFileKey({ workspaceId }); const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); - let randomBytes; + let randomBytes: string; if (Object.keys(sharedKey).length > 0) { // case: a (shared) key exists for the workspace randomBytes = decryptAssymmetric({ @@ -51,11 +61,11 @@ const pushKeys = async (obj, workspaceId, env) => { iv: ivValue, tag: tagValue, } = encryptSymmetric({ - plaintext: obj[key][0], + plaintext: obj[key as keyof typeof obj][0], key: randomBytes, }); - const visibility = obj[key][1] != null ? obj[key][1] : "personal"; + const visibility = obj[key as keyof typeof obj][1] != null ? obj[key as keyof typeof obj][1] : "personal"; return { ciphertextKey, @@ -65,7 +75,7 @@ const pushKeys = async (obj, workspaceId, env) => { ciphertextValue, ivValue, tagValue, - hashValue: crypto.createHash("sha256").update(obj[key][0]).digest("hex"), + hashValue: crypto.createHash("sha256").update(obj[key as keyof typeof obj][0]).digest("hex"), type: visibility, }; }); @@ -76,7 +86,7 @@ const pushKeys = async (obj, workspaceId, env) => { }); // assymmetrically encrypt key with each receiver public keys - const keys = publicKeys.map((k) => { + const keys = publicKeys.map((k: IK) => { const { ciphertext, nonce } = encryptAssymmetric({ plaintext: randomBytes, publicKey: k.publicKey, @@ -95,7 +105,7 @@ const pushKeys = async (obj, workspaceId, env) => { workspaceId, secrets, keys, - environment: envMapping[env], + environment: envMapping[env as keyof typeof envMapping], }); }; diff --git a/frontend/pages/api/organization/GetOrgUsers.js b/frontend/pages/api/organization/GetOrgUsers.ts similarity index 85% rename from frontend/pages/api/organization/GetOrgUsers.js rename to frontend/pages/api/organization/GetOrgUsers.ts index 81e9caa4d..53b9518cf 100644 --- a/frontend/pages/api/organization/GetOrgUsers.js +++ b/frontend/pages/api/organization/GetOrgUsers.ts @@ -6,7 +6,7 @@ import SecurityClient from "~/utilities/SecurityClient"; * @param {string} obj.orgId - organization Id * @returns */ -const getOrganizationUsers = ({ orgId }) => { +const getOrganizationUsers = ({ orgId }: { orgId: string; }) => { return SecurityClient.fetchCall( "/api/v1/organization/" + orgId + "/users", { @@ -16,7 +16,7 @@ const getOrganizationUsers = ({ orgId }) => { }, } ).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).users; } else { console.log("Failed to get org users"); diff --git a/frontend/pages/api/workspace/createWorkspace.js b/frontend/pages/api/workspace/createWorkspace.ts similarity index 61% rename from frontend/pages/api/workspace/createWorkspace.js rename to frontend/pages/api/workspace/createWorkspace.ts index d5c44e2a6..0cedb0a57 100644 --- a/frontend/pages/api/workspace/createWorkspace.js +++ b/frontend/pages/api/workspace/createWorkspace.ts @@ -1,11 +1,12 @@ import SecurityClient from "~/utilities/SecurityClient"; /** - * This route creates a new workspace for a user. - * @param {*} workspaceName + * This route creates a new workspace for a user within a certain organization. + * @param {string} workspaceName - project Name + * @param {string} organizationId - org ID * @returns */ -const createWorkspace = (workspaceName, organizationId) => { +const createWorkspace = ( { workspaceName, organizationId }: { workspaceName: string; organizationId: string; }) => { return SecurityClient.fetchCall("/api/v1/workspace", { method: "POST", headers: { @@ -16,7 +17,7 @@ const createWorkspace = (workspaceName, organizationId) => { organizationId: organizationId, }), }).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).workspace; } else { console.log("Failed to create a project"); diff --git a/frontend/pages/api/workspace/getLatestFileKey.js b/frontend/pages/api/workspace/getLatestFileKey.ts similarity index 79% rename from frontend/pages/api/workspace/getLatestFileKey.js rename to frontend/pages/api/workspace/getLatestFileKey.ts index a5b14520a..86ecb7456 100644 --- a/frontend/pages/api/workspace/getLatestFileKey.js +++ b/frontend/pages/api/workspace/getLatestFileKey.ts @@ -2,10 +2,10 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * Get the latest key pairs from a certain workspace - * @param {*} workspaceId + * @param {string} workspaceId * @returns */ -const getLatestFileKey = (workspaceId) => { +const getLatestFileKey = ({ workspaceId } : { workspaceId: string; }) => { return SecurityClient.fetchCall( "/api/v1/key/" + workspaceId + "/latest", { @@ -15,7 +15,7 @@ const getLatestFileKey = (workspaceId) => { }, } ).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return await res.json(); } else { console.log("Failed to get the latest key pairs for a certain project"); diff --git a/frontend/pages/api/workspace/getWorkspaceKeys.js b/frontend/pages/api/workspace/getWorkspaceKeys.ts similarity index 73% rename from frontend/pages/api/workspace/getWorkspaceKeys.js rename to frontend/pages/api/workspace/getWorkspaceKeys.ts index 368d00fa0..09b468662 100644 --- a/frontend/pages/api/workspace/getWorkspaceKeys.js +++ b/frontend/pages/api/workspace/getWorkspaceKeys.ts @@ -2,13 +2,12 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route lets us get the public keys of everyone in your workspace. - * @param {*} req - * @param {*} res + * @param {string} workspaceId * @returns */ -const getWorkspaceKeys = (req, res) => { +const getWorkspaceKeys = ({ workspaceId }: { workspaceId: string; }) => { return SecurityClient.fetchCall( - "/api/v1/workspace/" + req.workspaceId + "/keys", + "/api/v1/workspace/" + workspaceId + "/keys", { method: "GET", headers: { @@ -16,7 +15,7 @@ const getWorkspaceKeys = (req, res) => { }, } ).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).publicKeys; } else { console.log("Failed to get the public keys of everyone in the workspace"); diff --git a/frontend/pages/api/workspace/getWorkspaceUsers.js b/frontend/pages/api/workspace/getWorkspaceUsers.ts similarity index 69% rename from frontend/pages/api/workspace/getWorkspaceUsers.js rename to frontend/pages/api/workspace/getWorkspaceUsers.ts index 4d87836c7..9805c2695 100644 --- a/frontend/pages/api/workspace/getWorkspaceUsers.js +++ b/frontend/pages/api/workspace/getWorkspaceUsers.ts @@ -2,13 +2,12 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route lets us get all the users in the workspace. - * @param {*} req - * @param {*} res + * @param {string} workspaceId - workspace ID * @returns */ -const getWorkspaceUsers = (req, res) => { +const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string; }) => { return SecurityClient.fetchCall( - "/api/v1/workspace/" + req.workspaceId + "/users", + "/api/v1/workspace/" + workspaceId + "/users", { method: "GET", headers: { @@ -16,7 +15,7 @@ const getWorkspaceUsers = (req, res) => { }, } ).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).users; } else { console.log("Failed to get Project Users"); diff --git a/frontend/pages/api/workspace/getWorkspaces.js b/frontend/pages/api/workspace/getWorkspaces.ts similarity index 69% rename from frontend/pages/api/workspace/getWorkspaces.js rename to frontend/pages/api/workspace/getWorkspaces.ts index ccaf49e9b..9427c03d0 100644 --- a/frontend/pages/api/workspace/getWorkspaces.js +++ b/frontend/pages/api/workspace/getWorkspaces.ts @@ -1,19 +1,17 @@ import SecurityClient from "~/utilities/SecurityClient"; /** - * This route lets us get the public keys of everyone in your workspace. - * @param {*} req - * @param {*} res + * This route lets us get the workspaces of a certain user * @returns */ -const getWorkspaces = (req, res) => { +const getWorkspaces = () => { return SecurityClient.fetchCall("/api/v1/workspace", { method: "GET", headers: { "Content-Type": "application/json", }, }).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).workspaces; } else { console.log("Failed to get projects"); diff --git a/frontend/pages/dashboard/[id].js b/frontend/pages/dashboard/[id].js index 42abf24db..b2dfd70f4 100644 --- a/frontend/pages/dashboard/[id].js +++ b/frontend/pages/dashboard/[id].js @@ -378,9 +378,9 @@ export default function Dashboard() { } else if (duplicatesExist) { console.log("Remove the duplicated entries first!"); } else { - // Once "Save changed is clicked", disable that button + // Once "Save changes is clicked", disable that button setButtonReady(false); - pushKeys(obj, router.query.id, env); + pushKeys({obj, workspaceId: router.query.id, env}); /** * Check which integrations are active for this project and environment From 088668e1b05bef12bdbd66f14a94705f842d3d8a Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Sun, 4 Dec 2022 23:18:39 -0500 Subject: [PATCH 2/6] Fix let -> const --- frontend/components/utilities/secrets/pushKeys.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/utilities/secrets/pushKeys.ts b/frontend/components/utilities/secrets/pushKeys.ts index a4954e8c3..0d570f273 100644 --- a/frontend/components/utilities/secrets/pushKeys.ts +++ b/frontend/components/utilities/secrets/pushKeys.ts @@ -26,7 +26,7 @@ export interface IK { * @param {object} obj.env - which environment a user is pushing to */ const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: string; env: string; }) => { - let sharedKey = await getLatestFileKey({ workspaceId }); + const sharedKey = await getLatestFileKey({ workspaceId }); const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); From e00c3ab9e22b1c43fd04a1310f2c0096b0213add Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Mon, 5 Dec 2022 00:07:03 -0500 Subject: [PATCH 3/6] Expanded contributing docs --- docs/contributing/FAQ.mdx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 docs/contributing/FAQ.mdx diff --git a/docs/contributing/FAQ.mdx b/docs/contributing/FAQ.mdx new file mode 100644 index 000000000..be65f5ca7 --- /dev/null +++ b/docs/contributing/FAQ.mdx @@ -0,0 +1,16 @@ +--- +title: "Frequently Asked Questions" +description: "Have any questions? [Join our Slack community](https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g)." +--- + +## Problem with SMTP + +You can normally populate `SMTP_USERNAME` and `SMTP_PASSWORD` with your usual login and password (you could also create a 'burner' email). Sometimes, there still are problems. + +You can go to your Gmail account settings > security and enable “less secure apps”. This would allow Infisical to use your Gmail to send emails. + +If it still doesn't work, [this](https://stackoverflow.com/questions/72547853/unable-to-send-email-in-c-sharp-less-secure-app-access-not-longer-available/72553362#72553362) should help. + +## `MONGO_URL` issues + +Your `MONGO_URL` should be something like `mongodb://root:example@mongo:27017/?authSource=admin`. If you want to change it (not recommended), you should make sure that you keep this URL in line with `MONGO_USERNAME=root` and `MONGO_PASSWORD=example`. \ No newline at end of file From b13b0693baf5740f77938a102509d9dc416a3117 Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Mon, 5 Dec 2022 00:11:47 -0500 Subject: [PATCH 4/6] Updated menu in docs --- docs/mint.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/mint.json b/docs/mint.json index 7d0317f0e..4ff49b5b9 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -162,7 +162,8 @@ "pages": [ "contributing/overview", "contributing/code-of-conduct", - "contributing/developing" + "contributing/developing", + "contributing/FAQ" ] } ], From d82dfa5504026542bb77aaadaa2a4dba4e586f45 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 5 Dec 2022 10:28:49 -0500 Subject: [PATCH 5/6] create helm repo install file --- helm-charts/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 helm-charts/README.md diff --git a/helm-charts/README.md b/helm-charts/README.md new file mode 100644 index 000000000..ffcef1a65 --- /dev/null +++ b/helm-charts/README.md @@ -0,0 +1,22 @@ +## Usage + +[Helm](https://helm.sh) must be installed to use the charts. Please refer to +Helm's [documentation](https://helm.sh/docs) to get started. + +Once Helm has been set up correctly, add the repo as follows: + +``` + helm repo add https://infisical.github.io/helm-charts +``` + +If you had already added this repo earlier, run `helm repo update` to retrieve +the latest versions of the packages. You can then run `helm search repo +` to see the charts. + +To install the chart: + + helm install my- / + +To uninstall the chart: + + helm delete my- From 0dd546813a302c8e462186c70969fe8a3ce4eaf3 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 5 Dec 2022 10:37:33 -0500 Subject: [PATCH 6/6] Create helm-chart-release.yaml --- .github/workflows/helm-chart-release.yaml | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/helm-chart-release.yaml diff --git a/.github/workflows/helm-chart-release.yaml b/.github/workflows/helm-chart-release.yaml new file mode 100644 index 000000000..5371848fb --- /dev/null +++ b/.github/workflows/helm-chart-release.yaml @@ -0,0 +1,36 @@ +name: Release Charts + +on: + push: + branches: + - main + +jobs: + release: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@v3 + with: + version: v3.10.0 + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.4.1 + with: + charts_dir: helm-charts + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"