diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index e837c5530..738be38ab 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -75,6 +75,7 @@ const envSchema = z .optional() .default(process.env.URL_GITLAB_LOGIN ?? GITLAB_URL) ), // fallback since URL_GITLAB_LOGIN has been renamed + DEFAULT_SAML_ORG_SLUG: zpStr(z.string().optional()).default(process.env.NEXT_PUBLIC_SAML_ORG_SLUG), // integration client secrets // heroku CLIENT_ID_HEROKU: zpStr(z.string().optional()), @@ -134,7 +135,8 @@ const envSchema = z isSecretScanningConfigured: Boolean(data.SECRET_SCANNING_GIT_APP_ID) && Boolean(data.SECRET_SCANNING_PRIVATE_KEY) && - Boolean(data.SECRET_SCANNING_WEBHOOK_SECRET) + Boolean(data.SECRET_SCANNING_WEBHOOK_SECRET), + samlDefaultOrgSlug: data.DEFAULT_SAML_ORG_SLUG })); let envCfg: Readonly>; diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index cdd3e3bd8..00590386a 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -919,7 +919,8 @@ export const registerRoutes = async ( emailConfigured: z.boolean().optional(), inviteOnlySignup: z.boolean().optional(), redisConfigured: z.boolean().optional(), - secretScanningConfigured: z.boolean().optional() + secretScanningConfigured: z.boolean().optional(), + samlDefaultOrgSlug: z.string().optional() }) } }, @@ -932,7 +933,8 @@ export const registerRoutes = async ( emailConfigured: cfg.isSmtpConfigured, inviteOnlySignup: Boolean(serverCfg.allowSignUp), redisConfigured: cfg.isRedisConfigured, - secretScanningConfigured: cfg.isSecretScanningConfigured + secretScanningConfigured: cfg.isSecretScanningConfigured, + samlDefaultOrgSlug: cfg.samlDefaultOrgSlug }; } }); diff --git a/backend/src/services/integration-auth/integration-sync-secret.ts b/backend/src/services/integration-auth/integration-sync-secret.ts index 9d8ee8895..0ae0a0275 100644 --- a/backend/src/services/integration-auth/integration-sync-secret.ts +++ b/backend/src/services/integration-auth/integration-sync-secret.ts @@ -2750,6 +2750,20 @@ const syncSecretsCloudflarePages = async ({ } } ); + + const metadata = z.record(z.any()).parse(integration.metadata); + if (metadata.shouldAutoRedeploy) { + await request.post( + `${IntegrationUrls.CLOUDFLARE_PAGES_API_URL}/client/v4/accounts/${accessId}/pages/projects/${integration.app}/deployments`, + {}, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); + } }; /** diff --git a/backend/src/services/kms/kms-service.ts b/backend/src/services/kms/kms-service.ts index 24d901867..97d2b29d6 100644 --- a/backend/src/services/kms/kms-service.ts +++ b/backend/src/services/kms/kms-service.ts @@ -77,7 +77,7 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe // This will switch to a seal process and HMS flow in future const encryptionKey = appCfg.ENCRYPTION_KEY || appCfg.ROOT_ENCRYPTION_KEY; // if root key its base64 encoded - const isBase64 = Boolean(appCfg.ROOT_ENCRYPTION_KEY); + const isBase64 = !appCfg.ENCRYPTION_KEY; if (!encryptionKey) throw new Error("Root encryption key not found for KMS service."); const encryptionKeyBuffer = Buffer.from(encryptionKey, isBase64 ? "base64" : "utf8"); diff --git a/docs/integrations/platforms/kubernetes.mdx b/docs/integrations/platforms/kubernetes.mdx index 3d1b72331..41a41726c 100644 --- a/docs/integrations/platforms/kubernetes.mdx +++ b/docs/integrations/platforms/kubernetes.mdx @@ -496,7 +496,6 @@ To enable auto redeployment you simply have to add the following annotation to t ```yaml secrets.infisical.com/auto-reload: "true" ``` - ```yaml apiVersion: apps/v1 @@ -527,7 +526,11 @@ spec: - containerPort: 80 ``` - + + #### How it works + When a secret change occurs, the operator will check to see which deployments are using the operator-managed Kubernetes secret that received the update. + Then, for each deployment that has this annotation present, a rolling update will be triggered. + ## Global configuration To configure global settings that will apply to all instances of `InfisicalSecret`, you can define these configurations in a Kubernetes ConfigMap. diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index 5233ae910..33e6c697c 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -318,6 +318,11 @@ SMTP_FROM_NAME=Infisical By default, users can only login via email/password based login method. To login into Infisical with OAuth providers such as Google, configure the associated variables. + + + When set, all visits to the Infisical login page will automatically redirect users of your Infisical instance to the SAML identity provider associated with the specified organization slug. + + Follow detailed guide to configure [Google SSO](/documentation/platform/sso/google) @@ -369,11 +374,6 @@ To login into Infisical with OAuth providers such as Google, configure the assoc information. - - Configure SAML organization slug to automatically redirect all users of your - Infisical instance to the identity provider. - - ## Native secret integrations To help you sync secrets from Infisical to services such as Github and Gitlab, Infisical provides native integrations out of the box. diff --git a/frontend/src/hooks/api/serverDetails/types.ts b/frontend/src/hooks/api/serverDetails/types.ts index 80d34a150..911526404 100644 --- a/frontend/src/hooks/api/serverDetails/types.ts +++ b/frontend/src/hooks/api/serverDetails/types.ts @@ -4,4 +4,5 @@ export type ServerStatus = { emailConfigured: boolean; secretScanningConfigured: boolean; redisConfigured: boolean; + samlDefaultOrgSlug: boolean }; diff --git a/frontend/src/pages/integrations/cloudflare-pages/create.tsx b/frontend/src/pages/integrations/cloudflare-pages/create.tsx index 570b2b83a..d7cb6bdab 100644 --- a/frontend/src/pages/integrations/cloudflare-pages/create.tsx +++ b/frontend/src/pages/integrations/cloudflare-pages/create.tsx @@ -7,7 +7,15 @@ import { createNotification } from "@app/components/notifications"; import { SecretPathInput } from "@app/components/v2/SecretPathInput"; import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api"; -import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "../../../components/v2"; +import { + Button, + Card, + CardTitle, + FormControl, + Select, + SelectItem, + Switch +} from "../../../components/v2"; import { useGetIntegrationAuthApps, useGetIntegrationAuthById @@ -34,6 +42,7 @@ export default function CloudflarePagesIntegrationPage() { const [targetApp, setTargetApp] = useState(""); const [targetAppId, setTargetAppId] = useState(""); const [targetEnvironment, setTargetEnvironment] = useState(""); + const [shouldAutoRedeploy, setShouldAutoRedeploy] = useState(false); const [isLoading, setIsLoading] = useState(false); @@ -69,7 +78,10 @@ export default function CloudflarePagesIntegrationPage() { appId: targetAppId, sourceEnvironment: selectedSourceEnvironment, targetEnvironment, - secretPath + secretPath, + metadata: { + shouldAutoRedeploy + } }); setIsLoading(false); @@ -169,6 +181,15 @@ export default function CloudflarePagesIntegrationPage() { ))} +
+ setShouldAutoRedeploy(isChecked)} + isChecked={shouldAutoRedeploy} + > + Auto-redeploy service upon secret change + +