improvements: final feedback and ssl enforcement

This commit is contained in:
Scott Wilson
2025-04-04 13:28:01 -07:00
parent cd333a7923
commit 06fc4e955d
9 changed files with 52 additions and 24 deletions

View File

@@ -28,6 +28,7 @@ export async function up(knex: Knex): Promise<void> {
t.binary("encryptedLastRotationMessage"); // we encrypt this because it may contain sensitive info (SQL errors showing credentials)
t.string("lastRotationJobId");
t.datetime("nextRotationAt");
t.boolean("isLastRotationManual").notNullable().defaultTo(true); // creation is considered a "manual" rotation
});
await createOnUpdateTrigger(knex, TableName.SecretRotationV2);

View File

@@ -23,10 +23,10 @@ export const OrganizationsSchema = z.object({
defaultMembershipRole: z.string().default("member"),
enforceMfa: z.boolean().default(false),
selectedMfaMethod: z.string().nullable().optional(),
allowSecretSharingOutsideOrganization: z.boolean().default(true).nullable().optional(),
shouldUseNewPrivilegeSystem: z.boolean().default(true),
privilegeUpgradeInitiatedByUsername: z.string().nullable().optional(),
privilegeUpgradeInitiatedAt: z.date().nullable().optional(),
allowSecretSharingOutsideOrganization: z.boolean().default(true).nullable().optional()
privilegeUpgradeInitiatedAt: z.date().nullable().optional()
});
export type TOrganizations = z.infer<typeof OrganizationsSchema>;

View File

@@ -30,7 +30,8 @@ export const SecretRotationsV2Schema = z.object({
lastRotatedAt: z.date(),
encryptedLastRotationMessage: zodBuffer.nullable().optional(),
lastRotationJobId: z.string().nullable().optional(),
nextRotationAt: z.date().nullable().optional()
nextRotationAt: z.date().nullable().optional(),
isLastRotationManual: z.boolean().default(true)
});
export type TSecretRotationsV2 = z.infer<typeof SecretRotationsV2Schema>;

View File

