mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 05:28:23 +00:00
Update github integration org/envs support
This commit is contained in:
@@ -410,6 +410,7 @@ export const integrationAuthServiceFactory = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!data) return [];
|
if (!data) return [];
|
||||||
|
|
||||||
return data.map(({ login: name, id: orgId }) => ({ name, orgId: String(orgId) }));
|
return data.map(({ login: name, id: orgId }) => ({ name, orgId: String(orgId) }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1124,10 +1124,6 @@ const syncSecretsGitHub = async ({
|
|||||||
selected_repositories_url?: string | undefined;
|
selected_repositories_url?: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GitHubSecretRes {
|
|
||||||
[index: string]: GitHubSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const octokit = new Octokit({
|
const octokit = new Octokit({
|
||||||
auth: accessToken
|
auth: accessToken
|
||||||
});
|
});
|
||||||
@@ -1152,7 +1148,7 @@ const syncSecretsGitHub = async ({
|
|||||||
const { data } = await octokit.request(
|
const { data } = await octokit.request(
|
||||||
"GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key",
|
"GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key",
|
||||||
{
|
{
|
||||||
repository_id: Number(integration.targetServiceId),
|
repository_id: Number(integration.appId),
|
||||||
environment_name: integration.targetEnvironmentId as string
|
environment_name: integration.targetEnvironmentId as string
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -1173,24 +1169,24 @@ const syncSecretsGitHub = async ({
|
|||||||
let encryptedSecrets: GitHubSecret[];
|
let encryptedSecrets: GitHubSecret[];
|
||||||
|
|
||||||
switch (integration.scope) {
|
switch (integration.scope) {
|
||||||
case GithubScope.Org:
|
case GithubScope.Org: {
|
||||||
encryptedSecrets = (
|
encryptedSecrets = (
|
||||||
await octokit.request("GET /orgs/{org}/actions/secrets", {
|
await octokit.request("GET /orgs/{org}/actions/secrets", {
|
||||||
org: integration.owner as string
|
org: integration.owner as string
|
||||||
})
|
})
|
||||||
).data.secrets;
|
).data.secrets;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GithubScope.Env:
|
case GithubScope.Env: {
|
||||||
encryptedSecrets = (
|
encryptedSecrets = (
|
||||||
await octokit.request("GET /repositories/{repository_id}/environments/{environment_name}/secrets", {
|
await octokit.request("GET /repositories/{repository_id}/environments/{environment_name}/secrets", {
|
||||||
repository_id: Number(integration.targetServiceId),
|
repository_id: Number(integration.appId),
|
||||||
environment_name: integration.targetEnvironmentId as string
|
environment_name: integration.targetEnvironmentId as string
|
||||||
})
|
})
|
||||||
).data.secrets;
|
).data.secrets;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default: {
|
||||||
encryptedSecrets = (
|
encryptedSecrets = (
|
||||||
await octokit.request("GET /repos/{owner}/{repo}/actions/secrets", {
|
await octokit.request("GET /repos/{owner}/{repo}/actions/secrets", {
|
||||||
owner: integration.owner as string,
|
owner: integration.owner as string,
|
||||||
@@ -1198,111 +1194,139 @@ const syncSecretsGitHub = async ({
|
|||||||
})
|
})
|
||||||
).data.secrets;
|
).data.secrets;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let encryptedSecretsMap: GitHubSecretRes = encryptedSecrets.reduce(
|
for await (const encryptedSecret of encryptedSecrets) {
|
||||||
(obj, secret) => ({
|
if (
|
||||||
...obj,
|
!(encryptedSecret.name in secrets) &&
|
||||||
[secret.name]: secret
|
!(appendices?.prefix !== undefined && !encryptedSecret.name.startsWith(appendices?.prefix)) &&
|
||||||
}),
|
!(appendices?.suffix !== undefined && !encryptedSecret.name.endsWith(appendices?.suffix))
|
||||||
{}
|
) {
|
||||||
);
|
switch (integration.scope) {
|
||||||
|
case GithubScope.Org: {
|
||||||
// filter out secrets based on prefix or suffix
|
await octokit.request("DELETE /orgs/{org}/actions/secrets/{secret_name}", {
|
||||||
encryptedSecretsMap = Object.keys(encryptedSecretsMap).reduce(
|
org: integration.owner as string,
|
||||||
(
|
secret_name: encryptedSecret.name
|
||||||
result: {
|
});
|
||||||
[key: string]: GitHubSecret;
|
break;
|
||||||
},
|
}
|
||||||
key
|
case GithubScope.Env: {
|
||||||
) => {
|
await octokit.request(
|
||||||
if (
|
"DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}",
|
||||||
(appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) &&
|
{
|
||||||
(appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)
|
repository_id: Number(integration.appId),
|
||||||
) {
|
environment_name: integration.targetEnvironmentId as string,
|
||||||
result[key] = encryptedSecretsMap[key];
|
secret_name: encryptedSecret.name
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
await octokit.request("DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
|
||||||
|
owner: integration.owner as string,
|
||||||
|
repo: integration.app as string,
|
||||||
|
secret_name: encryptedSecret.name
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
},
|
}
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
await Promise.all(
|
await sodium.ready.then(async () => {
|
||||||
Object.keys(encryptedSecretsMap).map(async (key) => {
|
for await (const key of Object.keys(secrets)) {
|
||||||
if (key in secrets) return;
|
// convert secret & base64 key to Uint8Array.
|
||||||
|
const binkey = sodium.from_base64(repoPublicKey.key, sodium.base64_variants.ORIGINAL);
|
||||||
|
const binsec = sodium.from_string(secrets[key].value);
|
||||||
|
|
||||||
|
// encrypt secret using libsodium
|
||||||
|
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
||||||
|
|
||||||
|
// convert encrypted Uint8Array to base64
|
||||||
|
const encryptedSecret = sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
||||||
|
|
||||||
switch (integration.scope) {
|
switch (integration.scope) {
|
||||||
case GithubScope.Org:
|
case GithubScope.Org:
|
||||||
return octokit.request("DELETE /orgs/{org}/actions/secrets/{secret_name}", {
|
await octokit.request("PUT /orgs/{org}/actions/secrets/{secret_name}", {
|
||||||
org: integration.owner as string,
|
org: integration.owner as string,
|
||||||
secret_name: key
|
secret_name: key,
|
||||||
|
visibility: "all",
|
||||||
|
encrypted_value: encryptedSecret,
|
||||||
|
key_id: repoPublicKey.key_id
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
case GithubScope.Env:
|
case GithubScope.Env:
|
||||||
return octokit.request(
|
await octokit.request(
|
||||||
"DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}",
|
"PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}",
|
||||||
{
|
{
|
||||||
repository_id: Number(integration.targetServiceId),
|
repository_id: Number(integration.appId),
|
||||||
environment_name: integration.targetEnvironmentId as string,
|
environment_name: integration.targetEnvironmentId as string,
|
||||||
secret_name: key
|
secret_name: key,
|
||||||
|
encrypted_value: encryptedSecret,
|
||||||
|
key_id: repoPublicKey.key_id
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return octokit.request("DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
|
await octokit.request("PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
|
||||||
owner: integration.owner as string,
|
owner: integration.owner as string,
|
||||||
repo: integration.app as string,
|
repo: integration.app as string,
|
||||||
secret_name: key
|
secret_name: key,
|
||||||
|
encrypted_value: encryptedSecret,
|
||||||
|
key_id: repoPublicKey.key_id
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
await Promise.all(
|
// for await (const key of Object.keys(secrets)) {
|
||||||
Object.keys(secrets).map((key) => {
|
// sodium.ready.then(async () => {
|
||||||
// let encryptedSecret;
|
// // convert secret & base64 key to Uint8Array.
|
||||||
return sodium.ready.then(async () => {
|
// const binkey = sodium.from_base64(repoPublicKey.key, sodium.base64_variants.ORIGINAL);
|
||||||
// convert secret & base64 key to Uint8Array.
|
// const binsec = sodium.from_string(secrets[key].value);
|
||||||
const binkey = sodium.from_base64(repoPublicKey.key, sodium.base64_variants.ORIGINAL);
|
|
||||||
const binsec = sodium.from_string(secrets[key].value);
|
|
||||||
|
|
||||||
// encrypt secret using libsodium
|
// // encrypt secret using libsodium
|
||||||
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
// const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
||||||
|
|
||||||
// convert encrypted Uint8Array to base64
|
// // convert encrypted Uint8Array to base64
|
||||||
const encryptedSecret = sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
// const encryptedSecret = sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
||||||
|
|
||||||
switch (integration.scope) {
|
// switch (integration.scope) {
|
||||||
case GithubScope.Org:
|
// case GithubScope.Org:
|
||||||
return octokit.request("PUT /orgs/{org}/actions/secrets/{secret_name}", {
|
// await octokit.request("PUT /orgs/{org}/actions/secrets/{secret_name}", {
|
||||||
org: integration.owner as string,
|
// org: integration.owner as string,
|
||||||
secret_name: key,
|
// secret_name: key,
|
||||||
visibility: "all",
|
// visibility: "all",
|
||||||
encrypted_value: encryptedSecret,
|
// encrypted_value: encryptedSecret,
|
||||||
key_id: repoPublicKey.key_id
|
// key_id: repoPublicKey.key_id
|
||||||
});
|
// });
|
||||||
case GithubScope.Env:
|
// break;
|
||||||
return octokit.request(
|
// case GithubScope.Env:
|
||||||
"PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}",
|
// await octokit.request(
|
||||||
{
|
// "PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}",
|
||||||
repository_id: Number(integration.targetServiceId),
|
// {
|
||||||
environment_name: integration.targetEnvironmentId as string,
|
// repository_id: Number(integration.appId),
|
||||||
secret_name: key,
|
// environment_name: integration.targetEnvironmentId as string,
|
||||||
encrypted_value: encryptedSecret,
|
// secret_name: key,
|
||||||
key_id: repoPublicKey.key_id
|
// encrypted_value: encryptedSecret,
|
||||||
}
|
// key_id: repoPublicKey.key_id
|
||||||
);
|
// }
|
||||||
default:
|
// );
|
||||||
return octokit.request("PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
|
// break;
|
||||||
owner: integration.owner as string,
|
// default:
|
||||||
repo: integration.app as string,
|
// await octokit.request("PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", {
|
||||||
secret_name: key,
|
// owner: integration.owner as string,
|
||||||
encrypted_value: encryptedSecret,
|
// repo: integration.app as string,
|
||||||
key_id: repoPublicKey.key_id
|
// secret_name: key,
|
||||||
});
|
// encrypted_value: encryptedSecret,
|
||||||
}
|
// key_id: repoPublicKey.key_id
|
||||||
});
|
// });
|
||||||
})
|
// break;
|
||||||
);
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -331,8 +331,6 @@ const fetchIntegrationAuthHerokuPipelines = async ({ integrationAuthId }: {
|
|||||||
`/api/v1/integration-auth/${integrationAuthId}/heroku/pipelines`
|
`/api/v1/integration-auth/${integrationAuthId}/heroku/pipelines`
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(99999, pipelines)
|
|
||||||
|
|
||||||
return pipelines;
|
return pipelines;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
repoName,
|
repoName,
|
||||||
repoOwner
|
repoOwner
|
||||||
);
|
);
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -205,9 +205,8 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
sourceEnvironment: data.selectedSourceEnvironment,
|
sourceEnvironment: data.selectedSourceEnvironment,
|
||||||
scope: data.scope,
|
scope: data.scope,
|
||||||
app: repoName,
|
app: repoName,
|
||||||
|
appId: data.repoId,
|
||||||
owner: repoOwner,
|
owner: repoOwner,
|
||||||
targetService: "Repository",
|
|
||||||
targetServiceId: data.repoId, // github repo id is needed for sync secret
|
|
||||||
targetEnvironmentId: data.envId,
|
targetEnvironmentId: data.envId,
|
||||||
metadata: {
|
metadata: {
|
||||||
secretSuffix: data.secretSuffix
|
secretSuffix: data.secretSuffix
|
||||||
@@ -238,7 +237,7 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return integrationAuth && workspace && integrationAuthApps ? (
|
return integrationAuth && workspace && integrationAuthApps ? (
|
||||||
<div className="flex w-full flex-col items-center justify-center py-4">
|
<div className="flex w-full h-full flex-col items-center justify-center py-4">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Set Up GitHub Integration</title>
|
<title>Set Up GitHub Integration</title>
|
||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
@@ -337,9 +336,9 @@ export default function GitHubCreateIntegrationPage() {
|
|||||||
onValueChange={onChange}
|
onValueChange={onChange}
|
||||||
className="w-full border border-mineshaft-500"
|
className="w-full border border-mineshaft-500"
|
||||||
>
|
>
|
||||||
<SelectItem value="github-repo">Github Repositories</SelectItem>
|
<SelectItem value="github-org">Organization</SelectItem>
|
||||||
<SelectItem value="github-org">Github Organization</SelectItem>
|
<SelectItem value="github-repo">Repository</SelectItem>
|
||||||
<SelectItem value="github-env">Github Environment</SelectItem>
|
<SelectItem value="github-env">Repository Environment</SelectItem>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const redirectForProviderAuth = (integrationOption: TCloudIntegration) =>
|
|||||||
link = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/integrations/netlify/oauth2/callback`;
|
link = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/integrations/netlify/oauth2/callback`;
|
||||||
break;
|
break;
|
||||||
case "github":
|
case "github":
|
||||||
link = `https://github.com/login/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=repo&redirect_uri=${window.location.origin}/integrations/github/oauth2/callback&state=${state}`;
|
link = `https://github.com/login/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=repo,admin:org&redirect_uri=${window.location.origin}/integrations/github/oauth2/callback&state=${state}`;
|
||||||
break;
|
break;
|
||||||
case "gitlab":
|
case "gitlab":
|
||||||
link = `${window.location.origin}/integrations/gitlab/authorize`;
|
link = `${window.location.origin}/integrations/gitlab/authorize`;
|
||||||
|
|||||||
Reference in New Issue
Block a user