From 3f6b84de3b5d4e4e831f7207a12525b9226568e8 Mon Sep 17 00:00:00 2001
From: Remy
Date: Thu, 20 Jun 2024 16:32:47 +0200
Subject: [PATCH 001/145] fix(helm-charts): add nodeSelector and tolerations
---
helm-charts/secrets-operator/templates/deployment.yaml | 4 +++-
helm-charts/secrets-operator/values.yaml | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/helm-charts/secrets-operator/templates/deployment.yaml b/helm-charts/secrets-operator/templates/deployment.yaml
index 2d27b4b5ac..ec02df12d5 100644
--- a/helm-charts/secrets-operator/templates/deployment.yaml
+++ b/helm-charts/secrets-operator/templates/deployment.yaml
@@ -82,4 +82,6 @@ spec:
securityContext:
runAsNonRoot: true
serviceAccountName: {{ include "secrets-operator.fullname" . }}-controller-manager
- terminationGracePeriodSeconds: 10
\ No newline at end of file
+ terminationGracePeriodSeconds: 10
+ nodeSelector: {{ toYaml .Values.controllerManager.nodeSelector | nindent 8 }}
+ tolerations: {{ toYaml .Values.controllerManager.tolerations | nindent 8 }}
\ No newline at end of file
diff --git a/helm-charts/secrets-operator/values.yaml b/helm-charts/secrets-operator/values.yaml
index 001ef4b109..4b35577e71 100644
--- a/helm-charts/secrets-operator/values.yaml
+++ b/helm-charts/secrets-operator/values.yaml
@@ -43,6 +43,8 @@ controllerManager:
replicas: 1
serviceAccount:
annotations: {}
+ nodeSelector: {}
+ tolerations: []
kubernetesClusterDomain: cluster.local
metricsService:
ports:
From 98a15a901ec17c38c9312ce0e5196b45524475ba Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Wed, 26 Jun 2024 22:45:14 +0800
Subject: [PATCH 002/145] feat: allowed toggling login options as admin
---
...0240626115035_admin-login-method-config.ts | 19 ++
backend/src/db/schemas/super-admin.ts | 3 +-
backend/src/server/routes/v1/admin-router.ts | 10 +-
.../services/super-admin/super-admin-types.ts | 10 +
frontend/src/hooks/api/admin/types.ts | 11 +
.../components/InitialStep/InitialStep.tsx | 321 ++++++++++--------
.../views/admin/DashboardPage/AuthPanel.tsx | 251 ++++++++++++++
.../admin/DashboardPage/DashboardPage.tsx | 9 +-
8 files changed, 488 insertions(+), 146 deletions(-)
create mode 100644 backend/src/db/migrations/20240626115035_admin-login-method-config.ts
create mode 100644 frontend/src/views/admin/DashboardPage/AuthPanel.tsx
diff --git a/backend/src/db/migrations/20240626115035_admin-login-method-config.ts b/backend/src/db/migrations/20240626115035_admin-login-method-config.ts
new file mode 100644
index 0000000000..8748fe753e
--- /dev/null
+++ b/backend/src/db/migrations/20240626115035_admin-login-method-config.ts
@@ -0,0 +1,19 @@
+import { Knex } from "knex";
+
+import { TableName } from "../schemas";
+
+export async function up(knex: Knex): Promise {
+ if (!(await knex.schema.hasColumn(TableName.SuperAdmin, "enabledLoginMethods"))) {
+ await knex.schema.alterTable(TableName.SuperAdmin, (tb) => {
+ tb.specificType("enabledLoginMethods", "text[]");
+ });
+ }
+}
+
+export async function down(knex: Knex): Promise {
+ if (await knex.schema.hasColumn(TableName.SuperAdmin, "enabledLoginMethods")) {
+ await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
+ t.dropColumn("enabledLoginMethods");
+ });
+ }
+}
diff --git a/backend/src/db/schemas/super-admin.ts b/backend/src/db/schemas/super-admin.ts
index 29e41c78ef..b676b81a80 100644
--- a/backend/src/db/schemas/super-admin.ts
+++ b/backend/src/db/schemas/super-admin.ts
@@ -18,7 +18,8 @@ export const SuperAdminSchema = z.object({
trustSamlEmails: z.boolean().default(false).nullable().optional(),
trustLdapEmails: z.boolean().default(false).nullable().optional(),
trustOidcEmails: z.boolean().default(false).nullable().optional(),
- defaultAuthOrgId: z.string().uuid().nullable().optional()
+ defaultAuthOrgId: z.string().uuid().nullable().optional(),
+ enabledLoginMethods: z.string().array().nullable().optional()
});
export type TSuperAdmin = z.infer;
diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts
index 24c7e2a6e4..4557152bdb 100644
--- a/backend/src/server/routes/v1/admin-router.ts
+++ b/backend/src/server/routes/v1/admin-router.ts
@@ -8,6 +8,7 @@ import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
+import { LoginMethod } from "@app/services/super-admin/super-admin-types";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
export const registerAdminRouter = async (server: FastifyZodProvider) => {
@@ -54,7 +55,14 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
trustSamlEmails: z.boolean().optional(),
trustLdapEmails: z.boolean().optional(),
trustOidcEmails: z.boolean().optional(),
- defaultAuthOrgId: z.string().optional().nullable()
+ defaultAuthOrgId: z.string().optional().nullable(),
+ enabledLoginMethods: z
+ .nativeEnum(LoginMethod)
+ .array()
+ .optional()
+ .refine((methods) => !methods || methods.length > 0, {
+ message: "At least one login method should be enabled."
+ })
}),
response: {
200: z.object({
diff --git a/backend/src/services/super-admin/super-admin-types.ts b/backend/src/services/super-admin/super-admin-types.ts
index e444c8843a..f622c8f174 100644
--- a/backend/src/services/super-admin/super-admin-types.ts
+++ b/backend/src/services/super-admin/super-admin-types.ts
@@ -15,3 +15,13 @@ export type TAdminSignUpDTO = {
ip: string;
userAgent: string;
};
+
+export enum LoginMethod {
+ EMAIL = "email",
+ GOOGLE = "google",
+ GITHUB = "github",
+ GITLAB = "gitlab",
+ SAML = "saml",
+ LDAP = "ldap",
+ OIDC = "oidc"
+}
diff --git a/frontend/src/hooks/api/admin/types.ts b/frontend/src/hooks/api/admin/types.ts
index 524bc6ace0..4d5add1e0e 100644
--- a/frontend/src/hooks/api/admin/types.ts
+++ b/frontend/src/hooks/api/admin/types.ts
@@ -1,3 +1,13 @@
+export enum LoginMethod {
+ EMAIL = "email",
+ GOOGLE = "google",
+ GITHUB = "github",
+ GITLAB = "gitlab",
+ SAML = "saml",
+ LDAP = "ldap",
+ OIDC = "oidc"
+}
+
export type TServerConfig = {
initialized: boolean;
allowSignUp: boolean;
@@ -9,6 +19,7 @@ export type TServerConfig = {
isSecretScanningDisabled: boolean;
defaultAuthOrgSlug: string | null;
defaultAuthOrgId: string | null;
+ enabledLoginMethods: LoginMethod[];
};
export type TCreateAdminUserDTO = {
diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
index 0616ee58d1..83615ccf56 100644
--- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
+++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
@@ -15,6 +15,7 @@ import { CAPTCHA_SITE_KEY } from "@app/components/utilities/config";
import { Button, Input } from "@app/components/v2";
import { useServerConfig } from "@app/context";
import { useFetchServerStatus } from "@app/hooks/api";
+import { LoginMethod } from "@app/hooks/api/admin/types";
import { useNavigateToSelectOrganization } from "../../Login.utils";
@@ -162,154 +163,188 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
Login to Infisical
-
-
{
- const callbackPort = queryParams.get("callback_port");
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.GOOGLE) && (
+
+ {
+ const callbackPort = queryParams.get("callback_port");
- window.open(
- `/api/v1/sso/redirect/google${callbackPort ? `?callback_port=${callbackPort}` : ""}`
- );
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- {t("login.continue-with-google")}
-
-
-
- {
- const callbackPort = queryParams.get("callback_port");
+ window.open(
+ `/api/v1/sso/redirect/google${
+ callbackPort ? `?callback_port=${callbackPort}` : ""
+ }`
+ );
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ {t("login.continue-with-google")}
+
+
+ ))}
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.GITHUB) && (
+
+ {
+ const callbackPort = queryParams.get("callback_port");
- window.open(
- `/api/v1/sso/redirect/github${callbackPort ? `?callback_port=${callbackPort}` : ""}`
- );
+ window.open(
+ `/api/v1/sso/redirect/github${
+ callbackPort ? `?callback_port=${callbackPort}` : ""
+ }`
+ );
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with GitHub
-
-
-
- {
- const callbackPort = queryParams.get("callback_port");
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with GitHub
+
+
+ ))}
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.GITLAB) && (
+
+ {
+ const callbackPort = queryParams.get("callback_port");
- window.open(
- `/api/v1/sso/redirect/gitlab${callbackPort ? `?callback_port=${callbackPort}` : ""}`
- );
+ window.open(
+ `/api/v1/sso/redirect/gitlab${
+ callbackPort ? `?callback_port=${callbackPort}` : ""
+ }`
+ );
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with GitLab
-
-
-
- {
- handleSaml(2);
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with SAML
-
-
-
- {
- setStep(3);
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with OIDC
-
-
-
- {
- router.push("/login/ldap");
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with LDAP
-
-
-
-
- setEmail(e.target.value)}
- type="email"
- placeholder="Enter your email..."
- isRequired
- autoComplete="username"
- className="h-10"
- />
-
-
- setPassword(e.target.value)}
- type="password"
- placeholder="Enter your password..."
- isRequired
- autoComplete="current-password"
- id="current-password"
- className="select:-webkit-autofill:focus h-10"
- />
-
- {shouldShowCaptcha && (
-
- setCaptchaToken(token)}
- ref={captchaRef}
- />
-
- )}
-
-
- {" "}
- Continue with Email{" "}
-
-
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with GitLab
+
+
+ ))}
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.SAML) && (
+
+ {
+ handleSaml(2);
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with SAML
+
+
+ ))}
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.OIDC) && (
+
+ {
+ setStep(3);
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with OIDC
+
+
+ ))}
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.LDAP) && (
+
+ {
+ router.push("/login/ldap");
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with LDAP
+
+
+ ))}
+
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.length > 1 &&
+ config.enabledLoginMethods.includes(LoginMethod.EMAIL) && (
+
+ ))}
+ {!config.enabledLoginMethods ||
+ (config.enabledLoginMethods.includes(LoginMethod.EMAIL) && (
+ <>
+
+ setEmail(e.target.value)}
+ type="email"
+ placeholder="Enter your email..."
+ isRequired
+ autoComplete="username"
+ className="h-10"
+ />
+
+
+ setPassword(e.target.value)}
+ type="password"
+ placeholder="Enter your password..."
+ isRequired
+ autoComplete="current-password"
+ id="current-password"
+ className="select:-webkit-autofill:focus h-10"
+ />
+
+ {shouldShowCaptcha && (
+
+ setCaptchaToken(token)}
+ ref={captchaRef}
+ />
+
+ )}
+
+
+ {" "}
+ Continue with Email{" "}
+
+
+ >
+ ))}
{!isLoading && loginError && }
{config.allowSignUp ? (
diff --git a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
new file mode 100644
index 0000000000..0060cb095a
--- /dev/null
+++ b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
@@ -0,0 +1,251 @@
+import { Controller, useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { z } from "zod";
+
+import { createNotification } from "@app/components/notifications";
+import { Button, FormControl, Switch } from "@app/components/v2";
+import { useServerConfig } from "@app/context";
+import { useUpdateServerConfig } from "@app/hooks/api";
+import { LoginMethod } from "@app/hooks/api/admin/types";
+
+const formSchema = z.object({
+ isEmailEnabled: z.boolean(),
+ isGoogleEnabled: z.boolean(),
+ isGithubEnabled: z.boolean(),
+ isGitlabEnabled: z.boolean(),
+ isSamlEnabled: z.boolean(),
+ isLdapEnabled: z.boolean(),
+ isOidcEnabled: z.boolean()
+});
+
+type TAuthForm = z.infer
;
+
+export const AuthPanel = () => {
+ const { config } = useServerConfig();
+ const { enabledLoginMethods } = config;
+ const { mutateAsync: updateServerConfig } = useUpdateServerConfig();
+
+ const {
+ control,
+ handleSubmit,
+ formState: { isSubmitting, isDirty }
+ } = useForm({
+ resolver: zodResolver(formSchema),
+ values: enabledLoginMethods
+ ? {
+ isEmailEnabled: enabledLoginMethods.includes(LoginMethod.EMAIL),
+ isGoogleEnabled: enabledLoginMethods.includes(LoginMethod.GOOGLE),
+ isGithubEnabled: enabledLoginMethods.includes(LoginMethod.GITHUB),
+ isGitlabEnabled: enabledLoginMethods.includes(LoginMethod.GITLAB),
+ isSamlEnabled: enabledLoginMethods.includes(LoginMethod.SAML),
+ isLdapEnabled: enabledLoginMethods.includes(LoginMethod.LDAP),
+ isOidcEnabled: enabledLoginMethods.includes(LoginMethod.OIDC)
+ }
+ : {
+ isEmailEnabled: true,
+ isGoogleEnabled: true,
+ isGithubEnabled: true,
+ isGitlabEnabled: true,
+ isSamlEnabled: true,
+ isLdapEnabled: true,
+ isOidcEnabled: true
+ }
+ });
+
+ const onAuthFormSubmit = async (formData: TAuthForm) => {
+ try {
+ const enabledMethods: LoginMethod[] = [];
+ if (formData.isEmailEnabled) {
+ enabledMethods.push(LoginMethod.EMAIL);
+ }
+
+ if (formData.isGoogleEnabled) {
+ enabledMethods.push(LoginMethod.GOOGLE);
+ }
+
+ if (formData.isGithubEnabled) {
+ enabledMethods.push(LoginMethod.GITHUB);
+ }
+
+ if (formData.isGitlabEnabled) {
+ enabledMethods.push(LoginMethod.GITLAB);
+ }
+
+ if (formData.isSamlEnabled) {
+ enabledMethods.push(LoginMethod.SAML);
+ }
+
+ if (formData.isLdapEnabled) {
+ enabledMethods.push(LoginMethod.LDAP);
+ }
+
+ if (formData.isOidcEnabled) {
+ enabledMethods.push(LoginMethod.OIDC);
+ }
+
+ if (!enabledMethods.length) {
+ createNotification({
+ type: "error",
+ text: "At least one login method should be enabled."
+ });
+ return;
+ }
+
+ await updateServerConfig({
+ enabledLoginMethods: enabledMethods
+ });
+
+ createNotification({
+ text: "Login methods have been successfully updated.",
+ type: "success"
+ });
+ } catch (e) {
+ console.error(e);
+ createNotification({
+ type: "error",
+ text: "Failed to update login methods."
+ });
+ }
+ };
+
+ return (
+
+ );
+};
diff --git a/frontend/src/views/admin/DashboardPage/DashboardPage.tsx b/frontend/src/views/admin/DashboardPage/DashboardPage.tsx
index 134a67f8cd..bf8a5a4a9e 100644
--- a/frontend/src/views/admin/DashboardPage/DashboardPage.tsx
+++ b/frontend/src/views/admin/DashboardPage/DashboardPage.tsx
@@ -24,10 +24,12 @@ import {
import { useOrganization, useServerConfig, useUser } from "@app/context";
import { useGetOrganizations, useUpdateServerConfig } from "@app/hooks/api";
+import { AuthPanel } from "./AuthPanel";
import { RateLimitPanel } from "./RateLimitPanel";
enum TabSections {
Settings = "settings",
+ Auth = "auth",
RateLimit = "rate-limit"
}
@@ -131,6 +133,7 @@ export const AdminDashboardPage = () => {
General
+ Auth
Rate Limit
@@ -203,7 +206,8 @@ export const AdminDashboardPage = () => {
Default organization
- Select the default organization you want to set for SAML/LDAP based logins. When selected, user logins will be automatically scoped to the selected organization.
+ Select the default organization you want to set for SAML/LDAP based logins. When
+ selected, user logins will be automatically scoped to the selected organization.
{
+
+
+
From e1ed37c7135caf3e916bcbd9d56e182bdb44ab4d Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 01:07:28 +0800
Subject: [PATCH 003/145] misc: adjusted OrgSettingsPage and
PersonalSettingsPage to include toggle
---
.../components/OrgAuthTab/OrgAuthTab.tsx | 26 +++++++++++++++----
.../OrgAuthTab/OrgGeneralAuthSection.tsx | 2 +-
.../components/OrgAuthTab/OrgLDAPSection.tsx | 2 +-
.../components/OrgAuthTab/OrgOIDCSection.tsx | 2 +-
.../components/OrgAuthTab/OrgSSOSection.tsx | 3 ++-
.../AuthMethodSection/AuthMethodSection.tsx | 23 +++++++++++-----
6 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx
index 31d6987bd8..b1a079922f 100644
--- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx
+++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx
@@ -1,5 +1,8 @@
-import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
+import { useCallback } from "react";
+
+import { OrgPermissionActions, OrgPermissionSubjects, useServerConfig } from "@app/context";
import { withPermission } from "@app/hoc";
+import { LoginMethod } from "@app/hooks/api/admin/types";
import { OrgGeneralAuthSection } from "./OrgGeneralAuthSection";
import { OrgLDAPSection } from "./OrgLDAPSection";
@@ -9,12 +12,25 @@ import { OrgSSOSection } from "./OrgSSOSection";
export const OrgAuthTab = withPermission(
() => {
+ const {
+ config: { enabledLoginMethods }
+ } = useServerConfig();
+
+ const shouldDisplaySection = useCallback(
+ (method: LoginMethod) => !enabledLoginMethods || enabledLoginMethods.includes(method),
+ [enabledLoginMethods]
+ );
+
return (
-
-
-
-
+ {shouldDisplaySection(LoginMethod.SAML) && (
+ <>
+
+
+ >
+ )}
+ {shouldDisplaySection(LoginMethod.OIDC) && }
+ {shouldDisplaySection(LoginMethod.LDAP) && }
);
diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx
index 7c3af9493f..6e4eca456b 100644
--- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx
+++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx
@@ -11,7 +11,6 @@ import { useLogoutUser, useUpdateOrg } from "@app/hooks/api";
import { usePopUp } from "@app/hooks/usePopUp";
export const OrgGeneralAuthSection = () => {
-
const { currentOrg } = useOrganization();
const { subscription } = useSubscription();
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
@@ -88,6 +87,7 @@ export const OrgGeneralAuthSection = () => {
Enforce members to authenticate via SAML to access this organization
+
handlePopUpToggle("upgradePlan", isOpen)}
diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx
index 87d0f28aff..0d34fcefc0 100644
--- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx
+++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx
@@ -94,7 +94,6 @@ export const OrgLDAPSection = (): JSX.Element => {
return (
<>
-
LDAP
@@ -151,6 +150,7 @@ export const OrgLDAPSection = (): JSX.Element => {
)}
+
{
return (
<>
-
OIDC
@@ -103,6 +102,7 @@ export const OrgOIDCSection = (): JSX.Element => {
)}
+
{
const { currentOrg } = useOrganization();
const { subscription } = useSubscription();
-
+
const { data, isLoading } = useGetSSOConfig(currentOrg?.id ?? "");
const { mutateAsync } = useUpdateSSOConfig();
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
@@ -115,6 +115,7 @@ export const OrgSSOSection = (): JSX.Element => {
Allow members to authenticate into Infisical with SAML
+
;
export const AuthMethodSection = () => {
-
const { user } = useUser();
+ const { config } = useServerConfig();
const { mutateAsync } = useUpdateUserAuthMethods();
const { reset, setValue, watch } = useForm({
@@ -102,6 +103,14 @@ export const AuthMethodSection = () => {
{user &&
authMethodOpts.map((authMethodOpt) => {
+ // only filter when enabledLoginMethods is explicitly configured by admin
+ if (
+ config.enabledLoginMethods &&
+ !config.enabledLoginMethods.includes(authMethodOpt.loginMethod)
+ ) {
+ return null;
+ }
+
return (
From 9daa5badec8657f8fd0b8e3f8f129824e30bcd65 Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 01:15:50 +0800
Subject: [PATCH 004/145] misc: made reusable helper for login page
---
.../components/InitialStep/InitialStep.tsx | 339 +++++++++---------
1 file changed, 165 insertions(+), 174 deletions(-)
diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
index 83615ccf56..d97126f671 100644
--- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
+++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
@@ -62,6 +62,12 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
}
}, []);
+ const shouldDisplayLoginMethod = useCallback(
+ (method: LoginMethod) =>
+ !config.enabledLoginMethods || config.enabledLoginMethods.includes(method),
+ [config]
+ );
+
const handleLogin = async (e: FormEvent) => {
e.preventDefault();
try {
@@ -163,188 +169,173 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
Login to Infisical
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.GOOGLE) && (
-
-
{
- const callbackPort = queryParams.get("callback_port");
+ {shouldDisplayLoginMethod(LoginMethod.GOOGLE) && (
+
+ {
+ const callbackPort = queryParams.get("callback_port");
- window.open(
- `/api/v1/sso/redirect/google${
- callbackPort ? `?callback_port=${callbackPort}` : ""
- }`
- );
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- {t("login.continue-with-google")}
-
-
- ))}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.GITHUB) && (
-
- {
- const callbackPort = queryParams.get("callback_port");
+ window.open(
+ `/api/v1/sso/redirect/google${callbackPort ? `?callback_port=${callbackPort}` : ""}`
+ );
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ {t("login.continue-with-google")}
+
+
+ )}
+ {shouldDisplayLoginMethod(LoginMethod.GITHUB) && (
+
+ {
+ const callbackPort = queryParams.get("callback_port");
- window.open(
- `/api/v1/sso/redirect/github${
- callbackPort ? `?callback_port=${callbackPort}` : ""
- }`
- );
+ window.open(
+ `/api/v1/sso/redirect/github${callbackPort ? `?callback_port=${callbackPort}` : ""}`
+ );
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with GitHub
-
-
- ))}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.GITLAB) && (
-
- {
- const callbackPort = queryParams.get("callback_port");
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with GitHub
+
+
+ )}
+ {shouldDisplayLoginMethod(LoginMethod.GITLAB) && (
+
+ {
+ const callbackPort = queryParams.get("callback_port");
- window.open(
- `/api/v1/sso/redirect/gitlab${
- callbackPort ? `?callback_port=${callbackPort}` : ""
- }`
- );
+ window.open(
+ `/api/v1/sso/redirect/gitlab${callbackPort ? `?callback_port=${callbackPort}` : ""}`
+ );
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with GitLab
-
-
- ))}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.SAML) && (
-
- {
- handleSaml(2);
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with SAML
-
-
- ))}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.OIDC) && (
-
- {
- setStep(3);
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with OIDC
-
-
- ))}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.LDAP) && (
-
- {
- router.push("/login/ldap");
- }}
- leftIcon={ }
- className="mx-0 h-10 w-full"
- >
- Continue with LDAP
-
-
- ))}
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with GitLab
+
+
+ )}
+ {shouldDisplayLoginMethod(LoginMethod.SAML) && (
+
+ {
+ handleSaml(2);
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with SAML
+
+
+ )}
+ {shouldDisplayLoginMethod(LoginMethod.OIDC) && (
+
+ {
+ setStep(3);
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with OIDC
+
+
+ )}
+ {shouldDisplayLoginMethod(LoginMethod.LDAP) && (
+
+ {
+ router.push("/login/ldap");
+ }}
+ leftIcon={ }
+ className="mx-0 h-10 w-full"
+ >
+ Continue with LDAP
+
+
+ )}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.length > 1 &&
- config.enabledLoginMethods.includes(LoginMethod.EMAIL) && (
-
- ))}
- {!config.enabledLoginMethods ||
- (config.enabledLoginMethods.includes(LoginMethod.EMAIL) && (
- <>
-
-
setEmail(e.target.value)}
- type="email"
- placeholder="Enter your email..."
- isRequired
- autoComplete="username"
- className="h-10"
+ {shouldDisplayLoginMethod(LoginMethod.EMAIL) && config.enabledLoginMethods.length > 1 && (
+
+ )}
+ {shouldDisplayLoginMethod(LoginMethod.EMAIL) && (
+ <>
+
+ setEmail(e.target.value)}
+ type="email"
+ placeholder="Enter your email..."
+ isRequired
+ autoComplete="username"
+ className="h-10"
+ />
+
+
+ setPassword(e.target.value)}
+ type="password"
+ placeholder="Enter your password..."
+ isRequired
+ autoComplete="current-password"
+ id="current-password"
+ className="select:-webkit-autofill:focus h-10"
+ />
+
+ {shouldShowCaptcha && (
+
+ setCaptchaToken(token)}
+ ref={captchaRef}
/>
-
- setPassword(e.target.value)}
- type="password"
- placeholder="Enter your password..."
- isRequired
- autoComplete="current-password"
- id="current-password"
- className="select:-webkit-autofill:focus h-10"
- />
-
- {shouldShowCaptcha && (
-
- setCaptchaToken(token)}
- ref={captchaRef}
- />
-
- )}
-
-
- {" "}
- Continue with Email{" "}
-
-
- >
- ))}
+ )}
+
+
+ {" "}
+ Continue with Email{" "}
+
+
+ >
+ )}
{!isLoading && loginError &&
}
{config.allowSignUp ? (
From db39d03713403206725d1e2d0344020ab648074f Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 01:59:02 +0800
Subject: [PATCH 005/145] misc: added check to backend
---
.../src/services/auth/auth-login-service.ts | 35 +++++++++++++++++++
.../components/InitialStep/InitialStep.tsx | 4 +--
2 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts
index 8090b937ab..8207e4bec6 100644
--- a/backend/src/services/auth/auth-login-service.ts
+++ b/backend/src/services/auth/auth-login-service.ts
@@ -17,6 +17,7 @@ import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TokenType } from "../auth-token/auth-token-types";
import { TOrgDALFactory } from "../org/org-dal";
import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service";
+import { LoginMethod } from "../super-admin/super-admin-types";
import { TUserDALFactory } from "../user/user-dal";
import { enforceUserLockStatus, validateProviderAuthToken } from "./auth-fns";
import {
@@ -507,6 +508,40 @@ export const authLoginServiceFactory = ({
let user = await userDAL.findUserByUsername(email);
const serverCfg = await getServerCfg();
+ if (serverCfg.enabledLoginMethods) {
+ switch (authMethod) {
+ case AuthMethod.GITHUB: {
+ if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITHUB)) {
+ throw new BadRequestError({
+ message: "Login with Github is disabled.",
+ name: "Oauth 2 login"
+ });
+ }
+ break;
+ }
+ case AuthMethod.GOOGLE: {
+ if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GOOGLE)) {
+ throw new BadRequestError({
+ message: "Login with Google is disabled.",
+ name: "Oauth 2 login"
+ });
+ }
+ break;
+ }
+ case AuthMethod.GITLAB: {
+ if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITLAB)) {
+ throw new BadRequestError({
+ message: "Login with Gitlab is disabled.",
+ name: "Oauth 2 login"
+ });
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
const appCfg = getConfig();
if (!user) {
diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
index d97126f671..99e80048af 100644
--- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
+++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
@@ -276,8 +276,8 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
)}
-
- {shouldDisplayLoginMethod(LoginMethod.EMAIL) && config.enabledLoginMethods.length > 1 && (
+ {(!config.enabledLoginMethods ||
+ (shouldDisplayLoginMethod(LoginMethod.EMAIL) && config.enabledLoginMethods.length > 1)) && (
or
From c460f226650313ad1ff271d2113829d9cc14966f Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 12:40:56 +0800
Subject: [PATCH 006/145] misc: added backend disable checks
---
.../ee/services/ldap-config/ldap-config-service.ts | 8 ++++++++
backend/src/ee/services/oidc/oidc-config-service.ts | 8 ++++++++
.../ee/services/saml-config/saml-config-service.ts | 8 ++++++++
backend/src/services/auth/auth-login-service.ts | 13 +++++++++++++
4 files changed, 37 insertions(+)
diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts
index 63565d94c2..7434862fc7 100644
--- a/backend/src/ee/services/ldap-config/ldap-config-service.ts
+++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts
@@ -34,6 +34,7 @@ import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal
import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
+import { LoginMethod } from "@app/services/super-admin/super-admin-types";
import { TUserDALFactory } from "@app/services/user/user-dal";
import { normalizeUsername } from "@app/services/user/user-fns";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
@@ -411,6 +412,13 @@ export const ldapConfigServiceFactory = ({
}: TLdapLoginDTO) => {
const appCfg = getConfig();
const serverCfg = await getServerCfg();
+
+ if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.LDAP)) {
+ throw new BadRequestError({
+ message: "Login with LDAP is disabled."
+ });
+ }
+
let userAlias = await userAliasDAL.findOne({
externalId,
orgId,
diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts
index b983492bc2..58b098522c 100644
--- a/backend/src/ee/services/oidc/oidc-config-service.ts
+++ b/backend/src/ee/services/oidc/oidc-config-service.ts
@@ -26,6 +26,7 @@ import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
+import { LoginMethod } from "@app/services/super-admin/super-admin-types";
import { TUserDALFactory } from "@app/services/user/user-dal";
import { normalizeUsername } from "@app/services/user/user-fns";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
@@ -157,6 +158,13 @@ export const oidcConfigServiceFactory = ({
const oidcLogin = async ({ externalId, email, firstName, lastName, orgId, callbackPort }: TOidcLoginDTO) => {
const serverCfg = await getServerCfg();
+
+ if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.OIDC)) {
+ throw new BadRequestError({
+ message: "Login with OIDC is disabled."
+ });
+ }
+
const appCfg = getConfig();
const userAlias = await userAliasDAL.findOne({
externalId,
diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts
index 3cc51e1c20..286a85746d 100644
--- a/backend/src/ee/services/saml-config/saml-config-service.ts
+++ b/backend/src/ee/services/saml-config/saml-config-service.ts
@@ -28,6 +28,7 @@ import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
+import { LoginMethod } from "@app/services/super-admin/super-admin-types";
import { TUserDALFactory } from "@app/services/user/user-dal";
import { normalizeUsername } from "@app/services/user/user-fns";
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
@@ -335,6 +336,13 @@ export const samlConfigServiceFactory = ({
}: TSamlLoginDTO) => {
const appCfg = getConfig();
const serverCfg = await getServerCfg();
+
+ if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.SAML)) {
+ throw new BadRequestError({
+ message: "Login with SAML is disabled."
+ });
+ }
+
const userAlias = await userAliasDAL.findOne({
externalId,
orgId,
diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts
index 8207e4bec6..24ae087b7a 100644
--- a/backend/src/services/auth/auth-login-service.ts
+++ b/backend/src/services/auth/auth-login-service.ts
@@ -159,9 +159,22 @@ export const authLoginServiceFactory = ({
const userEnc = await userDAL.findUserEncKeyByUsername({
username: email
});
+ const serverCfg = await getServerCfg();
+
+ if (
+ serverCfg.enabledLoginMethods &&
+ !serverCfg.enabledLoginMethods.includes(LoginMethod.EMAIL) &&
+ !providerAuthToken
+ ) {
+ throw new BadRequestError({
+ message: "Login with email is disabled."
+ });
+ }
+
if (!userEnc || (userEnc && !userEnc.isAccepted)) {
throw new Error("Failed to find user");
}
+
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) {
validateProviderAuthToken(providerAuthToken as string, email);
}
From b3463e0d0fe563ccc8f5c4a744aaf618d1c0020f Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 12:55:39 +0800
Subject: [PATCH 007/145] misc: added explicit comment of intent
---
frontend/src/views/admin/DashboardPage/AuthPanel.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
index 0060cb095a..f2fab83ec1 100644
--- a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
+++ b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
@@ -31,6 +31,7 @@ export const AuthPanel = () => {
formState: { isSubmitting, isDirty }
} = useForm({
resolver: zodResolver(formSchema),
+ // if not yet explicitly defined by the admin, all login methods should be enabled by default
values: enabledLoginMethods
? {
isEmailEnabled: enabledLoginMethods.includes(LoginMethod.EMAIL),
From 92a663a17d3f1f3879ea45e3c80d1778148c041c Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 13:24:26 +0800
Subject: [PATCH 008/145] misc: design change to finalize scim section in org
settings
---
.../OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx
index 601643db80..ffec3f3558 100644
--- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx
+++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx
@@ -13,7 +13,6 @@ import { usePopUp } from "@app/hooks/usePopUp";
import { ScimTokenModal } from "./ScimTokenModal";
export const OrgScimSection = () => {
-
const { currentOrg } = useOrganization();
const { subscription } = useSubscription();
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
@@ -59,7 +58,6 @@ export const OrgScimSection = () => {
return (
<>
-
SCIM
From d6881e2e6831429ded24526e21ff210812e71af9 Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Thu, 27 Jun 2024 13:53:12 +0800
Subject: [PATCH 009/145] misc: added signup option filtering
---
.../components/signup/InitialSignupStep.tsx | 129 ++++++++++--------
1 file changed, 74 insertions(+), 55 deletions(-)
diff --git a/frontend/src/components/signup/InitialSignupStep.tsx b/frontend/src/components/signup/InitialSignupStep.tsx
index e5c23f3334..8df6759132 100644
--- a/frontend/src/components/signup/InitialSignupStep.tsx
+++ b/frontend/src/components/signup/InitialSignupStep.tsx
@@ -1,9 +1,13 @@
+import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import Link from "next/link";
import { faGithub, faGitlab, faGoogle } from "@fortawesome/free-brands-svg-icons";
import { faEnvelope } from "@fortawesome/free-regular-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useServerConfig } from "@app/context";
+import { LoginMethod } from "@app/hooks/api/admin/types";
+
import { Button } from "../v2";
export default function InitialSignupStep({
@@ -12,67 +16,82 @@ export default function InitialSignupStep({
setIsSignupWithEmail: (value: boolean) => void;
}) {
const { t } = useTranslation();
+ const { config } = useServerConfig();
+
+ const shouldDisplaySignupMethod = useCallback(
+ (method: LoginMethod) =>
+ !config.enabledLoginMethods || config.enabledLoginMethods.includes(method),
+ [config]
+ );
return (
{t("signup.initial-title")}
-
- {
- window.open("/api/v1/sso/redirect/google");
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-12 w-full"
- >
- {t("signup.continue-with-google")}
-
-
-
- {
- window.open("/api/v1/sso/redirect/github");
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-12 w-full"
- >
- Continue with GitHub
-
-
-
- {
- window.open("/api/v1/sso/redirect/gitlab");
- window.close();
- }}
- leftIcon={ }
- className="mx-0 h-12 w-full"
- >
- Continue with GitLab
-
-
-
- {
- setIsSignupWithEmail(true);
- }}
- leftIcon={ }
- className="mx-0 h-12 w-full"
- >
- Continue with Email
-
-
+ {shouldDisplaySignupMethod(LoginMethod.GOOGLE) && (
+
+ {
+ window.open("/api/v1/sso/redirect/google");
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-12 w-full"
+ >
+ {t("signup.continue-with-google")}
+
+
+ )}
+ {shouldDisplaySignupMethod(LoginMethod.GITHUB) && (
+
+ {
+ window.open("/api/v1/sso/redirect/github");
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-12 w-full"
+ >
+ Continue with GitHub
+
+
+ )}
+ {shouldDisplaySignupMethod(LoginMethod.GITLAB) && (
+
+ {
+ window.open("/api/v1/sso/redirect/gitlab");
+ window.close();
+ }}
+ leftIcon={ }
+ className="mx-0 h-12 w-full"
+ >
+ Continue with GitLab
+
+
+ )}
+ {shouldDisplaySignupMethod(LoginMethod.EMAIL) && (
+
+ {
+ setIsSignupWithEmail(true);
+ }}
+ leftIcon={ }
+ className="mx-0 h-12 w-full"
+ >
+ Continue with Email
+
+
+ )}
{t("signup.create-policy")}
From 59fc34412dde33add0068a73d2e93af344e3bdbe Mon Sep 17 00:00:00 2001
From: Maidul Islam
Date: Thu, 27 Jun 2024 20:35:15 -0400
Subject: [PATCH 010/145] small nits for admin login toggle pr
---
.../src/ee/services/ldap-config/ldap-config-service.ts | 2 +-
backend/src/ee/services/oidc/oidc-config-service.ts | 2 +-
.../src/ee/services/saml-config/saml-config-service.ts | 2 +-
backend/src/services/auth/auth-login-service.ts | 8 ++++----
frontend/src/views/admin/DashboardPage/AuthPanel.tsx | 2 +-
frontend/src/views/admin/DashboardPage/DashboardPage.tsx | 4 ++--
6 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts
index 7434862fc7..55129ca025 100644
--- a/backend/src/ee/services/ldap-config/ldap-config-service.ts
+++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts
@@ -415,7 +415,7 @@ export const ldapConfigServiceFactory = ({
if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.LDAP)) {
throw new BadRequestError({
- message: "Login with LDAP is disabled."
+ message: "Login with LDAP is disabled by administrator."
});
}
diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts
index 58b098522c..55c929b9a9 100644
--- a/backend/src/ee/services/oidc/oidc-config-service.ts
+++ b/backend/src/ee/services/oidc/oidc-config-service.ts
@@ -161,7 +161,7 @@ export const oidcConfigServiceFactory = ({
if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.OIDC)) {
throw new BadRequestError({
- message: "Login with OIDC is disabled."
+ message: "Login with OIDC is disabled by administrator."
});
}
diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts
index 286a85746d..9ac6c9c5ed 100644
--- a/backend/src/ee/services/saml-config/saml-config-service.ts
+++ b/backend/src/ee/services/saml-config/saml-config-service.ts
@@ -339,7 +339,7 @@ export const samlConfigServiceFactory = ({
if (serverCfg.enabledLoginMethods && !serverCfg.enabledLoginMethods.includes(LoginMethod.SAML)) {
throw new BadRequestError({
- message: "Login with SAML is disabled."
+ message: "Login with SAML is disabled by administrator."
});
}
diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts
index 24ae087b7a..2ce900b471 100644
--- a/backend/src/services/auth/auth-login-service.ts
+++ b/backend/src/services/auth/auth-login-service.ts
@@ -167,7 +167,7 @@ export const authLoginServiceFactory = ({
!providerAuthToken
) {
throw new BadRequestError({
- message: "Login with email is disabled."
+ message: "Login with email is disabled by administrator."
});
}
@@ -526,7 +526,7 @@ export const authLoginServiceFactory = ({
case AuthMethod.GITHUB: {
if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITHUB)) {
throw new BadRequestError({
- message: "Login with Github is disabled.",
+ message: "Login with Github is disabled by administrator.",
name: "Oauth 2 login"
});
}
@@ -535,7 +535,7 @@ export const authLoginServiceFactory = ({
case AuthMethod.GOOGLE: {
if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GOOGLE)) {
throw new BadRequestError({
- message: "Login with Google is disabled.",
+ message: "Login with Google is disabled by administrator.",
name: "Oauth 2 login"
});
}
@@ -544,7 +544,7 @@ export const authLoginServiceFactory = ({
case AuthMethod.GITLAB: {
if (!serverCfg.enabledLoginMethods.includes(LoginMethod.GITLAB)) {
throw new BadRequestError({
- message: "Login with Gitlab is disabled.",
+ message: "Login with Gitlab is disabled by administrator.",
name: "Oauth 2 login"
});
}
diff --git a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
index f2fab83ec1..84e48ea0f6 100644
--- a/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
+++ b/frontend/src/views/admin/DashboardPage/AuthPanel.tsx
@@ -117,7 +117,7 @@ export const AuthPanel = () => {
Login Methods
- Select the login methods available to users
+ Select the login methods you wish to allow for all users of this instance.
{
Admin Dashboard
-
Manage your Infisical instance.
+
Manage your instance level configurations.
{isUserLoading || isNotAllowed ? (
@@ -133,7 +133,7 @@ export const AdminDashboardPage = () => {
General
- Auth
+ Authentication
Rate Limit
From 04f54479cd6a968f2fd1e6e5bcc5459ddfa98fbd Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Sat, 29 Jun 2024 01:58:27 +0800
Subject: [PATCH 011/145] misc: implemented review comments
---
backend/src/server/routes/v1/admin-router.ts | 2 +-
.../super-admin/super-admin-service.ts | 37 +++++++++++++++++--
.../components/InitialStep/InitialStep.tsx | 6 ++-
3 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts
index 4557152bdb..73d6cc7e78 100644
--- a/backend/src/server/routes/v1/admin-router.ts
+++ b/backend/src/server/routes/v1/admin-router.ts
@@ -78,7 +78,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
});
},
handler: async (req) => {
- const config = await server.services.superAdmin.updateServerCfg(req.body);
+ const config = await server.services.superAdmin.updateServerCfg(req.body, req.permission.id);
return { config };
}
});
diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts
index 41b97efa42..a51282db6f 100644
--- a/backend/src/services/super-admin/super-admin-service.ts
+++ b/backend/src/services/super-admin/super-admin-service.ts
@@ -12,7 +12,7 @@ import { AuthMethod } from "../auth/auth-type";
import { TOrgServiceFactory } from "../org/org-service";
import { TUserDALFactory } from "../user/user-dal";
import { TSuperAdminDALFactory } from "./super-admin-dal";
-import { TAdminSignUpDTO } from "./super-admin-types";
+import { LoginMethod, TAdminSignUpDTO } from "./super-admin-types";
type TSuperAdminServiceFactoryDep = {
serverCfgDAL: TSuperAdminDALFactory;
@@ -79,7 +79,38 @@ export const superAdminServiceFactory = ({
return newCfg;
};
- const updateServerCfg = async (data: TSuperAdminUpdate) => {
+ const updateServerCfg = async (data: TSuperAdminUpdate, userId: string) => {
+ if (data.enabledLoginMethods) {
+ const superAdminUser = await userDAL.findById(userId);
+ const loginMethodToAuthMethod = {
+ [LoginMethod.EMAIL]: [AuthMethod.EMAIL],
+ [LoginMethod.GOOGLE]: [AuthMethod.GOOGLE],
+ [LoginMethod.GITLAB]: [AuthMethod.GITLAB],
+ [LoginMethod.GITHUB]: [AuthMethod.GITHUB],
+ [LoginMethod.LDAP]: [AuthMethod.LDAP],
+ [LoginMethod.OIDC]: [AuthMethod.OIDC],
+ [LoginMethod.SAML]: [
+ AuthMethod.AZURE_SAML,
+ AuthMethod.GOOGLE_SAML,
+ AuthMethod.JUMPCLOUD_SAML,
+ AuthMethod.KEYCLOAK_SAML,
+ AuthMethod.OKTA_SAML
+ ]
+ };
+
+ if (
+ !data.enabledLoginMethods.some((loginMethod) =>
+ loginMethodToAuthMethod[loginMethod as LoginMethod].some(
+ (authMethod) => superAdminUser.authMethods?.includes(authMethod)
+ )
+ )
+ ) {
+ throw new BadRequestError({
+ message:
+ "Admin has insufficient authentication methods for update operation to complete without getting locked out."
+ });
+ }
+ }
const updatedServerCfg = await serverCfgDAL.updateById(ADMIN_CONFIG_DB_UUID, data);
await keyStore.setItemWithExpiry(ADMIN_CONFIG_KEY, ADMIN_CONFIG_KEY_EXP, JSON.stringify(updatedServerCfg));
@@ -167,7 +198,7 @@ export const superAdminServiceFactory = ({
orgName: initialOrganizationName
});
- await updateServerCfg({ initialized: true });
+ await updateServerCfg({ initialized: true }, userInfo.user.id);
const token = await authService.generateUserTokens({
user: userInfo.user,
authMethod: AuthMethod.EMAIL,
diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
index 99e80048af..69a4188270 100644
--- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
+++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
@@ -337,7 +337,11 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
>
)}
{!isLoading && loginError && }
- {config.allowSignUp ? (
+ {config.allowSignUp &&
+ (shouldDisplayLoginMethod(LoginMethod.EMAIL) ||
+ shouldDisplayLoginMethod(LoginMethod.GOOGLE) ||
+ shouldDisplayLoginMethod(LoginMethod.GITHUB) ||
+ shouldDisplayLoginMethod(LoginMethod.GITLAB)) ? (
From 5a1e43be4448fe2d1b069a9338a701414ae521c4 Mon Sep 17 00:00:00 2001
From: Sheen Capadngan
Date: Sat, 29 Jun 2024 02:12:09 +0800
Subject: [PATCH 012/145] misc: only display recover when email login is
enabled
---
.../Login/components/InitialStep/InitialStep.tsx | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
index 69a4188270..06c4df835b 100644
--- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
+++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx
@@ -352,13 +352,15 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
) : (
)}
-
-
-
- Forgot password? Recover your account
-
-
-
+ {shouldDisplayLoginMethod(LoginMethod.EMAIL) && (
+
+
+
+ Forgot password? Recover your account
+
+
+
+ )}
);
};
From ae953add3d9d8925d837cc5edf500e7acd2140ba Mon Sep 17 00:00:00 2001
From: =
Date: Tue, 2 Jul 2024 00:12:38 +0530
Subject: [PATCH 013/145] feat: dynamic secret for mssql completed
---
backend/package-lock.json | 512 ++++++++++++++++++
backend/package.json | 1 +
.../dynamic-secret/providers/models.ts | 3 +-
frontend/src/hooks/api/dynamicSecret/types.ts | 3 +-
.../SqlDatabaseInputForm.tsx | 37 +-
.../EditDynamicSecretSqlProviderForm.tsx | 1 +
6 files changed, 550 insertions(+), 7 deletions(-)
diff --git a/backend/package-lock.json b/backend/package-lock.json
index 220d4305ca..20a5f7c21c 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -73,6 +73,7 @@
"posthog-node": "^3.6.2",
"probot": "^13.0.0",
"smee-client": "^2.0.0",
+ "tedious": "^18.2.1",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
"uuid": "^9.0.1",
@@ -2910,6 +2911,351 @@
"tslib": "^2.3.1"
}
},
+ "node_modules/@azure/abort-controller": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
+ "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==",
+ "dependencies": {
+ "tslib": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@azure/core-auth": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.2.tgz",
+ "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-util": "^1.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-client": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz",
+ "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-auth": "^1.4.0",
+ "@azure/core-rest-pipeline": "^1.9.1",
+ "@azure/core-tracing": "^1.0.0",
+ "@azure/core-util": "^1.6.1",
+ "@azure/logger": "^1.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-client/node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-http-compat": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.1.2.tgz",
+ "integrity": "sha512-5MnV1yqzZwgNLLjlizsU3QqOeQChkIXw781Fwh1xdAqJR5AA32IUaq6xv1BICJvfbHoa+JYcaij2HFkhLbNTJQ==",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-client": "^1.3.0",
+ "@azure/core-rest-pipeline": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-http-compat/node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-lro": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz",
+ "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-util": "^1.2.0",
+ "@azure/logger": "^1.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-lro/node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-paging": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz",
+ "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.1.tgz",
+ "integrity": "sha512-ExPSbgjwCoht6kB7B4MeZoBAxcQSIl29r/bPeazZJx50ej4JJCByimLOrZoIsurISNyJQQHf30b3JfqC3Hb88A==",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-auth": "^1.4.0",
+ "@azure/core-tracing": "^1.0.1",
+ "@azure/core-util": "^1.9.0",
+ "@azure/logger": "^1.0.0",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/debug": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/@azure/core-tracing": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz",
+ "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-util": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.0.tgz",
+ "integrity": "sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-util/node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/identity": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.3.0.tgz",
+ "integrity": "sha512-LHZ58/RsIpIWa4hrrE2YuJ/vzG1Jv9f774RfTTAVDZDriubvJ0/S5u4pnw4akJDlS0TiJb6VMphmVUFsWmgodQ==",
+ "dependencies": {
+ "@azure/abort-controller": "^1.0.0",
+ "@azure/core-auth": "^1.5.0",
+ "@azure/core-client": "^1.9.2",
+ "@azure/core-rest-pipeline": "^1.1.0",
+ "@azure/core-tracing": "^1.0.0",
+ "@azure/core-util": "^1.3.0",
+ "@azure/logger": "^1.0.0",
+ "@azure/msal-browser": "^3.11.1",
+ "@azure/msal-node": "^2.9.2",
+ "events": "^3.0.0",
+ "jws": "^4.0.0",
+ "open": "^8.0.0",
+ "stoppable": "^1.1.0",
+ "tslib": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/identity/node_modules/jwa": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
+ "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
+ "dependencies": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/@azure/identity/node_modules/jws": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
+ "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
+ "dependencies": {
+ "jwa": "^2.0.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/@azure/keyvault-keys": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.8.0.tgz",
+ "integrity": "sha512-jkuYxgkw0aaRfk40OQhFqDIupqblIOIlYESWB6DKCVDxQet1pyv86Tfk9M+5uFM0+mCs6+MUHU+Hxh3joiUn4Q==",
+ "dependencies": {
+ "@azure/abort-controller": "^1.0.0",
+ "@azure/core-auth": "^1.3.0",
+ "@azure/core-client": "^1.5.0",
+ "@azure/core-http-compat": "^2.0.1",
+ "@azure/core-lro": "^2.2.0",
+ "@azure/core-paging": "^1.1.1",
+ "@azure/core-rest-pipeline": "^1.8.1",
+ "@azure/core-tracing": "^1.0.0",
+ "@azure/core-util": "^1.0.0",
+ "@azure/logger": "^1.0.0",
+ "tslib": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/logger": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.2.tgz",
+ "integrity": "sha512-l170uE7bsKpIU6B/giRc9i4NI0Mj+tANMMMxf7Zi/5cKzEqPayP7+X1WPrG7e+91JgY8N+7K7nF2WOi7iVhXvg==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/msal-browser": {
+ "version": "3.17.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.17.0.tgz",
+ "integrity": "sha512-csccKXmW2z7EkZ0I3yAoW/offQt+JECdTIV/KrnRoZyM7wCSsQWODpwod8ZhYy7iOyamcHApR9uCh0oD1M+0/A==",
+ "dependencies": {
+ "@azure/msal-common": "14.12.0"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@azure/msal-common": {
+ "version": "14.12.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.12.0.tgz",
+ "integrity": "sha512-IDDXmzfdwmDkv4SSmMEyAniJf6fDu3FJ7ncOjlxkDuT85uSnLEhZi3fGZpoR7T4XZpOMx9teM9GXBgrfJgyeBw==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@azure/msal-node": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.9.2.tgz",
+ "integrity": "sha512-8tvi6Cos3m+0KmRbPjgkySXi+UQU/QiuVRFnrxIwt5xZlEEFa69O04RTaNESGgImyBBlYbo2mfE8/U8Bbdk1WQ==",
+ "dependencies": {
+ "@azure/msal-common": "14.12.0",
+ "jsonwebtoken": "^9.0.0",
+ "uuid": "^8.3.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@azure/msal-node/node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/@casl/ability": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@casl/ability/-/ability-6.5.0.tgz",
@@ -3733,6 +4079,11 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
+ "node_modules/@js-joda/core": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.3.tgz",
+ "integrity": "sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA=="
+ },
"node_modules/@ldapjs/asn1": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ldapjs/asn1/-/asn1-2.0.0.tgz",
@@ -6194,6 +6545,20 @@
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
},
+ "node_modules/@types/readable-stream": {
+ "version": "4.0.14",
+ "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.14.tgz",
+ "integrity": "sha512-xZn/AuUbCMShGsqH/ehZtGDwQtbx00M9rZ2ENLe4tOjFZ/JFeWMhEZkk2fEe1jAUqqEAURIkFJ7Az/go8mM1/w==",
+ "dependencies": {
+ "@types/node": "*",
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "node_modules/@types/readable-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
"node_modules/@types/resolve": {
"version": "1.20.6",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz",
@@ -8015,6 +8380,14 @@
"node": ">= 0.4"
}
},
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
@@ -10145,6 +10518,50 @@
"node": ">= 0.8"
}
},
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/debug": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
@@ -10464,6 +10881,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -10686,6 +11117,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -10740,6 +11182,11 @@
"node": ">=10"
}
},
+ "node_modules/js-md4": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz",
+ "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA=="
+ },
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -11665,6 +12112,11 @@
"node": "^18 || >=20"
}
},
+ "node_modules/native-duplexpair": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz",
+ "integrity": "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -12046,6 +12498,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/openapi-types": {
"version": "12.1.3",
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
@@ -13823,6 +14291,11 @@
"node": ">= 10.x"
}
},
+ "node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ },
"node_modules/sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
@@ -13870,6 +14343,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/stoppable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
+ "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==",
+ "engines": {
+ "node": ">=4",
+ "npm": ">=6"
+ }
+ },
"node_modules/stream-shift": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
@@ -14192,6 +14674,36 @@
"node": ">=8.0.0"
}
},
+ "node_modules/tedious": {
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/tedious/-/tedious-18.2.1.tgz",
+ "integrity": "sha512-DKsTgGBC0ZeZexAd5OObfeKd0Tlx3jx3kNoKImsxfBKdRuV216u9n6Sr+4w6vzn+S4r43XmWAXQwM7UkDkbIEg==",
+ "dependencies": {
+ "@azure/identity": "^4.2.1",
+ "@azure/keyvault-keys": "^4.4.0",
+ "@js-joda/core": "^5.6.1",
+ "@types/node": ">=18",
+ "bl": "^6.0.11",
+ "iconv-lite": "^0.6.3",
+ "js-md4": "^0.3.2",
+ "native-duplexpair": "^1.0.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tedious/node_modules/bl": {
+ "version": "6.0.13",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.13.tgz",
+ "integrity": "sha512-tMncAcpsyjZgAVbVFupVIaB2xud13xxT59fdHkuszY2jdZkqIWfpQdmII1fOe3kOGAz0mNLTIHEm+KxpYsQKKg==",
+ "dependencies": {
+ "@types/readable-stream": "^4.0.0",
+ "buffer": "^6.0.3",
+ "inherits": "^2.0.4",
+ "readable-stream": "^4.2.0"
+ }
+ },
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
diff --git a/backend/package.json b/backend/package.json
index 6ef9add0df..b278be571c 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -134,6 +134,7 @@
"posthog-node": "^3.6.2",
"probot": "^13.0.0",
"smee-client": "^2.0.0",
+ "tedious": "^18.2.1",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
"uuid": "^9.0.1",
diff --git a/backend/src/ee/services/dynamic-secret/providers/models.ts b/backend/src/ee/services/dynamic-secret/providers/models.ts
index c11f6ddfb3..14b79eeea7 100644
--- a/backend/src/ee/services/dynamic-secret/providers/models.ts
+++ b/backend/src/ee/services/dynamic-secret/providers/models.ts
@@ -3,7 +3,8 @@ import { z } from "zod";
export enum SqlProviders {
Postgres = "postgres",
MySQL = "mysql2",
- Oracle = "oracledb"
+ Oracle = "oracledb",
+ MsSQL = "mssql"
}
export const DynamicSecretSqlDBSchema = z.object({
diff --git a/frontend/src/hooks/api/dynamicSecret/types.ts b/frontend/src/hooks/api/dynamicSecret/types.ts
index a9aab83183..b987e94cc9 100644
--- a/frontend/src/hooks/api/dynamicSecret/types.ts
+++ b/frontend/src/hooks/api/dynamicSecret/types.ts
@@ -24,7 +24,8 @@ export enum DynamicSecretProviders {
export enum SqlProviders {
Postgres = "postgres",
MySql = "mysql2",
- Oracle = "oracledb"
+ Oracle = "oracledb",
+ MsSQL = "mssql"
}
export type TDynamicSecretProvider =
diff --git a/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx b/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx
index 0910e137eb..6d92641c66 100644
--- a/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx
+++ b/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx
@@ -86,6 +86,14 @@ const getSqlStatements = (provider: SqlProviders) => {
'REVOKE CONNECT FROM "{{username}}";\nREVOKE CREATE SESSION FROM "{{username}}";\nDROP USER "{{username}}";'
};
}
+ if (provider === SqlProviders.MsSQL) {
+ return {
+ creationStatement:
+ "CREATE LOGIN [{{username}}] WITH PASSWORD = '{{password}}';\nCREATE USER [{{username}}] FOR LOGIN [{{username}}];\nGRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo TO [{{username}}];",
+ renewStatement: "",
+ revocationStatement: "DROP USER [{{username}}];\nDROP LOGIN [{{username}}];"
+ };
+ }
return {
creationStatement:
@@ -96,6 +104,19 @@ const getSqlStatements = (provider: SqlProviders) => {
};
};
+const getDefaultPort = (provider: SqlProviders) => {
+ switch (provider) {
+ case SqlProviders.MySql:
+ return 3306;
+ case SqlProviders.Oracle:
+ return 1521;
+ case SqlProviders.MsSQL:
+ return 1433;
+ default:
+ return 5432;
+ }
+};
+
export const SqlDatabaseInputForm = ({
onCompleted,
onCancel,
@@ -139,6 +160,14 @@ export const SqlDatabaseInputForm = ({
}
};
+ const handleDatabaseChange = (type: SqlProviders) => {
+ const sqlStatment = getSqlStatements(type);
+ setValue("provider.creationStatement", sqlStatment.creationStatement);
+ setValue("provider.renewStatement", sqlStatment.renewStatement);
+ setValue("provider.revocationStatement", sqlStatment.revocationStatement);
+ setValue("provider.port", getDefaultPort(type));
+ };
+
return (