Compare commits

...

24 Commits

Author SHA1 Message Date
239cef40f9 Update cpp.mdx 2025-07-13 20:12:43 +04:00
5545f3fe62 docs: cpp sdk 2025-07-13 20:10:01 +04:00
be0ca08821 Merge pull request #4093 from Infisical/docs-update
updated changelog
2025-07-12 15:56:52 -07:00
d816e9daa1 updated changelog 2025-07-12 15:54:54 -07:00
eb4fd0085d Merge pull request #4014 from Infisical/empty-secret-value-overview-styling
improvement(frontend): make empty value circle display on overview page yellow
2025-07-11 21:13:25 -07:00
f5b95fbe25 improvment: make empty value circle display on overview page yellow 2025-07-11 21:00:32 -07:00
6df6f44b50 Merge pull request #4008 from Infisical/ENG-3156
Use non root user for docs Dockerfile
2025-07-11 18:12:57 -04:00
2f6c79beb6 Use non root user for docs Dockerfile 2025-07-11 14:47:22 -04:00
Sid
b67fcad252 feat: migrate github app connection to env override (#4004)
* feat: migrate github app connection to env override

* fix: remove usage of github app integration

* chore: lint fix

* fix: migration cleanup

* fix: refactor integrations tab

* fix: content

* fix: remove integrations tab

---------

Co-authored-by: sidwebworks <xodeveloper@gmail.com>
2025-07-11 23:56:55 +05:30
5a41862dc9 Merge pull request #4002 from Infisical/create-policy-secret-path-input
improvement(frontend): use secret path input for create policy modal
2025-07-11 11:14:36 -07:00
9fd0189dbb Merge pull request #4007 from Infisical/move-sso-settings-to-org-settings
improvement(frontend): Move sso/provision settings back to org settings tabs
2025-07-11 11:07:34 -07:00
af26323f3b improvement: address feedback 2025-07-11 11:06:42 -07:00
74fae78c31 Merge pull request #3988 from Infisical/ENG-2932
feat(secret-sync): Cloudflare Workers
2025-07-11 14:04:54 -04:00
1aa9be203e improvement: move sso/provision settings back to org settings tabs 2025-07-11 10:58:35 -07:00
f9ef5cf930 Remove concurrency to avoid rate limit 2025-07-11 13:47:43 -04:00
16c89c6dbd Reviews 2025-07-11 13:38:17 -04:00
782b6fce4a Merge branch 'main' into ENG-2932 2025-07-11 12:54:27 -04:00
1567239fc2 improvement: use secret path input for create policy modal 2025-07-10 16:05:37 -07:00
79d80fad08 Fix greptile reviews 2025-07-09 22:27:42 -04:00
f58de53995 CF Workers Sync Docs 2025-07-09 22:05:36 -04:00
f85c045b09 Fix endpoints 2025-07-09 20:16:55 -04:00
6477a9f095 Merge branch 'main' into ENG-2932 2025-07-09 20:02:15 -04:00
e3a7478acb Merge branch 'main' into ENG-2932 2025-07-09 18:13:48 -04:00
4f348316e7 feat(secret-sync): Cloudflare Workers 2025-07-09 17:03:18 -04:00
95 changed files with 906 additions and 419 deletions

View File

@ -0,0 +1,66 @@
import { Knex } from "knex";
import { inMemoryKeyStore } from "@app/keystore/memory";
import { selectAllTableCols } from "@app/lib/knex";
import { TableName } from "../schemas";
import { getMigrationEnvConfig } from "./utils/env-config";
import { getMigrationEncryptionServices } from "./utils/services";
export async function up(knex: Knex) {
const existingSuperAdminsWithGithubConnection = await knex(TableName.SuperAdmin)
.select(selectAllTableCols(TableName.SuperAdmin))
.whereNotNull(`${TableName.SuperAdmin}.encryptedGitHubAppConnectionClientId`);
const envConfig = getMigrationEnvConfig();
const keyStore = inMemoryKeyStore();
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
const decryptor = kmsService.decryptWithRootKey();
const encryptor = kmsService.encryptWithRootKey();
const tasks = existingSuperAdminsWithGithubConnection.map(async (admin) => {
const overrides = (
admin.encryptedEnvOverrides ? JSON.parse(decryptor(Buffer.from(admin.encryptedEnvOverrides)).toString()) : {}
) as Record<string, string>;
if (admin.encryptedGitHubAppConnectionClientId) {
overrides.INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID = decryptor(
admin.encryptedGitHubAppConnectionClientId
).toString();
}
if (admin.encryptedGitHubAppConnectionClientSecret) {
overrides.INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET = decryptor(
admin.encryptedGitHubAppConnectionClientSecret
).toString();
}
if (admin.encryptedGitHubAppConnectionPrivateKey) {
overrides.INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY = decryptor(
admin.encryptedGitHubAppConnectionPrivateKey
).toString();
}
if (admin.encryptedGitHubAppConnectionSlug) {
overrides.INF_APP_CONNECTION_GITHUB_APP_SLUG = decryptor(admin.encryptedGitHubAppConnectionSlug).toString();
}
if (admin.encryptedGitHubAppConnectionId) {
overrides.INF_APP_CONNECTION_GITHUB_APP_ID = decryptor(admin.encryptedGitHubAppConnectionId).toString();
}
const encryptedEnvOverrides = encryptor(Buffer.from(JSON.stringify(overrides)));
await knex(TableName.SuperAdmin).where({ id: admin.id }).update({
encryptedEnvOverrides
});
});
await Promise.all(tasks);
}
export async function down() {
// No down migration needed as this migration is only for data transformation
// and does not change the schema.
}

View File

@ -2472,6 +2472,9 @@ export const SecretSyncs = {
projectName: "The name of the Cloudflare Pages project to sync secrets to.", projectName: "The name of the Cloudflare Pages project to sync secrets to.",
environment: "The environment of the Cloudflare Pages project to sync secrets to." environment: "The environment of the Cloudflare Pages project to sync secrets to."
}, },
CLOUDFLARE_WORKERS: {
scriptId: "The ID of the Cloudflare Workers script to sync secrets to."
},
ZABBIX: { ZABBIX: {
scope: "The Zabbix scope that secrets should be synced to.", scope: "The Zabbix scope that secrets should be synced to.",
hostId: "The ID of the Zabbix host to sync secrets to.", hostId: "The ID of the Zabbix host to sync secrets to.",

View File

@ -50,4 +50,32 @@ export const registerCloudflareConnectionRouter = async (server: FastifyZodProvi
return projects; return projects;
} }
}); });
server.route({
method: "GET",
url: `/:connectionId/cloudflare-workers-scripts`,
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
connectionId: z.string().uuid()
}),
response: {
200: z
.object({
id: z.string()
})
.array()
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { connectionId } = req.params;
const projects = await server.services.appConnection.cloudflare.listWorkersScripts(connectionId, req.permission);
return projects;
}
});
}; };

View File

@ -0,0 +1,17 @@
import {
CloudflareWorkersSyncSchema,
CreateCloudflareWorkersSyncSchema,
UpdateCloudflareWorkersSyncSchema
} from "@app/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints";
export const registerCloudflareWorkersSyncRouter = async (server: FastifyZodProvider) =>
registerSyncSecretsEndpoints({
destination: SecretSync.CloudflareWorkers,
server,
responseSchema: CloudflareWorkersSyncSchema,
createSchema: CreateCloudflareWorkersSyncSchema,
updateSchema: UpdateCloudflareWorkersSyncSchema
});

View File

@ -9,6 +9,7 @@ import { registerAzureDevOpsSyncRouter } from "./azure-devops-sync-router";
import { registerAzureKeyVaultSyncRouter } from "./azure-key-vault-sync-router"; import { registerAzureKeyVaultSyncRouter } from "./azure-key-vault-sync-router";
import { registerCamundaSyncRouter } from "./camunda-sync-router"; import { registerCamundaSyncRouter } from "./camunda-sync-router";
import { registerCloudflarePagesSyncRouter } from "./cloudflare-pages-sync-router"; import { registerCloudflarePagesSyncRouter } from "./cloudflare-pages-sync-router";
import { registerCloudflareWorkersSyncRouter } from "./cloudflare-workers-sync-router";
import { registerDatabricksSyncRouter } from "./databricks-sync-router"; import { registerDatabricksSyncRouter } from "./databricks-sync-router";
import { registerFlyioSyncRouter } from "./flyio-sync-router"; import { registerFlyioSyncRouter } from "./flyio-sync-router";
import { registerGcpSyncRouter } from "./gcp-sync-router"; import { registerGcpSyncRouter } from "./gcp-sync-router";
@ -50,6 +51,8 @@ export const SECRET_SYNC_REGISTER_ROUTER_MAP: Record<SecretSync, (server: Fastif
[SecretSync.Flyio]: registerFlyioSyncRouter, [SecretSync.Flyio]: registerFlyioSyncRouter,
[SecretSync.GitLab]: registerGitLabSyncRouter, [SecretSync.GitLab]: registerGitLabSyncRouter,
[SecretSync.CloudflarePages]: registerCloudflarePagesSyncRouter, [SecretSync.CloudflarePages]: registerCloudflarePagesSyncRouter,
[SecretSync.CloudflareWorkers]: registerCloudflareWorkersSyncRouter,
[SecretSync.Zabbix]: registerZabbixSyncRouter, [SecretSync.Zabbix]: registerZabbixSyncRouter,
[SecretSync.Railway]: registerRailwaySyncRouter [SecretSync.Railway]: registerRailwaySyncRouter
}; };

View File

@ -26,6 +26,10 @@ import {
CloudflarePagesSyncListItemSchema, CloudflarePagesSyncListItemSchema,
CloudflarePagesSyncSchema CloudflarePagesSyncSchema
} from "@app/services/secret-sync/cloudflare-pages/cloudflare-pages-schema"; } from "@app/services/secret-sync/cloudflare-pages/cloudflare-pages-schema";
import {
CloudflareWorkersSyncListItemSchema,
CloudflareWorkersSyncSchema
} from "@app/services/secret-sync/cloudflare-workers/cloudflare-workers-schemas";
import { DatabricksSyncListItemSchema, DatabricksSyncSchema } from "@app/services/secret-sync/databricks"; import { DatabricksSyncListItemSchema, DatabricksSyncSchema } from "@app/services/secret-sync/databricks";
import { FlyioSyncListItemSchema, FlyioSyncSchema } from "@app/services/secret-sync/flyio"; import { FlyioSyncListItemSchema, FlyioSyncSchema } from "@app/services/secret-sync/flyio";
import { GcpSyncListItemSchema, GcpSyncSchema } from "@app/services/secret-sync/gcp"; import { GcpSyncListItemSchema, GcpSyncSchema } from "@app/services/secret-sync/gcp";
@ -65,6 +69,8 @@ const SecretSyncSchema = z.discriminatedUnion("destination", [
FlyioSyncSchema, FlyioSyncSchema,
GitLabSyncSchema, GitLabSyncSchema,
CloudflarePagesSyncSchema, CloudflarePagesSyncSchema,
CloudflareWorkersSyncSchema,
ZabbixSyncSchema, ZabbixSyncSchema,
RailwaySyncSchema RailwaySyncSchema
]); ]);
@ -92,6 +98,8 @@ const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [
FlyioSyncListItemSchema, FlyioSyncListItemSchema,
GitLabSyncListItemSchema, GitLabSyncListItemSchema,
CloudflarePagesSyncListItemSchema, CloudflarePagesSyncListItemSchema,
CloudflareWorkersSyncListItemSchema,
ZabbixSyncListItemSchema, ZabbixSyncListItemSchema,
RailwaySyncListItemSchema RailwaySyncListItemSchema
]); ]);

View File

