mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 13:27:46 +00:00
Remove frontend/backend sync operation for envars to integrations in favor of bot
This commit is contained in:
@@ -49,57 +49,6 @@ export const getIntegrations = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Sync secrets [secrets] to integration with id [integrationId]
|
|
||||||
* @param req
|
|
||||||
* @param res
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const syncIntegration = async (req: Request, res: Response) => {
|
|
||||||
// NOTE TO ALL DEVS: THIS FUNCTION IS BEING DEPRECATED. IGNORE IT BUT KEEP IT FOR NOW.
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { key, secrets }: { key: Key; secrets: PushSecret[] } = req.body;
|
|
||||||
const symmetricKey = decryptAsymmetric({
|
|
||||||
ciphertext: key.encryptedKey,
|
|
||||||
nonce: key.nonce,
|
|
||||||
publicKey: req.user.publicKey,
|
|
||||||
privateKey: PRIVATE_KEY
|
|
||||||
});
|
|
||||||
|
|
||||||
// decrypt secrets with symmetric key
|
|
||||||
const content = decryptSecrets({
|
|
||||||
secrets,
|
|
||||||
key: symmetricKey,
|
|
||||||
format: 'object'
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: make integration work for other integrations as well
|
|
||||||
const res = await axios.patch(
|
|
||||||
`https://api.heroku.com/apps/${req.integration.app}/config-vars`,
|
|
||||||
content,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/vnd.heroku+json; version=3',
|
|
||||||
Authorization: 'Bearer ' + req.accessToken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to sync secrets with integration'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
message: 'Successfully synced secrets with integration'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change environment or name of integration with id [integrationId]
|
* Change environment or name of integration with id [integrationId]
|
||||||
* @param req
|
* @param req
|
||||||
|
|||||||
@@ -11,20 +11,6 @@ import { integrationController } from '../controllers';
|
|||||||
|
|
||||||
router.get('/integrations', requireAuth, integrationController.getIntegrations);
|
router.get('/integrations', requireAuth, integrationController.getIntegrations);
|
||||||
|
|
||||||
router.post( // TODO: deprecate
|
|
||||||
'/:integrationId/sync',
|
|
||||||
requireAuth,
|
|
||||||
requireIntegrationAuth({
|
|
||||||
acceptedRoles: [ADMIN, MEMBER],
|
|
||||||
acceptedStatuses: [GRANTED]
|
|
||||||
}),
|
|
||||||
param('integrationId').exists().trim(),
|
|
||||||
body('key').exists(),
|
|
||||||
body('secrets').exists(),
|
|
||||||
validateRequest,
|
|
||||||
integrationController.syncIntegration
|
|
||||||
);
|
|
||||||
|
|
||||||
router.patch(
|
router.patch(
|
||||||
'/:integrationId',
|
'/:integrationId',
|
||||||
requireAuth,
|
requireAuth,
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
import publicKeyInfical from "~/pages/api/auth/publicKeyInfisical";
|
|
||||||
import changeHerokuConfigVars from "~/pages/api/integrations/ChangeHerokuConfigVars";
|
|
||||||
|
|
||||||
const crypto = require("crypto");
|
|
||||||
const {
|
|
||||||
encryptSymmetric,
|
|
||||||
encryptAssymmetric,
|
|
||||||
} = require("../cryptography/crypto");
|
|
||||||
const nacl = require("tweetnacl");
|
|
||||||
nacl.util = require("tweetnacl-util");
|
|
||||||
|
|
||||||
const pushKeysIntegration = async ({ obj, integrationId }) => {
|
|
||||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
|
|
||||||
|
|
||||||
let randomBytes = crypto.randomBytes(16).toString("hex");
|
|
||||||
|
|
||||||
const secrets = Object.keys(obj).map((key) => {
|
|
||||||
// encrypt key
|
|
||||||
const {
|
|
||||||
ciphertext: ciphertextKey,
|
|
||||||
iv: ivKey,
|
|
||||||
tag: tagKey,
|
|
||||||
} = encryptSymmetric({
|
|
||||||
plaintext: key,
|
|
||||||
key: randomBytes,
|
|
||||||
});
|
|
||||||
|
|
||||||
// encrypt value
|
|
||||||
const {
|
|
||||||
ciphertext: ciphertextValue,
|
|
||||||
iv: ivValue,
|
|
||||||
tag: tagValue,
|
|
||||||
} = encryptSymmetric({
|
|
||||||
plaintext: obj[key],
|
|
||||||
key: randomBytes,
|
|
||||||
});
|
|
||||||
|
|
||||||
const visibility = "shared";
|
|
||||||
|
|
||||||
return {
|
|
||||||
ciphertextKey,
|
|
||||||
ivKey,
|
|
||||||
tagKey,
|
|
||||||
hashKey: crypto.createHash("sha256").update(key).digest("hex"),
|
|
||||||
ciphertextValue,
|
|
||||||
ivValue,
|
|
||||||
tagValue,
|
|
||||||
hashValue: crypto.createHash("sha256").update(obj[key]).digest("hex"),
|
|
||||||
type: visibility,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// obtain public keys of all receivers (i.e. members in workspace)
|
|
||||||
let publicKeyInfisical = await publicKeyInfical();
|
|
||||||
|
|
||||||
publicKeyInfisical = (await publicKeyInfisical.json()).publicKey;
|
|
||||||
|
|
||||||
// assymmetrically encrypt key with each receiver public keys
|
|
||||||
|
|
||||||
const { ciphertext, nonce } = encryptAssymmetric({
|
|
||||||
plaintext: randomBytes,
|
|
||||||
publicKey: publicKeyInfisical,
|
|
||||||
privateKey: PRIVATE_KEY,
|
|
||||||
});
|
|
||||||
|
|
||||||
const key = {
|
|
||||||
encryptedKey: ciphertext,
|
|
||||||
nonce,
|
|
||||||
};
|
|
||||||
|
|
||||||
changeHerokuConfigVars({ integrationId, key, secrets });
|
|
||||||
};
|
|
||||||
|
|
||||||
export default pushKeysIntegration;
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import SecurityClient from "~/utilities/SecurityClient";
|
|
||||||
|
|
||||||
const changeHerokuConfigVars = ({ integrationId, key, secrets }) => {
|
|
||||||
return SecurityClient.fetchCall(
|
|
||||||
"/api/v1/integration/" + integrationId + "/sync",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
key,
|
|
||||||
secrets,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
).then(async (res) => {
|
|
||||||
if (res.status == 200) {
|
|
||||||
return res;
|
|
||||||
} else {
|
|
||||||
console.log("Failed to sync secrets to Heroku");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default changeHerokuConfigVars;
|
|
||||||
@@ -32,7 +32,6 @@ import DropZone from "~/components/dashboard/DropZone";
|
|||||||
import NavHeader from "~/components/navigation/NavHeader";
|
import NavHeader from "~/components/navigation/NavHeader";
|
||||||
import getSecretsForProject from "~/components/utilities/secrets/getSecretsForProject";
|
import getSecretsForProject from "~/components/utilities/secrets/getSecretsForProject";
|
||||||
import pushKeys from "~/components/utilities/secrets/pushKeys";
|
import pushKeys from "~/components/utilities/secrets/pushKeys";
|
||||||
import pushKeysIntegration from "~/components/utilities/secrets/pushKeysIntegration";
|
|
||||||
import guidGenerator from "~/utilities/randomId";
|
import guidGenerator from "~/utilities/randomId";
|
||||||
|
|
||||||
import { envMapping } from "../../public/data/frequentConstants";
|
import { envMapping } from "../../public/data/frequentConstants";
|
||||||
@@ -401,29 +400,6 @@ export default function Dashboard() {
|
|||||||
setButtonReady(false);
|
setButtonReady(false);
|
||||||
pushKeys({ obj, workspaceId: router.query.id, env });
|
pushKeys({ obj, workspaceId: router.query.id, env });
|
||||||
|
|
||||||
/**
|
|
||||||
* Check which integrations are active for this project and environment
|
|
||||||
* If there are any, update environment variables for those integrations
|
|
||||||
*/
|
|
||||||
let integrations = await getWorkspaceIntegrations({
|
|
||||||
workspaceId: router.query.id,
|
|
||||||
});
|
|
||||||
integrations.map(async (integration) => {
|
|
||||||
if (
|
|
||||||
envMapping[env] == integration.environment &&
|
|
||||||
integration.isActive == true
|
|
||||||
) {
|
|
||||||
let objIntegration = Object.assign(
|
|
||||||
{},
|
|
||||||
...data.map((row) => ({ [row[2]]: row[3] }))
|
|
||||||
);
|
|
||||||
await pushKeysIntegration({
|
|
||||||
obj: objIntegration,
|
|
||||||
integrationId: integration._id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// If this user has never saved environment variables before, show them a prompt to read docs
|
// If this user has never saved environment variables before, show them a prompt to read docs
|
||||||
if (!hasUserEverPushed) {
|
if (!hasUserEverPushed) {
|
||||||
setCheckDocsPopUpVisible(true);
|
setCheckDocsPopUpVisible(true);
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import Button from "~/components/basic/buttons/Button";
|
|||||||
import ListBox from "~/components/basic/Listbox";
|
import ListBox from "~/components/basic/Listbox";
|
||||||
import NavHeader from "~/components/navigation/NavHeader";
|
import NavHeader from "~/components/navigation/NavHeader";
|
||||||
import getSecretsForProject from "~/components/utilities/secrets/getSecretsForProject";
|
import getSecretsForProject from "~/components/utilities/secrets/getSecretsForProject";
|
||||||
import pushKeysIntegration from "~/components/utilities/secrets/pushKeysIntegration";
|
|
||||||
import guidGenerator from "~/utilities/randomId";
|
import guidGenerator from "~/utilities/randomId";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -126,27 +125,7 @@ const Integration = ({ projectIntegration }) => {
|
|||||||
environment: envMapping[integrationEnvironment],
|
environment: envMapping[integrationEnvironment],
|
||||||
appName: integrationApp,
|
appName: integrationApp,
|
||||||
});
|
});
|
||||||
if (result?.status == 200) {
|
router.reload();
|
||||||
let currentSecrets = await getSecretsForProject({
|
|
||||||
env: integrationEnvironment,
|
|
||||||
setFileState,
|
|
||||||
setIsKeyAvailable,
|
|
||||||
setData,
|
|
||||||
workspaceId: router.query.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
let obj = Object.assign(
|
|
||||||
{},
|
|
||||||
...currentSecrets.map((row) => ({
|
|
||||||
[row[2]]: row[3],
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
await pushKeysIntegration({
|
|
||||||
obj,
|
|
||||||
integrationId: projectIntegration._id,
|
|
||||||
});
|
|
||||||
router.reload();
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
color="mineshaft"
|
color="mineshaft"
|
||||||
size="md"
|
size="md"
|
||||||
@@ -331,7 +310,7 @@ export default function Integrations() {
|
|||||||
<a
|
<a
|
||||||
href={`${
|
href={`${
|
||||||
["Heroku"].includes(integrations[integration].name)
|
["Heroku"].includes(integrations[integration].name)
|
||||||
? `https://id.heroku.com/oauth/authorize?client_id=bc132901-935a-4590-b010-f1857efc380d&response_type=code&scope=write-protected&state=${csrfToken}`
|
? `https://id.heroku.com/oauth/authorize?client_id=7b1311a1-1cb2-4938-8adf-f37a399ec41b&response_type=code&scope=write-protected&state=${csrfToken}`
|
||||||
: "#"
|
: "#"
|
||||||
}`}
|
}`}
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
|
|||||||
Reference in New Issue
Block a user