Merge remote-tracking branch 'origin/main' into feat/acme-and-external-ca

This commit is contained in:
Sheen Capadngan
2025-05-21 19:21:12 +08:00
100 changed files with 3043 additions and 913 deletions
+6 -3
View File
@@ -2126,7 +2126,7 @@ export const AppConnections = {
LDAP: {
provider: "The type of LDAP provider. Determines provider-specific behaviors.",
url: "The LDAP/LDAPS URL to connect to (e.g., 'ldap://domain-or-ip:389' or 'ldaps://domain-or-ip:636').",
dn: "The Distinguished Name (DN) of the principal to bind with (e.g., 'CN=John,CN=Users,DC=example,DC=com').",
dn: "The Distinguished Name (DN) or User Principal Name (UPN) of the principal to bind with (e.g., 'CN=John,CN=Users,DC=example,DC=com').",
password: "The password to bind with for authentication.",
sslRejectUnauthorized:
"Whether or not to reject unauthorized SSL certificates (true/false) when using ldaps://. Set to false only in test environments.",
@@ -2371,7 +2371,10 @@ export const SecretRotations = {
clientId: "The client ID of the Azure Application to rotate the client secret for."
},
LDAP_PASSWORD: {
dn: "The Distinguished Name (DN) of the principal to rotate the password for."
dn: "The Distinguished Name (DN) or User Principal Name (UPN) of the principal to rotate the password for.",
rotationMethod:
'Whether the rotation should be performed by the LDAP "connection-principal" or the "target-principal" (defaults to \'connection-principal\').',
password: 'The password of the provided principal if "parameters.rotationMethod" is set to "target-principal".'
},
GENERAL: {
PASSWORD_REQUIREMENTS: {
@@ -2405,7 +2408,7 @@ export const SecretRotations = {
clientSecret: "The name of the secret that the rotated client secret will be mapped to."
},
LDAP_PASSWORD: {
dn: "The name of the secret that the Distinguished Name (DN) of the principal will be mapped to.",
dn: "The name of the secret that the Distinguished Name (DN) or User Principal Name (UPN) of the principal will be mapped to.",
password: "The name of the secret that the rotated password will be mapped to."
},
AWS_IAM_USER_SECRET: {
+22 -4
View File
@@ -1,6 +1,8 @@
import { Knex } from "knex";
import { Compare, Filter, parse } from "scim2-parse-filter";
import { TableName } from "@app/db/schemas";
const appendParentToGroupingOperator = (parentPath: string, filter: Filter) => {
if (filter.op !== "[]" && filter.op !== "and" && filter.op !== "or" && filter.op !== "not") {
return { ...filter, attrPath: `${parentPath}.${(filter as Compare).attrPath}` };
@@ -27,8 +29,12 @@ const processDynamicQuery = (
const { scimFilterAst, query } = stack.pop()!;
switch (scimFilterAst.op) {
case "eq": {
let sanitizedValue = scimFilterAst.compValue;
const attrPath = getAttributeField(scimFilterAst.attrPath);
if (attrPath) void query.where(attrPath, scimFilterAst.compValue);
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
sanitizedValue = sanitizedValue.toLowerCase();
}
if (attrPath) void query.where(attrPath, sanitizedValue);
break;
}
case "pr": {
@@ -62,18 +68,30 @@ const processDynamicQuery = (
break;
}
case "ew": {
let sanitizedValue = scimFilterAst.compValue;
const attrPath = getAttributeField(scimFilterAst.attrPath);
if (attrPath) void query.whereILike(attrPath, `%${scimFilterAst.compValue}`);
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
sanitizedValue = sanitizedValue.toLowerCase();
}
if (attrPath) void query.whereILike(attrPath, `%${sanitizedValue}`);
break;
}
case "co": {
let sanitizedValue = scimFilterAst.compValue;
const attrPath = getAttributeField(scimFilterAst.attrPath);
if (attrPath) void query.whereILike(attrPath, `%${scimFilterAst.compValue}%`);
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
sanitizedValue = sanitizedValue.toLowerCase();
}
if (attrPath) void query.whereILike(attrPath, `%${sanitizedValue}%`);
break;
}
case "ne": {
let sanitizedValue = scimFilterAst.compValue;
const attrPath = getAttributeField(scimFilterAst.attrPath);
if (attrPath) void query.whereNot(attrPath, "=", scimFilterAst.compValue);
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
sanitizedValue = sanitizedValue.toLowerCase();
}
if (attrPath) void query.whereNot(attrPath, "=", sanitizedValue);
break;
}
case "and": {
+9 -1
View File
@@ -1,3 +1,11 @@
import RE2 from "re2";
export const DistinguishedNameRegex =
// DN format, ie; CN=user,OU=users,DC=example,DC=com
/^(?:(?:[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)(?:(?:\\+[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)*)(?:,(?:[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)(?:(?:\\+[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)*))*)?$/;
new RE2(
/^(?:(?:[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)(?:(?:\\+[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)*)(?:,(?:[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)(?:(?:\\+[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)*))*)?$/
);
export const UserPrincipalNameRegex = new RE2(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}$/);
export const LdapUrlRegex = new RE2(/^ldaps?:\/\//);