Merge branch 'feat/add-captcha' of https://github.com/Infisical/infisical into feat/add-captcha

This commit is contained in:
Sheen Capadngan
2024-06-10 13:27:31 +08:00
11 changed files with 71 additions and 33 deletions
+3 -1
View File
@@ -75,6 +75,7 @@ const envSchema = z
.optional() .optional()
.default(process.env.URL_GITLAB_LOGIN ?? GITLAB_URL) .default(process.env.URL_GITLAB_LOGIN ?? GITLAB_URL)
), // fallback since URL_GITLAB_LOGIN has been renamed ), // 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 // integration client secrets
// heroku // heroku
CLIENT_ID_HEROKU: zpStr(z.string().optional()), CLIENT_ID_HEROKU: zpStr(z.string().optional()),
@@ -134,7 +135,8 @@ const envSchema = z
isSecretScanningConfigured: isSecretScanningConfigured:
Boolean(data.SECRET_SCANNING_GIT_APP_ID) && Boolean(data.SECRET_SCANNING_GIT_APP_ID) &&
Boolean(data.SECRET_SCANNING_PRIVATE_KEY) && 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<z.infer<typeof envSchema>>; let envCfg: Readonly<z.infer<typeof envSchema>>;
+4 -2
View File
@@ -919,7 +919,8 @@ export const registerRoutes = async (
emailConfigured: z.boolean().optional(), emailConfigured: z.boolean().optional(),
inviteOnlySignup: z.boolean().optional(), inviteOnlySignup: z.boolean().optional(),
redisConfigured: 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, emailConfigured: cfg.isSmtpConfigured,
inviteOnlySignup: Boolean(serverCfg.allowSignUp), inviteOnlySignup: Boolean(serverCfg.allowSignUp),
redisConfigured: cfg.isRedisConfigured, redisConfigured: cfg.isRedisConfigured,
secretScanningConfigured: cfg.isSecretScanningConfigured secretScanningConfigured: cfg.isSecretScanningConfigured,
samlDefaultOrgSlug: cfg.samlDefaultOrgSlug
}; };
} }
}); });
@@ -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"
}
}
);
}
}; };
/** /**
+1 -1
View File
@@ -77,7 +77,7 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe
// This will switch to a seal process and HMS flow in future // This will switch to a seal process and HMS flow in future
const encryptionKey = appCfg.ENCRYPTION_KEY || appCfg.ROOT_ENCRYPTION_KEY; const encryptionKey = appCfg.ENCRYPTION_KEY || appCfg.ROOT_ENCRYPTION_KEY;
// if root key its base64 encoded // 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."); if (!encryptionKey) throw new Error("Root encryption key not found for KMS service.");
const encryptionKeyBuffer = Buffer.from(encryptionKey, isBase64 ? "base64" : "utf8"); const encryptionKeyBuffer = Buffer.from(encryptionKey, isBase64 ? "base64" : "utf8");
+5 -2
View File
@@ -496,7 +496,6 @@ To enable auto redeployment you simply have to add the following annotation to t
```yaml ```yaml
secrets.infisical.com/auto-reload: "true" secrets.infisical.com/auto-reload: "true"
``` ```
<Accordion title="Deployment example with auto redeploy enabled"> <Accordion title="Deployment example with auto redeploy enabled">
```yaml ```yaml
apiVersion: apps/v1 apiVersion: apps/v1
@@ -527,7 +526,11 @@ spec:
- containerPort: 80 - containerPort: 80
``` ```
</Accordion> </Accordion>
<Info>
#### 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.
</Info>
## Global configuration ## Global configuration
To configure global settings that will apply to all instances of `InfisicalSecret`, you can define these configurations in a Kubernetes ConfigMap. To configure global settings that will apply to all instances of `InfisicalSecret`, you can define these configurations in a Kubernetes ConfigMap.
+5 -5
View File
@@ -318,6 +318,11 @@ SMTP_FROM_NAME=Infisical
By default, users can only login via email/password based login method. 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. To login into Infisical with OAuth providers such as Google, configure the associated variables.
<ParamField query="DEFAULT_SAML_ORG_SLUG" type="string">
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.
</ParamField>
<Accordion title="Google"> <Accordion title="Google">
Follow detailed guide to configure [Google SSO](/documentation/platform/sso/google) 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. information.
</Accordion> </Accordion>
<ParamField query="NEXT_PUBLIC_SAML_ORG_SLUG" type="string">
Configure SAML organization slug to automatically redirect all users of your
Infisical instance to the identity provider.
</ParamField>
## Native secret integrations ## 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. To help you sync secrets from Infisical to services such as Github and Gitlab, Infisical provides native integrations out of the box.
@@ -4,4 +4,5 @@ export type ServerStatus = {
emailConfigured: boolean; emailConfigured: boolean;
secretScanningConfigured: boolean; secretScanningConfigured: boolean;
redisConfigured: boolean; redisConfigured: boolean;
samlDefaultOrgSlug: boolean
}; };
@@ -7,7 +7,15 @@ import { createNotification } from "@app/components/notifications";
import { SecretPathInput } from "@app/components/v2/SecretPathInput"; import { SecretPathInput } from "@app/components/v2/SecretPathInput";
import { useCreateIntegration, useGetWorkspaceById } from "@app/hooks/api"; 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 { import {
useGetIntegrationAuthApps, useGetIntegrationAuthApps,
useGetIntegrationAuthById useGetIntegrationAuthById
@@ -34,6 +42,7 @@ export default function CloudflarePagesIntegrationPage() {
const [targetApp, setTargetApp] = useState(""); const [targetApp, setTargetApp] = useState("");
const [targetAppId, setTargetAppId] = useState(""); const [targetAppId, setTargetAppId] = useState("");
const [targetEnvironment, setTargetEnvironment] = useState(""); const [targetEnvironment, setTargetEnvironment] = useState("");
const [shouldAutoRedeploy, setShouldAutoRedeploy] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -69,7 +78,10 @@ export default function CloudflarePagesIntegrationPage() {
appId: targetAppId, appId: targetAppId,
sourceEnvironment: selectedSourceEnvironment, sourceEnvironment: selectedSourceEnvironment,
targetEnvironment, targetEnvironment,
secretPath secretPath,
metadata: {
shouldAutoRedeploy
}
}); });
setIsLoading(false); setIsLoading(false);
@@ -169,6 +181,15 @@ export default function CloudflarePagesIntegrationPage() {
))} ))}
</Select> </Select>
</FormControl> </FormControl>
<div className="mb-[2.36rem] ml-1 px-6">
<Switch
id="redeploy-cloudflare-pages"
onCheckedChange={(isChecked: boolean) => setShouldAutoRedeploy(isChecked)}
isChecked={shouldAutoRedeploy}
>
Auto-redeploy service upon secret change
</Switch>
</div>
<Button <Button
onClick={handleButtonClick} onClick={handleButtonClick}
color="mineshaft" color="mineshaft"
@@ -14,6 +14,7 @@ import attemptLogin from "@app/components/utilities/attemptLogin";
import { CAPTCHA_SITE_KEY } from "@app/components/utilities/config"; import { CAPTCHA_SITE_KEY } from "@app/components/utilities/config";
import { Button, Input } from "@app/components/v2"; import { Button, Input } from "@app/components/v2";
import { useServerConfig } from "@app/context"; import { useServerConfig } from "@app/context";
import { useFetchServerStatus } from "@app/hooks/api";
import { navigateUserToSelectOrg } from "../../Login.utils"; import { navigateUserToSelectOrg } from "../../Login.utils";
@@ -36,21 +37,15 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
const [captchaToken, setCaptchaToken] = useState(""); const [captchaToken, setCaptchaToken] = useState("");
const [shouldShowCaptcha, setShouldShowCaptcha] = useState(false); const [shouldShowCaptcha, setShouldShowCaptcha] = useState(false);
const captchaRef = useRef<HCaptcha>(null); const captchaRef = useRef<HCaptcha>(null);
const { data: serverDetails } = useFetchServerStatus();
useEffect(() => { useEffect(() => {
if ( if (serverDetails?.samlDefaultOrgSlug){
process.env.NEXT_PUBLIC_SAML_ORG_SLUG && const callbackPort = queryParams.get("callback_port");
process.env.NEXT_PUBLIC_SAML_ORG_SLUG !== "saml-org-slug-default" const redirectUrl = `/api/v1/sso/redirect/saml2/organizations/${serverDetails?.samlDefaultOrgSlug}${callbackPort ? `?callback_port=${callbackPort}` : ""}`
) { router.push(redirectUrl);
const callbackPort = queryParams.get("callback_port"); }
window.open( }, [serverDetails?.samlDefaultOrgSlug]);
`/api/v1/sso/redirect/saml2/organizations/${process.env.NEXT_PUBLIC_SAML_ORG_SLUG}${
callbackPort ? `?callback_port=${callbackPort}` : ""
}`
);
window.close();
}
}, []);
const handleLogin = async (e: FormEvent<HTMLFormElement>) => { const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
@@ -454,12 +454,12 @@ export const SecretOverviewPage = () => {
const filteredSecretNames = secKeys const filteredSecretNames = secKeys
?.filter((name) => name.toUpperCase().includes(searchFilter.toUpperCase())) ?.filter((name) => name.toUpperCase().includes(searchFilter.toUpperCase()))
.sort((a, b) => (sortDir === "asc" ? a.localeCompare(b) : b.localeCompare(a))); .sort((a, b) => (sortDir === "asc" ? a.localeCompare(b) : b.localeCompare(a)));
const filteredFolderNames = folderNames?.filter((name) => const filteredFolderNames = folderNames
name.toLowerCase().includes(searchFilter.toLowerCase()) ?.filter((name) => name.toLowerCase().includes(searchFilter.toLowerCase()))
); .sort((a, b) => (sortDir === "asc" ? a.localeCompare(b) : b.localeCompare(a)));
const filteredDynamicSecrets = dynamicSecretNames?.filter((name) => const filteredDynamicSecrets = dynamicSecretNames
name.toLowerCase().includes(searchFilter.toLowerCase()) ?.filter((name) => name.toLowerCase().includes(searchFilter.toLowerCase()))
); .sort((a, b) => (sortDir === "asc" ? a.localeCompare(b) : b.localeCompare(a)));
const isTableEmpty = const isTableEmpty =
!( !(
@@ -178,7 +178,7 @@ export const AddShareSecretModal = ({ popUp, handlePopUpToggle }: Props) => {
errorText={error?.message} errorText={error?.message}
> >
<SecretInput <SecretInput
isVisible isVisible={false}
{...field} {...field}
containerClassName="py-1.5 rounded-md transition-all group-hover:mr-2 text-bunker-300 hover:border-primary-400/50 border border-mineshaft-600 bg-mineshaft-900 px-2 min-h-[100px]" containerClassName="py-1.5 rounded-md transition-all group-hover:mr-2 text-bunker-300 hover:border-primary-400/50 border border-mineshaft-600 bg-mineshaft-900 px-2 min-h-[100px]"
/> />