feat: add sync

This commit is contained in:
nafees nazik
2023-10-20 13:20:00 +05:30
parent 0fb0744f09
commit 40e5ecfd7d
2 changed files with 132 additions and 29 deletions
+122 -29
View File
@@ -32,6 +32,8 @@ import {
INTEGRATION_GITLAB, INTEGRATION_GITLAB,
INTEGRATION_GITLAB_API_URL, INTEGRATION_GITLAB_API_URL,
INTEGRATION_HASHICORP_VAULT, INTEGRATION_HASHICORP_VAULT,
INTEGRATION_HASURA_CLOUD,
INTEGRATION_HASURA_CLOUD_API_URL,
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_LARAVELFORGE, INTEGRATION_LARAVELFORGE,
@@ -63,6 +65,7 @@ import { Octokit } from "@octokit/rest";
import _ from "lodash"; import _ from "lodash";
import sodium from "libsodium-wrappers"; import sodium from "libsodium-wrappers";
import { standardRequest } from "../config/request"; import { standardRequest } from "../config/request";
import { ZGetTenantEnv } from "../validation/hasuraCloudIntegration";
const getSecretKeyValuePair = ( const getSecretKeyValuePair = (
secrets: Record<string, { value: string | null; comment?: string } | null> secrets: Record<string, { value: string | null; comment?: string } | null>
@@ -95,7 +98,7 @@ const syncSecrets = async ({
secrets: Record<string, { value: string; comment?: string }>; secrets: Record<string, { value: string; comment?: string }>;
accessId: string | null; accessId: string | null;
accessToken: string; accessToken: string;
appendices?: { prefix: string, suffix: string }; appendices?: { prefix: string; suffix: string };
}) => { }) => {
switch (integration.integration) { switch (integration.integration) {
case INTEGRATION_GCP_SECRET_MANAGER: case INTEGRATION_GCP_SECRET_MANAGER:
@@ -306,6 +309,14 @@ const syncSecrets = async ({
accessToken accessToken
}); });
break; break;
case INTEGRATION_HASURA_CLOUD:
await syncSecretsHasuraCloud({
integration,
secrets,
accessToken
});
break;
} }
}; };
@@ -963,8 +974,9 @@ const syncSecretsVercel = async ({
: {}), : {}),
...(integration?.path ...(integration?.path
? { ? {
gitBranch: integration?.path gitBranch: integration?.path
} : {}) }
: {})
}; };
const vercelSecrets: VercelSecret[] = ( const vercelSecrets: VercelSecret[] = (
@@ -992,7 +1004,7 @@ const syncSecretsVercel = async ({
return true; return true;
}); });
const res: { [key: string]: VercelSecret } = {}; const res: { [key: string]: VercelSecret } = {};
for await (const vercelSecret of vercelSecrets) { for await (const vercelSecret of vercelSecrets) {
@@ -1352,7 +1364,7 @@ const syncSecretsGitHub = async ({
integration: IIntegration; integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>; secrets: Record<string, { value: string; comment?: string }>;
accessToken: string; accessToken: string;
appendices?: { prefix: string, suffix: string }; appendices?: { prefix: string; suffix: string };
}) => { }) => {
interface GitHubRepoKey { interface GitHubRepoKey {
key_id: string; key_id: string;
@@ -1395,14 +1407,23 @@ const syncSecretsGitHub = async ({
{} {}
); );
encryptedSecrets = Object.keys(encryptedSecrets).reduce((result: { encryptedSecrets = Object.keys(encryptedSecrets).reduce(
[key: string]: GitHubSecret; (
}, key) => { result: {
if ((appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)) { [key: string]: GitHubSecret;
result[key] = encryptedSecrets[key]; },
} key
return result; ) => {
}, {}); if (
(appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) &&
(appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)
) {
result[key] = encryptedSecrets[key];
}
return result;
},
{}
);
Object.keys(encryptedSecrets).map(async (key) => { Object.keys(encryptedSecrets).map(async (key) => {
if (!(key in secrets)) { if (!(key in secrets)) {
@@ -2095,7 +2116,7 @@ const syncSecretsCheckly = async ({
integration: IIntegration; integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>; secrets: Record<string, { value: string; comment?: string }>;
accessToken: string; accessToken: string;
appendices?: { prefix: string, suffix: string }; appendices?: { prefix: string; suffix: string };
}) => { }) => {
let getSecretsRes = ( let getSecretsRes = (
await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/variables`, { await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/variables`, {
@@ -2113,14 +2134,23 @@ const syncSecretsCheckly = async ({
{} {}
); );
getSecretsRes = Object.keys(getSecretsRes).reduce((result: { getSecretsRes = Object.keys(getSecretsRes).reduce(
[key: string]: string; (
}, key) => { result: {
if ((appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)) { [key: string]: string;
result[key] = getSecretsRes[key]; },
} key
return result; ) => {
}, {}); if (
(appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) &&
(appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)
) {
result[key] = getSecretsRes[key];
}
return result;
},
{}
);
// add secrets // add secrets
for await (const key of Object.keys(secrets)) { for await (const key of Object.keys(secrets)) {
@@ -2195,18 +2225,20 @@ const syncSecretsQovery = async ({
secrets: Record<string, { value: string; comment?: string }>; secrets: Record<string, { value: string; comment?: string }>;
accessToken: string; accessToken: string;
}) => { }) => {
const getSecretsRes = ( const getSecretsRes = (
await standardRequest.get(`${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable`, { await standardRequest.get(
headers: { `${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable`,
Authorization: `Token ${accessToken}`, {
"Accept-Encoding": "application/json" headers: {
Authorization: `Token ${accessToken}`,
"Accept-Encoding": "application/json"
}
} }
}) )
).data.results.reduce( ).data.results.reduce(
(obj: any, secret: any) => ({ (obj: any, secret: any) => ({
...obj, ...obj,
[secret.key]: {"id": secret.id, "value": secret.value} [secret.key]: { id: secret.id, value: secret.value }
}), }),
{} {}
); );
@@ -3076,4 +3108,65 @@ const syncSecretsNorthflank = async ({
); );
}; };
const syncSecretsHasuraCloud = async ({
integration,
secrets,
accessToken
}: {
integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>;
accessToken: string;
}) => {
const res = await standardRequest.post(
INTEGRATION_HASURA_CLOUD_API_URL,
{
query:
"query MyQuery($tenantId: uuid!) { getTenantEnv(tenantId: $tenantId) { hash envVars } }",
variables: {
tenantId: integration.appId
}
},
{
headers: {
Authorization: `pat ${accessToken}`,
"Content-Type": "application/json"
}
}
);
const {
data: {
getTenantEnv: { hash: currentHash }
}
} = ZGetTenantEnv.parse(res.data);
const envs = Object.keys(secrets).reduce<{ key: string; value: any }[]>((prev, key) => {
if (secrets?.[key]?.value) {
prev.push({ key, value: secrets[key].value });
}
return prev;
}, []);
const variables = {
currentHash,
envs,
tenantId: integration.appId
};
await standardRequest.post(
INTEGRATION_HASURA_CLOUD_API_URL,
{
query:
"mutation MyQuery($currentHash: String!, $envs: [UpdateEnvObject!]!, $tenantId: uuid!) { updateTenantEnv(currentHash: $currentHash, envs: $envs, tenantId: $tenantId) { hash envVars} }",
variables
},
{
headers: {
Authorization: `pat ${accessToken}`,
"Content-Type": "application/json"
}
}
);
};
export { syncSecrets }; export { syncSecrets };
@@ -0,0 +1,10 @@
import * as z from "zod";
export const ZGetTenantEnv = z.object({
data: z.object({
getTenantEnv: z.object({
hash: z.string(),
envVars: z.record(z.any())
})
})
});