mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 13:27:46 +00:00
requested changes
This commit is contained in:
+33
-16
@@ -15,6 +15,21 @@ import {
|
|||||||
TRedisCredentialsRotationGeneratedCredentials,
|
TRedisCredentialsRotationGeneratedCredentials,
|
||||||
TRedisCredentialsRotationWithConnection
|
TRedisCredentialsRotationWithConnection
|
||||||
} from "./redis-credentials-rotation-types";
|
} from "./redis-credentials-rotation-types";
|
||||||
|
import { verifyHostInputValidity } from "../../dynamic-secret/dynamic-secret-fns";
|
||||||
|
|
||||||
|
const redactPasswords = (e: unknown, credentials: TRedisCredentialsRotationGeneratedCredentials) => {
|
||||||
|
const error = e as Error;
|
||||||
|
|
||||||
|
if (!error?.message) return "Unknown error";
|
||||||
|
|
||||||
|
let redactedMessage = error.message;
|
||||||
|
|
||||||
|
credentials.forEach(({ password }) => {
|
||||||
|
redactedMessage = redactedMessage.replaceAll(password, "*******************");
|
||||||
|
});
|
||||||
|
|
||||||
|
return redactedMessage;
|
||||||
|
};
|
||||||
|
|
||||||
export const redisCredentialsRotationFactory: TRotationFactory<
|
export const redisCredentialsRotationFactory: TRotationFactory<
|
||||||
TRedisCredentialsRotationWithConnection,
|
TRedisCredentialsRotationWithConnection,
|
||||||
@@ -23,11 +38,13 @@ export const redisCredentialsRotationFactory: TRotationFactory<
|
|||||||
const { connection, secretsMapping, parameters } = secretRotation;
|
const { connection, secretsMapping, parameters } = secretRotation;
|
||||||
|
|
||||||
const $getClient = async () => {
|
const $getClient = async () => {
|
||||||
|
const [hostIp] = await verifyHostInputValidity(connection.credentials.host);
|
||||||
|
|
||||||
let conn: Redis | null = null;
|
let conn: Redis | null = null;
|
||||||
try {
|
try {
|
||||||
conn = new Redis({
|
conn = new Redis({
|
||||||
username: connection.credentials.username,
|
username: connection.credentials.username,
|
||||||
host: connection.credentials.host,
|
host: hostIp,
|
||||||
port: connection.credentials.port,
|
port: connection.credentials.port,
|
||||||
password: connection.credentials.password,
|
password: connection.credentials.password,
|
||||||
...(connection.credentials.sslEnabled && {
|
...(connection.credentials.sslEnabled && {
|
||||||
@@ -63,23 +80,23 @@ export const redisCredentialsRotationFactory: TRotationFactory<
|
|||||||
const $rotateAclUser = async () => {
|
const $rotateAclUser = async () => {
|
||||||
let client: Redis | null = null;
|
let client: Redis | null = null;
|
||||||
|
|
||||||
|
const username = generatePassword({
|
||||||
|
length: 32,
|
||||||
|
required: {
|
||||||
|
symbols: 0,
|
||||||
|
digits: 5,
|
||||||
|
uppercase: 5,
|
||||||
|
lowercase: 5
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const password = generatePassword(parameters.passwordRequirements || DEFAULT_PASSWORD_REQUIREMENTS);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = await $getClient();
|
client = await $getClient();
|
||||||
|
|
||||||
const username = generatePassword({
|
|
||||||
length: 32,
|
|
||||||
required: {
|
|
||||||
symbols: 0,
|
|
||||||
digits: 5,
|
|
||||||
uppercase: 5,
|
|
||||||
lowercase: 5
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const password = generatePassword(parameters.passwordRequirements || DEFAULT_PASSWORD_REQUIREMENTS);
|
|
||||||
|
|
||||||
// important: permissionScope is user input so we need to sanitize it, which we do by splitting the permission scope into parts and then passing them to the ACL command as separate arguments
|
// important: permissionScope is user input so we need to sanitize it, which we do by splitting the permission scope into parts and then passing them to the ACL command as separate arguments
|
||||||
const permissionParts = (parameters.permissionScope || "~* +@all").split(" ");
|
const permissionParts = parameters.permissionScope.split(" ");
|
||||||
await client.call("ACL", "SETUSER", username, `>${password}`, "on", ...permissionParts);
|
await client.call("ACL", "SETUSER", username, `>${password}`, "on", ...permissionParts);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -88,7 +105,7 @@ export const redisCredentialsRotationFactory: TRotationFactory<
|
|||||||
};
|
};
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
message: "Unable to validate connection: verify credentials"
|
message: `Unable to rotate credentials: ${redactPasswords(error, [{ username, password }])}`
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
if (client) await client.quit();
|
if (client) await client.quit();
|
||||||
@@ -106,7 +123,7 @@ export const redisCredentialsRotationFactory: TRotationFactory<
|
|||||||
await client.call("ACL", "DELUSER", username);
|
await client.call("ACL", "DELUSER", username);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
message: "Unable to revoke credential: verify credentials"
|
message: `Unable to revoke credential: ${redactPasswords(error, [{ username, password: username }])}`
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
if (client) await client.quit();
|
if (client) await client.quit();
|
||||||
|
|||||||
+8
-13
@@ -28,7 +28,11 @@ const RedisCredentialsRotationSecretsMappingSchema = z.object({
|
|||||||
|
|
||||||
export const RedisCredentialsRotationParametersSchema = z.object({
|
export const RedisCredentialsRotationParametersSchema = z.object({
|
||||||
passwordRequirements: PasswordRequirementsSchema.optional(),
|
passwordRequirements: PasswordRequirementsSchema.optional(),
|
||||||
permissionScope: z.string().optional().describe(SecretRotations.PARAMETERS.REDIS_CREDENTIALS.permissionScope)
|
permissionScope: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, "Permission scope is required")
|
||||||
|
.describe(SecretRotations.PARAMETERS.REDIS_CREDENTIALS.permissionScope)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RedisCredentialsRotationTemplateSchema = z.object({
|
export const RedisCredentialsRotationTemplateSchema = z.object({
|
||||||
@@ -40,30 +44,21 @@ export const RedisCredentialsRotationTemplateSchema = z.object({
|
|||||||
|
|
||||||
export const RedisCredentialsRotationSchema = BaseSecretRotationSchema(SecretRotation.RedisCredentials).extend({
|
export const RedisCredentialsRotationSchema = BaseSecretRotationSchema(SecretRotation.RedisCredentials).extend({
|
||||||
type: z.literal(SecretRotation.RedisCredentials),
|
type: z.literal(SecretRotation.RedisCredentials),
|
||||||
parameters: z.object({
|
parameters: RedisCredentialsRotationParametersSchema,
|
||||||
passwordRequirements: PasswordRequirementsSchema.optional(),
|
|
||||||
permissionScope: z.string().optional()
|
|
||||||
}),
|
|
||||||
secretsMapping: RedisCredentialsRotationSecretsMappingSchema
|
secretsMapping: RedisCredentialsRotationSecretsMappingSchema
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CreateRedisCredentialsRotationSchema = BaseCreateSecretRotationSchema(
|
export const CreateRedisCredentialsRotationSchema = BaseCreateSecretRotationSchema(
|
||||||
SecretRotation.RedisCredentials
|
SecretRotation.RedisCredentials
|
||||||
).extend({
|
).extend({
|
||||||
parameters: z.object({
|
parameters: RedisCredentialsRotationParametersSchema,
|
||||||
passwordRequirements: PasswordRequirementsSchema.optional(),
|
|
||||||
permissionScope: z.string().optional()
|
|
||||||
}),
|
|
||||||
secretsMapping: RedisCredentialsRotationSecretsMappingSchema
|
secretsMapping: RedisCredentialsRotationSecretsMappingSchema
|
||||||
});
|
});
|
||||||
|
|
||||||
export const UpdateRedisCredentialsRotationSchema = BaseUpdateSecretRotationSchema(
|
export const UpdateRedisCredentialsRotationSchema = BaseUpdateSecretRotationSchema(
|
||||||
SecretRotation.RedisCredentials
|
SecretRotation.RedisCredentials
|
||||||
).extend({
|
).extend({
|
||||||
parameters: z.object({
|
parameters: RedisCredentialsRotationParametersSchema.optional(),
|
||||||
passwordRequirements: PasswordRequirementsSchema.optional(),
|
|
||||||
permissionScope: z.string().optional()
|
|
||||||
}),
|
|
||||||
secretsMapping: RedisCredentialsRotationSecretsMappingSchema.optional()
|
secretsMapping: RedisCredentialsRotationSecretsMappingSchema.optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -101,10 +101,6 @@ Create a Redis Credentials Rotation in Infisical
|
|||||||
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
|
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
|
||||||
"name": "my-redis-rotation",
|
"name": "my-redis-rotation",
|
||||||
"description": "my database credentials rotation",
|
"description": "my database credentials rotation",
|
||||||
"secretsMapping": {
|
|
||||||
"username": "REDIS_USERNAME",
|
|
||||||
"password": "REDIS_PASSWORD"
|
|
||||||
},
|
|
||||||
"isAutoRotationEnabled": true,
|
"isAutoRotationEnabled": true,
|
||||||
"activeIndex": 0,
|
"activeIndex": 0,
|
||||||
"folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
|
"folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
|
||||||
|
|||||||
@@ -111,6 +111,14 @@ Infisical supports the use of Username & Password authentication to connect with
|
|||||||
"credentialsHash": "7c2d371dec195f82a6a0d5b41c970a229cfcaf88e894a5b6395e2dbd0280661f",
|
"credentialsHash": "7c2d371dec195f82a6a0d5b41c970a229cfcaf88e894a5b6395e2dbd0280661f",
|
||||||
"app": "redis",
|
"app": "redis",
|
||||||
"method": "username-and-password",
|
"method": "username-and-password",
|
||||||
|
credentials: {
|
||||||
|
"host": "<redis-host>",
|
||||||
|
"port": 6379,
|
||||||
|
"username": "<redis-username>",
|
||||||
|
"sslEnabled": true,
|
||||||
|
"sslRejectUnauthorized": false,
|
||||||
|
"sslCertificate": "<redis-ssl-certificate>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ export const RedisCredentialsRotationParametersFields = () => {
|
|||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input {...field} placeholder="~* +@all" />
|
<Input {...field} placeholder="~* +@read @write" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ export const RedisCredentialsRotationSchema = z
|
|||||||
type: z.literal(SecretRotation.RedisCredentials),
|
type: z.literal(SecretRotation.RedisCredentials),
|
||||||
parameters: z.object({
|
parameters: z.object({
|
||||||
passwordRequirements: PasswordRequirementsSchema.optional(),
|
passwordRequirements: PasswordRequirementsSchema.optional(),
|
||||||
permissionScope: z.string().optional()
|
permissionScope: z.string().trim().min(1, "Permission scope is required")
|
||||||
}),
|
}),
|
||||||
secretsMapping: z.object({
|
secretsMapping: z.object({
|
||||||
username: z.string().trim().min(1, "Username required"),
|
username: z.string().trim().min(1, "Username required"),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export type TRedisCredentialsRotation = TSecretRotationV2Base & {
|
|||||||
type: SecretRotation.RedisCredentials;
|
type: SecretRotation.RedisCredentials;
|
||||||
parameters: {
|
parameters: {
|
||||||
passwordRequirements?: TPasswordRequirements;
|
passwordRequirements?: TPasswordRequirements;
|
||||||
permissionScope?: string;
|
permissionScope: string;
|
||||||
};
|
};
|
||||||
secretsMapping: {
|
secretsMapping: {
|
||||||
username: string;
|
username: string;
|
||||||
|
|||||||
+2
@@ -323,6 +323,8 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
|||||||
return <DigitalOceanConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
return <DigitalOceanConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||||
case AppConnection.Okta:
|
case AppConnection.Okta:
|
||||||
return <OktaConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
return <OktaConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||||
|
case AppConnection.Redis:
|
||||||
|
return <RedisConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled App ${(appConnection as TAppConnection).app}`);
|
throw new Error(`Unhandled App ${(appConnection as TAppConnection).app}`);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user