@@ -597,7 +597,7 @@ export const secretRotationV2ServiceFactory = ({
const nextRotationAt = calculateNextRotationAt({
...(secretRotation as TSecretRotationV2),
...payload,
isManualRotation: false
isManualRotation: secretRotation.isLastRotationManual
});
let secretsMappingUpdated = false;
@@ -892,6 +892,7 @@ export const secretRotationV2ServiceFactory = ({
{
encryptedGeneratedCredentials: encryptedUpdatedCredentials,
activeIndex: inactiveIndex,
isLastRotationManual: isManualRotation,
lastRotatedAt: currentTime,
lastRotationAttemptedAt: currentTime,
nextRotationAt: calculateNextRotationAt({

View File

@@ -60,6 +60,7 @@ const envSchema = z
HTTPS_ENABLED: zodStrBool,
ROTATION_DEVELOPMENT_MODE: zodStrBool.default("false").optional(),
DB_SSL_REJECT_UNAUTHORIZED: zodStrBool.default("true"),
DB_SSL_REQUIRED: zodStrBool.default("true"),
// smtp options
SMTP_HOST: zpStr(z.string().optional()),
SMTP_IGNORE_TLS: zodStrBool.default("false"),

View File

@@ -19,18 +19,46 @@ const SQL_CONNECTION_CLIENT_MAP = {
[AppConnection.MsSql]: "mssql"
};
export const getSqlConnectionClient = async (appConnection: Pick<TSqlConnection, "credentials" | "app">) => {
const getConnectionConfig = ({
app,
credentials: { sslCertificate, host }
}: Pick<TSqlConnection, "credentials" | "app">) => {
const appCfg = getConfig();
switch (app) {
case AppConnection.Postgres: {
return {
ssl: appCfg.DB_SSL_REQUIRED
? {
rejectUnauthorized: appCfg.DB_SSL_REJECT_UNAUTHORIZED,
ca: sslCertificate,
servername: host
}
: false
};
}
case AppConnection.MsSql: {
return {
options: appCfg.DB_SSL_REQUIRED
? {
trustServerCertificate: !appCfg.DB_SSL_REJECT_UNAUTHORIZED,
encrypt: true,
cryptoCredentialsDetails: sslCertificate ? { ca: sslCertificate } : {}
}
: undefined
};
}
default:
throw new Error(`Unhandled SQL Connection Config: ${app as AppConnection}`);
}
};
export const getSqlConnectionClient = async (appConnection: Pick<TSqlConnection, "credentials" | "app">) => {
const {
app,
credentials: { host: baseHost, database, port, sslCertificate, password, username }
credentials: { host: baseHost, database, port, password, username }
} = appConnection;
const ssl = sslCertificate
? { rejectUnauthorized: appCfg.DB_SSL_REJECT_UNAUTHORIZED, ca: sslCertificate, servername: baseHost }
: undefined;
const [host] = await verifyHostInputValidity(baseHost);
const client = knex({
@@ -42,16 +70,7 @@ export const getSqlConnectionClient = async (appConnection: Pick<TSqlConnection,
user: username,
password,
connectionTimeoutMillis: EXTERNAL_REQUEST_TIMEOUT,
ssl,
// following dynamic secret mssql driver requirements (see sql-database.ts)
// @ts-expect-error this is because of knexjs type signature issue. This is directly passed to driver
options:
app === AppConnection.MsSql
? {
trustServerCertificate: !appCfg.DB_SSL_REJECT_UNAUTHORIZED,
cryptoCredentialsDetails: sslCertificate ? { ca: sslCertificate } : {}
}
: undefined
...getConnectionConfig(appConnection)
}
});

View File

@@ -49,7 +49,7 @@ An example creation statement might look like:
- **Rotate At** - the local time of day when rotation should occur once the interval has elapsed.
- **Auto-Rotation Enabled** - whether secrets should automatically be rotated once the rotation interval has elapsed. Disable this option to manually rotate secrets or pause secret rotation.
4. Input the the usernames of the database roles created above that will be used for rotation. The click **Next**.
4. Input the usernames of the database users created above that will be used for rotation. Then click **Next**.
![Rotation Parameters](/images/secret-rotations-v2/mssql-credentials/mssql-credentials-parameters.png)
- **Database Username 1** - the username of the first user that will be used for rotation.

View File

@@ -44,7 +44,7 @@ description: "Learn how to automatically rotate PostgreSQL credentials."
- **Rotate At** - the local time of day when rotation should occur once the interval has elapsed.
- **Auto-Rotation Enabled** - whether secrets should automatically be rotated once the rotation interval has elapsed. Disable this option to manually rotate secrets or pause secret rotation.
4. Input the the usernames of the database roles created above that will be used for rotation. The click **Next**.
4. Input the usernames of the database users created above that will be used for rotation. Then click **Next**.
![Rotation Parameters](/images/secret-rotations-v2/postgres-credentials/postgres-credentials-parameters.png)
- **Database Username 1** - the username of the first user that will be used for rotation.

View File

@@ -442,8 +442,13 @@ When set, all visits to the Infisical login page will automatically redirect use
## External Database Connections
<ParamField query="DB_SSL_REJECT_UNAUTHORIZED" type="boolean" default="true" optional>
Whether external database connections should reject unauthorized SSL certificates. Only set this to `false` if
the database you are connecting to is within your internal network.
Specify whether external database connections should reject unauthorized SSL certificates.
We highly recommend keeping this value set to `true` for production use-cases.
</ParamField>
<ParamField query="DB_SSL_REQUIRED" type="boolean" default="true" optional>
Specify whether external database connections should require SSL.
We highly recommend keeping this value set to `true` for production use-cases.
</ParamField>