@ -9,7 +9,8 @@ import { CloudflareConnectionMethod } from "./cloudflare-connection-enum";
import { import {
TCloudflareConnection, TCloudflareConnection,
TCloudflareConnectionConfig, TCloudflareConnectionConfig,
TCloudflarePagesProject TCloudflarePagesProject,
TCloudflareWorkersScript
} from "./cloudflare-connection-types"; } from "./cloudflare-connection-types";
export const getCloudflareConnectionListItem = () => { export const getCloudflareConnectionListItem = () => {
@ -43,6 +44,28 @@ export const listCloudflarePagesProjects = async (
})); }));
}; };
export const listCloudflareWorkersScripts = async (
appConnection: TCloudflareConnection
): Promise<TCloudflareWorkersScript[]> => {
const {
credentials: { apiToken, accountId }
} = appConnection;
const { data } = await request.get<{ result: { id: string }[] }>(
`${IntegrationUrls.CLOUDFLARE_API_URL}/client/v4/accounts/${accountId}/workers/scripts`,
{
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
}
);
return data.result.map((a) => ({
id: a.id
}));
};
export const validateCloudflareConnectionCredentials = async (config: TCloudflareConnectionConfig) => { export const validateCloudflareConnectionCredentials = async (config: TCloudflareConnectionConfig) => {
const { apiToken, accountId } = config.credentials; const { apiToken, accountId } = config.credentials;

View File

@ -2,7 +2,7 @@ import { logger } from "@app/lib/logger";
import { OrgServiceActor } from "@app/lib/types"; import { OrgServiceActor } from "@app/lib/types";
import { AppConnection } from "../app-connection-enums"; import { AppConnection } from "../app-connection-enums";
import { listCloudflarePagesProjects } from "./cloudflare-connection-fns"; import { listCloudflarePagesProjects, listCloudflareWorkersScripts } from "./cloudflare-connection-fns";
import { TCloudflareConnection } from "./cloudflare-connection-types"; import { TCloudflareConnection } from "./cloudflare-connection-types";
type TGetAppConnectionFunc = ( type TGetAppConnectionFunc = (
@ -19,12 +19,31 @@ export const cloudflareConnectionService = (getAppConnection: TGetAppConnectionF
return projects; return projects;
} catch (error) { } catch (error) {
logger.error(error, "Failed to list Cloudflare Pages projects for Cloudflare connection"); logger.error(
error,
`Failed to list Cloudflare Pages projects for Cloudflare connection [connectionId=${connectionId}]`
);
return [];
}
};
const listWorkersScripts = async (connectionId: string, actor: OrgServiceActor) => {
const appConnection = await getAppConnection(AppConnection.Cloudflare, connectionId, actor);
try {
const projects = await listCloudflareWorkersScripts(appConnection);
return projects;
} catch (error) {
logger.error(
error,
`Failed to list Cloudflare Workers scripts for Cloudflare connection [connectionId=${connectionId}]`
);
return []; return [];
} }
}; };
return { return {
listPagesProjects listPagesProjects,
listWorkersScripts
}; };
}; };

View File

@ -28,3 +28,7 @@ export type TCloudflarePagesProject = {
id: string; id: string;
name: string; name: string;
}; };
export type TCloudflareWorkersScript = {
id: string;
};

View File

