mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 10:26:35 +00:00
Merge branch 'main' into feat/add-captcha
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
ARG POSTHOG_HOST=https://app.posthog.com
|
ARG POSTHOG_HOST=https://app.posthog.com
|
||||||
ARG POSTHOG_API_KEY=posthog-api-key
|
ARG POSTHOG_API_KEY=posthog-api-key
|
||||||
ARG INTERCOM_ID=intercom-id
|
ARG INTERCOM_ID=intercom-id
|
||||||
ARG SAML_ORG_SLUG=saml-org-slug-default
|
|
||||||
|
|
||||||
FROM node:20-alpine AS base
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
@@ -35,9 +34,7 @@ ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
|
|||||||
ARG INTERCOM_ID
|
ARG INTERCOM_ID
|
||||||
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
||||||
ARG INFISICAL_PLATFORM_VERSION
|
ARG INFISICAL_PLATFORM_VERSION
|
||||||
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||||
ARG SAML_ORG_SLUG
|
|
||||||
ENV NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG
|
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
@@ -113,9 +110,6 @@ ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
|||||||
ARG INTERCOM_ID=intercom-id
|
ARG INTERCOM_ID=intercom-id
|
||||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
||||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
||||||
ARG SAML_ORG_SLUG
|
|
||||||
ENV NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG \
|
|
||||||
BAKED_NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG
|
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
|
|||||||
@@ -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()),
|
||||||
@@ -135,7 +136,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>>;
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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,8 +4,6 @@ scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_POSTHOG_API_KEY
|
|||||||
|
|
||||||
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$NEXT_PUBLIC_INTERCOM_ID"
|
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$NEXT_PUBLIC_INTERCOM_ID"
|
||||||
|
|
||||||
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_SAML_ORG_SLUG" "$NEXT_PUBLIC_SAML_ORG_SLUG"
|
|
||||||
|
|
||||||
if [ "$TELEMETRY_ENABLED" != "false" ]; then
|
if [ "$TELEMETRY_ENABLED" != "false" ]; then
|
||||||
echo "Telemetry is enabled"
|
echo "Telemetry is enabled"
|
||||||
scripts/set-standalone-build-telemetry.sh true
|
scripts/set-standalone-build-telemetry.sh true
|
||||||
|
|||||||
@@ -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]"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user