feat: updated pr by review changes

This commit is contained in:
=
2025-12-19 14:28:04 +05:30
parent be83592f16
commit fa52dca642
12 changed files with 172 additions and 17 deletions

View File

@@ -16,7 +16,9 @@ import { SecretNameSchema } from "@app/server/lib/schemas";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
export const MongoDBCredentialsRotationGeneratedCredentialsSchema = SqlCredentialsRotationGeneratedCredentialsSchema;
export const MongoDBCredentialsRotationParametersSchema = SqlCredentialsRotationParametersSchema;
export const MongoDBCredentialsRotationParametersSchema = SqlCredentialsRotationParametersSchema.omit({
rotationStatement: true
});
export const MongoDBCredentialsRotationTemplateSchema = SqlCredentialsRotationTemplateSchema.omit({
rotationStatement: true
});

View File

@@ -89,6 +89,22 @@ export const sqlCredentialsRotationFactory: TRotationFactory<
}
};
const $executeQuery = async (tx: Knex, username: string, password: string) => {
if (userProvidedRotationStatement) {
const revokeStatement = handlebars.compile(userProvidedRotationStatement)({
username,
password,
database: connection.credentials.database
});
const queries = revokeStatement.toString().split(";").filter(Boolean);
for await (const query of queries) {
await tx.raw(query);
}
} else {
await tx.raw(...SQL_CONNECTION_ALTER_LOGIN_STATEMENT[connection.app]({ username, password }));
}
};
const issueCredentials: TRotationFactoryIssueCredentials<TSqlCredentialsRotationGeneratedCredentials> = async (
callback
) => {
@@ -103,19 +119,7 @@ export const sqlCredentialsRotationFactory: TRotationFactory<
await executeOperation(async (client) => {
await client.transaction(async (tx) => {
for await (const credentials of credentialsSet) {
if (userProvidedRotationStatement) {
const revokeStatement = handlebars.compile(userProvidedRotationStatement)({
username: credentials.username,
password: credentials.password,
database: connection.credentials.database
});
const queries = revokeStatement.toString().split(";").filter(Boolean);
for await (const query of queries) {
await tx.raw(query);
}
} else {
await tx.raw(...SQL_CONNECTION_ALTER_LOGIN_STATEMENT[connection.app](credentials));
}
await $executeQuery(tx, credentials.username, credentials.password);
}
});
});
@@ -144,7 +148,7 @@ export const sqlCredentialsRotationFactory: TRotationFactory<
await client.transaction(async (tx) => {
for await (const credentials of revokedCredentials) {
// invalidate previous passwords
await tx.raw(...SQL_CONNECTION_ALTER_LOGIN_STATEMENT[connection.app](credentials));
await $executeQuery(tx, credentials.username, credentials.password);
}
});
});
@@ -167,7 +171,7 @@ export const sqlCredentialsRotationFactory: TRotationFactory<
try {
await executeOperation(async (client) => {
await client.raw(...SQL_CONNECTION_ALTER_LOGIN_STATEMENT[connection.app](credentials));
await $executeQuery(client, credentials.username, credentials.password);
});
} catch (error) {
throw new Error(redactPasswords(error, [credentials]));

View File

@@ -56,6 +56,8 @@ An example creation statement might look like:
- **Database Username 1** - the username of the first user that will be used for rotation.
- **Database Username 2** - the username of the second user that will be used for rotation.
![Rotation Advance Parameters](/images/secret-rotations-v2/mssql-credentials/mssql-credentials-advance-parameters.png)
- **Rotation Statement** - the template string query to generate password for the rotated user.
- **Password Requirements** - the requirements for the password of the MySQL users that will be created for the rotation.

View File

@@ -61,6 +61,8 @@ description: "Learn how to automatically rotate Oracle Database credentials."
If your Oracle usernames were created without "quotes", Oracle sees them as UPPERCASE. Please use UPPERCASE for those names in the fields above.
</Note>
![Rotation Advance Parameters](/images/secret-rotations-v2/oracledb-credentials/oracledb-credentials-advance-parameters.png)
- **Rotation Statement** - the template string query to generate password for the rotated user.
- **Password Requirements** - the requirements for the password of the MySQL users that will be created for the rotation.

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 837 KiB

After

Width:  |  Height:  |  Size: 563 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 712 KiB

After

Width:  |  Height:  |  Size: 531 KiB

View File

@@ -0,0 +1,66 @@
import { Controller, useFormContext } from "react-hook-form";
import { TSecretRotationV2Form } from "@app/components/secret-rotations-v2/forms/schemas";
import { FormControl, Input } from "@app/components/v2";
import { NoticeBannerV2 } from "@app/components/v2/NoticeBannerV2/NoticeBannerV2";
import { SecretRotation, useSecretRotationV2Option } from "@app/hooks/api/secretRotationsV2";
export const MongoRotationParametersFields = () => {
const { control, watch } = useFormContext<
TSecretRotationV2Form & {
type: SecretRotation.MongoDBCredentials;
}
>();
const type = watch("type");
const { rotationOption } = useSecretRotationV2Option(type);
return (
<>
<Controller
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isError={Boolean(error)}
errorText={error?.message}
label="Database Username 1"
>
<Input value={value} onChange={onChange} placeholder="infisical_user_1" />
</FormControl>
)}
control={control}
name="parameters.username1"
/>
<Controller
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isError={Boolean(error)}
errorText={error?.message}
label="Database Username 2"
>
<Input value={value} onChange={onChange} placeholder="infisical_user_2" />
</FormControl>
)}
control={control}
name="parameters.username2"
/>
<NoticeBannerV2 title="Example Create User Statement">
<p className="mb-3 text-sm text-mineshaft-300">
Infisical requires two database users to be created for rotation.
</p>
<p className="mb-3 text-sm text-mineshaft-300">
These users are intended to be solely managed by Infisical. Altering their login after
rotation may cause unexpected failure.
</p>
<p className="mb-3 text-sm text-mineshaft-300">
Below is an example statement for creating the required users. You may need to modify it
to suit your needs.
</p>
<p className="mb-3 text-sm">
<pre className="max-h-40 overflow-y-auto rounded-sm border border-mineshaft-700 bg-mineshaft-800 p-2 whitespace-pre-wrap text-mineshaft-300">
{rotationOption!.template.createUserStatement}
</pre>
</p>
</NoticeBannerV2>
</>
);
};

