mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 07:27:43 +00:00
Begin Netlify integration
This commit is contained in:
@@ -11,8 +11,10 @@ const JWT_SIGNUP_SECRET = process.env.JWT_SIGNUP_SECRET!;
|
|||||||
const MONGO_URL = process.env.MONGO_URL!;
|
const MONGO_URL = process.env.MONGO_URL!;
|
||||||
const NODE_ENV = process.env.NODE_ENV! || 'production';
|
const NODE_ENV = process.env.NODE_ENV! || 'production';
|
||||||
const OAUTH_CLIENT_SECRET_HEROKU = process.env.OAUTH_CLIENT_SECRET_HEROKU!;
|
const OAUTH_CLIENT_SECRET_HEROKU = process.env.OAUTH_CLIENT_SECRET_HEROKU!;
|
||||||
const CLIENT_SECRET_VERCEL = process.env.CLIENT_SECRET_VERCEL!;
|
|
||||||
const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!;
|
const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!;
|
||||||
|
const CLIENT_ID_NETLIFY = process.env.CLIENT_ID_NETLIFY!;
|
||||||
|
const CLIENT_SECRET_VERCEL = process.env.CLIENT_SECRET_VERCEL!;
|
||||||
|
const CLIENT_SECRET_NETLIFY = process.env.CLIENT_SECRET_NETLIFY!;
|
||||||
const POSTHOG_HOST = process.env.POSTHOG_HOST! || 'https://app.posthog.com';
|
const POSTHOG_HOST = process.env.POSTHOG_HOST! || 'https://app.posthog.com';
|
||||||
const POSTHOG_PROJECT_API_KEY =
|
const POSTHOG_PROJECT_API_KEY =
|
||||||
process.env.POSTHOG_PROJECT_API_KEY! ||
|
process.env.POSTHOG_PROJECT_API_KEY! ||
|
||||||
@@ -48,8 +50,10 @@ export {
|
|||||||
MONGO_URL,
|
MONGO_URL,
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
OAUTH_CLIENT_SECRET_HEROKU,
|
OAUTH_CLIENT_SECRET_HEROKU,
|
||||||
CLIENT_SECRET_VERCEL,
|
|
||||||
CLIENT_ID_VERCEL,
|
CLIENT_ID_VERCEL,
|
||||||
|
CLIENT_ID_NETLIFY,
|
||||||
|
CLIENT_SECRET_VERCEL,
|
||||||
|
CLIENT_SECRET_NETLIFY,
|
||||||
POSTHOG_HOST,
|
POSTHOG_HOST,
|
||||||
POSTHOG_PROJECT_API_KEY,
|
POSTHOG_PROJECT_API_KEY,
|
||||||
PRIVATE_KEY,
|
PRIVATE_KEY,
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ const handleOAuthExchangeHelper = async ({
|
|||||||
code
|
code
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: continue ironing out Vercel integration
|
return;
|
||||||
|
|
||||||
let update: Update = {
|
let update: Update = {
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
|
|||||||
@@ -3,15 +3,19 @@ import * as Sentry from '@sentry/node';
|
|||||||
import {
|
import {
|
||||||
INTEGRATION_HEROKU,
|
INTEGRATION_HEROKU,
|
||||||
INTEGRATION_VERCEL,
|
INTEGRATION_VERCEL,
|
||||||
|
INTEGRATION_NETLIFY,
|
||||||
INTEGRATION_HEROKU_TOKEN_URL,
|
INTEGRATION_HEROKU_TOKEN_URL,
|
||||||
INTEGRATION_VERCEL_TOKEN_URL,
|
INTEGRATION_VERCEL_TOKEN_URL,
|
||||||
|
INTEGRATION_NETLIFY_TOKEN_URL,
|
||||||
ACTION_PUSH_TO_HEROKU
|
ACTION_PUSH_TO_HEROKU
|
||||||
} from '../variables';
|
} from '../variables';
|
||||||
import {
|
import {
|
||||||
SITE_URL,
|
SITE_URL,
|
||||||
OAUTH_CLIENT_SECRET_HEROKU,
|
OAUTH_CLIENT_SECRET_HEROKU,
|
||||||
CLIENT_ID_VERCEL,
|
CLIENT_ID_VERCEL,
|
||||||
CLIENT_SECRET_VERCEL
|
CLIENT_ID_NETLIFY,
|
||||||
|
CLIENT_SECRET_VERCEL,
|
||||||
|
CLIENT_SECRET_NETLIFY
|
||||||
} from '../config';
|
} from '../config';
|
||||||
|
|
||||||
interface ExchangeCodeHerokuResponse {
|
interface ExchangeCodeHerokuResponse {
|
||||||
@@ -63,6 +67,12 @@ const exchangeCode = async ({
|
|||||||
obj = await exchangeCodeVercel({
|
obj = await exchangeCodeVercel({
|
||||||
code
|
code
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case INTEGRATION_NETLIFY:
|
||||||
|
obj = await exchangeCodeNetlify({
|
||||||
|
code
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
Sentry.setUser(null);
|
||||||
@@ -157,6 +167,60 @@ const exchangeCodeVercel = async ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
|
||||||
|
* code-token exchange
|
||||||
|
* @param {Object} obj1
|
||||||
|
* @param {Object} obj1.code - code for code-token exchange
|
||||||
|
* @returns {Object} obj2
|
||||||
|
* @returns {String} obj2.accessToken - access token for Heroku API
|
||||||
|
* @returns {String} obj2.refreshToken - refresh token for Heroku API
|
||||||
|
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
|
||||||
|
*/
|
||||||
|
const exchangeCodeNetlify = async ({
|
||||||
|
code
|
||||||
|
}: {
|
||||||
|
code: string;
|
||||||
|
}) => {
|
||||||
|
console.log('exchangeCodeNetlify');
|
||||||
|
let res: ExchangeCodeVercelResponse;
|
||||||
|
try {
|
||||||
|
res = (await axios.post(
|
||||||
|
INTEGRATION_VERCEL_TOKEN_URL,
|
||||||
|
new URLSearchParams({
|
||||||
|
code: code,
|
||||||
|
client_id: CLIENT_ID_VERCEL,
|
||||||
|
client_secret: CLIENT_SECRET_VERCEL,
|
||||||
|
redirect_uri: `${SITE_URL}/vercel`
|
||||||
|
} as any)
|
||||||
|
)).data;
|
||||||
|
|
||||||
|
res = (await axios.post(
|
||||||
|
INTEGRATION_NETLIFY_TOKEN_URL,
|
||||||
|
`${"https://api.netlify.com/oauth/token"}?code=${code}&client_id=${CLIENT_ID_NETLIFY}&client_secret=${CLIENT_SECRET_NETLIFY}&grant_type=authorization_code&redirect_uri=${SITE_URL}/netlify`
|
||||||
|
// INTEGRATION_NETLIFY_TOKEN_URL,
|
||||||
|
// new URLSearchParams({
|
||||||
|
// code: code,
|
||||||
|
// client_id: CLIENT_ID_NETLIFY,
|
||||||
|
// client_secret: CLIENT_SECRET_NETLIFY,
|
||||||
|
// redirect_uri: `${SITE_URL}/netlify`
|
||||||
|
// } as any)
|
||||||
|
));
|
||||||
|
|
||||||
|
console.log('resss', res);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('netlify err', err);
|
||||||
|
Sentry.setUser(null);
|
||||||
|
Sentry.captureException(err);
|
||||||
|
throw new Error('Failed OAuth2 code-token exchange with Netlify');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ({
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
exchangeCode
|
exchangeCode
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ const INTEGRATION_OAUTH2 = 'oauth2';
|
|||||||
// integration oauth endpoints
|
// integration oauth endpoints
|
||||||
const INTEGRATION_HEROKU_TOKEN_URL = 'https://id.heroku.com/oauth/token';
|
const INTEGRATION_HEROKU_TOKEN_URL = 'https://id.heroku.com/oauth/token';
|
||||||
const INTEGRATION_VERCEL_TOKEN_URL = 'https://api.vercel.com/v2/oauth/access_token';
|
const INTEGRATION_VERCEL_TOKEN_URL = 'https://api.vercel.com/v2/oauth/access_token';
|
||||||
const INTEGRATION_NETLIFY_TOKEN_URL = 'https://app.netlify.com/authorize';
|
const INTEGRATION_NETLIFY_TOKEN_URL = 'https://api.netlify.com/oauth/token';
|
||||||
|
|
||||||
// integration apps endpoints
|
// integration apps endpoints
|
||||||
const INTEGRATION_HEROKU_API_URL = 'https://api.heroku.com';
|
const INTEGRATION_HEROKU_API_URL = 'https://api.heroku.com';
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ const {
|
|||||||
} = require('../../components/utilities/cryptography/crypto');
|
} = require('../../components/utilities/cryptography/crypto');
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
export default function Integrations() {
|
export default function Integrations() {
|
||||||
const [integrationAuths, setIntegrationAuths] = useState([]);
|
const [integrationAuths, setIntegrationAuths] = useState([]);
|
||||||
const [integrations, setIntegrations] = useState([]);
|
const [integrations, setIntegrations] = useState([]);
|
||||||
@@ -115,20 +117,41 @@ export default function Integrations() {
|
|||||||
const handleIntegrationOption = async ({ integrationOption }) => {
|
const handleIntegrationOption = async ({ integrationOption }) => {
|
||||||
// TODO: modularize and handle switch by slug
|
// TODO: modularize and handle switch by slug
|
||||||
|
|
||||||
|
console.log('handle', integrationOption);
|
||||||
|
|
||||||
// generate CSRF token for OAuth2 code-token exchange integrations
|
// generate CSRF token for OAuth2 code-token exchange integrations
|
||||||
const csrfToken = crypto.randomBytes(16).toString("hex");
|
const state = crypto.randomBytes(16).toString("hex");
|
||||||
localStorage.setItem('latestCSRFToken', csrfToken);
|
localStorage.setItem('latestCSRFToken', state);
|
||||||
|
|
||||||
switch (integrationOption.name) {
|
switch (integrationOption.name) {
|
||||||
case 'Heroku':
|
case 'Heroku':
|
||||||
// console.log('Heroku integration ', integrationOption);
|
// console.log('Heroku integration ', integrationOption);
|
||||||
window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${csrfToken}`;
|
window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`;
|
||||||
break;
|
break;
|
||||||
case 'Vercel':
|
case 'Vercel':
|
||||||
window.location = `https://vercel.com/integrations/infisical/new?state=${csrfToken}`;
|
window.location = `https://vercel.com/integrations/infisical/new?state=${state}`;
|
||||||
break;
|
break;
|
||||||
case 'Netlify':
|
case 'Netlify':
|
||||||
console.log('netlifyyy');
|
// window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=token&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
|
||||||
|
window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
|
||||||
|
// const res = await axios.post('https://api.netlify.com/api/v1/oauth/tickets' + '?client_id=' + integrationOption.clientId);
|
||||||
|
|
||||||
|
// window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=ticket&redirect_uri=${integrationOption.redirectURL}&state=${state}&ticket=${res.data.id}`;
|
||||||
|
// `https://app.netlify.com/authorize?response_type=ticket&ticket=${ticket.id}`
|
||||||
|
try {
|
||||||
|
// const res = await axios.post('https://api.netlify.com/api/v1/oauth/tickets' + '?client_id=' + integrationOption.clientId);
|
||||||
|
// console.log('res response', res);
|
||||||
|
// const res2 = await axios.get('https://api.netlify.com/api/v1/oauth/tickets/' + res.data.id);
|
||||||
|
// console.log('res2 response', res2);
|
||||||
|
// console.log('ticket_id', res.data.id);
|
||||||
|
// // exchange ticket:
|
||||||
|
// const res3 = await axios.get(`https://api.netlify.com/api/v1/oauth/tickets/${res.data.id}/exchange`);
|
||||||
|
// console.log('res3 response', res3);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Netlify ', err);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
|
|||||||
export default function Netlify() {
|
export default function Netlify() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
|
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
|
||||||
|
const code = parsedUrl.code;
|
||||||
|
const state = parsedUrl.state;
|
||||||
// modify comment here
|
// modify comment here
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,16 +16,19 @@ export default function Netlify() {
|
|||||||
*/
|
*/
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
useEffect(async () => {
|
useEffect(async () => {
|
||||||
|
console.log('AA');
|
||||||
if (state === localStorage.getItem('latestCSRFToken')) {
|
if (state === localStorage.getItem('latestCSRFToken')) {
|
||||||
localStorage.removeItem('latestCSRFToken');
|
localStorage.removeItem('latestCSRFToken');
|
||||||
|
|
||||||
console.log('Netlify', parsedUrl);
|
console.log('Netlify', parsedUrl);
|
||||||
|
// http://localhost:8080/netlify?code=qnG0g_krhklWDpdUqfhU-t1sLeZzYI3gF2d6QVnL-Gc&state=3a78cd3154a9a99ddd4eb5d99dbb3289
|
||||||
|
// http://localhost:8080/netlify#access_token=d-78qUAnnSzvlgfG9Y_oUV6_4TQBxLbofImiBbKAjzE&token_type=Bearer&state=5da34fa49e301e9fa1a6e40925694b77
|
||||||
|
|
||||||
// await AuthorizeIntegration({
|
await AuthorizeIntegration({
|
||||||
// workspaceId: localStorage.getItem('projectData.id'),
|
workspaceId: localStorage.getItem('projectData.id'),
|
||||||
// code,
|
code,
|
||||||
// integration: "vercel"
|
integration: "netlify"
|
||||||
// });
|
});
|
||||||
|
|
||||||
// router.push("/integrations/" + localStorage.getItem("projectData.id"));
|
// router.push("/integrations/" + localStorage.getItem("projectData.id"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
"image": "Netlify",
|
"image": "Netlify",
|
||||||
"isAvailable": true,
|
"isAvailable": true,
|
||||||
"type": "oauth2",
|
"type": "oauth2",
|
||||||
"clientId": ""
|
"clientId": "frGheMeEzVEUgM5yHLcPeTj9kYJhYvqkR5IkSexOS50",
|
||||||
|
"redirectURL": "http://localhost:8080/netlify"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Google Cloud Platform",
|
"name": "Google Cloud Platform",
|
||||||
|
|||||||
Reference in New Issue
Block a user