mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 07:30:20 +00:00
feat: finished integration sync for rundeck
This commit is contained in:
@@ -661,6 +661,7 @@ export const INTEGRATION = {
|
||||
targetServiceId:
|
||||
"The service based grouping identifier ID of the external provider. Used in Terraform cloud, Checkly, Railway and NorthFlank",
|
||||
owner: "External integration providers service entity owner. Used in Github.",
|
||||
url: "The self-hosted URL of the platform to integrate with",
|
||||
path: "Path to save the synced secrets. Used by Gitlab, AWS Parameter Store, Vault",
|
||||
region: "AWS region to sync secrets to.",
|
||||
scope: "Scope of the provider. Used by Github, Qovery",
|
||||
|
||||
@@ -42,6 +42,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
targetService: z.string().trim().optional().describe(INTEGRATION.CREATE.targetService),
|
||||
targetServiceId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetServiceId),
|
||||
owner: z.string().trim().optional().describe(INTEGRATION.CREATE.owner),
|
||||
url: z.string().trim().optional().describe(INTEGRATION.CREATE.url),
|
||||
path: z.string().trim().optional().describe(INTEGRATION.CREATE.path),
|
||||
region: z.string().trim().optional().describe(INTEGRATION.CREATE.region),
|
||||
scope: z.string().trim().optional().describe(INTEGRATION.CREATE.scope),
|
||||
|
||||
@@ -199,6 +199,7 @@ export const integrationAuthServiceFactory = ({
|
||||
projectId,
|
||||
namespace,
|
||||
integration,
|
||||
url,
|
||||
algorithm: SecretEncryptionAlgo.AES_256_GCM,
|
||||
keyEncoding: SecretKeyEncoding.UTF8,
|
||||
...(integration === Integrations.GCP_SECRET_MANAGER
|
||||
|
||||
@@ -3355,6 +3355,74 @@ const syncSecretsHasuraCloud = async ({
|
||||
}
|
||||
};
|
||||
|
||||
/** Sync/push [secrets] to Rundeck
|
||||
* @param {Object} obj
|
||||
* @param {TIntegrations} obj.integration - integration details
|
||||
* @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values)
|
||||
* @param {String} obj.accessToken - access token for Rundeck integration
|
||||
*/
|
||||
const syncSecretsRundeck = async ({
|
||||
integration,
|
||||
secrets,
|
||||
accessToken
|
||||
}: {
|
||||
integration: TIntegrations;
|
||||
secrets: Record<string, { value: string; comment?: string }>;
|
||||
accessToken: string;
|
||||
}) => {
|
||||
interface RundeckSecretResource {
|
||||
name: string;
|
||||
}
|
||||
interface RundeckSecretsGetRes {
|
||||
resources: RundeckSecretResource[];
|
||||
}
|
||||
|
||||
let existingRundeckSecrets: string[] = [];
|
||||
|
||||
try {
|
||||
const listResult = await request.get<RundeckSecretsGetRes>(
|
||||
`${integration.url}/api/44/storage/${integration.path}`,
|
||||
{
|
||||
headers: {
|
||||
"X-Rundeck-Auth-Token": accessToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
existingRundeckSecrets = listResult.data.resources.map((res) => res.name);
|
||||
} catch (err) {
|
||||
logger.info("No existing rundeck secrets");
|
||||
}
|
||||
|
||||
for await (const [key, value] of Object.entries(secrets)) {
|
||||
if (existingRundeckSecrets.includes(key)) {
|
||||
await request.put(`${integration.url}/api/44/storage/${integration.path}/${key}`, value, {
|
||||
headers: {
|
||||
"X-Rundeck-Auth-Token": accessToken,
|
||||
"Content-Type": "application/x-rundeck-data-password"
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await request.post(`${integration.url}/api/44/storage/${integration.path}/${key}`, value, {
|
||||
headers: {
|
||||
"X-Rundeck-Auth-Token": accessToken,
|
||||
"Content-Type": "application/x-rundeck-data-password"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for await (const existingSecret of existingRundeckSecrets) {
|
||||
if (!(existingSecret in secrets)) {
|
||||
await request.delete(`${integration.url}/api/44/storage/${integration.path}/${existingSecret}`, {
|
||||
headers: {
|
||||
"X-Rundeck-Auth-Token": accessToken
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sync/push [secrets] to [app] in integration named [integration]
|
||||
*
|
||||
@@ -3621,6 +3689,13 @@ export const syncIntegrationSecrets = async ({
|
||||
accessToken
|
||||
});
|
||||
break;
|
||||
case Integrations.RUNDECK:
|
||||
await syncSecretsRundeck({
|
||||
integration,
|
||||
secrets,
|
||||
accessToken
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestError({ message: "Invalid integration" });
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ export const integrationServiceFactory = ({
|
||||
scope,
|
||||
actorId,
|
||||
region,
|
||||
url,
|
||||
isActive,
|
||||
metadata,
|
||||
secretPath,
|
||||
@@ -87,6 +88,7 @@ export const integrationServiceFactory = ({
|
||||
region,
|
||||
scope,
|
||||
owner,
|
||||
url,
|
||||
appId,
|
||||
path,
|
||||
app,
|
||||
|
||||
@@ -12,6 +12,7 @@ export type TCreateIntegrationDTO = {
|
||||
targetService?: string;
|
||||
targetServiceId?: string;
|
||||
owner?: string;
|
||||
url?: string;
|
||||
path?: string;
|
||||
region?: string;
|
||||
scope?: string;
|
||||
|
||||
Reference in New Issue
Block a user