mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 22:28:15 +00:00
Migrate POST /v1/secret/:workspaceId to /v2/workspace/:workspaceId/secrets and cleared room for /v2 secret routes
This commit is contained in:
+4
-4
@@ -66,7 +66,7 @@ if (NODE_ENV === 'production') {
|
|||||||
app.use(helmet());
|
app.use(helmet());
|
||||||
}
|
}
|
||||||
|
|
||||||
// (EE) routers
|
// (EE) routes
|
||||||
app.use('/api/v1/secret', eeSecretRouter);
|
app.use('/api/v1/secret', eeSecretRouter);
|
||||||
app.use('/api/v1/workspace', eeWorkspaceRouter);
|
app.use('/api/v1/workspace', eeWorkspaceRouter);
|
||||||
|
|
||||||
@@ -89,9 +89,9 @@ app.use('/api/v1/stripe', v1StripeRouter);
|
|||||||
app.use('/api/v1/integration', v1IntegrationRouter);
|
app.use('/api/v1/integration', v1IntegrationRouter);
|
||||||
app.use('/api/v1/integration-auth', v1IntegrationAuthRouter);
|
app.use('/api/v1/integration-auth', v1IntegrationAuthRouter);
|
||||||
|
|
||||||
// v2 routes (new)
|
// v2 routes
|
||||||
app.use('/api/v1/workspace', v2WorkspaceRouter);
|
app.use('/api/v2/workspace', v2WorkspaceRouter);
|
||||||
app.use('/api/v1/secret', v2SecretRouter);
|
app.use('/api/v2/secret', v2SecretRouter);
|
||||||
|
|
||||||
|
|
||||||
//* Handle unrouted requests and respond with proper error message as well as status code
|
//* Handle unrouted requests and respond with proper error message as well as status code
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Request, Response } from 'express';
|
|||||||
import * as Sentry from '@sentry/node';
|
import * as Sentry from '@sentry/node';
|
||||||
import { Key, Secret } from '../../models';
|
import { Key, Secret } from '../../models';
|
||||||
import {
|
import {
|
||||||
pushSecrets as push,
|
v1PushSecrets as push,
|
||||||
pullSecrets as pull,
|
pullSecrets as pull,
|
||||||
reformatPullSecrets
|
reformatPullSecrets
|
||||||
} from '../../helpers/secret';
|
} from '../../helpers/secret';
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
deleteWorkspace as deleteWork
|
deleteWorkspace as deleteWork
|
||||||
} from '../../helpers/workspace';
|
} from '../../helpers/workspace';
|
||||||
import {
|
import {
|
||||||
pushSecrets as push,
|
v2PushSecrets as push,
|
||||||
pullSecrets as pull,
|
pullSecrets as pull,
|
||||||
reformatPullSecrets
|
reformatPullSecrets
|
||||||
} from '../../helpers/secret';
|
} from '../../helpers/secret';
|
||||||
@@ -24,17 +24,20 @@ import { addMemberships } from '../../helpers/membership';
|
|||||||
import { postHogClient, EventService } from '../../services';
|
import { postHogClient, EventService } from '../../services';
|
||||||
import { eventPushSecrets } from '../../events';
|
import { eventPushSecrets } from '../../events';
|
||||||
import { ADMIN, COMPLETED, GRANTED, ENV_SET } from '../../variables';
|
import { ADMIN, COMPLETED, GRANTED, ENV_SET } from '../../variables';
|
||||||
|
interface V2PushSecret {
|
||||||
interface PushSecret {
|
type: string; // personal or shared
|
||||||
ciphertextKey: string;
|
secretKeyCiphertext: string;
|
||||||
ivKey: string;
|
secretKeyIV: string;
|
||||||
tagKey: string;
|
secretKeyTag: string;
|
||||||
hashKey: string;
|
secretKeyHash: string;
|
||||||
ciphertextValue: string;
|
secretValueCiphertext: string;
|
||||||
ivValue: string;
|
secretValueIV: string;
|
||||||
tagValue: string;
|
secretValueTag: string;
|
||||||
hashValue: string;
|
secretValueHash: string;
|
||||||
type: 'shared' | 'personal';
|
secretCommentCiphertext?: string;
|
||||||
|
secretCommentIV?: string;
|
||||||
|
secretCommentTag?: string;
|
||||||
|
secretCommentHash?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -364,11 +367,11 @@ export const getWorkspaceServiceTokens = async (
|
|||||||
* @param res
|
* @param res
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const pushSecrets = async (req: Request, res: Response) => {
|
export const pushWorkspaceSecrets = async (req: Request, res: Response) => {
|
||||||
// upload (encrypted) secrets to workspace with id [workspaceId]
|
// upload (encrypted) secrets to workspace with id [workspaceId]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let { secrets }: { secrets: PushSecret[] } = req.body;
|
let { secrets }: { secrets: V2PushSecret[] } = req.body;
|
||||||
const { keys, environment, channel } = req.body;
|
const { keys, environment, channel } = req.body;
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
@@ -379,7 +382,7 @@ export const pushSecrets = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
// sanitize secrets
|
// sanitize secrets
|
||||||
secrets = secrets.filter(
|
secrets = secrets.filter(
|
||||||
(s: PushSecret) => s.ciphertextKey !== '' && s.ciphertextValue !== ''
|
(s: V2PushSecret) => s.secretKeyCiphertext !== '' && s.secretValueCiphertext !== ''
|
||||||
);
|
);
|
||||||
|
|
||||||
await push({
|
await push({
|
||||||
@@ -437,6 +440,8 @@ export const pushSecrets = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const pullSecrets = async (req: Request, res: Response) => {
|
export const pullSecrets = async (req: Request, res: Response) => {
|
||||||
|
// TODO: only return secrets, do not return workspace key
|
||||||
|
|
||||||
let secrets;
|
let secrets;
|
||||||
let key;
|
let key;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
decryptSymmetric,
|
decryptSymmetric,
|
||||||
decryptAsymmetric
|
decryptAsymmetric
|
||||||
} from '../utils/crypto';
|
} from '../utils/crypto';
|
||||||
import { decryptSecrets } from '../helpers/secret';
|
|
||||||
import { ENCRYPTION_KEY } from '../config';
|
import { ENCRYPTION_KEY } from '../config';
|
||||||
import { SECRET_SHARED } from '../variables';
|
import { SECRET_SHARED } from '../variables';
|
||||||
|
|
||||||
|
|||||||
+266
-72
@@ -14,9 +14,8 @@ import {
|
|||||||
} from '../ee/helpers/secret';
|
} from '../ee/helpers/secret';
|
||||||
import { decryptSymmetric } from '../utils/crypto';
|
import { decryptSymmetric } from '../utils/crypto';
|
||||||
import { SECRET_SHARED, SECRET_PERSONAL } from '../variables';
|
import { SECRET_SHARED, SECRET_PERSONAL } from '../variables';
|
||||||
import { LICENSE_KEY } from '../config';
|
|
||||||
|
|
||||||
interface PushSecret {
|
interface V1PushSecret {
|
||||||
ciphertextKey: string;
|
ciphertextKey: string;
|
||||||
ivKey: string;
|
ivKey: string;
|
||||||
tagKey: string;
|
tagKey: string;
|
||||||
@@ -32,6 +31,22 @@ interface PushSecret {
|
|||||||
type: 'shared' | 'personal';
|
type: 'shared' | 'personal';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface V2PushSecret {
|
||||||
|
type: string; // personal or shared
|
||||||
|
secretKeyCiphertext: string;
|
||||||
|
secretKeyIV: string;
|
||||||
|
secretKeyTag: string;
|
||||||
|
secretKeyHash: string;
|
||||||
|
secretValueCiphertext: string;
|
||||||
|
secretValueIV: string;
|
||||||
|
secretValueTag: string;
|
||||||
|
secretValueHash: string;
|
||||||
|
secretCommentCiphertext?: string;
|
||||||
|
secretCommentIV?: string;
|
||||||
|
secretCommentTag?: string;
|
||||||
|
secretCommentHash?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface Update {
|
interface Update {
|
||||||
[index: string]: any;
|
[index: string]: any;
|
||||||
}
|
}
|
||||||
@@ -49,7 +64,7 @@ type DecryptSecretType = 'text' | 'object' | 'expanded';
|
|||||||
* @param {String} obj.environment - environment for secrets
|
* @param {String} obj.environment - environment for secrets
|
||||||
* @param {Object[]} obj.secrets - secrets to push
|
* @param {Object[]} obj.secrets - secrets to push
|
||||||
*/
|
*/
|
||||||
const pushSecrets = async ({
|
const v1PushSecrets = async ({
|
||||||
userId,
|
userId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
environment,
|
environment,
|
||||||
@@ -58,7 +73,7 @@ const pushSecrets = async ({
|
|||||||
userId: string;
|
userId: string;
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
secrets: PushSecret[];
|
secrets: V1PushSecret[];
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
// TODO: clean up function and fix up types
|
// TODO: clean up function and fix up types
|
||||||
try {
|
try {
|
||||||
@@ -99,7 +114,7 @@ const pushSecrets = async ({
|
|||||||
if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) {
|
if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) {
|
||||||
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue
|
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue
|
||||||
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment) {
|
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment) {
|
||||||
// case: filter secrets where value changed
|
// case: filter secrets where value or comment changed
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +274,249 @@ const pushSecrets = async ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push secrets for user with id [userId] to workspace
|
||||||
|
* with id [workspaceId] with environment [environment]. Follow steps:
|
||||||
|
* 1. Handle shared secrets (insert, delete)
|
||||||
|
* 2. handle personal secrets (insert, delete)
|
||||||
|
* @param {Object} obj
|
||||||
|
* @param {String} obj.userId - id of user to push secrets for
|
||||||
|
* @param {String} obj.workspaceId - id of workspace to push to
|
||||||
|
* @param {String} obj.environment - environment for secrets
|
||||||
|
* @param {Object[]} obj.secrets - secrets to push
|
||||||
|
*/
|
||||||
|
const v2PushSecrets = async ({
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
secrets
|
||||||
|
}: {
|
||||||
|
userId: string;
|
||||||
|
workspaceId: string;
|
||||||
|
environment: string;
|
||||||
|
secrets: V2PushSecret[];
|
||||||
|
}): Promise<void> => {
|
||||||
|
// TODO: clean up function and fix up types
|
||||||
|
try {
|
||||||
|
// construct useful data structures
|
||||||
|
const oldSecrets = await pullSecrets({
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
environment
|
||||||
|
});
|
||||||
|
|
||||||
|
const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) =>
|
||||||
|
({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s })
|
||||||
|
, {});
|
||||||
|
const newSecretsObj: any = secrets.reduce((accumulator, s) =>
|
||||||
|
({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s })
|
||||||
|
, {});
|
||||||
|
|
||||||
|
// handle deleting secrets
|
||||||
|
const toDelete = oldSecrets
|
||||||
|
.filter(
|
||||||
|
(s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj)
|
||||||
|
)
|
||||||
|
.map((s) => s._id);
|
||||||
|
if (toDelete.length > 0) {
|
||||||
|
await Secret.deleteMany({
|
||||||
|
_id: { $in: toDelete }
|
||||||
|
});
|
||||||
|
|
||||||
|
await SecretVersion.updateMany({
|
||||||
|
secret: { $in: toDelete }
|
||||||
|
}, {
|
||||||
|
isDeleted: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const toUpdate = oldSecrets
|
||||||
|
.filter((s) => {
|
||||||
|
if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) {
|
||||||
|
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretValueHash
|
||||||
|
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretCommentHash) {
|
||||||
|
// case: filter secrets where value or comment changed
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s.version) {
|
||||||
|
// case: filter (legacy) secrets that were not versioned
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const operations = toUpdate
|
||||||
|
.map((s) => {
|
||||||
|
const {
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash,
|
||||||
|
secretCommentCiphertext,
|
||||||
|
secretCommentIV,
|
||||||
|
secretCommentTag,
|
||||||
|
secretCommentHash,
|
||||||
|
} = newSecretsObj[`${s.type}-${s.secretKeyHash}`];
|
||||||
|
|
||||||
|
const update: Update = {
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash,
|
||||||
|
secretCommentCiphertext,
|
||||||
|
secretCommentIV,
|
||||||
|
secretCommentTag,
|
||||||
|
secretCommentHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s.version) {
|
||||||
|
// case: (legacy) secret was not versioned
|
||||||
|
update.version = 1;
|
||||||
|
} else {
|
||||||
|
update['$inc'] = {
|
||||||
|
version: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.type === SECRET_PERSONAL) {
|
||||||
|
// attach user associated with the personal secret
|
||||||
|
update['user'] = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
updateOne: {
|
||||||
|
filter: {
|
||||||
|
_id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id
|
||||||
|
},
|
||||||
|
update
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
await Secret.bulkWrite(operations as any);
|
||||||
|
|
||||||
|
// (EE) add secret versions for updated secrets
|
||||||
|
await EESecretService.addSecretVersions({
|
||||||
|
secretVersions: toUpdate.map((s) => {
|
||||||
|
const {
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretKeyHash,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash,
|
||||||
|
secretCommentCiphertext,
|
||||||
|
secretCommentIV,
|
||||||
|
secretCommentTag,
|
||||||
|
secretCommentHash,
|
||||||
|
} = newSecretsObj[`${s.type}-${s.secretKeyHash}`];
|
||||||
|
|
||||||
|
return ({
|
||||||
|
secret: s._id,
|
||||||
|
version: s.version ? s.version + 1 : 1,
|
||||||
|
isDeleted: false,
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretKeyHash,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// handle adding new secrets
|
||||||
|
const toAdd = secrets.filter((s) => !(`${s.type}-${s.secretKeyHash}` in oldSecretsObj));
|
||||||
|
|
||||||
|
if (toAdd.length > 0) {
|
||||||
|
// add secrets
|
||||||
|
const newSecrets = await Secret.insertMany(
|
||||||
|
toAdd.map(({
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretKeyHash,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash,
|
||||||
|
secretCommentCiphertext,
|
||||||
|
secretCommentIV,
|
||||||
|
secretCommentTag,
|
||||||
|
secretCommentHash,
|
||||||
|
}, idx) => {
|
||||||
|
const obj: any = {
|
||||||
|
version: 1,
|
||||||
|
workspace: workspaceId,
|
||||||
|
type: toAdd[idx].type,
|
||||||
|
environment,
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretKeyHash,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash,
|
||||||
|
secretCommentCiphertext,
|
||||||
|
secretCommentIV,
|
||||||
|
secretCommentTag,
|
||||||
|
secretCommentHash
|
||||||
|
};
|
||||||
|
|
||||||
|
if (toAdd[idx].type === 'personal') {
|
||||||
|
obj['user' as keyof typeof obj] = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// (EE) add secret versions for new secrets
|
||||||
|
EESecretService.addSecretVersions({
|
||||||
|
secretVersions: newSecrets.map(({
|
||||||
|
_id,
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretKeyHash,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash
|
||||||
|
}) => ({
|
||||||
|
secret: _id,
|
||||||
|
version: 1,
|
||||||
|
isDeleted: false,
|
||||||
|
secretKeyCiphertext,
|
||||||
|
secretKeyIV,
|
||||||
|
secretKeyTag,
|
||||||
|
secretKeyHash,
|
||||||
|
secretValueCiphertext,
|
||||||
|
secretValueIV,
|
||||||
|
secretValueTag,
|
||||||
|
secretValueHash
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// (EE) take a secret snapshot
|
||||||
|
await EESecretService.takeSecretSnapshot({
|
||||||
|
workspaceId
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
Sentry.setUser(null);
|
||||||
|
Sentry.captureException(err);
|
||||||
|
throw new Error('Failed to push shared and personal secrets');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pull secrets for user with id [userId] for workspace
|
* Pull secrets for user with id [userId] for workspace
|
||||||
* with id [workspaceId] with environment [environment]
|
* with id [workspaceId] with environment [environment]
|
||||||
@@ -350,73 +608,9 @@ const reformatPullSecrets = ({ secrets }: { secrets: ISecret[] }) => {
|
|||||||
return reformatedSecrets;
|
return reformatedSecrets;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Return decrypted secrets in format [format]
|
|
||||||
* @param {Object} obj
|
|
||||||
* @param {Object[]} obj.secrets - array of (encrypted) secret key-value pair objects
|
|
||||||
* @param {String} obj.key - symmetric key to decrypt secret key-value pairs
|
|
||||||
* @param {String} obj.format - desired return format that is either "text," "object," or "expanded"
|
|
||||||
* @return {String|Object} (decrypted) secrets also called the content
|
|
||||||
*/
|
|
||||||
const decryptSecrets = ({
|
|
||||||
secrets,
|
|
||||||
key,
|
|
||||||
format
|
|
||||||
}: {
|
|
||||||
secrets: PushSecret[];
|
|
||||||
key: string;
|
|
||||||
format: DecryptSecretType;
|
|
||||||
}) => {
|
|
||||||
// init content
|
|
||||||
let content: any = format === 'text' ? '' : {};
|
|
||||||
|
|
||||||
// decrypt secrets
|
|
||||||
secrets.forEach((s, idx) => {
|
|
||||||
const secretKey = decryptSymmetric({
|
|
||||||
ciphertext: s.ciphertextKey,
|
|
||||||
iv: s.ivKey,
|
|
||||||
tag: s.tagKey,
|
|
||||||
key
|
|
||||||
});
|
|
||||||
|
|
||||||
const secretValue = decryptSymmetric({
|
|
||||||
ciphertext: s.ciphertextValue,
|
|
||||||
iv: s.ivValue,
|
|
||||||
tag: s.tagValue,
|
|
||||||
key
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (format) {
|
|
||||||
case 'text':
|
|
||||||
content += secretKey;
|
|
||||||
content += '=';
|
|
||||||
content += secretValue;
|
|
||||||
|
|
||||||
if (idx < secrets.length) {
|
|
||||||
content += '\n';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'object':
|
|
||||||
content[secretKey] = secretValue;
|
|
||||||
break;
|
|
||||||
case 'expanded':
|
|
||||||
content[secretKey] = {
|
|
||||||
...s,
|
|
||||||
plaintextKey: secretKey,
|
|
||||||
plaintextValue: secretValue
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return content;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
pushSecrets,
|
v1PushSecrets,
|
||||||
|
v2PushSecrets,
|
||||||
pullSecrets,
|
pullSecrets,
|
||||||
reformatPullSecrets,
|
reformatPullSecrets
|
||||||
decryptSecrets
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ router.get(
|
|||||||
workspaceController.getWorkspaceIntegrationAuthorizations
|
workspaceController.getWorkspaceIntegrationAuthorizations
|
||||||
);
|
);
|
||||||
|
|
||||||
router.get(
|
router.get( // TODO: modify
|
||||||
'/:workspaceId/service-tokens',
|
'/:workspaceId/service-tokens',
|
||||||
requireAuth,
|
requireAuth,
|
||||||
requireWorkspaceAuth({
|
requireWorkspaceAuth({
|
||||||
@@ -145,7 +145,7 @@ router.post(
|
|||||||
body('channel'),
|
body('channel'),
|
||||||
param('workspaceId').exists().trim(),
|
param('workspaceId').exists().trim(),
|
||||||
validateRequest,
|
validateRequest,
|
||||||
workspaceController.pushSecrets
|
workspaceController.pushWorkspaceSecrets
|
||||||
);
|
);
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: st
|
|||||||
const secrets = Object.keys(obj).map((key) => {
|
const secrets = Object.keys(obj).map((key) => {
|
||||||
// encrypt key
|
// encrypt key
|
||||||
const {
|
const {
|
||||||
ciphertext: ciphertextKey,
|
ciphertext: secretKeyCiphertext,
|
||||||
iv: ivKey,
|
iv: secretKeyIV,
|
||||||
tag: tagKey,
|
tag: secretKeyTag,
|
||||||
} = encryptSymmetric({
|
} = encryptSymmetric({
|
||||||
plaintext: key.slice(1),
|
plaintext: key.slice(1),
|
||||||
key: randomBytes,
|
key: randomBytes,
|
||||||
@@ -57,9 +57,9 @@ const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: st
|
|||||||
|
|
||||||
// encrypt value
|
// encrypt value
|
||||||
const {
|
const {
|
||||||
ciphertext: ciphertextValue,
|
ciphertext: secretValueCiphertext,
|
||||||
iv: ivValue,
|
iv: secretValueIV,
|
||||||
tag: tagValue,
|
tag: secretValueTag,
|
||||||
} = encryptSymmetric({
|
} = encryptSymmetric({
|
||||||
plaintext: obj[key as keyof typeof obj][0],
|
plaintext: obj[key as keyof typeof obj][0],
|
||||||
key: randomBytes,
|
key: randomBytes,
|
||||||
@@ -67,9 +67,9 @@ const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: st
|
|||||||
|
|
||||||
// encrypt comment
|
// encrypt comment
|
||||||
const {
|
const {
|
||||||
ciphertext: ciphertextComment,
|
ciphertext: secretCommentCiphertext,
|
||||||
iv: ivComment,
|
iv: secretCommentIV,
|
||||||
tag: tagComment,
|
tag: secretCommentTag,
|
||||||
} = encryptSymmetric({
|
} = encryptSymmetric({
|
||||||
plaintext: obj[key as keyof typeof obj][1],
|
plaintext: obj[key as keyof typeof obj][1],
|
||||||
key: randomBytes,
|
key: randomBytes,
|
||||||
@@ -78,18 +78,18 @@ const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: st
|
|||||||
const visibility = key.charAt(0) == "p" ? "personal" : "shared";
|
const visibility = key.charAt(0) == "p" ? "personal" : "shared";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ciphertextKey,
|
secretKeyCiphertext,
|
||||||
ivKey,
|
secretKeyIV,
|
||||||
tagKey,
|
secretKeyTag,
|
||||||
hashKey: crypto.createHash("sha256").update(key.slice(1)).digest("hex"),
|
secretKeyHash: crypto.createHash("sha256").update(key.slice(1)).digest("hex"),
|
||||||
ciphertextValue,
|
secretValueCiphertext,
|
||||||
ivValue,
|
secretValueIV,
|
||||||
tagValue,
|
secretValueTag,
|
||||||
hashValue: crypto.createHash("sha256").update(obj[key as keyof typeof obj][0]).digest("hex"),
|
secretValueHash: crypto.createHash("sha256").update(obj[key as keyof typeof obj][0]).digest("hex"),
|
||||||
ciphertextComment,
|
secretCommentCiphertext,
|
||||||
ivComment,
|
secretCommentIV,
|
||||||
tagComment,
|
secretCommentTag,
|
||||||
hashComment: crypto.createHash("sha256").update(obj[key as keyof typeof obj][1]).digest("hex"),
|
secretCommentHash: crypto.createHash("sha256").update(obj[key as keyof typeof obj][1]).digest("hex"),
|
||||||
type: visibility,
|
type: visibility,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const uploadSecrets = async ({
|
|||||||
keys,
|
keys,
|
||||||
environment
|
environment
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
return SecurityClient.fetchCall('/api/v1/secret/' + workspaceId, {
|
return SecurityClient.fetchCall('/api/v2/workspace/' + workspaceId + '/secrets', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
|
|||||||
Reference in New Issue
Block a user