feat(dynamic-secret): Minor improvements on usernameTemplate

This commit is contained in:
carlosmonastyrski
2025-06-05 17:18:56 -03:00
parent 5367d1ac2e
commit ac5bfbb6c9
33 changed files with 138 additions and 145 deletions

View File

@@ -146,23 +146,23 @@ export const dynamicSecretLeaseServiceFactory = ({
let result;
try {
let identityName = "";
const identity: { name: string } = { name: "" };
if (actor === ActorType.USER) {
const user = await userDAL.findById(actorId);
if (user) {
identityName = extractEmailUsername(user.username);
identity.name = extractEmailUsername(user.username);
}
} else if (actor === ActorType.Machine) {
const identity = await identityDAL.findById(actorId);
if (identity) {
identityName = identity.name;
const machineIdentity = await identityDAL.findById(actorId);
if (machineIdentity) {
identity.name = machineIdentity.name;
}
}
result = await selectedProvider.create({
inputs: decryptedStoredInput,
expireAt: expireAt.getTime(),
usernameTemplate: dynamicSecretCfg.usernameTemplate,
identityName
identity
});
} catch (error: unknown) {
if (error && typeof error === "object" && error !== null && "sqlMessage" in error) {

View File

@@ -133,14 +133,14 @@ const generatePassword = () => {
return customAlphabet(charset, 64)();
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-";
const randomUsername = `inf-${customAlphabet(charset, 32)()}`;
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -179,15 +179,17 @@ export const AwsElastiCacheDatabaseProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: {
name: string;
};
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
if (!(await validateConnection(providerInputs))) {
throw new BadRequestError({ message: "Failed to establish connection" });
}
const leaseUsername = generateUsername(usernameTemplate, identityName);
const leaseUsername = generateUsername(usernameTemplate, identity);
const leasePassword = generatePassword();
const leaseExpiration = new Date(expireAt).toISOString();

View File

@@ -24,14 +24,14 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
import { DynamicSecretAwsIamSchema, TDynamicProviderFns } from "./models";
import { compileUsernameTemplate } from "./templateUtils";
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32);
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -65,14 +65,16 @@ export const AwsIamProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: {
name: string;
};
}) => {
const { inputs, usernameTemplate, identityName } = data;
const { inputs, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const client = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const { policyArns, userGroups, policyDocument, awsPath, permissionBoundaryPolicyArn } = providerInputs;
const createUserRes = await client.send(
new CreateUserCommand({

View File

@@ -15,13 +15,13 @@ const generatePassword = (size = 48) => {
return customAlphabet(charset, 48)(size);
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -80,13 +80,13 @@ export const CassandraProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: { name: string };
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const client = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const { keyspace } = providerInputs;
const expiration = new Date(expireAt).toISOString();

View File

@@ -13,13 +13,13 @@ const generatePassword = () => {
return customAlphabet(charset, 64)();
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -71,12 +71,12 @@ export const ElasticSearchProvider = (): TDynamicProviderFns => {
return infoResponse;
};
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identityName?: string }) => {
const { inputs, usernameTemplate, identityName } = data;
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
const { inputs, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const connection = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
await connection.security.putUser({

View File

@@ -23,13 +23,13 @@ const encodePassword = (password?: string) => {
return base64Password;
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -197,8 +197,8 @@ export const LdapProvider = (): TDynamicProviderFns => {
return dnArray;
};
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identityName?: string }) => {
const { inputs, usernameTemplate, identityName } = data;
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
const { inputs, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const client = await $getClient(providerInputs);
@@ -225,7 +225,7 @@ export const LdapProvider = (): TDynamicProviderFns => {
});
}
} else {
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const generatedLdif = generateLDIF({ username, password, ldifTemplate: providerInputs.creationLdif });

View File

@@ -364,7 +364,9 @@ export type TDynamicProviderFns = {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: {
name: string;
};
}) => Promise<{ entityId: string; data: unknown }>;
validateConnection: (inputs: unknown) => Promise<boolean>;
validateProviderInputs: (inputs: object) => Promise<unknown>;

View File

@@ -13,13 +13,13 @@ const generatePassword = (size = 48) => {
return customAlphabet(charset, 48)(size);
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32);
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -68,13 +68,13 @@ export const MongoAtlasProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: { name: string };
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const client = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const expiration = new Date(expireAt).toISOString();
await client({

View File

@@ -13,13 +13,13 @@ const generatePassword = (size = 48) => {
return customAlphabet(charset, 48)(size);
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32);
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -60,12 +60,12 @@ export const MongoDBProvider = (): TDynamicProviderFns => {
return isConnected;
};
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identityName?: string }) => {
const { inputs, usernameTemplate, identityName } = data;
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
const { inputs, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const client = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const db = client.db(providerInputs.database);

View File

@@ -15,13 +15,13 @@ const generatePassword = () => {
return customAlphabet(charset, 64)();
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -117,12 +117,12 @@ export const RabbitMqProvider = (): TDynamicProviderFns => {
return infoResponse;
};
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identityName?: string }) => {
const { inputs, usernameTemplate, identityName } = data;
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
const { inputs, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const connection = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
await createRabbitMqUser({

View File

@@ -16,13 +16,13 @@ const generatePassword = () => {
return customAlphabet(charset, 64)();
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -126,13 +126,13 @@ export const RedisDatabaseProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: { name: string };
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const connection = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const expiration = new Date(expireAt).toISOString();

View File

@@ -16,13 +16,13 @@ const generatePassword = (size = 48) => {
return customAlphabet(charset, 48)(size);
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = `inf_${alphaNumericNanoId(25)}`; // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -88,11 +88,11 @@ export const SapAseProvider = (): TDynamicProviderFns => {
return true;
};
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identityName?: string }) => {
const { inputs, usernameTemplate, identityName } = data;
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
const { inputs, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const client = await $getClient(providerInputs);

View File

@@ -22,13 +22,13 @@ const generatePassword = (size = 48) => {
return customAlphabet(charset, 48)(size);
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -102,12 +102,12 @@ export const SapHanaProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: { name: string };
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
const expiration = new Date(expireAt).toISOString();

View File

@@ -18,13 +18,13 @@ const generatePassword = (size = 48) => {
return customAlphabet(charset, 48)(size);
};
const generateUsername = (usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
const randomUsername = `infisical_${alphaNumericNanoId(32)}`; // Username must start with an ascii letter, so we prepend the username with "inf-"
if (!usernameTemplate) return randomUsername;
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName
identity
});
};
@@ -93,14 +93,14 @@ export const SnowflakeProvider = (): TDynamicProviderFns => {
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: { name: string };
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const client = await $getClient(providerInputs);
const username = generateUsername(usernameTemplate, identityName);
const username = generateUsername(usernameTemplate, identity);
const password = generatePassword();
try {

View File

@@ -105,7 +105,7 @@ const generatePassword = (provider: SqlProviders, requirements?: PasswordRequire
}
};
const generateUsername = (provider: SqlProviders, usernameTemplate?: string | null, identityName?: string) => {
const generateUsername = (provider: SqlProviders, usernameTemplate?: string | null, identity?: { name: string }) => {
let randomUsername = "";
// For oracle, the client assumes everything is upper case when not using quotes around the password
if (provider === SqlProviders.Oracle) {
@@ -117,7 +117,7 @@ const generateUsername = (provider: SqlProviders, usernameTemplate?: string | nu
return compileUsernameTemplate({
usernameTemplate,
randomUsername,
identityName,
identity,
options: {
toUpperCase: provider === SqlProviders.Oracle
}
@@ -227,12 +227,12 @@ export const SqlDatabaseProvider = ({ gatewayService }: TSqlDatabaseProviderDTO)
inputs: unknown;
expireAt: number;
usernameTemplate?: string | null;
identityName?: string;
identity?: { name: string };
}) => {
const { inputs, expireAt, usernameTemplate, identityName } = data;
const { inputs, expireAt, usernameTemplate, identity } = data;
const providerInputs = await validateProviderInputs(inputs);
const username = generateUsername(providerInputs.client, usernameTemplate, identityName);
const username = generateUsername(providerInputs.client, usernameTemplate, identity);
const password = generatePassword(providerInputs.client, providerInputs.passwordRequirements);
const gatewayCallback = async (host = providerInputs.host, port = providerInputs.port) => {

View File

@@ -2,73 +2,68 @@
import handlebars from "handlebars";
import RE2 from "re2";
import { logger } from "@app/lib/logger";
import { alphaNumericNanoId } from "@app/lib/nanoid";
export const compileUsernameTemplate = ({
usernameTemplate,
randomUsername,
identityName,
identity,
unixTimestamp,
options
}: {
usernameTemplate: string;
randomUsername: string;
identityName?: string;
identity?: { name: string };
unixTimestamp?: number;
options?: {
toUpperCase?: boolean;
};
}): string => {
// Pre-process template to replace {{random-N}} patterns before compiling
// Create isolated handlebars instance
const hbs = handlebars.create();
// Pre-process template to replace {{random N}} patterns using RE2
let processedTemplate = usernameTemplate;
const randomPattern = /\{\{random-(\d+)\}\}/g;
let match;
// eslint-disable-next-line no-cond-assign
while ((match = randomPattern.exec(usernameTemplate)) !== null) {
const fullMatch = match[0];
const length = parseInt(match[1], 10);
try {
const randomPattern = new RE2("\\{\\{random (\\d+)\\}\\}", "g");
if (length > 0 && length <= 100) {
const randomValue = alphaNumericNanoId(length);
processedTemplate = processedTemplate.replace(fullMatch, randomValue);
}
// Use RE2's replace with callback function
processedTemplate = randomPattern.replace(processedTemplate, (fullMatch: string, lengthStr: string) => {
const length = parseInt(lengthStr, 10);
if (length > 0 && length <= 100) {
return alphaNumericNanoId(length);
}
// Return original match if invalid length
return fullMatch;
});
} catch (error) {
logger.error(error, "RE2 pattern failed, using original template");
}
// Register replace helper
handlebars.registerHelper(
"replace",
function (text: string, searchValue: string, replaceValue: string, limit?: number) {
// Convert to string if it's not already
const textStr = String(text || "");
if (!textStr) {
return textStr;
}
try {
const re2Pattern = new RE2(searchValue, "g");
if (limit && limit > 0) {
// Replace only up to the specified limit
let count = 0;
return textStr.replace(re2Pattern, (textMatch) => {
if (count < limit) {
count += 1;
return replaceValue;
}
return textMatch;
});
}
// Replace all occurrences
return textStr.replace(re2Pattern, replaceValue);
} catch (error) {
return textStr;
}
// Register replace helper on local instance
hbs.registerHelper("replace", function (text: string, searchValue: string, replaceValue: string) {
// Convert to string if it's not already
const textStr = String(text || "");
if (!textStr) {
return textStr;
}
);
// Register truncate helper
handlebars.registerHelper("truncate", function (text: string, length: number) {
try {
const re2Pattern = new RE2(searchValue, "g");
// Replace all occurrences
return textStr.replace(re2Pattern, replaceValue);
} catch (error) {
logger.error(error, "RE2 pattern failed, using original template");
return textStr;
}
});
// Register truncate helper on local instance
hbs.registerHelper("truncate", function (text: string, length: number) {
// Convert to string if it's not already
const textStr = String(text || "");
if (!textStr) {
@@ -79,16 +74,16 @@ export const compileUsernameTemplate = ({
return textStr.substring(0, length);
});
// Compile template with context
// Compile template with context using local instance
const context = {
randomUsername,
unixTimestamp: unixTimestamp || Math.floor(Date.now() / 100),
identity: {
name: identityName
name: identity?.name
}
};
const result = handlebars.compile(processedTemplate)(context);
const result = hbs.compile(processedTemplate)(context);
if (options?.toUpperCase) {
return result.toUpperCase();

View File

@@ -1,5 +1,4 @@
import handlebars from "handlebars";
import RE2 from "re2";
import { BadRequestError } from "../errors";
import { logger } from "../logger";
@@ -8,16 +7,9 @@ type SanitizationArg = {
allowedExpressions?: (arg: string) => boolean;
};
const randomPattern = new RE2("^random-\\d+$");
const isValidExpression = (expression: string, dto: SanitizationArg): boolean => {
// Check for random-N pattern (e.g., random-16, random-8)
if (expression.startsWith("random-") && randomPattern.test(expression)) {
return true;
}
// Allow helper functions (replace, truncate)
const allowedHelpers = ["replace", "truncate"];
const allowedHelpers = ["replace", "truncate", "random"];
if (allowedHelpers.includes(expression)) {
return true;
}

View File

@@ -102,7 +102,7 @@ The Infisical AWS ElastiCache dynamic secret allows you to generate AWS ElastiCa
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -112,7 +112,7 @@ Replace **\<account id\>** with your AWS account id and **\<aws-scope-path\>** w
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -86,7 +86,7 @@ The above configuration allows user creation and granting permissions.
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -94,7 +94,7 @@ The port that your Elasticsearch instance is running on. _(Example: 9200)_
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -130,7 +130,7 @@ The Infisical LDAP dynamic secret allows you to generate user credentials on dem
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -70,7 +70,7 @@ Create a project scoped API Key with the required permission in your Mongo Atlas
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -73,7 +73,7 @@ Create a user with the required permission in your MongoDB instance. This user w
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -78,7 +78,7 @@ Create a user with the required permission in your SQL instance. This user will
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -76,7 +76,7 @@ Create a user with the required permission in your SQL instance. This user will
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -78,7 +78,7 @@ Create a user with the required permission in your SQL instance. This user will
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -79,7 +79,7 @@ Create a user with the required permission in your SQL instance. This user will
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -72,7 +72,7 @@ The port that the RabbitMQ management plugin is listening on. This is `15672` by
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -64,7 +64,7 @@ Create a user with the required permission in your Redis instance. This user wil
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -71,7 +71,7 @@ The Infisical SAP ASE dynamic secret allows you to generate SAP ASE database cre
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -71,7 +71,7 @@ The Infisical SAP HANA dynamic secret allows you to generate SAP HANA database c
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length

View File

@@ -84,7 +84,7 @@ Infisical's Snowflake dynamic secrets allow you to generate Snowflake user crede
- `{{randomUsername}}`: Random username string
- `{{unixTimestamp}}`: Current Unix timestamp
- `{{identity.name}}`: Name of the identity that is generating the secret
- `{{random-N}}`: Random string of N characters
- `{{random N}}`: Random string of N characters
Allowed template functions are
- `truncate`: Truncates a string to a specified length