@ -7,7 +7,6 @@ import { request } from "@app/lib/config/request";
import { BadRequestError, ForbiddenRequestError, InternalServerError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, InternalServerError } from "@app/lib/errors";
import { getAppConnectionMethodName } from "@app/services/app-connection/app-connection-fns"; import { getAppConnectionMethodName } from "@app/services/app-connection/app-connection-fns";
import { IntegrationUrls } from "@app/services/integration-auth/integration-list"; import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
import { getInstanceIntegrationsConfig } from "@app/services/super-admin/super-admin-service";
import { AppConnection } from "../app-connection-enums"; import { AppConnection } from "../app-connection-enums";
import { GitHubConnectionMethod } from "./github-connection-enums"; import { GitHubConnectionMethod } from "./github-connection-enums";
@ -15,14 +14,13 @@ import { TGitHubConnection, TGitHubConnectionConfig } from "./github-connection-
export const getGitHubConnectionListItem = () => { export const getGitHubConnectionListItem = () => {
const { INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID, INF_APP_CONNECTION_GITHUB_APP_SLUG } = getConfig(); const { INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID, INF_APP_CONNECTION_GITHUB_APP_SLUG } = getConfig();
const { gitHubAppConnection } = getInstanceIntegrationsConfig();
return { return {
name: "GitHub" as const, name: "GitHub" as const,
app: AppConnection.GitHub as const, app: AppConnection.GitHub as const,
methods: Object.values(GitHubConnectionMethod) as [GitHubConnectionMethod.App, GitHubConnectionMethod.OAuth], methods: Object.values(GitHubConnectionMethod) as [GitHubConnectionMethod.App, GitHubConnectionMethod.OAuth],
oauthClientId: INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID, oauthClientId: INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID,
appClientSlug: gitHubAppConnection.appSlug || INF_APP_CONNECTION_GITHUB_APP_SLUG appClientSlug: INF_APP_CONNECTION_GITHUB_APP_SLUG
}; };
}; };
@ -32,10 +30,9 @@ export const getGitHubClient = (appConnection: TGitHubConnection) => {
const { method, credentials } = appConnection; const { method, credentials } = appConnection;
let client: Octokit; let client: Octokit;
const { gitHubAppConnection } = getInstanceIntegrationsConfig();
const appId = gitHubAppConnection.appId || appCfg.INF_APP_CONNECTION_GITHUB_APP_ID; const appId = appCfg.INF_APP_CONNECTION_GITHUB_APP_ID;
const appPrivateKey = gitHubAppConnection.privateKey || appCfg.INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY; const appPrivateKey = appCfg.INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY;
switch (method) { switch (method) {
case GitHubConnectionMethod.App: case GitHubConnectionMethod.App:
@ -157,8 +154,6 @@ type TokenRespData = {
export const validateGitHubConnectionCredentials = async (config: TGitHubConnectionConfig) => { export const validateGitHubConnectionCredentials = async (config: TGitHubConnectionConfig) => {
const { credentials, method } = config; const { credentials, method } = config;
const { gitHubAppConnection } = getInstanceIntegrationsConfig();
const { const {
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID, INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID,
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_SECRET, INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_SECRET,
@ -170,8 +165,8 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
const { clientId, clientSecret } = const { clientId, clientSecret } =
method === GitHubConnectionMethod.App method === GitHubConnectionMethod.App
? { ? {
clientId: gitHubAppConnection.clientId || INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID, clientId: INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID,
clientSecret: gitHubAppConnection.clientSecret || INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET clientSecret: INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET
} }
: // oauth : // oauth
{ {

View File

@ -0,0 +1,10 @@
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import { TSecretSyncListItem } from "@app/services/secret-sync/secret-sync-types";
export const CLOUDFLARE_WORKERS_SYNC_LIST_OPTION: TSecretSyncListItem = {
name: "Cloudflare Workers",
destination: SecretSync.CloudflareWorkers,
connection: AppConnection.Cloudflare,
canImportSecrets: false
};

View File

@ -0,0 +1,121 @@
import { request } from "@app/lib/config/request";
import { applyJitter } from "@app/lib/dates";
import { delay as delayMs } from "@app/lib/delay";
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns";
import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
import { SECRET_SYNC_NAME_MAP } from "../secret-sync-maps";
import { TCloudflareWorkersSyncWithCredentials } from "./cloudflare-workers-types";
const getSecretKeys = async (secretSync: TCloudflareWorkersSyncWithCredentials): Promise<string[]> => {
const {
destinationConfig,
connection: {
credentials: { apiToken, accountId }
}
} = secretSync;
const { data } = await request.get<{
result: Array<{ name: string }>;
}>(
`${IntegrationUrls.CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/scripts/${destinationConfig.scriptId}/secrets`,
{
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
}
);
return data.result.map((s) => s.name);
};
export const CloudflareWorkersSyncFns = {
syncSecrets: async (secretSync: TCloudflareWorkersSyncWithCredentials, secretMap: TSecretMap) => {
const {
connection: {
credentials: { apiToken, accountId }
},
destinationConfig: { scriptId }
} = secretSync;
const existingSecretNames = await getSecretKeys(secretSync);
const secretMapKeys = new Set(Object.keys(secretMap));
for await (const [key, val] of Object.entries(secretMap)) {
await delayMs(Math.max(0, applyJitter(100, 200)));
await request.put(
`${IntegrationUrls.CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/scripts/${scriptId}/secrets`,
{ name: key, text: val.value, type: "secret_text" },
{
headers: {
Authorization: `Bearer ${apiToken}`,
"Content-Type": "application/json"
}
}
);
}
if (!secretSync.syncOptions.disableSecretDeletion) {
const secretsToDelete = existingSecretNames.filter((existingKey) => {
const isManagedBySchema = matchesSchema(
existingKey,
secretSync.environment?.slug || "",
secretSync.syncOptions.keySchema
);
const isInNewSecretMap = secretMapKeys.has(existingKey);
return !isInNewSecretMap && isManagedBySchema;
});
for await (const key of secretsToDelete) {
await delayMs(Math.max(0, applyJitter(100, 200)));
await request.delete(
`${IntegrationUrls.CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/scripts/${scriptId}/secrets/${key}`,
{
headers: {
Authorization: `Bearer ${apiToken}`
}
}
);
}
}
},
getSecrets: async (secretSync: TCloudflareWorkersSyncWithCredentials): Promise<TSecretMap> => {
throw new Error(`${SECRET_SYNC_NAME_MAP[secretSync.destination]} does not support importing secrets.`);
},
removeSecrets: async (secretSync: TCloudflareWorkersSyncWithCredentials, secretMap: TSecretMap) => {
const {
connection: {
credentials: { apiToken, accountId }
},
destinationConfig: { scriptId }
} = secretSync;
const existingSecretNames = await getSecretKeys(secretSync);
const secretMapToRemoveKeys = new Set(Object.keys(secretMap));
for await (const existingKey of existingSecretNames) {
const isManagedBySchema = matchesSchema(
existingKey,
secretSync.environment?.slug || "",
secretSync.syncOptions.keySchema
);
const isInSecretMapToRemove = secretMapToRemoveKeys.has(existingKey);
if (isInSecretMapToRemove && isManagedBySchema) {
await delayMs(Math.max(0, applyJitter(100, 200)));
await request.delete(
`${IntegrationUrls.CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/scripts/${scriptId}/secrets/${existingKey}`,
{
headers: {
Authorization: `Bearer ${apiToken}`
}
}
);
}
}
}
};

View File

@ -0,0 +1,55 @@
import RE2 from "re2";
import { z } from "zod";
import { SecretSyncs } from "@app/lib/api-docs";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import {
BaseSecretSyncSchema,
GenericCreateSecretSyncFieldsSchema,
GenericUpdateSecretSyncFieldsSchema
} from "@app/services/secret-sync/secret-sync-schemas";
import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types";
const CloudflareWorkersSyncDestinationConfigSchema = z.object({
scriptId: z
.string()
.min(1, "Script ID is required")
.max(64)
.refine((val) => {
const re2 = new RE2(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/);
return re2.test(val);
}, "Invalid script ID format")
.describe(SecretSyncs.DESTINATION_CONFIG.CLOUDFLARE_WORKERS.scriptId)
});
const CloudflareWorkersSyncOptionsConfig: TSyncOptionsConfig = { canImportSecrets: false };
export const CloudflareWorkersSyncSchema = BaseSecretSyncSchema(
SecretSync.CloudflareWorkers,
CloudflareWorkersSyncOptionsConfig
).extend({
destination: z.literal(SecretSync.CloudflareWorkers),
destinationConfig: CloudflareWorkersSyncDestinationConfigSchema
});
export const CreateCloudflareWorkersSyncSchema = GenericCreateSecretSyncFieldsSchema(
SecretSync.CloudflareWorkers,
CloudflareWorkersSyncOptionsConfig
).extend({
destinationConfig: CloudflareWorkersSyncDestinationConfigSchema
});
export const UpdateCloudflareWorkersSyncSchema = GenericUpdateSecretSyncFieldsSchema(
SecretSync.CloudflareWorkers,
CloudflareWorkersSyncOptionsConfig
).extend({
destinationConfig: CloudflareWorkersSyncDestinationConfigSchema.optional()
});
export const CloudflareWorkersSyncListItemSchema = z.object({
name: z.literal("Cloudflare Workers"),
connection: z.literal(AppConnection.Cloudflare),
destination: z.literal(SecretSync.CloudflareWorkers),
canImportSecrets: z.literal(false)
});

View File

@ -0,0 +1,19 @@
import z from "zod";
import { TCloudflareConnection } from "@app/services/app-connection/cloudflare/cloudflare-connection-types";
import {
CloudflareWorkersSyncListItemSchema,
CloudflareWorkersSyncSchema,
CreateCloudflareWorkersSyncSchema
} from "./cloudflare-workers-schemas";
export type TCloudflareWorkersSyncListItem = z.infer<typeof CloudflareWorkersSyncListItemSchema>;
export type TCloudflareWorkersSync = z.infer<typeof CloudflareWorkersSyncSchema>;
export type TCloudflareWorkersSyncInput = z.infer<typeof CreateCloudflareWorkersSyncSchema>;
export type TCloudflareWorkersSyncWithCredentials = TCloudflareWorkersSync & {
connection: TCloudflareConnection;
};

View File

@ -0,0 +1,4 @@
export * from "./cloudflare-workers-constants";
export * from "./cloudflare-workers-fns";
export * from "./cloudflare-workers-schemas";
export * from "./cloudflare-workers-types";

View File

@ -21,6 +21,8 @@ export enum SecretSync {
Flyio = "flyio", Flyio = "flyio",
GitLab = "gitlab", GitLab = "gitlab",
CloudflarePages = "cloudflare-pages", CloudflarePages = "cloudflare-pages",
CloudflareWorkers = "cloudflare-workers",
Zabbix = "zabbix", Zabbix = "zabbix",
Railway = "railway" Railway = "railway"
} }

View File

@ -31,6 +31,7 @@ import { AZURE_KEY_VAULT_SYNC_LIST_OPTION, azureKeyVaultSyncFactory } from "./az
import { CAMUNDA_SYNC_LIST_OPTION, camundaSyncFactory } from "./camunda"; import { CAMUNDA_SYNC_LIST_OPTION, camundaSyncFactory } from "./camunda";
import { CLOUDFLARE_PAGES_SYNC_LIST_OPTION } from "./cloudflare-pages/cloudflare-pages-constants"; import { CLOUDFLARE_PAGES_SYNC_LIST_OPTION } from "./cloudflare-pages/cloudflare-pages-constants";
import { CloudflarePagesSyncFns } from "./cloudflare-pages/cloudflare-pages-fns"; import { CloudflarePagesSyncFns } from "./cloudflare-pages/cloudflare-pages-fns";
import { CLOUDFLARE_WORKERS_SYNC_LIST_OPTION, CloudflareWorkersSyncFns } from "./cloudflare-workers";
import { FLYIO_SYNC_LIST_OPTION, FlyioSyncFns } from "./flyio"; import { FLYIO_SYNC_LIST_OPTION, FlyioSyncFns } from "./flyio";
import { GCP_SYNC_LIST_OPTION } from "./gcp"; import { GCP_SYNC_LIST_OPTION } from "./gcp";
import { GcpSyncFns } from "./gcp/gcp-sync-fns"; import { GcpSyncFns } from "./gcp/gcp-sync-fns";
@ -72,6 +73,8 @@ const SECRET_SYNC_LIST_OPTIONS: Record<SecretSync, TSecretSyncListItem> = {
[SecretSync.Flyio]: FLYIO_SYNC_LIST_OPTION, [SecretSync.Flyio]: FLYIO_SYNC_LIST_OPTION,
[SecretSync.GitLab]: GITLAB_SYNC_LIST_OPTION, [SecretSync.GitLab]: GITLAB_SYNC_LIST_OPTION,
[SecretSync.CloudflarePages]: CLOUDFLARE_PAGES_SYNC_LIST_OPTION, [SecretSync.CloudflarePages]: CLOUDFLARE_PAGES_SYNC_LIST_OPTION,
[SecretSync.CloudflareWorkers]: CLOUDFLARE_WORKERS_SYNC_LIST_OPTION,
[SecretSync.Zabbix]: ZABBIX_SYNC_LIST_OPTION, [SecretSync.Zabbix]: ZABBIX_SYNC_LIST_OPTION,
[SecretSync.Railway]: RAILWAY_SYNC_LIST_OPTION [SecretSync.Railway]: RAILWAY_SYNC_LIST_OPTION
}; };
@ -241,6 +244,8 @@ export const SecretSyncFns = {
return GitLabSyncFns.syncSecrets(secretSync, schemaSecretMap, { appConnectionDAL, kmsService }); return GitLabSyncFns.syncSecrets(secretSync, schemaSecretMap, { appConnectionDAL, kmsService });
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
return CloudflarePagesSyncFns.syncSecrets(secretSync, schemaSecretMap); return CloudflarePagesSyncFns.syncSecrets(secretSync, schemaSecretMap);
case SecretSync.CloudflareWorkers:
return CloudflareWorkersSyncFns.syncSecrets(secretSync, schemaSecretMap);
case SecretSync.Zabbix: case SecretSync.Zabbix:
return ZabbixSyncFns.syncSecrets(secretSync, schemaSecretMap); return ZabbixSyncFns.syncSecrets(secretSync, schemaSecretMap);
case SecretSync.Railway: case SecretSync.Railway:
@ -337,6 +342,9 @@ export const SecretSyncFns = {
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
secretMap = await CloudflarePagesSyncFns.getSecrets(secretSync); secretMap = await CloudflarePagesSyncFns.getSecrets(secretSync);
break; break;
case SecretSync.CloudflareWorkers:
secretMap = await CloudflareWorkersSyncFns.getSecrets(secretSync);
break;
case SecretSync.Zabbix: case SecretSync.Zabbix:
secretMap = await ZabbixSyncFns.getSecrets(secretSync); secretMap = await ZabbixSyncFns.getSecrets(secretSync);
break; break;
@ -420,6 +428,8 @@ export const SecretSyncFns = {
return GitLabSyncFns.removeSecrets(secretSync, schemaSecretMap, { appConnectionDAL, kmsService }); return GitLabSyncFns.removeSecrets(secretSync, schemaSecretMap, { appConnectionDAL, kmsService });
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
return CloudflarePagesSyncFns.removeSecrets(secretSync, schemaSecretMap); return CloudflarePagesSyncFns.removeSecrets(secretSync, schemaSecretMap);
case SecretSync.CloudflareWorkers:
return CloudflareWorkersSyncFns.removeSecrets(secretSync, schemaSecretMap);
case SecretSync.Zabbix: case SecretSync.Zabbix:
return ZabbixSyncFns.removeSecrets(secretSync, schemaSecretMap); return ZabbixSyncFns.removeSecrets(secretSync, schemaSecretMap);
case SecretSync.Railway: case SecretSync.Railway:

View File

@ -24,6 +24,8 @@ export const SECRET_SYNC_NAME_MAP: Record<SecretSync, string> = {
[SecretSync.Flyio]: "Fly.io", [SecretSync.Flyio]: "Fly.io",
[SecretSync.GitLab]: "GitLab", [SecretSync.GitLab]: "GitLab",
[SecretSync.CloudflarePages]: "Cloudflare Pages", [SecretSync.CloudflarePages]: "Cloudflare Pages",
[SecretSync.CloudflareWorkers]: "Cloudflare Workers",
[SecretSync.Zabbix]: "Zabbix", [SecretSync.Zabbix]: "Zabbix",
[SecretSync.Railway]: "Railway" [SecretSync.Railway]: "Railway"
}; };
@ -51,6 +53,8 @@ export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
[SecretSync.Flyio]: AppConnection.Flyio, [SecretSync.Flyio]: AppConnection.Flyio,
[SecretSync.GitLab]: AppConnection.GitLab, [SecretSync.GitLab]: AppConnection.GitLab,
[SecretSync.CloudflarePages]: AppConnection.Cloudflare, [SecretSync.CloudflarePages]: AppConnection.Cloudflare,
[SecretSync.CloudflareWorkers]: AppConnection.Cloudflare,
[SecretSync.Zabbix]: AppConnection.Zabbix, [SecretSync.Zabbix]: AppConnection.Zabbix,
[SecretSync.Railway]: AppConnection.Railway [SecretSync.Railway]: AppConnection.Railway
}; };
@ -78,6 +82,8 @@ export const SECRET_SYNC_PLAN_MAP: Record<SecretSync, SecretSyncPlanType> = {
[SecretSync.Flyio]: SecretSyncPlanType.Regular, [SecretSync.Flyio]: SecretSyncPlanType.Regular,
[SecretSync.GitLab]: SecretSyncPlanType.Regular, [SecretSync.GitLab]: SecretSyncPlanType.Regular,
[SecretSync.CloudflarePages]: SecretSyncPlanType.Regular, [SecretSync.CloudflarePages]: SecretSyncPlanType.Regular,
[SecretSync.CloudflareWorkers]: SecretSyncPlanType.Regular,
[SecretSync.Zabbix]: SecretSyncPlanType.Regular, [SecretSync.Zabbix]: SecretSyncPlanType.Regular,
[SecretSync.Railway]: SecretSyncPlanType.Regular [SecretSync.Railway]: SecretSyncPlanType.Regular
}; };

View File

@ -78,6 +78,12 @@ import {
TCloudflarePagesSyncListItem, TCloudflarePagesSyncListItem,
TCloudflarePagesSyncWithCredentials TCloudflarePagesSyncWithCredentials
} from "./cloudflare-pages/cloudflare-pages-types"; } from "./cloudflare-pages/cloudflare-pages-types";
import {
TCloudflareWorkersSync,
TCloudflareWorkersSyncInput,
TCloudflareWorkersSyncListItem,
TCloudflareWorkersSyncWithCredentials
} from "./cloudflare-workers";
import { TFlyioSync, TFlyioSyncInput, TFlyioSyncListItem, TFlyioSyncWithCredentials } from "./flyio/flyio-sync-types"; import { TFlyioSync, TFlyioSyncInput, TFlyioSyncListItem, TFlyioSyncWithCredentials } from "./flyio/flyio-sync-types";
import { TGcpSync, TGcpSyncInput, TGcpSyncListItem, TGcpSyncWithCredentials } from "./gcp"; import { TGcpSync, TGcpSyncInput, TGcpSyncListItem, TGcpSyncWithCredentials } from "./gcp";
import { TGitLabSync, TGitLabSyncInput, TGitLabSyncListItem, TGitLabSyncWithCredentials } from "./gitlab"; import { TGitLabSync, TGitLabSyncInput, TGitLabSyncListItem, TGitLabSyncWithCredentials } from "./gitlab";
@ -144,6 +150,7 @@ export type TSecretSync =
| TFlyioSync | TFlyioSync
| TGitLabSync | TGitLabSync
| TCloudflarePagesSync | TCloudflarePagesSync
| TCloudflareWorkersSync
| TZabbixSync | TZabbixSync
| TRailwaySync; | TRailwaySync;
@ -170,6 +177,7 @@ export type TSecretSyncWithCredentials =
| TFlyioSyncWithCredentials | TFlyioSyncWithCredentials
| TGitLabSyncWithCredentials | TGitLabSyncWithCredentials
| TCloudflarePagesSyncWithCredentials | TCloudflarePagesSyncWithCredentials
| TCloudflareWorkersSyncWithCredentials
| TZabbixSyncWithCredentials | TZabbixSyncWithCredentials
| TRailwaySyncWithCredentials; | TRailwaySyncWithCredentials;
@ -196,6 +204,7 @@ export type TSecretSyncInput =
| TFlyioSyncInput | TFlyioSyncInput
| TGitLabSyncInput | TGitLabSyncInput
| TCloudflarePagesSyncInput | TCloudflarePagesSyncInput
| TCloudflareWorkersSyncInput
| TZabbixSyncInput | TZabbixSyncInput
| TRailwaySyncInput; | TRailwaySyncInput;
@ -222,6 +231,7 @@ export type TSecretSyncListItem =
| TFlyioSyncListItem | TFlyioSyncListItem
| TGitLabSyncListItem | TGitLabSyncListItem
| TCloudflarePagesSyncListItem | TCloudflarePagesSyncListItem
| TCloudflareWorkersSyncListItem
| TZabbixSyncListItem | TZabbixSyncListItem
| TRailwaySyncListItem; | TRailwaySyncListItem;

View File

@ -19,13 +19,17 @@ FROM node:20-alpine
WORKDIR /app WORKDIR /app
RUN npm install -g mint@4.2.13 RUN addgroup -g 1001 -S mintuser && \
adduser -S -D -H -u 1001 -s /sbin/nologin -G mintuser mintuser && \
npm install -g mint@4.2.13
COPY . . COPY --chown=mintuser:mintuser . .
COPY --from=builder /root/.mintlify /root/.mintlify COPY --from=builder --chown=mintuser:mintuser /root/.mintlify /home/mintuser/.mintlify
COPY --from=builder /app/docs.json /app/docs.json COPY --from=builder --chown=mintuser:mintuser /app/docs.json /app/docs.json
COPY --from=builder /app/spec.json /app/spec.json COPY --from=builder --chown=mintuser:mintuser /app/spec.json /app/spec.json
USER mintuser
EXPOSE 3000 EXPOSE 3000

View File

@ -0,0 +1,4 @@
---
title: "Create"
openapi: "POST /api/v1/secret-syncs/cloudflare-workers"
---

View File

@ -0,0 +1,4 @@
---
title: "Delete"
openapi: "DELETE /api/v1/secret-syncs/cloudflare-workers/{syncId}"
---

View File

@ -0,0 +1,4 @@
---
title: "Get by ID"
openapi: "GET /api/v1/secret-syncs/cloudflare-workers/{syncId}"
---

View File

@ -0,0 +1,4 @@
---
title: "Get by Name"
openapi: "GET /api/v1/secret-syncs/cloudflare-workers/sync-name/{syncName}"
---

View File

@ -0,0 +1,4 @@
---
title: "List"
openapi: "GET /api/v1/secret-syncs/cloudflare-workers"
---

View File

@ -0,0 +1,4 @@
---
title: "Remove Secrets"
openapi: "POST /api/v1/secret-syncs/cloudflare-workers/{syncId}/remove-secrets"
---

View File

@ -0,0 +1,4 @@
---
title: "Sync Secrets"
openapi: "POST /api/v1/secret-syncs/cloudflare-workers/{syncId}/sync-secrets"
---

View File

@ -0,0 +1,4 @@
---
title: "Update"
openapi: "PATCH /api/v1/secret-syncs/cloudflare-workers/{syncId}"
---

View File

@ -4,6 +4,61 @@ title: "Changelog"
The changelog below reflects new product developments and updates on a monthly basis. The changelog below reflects new product developments and updates on a monthly basis.
## July 2025
- Improved speed performance of audit log filtering.
- Revamped password reset flow pages.
- Added support for [Bitbucket for Secret Scanning](https://infisical.com/docs/documentation/platform/secret-scanning/bitbucket).
- Released Secret Sync for [Zabbix](https://infisical.com/docs/integrations/secret-syncs/zabbix).
## June 2025
- Released Secret Sync for [1Password](https://infisical.com/docs/integrations/secret-syncs/1password), [Heroku](https://infisical.com/docs/integrations/secret-syncs/heroku), [Fly.io](https://infisical.com/docs/integrations/secret-syncs/flyio), and [Render](https://infisical.com/docs/integrations/secret-syncs/render).
- Added support for [Kubernetes dynamic secrets](https://infisical.com/docs/documentation/platform/dynamic-secrets/kubernetes) to generate service account tokens
- Released Secret Rotation for [MySQL](https://infisical.com/docs/documentation/platform/secret-rotation/mysql-credentials) and [OracleDB](https://infisical.com/docs/documentation/platform/secret-rotation/oracledb-credentials) as well as Dynamic Secrets for [Vertica](https://infisical.com/docs/documentation/platform/dynamic-secrets/vertica) and [GitHub App Tokens](https://infisical.com/docs/documentation/platform/dynamic-secrets/github).
- Added support for Azure Auth in ESO.
- [Kubernetes auth](https://infisical.com/docs/documentation/platform/identities/kubernetes-auth) now supports gateway as a token reviewer.
- Revamped [Infisical CLI](https://infisical.com/docs/cli/commands/login) to auto-open login link.
- Rolled out [Infisical Packer integration](https://infisical.com/docs/integrations/frameworks/packer).
- Released [AliCloud Authentication method](https://infisical.com/docs/documentation/platform/identities/alicloud-auth).
- Added support for [multi-step approval workflows](https://infisical.com/docs/documentation/platform/pr-workflows).
- Revamped UI for Access Controls, Access Tree, Policies, and Approval Workflows.
- Released [TLS Certificate Authentication method](https://infisical.com/docs/documentation/platform/identities/tls-cert-auth).
- Added ability to copy session tokens in the Infisical Dashboard.
- Expanded resource support for [Infisical Terraform Provider](https://infisical.com/docs/integrations/frameworks/terraform).
## May 2025
- Added support for [Microsoft Teams integration](https://infisical.com/docs/documentation/platform/workflow-integrations/microsoft-teams-integration).
- Released [Infisical Gateway](https://infisical.com/docs/documentation/platform/gateways/overview) for accessing private network resources from Infisical.
- Added support for [Host Groups](https://infisical.com/docs/documentation/platform/ssh/host-groups) in Infisical SSH.
- Updated the designs of all emails send by Infisical.
- Added secret rotation support for [Azure Client](https://infisical.com/docs/documentation/platform/secret-rotation/azure-client-secret).
- Released secret sync for [HashiCorp Vault](https://infisical.com/docs/integrations/secret-syncs/hashicorp-vault).
- Made significant improvements to [Infisical Secret Scanning](https://infisical.com/docs/documentation/platform/secret-scanning/overview).
- Released [Infisical ACME Client](https://infisical.com/docs/documentation/platform/pki/acme-ca#certificates-with-acme-ca).
- [Access requests](https://infisical.com/docs/documentation/platform/access-controls/access-requests) now support "break-glass" policies.
- Updated [Point-in-time Recovery](https://infisical.com/docs/documentation/platform/pit-recovery) UI/UX.
- Redesigned [Approval Workflows and Change Requests](https://infisical.com/docs/documentation/platform/pr-workflows) user interface.
## April 2025
- Released ability to [request access to projects](https://infisical.com/docs/documentation/platform/access-controls/project-access-requests#project-access-requests).
- Updated UI for Audit Logs and Log Filtering.
- Launched [Infisical SSH V2](https://infisical.com/docs/documentation/platform/ssh/overview).
- Developer [Infisical MCP](https://github.com/Infisical/infisical-mcp-server).
- Added support for [Spotify Backstage Infisical plugin](https://infisical.com/docs/integrations/external/backstage).
- Added secret syncs for Terraform Cloud, Vercel, Windmill, TeamCity, and Camunda.
- Released [Auth0 Client Secret Rotation](https://infisical.com/docs/documentation/platform/secret-rotation/auth0-client-secret).
- Launched [Infisical C++ SDK](https://github.com/Infisical/infisical-cpp-sdk).
- Service tokens will now get expiry notifications.
- Added Infisical [Linux binary](https://infisical.com/docs/self-hosting/reference-architectures/linux-deployment-ha#linux-ha).
- Released ability to perform user impersonation.
- Added support for [LDAP password rotation](https://infisical.com/docs/documentation/platform/secret-rotation/ldap-password).
## March 2025 ## March 2025
- Released [Infisical Gateway](https://infisical.com/docs/documentation/platform/gateways/overview) for secure access to private resources without needing direct inbound connections to private networks. - Released [Infisical Gateway](https://infisical.com/docs/documentation/platform/gateways/overview) for secure access to private resources without needing direct inbound connections to private networks.

View File

@ -514,6 +514,7 @@
"integrations/secret-syncs/azure-key-vault", "integrations/secret-syncs/azure-key-vault",
"integrations/secret-syncs/camunda", "integrations/secret-syncs/camunda",
"integrations/secret-syncs/cloudflare-pages", "integrations/secret-syncs/cloudflare-pages",
"integrations/secret-syncs/cloudflare-workers",
"integrations/secret-syncs/databricks", "integrations/secret-syncs/databricks",
"integrations/secret-syncs/flyio", "integrations/secret-syncs/flyio",
"integrations/secret-syncs/gcp-secret-manager", "integrations/secret-syncs/gcp-secret-manager",
@ -1720,6 +1721,19 @@
"api-reference/endpoints/secret-syncs/cloudflare-pages/remove-secrets" "api-reference/endpoints/secret-syncs/cloudflare-pages/remove-secrets"
] ]
}, },
{
"group": "Cloudflare Workers",
"pages": [
"api-reference/endpoints/secret-syncs/cloudflare-workers/list",
"api-reference/endpoints/secret-syncs/cloudflare-workers/get-by-id",
"api-reference/endpoints/secret-syncs/cloudflare-workers/get-by-name",
"api-reference/endpoints/secret-syncs/cloudflare-workers/create",
"api-reference/endpoints/secret-syncs/cloudflare-workers/update",
"api-reference/endpoints/secret-syncs/cloudflare-workers/delete",
"api-reference/endpoints/secret-syncs/cloudflare-workers/sync-secrets",
"api-reference/endpoints/secret-syncs/cloudflare-workers/remove-secrets"
]
},
{ {
"group": "Databricks", "group": "Databricks",
"pages": [ "pages": [
@ -2175,6 +2189,7 @@
"sdks/languages/python", "sdks/languages/python",
"sdks/languages/java", "sdks/languages/java",
"sdks/languages/csharp", "sdks/languages/csharp",
"sdks/languages/cpp",
"sdks/languages/go", "sdks/languages/go",
"sdks/languages/ruby" "sdks/languages/ruby"
] ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 KiB

View File

@ -35,6 +35,17 @@ Infisical supports connecting to Cloudflare using API tokens and Account ID for
- **Account** - **Cloudflare Pages** - **Edit** - **Account** - **Cloudflare Pages** - **Edit**
- **Account** - **Account Settings** - **Read** - **Account** - **Account Settings** - **Read**
Add these permissions to your API token and click **Continue to summary**, then **Create Token** to generate your API token.
</Accordion>
<Accordion title="Cloudflare Workers">
Use the following permissions to grant Infisical access to sync secrets to Cloudflare Workers:
![Configure Token](/images/app-connections/cloudflare/cloudflare-workers-configure-permissions.png)
**Required Permissions:**
- **Account** - **Workers Scripts** - **Edit**
- **Account** - **Account Settings** - **Read**
Add these permissions to your API token and click **Continue to summary**, then **Create Token** to generate your API token. Add these permissions to your API token and click **Continue to summary**, then **Create Token** to generate your API token.
</Accordion> </Accordion>
</AccordionGroup> </AccordionGroup>
@ -44,7 +55,7 @@ Infisical supports connecting to Cloudflare using API tokens and Account ID for
</Step> </Step>
<Step title="Save Your API Token"> <Step title="Save Your API Token">
After creation, copy and securely store your API token as it will not be shown again. After creation, copy and securely store your API token as it will not be shown again.
![Generated API Token](/images/app-connections/cloudflare/cloudflare-generated-token.png) ![Generated API Token](/images/app-connections/cloudflare/cloudflare-generated-token.png)
<Warning> <Warning>

View File

@ -0,0 +1,128 @@
---
title: "Cloudflare Workers Sync"
description: "Learn how to configure a Cloudflare Workers Sync for Infisical."
---
**Prerequisites:**
- Set up and add secrets to [Infisical Cloud](https://app.infisical.com)
- Create a [Cloudflare Connection](/integrations/app-connections/cloudflare)
<Tabs>
<Tab title="Infisical UI">
1. Navigate to **Project** > **Integrations** and select the **Secret Syncs** tab. Click on the **Add Sync** button.
![Secret Syncs Tab](/images/secret-syncs/general/secret-sync-tab.png)
2. Select the **Cloudflare Workers** option.
![Select Cloudflare Workers](/images/secret-syncs/cloudflare-workers/select-cloudflare-workers-option.png)
3. Configure the **Source** from where secrets should be retrieved, then click **Next**.
![Configure Source](/images/secret-syncs/cloudflare-workers/cloudflare-workers-sync-source.png)
- **Environment**: The project environment to retrieve secrets from.
- **Secret Path**: The folder path to retrieve secrets from.
<Tip>
If you need to sync secrets from multiple folder locations, check out [secret imports](/documentation/platform/secret-reference#secret-imports).
</Tip>
4. Configure the **Destination** to where secrets should be deployed, then click **Next**.
![Configure Destination](/images/secret-syncs/cloudflare-workers/cloudflare-workers-sync-destination.png)
- **Cloudflare Connection**: The Cloudflare Connection to authenticate with.
- **Cloudflare Workers Script**: Choose the Cloudflare Workers script you want to sync secrets to.
5. Configure the **Sync Options** to specify how secrets should be synced, then click **Next**.
![Configure Options](/images/secret-syncs/cloudflare-workers/cloudflare-workers-sync-options.png)
- **Initial Sync Behavior**: Determines how Infisical should resolve the initial sync.
- **Overwrite Destination Secrets**: Removes any secrets at the destination endpoint not present in Infisical.
- **Key Schema**: Template that determines how secret names are transformed when syncing, using `{{secretKey}}` as a placeholder for the original secret name and `{{environment}}` for the environment.
- **Auto-Sync Enabled**: If enabled, secrets will automatically be synced from the source location when changes occur. Disable to enforce manual syncing only.
- **Disable Secret Deletion**: If enabled, Infisical will not remove secrets from the sync destination. Enable this option if you intend to manage some secrets manually outside of Infisical.
6. Configure the **Details** of your Cloudflare Workers Sync, then click **Next**.
![Configure Details](/images/secret-syncs/cloudflare-workers/cloudflare-workers-sync-details.png)
- **Name**: The name of your sync. Must be slug-friendly.
- **Description**: An optional description for your sync.
7. Review your Cloudflare Workers Sync configuration, then click **Create Sync**.
![Confirm Configuration](/images/secret-syncs/cloudflare-workers/cloudflare-workers-sync-review.png)
8. If enabled, your Cloudflare Workers Sync will begin syncing your secrets to the destination endpoint.
![Sync Secrets](/images/secret-syncs/cloudflare-workers/cloudflare-workers-sync-created.png)
</Tab>
<Tab title="API">
To create a **Cloudflare Workers Sync**, make an API request to the [Create Cloudflare Workers Sync](/api-reference/endpoints/secret-syncs/cloudflare-workers/create) API endpoint.
### Sample request
```bash Request
curl --request POST \
--url https://app.infisical.com/api/v1/secret-syncs/cloudflare-workers \
--header 'Content-Type: application/json' \
--data '{
"name": "my-cloudflare-workers-sync",
"projectId": "your-project-id",
"description": "an example sync",
"connectionId": "your-cloudflare-connection-id",
"environment": "production",
"secretPath": "/my-secrets",
"isEnabled": true,
"syncOptions": {
"initialSyncBehavior": "overwrite-destination"
},
"destinationConfig": {
"scriptId": "my-workers-script"
}
}'
```
### Sample response
```bash Response
{
"secretSync": {
"id": "your-sync-id",
"name": "my-cloudflare-workers-sync",
"description": "an example sync",
"isEnabled": true,
"version": 1,
"folderId": "your-folder-id",
"connectionId": "your-cloudflare-connection-id",
"createdAt": "2024-05-01T12:00:00Z",
"updatedAt": "2024-05-01T12:00:00Z",
"syncStatus": "succeeded",
"lastSyncJobId": "123",
"lastSyncMessage": null,
"lastSyncedAt": "2024-05-01T12:00:00Z",
"syncOptions": {
"initialSyncBehavior": "overwrite-destination"
},
"projectId": "your-project-id",
"connection": {
"app": "cloudflare",
"name": "my-cloudflare-connection",
"id": "your-cloudflare-connection-id"
},
"environment": {
"slug": "production",
"name": "Production",
"id": "your-env-id"
},
"folder": {
"id": "your-folder-id",
"path": "/my-secrets"
},
"destination": "cloudflare-workers",
"destinationConfig": {
"scriptId": "my-workers-script"
}
}
}
```
</Tab>
</Tabs>

View File

@ -0,0 +1,6 @@
---
title: "Infisical C++ SDK"
sidebarTitle: "C++"
url: "https://github.com/Infisical/infisical-cpp-sdk/?tab=readme-ov-file#infisical-c-sdk"
icon: "c"
---

View File

@ -25,6 +25,9 @@ From local development to production, Infisical SDKs provide the easiest way for
<Card href="https://github.com/Infisical/infisical-dotnet-sdk?tab=readme-ov-file#infisical-net-sdk" title=".NET" icon="bars" color="#368833"> <Card href="https://github.com/Infisical/infisical-dotnet-sdk?tab=readme-ov-file#infisical-net-sdk" title=".NET" icon="bars" color="#368833">
Manage secrets for your .NET application on demand Manage secrets for your .NET application on demand
</Card> </Card>
<Card href="https://github.com/Infisical/infisical-cpp-sdk/?tab=readme-ov-file#infisical-c-sdk" title="C++" icon="c" color="#b00dd1">
Manage secrets for your C++ application on demand
</Card>
<Card href="/sdks/languages/ruby" title="Ruby" icon="diamond" color="#367B99"> <Card href="/sdks/languages/ruby" title="Ruby" icon="diamond" color="#367B99">
Manage secrets for your Ruby application on demand Manage secrets for your Ruby application on demand
</Card> </Card>

View File

@ -4,7 +4,7 @@ import { SingleValue } from "react-select";
import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField"; import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField";
import { FilterableSelect, FormControl, Select, SelectItem } from "@app/components/v2"; import { FilterableSelect, FormControl, Select, SelectItem } from "@app/components/v2";
import { import {
TCloudflareProject, TCloudflarePagesProject,
useCloudflareConnectionListPagesProjects useCloudflareConnectionListPagesProjects
} from "@app/hooks/api/appConnections/cloudflare"; } from "@app/hooks/api/appConnections/cloudflare";
import { SecretSync } from "@app/hooks/api/secretSyncs"; import { SecretSync } from "@app/hooks/api/secretSyncs";
@ -52,7 +52,7 @@ export const CloudflarePagesSyncFields = () => {
isDisabled={!connectionId} isDisabled={!connectionId}
value={projects ? (projects.find((project) => project.name === value) ?? []) : []} value={projects ? (projects.find((project) => project.name === value) ?? []) : []}
onChange={(option) => { onChange={(option) => {
onChange((option as SingleValue<TCloudflareProject>)?.name ?? null); onChange((option as SingleValue<TCloudflarePagesProject>)?.name ?? null);
}} }}
options={projects} options={projects}
placeholder="Select a project..." placeholder="Select a project..."

View File

@ -0,0 +1,59 @@
import { Controller, useFormContext, useWatch } from "react-hook-form";
import { SingleValue } from "react-select";
import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField";
import { FilterableSelect, FormControl } from "@app/components/v2";
import {
TCloudflareWorkersScript,
useCloudflareConnectionListWorkersScripts
} from "@app/hooks/api/appConnections/cloudflare";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TSecretSyncForm } from "../schemas";
export const CloudflareWorkersSyncFields = () => {
const { control, setValue } = useFormContext<
TSecretSyncForm & { destination: SecretSync.CloudflareWorkers }
>();
const connectionId = useWatch({ name: "connection.id", control });
const { data: scripts = [], isPending: isScriptsPending } =
useCloudflareConnectionListWorkersScripts(connectionId, {
enabled: Boolean(connectionId)
});
return (
<>
<SecretSyncConnectionField
onChange={() => {
setValue("destinationConfig.scriptId", "");
}}
/>
<Controller
name="destinationConfig.scriptId"
control={control}
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
errorText={error?.message}
isError={Boolean(error?.message)}
label="Worker Script"
>
<FilterableSelect
isLoading={isScriptsPending && Boolean(connectionId)}
isDisabled={!connectionId}
value={scripts?.find((script) => script.id === value) || []}
onChange={(option) => {
onChange((option as SingleValue<TCloudflareWorkersScript>)?.id ?? null);
}}
options={scripts}
placeholder="Select a worker script..."
getOptionLabel={(option) => option.id}
getOptionValue={(option) => option.id}
/>
</FormControl>
)}
/>
</>
);
};

View File

@ -11,6 +11,7 @@ import { AzureDevOpsSyncFields } from "./AzureDevOpsSyncFields";
import { AzureKeyVaultSyncFields } from "./AzureKeyVaultSyncFields"; import { AzureKeyVaultSyncFields } from "./AzureKeyVaultSyncFields";
import { CamundaSyncFields } from "./CamundaSyncFields"; import { CamundaSyncFields } from "./CamundaSyncFields";
import { CloudflarePagesSyncFields } from "./CloudflarePagesSyncFields"; import { CloudflarePagesSyncFields } from "./CloudflarePagesSyncFields";
import { CloudflareWorkersSyncFields } from "./CloudflareWorkersSyncFields";
import { DatabricksSyncFields } from "./DatabricksSyncFields"; import { DatabricksSyncFields } from "./DatabricksSyncFields";
import { FlyioSyncFields } from "./FlyioSyncFields"; import { FlyioSyncFields } from "./FlyioSyncFields";
import { GcpSyncFields } from "./GcpSyncFields"; import { GcpSyncFields } from "./GcpSyncFields";
@ -78,6 +79,8 @@ export const SecretSyncDestinationFields = () => {
return <GitLabSyncFields />; return <GitLabSyncFields />;
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
return <CloudflarePagesSyncFields />; return <CloudflarePagesSyncFields />;
case SecretSync.CloudflareWorkers:
return <CloudflareWorkersSyncFields />;
case SecretSync.Zabbix: case SecretSync.Zabbix:
return <ZabbixSyncFields />; return <ZabbixSyncFields />;
case SecretSync.Railway: case SecretSync.Railway:

View File

@ -58,6 +58,7 @@ export const SecretSyncOptionsFields = ({ hideInitialSync }: Props) => {
case SecretSync.Flyio: case SecretSync.Flyio:
case SecretSync.GitLab: case SecretSync.GitLab:
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
case SecretSync.CloudflareWorkers:
case SecretSync.Zabbix: case SecretSync.Zabbix:
case SecretSync.Railway: case SecretSync.Railway:
AdditionalSyncOptionsFieldsComponent = null; AdditionalSyncOptionsFieldsComponent = null;

View File

@ -0,0 +1,14 @@
import { useFormContext } from "react-hook-form";
import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
import { GenericFieldLabel } from "@app/components/v2";
import { SecretSync } from "@app/hooks/api/secretSyncs";
export const CloudflareWorkersSyncReviewFields = () => {
const { watch } = useFormContext<
TSecretSyncForm & { destination: SecretSync.CloudflareWorkers }
>();
const scriptId = watch("destinationConfig.scriptId");
return <GenericFieldLabel label="Script">{scriptId}</GenericFieldLabel>;
};

View File

@ -20,6 +20,7 @@ import { AzureDevOpsSyncReviewFields } from "./AzureDevOpsSyncReviewFields";
import { AzureKeyVaultSyncReviewFields } from "./AzureKeyVaultSyncReviewFields"; import { AzureKeyVaultSyncReviewFields } from "./AzureKeyVaultSyncReviewFields";
import { CamundaSyncReviewFields } from "./CamundaSyncReviewFields"; import { CamundaSyncReviewFields } from "./CamundaSyncReviewFields";
import { CloudflarePagesSyncReviewFields } from "./CloudflarePagesReviewFields"; import { CloudflarePagesSyncReviewFields } from "./CloudflarePagesReviewFields";
import { CloudflareWorkersSyncReviewFields } from "./CloudflareWorkersReviewFields";
import { DatabricksSyncReviewFields } from "./DatabricksSyncReviewFields"; import { DatabricksSyncReviewFields } from "./DatabricksSyncReviewFields";
import { FlyioSyncReviewFields } from "./FlyioSyncReviewFields"; import { FlyioSyncReviewFields } from "./FlyioSyncReviewFields";
import { GcpSyncReviewFields } from "./GcpSyncReviewFields"; import { GcpSyncReviewFields } from "./GcpSyncReviewFields";
@ -126,6 +127,9 @@ export const SecretSyncReviewFields = () => {
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
DestinationFieldsComponent = <CloudflarePagesSyncReviewFields />; DestinationFieldsComponent = <CloudflarePagesSyncReviewFields />;
break; break;
case SecretSync.CloudflareWorkers:
DestinationFieldsComponent = <CloudflareWorkersSyncReviewFields />;
break;
case SecretSync.Zabbix: case SecretSync.Zabbix:
DestinationFieldsComponent = <ZabbixSyncReviewFields />; DestinationFieldsComponent = <ZabbixSyncReviewFields />;
break; break;

View File

@ -0,0 +1,18 @@
import { z } from "zod";
import { BaseSecretSyncSchema } from "@app/components/secret-syncs/forms/schemas/base-secret-sync-schema";
import { SecretSync } from "@app/hooks/api/secretSyncs";
export const CloudflareWorkersSyncDestinationSchema = BaseSecretSyncSchema().merge(
z.object({
destination: z.literal(SecretSync.CloudflareWorkers),
destinationConfig: z.object({
scriptId: z
.string()
.trim()
.min(1, "Script ID is required")
.max(64)
.regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, "Invalid script ID format")
})
})
);

View File

@ -8,6 +8,7 @@ import { AzureDevOpsSyncDestinationSchema } from "./azure-devops-sync-destinatio
import { AzureKeyVaultSyncDestinationSchema } from "./azure-key-vault-sync-destination-schema"; import { AzureKeyVaultSyncDestinationSchema } from "./azure-key-vault-sync-destination-schema";
import { CamundaSyncDestinationSchema } from "./camunda-sync-destination-schema"; import { CamundaSyncDestinationSchema } from "./camunda-sync-destination-schema";
import { CloudflarePagesSyncDestinationSchema } from "./cloudflare-pages-sync-destination-schema"; import { CloudflarePagesSyncDestinationSchema } from "./cloudflare-pages-sync-destination-schema";
import { CloudflareWorkersSyncDestinationSchema } from "./cloudflare-workers-sync-destination-schema";
import { DatabricksSyncDestinationSchema } from "./databricks-sync-destination-schema"; import { DatabricksSyncDestinationSchema } from "./databricks-sync-destination-schema";
import { FlyioSyncDestinationSchema } from "./flyio-sync-destination-schema"; import { FlyioSyncDestinationSchema } from "./flyio-sync-destination-schema";
import { GcpSyncDestinationSchema } from "./gcp-sync-destination-schema"; import { GcpSyncDestinationSchema } from "./gcp-sync-destination-schema";
@ -48,6 +49,8 @@ const SecretSyncUnionSchema = z.discriminatedUnion("destination", [
FlyioSyncDestinationSchema, FlyioSyncDestinationSchema,
GitlabSyncDestinationSchema, GitlabSyncDestinationSchema,
CloudflarePagesSyncDestinationSchema, CloudflarePagesSyncDestinationSchema,
CloudflareWorkersSyncDestinationSchema,
ZabbixSyncDestinationSchema, ZabbixSyncDestinationSchema,
RailwaySyncDestinationSchema RailwaySyncDestinationSchema
]); ]);

View File

@ -29,10 +29,6 @@ export const ROUTE_PATHS = Object.freeze({
"/_authenticate/_inject-org-details/_org-layout/organization/settings/oauth/callback" "/_authenticate/_inject-org-details/_org-layout/organization/settings/oauth/callback"
) )
}, },
SsoPage: setRoute(
"/organization/sso",
"/_authenticate/_inject-org-details/_org-layout/organization/sso"
),
SecretSharing: setRoute( SecretSharing: setRoute(
"/organization/secret-sharing", "/organization/secret-sharing",
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/" "/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/"

View File

@ -82,6 +82,10 @@ export const SECRET_SYNC_MAP: Record<SecretSync, { name: string; image: string }
name: "Cloudflare Pages", name: "Cloudflare Pages",
image: "Cloudflare.png" image: "Cloudflare.png"
}, },
[SecretSync.CloudflareWorkers]: {
name: "Cloudflare Workers",
image: "Cloudflare.png"
},
[SecretSync.Zabbix]: { [SecretSync.Zabbix]: {
name: "Zabbix", name: "Zabbix",
image: "Zabbix.png" image: "Zabbix.png"
@ -115,6 +119,8 @@ export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
[SecretSync.Flyio]: AppConnection.Flyio, [SecretSync.Flyio]: AppConnection.Flyio,
[SecretSync.GitLab]: AppConnection.Gitlab, [SecretSync.GitLab]: AppConnection.Gitlab,
[SecretSync.CloudflarePages]: AppConnection.Cloudflare, [SecretSync.CloudflarePages]: AppConnection.Cloudflare,
[SecretSync.CloudflareWorkers]: AppConnection.Cloudflare,
[SecretSync.Zabbix]: AppConnection.Zabbix, [SecretSync.Zabbix]: AppConnection.Zabbix,
[SecretSync.Railway]: AppConnection.Railway [SecretSync.Railway]: AppConnection.Railway
}; };

View File

@ -3,21 +3,23 @@ import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "../queries"; import { appConnectionKeys } from "../queries";
import { TCloudflareProject } from "./types"; import { TCloudflarePagesProject, TCloudflareWorkersScript } from "./types";
const cloudflareConnectionKeys = { const cloudflareConnectionKeys = {
all: [...appConnectionKeys.all, "cloudflare"] as const, all: [...appConnectionKeys.all, "cloudflare"] as const,
listPagesProjects: (connectionId: string) => listPagesProjects: (connectionId: string) =>
[...cloudflareConnectionKeys.all, "pages-projects", connectionId] as const [...cloudflareConnectionKeys.all, "pages-projects", connectionId] as const,
listWorkersScripts: (connectionId: string) =>
[...cloudflareConnectionKeys.all, "workers-scripts", connectionId] as const
}; };
export const useCloudflareConnectionListPagesProjects = ( export const useCloudflareConnectionListPagesProjects = (
connectionId: string, connectionId: string,
options?: Omit< options?: Omit<
UseQueryOptions< UseQueryOptions<
TCloudflareProject[], TCloudflarePagesProject[],
unknown, unknown,
TCloudflareProject[], TCloudflarePagesProject[],
ReturnType<typeof cloudflareConnectionKeys.listPagesProjects> ReturnType<typeof cloudflareConnectionKeys.listPagesProjects>
>, >,
"queryKey" | "queryFn" "queryKey" | "queryFn"
@ -26,7 +28,7 @@ export const useCloudflareConnectionListPagesProjects = (
return useQuery({ return useQuery({
queryKey: cloudflareConnectionKeys.listPagesProjects(connectionId), queryKey: cloudflareConnectionKeys.listPagesProjects(connectionId),
queryFn: async () => { queryFn: async () => {
const { data } = await apiRequest.get<TCloudflareProject[]>( const { data } = await apiRequest.get<TCloudflarePagesProject[]>(
`/api/v1/app-connections/cloudflare/${connectionId}/cloudflare-pages-projects` `/api/v1/app-connections/cloudflare/${connectionId}/cloudflare-pages-projects`
); );
@ -35,3 +37,28 @@ export const useCloudflareConnectionListPagesProjects = (
...options ...options
}); });
}; };
export const useCloudflareConnectionListWorkersScripts = (
connectionId: string,
options?: Omit<
UseQueryOptions<
TCloudflareWorkersScript[],
unknown,
TCloudflareWorkersScript[],
ReturnType<typeof cloudflareConnectionKeys.listWorkersScripts>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: cloudflareConnectionKeys.listWorkersScripts(connectionId),
queryFn: async () => {
const { data } = await apiRequest.get<TCloudflareWorkersScript[]>(
`/api/v1/app-connections/cloudflare/${connectionId}/cloudflare-workers-scripts`
);
return data;
},
...options
});
};

View File

@ -1,4 +1,8 @@
export type TCloudflareProject = { export type TCloudflarePagesProject = {
id: string; id: string;
name: string; name: string;
}; };
export type TCloudflareWorkersScript = {
id: string;
};

View File

@ -21,6 +21,8 @@ export enum SecretSync {
Flyio = "flyio", Flyio = "flyio",
GitLab = "gitlab", GitLab = "gitlab",
CloudflarePages = "cloudflare-pages", CloudflarePages = "cloudflare-pages",
CloudflareWorkers = "cloudflare-workers",
Zabbix = "zabbix", Zabbix = "zabbix",
Railway = "railway" Railway = "railway"
} }

View File

@ -0,0 +1,15 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
export type TCloudflareWorkersSync = TRootSecretSync & {
destination: SecretSync.CloudflareWorkers;
destinationConfig: {
scriptId: string;
};
connection: {
app: AppConnection.Cloudflare;
name: string;
id: string;
};
};

View File

@ -10,6 +10,7 @@ import { TAzureDevOpsSync } from "./azure-devops-sync";
import { TAzureKeyVaultSync } from "./azure-key-vault-sync"; import { TAzureKeyVaultSync } from "./azure-key-vault-sync";
import { TCamundaSync } from "./camunda-sync"; import { TCamundaSync } from "./camunda-sync";
import { TCloudflarePagesSync } from "./cloudflare-pages-sync"; import { TCloudflarePagesSync } from "./cloudflare-pages-sync";
import { TCloudflareWorkersSync } from "./cloudflare-workers-sync";
import { TDatabricksSync } from "./databricks-sync"; import { TDatabricksSync } from "./databricks-sync";
import { TFlyioSync } from "./flyio-sync"; import { TFlyioSync } from "./flyio-sync";
import { TGcpSync } from "./gcp-sync"; import { TGcpSync } from "./gcp-sync";
@ -56,6 +57,7 @@ export type TSecretSync =
| TFlyioSync | TFlyioSync
| TGitLabSync | TGitLabSync
| TCloudflarePagesSync | TCloudflarePagesSync
| TCloudflareWorkersSync
| TZabbixSync | TZabbixSync
| TRailwaySync; | TRailwaySync;

View File

@ -1,6 +1,5 @@
import { import {
faBook, faBook,
faCheckCircle,
faCog, faCog,
faCubes, faCubes,
faDoorClosed, faDoorClosed,
@ -100,18 +99,6 @@ export const OrgSidebar = ({ isHidden }: Props) => {
</MenuItem> </MenuItem>
)} )}
</Link> </Link>
<Link to="/organization/sso">
{({ isActive }) => (
<MenuItem isSelected={isActive}>
<div className="mx-1 flex gap-2">
<div className="w-6">
<FontAwesomeIcon icon={faCheckCircle} className="mr-4" />
</div>
SSO Settings
</div>
</MenuItem>
)}
</Link>
<Link to="/organization/settings"> <Link to="/organization/settings">
{({ isActive }) => ( {({ isActive }) => (
<MenuItem isSelected={isActive}> <MenuItem isSelected={isActive}>

View File

@ -1,222 +0,0 @@
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { FaGithub } from "react-icons/fa";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
Button,
FormControl,
Input,
TextArea
} from "@app/components/v2";
import { useToggle } from "@app/hooks";
import { useUpdateServerConfig } from "@app/hooks/api";
import { AdminIntegrationsConfig } from "@app/hooks/api/admin/types";
const gitHubAppFormSchema = z.object({
clientId: z.string(),
clientSecret: z.string(),
appSlug: z.string(),
appId: z.string(),
privateKey: z.string()
});
type TGitHubAppConnectionForm = z.infer<typeof gitHubAppFormSchema>;
type Props = {
adminIntegrationsConfig?: AdminIntegrationsConfig;
};
export const GitHubAppConnectionForm = ({ adminIntegrationsConfig }: Props) => {
const { mutateAsync: updateAdminServerConfig } = useUpdateServerConfig();
const [isGitHubAppClientSecretFocused, setIsGitHubAppClientSecretFocused] = useToggle();
const {
control,
handleSubmit,
setValue,
formState: { isSubmitting, isDirty }
} = useForm<TGitHubAppConnectionForm>({
resolver: zodResolver(gitHubAppFormSchema)
});
const onSubmit = async (data: TGitHubAppConnectionForm) => {
await updateAdminServerConfig({
gitHubAppConnectionClientId: data.clientId,
gitHubAppConnectionClientSecret: data.clientSecret,
gitHubAppConnectionSlug: data.appSlug,
gitHubAppConnectionId: data.appId,
gitHubAppConnectionPrivateKey: data.privateKey
});
createNotification({
text: "Updated GitHub app connection configuration. It can take up to 5 minutes to take effect.",
type: "success"
});
};
useEffect(() => {
if (adminIntegrationsConfig) {
setValue("clientId", adminIntegrationsConfig.gitHubAppConnection.clientId);
setValue("clientSecret", adminIntegrationsConfig.gitHubAppConnection.clientSecret);
setValue("appSlug", adminIntegrationsConfig.gitHubAppConnection.appSlug);
setValue("appId", adminIntegrationsConfig.gitHubAppConnection.appId);
setValue("privateKey", adminIntegrationsConfig.gitHubAppConnection.privateKey);
}
}, [adminIntegrationsConfig]);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="github-app-integration" className="data-[state=open]:border-none">
<AccordionTrigger className="flex h-fit w-full justify-start rounded-md border border-mineshaft-500 bg-mineshaft-700 px-4 py-6 text-sm transition-colors data-[state=open]:rounded-b-none">
<div className="text-md group order-1 ml-3 flex items-center gap-2">
<FaGithub className="text-lg group-hover:text-primary-400" />
<div className="text-[15px] font-semibold">GitHub App</div>
</div>
</AccordionTrigger>
<AccordionContent childrenClassName="px-0 py-0">
<div className="flex w-full flex-col justify-start rounded-md rounded-t-none border border-t-0 border-mineshaft-500 bg-mineshaft-700 px-4 py-4">
<div className="mb-2 max-w-lg text-sm text-mineshaft-300">
Step 1: Create and configure GitHub App. Please refer to the documentation below for
more information.
</div>
<div className="mb-6">
<a
href="https://infisical.com/docs/integrations/app-connections/github#self-hosted-instance"
target="_blank"
rel="noopener noreferrer"
>
<Button colorSchema="secondary">Documentation</Button>
</a>
</div>
<div className="mb-4 max-w-lg text-sm text-mineshaft-300">
Step 2: Configure your instance-wide settings to enable GitHub App connections. Copy
the credentials from your GitHub App&apos;s settings page.
</div>
<Controller
control={control}
name="clientId"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Client ID"
className="w-96"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
value={field.value || ""}
type="text"
onChange={(e) => field.onChange(e.target.value)}
/>
</FormControl>
)}
/>
<Controller
control={control}
name="clientSecret"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Client Secret"
tooltipText="You can find your Client Secret in the GitHub App's settings under 'Client secrets'."
className="w-96"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
value={field.value || ""}
type={isGitHubAppClientSecretFocused ? "text" : "password"}
onFocus={() => setIsGitHubAppClientSecretFocused.on()}
onBlur={() => setIsGitHubAppClientSecretFocused.off()}
onChange={(e) => field.onChange(e.target.value)}
/>
</FormControl>
)}
/>
<Controller
control={control}
name="appSlug"
render={({ field, fieldState: { error } }) => (
<FormControl
label="App Slug"
tooltipText="The GitHub App slug from the app's URL (e.g., 'my-app' from github.com/apps/my-app)."
className="w-96"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
value={field.value || ""}
type="text"
onChange={(e) => field.onChange(e.target.value)}
/>
</FormControl>
)}
/>
<Controller
control={control}
name="appId"
render={({ field, fieldState: { error } }) => (
<FormControl
label="App ID"
tooltipText="The numeric App ID found in your GitHub App's settings."
className="w-96"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
value={field.value || ""}
type="text"
onChange={(e) => field.onChange(e.target.value)}
/>
</FormControl>
)}
/>
<Controller
control={control}
name="privateKey"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Private Key"
tooltipText="The private key generated for your GitHub App (PEM format)."
className="w-96"
isError={Boolean(error)}
errorText={error?.message}
>
<TextArea
{...field}
value={field.value || ""}
className="min-h-32"
onChange={(e) => field.onChange(e.target.value)}
/>
</FormControl>
)}
/>
<div>
<Button
className="mt-2"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
>
Save
</Button>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</form>
);
};

View File

@ -5,23 +5,17 @@ import { ROUTE_PATHS } from "@app/const/routes";
import { useGetAdminIntegrationsConfig } from "@app/hooks/api"; import { useGetAdminIntegrationsConfig } from "@app/hooks/api";
import { AdminIntegrationsConfig } from "@app/hooks/api/admin/types"; import { AdminIntegrationsConfig } from "@app/hooks/api/admin/types";
import { GitHubAppConnectionForm } from "./GitHubAppConnectionForm";
import { MicrosoftTeamsIntegrationForm } from "./MicrosoftTeamsIntegrationForm"; import { MicrosoftTeamsIntegrationForm } from "./MicrosoftTeamsIntegrationForm";
import { SlackIntegrationForm } from "./SlackIntegrationForm"; import { SlackIntegrationForm } from "./SlackIntegrationForm";
enum IntegrationTabSections { enum IntegrationTabSections {
Workflow = "workflow", Workflow = "workflow"
AppConnections = "app-connections"
} }
interface WorkflowTabProps { interface WorkflowTabProps {
adminIntegrationsConfig: AdminIntegrationsConfig; adminIntegrationsConfig: AdminIntegrationsConfig;
} }
interface AppConnectionsTabProps {
adminIntegrationsConfig: AdminIntegrationsConfig;
}
const WorkflowTab = ({ adminIntegrationsConfig }: WorkflowTabProps) => ( const WorkflowTab = ({ adminIntegrationsConfig }: WorkflowTabProps) => (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<SlackIntegrationForm adminIntegrationsConfig={adminIntegrationsConfig} /> <SlackIntegrationForm adminIntegrationsConfig={adminIntegrationsConfig} />
@ -29,12 +23,6 @@ const WorkflowTab = ({ adminIntegrationsConfig }: WorkflowTabProps) => (
</div> </div>
); );
const AppConnectionsTab = ({ adminIntegrationsConfig }: AppConnectionsTabProps) => (
<div className="flex flex-col gap-2">
<GitHubAppConnectionForm adminIntegrationsConfig={adminIntegrationsConfig} />
</div>
);
export const IntegrationsPageForm = () => { export const IntegrationsPageForm = () => {
const { data: adminIntegrationsConfig } = useGetAdminIntegrationsConfig(); const { data: adminIntegrationsConfig } = useGetAdminIntegrationsConfig();
@ -59,11 +47,6 @@ export const IntegrationsPageForm = () => {
key: IntegrationTabSections.Workflow, key: IntegrationTabSections.Workflow,
label: "Workflows", label: "Workflows",
component: WorkflowTab component: WorkflowTab
},
{
key: IntegrationTabSections.AppConnections,
label: "App Connections",
component: AppConnectionsTab
} }
]; ];

View File

@ -1,6 +1,3 @@
import { Link } from "@tanstack/react-router";
import { NoticeBannerV2 } from "@app/components/v2/NoticeBannerV2/NoticeBannerV2";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
import { withPermission } from "@app/hoc"; import { withPermission } from "@app/hoc";
@ -11,21 +8,6 @@ export const OrgSecurityTab = withPermission(
() => { () => {
return ( return (
<> <>
<NoticeBannerV2
className="mx-auto mb-4"
titleClassName="text-base"
title="Single Sign-On (SSO) Settings"
>
<p className="mt-1 text-mineshaft-300">
SSO Settings have been relocated:{" "}
<Link
className="text-mineshaft-200 underline underline-offset-2"
to="/organization/sso"
>
Click here to view SSO Settings
</Link>
</p>
</NoticeBannerV2>
<OrgGenericAuthSection /> <OrgGenericAuthSection />
<OrgUserAccessTokenLimitSection /> <OrgUserAccessTokenLimitSection />
</> </>

View File

@ -9,8 +9,10 @@ import { ImportTab } from "../ImportTab";
import { KmipTab } from "../KmipTab/OrgKmipTab"; import { KmipTab } from "../KmipTab/OrgKmipTab";
import { OrgEncryptionTab } from "../OrgEncryptionTab"; import { OrgEncryptionTab } from "../OrgEncryptionTab";
import { OrgGeneralTab } from "../OrgGeneralTab"; import { OrgGeneralTab } from "../OrgGeneralTab";
import { OrgProvisioningTab } from "../OrgProvisioningTab";
import { OrgSecurityTab } from "../OrgSecurityTab"; import { OrgSecurityTab } from "../OrgSecurityTab";
import { OrgWorkflowIntegrationTab } from "../OrgWorkflowIntegrationTab/OrgWorkflowIntegrationTab"; import { OrgSsoTab } from "../OrgSsoTab";
import { OrgWorkflowIntegrationTab } from "../OrgWorkflowIntegrationTab";
import { ProjectTemplatesTab } from "../ProjectTemplatesTab"; import { ProjectTemplatesTab } from "../ProjectTemplatesTab";
export const OrgTabGroup = () => { export const OrgTabGroup = () => {
@ -19,6 +21,16 @@ export const OrgTabGroup = () => {
}); });
const tabs = [ const tabs = [
{ name: "General", key: "tab-org-general", component: OrgGeneralTab }, { name: "General", key: "tab-org-general", component: OrgGeneralTab },
{
name: "SSO",
key: "sso-settings",
component: OrgSsoTab
},
{
name: "Provisioning",
key: "provisioning-settings",
component: OrgProvisioningTab
},
{ name: "Security", key: "tab-org-security", component: OrgSecurityTab }, { name: "Security", key: "tab-org-security", component: OrgSecurityTab },
{ name: "Encryption", key: "tab-org-encryption", component: OrgEncryptionTab }, { name: "Encryption", key: "tab-org-encryption", component: OrgEncryptionTab },
{ {

View File

@ -0,0 +1 @@
export * from "./OrgWorkflowIntegrationTab";

View File

@ -1,21 +0,0 @@
import { Helmet } from "react-helmet";
import { PageHeader } from "@app/components/v2";
import { SsoTabGroup } from "./components/SsoTabGroup";
export const SsoPage = () => {
return (
<>
<Helmet>
<title>Single Sign-On (SSO)</title>
</Helmet>
<div className="flex w-full justify-center bg-bunker-800 text-white">
<div className="w-full max-w-7xl">
<PageHeader title="Single Sign-On (SSO)" />
<SsoTabGroup />
</div>
</div>
</>
);
};

View File

@ -1,37 +0,0 @@
import { useState } from "react";
import { useSearch } from "@tanstack/react-router";
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
import { ROUTE_PATHS } from "@app/const/routes";
import { OrgProvisioningTab } from "../OrgProvisioningTab";
import { OrgSsoTab } from "../OrgSsoTab";
export const SsoTabGroup = () => {
const search = useSearch({
from: ROUTE_PATHS.Organization.SsoPage.id
});
const tabs = [
{ name: "General", key: "tab-sso-auth", component: OrgSsoTab },
{ name: "Provisioning", key: "tab-sso-identity", component: OrgProvisioningTab }
];
const [selectedTab, setSelectedTab] = useState(search.selectedTab || tabs[0].key);
return (
<Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabList>
{tabs.map((tab) => (
<Tab value={tab.key} key={tab.key}>
{tab.name}
</Tab>
))}
</TabList>
{tabs.map(({ key, component: Component }) => (
<TabPanel value={key} key={`tab-panel-${key}`}>
<Component />
</TabPanel>
))}
</Tabs>
);
};

View File

@ -1 +0,0 @@
export { SsoTabGroup } from "./SsoTabGroup";

View File

@ -1,26 +0,0 @@
import { createFileRoute, stripSearchParams } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { z } from "zod";
import { SsoPage } from "./SsoPage";
const SettingsPageQueryParams = z.object({
selectedTab: z.string().catch("")
});
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/_org-layout/organization/sso"
)({
component: SsoPage,
validateSearch: zodValidator(SettingsPageQueryParams),
search: {
middlewares: [stripSearchParams({ selectedTab: "" })]
},
context: () => ({
breadcrumbs: [
{
label: "Single Sign-On (SSO)"
}
]
})
});

View File

@ -0,0 +1,14 @@
import { TCloudflareWorkersSync } from "@app/hooks/api/secretSyncs/types/cloudflare-workers-sync";
import { getSecretSyncDestinationColValues } from "../helpers";
import { SecretSyncTableCell } from "../SecretSyncTableCell";
type Props = {
secretSync: TCloudflareWorkersSync;
};
export const CloudflareWorkersSyncDestinationCol = ({ secretSync }: Props) => {
const { primaryText, secondaryText } = getSecretSyncDestinationColValues(secretSync);
return <SecretSyncTableCell primaryText={primaryText} secondaryText={secondaryText} />;
};

View File

@ -8,6 +8,7 @@ import { AzureDevOpsSyncDestinationCol } from "./AzureDevOpsSyncDestinationCol";
import { AzureKeyVaultDestinationSyncCol } from "./AzureKeyVaultDestinationSyncCol"; import { AzureKeyVaultDestinationSyncCol } from "./AzureKeyVaultDestinationSyncCol";
import { CamundaSyncDestinationCol } from "./CamundaSyncDestinationCol"; import { CamundaSyncDestinationCol } from "./CamundaSyncDestinationCol";
import { CloudflarePagesSyncDestinationCol } from "./CloudflarePagesSyncDestinationCol"; import { CloudflarePagesSyncDestinationCol } from "./CloudflarePagesSyncDestinationCol";
import { CloudflareWorkersSyncDestinationCol } from "./CloudflareWorkersSyncDestinationCol";
import { DatabricksSyncDestinationCol } from "./DatabricksSyncDestinationCol"; import { DatabricksSyncDestinationCol } from "./DatabricksSyncDestinationCol";
import { FlyioSyncDestinationCol } from "./FlyioSyncDestinationCol"; import { FlyioSyncDestinationCol } from "./FlyioSyncDestinationCol";
import { GcpSyncDestinationCol } from "./GcpSyncDestinationCol"; import { GcpSyncDestinationCol } from "./GcpSyncDestinationCol";
@ -75,6 +76,8 @@ export const SecretSyncDestinationCol = ({ secretSync }: Props) => {
return <GitLabSyncDestinationCol secretSync={secretSync} />; return <GitLabSyncDestinationCol secretSync={secretSync} />;
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
return <CloudflarePagesSyncDestinationCol secretSync={secretSync} />; return <CloudflarePagesSyncDestinationCol secretSync={secretSync} />;
case SecretSync.CloudflareWorkers:
return <CloudflareWorkersSyncDestinationCol secretSync={secretSync} />;
case SecretSync.Zabbix: case SecretSync.Zabbix:
return <ZabbixSyncDestinationCol secretSync={secretSync} />; return <ZabbixSyncDestinationCol secretSync={secretSync} />;
case SecretSync.Railway: case SecretSync.Railway:

View File

@ -145,6 +145,10 @@ export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => {
primaryText = destinationConfig.projectName; primaryText = destinationConfig.projectName;
secondaryText = destinationConfig.environment; secondaryText = destinationConfig.environment;
break; break;
case SecretSync.CloudflareWorkers:
primaryText = destinationConfig.scriptId;
secondaryText = "Script ID";
break;
case SecretSync.Zabbix: case SecretSync.Zabbix:
if (destinationConfig.scope === ZabbixSyncScope.Host) { if (destinationConfig.scope === ZabbixSyncScope.Host) {
primaryText = destinationConfig.hostName; primaryText = destinationConfig.hostName;

View File

@ -174,7 +174,7 @@ export const SecretOverviewTableRow = ({
)} )}
{isSecretEmpty && ( {isSecretEmpty && (
<Tooltip content="Empty value"> <Tooltip content="Empty value">
<FontAwesomeIcon size="sm" icon={faCircle} /> <FontAwesomeIcon size="sm" icon={faCircle} className="text-yellow" />
</Tooltip> </Tooltip>
)} )}
</div> </div>

View File

@ -21,6 +21,7 @@ import {
Tag, Tag,
Tooltip Tooltip
} from "@app/components/v2"; } from "@app/components/v2";
import { SecretPathInput } from "@app/components/v2/SecretPathInput";
import { useWorkspace } from "@app/context"; import { useWorkspace } from "@app/context";
import { getMemberLabel } from "@app/helpers/members"; import { getMemberLabel } from "@app/helpers/members";
import { policyDetails } from "@app/helpers/policies"; import { policyDetails } from "@app/helpers/policies";
@ -203,6 +204,7 @@ const Form = ({
const formUserBypassers = watch("userBypassers"); const formUserBypassers = watch("userBypassers");
const formGroupBypassers = watch("groupBypassers"); const formGroupBypassers = watch("groupBypassers");
const formEnvironment = watch("environment")?.slug;
const bypasserCount = (formUserBypassers || []).length + (formGroupBypassers || []).length; const bypasserCount = (formUserBypassers || []).length + (formGroupBypassers || []).length;
const handleCreatePolicy = async ({ const handleCreatePolicy = async ({
@ -474,7 +476,11 @@ const Form = ({
errorText={error?.message} errorText={error?.message}
className="flex-1" className="flex-1"
> >
<Input {...field} value={field.value || ""} /> <SecretPathInput
{...field}
value={field.value || ""}
environment={formEnvironment}
/>
</FormControl> </FormControl>
)} )}
/> />

View File

@ -0,0 +1,14 @@
import { GenericFieldLabel } from "@app/components/secret-syncs";
import { TCloudflareWorkersSync } from "@app/hooks/api/secretSyncs/types/cloudflare-workers-sync";
type Props = {
secretSync: TCloudflareWorkersSync;
};
export const CloudflareWorkersSyncDestinationSection = ({ secretSync }: Props) => {
const {
destinationConfig: { scriptId }
} = secretSync;
return <GenericFieldLabel label="Script ID">{scriptId}</GenericFieldLabel>;
};

View File

@ -19,6 +19,7 @@ import { AzureDevOpsSyncDestinationSection } from "./AzureDevOpsSyncDestinationS
import { AzureKeyVaultSyncDestinationSection } from "./AzureKeyVaultSyncDestinationSection"; import { AzureKeyVaultSyncDestinationSection } from "./AzureKeyVaultSyncDestinationSection";
import { CamundaSyncDestinationSection } from "./CamundaSyncDestinationSection"; import { CamundaSyncDestinationSection } from "./CamundaSyncDestinationSection";
import { CloudflarePagesSyncDestinationSection } from "./CloudflarePagesSyncDestinationSection"; import { CloudflarePagesSyncDestinationSection } from "./CloudflarePagesSyncDestinationSection";
import { CloudflareWorkersSyncDestinationSection } from "./CloudflareWorkersSyncDestinationSection";
import { DatabricksSyncDestinationSection } from "./DatabricksSyncDestinationSection"; import { DatabricksSyncDestinationSection } from "./DatabricksSyncDestinationSection";
import { FlyioSyncDestinationSection } from "./FlyioSyncDestinationSection"; import { FlyioSyncDestinationSection } from "./FlyioSyncDestinationSection";
import { GcpSyncDestinationSection } from "./GcpSyncDestinationSection"; import { GcpSyncDestinationSection } from "./GcpSyncDestinationSection";
@ -116,6 +117,9 @@ export const SecretSyncDestinationSection = ({ secretSync, onEditDestination }:
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
DestinationComponents = <CloudflarePagesSyncDestinationSection secretSync={secretSync} />; DestinationComponents = <CloudflarePagesSyncDestinationSection secretSync={secretSync} />;
break; break;
case SecretSync.CloudflareWorkers:
DestinationComponents = <CloudflareWorkersSyncDestinationSection secretSync={secretSync} />;
break;
case SecretSync.Zabbix: case SecretSync.Zabbix:
DestinationComponents = <ZabbixSyncDestinationSection secretSync={secretSync} />; DestinationComponents = <ZabbixSyncDestinationSection secretSync={secretSync} />;
break; break;

View File

@ -60,6 +60,7 @@ export const SecretSyncOptionsSection = ({ secretSync, onEditOptions }: Props) =
case SecretSync.Flyio: case SecretSync.Flyio:
case SecretSync.GitLab: case SecretSync.GitLab:
case SecretSync.CloudflarePages: case SecretSync.CloudflarePages:
case SecretSync.CloudflareWorkers:
case SecretSync.Zabbix: case SecretSync.Zabbix:
case SecretSync.Railway: case SecretSync.Railway:
AdditionalSyncOptionsComponent = null; AdditionalSyncOptionsComponent = null;

View File

@ -47,7 +47,6 @@ import { Route as adminEnvironmentPageRouteImport } from './pages/admin/Environm
import { Route as adminEncryptionPageRouteImport } from './pages/admin/EncryptionPage/route' import { Route as adminEncryptionPageRouteImport } from './pages/admin/EncryptionPage/route'
import { Route as adminCachingPageRouteImport } from './pages/admin/CachingPage/route' import { Route as adminCachingPageRouteImport } from './pages/admin/CachingPage/route'
import { Route as adminAuthenticationPageRouteImport } from './pages/admin/AuthenticationPage/route' import { Route as adminAuthenticationPageRouteImport } from './pages/admin/AuthenticationPage/route'
import { Route as organizationSsoPageRouteImport } from './pages/organization/SsoPage/route'
import { Route as organizationProjectsPageRouteImport } from './pages/organization/ProjectsPage/route' import { Route as organizationProjectsPageRouteImport } from './pages/organization/ProjectsPage/route'
import { Route as organizationBillingPageRouteImport } from './pages/organization/BillingPage/route' import { Route as organizationBillingPageRouteImport } from './pages/organization/BillingPage/route'
import { Route as organizationAuditLogsPageRouteImport } from './pages/organization/AuditLogsPage/route' import { Route as organizationAuditLogsPageRouteImport } from './pages/organization/AuditLogsPage/route'
@ -591,12 +590,6 @@ const adminAuthenticationPageRouteRoute =
getParentRoute: () => adminLayoutRoute, getParentRoute: () => adminLayoutRoute,
} as any) } as any)
const organizationSsoPageRouteRoute = organizationSsoPageRouteImport.update({
id: '/sso',
path: '/sso',
getParentRoute: () => AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
} as any)
const organizationProjectsPageRouteRoute = const organizationProjectsPageRouteRoute =
organizationProjectsPageRouteImport.update({ organizationProjectsPageRouteImport.update({
id: '/projects', id: '/projects',
@ -2159,13 +2152,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof organizationProjectsPageRouteImport preLoaderRoute: typeof organizationProjectsPageRouteImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
} }
'/_authenticate/_inject-org-details/_org-layout/organization/sso': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/sso'
path: '/sso'
fullPath: '/organization/sso'
preLoaderRoute: typeof organizationSsoPageRouteImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
}
'/_authenticate/_inject-org-details/admin/_admin-layout/authentication': { '/_authenticate/_inject-org-details/admin/_admin-layout/authentication': {
id: '/_authenticate/_inject-org-details/admin/_admin-layout/authentication' id: '/_authenticate/_inject-org-details/admin/_admin-layout/authentication'
path: '/authentication' path: '/authentication'
@ -3428,7 +3414,6 @@ interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteChildren {
organizationAuditLogsPageRouteRoute: typeof organizationAuditLogsPageRouteRoute organizationAuditLogsPageRouteRoute: typeof organizationAuditLogsPageRouteRoute
organizationBillingPageRouteRoute: typeof organizationBillingPageRouteRoute organizationBillingPageRouteRoute: typeof organizationBillingPageRouteRoute
organizationProjectsPageRouteRoute: typeof organizationProjectsPageRouteRoute organizationProjectsPageRouteRoute: typeof organizationProjectsPageRouteRoute
organizationSsoPageRouteRoute: typeof organizationSsoPageRouteRoute
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
@ -3447,7 +3432,6 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteChildren: Authentica
organizationAuditLogsPageRouteRoute: organizationAuditLogsPageRouteRoute, organizationAuditLogsPageRouteRoute: organizationAuditLogsPageRouteRoute,
organizationBillingPageRouteRoute: organizationBillingPageRouteRoute, organizationBillingPageRouteRoute: organizationBillingPageRouteRoute,
organizationProjectsPageRouteRoute: organizationProjectsPageRouteRoute, organizationProjectsPageRouteRoute: organizationProjectsPageRouteRoute,
organizationSsoPageRouteRoute: organizationSsoPageRouteRoute,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute: AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute:
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren, AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute: AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute:
@ -4345,7 +4329,6 @@ export interface FileRoutesByFullPath {
'/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute '/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
'/organization/billing': typeof organizationBillingPageRouteRoute '/organization/billing': typeof organizationBillingPageRouteRoute
'/organization/projects': typeof organizationProjectsPageRouteRoute '/organization/projects': typeof organizationProjectsPageRouteRoute
'/organization/sso': typeof organizationSsoPageRouteRoute
'/admin/authentication': typeof adminAuthenticationPageRouteRoute '/admin/authentication': typeof adminAuthenticationPageRouteRoute
'/admin/caching': typeof adminCachingPageRouteRoute '/admin/caching': typeof adminCachingPageRouteRoute
'/admin/encryption': typeof adminEncryptionPageRouteRoute '/admin/encryption': typeof adminEncryptionPageRouteRoute
@ -4542,7 +4525,6 @@ export interface FileRoutesByTo {
'/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute '/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
'/organization/billing': typeof organizationBillingPageRouteRoute '/organization/billing': typeof organizationBillingPageRouteRoute
'/organization/projects': typeof organizationProjectsPageRouteRoute '/organization/projects': typeof organizationProjectsPageRouteRoute
'/organization/sso': typeof organizationSsoPageRouteRoute
'/admin/authentication': typeof adminAuthenticationPageRouteRoute '/admin/authentication': typeof adminAuthenticationPageRouteRoute
'/admin/caching': typeof adminCachingPageRouteRoute '/admin/caching': typeof adminCachingPageRouteRoute
'/admin/encryption': typeof adminEncryptionPageRouteRoute '/admin/encryption': typeof adminEncryptionPageRouteRoute
@ -4739,7 +4721,6 @@ export interface FileRoutesById {
'/_authenticate/_inject-org-details/_org-layout/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/billing': typeof organizationBillingPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organization/billing': typeof organizationBillingPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/projects': typeof organizationProjectsPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organization/projects': typeof organizationProjectsPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/sso': typeof organizationSsoPageRouteRoute
'/_authenticate/_inject-org-details/admin/_admin-layout/authentication': typeof adminAuthenticationPageRouteRoute '/_authenticate/_inject-org-details/admin/_admin-layout/authentication': typeof adminAuthenticationPageRouteRoute
'/_authenticate/_inject-org-details/admin/_admin-layout/caching': typeof adminCachingPageRouteRoute '/_authenticate/_inject-org-details/admin/_admin-layout/caching': typeof adminCachingPageRouteRoute
'/_authenticate/_inject-org-details/admin/_admin-layout/encryption': typeof adminEncryptionPageRouteRoute '/_authenticate/_inject-org-details/admin/_admin-layout/encryption': typeof adminEncryptionPageRouteRoute
@ -4949,7 +4930,6 @@ export interface FileRouteTypes {
| '/organization/audit-logs' | '/organization/audit-logs'
| '/organization/billing' | '/organization/billing'
| '/organization/projects' | '/organization/projects'
| '/organization/sso'
| '/admin/authentication' | '/admin/authentication'
| '/admin/caching' | '/admin/caching'
| '/admin/encryption' | '/admin/encryption'
@ -5145,7 +5125,6 @@ export interface FileRouteTypes {
| '/organization/audit-logs' | '/organization/audit-logs'
| '/organization/billing' | '/organization/billing'
| '/organization/projects' | '/organization/projects'
| '/organization/sso'
| '/admin/authentication' | '/admin/authentication'
| '/admin/caching' | '/admin/caching'
| '/admin/encryption' | '/admin/encryption'
@ -5340,7 +5319,6 @@ export interface FileRouteTypes {
| '/_authenticate/_inject-org-details/_org-layout/organization/audit-logs' | '/_authenticate/_inject-org-details/_org-layout/organization/audit-logs'
| '/_authenticate/_inject-org-details/_org-layout/organization/billing' | '/_authenticate/_inject-org-details/_org-layout/organization/billing'
| '/_authenticate/_inject-org-details/_org-layout/organization/projects' | '/_authenticate/_inject-org-details/_org-layout/organization/projects'
| '/_authenticate/_inject-org-details/_org-layout/organization/sso'
| '/_authenticate/_inject-org-details/admin/_admin-layout/authentication' | '/_authenticate/_inject-org-details/admin/_admin-layout/authentication'
| '/_authenticate/_inject-org-details/admin/_admin-layout/caching' | '/_authenticate/_inject-org-details/admin/_admin-layout/caching'
| '/_authenticate/_inject-org-details/admin/_admin-layout/encryption' | '/_authenticate/_inject-org-details/admin/_admin-layout/encryption'
@ -5732,7 +5710,6 @@ export const routeTree = rootRoute
"/_authenticate/_inject-org-details/_org-layout/organization/audit-logs", "/_authenticate/_inject-org-details/_org-layout/organization/audit-logs",
"/_authenticate/_inject-org-details/_org-layout/organization/billing", "/_authenticate/_inject-org-details/_org-layout/organization/billing",
"/_authenticate/_inject-org-details/_org-layout/organization/projects", "/_authenticate/_inject-org-details/_org-layout/organization/projects",
"/_authenticate/_inject-org-details/_org-layout/organization/sso",
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections", "/_authenticate/_inject-org-details/_org-layout/organization/app-connections",
"/_authenticate/_inject-org-details/_org-layout/organization/gateways", "/_authenticate/_inject-org-details/_org-layout/organization/gateways",
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing", "/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing",
@ -5782,10 +5759,6 @@ export const routeTree = rootRoute
"filePath": "organization/ProjectsPage/route.tsx", "filePath": "organization/ProjectsPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization" "parent": "/_authenticate/_inject-org-details/_org-layout/organization"
}, },
"/_authenticate/_inject-org-details/_org-layout/organization/sso": {
"filePath": "organization/SsoPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization"
},
"/_authenticate/_inject-org-details/admin/_admin-layout/authentication": { "/_authenticate/_inject-org-details/admin/_admin-layout/authentication": {
"filePath": "admin/AuthenticationPage/route.tsx", "filePath": "admin/AuthenticationPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/admin/_admin-layout" "parent": "/_authenticate/_inject-org-details/admin/_admin-layout"

View File

@ -31,7 +31,6 @@ const organizationRoutes = route("/organization", [
index("organization/SettingsPage/route.tsx"), index("organization/SettingsPage/route.tsx"),
route("/oauth/callback", "organization/SettingsPage/OauthCallbackPage/route.tsx") route("/oauth/callback", "organization/SettingsPage/OauthCallbackPage/route.tsx")
]), ]),
route("/sso", "organization/SsoPage/route.tsx"),
route("/groups/$groupId", "organization/GroupDetailsByIDPage/route.tsx"), route("/groups/$groupId", "organization/GroupDetailsByIDPage/route.tsx"),
route("/members/$membershipId", "organization/UserDetailsByIDPage/route.tsx"), route("/members/$membershipId", "organization/UserDetailsByIDPage/route.tsx"),
route("/roles/$roleId", "organization/RoleByIDPage/route.tsx"), route("/roles/$roleId", "organization/RoleByIDPage/route.tsx"),