mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 13:27:22 +00:00
Merge pull request #3722 from Infisical/feat/dynamicSecretIdentityName
Add identityName to Dynamic Secrets userName template
This commit is contained in:
@@ -23,7 +23,10 @@ const validateUsernameTemplateCharacters = characterValidator([
|
|||||||
CharacterType.CloseBrace,
|
CharacterType.CloseBrace,
|
||||||
CharacterType.CloseBracket,
|
CharacterType.CloseBracket,
|
||||||
CharacterType.OpenBracket,
|
CharacterType.OpenBracket,
|
||||||
CharacterType.Fullstop
|
CharacterType.Fullstop,
|
||||||
|
CharacterType.SingleQuote,
|
||||||
|
CharacterType.Spaces,
|
||||||
|
CharacterType.Pipe
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const userTemplateSchema = z
|
const userTemplateSchema = z
|
||||||
@@ -33,7 +36,7 @@ const userTemplateSchema = z
|
|||||||
.refine((el) => validateUsernameTemplateCharacters(el))
|
.refine((el) => validateUsernameTemplateCharacters(el))
|
||||||
.refine((el) =>
|
.refine((el) =>
|
||||||
isValidHandleBarTemplate(el, {
|
isValidHandleBarTemplate(el, {
|
||||||
allowedExpressions: (val) => ["randomUsername", "unixTimestamp"].includes(val)
|
allowedExpressions: (val) => ["randomUsername", "unixTimestamp", "identity.name"].includes(val)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ForbiddenError, subject } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
|
import RE2 from "re2";
|
||||||
|
|
||||||
import { ActionProjectType } from "@app/db/schemas";
|
import { ActionProjectType } from "@app/db/schemas";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
@@ -11,10 +12,13 @@ import { getConfig } from "@app/lib/config/env";
|
|||||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { logger } from "@app/lib/logger";
|
import { logger } from "@app/lib/logger";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
|
import { TIdentityDALFactory } from "@app/services/identity/identity-dal";
|
||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
||||||
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
|
|
||||||
import { TDynamicSecretDALFactory } from "../dynamic-secret/dynamic-secret-dal";
|
import { TDynamicSecretDALFactory } from "../dynamic-secret/dynamic-secret-dal";
|
||||||
import { DynamicSecretProviders, TDynamicProviderFns } from "../dynamic-secret/providers/models";
|
import { DynamicSecretProviders, TDynamicProviderFns } from "../dynamic-secret/providers/models";
|
||||||
@@ -39,6 +43,8 @@ type TDynamicSecretLeaseServiceFactoryDep = {
|
|||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
|
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
|
||||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||||
|
userDAL: Pick<TUserDALFactory, "findById">;
|
||||||
|
identityDAL: TIdentityDALFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TDynamicSecretLeaseServiceFactory = ReturnType<typeof dynamicSecretLeaseServiceFactory>;
|
export type TDynamicSecretLeaseServiceFactory = ReturnType<typeof dynamicSecretLeaseServiceFactory>;
|
||||||
@@ -52,8 +58,16 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
dynamicSecretQueueService,
|
dynamicSecretQueueService,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
licenseService,
|
licenseService,
|
||||||
kmsService
|
kmsService,
|
||||||
|
userDAL,
|
||||||
|
identityDAL
|
||||||
}: TDynamicSecretLeaseServiceFactoryDep) => {
|
}: TDynamicSecretLeaseServiceFactoryDep) => {
|
||||||
|
const extractEmailUsername = (email: string) => {
|
||||||
|
const regex = new RE2(/^([^@]+)/);
|
||||||
|
const match = email.match(regex);
|
||||||
|
return match ? match[1] : email;
|
||||||
|
};
|
||||||
|
|
||||||
const create = async ({
|
const create = async ({
|
||||||
environmentSlug,
|
environmentSlug,
|
||||||
path,
|
path,
|
||||||
@@ -132,10 +146,23 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
|
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
|
const identity: { name: string } = { name: "" };
|
||||||
|
if (actor === ActorType.USER) {
|
||||||
|
const user = await userDAL.findById(actorId);
|
||||||
|
if (user) {
|
||||||
|
identity.name = extractEmailUsername(user.username);
|
||||||
|
}
|
||||||
|
} else if (actor === ActorType.Machine) {
|
||||||
|
const machineIdentity = await identityDAL.findById(actorId);
|
||||||
|
if (machineIdentity) {
|
||||||
|
identity.name = machineIdentity.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
result = await selectedProvider.create({
|
result = await selectedProvider.create({
|
||||||
inputs: decryptedStoredInput,
|
inputs: decryptedStoredInput,
|
||||||
expireAt: expireAt.getTime(),
|
expireAt: expireAt.getTime(),
|
||||||
usernameTemplate: dynamicSecretCfg.usernameTemplate,
|
usernameTemplate: dynamicSecretCfg.usernameTemplate,
|
||||||
|
identity,
|
||||||
metadata: { projectId }
|
metadata: { projectId }
|
||||||
});
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { BadRequestError } from "@app/lib/errors";
|
|||||||
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
|
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
|
||||||
|
|
||||||
import { DynamicSecretAwsElastiCacheSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretAwsElastiCacheSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const CreateElastiCacheUserSchema = z.object({
|
const CreateElastiCacheUserSchema = z.object({
|
||||||
UserId: z.string().trim().min(1),
|
UserId: z.string().trim().min(1),
|
||||||
@@ -132,14 +133,14 @@ const generatePassword = () => {
|
|||||||
return customAlphabet(charset, 64)();
|
return customAlphabet(charset, 64)();
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
|
||||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-";
|
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-";
|
||||||
const randomUsername = `inf-${customAlphabet(charset, 32)()}`;
|
const randomUsername = `inf-${customAlphabet(charset, 32)()}`;
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,14 +175,21 @@ export const AwsElastiCacheDatabaseProvider = (): TDynamicProviderFns => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
if (!(await validateConnection(providerInputs))) {
|
if (!(await validateConnection(providerInputs))) {
|
||||||
throw new BadRequestError({ message: "Failed to establish connection" });
|
throw new BadRequestError({ message: "Failed to establish connection" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const leaseUsername = generateUsername(usernameTemplate);
|
const leaseUsername = generateUsername(usernameTemplate, identity);
|
||||||
const leasePassword = generatePassword();
|
const leasePassword = generatePassword();
|
||||||
const leaseExpiration = new Date(expireAt).toISOString();
|
const leaseExpiration = new Date(expireAt).toISOString();
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import {
|
|||||||
} from "@aws-sdk/client-iam";
|
} from "@aws-sdk/client-iam";
|
||||||
import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts";
|
import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts";
|
||||||
import { randomUUID } from "crypto";
|
import { randomUUID } from "crypto";
|
||||||
import handlebars from "handlebars";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
@@ -26,14 +25,16 @@ import { BadRequestError } from "@app/lib/errors";
|
|||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
|
|
||||||
import { AwsIamAuthType, DynamicSecretAwsIamSchema, TDynamicProviderFns } from "./models";
|
import { AwsIamAuthType, DynamicSecretAwsIamSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
|
||||||
const randomUsername = alphaNumericNanoId(32);
|
const randomUsername = alphaNumericNanoId(32);
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
|
||||||
return handlebars.compile(usernameTemplate)({
|
return compileUsernameTemplate({
|
||||||
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,14 +116,17 @@ export const AwsIamProvider = (): TDynamicProviderFns => {
|
|||||||
inputs: unknown;
|
inputs: unknown;
|
||||||
expireAt: number;
|
expireAt: number;
|
||||||
usernameTemplate?: string | null;
|
usernameTemplate?: string | null;
|
||||||
|
identity?: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
metadata: { projectId: string };
|
metadata: { projectId: string };
|
||||||
}) => {
|
}) => {
|
||||||
const { inputs, usernameTemplate, metadata } = data;
|
const { inputs, usernameTemplate, metadata, identity } = data;
|
||||||
|
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const client = await $getClient(providerInputs, metadata.projectId);
|
const client = await $getClient(providerInputs, metadata.projectId);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const { policyArns, userGroups, policyDocument, awsPath, permissionBoundaryPolicyArn } = providerInputs;
|
const { policyArns, userGroups, policyDocument, awsPath, permissionBoundaryPolicyArn } = providerInputs;
|
||||||
const createUserRes = await client.send(
|
const createUserRes = await client.send(
|
||||||
new CreateUserCommand({
|
new CreateUserCommand({
|
||||||
|
|||||||
@@ -8,19 +8,20 @@ import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretCassandraSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretCassandraSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = (size = 48) => {
|
const generatePassword = (size = 48) => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
||||||
return customAlphabet(charset, 48)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,12 +76,17 @@ export const CassandraProvider = (): TDynamicProviderFns => {
|
|||||||
return isConnected;
|
return isConnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: { name: string };
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const client = await $getClient(providerInputs);
|
const client = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const { keyspace } = providerInputs;
|
const { keyspace } = providerInputs;
|
||||||
const expiration = new Date(expireAt).toISOString();
|
const expiration = new Date(expireAt).toISOString();
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Client as ElasticSearchClient } from "@elastic/elasticsearch";
|
import { Client as ElasticSearchClient } from "@elastic/elasticsearch";
|
||||||
import handlebars from "handlebars";
|
|
||||||
import { customAlphabet } from "nanoid";
|
import { customAlphabet } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@@ -7,19 +6,20 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretElasticSearchSchema, ElasticSearchAuthTypes, TDynamicProviderFns } from "./models";
|
import { DynamicSecretElasticSearchSchema, ElasticSearchAuthTypes, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = () => {
|
const generatePassword = () => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
||||||
return customAlphabet(charset, 64)();
|
return customAlphabet(charset, 64)();
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,12 +71,12 @@ export const ElasticSearchProvider = (): TDynamicProviderFns => {
|
|||||||
return infoResponse;
|
return infoResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; usernameTemplate?: string | null }) => {
|
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
|
||||||
const { inputs, usernameTemplate } = data;
|
const { inputs, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const connection = await $getClient(providerInputs);
|
const connection = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
|
|
||||||
await connection.security.putUser({
|
await connection.security.putUser({
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { BadRequestError } from "@app/lib/errors";
|
|||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
|
|
||||||
import { LdapCredentialType, LdapSchema, TDynamicProviderFns } from "./models";
|
import { LdapCredentialType, LdapSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = () => {
|
const generatePassword = () => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*$#";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*$#";
|
||||||
@@ -22,13 +23,13 @@ const encodePassword = (password?: string) => {
|
|||||||
return base64Password;
|
return base64Password;
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -196,8 +197,8 @@ export const LdapProvider = (): TDynamicProviderFns => {
|
|||||||
return dnArray;
|
return dnArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; usernameTemplate?: string | null }) => {
|
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
|
||||||
const { inputs, usernameTemplate } = data;
|
const { inputs, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const client = await $getClient(providerInputs);
|
const client = await $getClient(providerInputs);
|
||||||
|
|
||||||
@@ -224,7 +225,7 @@ export const LdapProvider = (): TDynamicProviderFns => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const generatedLdif = generateLDIF({ username, password, ldifTemplate: providerInputs.creationLdif });
|
const generatedLdif = generateLDIF({ username, password, ldifTemplate: providerInputs.creationLdif });
|
||||||
|
|
||||||
|
|||||||
@@ -427,6 +427,9 @@ export type TDynamicProviderFns = {
|
|||||||
inputs: unknown;
|
inputs: unknown;
|
||||||
expireAt: number;
|
expireAt: number;
|
||||||
usernameTemplate?: string | null;
|
usernameTemplate?: string | null;
|
||||||
|
identity?: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
metadata: { projectId: string };
|
metadata: { projectId: string };
|
||||||
}) => Promise<{ entityId: string; data: unknown }>;
|
}) => Promise<{ entityId: string; data: unknown }>;
|
||||||
validateConnection: (inputs: unknown, metadata: { projectId: string }) => Promise<boolean>;
|
validateConnection: (inputs: unknown, metadata: { projectId: string }) => Promise<boolean>;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import axios, { AxiosError } from "axios";
|
import axios, { AxiosError } from "axios";
|
||||||
import handlebars from "handlebars";
|
|
||||||
import { customAlphabet } from "nanoid";
|
import { customAlphabet } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@@ -7,19 +6,20 @@ import { createDigestAuthRequestInterceptor } from "@app/lib/axios/digest-auth";
|
|||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
|
|
||||||
import { DynamicSecretMongoAtlasSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretMongoAtlasSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = (size = 48) => {
|
const generatePassword = (size = 48) => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
||||||
return customAlphabet(charset, 48)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
|
||||||
const randomUsername = alphaNumericNanoId(32);
|
const randomUsername = alphaNumericNanoId(32);
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,12 +64,17 @@ export const MongoAtlasProvider = (): TDynamicProviderFns => {
|
|||||||
return isConnected;
|
return isConnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: { name: string };
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const client = await $getClient(providerInputs);
|
const client = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const expiration = new Date(expireAt).toISOString();
|
const expiration = new Date(expireAt).toISOString();
|
||||||
await client({
|
await client({
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import handlebars from "handlebars";
|
|
||||||
import { MongoClient } from "mongodb";
|
import { MongoClient } from "mongodb";
|
||||||
import { customAlphabet } from "nanoid";
|
import { customAlphabet } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
@@ -7,19 +6,20 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretMongoDBSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretMongoDBSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = (size = 48) => {
|
const generatePassword = (size = 48) => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
||||||
return customAlphabet(charset, 48)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
const generateUsername = (usernameTemplate?: string | null, identity?: { name: string }) => {
|
||||||
const randomUsername = alphaNumericNanoId(32);
|
const randomUsername = alphaNumericNanoId(32);
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,12 +60,12 @@ export const MongoDBProvider = (): TDynamicProviderFns => {
|
|||||||
return isConnected;
|
return isConnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; usernameTemplate?: string | null }) => {
|
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
|
||||||
const { inputs, usernameTemplate } = data;
|
const { inputs, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const client = await $getClient(providerInputs);
|
const client = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
|
|
||||||
const db = client.db(providerInputs.database);
|
const db = client.db(providerInputs.database);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import axios, { Axios } from "axios";
|
import axios, { Axios } from "axios";
|
||||||
import handlebars from "handlebars";
|
|
||||||
import https from "https";
|
import https from "https";
|
||||||
import { customAlphabet } from "nanoid";
|
import { customAlphabet } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
@@ -9,19 +8,20 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretRabbitMqSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretRabbitMqSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = () => {
|
const generatePassword = () => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
||||||
return customAlphabet(charset, 64)();
|
return customAlphabet(charset, 64)();
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,12 +117,12 @@ export const RabbitMqProvider = (): TDynamicProviderFns => {
|
|||||||
return infoResponse;
|
return infoResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; usernameTemplate?: string | null }) => {
|
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
|
||||||
const { inputs, usernameTemplate } = data;
|
const { inputs, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const connection = await $getClient(providerInputs);
|
const connection = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
|
|
||||||
await createRabbitMqUser({
|
await createRabbitMqUser({
|
||||||
|
|||||||
@@ -9,19 +9,20 @@ import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretRedisDBSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretRedisDBSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = () => {
|
const generatePassword = () => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*";
|
||||||
return customAlphabet(charset, 64)();
|
return customAlphabet(charset, 64)();
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,12 +122,17 @@ export const RedisDatabaseProvider = (): TDynamicProviderFns => {
|
|||||||
return pingResponse;
|
return pingResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: { name: string };
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const connection = await $getClient(providerInputs);
|
const connection = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const expiration = new Date(expireAt).toISOString();
|
const expiration = new Date(expireAt).toISOString();
|
||||||
|
|
||||||
|
|||||||
@@ -9,19 +9,20 @@ import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretSapAseSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretSapAseSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = (size = 48) => {
|
const generatePassword = (size = 48) => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
return customAlphabet(charset, 48)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = `inf_${alphaNumericNanoId(25)}`; // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -87,11 +88,11 @@ export const SapAseProvider = (): TDynamicProviderFns => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; usernameTemplate?: string | null }) => {
|
const create = async (data: { inputs: unknown; usernameTemplate?: string | null; identity?: { name: string } }) => {
|
||||||
const { inputs, usernameTemplate } = data;
|
const { inputs, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
|
|
||||||
const client = await $getClient(providerInputs);
|
const client = await $getClient(providerInputs);
|
||||||
|
|||||||
@@ -15,19 +15,20 @@ import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars
|
|||||||
|
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretSapHanaSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretSapHanaSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const generatePassword = (size = 48) => {
|
const generatePassword = (size = 48) => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
return customAlphabet(charset, 48)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = alphaNumericNanoId(32); // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,11 +98,16 @@ export const SapHanaProvider = (): TDynamicProviderFns => {
|
|||||||
return testResult;
|
return testResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: { name: string };
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const expiration = new Date(expireAt).toISOString();
|
const expiration = new Date(expireAt).toISOString();
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
|
|||||||
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
|
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
|
||||||
|
|
||||||
import { DynamicSecretSnowflakeSchema, TDynamicProviderFns } from "./models";
|
import { DynamicSecretSnowflakeSchema, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
// destroy client requires callback...
|
// destroy client requires callback...
|
||||||
const noop = () => {};
|
const noop = () => {};
|
||||||
@@ -17,13 +18,13 @@ const generatePassword = (size = 48) => {
|
|||||||
return customAlphabet(charset, 48)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (usernameTemplate?: string | null) => {
|
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-"
|
const randomUsername = `infisical_${alphaNumericNanoId(32)}`; // Username must start with an ascii letter, so we prepend the username with "inf-"
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,13 +89,18 @@ export const SnowflakeProvider = (): TDynamicProviderFns => {
|
|||||||
return isValidConnection;
|
return isValidConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: { name: string };
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
|
|
||||||
const client = await $getClient(providerInputs);
|
const client = await $getClient(providerInputs);
|
||||||
|
|
||||||
const username = generateUsername(usernameTemplate);
|
const username = generateUsername(usernameTemplate, identity);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars
|
|||||||
import { TGatewayServiceFactory } from "../../gateway/gateway-service";
|
import { TGatewayServiceFactory } from "../../gateway/gateway-service";
|
||||||
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
import { verifyHostInputValidity } from "../dynamic-secret-fns";
|
||||||
import { DynamicSecretSqlDBSchema, PasswordRequirements, SqlProviders, TDynamicProviderFns } from "./models";
|
import { DynamicSecretSqlDBSchema, PasswordRequirements, SqlProviders, TDynamicProviderFns } from "./models";
|
||||||
|
import { compileUsernameTemplate } from "./templateUtils";
|
||||||
|
|
||||||
const EXTERNAL_REQUEST_TIMEOUT = 10 * 1000;
|
const EXTERNAL_REQUEST_TIMEOUT = 10 * 1000;
|
||||||
|
|
||||||
@@ -104,9 +105,8 @@ const generatePassword = (provider: SqlProviders, requirements?: PasswordRequire
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateUsername = (provider: SqlProviders, usernameTemplate?: string | null) => {
|
const generateUsername = (provider: SqlProviders, usernameTemplate?: string | null, identity?: { name: string }) => {
|
||||||
let randomUsername = "";
|
let randomUsername = "";
|
||||||
|
|
||||||
// For oracle, the client assumes everything is upper case when not using quotes around the password
|
// For oracle, the client assumes everything is upper case when not using quotes around the password
|
||||||
if (provider === SqlProviders.Oracle) {
|
if (provider === SqlProviders.Oracle) {
|
||||||
randomUsername = alphaNumericNanoId(32).toUpperCase();
|
randomUsername = alphaNumericNanoId(32).toUpperCase();
|
||||||
@@ -114,10 +114,13 @@ const generateUsername = (provider: SqlProviders, usernameTemplate?: string | nu
|
|||||||
randomUsername = alphaNumericNanoId(32);
|
randomUsername = alphaNumericNanoId(32);
|
||||||
}
|
}
|
||||||
if (!usernameTemplate) return randomUsername;
|
if (!usernameTemplate) return randomUsername;
|
||||||
|
return compileUsernameTemplate({
|
||||||
return handlebars.compile(usernameTemplate)({
|
usernameTemplate,
|
||||||
randomUsername,
|
randomUsername,
|
||||||
unixTimestamp: Math.floor(Date.now() / 100)
|
identity,
|
||||||
|
options: {
|
||||||
|
toUpperCase: provider === SqlProviders.Oracle
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -221,11 +224,16 @@ export const SqlDatabaseProvider = ({ gatewayService }: TSqlDatabaseProviderDTO)
|
|||||||
return isConnected;
|
return isConnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = async (data: { inputs: unknown; expireAt: number; usernameTemplate?: string | null }) => {
|
const create = async (data: {
|
||||||
const { inputs, expireAt, usernameTemplate } = data;
|
inputs: unknown;
|
||||||
|
expireAt: number;
|
||||||
|
usernameTemplate?: string | null;
|
||||||
|
identity?: { name: string };
|
||||||
|
}) => {
|
||||||
|
const { inputs, expireAt, usernameTemplate, identity } = data;
|
||||||
|
|
||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const username = generateUsername(providerInputs.client, usernameTemplate);
|
const username = generateUsername(providerInputs.client, usernameTemplate, identity);
|
||||||
|
|
||||||
const password = generatePassword(providerInputs.client, providerInputs.passwordRequirements);
|
const password = generatePassword(providerInputs.client, providerInputs.passwordRequirements);
|
||||||
const gatewayCallback = async (host = providerInputs.host, port = providerInputs.port) => {
|
const gatewayCallback = async (host = providerInputs.host, port = providerInputs.port) => {
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/* eslint-disable func-names */
|
||||||
|
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,
|
||||||
|
identity,
|
||||||
|
unixTimestamp,
|
||||||
|
options
|
||||||
|
}: {
|
||||||
|
usernameTemplate: string;
|
||||||
|
randomUsername: string;
|
||||||
|
identity?: { name: string };
|
||||||
|
unixTimestamp?: number;
|
||||||
|
options?: {
|
||||||
|
toUpperCase?: boolean;
|
||||||
|
};
|
||||||
|
}): string => {
|
||||||
|
// Create isolated handlebars instance
|
||||||
|
const hbs = handlebars.create();
|
||||||
|
|
||||||
|
// Register random helper on local instance
|
||||||
|
hbs.registerHelper("random", function (length: number) {
|
||||||
|
if (typeof length !== "number" || length <= 0 || length > 100) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return alphaNumericNanoId(length);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const re2Pattern = new RE2(searchValue, "g");
|
||||||
|
// Replace all occurrences
|
||||||
|
return re2Pattern.replace(textStr, 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) {
|
||||||
|
return textStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof length !== "number" || length <= 0) return textStr;
|
||||||
|
return textStr.substring(0, length);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Compile template with context using local instance
|
||||||
|
const context = {
|
||||||
|
randomUsername,
|
||||||
|
unixTimestamp: unixTimestamp || Math.floor(Date.now() / 100),
|
||||||
|
identity: {
|
||||||
|
name: identity?.name
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = hbs.compile(usernameTemplate)(context);
|
||||||
|
|
||||||
|
if (options?.toUpperCase) {
|
||||||
|
return result.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
@@ -7,13 +7,24 @@ type SanitizationArg = {
|
|||||||
allowedExpressions?: (arg: string) => boolean;
|
allowedExpressions?: (arg: string) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isValidExpression = (expression: string, dto: SanitizationArg): boolean => {
|
||||||
|
// Allow helper functions (replace, truncate)
|
||||||
|
const allowedHelpers = ["replace", "truncate", "random"];
|
||||||
|
if (allowedHelpers.includes(expression)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check regular allowed expressions
|
||||||
|
return dto?.allowedExpressions?.(expression) || false;
|
||||||
|
};
|
||||||
|
|
||||||
export const validateHandlebarTemplate = (templateName: string, template: string, dto: SanitizationArg) => {
|
export const validateHandlebarTemplate = (templateName: string, template: string, dto: SanitizationArg) => {
|
||||||
const parsedAst = handlebars.parse(template);
|
const parsedAst = handlebars.parse(template);
|
||||||
parsedAst.body.forEach((el) => {
|
parsedAst.body.forEach((el) => {
|
||||||
if (el.type === "ContentStatement") return;
|
if (el.type === "ContentStatement") return;
|
||||||
if (el.type === "MustacheStatement" && "path" in el) {
|
if (el.type === "MustacheStatement" && "path" in el) {
|
||||||
const { path } = el as { type: "MustacheStatement"; path: { type: "PathExpression"; original: string } };
|
const { path } = el as { type: "MustacheStatement"; path: { type: "PathExpression"; original: string } };
|
||||||
if (path.type === "PathExpression" && dto?.allowedExpressions?.(path.original)) return;
|
if (path.type === "PathExpression" && isValidExpression(path.original, dto)) return;
|
||||||
}
|
}
|
||||||
logger.error(el, "Template sanitization failed");
|
logger.error(el, "Template sanitization failed");
|
||||||
throw new BadRequestError({ message: `Template sanitization failed: ${templateName}` });
|
throw new BadRequestError({ message: `Template sanitization failed: ${templateName}` });
|
||||||
@@ -26,7 +37,7 @@ export const isValidHandleBarTemplate = (template: string, dto: SanitizationArg)
|
|||||||
if (el.type === "ContentStatement") return true;
|
if (el.type === "ContentStatement") return true;
|
||||||
if (el.type === "MustacheStatement" && "path" in el) {
|
if (el.type === "MustacheStatement" && "path" in el) {
|
||||||
const { path } = el as { type: "MustacheStatement"; path: { type: "PathExpression"; original: string } };
|
const { path } = el as { type: "MustacheStatement"; path: { type: "PathExpression"; original: string } };
|
||||||
if (path.type === "PathExpression" && dto?.allowedExpressions?.(path.original)) return true;
|
if (path.type === "PathExpression" && isValidExpression(path.original, dto)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1516,7 +1516,9 @@ export const registerRoutes = async (
|
|||||||
dynamicSecretProviders,
|
dynamicSecretProviders,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
licenseService,
|
licenseService,
|
||||||
kmsService
|
kmsService,
|
||||||
|
userDAL,
|
||||||
|
identityDAL
|
||||||
});
|
});
|
||||||
const dailyResourceCleanUp = dailyResourceCleanUpQueueServiceFactory({
|
const dailyResourceCleanUp = dailyResourceCleanUpQueueServiceFactory({
|
||||||
auditLogDAL,
|
auditLogDAL,
|
||||||
|
|||||||
@@ -101,6 +101,22 @@ The Infisical AWS ElastiCache dynamic secret allows you to generate AWS ElastiCa
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize ElastiCache Statement" type="string">
|
<ParamField path="Customize ElastiCache Statement" type="string">
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the ElastiCache statement to your needs. This is useful if you want to only give access to a specific resource.
|
If you want to provide specific privileges for the generated dynamic credentials, you can modify the ElastiCache statement to your needs. This is useful if you want to only give access to a specific resource.
|
||||||
|
|||||||
@@ -137,6 +137,29 @@ Replace **\<account id\>** with your AWS account id and **\<aws-scope-path\>** w
|
|||||||
Maximum time-to-live for a generated secret
|
Maximum time-to-live for a generated secret
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
|
<ParamField path="Username Template" type="string" default="{{randomUsername}}">
|
||||||
|
Specifies a template for generating usernames. This field allows customization of how usernames are automatically created.
|
||||||
|
|
||||||
|
Allowed template variables are
|
||||||
|
- `{{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
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
|
</ParamField>
|
||||||
<ParamField path="Method" type="string" required>
|
<ParamField path="Method" type="string" required>
|
||||||
Select *Assume Role* method.
|
Select *Assume Role* method.
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|||||||
@@ -85,6 +85,22 @@ The above configuration allows user creation and granting permissions.
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize CQL Statement" type="string">
|
<ParamField path="Customize CQL Statement" type="string">
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the CQL statement to your needs. This is useful if you want to only give access to a specific key-space(s).
|
If you want to provide specific privileges for the generated dynamic credentials, you can modify the CQL statement to your needs. This is useful if you want to only give access to a specific key-space(s).
|
||||||
|
|||||||
@@ -93,6 +93,22 @@ The port that your Elasticsearch instance is running on. _(Example: 9200)_
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -129,6 +129,22 @@ The Infisical LDAP dynamic secret allows you to generate user credentials on dem
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
</Step>
|
</Step>
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,22 @@ Create a project scoped API Key with the required permission in your Mongo Atlas
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize Scope" type="string">
|
<ParamField path="Customize Scope" type="string">
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,22 @@ Create a user with the required permission in your MongoDB instance. This user w
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -9,7 +9,6 @@ The Infisical MS SQL dynamic secret allows you to generate Microsoft SQL server
|
|||||||
|
|
||||||
Create a user with the required permission in your SQL instance. This user will be used to create new accounts on-demand.
|
Create a user with the required permission in your SQL instance. This user will be used to create new accounts on-demand.
|
||||||
|
|
||||||
|
|
||||||
## Set up Dynamic Secrets with MS SQL
|
## Set up Dynamic Secrets with MS SQL
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
@@ -78,10 +77,24 @@ Create a user with the required permission in your SQL instance. This user will
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize SQL Statement" type="string">
|
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s).
|
|
||||||
</ParamField>
|
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Click 'Submit'">
|
<Step title="Click 'Submit'">
|
||||||
After submitting the form, you will see a dynamic secret created in the dashboard.
|
After submitting the form, you will see a dynamic secret created in the dashboard.
|
||||||
@@ -91,6 +104,7 @@ Create a user with the required permission in your SQL instance. This user will
|
|||||||
</Note>
|
</Note>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Generate dynamic secrets">
|
<Step title="Generate dynamic secrets">
|
||||||
Once you've successfully configured the dynamic secret, you're ready to generate on-demand credentials.
|
Once you've successfully configured the dynamic secret, you're ready to generate on-demand credentials.
|
||||||
@@ -112,19 +126,23 @@ Create a user with the required permission in your SQL instance. This user will
|
|||||||
Once you click the `Submit` button, a new secret lease will be generated and the credentials for it will be shown to you.
|
Once you click the `Submit` button, a new secret lease will be generated and the credentials for it will be shown to you.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
## Audit or Revoke Leases
|
## Audit or Revoke Leases
|
||||||
|
|
||||||
Once you have created one or more leases, you will be able to access them by clicking on the respective dynamic secret item on the dashboard.
|
Once you have created one or more leases, you will be able to access them by clicking on the respective dynamic secret item on the dashboard.
|
||||||
This will allow you to see the expiration time of the lease or delete the lease before it's set time to live.
|
This will allow you to see the expiration time of the lease or delete the lease before it's set time to live.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Renew Leases
|
## Renew Leases
|
||||||
|
|
||||||
To extend the life of the generated dynamic secret leases past its initial time to live, simply click on the **Renew** button as illustrated below.
|
To extend the life of the generated dynamic secret leases past its initial time to live, simply click on the **Renew** button as illustrated below.
|
||||||

|

|
||||||
|
|
||||||
<Warning>
|
<Warning>
|
||||||
Lease renewals cannot exceed the maximum TTL set when configuring the dynamic secret
|
Lease renewals cannot exceed the maximum TTL set when configuring the dynamic
|
||||||
|
secret
|
||||||
</Warning>
|
</Warning>
|
||||||
|
|||||||
@@ -75,9 +75,22 @@ Create a user with the required permission in your SQL instance. This user will
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
</ParamField>
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
<ParamField path="Customize SQL Statement" type="string">
|
- `{{random N}}`: Random string of N characters
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s).
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Click `Submit`">
|
<Step title="Click `Submit`">
|
||||||
|
|||||||
@@ -77,9 +77,22 @@ Create a user with the required permission in your SQL instance. This user will
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
</ParamField>
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
<ParamField path="Customize SQL Statement" type="string">
|
- `{{random N}}`: Random string of N characters
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s).
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="Click 'Submit'">
|
<Step title="Click 'Submit'">
|
||||||
|
|||||||
@@ -78,6 +78,22 @@ Create a user with the required permission in your SQL instance. This user will
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize SQL Statement" type="string">
|
<ParamField path="Customize SQL Statement" type="string">
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s).
|
If you want to provide specific privileges for the generated dynamic credentials, you can modify the SQL statement to your needs. This is useful if you want to only give access to a specific table(s).
|
||||||
|
|||||||
@@ -71,6 +71,22 @@ Specifies a template for generating usernames. This field allows customization o
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField path="CA(SSL)" type="string">
|
<ParamField path="CA(SSL)" type="string">
|
||||||
|
|||||||
@@ -63,6 +63,22 @@ Create a user with the required permission in your Redis instance. This user wil
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize Redis Statement" type="string">
|
<ParamField path="Customize Redis Statement" type="string">
|
||||||
If you want to provide specific privileges for the generated dynamic credentials, you can modify the Redis statement to your needs. This is useful if you want to only give access to a specific table(s).
|
If you want to provide specific privileges for the generated dynamic credentials, you can modify the Redis statement to your needs. This is useful if you want to only give access to a specific table(s).
|
||||||
|
|||||||
@@ -70,6 +70,22 @@ The Infisical SAP ASE dynamic secret allows you to generate SAP ASE database cre
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize Statement" type="string">
|
<ParamField path="Customize Statement" type="string">
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,22 @@ The Infisical SAP HANA dynamic secret allows you to generate SAP HANA database c
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize Statement" type="string">
|
<ParamField path="Customize Statement" type="string">
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,22 @@ Infisical's Snowflake dynamic secrets allow you to generate Snowflake user crede
|
|||||||
Allowed template variables are
|
Allowed template variables are
|
||||||
- `{{randomUsername}}`: Random username string
|
- `{{randomUsername}}`: Random username string
|
||||||
- `{{unixTimestamp}}`: Current Unix timestamp
|
- `{{unixTimestamp}}`: Current Unix timestamp
|
||||||
|
- `{{identity.name}}`: Name of the identity that is generating the secret
|
||||||
|
- `{{random N}}`: Random string of N characters
|
||||||
|
|
||||||
|
Allowed template functions are
|
||||||
|
- `truncate`: Truncates a string to a specified length
|
||||||
|
- `replace`: Replaces a substring with another value
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
{{randomUsername}} // 3POnzeFyK9gW2nioK0q2gMjr6CZqsRiX
|
||||||
|
{{unixTimestamp}} // 17490641580
|
||||||
|
{{identity.name}} // testuser
|
||||||
|
{{random-5}} // x9k2m
|
||||||
|
{{truncate identity.name 4}} // test
|
||||||
|
{{replace identity.name 'user' 'replace'}} // testreplace
|
||||||
|
```
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField path="Customize Statement" type="string">
|
<ParamField path="Customize Statement" type="string">
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user