View File

@@ -7,6 +7,7 @@ import { Auth0ClientSecretRotationParametersFields } from "./Auth0ClientSecretRo
import { AwsIamUserSecretRotationParametersFields } from "./AwsIamUserSecretRotationParametersFields";
import { AzureClientSecretRotationParametersFields } from "./AzureClientSecretRotationParametersFields";
import { LdapPasswordRotationParametersFields } from "./LdapPasswordRotationParametersFields";
import { MongoRotationParametersFields } from "./MongoRotationParametersFields";
import { OktaClientSecretRotationParametersFields } from "./OktaClientSecretRotationParametersFields";
import { RedisCredentialsRotationParametersFields } from "./RedisCredentialsRotationParametersFields";
import { SqlCredentialsRotationParametersFields } from "./shared";
@@ -22,7 +23,7 @@ const COMPONENT_MAP: Record<SecretRotation, React.FC> = {
[SecretRotation.AwsIamUserSecret]: AwsIamUserSecretRotationParametersFields,
[SecretRotation.OktaClientSecret]: OktaClientSecretRotationParametersFields,
[SecretRotation.RedisCredentials]: RedisCredentialsRotationParametersFields,
[SecretRotation.MongoDBCredentials]: SqlCredentialsRotationParametersFields
[SecretRotation.MongoDBCredentials]: MongoRotationParametersFields
};
export const SecretRotationV2ParametersFields = () => {

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -e
CONTAINER_NAME="mssql"
SA_PASSWORD="StrongP@ssw0rd!"
IMAGE="mcr.microsoft.com/mssql/server:2022-latest"
echo "🚀 Starting SQL Server 2022 container..."
docker run -d \
--platform=linux/amd64 \
--name "${CONTAINER_NAME}" \
-p 1433:1433 \
-e "ACCEPT_EULA=Y" \
-e "SA_PASSWORD=${SA_PASSWORD}" \
"${IMAGE}"
echo "⏳ Waiting for SQL Server to be ready..."
# Check logs for ready message
until docker logs "${CONTAINER_NAME}" 2>&1 | grep -q "SQL Server is now ready for client connections."; do
sleep 5
done
echo ""
echo "✅ SQL Server is ready!"
echo ""
echo "🔐 Connection details:"
echo "------------------------------------"
echo "Host: localhost"
echo "Port: 1433"
echo "Username: sa"
echo "Password: ${SA_PASSWORD}"
echo "Database: master"
echo ""
echo "📎 JDBC URL:"
echo "jdbc:sqlserver://localhost:1433;databaseName=master;user=sa;password=${SA_PASSWORD}"
echo ""
echo "🧪 Connect using sqlcmd:"
echo "sqlcmd -S localhost,1433 -U sa -P '${SA_PASSWORD}'"
echo "------------------------------------"

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -e
CONTAINER_NAME="oracle-free"
ORACLE_PASSWORD="oracle"
IMAGE="gvenzl/oracle-free:23-slim"
echo "🚀 Starting Oracle Free 23c container..."
docker run -d \
--name "${CONTAINER_NAME}" \
-p 1521:1521 \
-p 5500:5500 \
-e ORACLE_PASSWORD="${ORACLE_PASSWORD}" \
"${IMAGE}"
echo "⏳ Waiting for Oracle database to be ready..."
until docker logs "${CONTAINER_NAME}" 2>&1 | grep -q "DATABASE IS READY TO USE"; do
sleep 5
done
echo ""
echo "✅ Oracle Database is ready!"
echo ""
echo "🔐 Connection details:"
echo "------------------------------------"
echo "Host: localhost"
echo "Port: 1521"
echo "Service: FREEPDB1"
echo "Username: system"
echo "Password: ${ORACLE_PASSWORD}"
echo ""
echo "📎 JDBC URL:"
echo "jdbc:oracle:thin:@localhost:1521/FREEPDB1"
echo ""
echo "🧪 Connect using SQL*Plus:"
echo "sqlplus system/${ORACLE_PASSWORD}@FREEPDB1"
echo "------------------------------------"