Merge branch 'main' of github.com:reginaldbondoc/infisical
@ -9,13 +9,13 @@ ENCRYPTION_KEY=replace_with_lengthy_secure_hex
|
||||
JWT_SIGNUP_SECRET=replace_with_lengthy_secure_hex
|
||||
JWT_REFRESH_SECRET=replace_with_lengthy_secure_hex
|
||||
JWT_AUTH_SECRET=replace_with_lengthy_secure_hex
|
||||
JWT_SERVICE_SECRET=replace_with_lengthy_secure_hex
|
||||
|
||||
# JWT lifetime
|
||||
# Optional lifetimes for JWT tokens expressed in seconds or a string
|
||||
# describing a time span (e.g. 60, "2 days", "10h", "7d")
|
||||
JWT_AUTH_LIFETIME=
|
||||
JWT_REFRESH_LIFETIME=
|
||||
JWT_SERVICE_SECRET=
|
||||
JWT_SIGNUP_LIFETIME=
|
||||
|
||||
# Optional lifetimes for OTP expressed in seconds
|
||||
|
@ -81,6 +81,7 @@ nfpms:
|
||||
- rpm
|
||||
- deb
|
||||
- apk
|
||||
- archlinux
|
||||
bindir: /usr/bin
|
||||
scoop:
|
||||
bucket:
|
||||
|
@ -157,10 +157,10 @@ We're currently setting the foundation and building [integrations](https://infis
|
||||
🔜 GCP
|
||||
</td>
|
||||
<td align="left" valign="middle">
|
||||
🔜 GitLab CI/CD
|
||||
🔜 GitLab CI/CD (https://github.com/Infisical/infisical/issues/134)
|
||||
</td>
|
||||
<td align="left" valign="middle">
|
||||
🔜 CircleCI
|
||||
🔜 CircleCI (https://github.com/Infisical/infisical/issues/91)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -193,7 +193,7 @@ We're currently setting the foundation and building [integrations](https://infis
|
||||
🔜 Supabase
|
||||
</td>
|
||||
<td align="left" valign="middle">
|
||||
🔜 Serverless
|
||||
🔜 Render (https://github.com/Infisical/infisical/issues/132)
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -317,4 +317,4 @@ Infisical officially launched as v.1.0 on November 21st, 2022. However, a lot of
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/asharonbaltazar"><img src="https://avatars.githubusercontent.com/u/58940073?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/edgarrmondragon"><img src="https://avatars.githubusercontent.com/u/16805946?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arjunyel"><img src="https://avatars.githubusercontent.com/u/11153289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/LemmyMwaura"><img src="https://avatars.githubusercontent.com/u/20738858?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/adrianmarinwork"><img src="https://avatars.githubusercontent.com/u/118568289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/wanjohiryan"><img src="https://avatars.githubusercontent.com/u/71614375?v=4" width="50" height="50" alt=""/></a>
|
||||
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/asharonbaltazar"><img src="https://avatars.githubusercontent.com/u/58940073?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/edgarrmondragon"><img src="https://avatars.githubusercontent.com/u/16805946?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arjunyel"><img src="https://avatars.githubusercontent.com/u/11153289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/LemmyMwaura"><img src="https://avatars.githubusercontent.com/u/20738858?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Zamion101"><img src="https://avatars.githubusercontent.com/u/8071263?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/adrianmarinwork"><img src="https://avatars.githubusercontent.com/u/118568289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/wanjohiryan"><img src="https://avatars.githubusercontent.com/u/71614375?v=4" width="50" height="50" alt=""/></a>
|
||||
|
10
backend/package-lock.json
generated
@ -3823,6 +3823,7 @@
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
@ -5090,6 +5091,7 @@
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"source-map": "^0.6.1",
|
||||
"uglify-js": "^3.1.4",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@ -5748,6 +5750,7 @@
|
||||
"@types/node": "*",
|
||||
"anymatch": "^3.0.3",
|
||||
"fb-watchman": "^2.0.0",
|
||||
"fsevents": "^2.3.2",
|
||||
"graceful-fs": "^4.2.9",
|
||||
"jest-regex-util": "^29.2.0",
|
||||
"jest-util": "^29.3.1",
|
||||
@ -6571,9 +6574,11 @@
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.11.0.tgz",
|
||||
"integrity": "sha512-9l9n4Nk2BYZzljW3vHah3Z0rfS5npKw6ktnkmFgTcnzaXH1DRm3pDl6VMHu84EVb1lzmSaJC4OzWZqTkB5i2wg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-providers": "^3.186.0",
|
||||
"bson": "^4.7.0",
|
||||
"denque": "^2.1.0",
|
||||
"mongodb-connection-string-url": "^2.5.4",
|
||||
"saslprep": "^1.0.3",
|
||||
"socks": "^2.7.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -6765,9 +6770,6 @@
|
||||
},
|
||||
"bin": {
|
||||
"nopt": "bin/nopt.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
@ -7499,6 +7501,7 @@
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"string-width": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -8294,6 +8297,7 @@
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"encoding": "^0.1.13",
|
||||
"minipass": "^3.1.6",
|
||||
"minipass-sized": "^1.0.3",
|
||||
"minizlib": "^2.1.2"
|
||||
|
@ -138,7 +138,7 @@ const syncIntegrationsHelper = async ({
|
||||
// to that integration
|
||||
for await (const integration of integrations) {
|
||||
// get workspace, environment (shared) secrets
|
||||
const secrets = await BotService.getSecrets({
|
||||
const secrets = await BotService.getSecrets({ // issue here?
|
||||
workspaceId: integration.workspace.toString(),
|
||||
environment: integration.environment
|
||||
});
|
||||
|
@ -288,176 +288,25 @@ const syncSecretsNetlify = async ({
|
||||
secrets: any;
|
||||
accessToken: string;
|
||||
}) => {
|
||||
// TODO: Netlify revision in progress
|
||||
// try {
|
||||
// const getParams = new URLSearchParams({
|
||||
// context_name: integration.context,
|
||||
// site_id: integration.siteId
|
||||
// });
|
||||
|
||||
// const res = (await axios.get(
|
||||
// `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`,
|
||||
// {
|
||||
// params: getParams,
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${accessToken}`
|
||||
// }
|
||||
// }
|
||||
// ))
|
||||
// .data
|
||||
// .reduce((obj: any, secret: any) => ({
|
||||
// ...obj,
|
||||
// [secret.key]: secret
|
||||
// }), {});
|
||||
|
||||
// res.forEach((r: any) => console.log(r));
|
||||
// console.log('getParams', getParams);
|
||||
|
||||
// interface UpdateNetlifySecret {
|
||||
// key: string;
|
||||
// context: string;
|
||||
// value: string;
|
||||
// }
|
||||
|
||||
// interface DeleteNetlifySecret {
|
||||
// key: string;
|
||||
// }
|
||||
|
||||
// interface NewNetlifySecretValue {
|
||||
// value: string;
|
||||
// context: string;
|
||||
// }
|
||||
|
||||
// interface NewNetlifySecret {
|
||||
// key: string;
|
||||
// values: NewNetlifySecretValue[];
|
||||
// }
|
||||
|
||||
// let updateSecrets: UpdateNetlifySecret[] = [];
|
||||
// let deleteSecrets: DeleteNetlifySecret[] = [];
|
||||
// let newSecrets: NewNetlifySecret[] = [];
|
||||
|
||||
// interface NetlifyValue {
|
||||
// id: string;
|
||||
// value: string;
|
||||
// context: string;
|
||||
// role: string;
|
||||
// }
|
||||
|
||||
// // Identify secrets to create - GOOD
|
||||
// Object.keys(secrets).map((key) => {
|
||||
// if (!(key in res)) {
|
||||
// // case: secret does not exist in Netlify -> create secret
|
||||
// newSecrets.push({
|
||||
// key: key,
|
||||
// values: [{
|
||||
// value: secrets[key],
|
||||
// context: integration.context
|
||||
// }]
|
||||
// });
|
||||
// } else {
|
||||
// // case: secret exists in Netlify
|
||||
|
||||
// const netlifyContextsSet = new Set (res[key].values.map((netlifyValue: NetlifyValue) => netlifyValue.context));
|
||||
|
||||
// // TODO: check context/env.
|
||||
// res[key].values.forEach((netlifyValue: NetlifyValue) => {
|
||||
// if (netlifyValue.context === integration.context) {
|
||||
// // case: Netlify value context matches integration context
|
||||
// // TODO: check if value has changed
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// // Identify secrets to update and delete
|
||||
// Object.keys(res).map((key) => {
|
||||
// if (key in secrets) {
|
||||
// // if (res[key] !== secrets[key]) {
|
||||
// // // case: secret value has changed
|
||||
// // updateSecrets.push({
|
||||
// // key: key,
|
||||
// // context: integration.context,
|
||||
// // value: secrets[key]
|
||||
// // });
|
||||
// // }
|
||||
|
||||
// // TODO: modify check and record of updated secrets
|
||||
|
||||
// // case 1: new context added.
|
||||
// } else {
|
||||
// // case: secret has been deleted
|
||||
// deleteSecrets.push({
|
||||
// key
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// const syncParams = new URLSearchParams({
|
||||
// site_id: integration.siteId
|
||||
// });
|
||||
|
||||
// console.log('Netlify newSecrets', newSecrets);
|
||||
// newSecrets.forEach(secret => console.log(secret.values));
|
||||
// // Sync/push new secrets
|
||||
// if (newSecrets.length > 0) {
|
||||
// await axios.post(
|
||||
// `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`,
|
||||
// newSecrets,
|
||||
// {
|
||||
// params: syncParams,
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${accessToken}`
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
// console.log('Netlify updateSecrets', updateSecrets);
|
||||
// // Sync/push updated secrets
|
||||
// if (updateSecrets.length > 0) {
|
||||
|
||||
// updateSecrets.forEach(async (secret: UpdateNetlifySecret) => {
|
||||
// await axios.patch(
|
||||
// `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
|
||||
// {
|
||||
// context: secret.context,
|
||||
// value: secret.value
|
||||
// },
|
||||
// {
|
||||
// params: syncParams,
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${accessToken}`
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
|
||||
// console.log('Netlify deleteSecrets', deleteSecrets);
|
||||
// // Delete secrets
|
||||
// if (deleteSecrets.length > 0) {
|
||||
// deleteSecrets.forEach(async (secret: DeleteNetlifySecret) => {
|
||||
// await axios.delete(
|
||||
// `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
|
||||
// {
|
||||
// params: syncParams,
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${accessToken}`
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
// } catch (err) {
|
||||
// Sentry.setUser(null);
|
||||
// Sentry.captureException(err);
|
||||
// throw new Error('Failed to sync secrets to Heroku');
|
||||
// }
|
||||
|
||||
try {
|
||||
|
||||
interface NetlifyValue {
|
||||
id?: string;
|
||||
context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production',
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface NetlifySecret {
|
||||
key: string;
|
||||
values: NetlifyValue[];
|
||||
}
|
||||
|
||||
interface NetlifySecretsRes {
|
||||
[index: string]: NetlifySecret;
|
||||
}
|
||||
|
||||
const getParams = new URLSearchParams({
|
||||
context_name: integration.context,
|
||||
context_name: 'all', // integration.context or all
|
||||
site_id: integration.siteId
|
||||
});
|
||||
|
||||
@ -473,71 +322,94 @@ const syncSecretsNetlify = async ({
|
||||
.data
|
||||
.reduce((obj: any, secret: any) => ({
|
||||
...obj,
|
||||
[secret.key]: secret.values[0].value
|
||||
[secret.key]: secret
|
||||
}), {});
|
||||
|
||||
interface UpdateNetlifySecret {
|
||||
key: string;
|
||||
context: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface DeleteNetlifySecret {
|
||||
key: string;
|
||||
}
|
||||
|
||||
interface NewNetlifySecretValue {
|
||||
value: string;
|
||||
context: string;
|
||||
}
|
||||
|
||||
interface NewNetlifySecret {
|
||||
key: string;
|
||||
values: NewNetlifySecretValue[];
|
||||
}
|
||||
|
||||
const updateSecrets: UpdateNetlifySecret[] = [];
|
||||
const deleteSecrets: DeleteNetlifySecret[] = [];
|
||||
const newSecrets: NewNetlifySecret[] = [];
|
||||
const newSecrets: NetlifySecret[] = []; // createEnvVars
|
||||
const deleteSecrets: string[] = []; // deleteEnvVar
|
||||
const deleteSecretValues: NetlifySecret[] = []; // deleteEnvVarValue
|
||||
const updateSecrets: NetlifySecret[] = []; // setEnvVarValue
|
||||
|
||||
// Identify secrets to create
|
||||
// identify secrets to create and update
|
||||
Object.keys(secrets).map((key) => {
|
||||
if (!(key in res)) {
|
||||
// case: secret has been created
|
||||
// case: Infisical secret does not exist in Netlify -> create secret
|
||||
newSecrets.push({
|
||||
key: key,
|
||||
key,
|
||||
values: [{
|
||||
value: secrets[key], // include id?
|
||||
value: secrets[key],
|
||||
context: integration.context
|
||||
}]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Identify secrets to update and delete
|
||||
Object.keys(res).map((key) => {
|
||||
if (key in secrets) {
|
||||
if (res[key] !== secrets[key]) {
|
||||
// case: secret value has changed
|
||||
} else {
|
||||
// case: Infisical secret exists in Netlify
|
||||
const contexts = res[key].values
|
||||
.reduce((obj: any, value: NetlifyValue) => ({
|
||||
...obj,
|
||||
[value.context]: value
|
||||
}), {});
|
||||
|
||||
if (integration.context in contexts) {
|
||||
// case: Netlify secret value exists in integration context
|
||||
if (secrets[key] !== contexts[integration.context].value) {
|
||||
// case: Infisical and Netlify secret values are different
|
||||
// -> update Netlify secret context and value
|
||||
updateSecrets.push({
|
||||
key,
|
||||
values: [{
|
||||
context: integration.context,
|
||||
value: secrets[key]
|
||||
}]
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// case: Netlify secret value does not exist in integration context
|
||||
// -> add the new Netlify secret context and value
|
||||
updateSecrets.push({
|
||||
key: key,
|
||||
context: integration.context,
|
||||
value: secrets[key]
|
||||
key,
|
||||
values: [{
|
||||
context: integration.context,
|
||||
value: secrets[key]
|
||||
}]
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// case: secret has been deleted
|
||||
deleteSecrets.push({
|
||||
key
|
||||
}
|
||||
})
|
||||
|
||||
// identify secrets to delete
|
||||
// TODO: revise (patch case where 1 context was deleted but others still there
|
||||
Object.keys(res).map((key) => {
|
||||
// loop through each key's context
|
||||
if (!(key in secrets)) {
|
||||
// case: Netlify secret does not exist in Infisical
|
||||
|
||||
const numberOfValues = res[key].values.length;
|
||||
|
||||
res[key].values.forEach((value: NetlifyValue) => {
|
||||
if (value.context === integration.context) {
|
||||
if (numberOfValues <= 1) {
|
||||
// case: Netlify secret value has less than 1 context -> delete secret
|
||||
deleteSecrets.push(key);
|
||||
} else {
|
||||
// case: Netlify secret value has more than 1 context -> delete secret value context
|
||||
deleteSecretValues.push({
|
||||
key,
|
||||
values: [{
|
||||
id: value.id,
|
||||
context: integration.context,
|
||||
value: value.value
|
||||
}]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const syncParams = new URLSearchParams({
|
||||
site_id: integration.siteId
|
||||
});
|
||||
|
||||
// Sync/push new secrets
|
||||
if (newSecrets.length > 0) {
|
||||
await axios.post(
|
||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`,
|
||||
@ -551,15 +423,13 @@ const syncSecretsNetlify = async ({
|
||||
);
|
||||
}
|
||||
|
||||
// Sync/push updated secrets
|
||||
if (updateSecrets.length > 0) {
|
||||
|
||||
updateSecrets.forEach(async (secret: UpdateNetlifySecret) => {
|
||||
updateSecrets.forEach(async (secret: NetlifySecret) => {
|
||||
await axios.patch(
|
||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
|
||||
{
|
||||
context: secret.context,
|
||||
value: secret.value
|
||||
context: secret.values[0].context,
|
||||
value: secret.values[0].value
|
||||
},
|
||||
{
|
||||
params: syncParams,
|
||||
@ -571,11 +441,24 @@ const syncSecretsNetlify = async ({
|
||||
});
|
||||
}
|
||||
|
||||
// Delete secrets
|
||||
if (deleteSecrets.length > 0) {
|
||||
deleteSecrets.forEach(async (secret: DeleteNetlifySecret) => {
|
||||
deleteSecrets.forEach(async (key: string) => {
|
||||
await axios.delete(
|
||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
|
||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${key}`,
|
||||
{
|
||||
params: syncParams,
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (deleteSecretValues.length > 0) {
|
||||
deleteSecretValues.forEach(async (secret: NetlifySecret) => {
|
||||
await axios.delete(
|
||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}/value/${secret.values[0].id}`,
|
||||
{
|
||||
params: syncParams,
|
||||
headers: {
|
||||
@ -585,13 +468,13 @@ const syncSecretsNetlify = async ({
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to sync secrets to Heroku');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export {
|
||||
syncSecrets
|
||||
|
@ -1,6 +1,7 @@
|
||||
import nacl from 'tweetnacl';
|
||||
import util from 'tweetnacl-util';
|
||||
import AesGCM from './aes-gcm';
|
||||
import * as Sentry from '@sentry/node';
|
||||
|
||||
/**
|
||||
* Return new base64, NaCl, public-private key pair.
|
||||
@ -47,6 +48,8 @@ const encryptAsymmetric = ({
|
||||
util.decodeBase64(privateKey)
|
||||
);
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to perform asymmetric encryption');
|
||||
}
|
||||
|
||||
@ -86,6 +89,8 @@ const decryptAsymmetric = ({
|
||||
util.decodeBase64(privateKey)
|
||||
);
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to perform asymmetric decryption');
|
||||
}
|
||||
|
||||
@ -112,6 +117,8 @@ const encryptSymmetric = ({
|
||||
iv = obj.iv;
|
||||
tag = obj.tag;
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to perform symmetric encryption');
|
||||
}
|
||||
|
||||
@ -147,6 +154,8 @@ const decryptSymmetric = ({
|
||||
try {
|
||||
plaintext = AesGCM.decrypt(ciphertext, iv, tag, key);
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to perform symmetric decryption');
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ const INTEGRATION_OPTIONS = [
|
||||
name: 'Netlify',
|
||||
slug: 'netlify',
|
||||
image: 'Netlify',
|
||||
isAvailable: false,
|
||||
isAvailable: true,
|
||||
type: 'oauth2',
|
||||
clientId: CLIENT_ID_NETLIFY,
|
||||
docsLink: ''
|
||||
|
@ -9,7 +9,7 @@ services:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- ./nginx/default.dev.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
depends_on:
|
||||
- frontend
|
||||
- backend
|
||||
|
@ -23,7 +23,7 @@ Mandatory variables in the `.env` file:
|
||||
|
||||
1. Keys and JWT variables
|
||||
|
||||

|
||||

|
||||
|
||||
The `.env.example` has these variables empty, you can self generate the `JWT and ENCRYPTION_KEY` with this [32-byte random hex strings generator](https://www.browserling.com/tools/random-hex).
|
||||
|
||||
|
BIN
docs/images/integrations-heroku-auth.png
Normal file
After Width: | Height: | Size: 842 KiB |
BIN
docs/images/integrations-heroku.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
docs/images/integrations-netlify-auth.png
Normal file
After Width: | Height: | Size: 740 KiB |
BIN
docs/images/integrations-netlify.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
docs/images/integrations-vercel-auth.png
Normal file
After Width: | Height: | Size: 862 KiB |
BIN
docs/images/integrations-vercel.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
docs/images/integrations.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
@ -1,26 +1,29 @@
|
||||
---
|
||||
title: "Heroku"
|
||||
description: "With this integration, you can automatically sync your secrets to Heroku as soon as you update secrets in Infisical."
|
||||
---
|
||||
|
||||
## Instructions
|
||||
Prerequisites:
|
||||
|
||||
### Step 1: Open the integrations console
|
||||
- Set up and add envars to [Infisical Cloud](https://app.infisical.com)
|
||||
|
||||
Open the Infisical Dashboard. Choose the project in which you want to set up the intergation. Go to the integrations tab in the left sidebar.
|
||||
## Navigate to your project's integrations tab
|
||||
|
||||
### Step 2: Authenticate with Heroku
|
||||

|
||||
|
||||
Click on "Heroku" tile. Log in if required and provide the necessary permissions to Infisical. You will afterwards be redirected back to the integrations page.
|
||||
## Authorize Infisical for Heroku
|
||||
|
||||
Note: during an integration with Heroku, for security reasons, it is impossible to maintain end-to-end encryption. In theory, this lets Infisical decrypt yor environment variables. In practice, we can assure you that this will never be done, and it allows us to protect your secrets from bad actors online. With any questions, reach out support@infisical.com.
|
||||
Press on the Heroku tile and grant Infisical access to your Heroku account.
|
||||
|
||||
### Step 3: Start integration
|
||||

|
||||
|
||||
Choose a Heroku App that you want to sync the secrets to, and the Infisical project environment that you want to sync the secrets from. Start the integration.
|
||||
|
||||
The integration should now show status 'In Sync'. Every time you edit secrets, they will be automatically pushed to Heroku.
|
||||
|
||||
<Info>
|
||||
If you need to update your integration, you will have to delete the current one and create a new one.
|
||||
<Info>
|
||||
If this is your project's first cloud integration, then you'll have to grant Infisical access to your project's environment variables.
|
||||
Although this step breaks E2EE, it's necessary for Infisical to sync the environment variables to the cloud platform.
|
||||
</Info>
|
||||
|
||||
## Start integration
|
||||
|
||||
Select which Infisical environment secrets you want to sync to which Heroku app and press start integration to start syncing secrets to Heroku.
|
||||
|
||||

|
||||
|
||||
|
32
docs/integrations/cloud/netlify.mdx
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "Netlify"
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Infisical integrates with Netlify's new environment variable experience. If your site uses Netlify's old environment variable experience, you'll have to upgrade it to the new one to use this integration.
|
||||
</Warning>
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- Set up and add envars to [Infisical Cloud](https://app.infisical.com)
|
||||
|
||||
## Navigate to your project's integrations tab
|
||||
|
||||

|
||||
|
||||
## Authorize Infisical for Netlify
|
||||
|
||||
Press on the Netlify tile and grant Infisical access to your Netlify account.
|
||||
|
||||

|
||||
|
||||
<Info>
|
||||
If this is your project's first cloud integration, then you'll have to grant Infisical access to your project's environment variables.
|
||||
Although this step breaks E2EE, it's necessary for Infisical to sync the environment variables to the cloud platform.
|
||||
</Info>
|
||||
|
||||
## Start integration
|
||||
|
||||
Select which Infisical environment secrets you want to sync to which Netlify app and context. Lastly, press start integration to start syncing secrets to Netlify.
|
||||
|
||||

|
@ -2,4 +2,22 @@
|
||||
title: "Vercel"
|
||||
---
|
||||
|
||||
Coming soon.
|
||||
Prerequisites:
|
||||
|
||||
- Set up and add envars to [Infisical Cloud](https://app.infisical.com)
|
||||
|
||||
## Navigate to your project's integrations tab
|
||||
|
||||

|
||||
|
||||
## Authorize Infisical for Vercel
|
||||
|
||||
Press on the Vercel tile and grant Infisical access to your Vercel account.
|
||||
|
||||

|
||||
|
||||
## Start integration
|
||||
|
||||
Select which Infisical environment secrets you want to sync to which Vercel app and environment. Lastly, press start integration to start syncing secrets to Vercel.
|
||||
|
||||

|
@ -12,6 +12,8 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
|
||||
| [Docker-Compose](/integrations/platforms/docker-compose) | Platform | Available |
|
||||
| [Kubernetes](/integrations/platforms/kubernetes) | Platform | Available |
|
||||
| [Heroku](/integrations/cloud/heroku) | Cloud | Available |
|
||||
| [Vercel](/integrations/cloud/vercel) | Cloud | Available |
|
||||
| [Netlify](/integrations/cloud/netlify) | Cloud | Available |
|
||||
| [React](/integrations/frameworks/react) | Framework | Available |
|
||||
| [Vue](/integrations/frameworks/vue) | Framework | Available |
|
||||
| [Express](/integrations/frameworks/express) | Framework | Available |
|
||||
@ -26,7 +28,6 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
|
||||
| [Flask](/integrations/frameworks/flask) | Framework | Available |
|
||||
| [Laravel](/integrations/frameworks/laravel) | Framework | Available |
|
||||
| [Ruby on Rails](/integrations/frameworks/rails) | Framework | Available |
|
||||
| [Vercel](/integrations/cloud/vercel) | Cloud | Coming soon |
|
||||
| [Render](/integrations/cloud/render) | Cloud | Coming soon |
|
||||
| [Fly.io](/integrations/cloud/flyio) | Cloud | Coming soon |
|
||||
| AWS | Cloud | Coming soon |
|
||||
|
@ -133,6 +133,7 @@
|
||||
"pages": [
|
||||
"integrations/cloud/heroku",
|
||||
"integrations/cloud/vercel",
|
||||
"integrations/cloud/netlify",
|
||||
"integrations/cloud/render",
|
||||
"integrations/cloud/flyio"
|
||||
]
|
||||
|
@ -42,9 +42,9 @@ const attemptLogin = async (
|
||||
async () => {
|
||||
const clientPublicKey = client.getPublicKey();
|
||||
|
||||
const { serverPublicKey, salt } = await login1(email, clientPublicKey);
|
||||
|
||||
try {
|
||||
const { serverPublicKey, salt } = await login1(email, clientPublicKey);
|
||||
|
||||
client.setSalt(salt);
|
||||
client.setServerPublicKey(serverPublicKey);
|
||||
const clientProof = client.getProof(); // called M1
|
||||
|
@ -7,7 +7,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.3
|
||||
version: 0.1.5
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
@ -20,6 +20,11 @@ spec:
|
||||
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
{{- if .Values.backend.kubeSecretRef }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ .Values.backend.kubeSecretRef }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- range $key, $value := .Values.backendEnvironmentVariables }}
|
||||
{{- if $value | quote | eq "MUST_REPLACE" }}
|
||||
|
@ -18,6 +18,12 @@ spec:
|
||||
- name: frontend
|
||||
image: infisical/frontend
|
||||
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
|
||||
{{- if .Values.frontend.kubeSecretRef }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ .Values.frontend.kubeSecretRef }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontendEnvironmentVariables }}
|
||||
env:
|
||||
{{- range $key, $value := .Values.frontendEnvironmentVariables }}
|
||||
{{- if $value | quote | eq "MUST_REPLACE" }}
|
||||
@ -26,6 +32,7 @@ spec:
|
||||
- name: {{ $key }}
|
||||
value: {{ quote $value }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
---
|
||||
|
@ -3,14 +3,14 @@
|
||||
# PLEASE REPLACE VALUES/EDIT AS REQUIRED
|
||||
#####
|
||||
|
||||
namespace: infisical
|
||||
|
||||
frontend:
|
||||
replicaCount: 1
|
||||
image:
|
||||
repository:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "latest"
|
||||
# kubeSecretRef: some-kube-secret-name
|
||||
|
||||
|
||||
backend:
|
||||
replicaCount: 1
|
||||
@ -18,6 +18,7 @@ backend:
|
||||
repository:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "latest"
|
||||
# kubeSecretRef: some-kube-secret-name
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
@ -54,8 +55,6 @@ ingress:
|
||||
###
|
||||
backendEnvironmentVariables:
|
||||
# Required keys for platform encryption/decryption ops. Replace with nacl sk keys
|
||||
PRIVATE_KEY: MUST_REPLACE
|
||||
PUBLIC_KEY: MUST_REPLACE
|
||||
ENCRYPTION_KEY: MUST_REPLACE
|
||||
|
||||
# JWT
|
||||
@ -71,9 +70,8 @@ backendEnvironmentVariables:
|
||||
SMTP_USERNAME: MUST_REPLACE
|
||||
SMTP_PASSWORD: MUST_REPLACE
|
||||
|
||||
# You may replace with Mongo Cloud URI
|
||||
# Recommended to replace with Mongo Cloud URI as the DB instance in the cluster does not have persistence yet
|
||||
MONGO_URL: mongodb://root:root@mongodb-service:27017/
|
||||
|
||||
# frontendEnvironmentVariables:
|
||||
# INFISICAL_TELEMETRY_ENABLED: true
|
||||
|