mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 13:27:22 +00:00
feat(server): updated dynamic secret names from feedback, added describe and fixed login not working
This commit is contained in:
@@ -8,7 +8,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
if (!doesTableExist) {
|
if (!doesTableExist) {
|
||||||
await knex.schema.createTable(TableName.DynamicSecret, (t) => {
|
await knex.schema.createTable(TableName.DynamicSecret, (t) => {
|
||||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
t.string("slug").notNullable();
|
t.string("name").notNullable();
|
||||||
t.integer("version").notNullable();
|
t.integer("version").notNullable();
|
||||||
t.string("type").notNullable();
|
t.string("type").notNullable();
|
||||||
t.string("defaultTTL").notNullable();
|
t.string("defaultTTL").notNullable();
|
||||||
@@ -23,7 +23,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.string("status");
|
t.string("status");
|
||||||
t.string("statusDetails");
|
t.string("statusDetails");
|
||||||
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
|
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
|
||||||
t.unique(["slug", "folderId"]);
|
t.unique(["name", "folderId"]);
|
||||||
t.timestamps(true, true, true);
|
t.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { TImmutableDBKeys } from "./models";
|
|||||||
|
|
||||||
export const DynamicSecretsSchema = z.object({
|
export const DynamicSecretsSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
slug: z.string(),
|
name: z.string(),
|
||||||
version: z.number(),
|
version: z.number(),
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
defaultTTL: z.string(),
|
defaultTTL: z.string(),
|
||||||
|
|||||||
@@ -285,3 +285,81 @@ export const AUDIT_LOGS = {
|
|||||||
actor: "The actor to filter the audit logs by."
|
actor: "The actor to filter the audit logs by."
|
||||||
}
|
}
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const DYNAMIC_SECRETS = {
|
||||||
|
LIST: {
|
||||||
|
projectSlug: "The slug of the project to create dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to list folders from.",
|
||||||
|
path: "The path to list folders from."
|
||||||
|
},
|
||||||
|
LIST_LEAES_BY_NAME: {
|
||||||
|
projectSlug: "The slug of the project to create dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to list folders from.",
|
||||||
|
path: "The path to list folders from.",
|
||||||
|
name: "The name of the dynamic secret."
|
||||||
|
},
|
||||||
|
GET_BY_NAME: {
|
||||||
|
projectSlug: "The slug of the project to create dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to list folders from.",
|
||||||
|
path: "The path to list folders from.",
|
||||||
|
name: "The name of the dynamic secret."
|
||||||
|
},
|
||||||
|
CREATE: {
|
||||||
|
projectSlug: "The slug of the project to create dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to create the dynamic secret in.",
|
||||||
|
path: "The path to create the dynamic secret in.",
|
||||||
|
name: "The name of the dynamic secret.",
|
||||||
|
provider: "The type of dynamic secret.",
|
||||||
|
defaultTTL: "The default TTL that will be applied for all the leases.",
|
||||||
|
maxTTL: "The maximum limit a TTL can be leases or renewed."
|
||||||
|
},
|
||||||
|
UPDATE: {
|
||||||
|
projectSlug: "The slug of the project to update dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to update the dynamic secret in.",
|
||||||
|
path: "The path to update the dynamic secret in.",
|
||||||
|
name: "The name of the dynamic secret.",
|
||||||
|
inputs: "The new partial values for the configurated provider of the dynamic secret",
|
||||||
|
defaultTTL: "The default TTL that will be applied for all the leases.",
|
||||||
|
maxTTL: "The maximum limit a TTL can be leases or renewed.",
|
||||||
|
newName: "The new name for the dynamic secret."
|
||||||
|
},
|
||||||
|
DELETE: {
|
||||||
|
projectSlug: "The slug of the project to delete dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to delete the dynamic secret in.",
|
||||||
|
path: "The path to delete the dynamic secret in.",
|
||||||
|
name: "The name of the dynamic secret.",
|
||||||
|
isForced:
|
||||||
|
"A boolean flag to delete the the dynamic secret from infisical without trying to remove it from external provider. Used when the dynamic secret got modified externally."
|
||||||
|
}
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const DYNAMIC_SECRET_LEASES = {
|
||||||
|
GET_BY_LEASEID: {
|
||||||
|
projectSlug: "The slug of the project to create dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment to list folders from.",
|
||||||
|
path: "The path to list folders from.",
|
||||||
|
leaseId: "The ID of the dynamic secret lease."
|
||||||
|
},
|
||||||
|
CREATE: {
|
||||||
|
projectSlug: "The slug of the project of the dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment of the dynamic secret in.",
|
||||||
|
path: "The path of the dynamic secret in.",
|
||||||
|
dynamicSecretName: "The name of the dynamic secret.",
|
||||||
|
ttl: "The lease lifetime ttl. If not provided the default TTL of dynamic secret will be used."
|
||||||
|
},
|
||||||
|
RENEW: {
|
||||||
|
projectSlug: "The slug of the project of the dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment of the dynamic secret in.",
|
||||||
|
path: "The path of the dynamic secret in.",
|
||||||
|
leaseId: "The ID of the dynamic secret lease.",
|
||||||
|
ttl: "The renew TTL that gets added with current expiry (ensure it's below max TTL) for a total less than creation time + max TTL."
|
||||||
|
},
|
||||||
|
DELETE: {
|
||||||
|
projectSlug: "The slug of the project of the dynamic secret in.",
|
||||||
|
environmentSlug: "The slug of the environment of the dynamic secret in.",
|
||||||
|
path: "The path of the dynamic secret in.",
|
||||||
|
leaseId: "The ID of the dynamic secret lease.",
|
||||||
|
isForced:
|
||||||
|
"A boolean flag to delete the the dynamic secret from infisical without trying to remove it from external provider. Used when the dynamic secret got modified externally."
|
||||||
|
}
|
||||||
|
} as const;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import ms from "ms";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
||||||
|
import { DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
|
||||||
import { daysToMillisecond } from "@app/lib/dates";
|
import { daysToMillisecond } from "@app/lib/dates";
|
||||||
import { removeTrailingSlash } from "@app/lib/fn";
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@@ -15,11 +16,12 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z.string().min(1),
|
dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(),
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.projectSlug),
|
||||||
ttl: z
|
ttl: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
|
.describe(DYNAMIC_SECRET_LEASES.CREATE.ttl)
|
||||||
.superRefine((val, ctx) => {
|
.superRefine((val, ctx) => {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
const valMs = ms(val);
|
const valMs = ms(val);
|
||||||
@@ -28,8 +30,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
if (valMs > daysToMillisecond(1))
|
if (valMs > daysToMillisecond(1))
|
||||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||||
}),
|
}),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRET_LEASES.CREATE.path),
|
||||||
environment: z.string().min(1)
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.path)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -46,6 +48,7 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
|
name: req.body.dynamicSecretName,
|
||||||
...req.body
|
...req.body
|
||||||
});
|
});
|
||||||
return { lease, data, dynamicSecret };
|
return { lease, data, dynamicSecret };
|
||||||
@@ -57,13 +60,19 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
leaseId: z.string()
|
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.projectSlug),
|
||||||
path: z.string().min(1).trim().default("/").transform(removeTrailingSlash),
|
path: z
|
||||||
environment: z.string().min(1),
|
.string()
|
||||||
isForced: z.boolean().default(false)
|
.min(1)
|
||||||
|
.trim()
|
||||||
|
.default("/")
|
||||||
|
.transform(removeTrailingSlash)
|
||||||
|
.describe(DYNAMIC_SECRET_LEASES.DELETE.path),
|
||||||
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.environmentSlug),
|
||||||
|
isForced: z.boolean().default(false).describe(DYNAMIC_SECRET_LEASES.DELETE.isForced)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -90,11 +99,12 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
leaseId: z.string()
|
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
ttl: z
|
ttl: z
|
||||||
.string()
|
.string()
|
||||||
|
.describe(DYNAMIC_SECRET_LEASES.RENEW.ttl)
|
||||||
.optional()
|
.optional()
|
||||||
.superRefine((val, ctx) => {
|
.superRefine((val, ctx) => {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
@@ -104,9 +114,15 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
if (valMs > daysToMillisecond(1))
|
if (valMs > daysToMillisecond(1))
|
||||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||||
}),
|
}),
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.projectSlug),
|
||||||
path: z.string().min(1).trim().default("/").transform(removeTrailingSlash),
|
path: z
|
||||||
environment: z.string().min(1)
|
.string()
|
||||||
|
.min(1)
|
||||||
|
.trim()
|
||||||
|
.default("/")
|
||||||
|
.transform(removeTrailingSlash)
|
||||||
|
.describe(DYNAMIC_SECRET_LEASES.RENEW.path),
|
||||||
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.ttl)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -133,12 +149,17 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
leaseId: z.string()
|
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId)
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z
|
||||||
environment: z.string().min(1)
|
.string()
|
||||||
|
.trim()
|
||||||
|
.default("/")
|
||||||
|
.transform(removeTrailingSlash)
|
||||||
|
.describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.path),
|
||||||
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.environmentSlug)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import slugify from "@sindresorhus/slugify";
|
||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
||||||
|
import { DYNAMIC_SECRETS } from "@app/lib/api-docs";
|
||||||
import { daysToMillisecond } from "@app/lib/dates";
|
import { daysToMillisecond } from "@app/lib/dates";
|
||||||
import { removeTrailingSlash } from "@app/lib/fn";
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@@ -16,17 +18,21 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug),
|
||||||
provider: DynamicSecretProviderSchema,
|
provider: DynamicSecretProviderSchema.describe(DYNAMIC_SECRETS.CREATE.provider),
|
||||||
defaultTTL: z.string().superRefine((val, ctx) => {
|
defaultTTL: z
|
||||||
const valMs = ms(val);
|
.string()
|
||||||
if (valMs < 60 * 1000)
|
.describe(DYNAMIC_SECRETS.CREATE.defaultTTL)
|
||||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
|
.superRefine((val, ctx) => {
|
||||||
if (valMs > daysToMillisecond(1))
|
const valMs = ms(val);
|
||||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
if (valMs < 60 * 1000)
|
||||||
}),
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
|
||||||
|
if (valMs > daysToMillisecond(1))
|
||||||
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||||
|
}),
|
||||||
maxTTL: z
|
maxTTL: z
|
||||||
.string()
|
.string()
|
||||||
|
.describe(DYNAMIC_SECRETS.CREATE.maxTTL)
|
||||||
.optional()
|
.optional()
|
||||||
.superRefine((val, ctx) => {
|
.superRefine((val, ctx) => {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
@@ -37,9 +43,17 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||||
})
|
})
|
||||||
.nullable(),
|
.nullable(),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z.string().describe(DYNAMIC_SECRETS.CREATE.path).trim().default("/").transform(removeTrailingSlash),
|
||||||
environment: z.string().min(1),
|
environmentSlug: z.string().describe(DYNAMIC_SECRETS.CREATE.environmentSlug).min(1),
|
||||||
slug: z.string().min(1).toLowerCase()
|
name: z
|
||||||
|
.string()
|
||||||
|
.describe(DYNAMIC_SECRETS.CREATE.name)
|
||||||
|
.min(1)
|
||||||
|
.toLowerCase()
|
||||||
|
.max(64)
|
||||||
|
.refine((v) => slugify(v) === v, {
|
||||||
|
message: "Slug must be a valid"
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -61,20 +75,21 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:slug",
|
url: "/:name",
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: z.string()
|
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.UPDATE.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.UPDATE.path),
|
||||||
environment: z.string().min(1),
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.UPDATE.environmentSlug),
|
||||||
data: z.object({
|
data: z.object({
|
||||||
inputs: z.any().optional(),
|
inputs: z.any().optional().describe(DYNAMIC_SECRETS.UPDATE.inputs),
|
||||||
defaultTTL: z
|
defaultTTL: z
|
||||||
.string()
|
.string()
|
||||||
|
.describe(DYNAMIC_SECRETS.UPDATE.defaultTTL)
|
||||||
.optional()
|
.optional()
|
||||||
.superRefine((val, ctx) => {
|
.superRefine((val, ctx) => {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
@@ -86,6 +101,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
}),
|
}),
|
||||||
maxTTL: z
|
maxTTL: z
|
||||||
.string()
|
.string()
|
||||||
|
.describe(DYNAMIC_SECRETS.UPDATE.maxTTL)
|
||||||
.optional()
|
.optional()
|
||||||
.superRefine((val, ctx) => {
|
.superRefine((val, ctx) => {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
@@ -96,7 +112,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||||
})
|
})
|
||||||
.nullable(),
|
.nullable(),
|
||||||
newSlug: z.string().optional()
|
newName: z.string().describe(DYNAMIC_SECRETS.UPDATE.newName).optional()
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@@ -107,15 +123,15 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const dynamicSecretCfg = await server.services.dynamicSecret.updateBySlug({
|
const dynamicSecretCfg = await server.services.dynamicSecret.updateByName({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
slug: req.params.slug,
|
name: req.params.name,
|
||||||
path: req.body.path,
|
path: req.body.path,
|
||||||
projectSlug: req.body.projectSlug,
|
projectSlug: req.body.projectSlug,
|
||||||
environment: req.body.environment,
|
environmentSlug: req.body.environmentSlug,
|
||||||
...req.body.data
|
...req.body.data
|
||||||
});
|
});
|
||||||
return { dynamicSecret: dynamicSecretCfg };
|
return { dynamicSecret: dynamicSecretCfg };
|
||||||
@@ -123,17 +139,17 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:slug",
|
url: "/:name",
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: z.string()
|
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.DELETE.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.DELETE.path),
|
||||||
environment: z.string().min(1),
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.DELETE.environmentSlug),
|
||||||
isForced: z.boolean().default(false)
|
isForced: z.boolean().default(false).describe(DYNAMIC_SECRETS.DELETE.isForced)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -143,12 +159,12 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const dynamicSecretCfg = await server.services.dynamicSecret.deleteBySlug({
|
const dynamicSecretCfg = await server.services.dynamicSecret.deleteByName({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
slug: req.params.slug,
|
name: req.params.name,
|
||||||
...req.body
|
...req.body
|
||||||
});
|
});
|
||||||
return { dynamicSecret: dynamicSecretCfg };
|
return { dynamicSecret: dynamicSecretCfg };
|
||||||
@@ -156,16 +172,16 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:slug",
|
url: "/:name",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: z.string()
|
name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name)
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.GET_BY_NAME.path),
|
||||||
environment: z.string().min(1)
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.environmentSlug)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -182,7 +198,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
slug: req.params.slug,
|
name: req.params.name,
|
||||||
...req.query
|
...req.query
|
||||||
});
|
});
|
||||||
return { dynamicSecret: dynamicSecretCfg };
|
return { dynamicSecret: dynamicSecretCfg };
|
||||||
@@ -194,9 +210,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.LIST.path),
|
||||||
environment: z.string().min(1)
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.environmentSlug)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -218,16 +234,21 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:slug/leases",
|
url: "/:name/leases",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: z.string()
|
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.name)
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectSlug: z.string().min(1),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
path: z
|
||||||
environment: z.string().min(1)
|
.string()
|
||||||
|
.trim()
|
||||||
|
.default("/")
|
||||||
|
.transform(removeTrailingSlash)
|
||||||
|
.describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.path),
|
||||||
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.environmentSlug)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -242,7 +263,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
slug: req.params.slug,
|
name: req.params.name,
|
||||||
...req.query
|
...req.query
|
||||||
});
|
});
|
||||||
return { leases };
|
return { leases };
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const dynamicSecretLeaseDALFactory = (db: TDbClient) => {
|
|||||||
.select(selectAllTableCols(TableName.DynamicSecretLease))
|
.select(selectAllTableCols(TableName.DynamicSecretLease))
|
||||||
.select(
|
.select(
|
||||||
db.ref("id").withSchema(TableName.DynamicSecret).as("dynId"),
|
db.ref("id").withSchema(TableName.DynamicSecret).as("dynId"),
|
||||||
db.ref("slug").withSchema(TableName.DynamicSecret).as("dynSlug"),
|
db.ref("name").withSchema(TableName.DynamicSecret).as("dynName"),
|
||||||
db.ref("version").withSchema(TableName.DynamicSecret).as("dynVersion"),
|
db.ref("version").withSchema(TableName.DynamicSecret).as("dynVersion"),
|
||||||
db.ref("type").withSchema(TableName.DynamicSecret).as("dynType"),
|
db.ref("type").withSchema(TableName.DynamicSecret).as("dynType"),
|
||||||
db.ref("defaultTTL").withSchema(TableName.DynamicSecret).as("dynDefaultTTL"),
|
db.ref("defaultTTL").withSchema(TableName.DynamicSecret).as("dynDefaultTTL"),
|
||||||
@@ -54,7 +54,7 @@ export const dynamicSecretLeaseDALFactory = (db: TDbClient) => {
|
|||||||
...DynamicSecretLeasesSchema.parse(doc),
|
...DynamicSecretLeasesSchema.parse(doc),
|
||||||
dynamicSecret: {
|
dynamicSecret: {
|
||||||
id: doc.dynId,
|
id: doc.dynId,
|
||||||
slug: doc.dynSlug,
|
name: doc.dynName,
|
||||||
version: doc.dynVersion,
|
version: doc.dynVersion,
|
||||||
type: doc.dynType,
|
type: doc.dynType,
|
||||||
defaultTTL: doc.dynDefaultTTL,
|
defaultTTL: doc.dynDefaultTTL,
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
projectDAL
|
projectDAL
|
||||||
}: TDynamicSecretLeaseServiceFactoryDep) => {
|
}: TDynamicSecretLeaseServiceFactoryDep) => {
|
||||||
const create = async ({
|
const create = async ({
|
||||||
environment,
|
environmentSlug,
|
||||||
path,
|
path,
|
||||||
slug,
|
name,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
@@ -69,13 +69,13 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ slug, folderId: folder.id });
|
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||||
|
|
||||||
const totalLeasesTaken = await dynamicSecretLeaseDAL.countLeasesForDynamicSecret(dynamicSecretCfg.id);
|
const totalLeasesTaken = await dynamicSecretLeaseDAL.countLeasesForDynamicSecret(dynamicSecretCfg.id);
|
||||||
@@ -119,7 +119,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
path,
|
path,
|
||||||
environment,
|
environmentSlug,
|
||||||
leaseId
|
leaseId
|
||||||
}: TRenewDynamicSecretLeaseDTO) => {
|
}: TRenewDynamicSecretLeaseDTO) => {
|
||||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
@@ -135,10 +135,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||||
@@ -180,7 +180,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
|
|
||||||
const revokeLease = async ({
|
const revokeLease = async ({
|
||||||
leaseId,
|
leaseId,
|
||||||
environment,
|
environmentSlug,
|
||||||
path,
|
path,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
actor,
|
actor,
|
||||||
@@ -202,10 +202,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Delete,
|
ProjectPermissionActions.Delete,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||||
@@ -245,12 +245,12 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
|
|
||||||
const listLeases = async ({
|
const listLeases = async ({
|
||||||
path,
|
path,
|
||||||
slug,
|
name,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
environment,
|
environmentSlug,
|
||||||
actorAuthMethod
|
actorAuthMethod
|
||||||
}: TListDynamicSecretLeasesDTO) => {
|
}: TListDynamicSecretLeasesDTO) => {
|
||||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
@@ -266,13 +266,13 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ slug, folderId: folder.id });
|
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||||
|
|
||||||
const dynamicSecretLeases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id });
|
const dynamicSecretLeases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id });
|
||||||
@@ -283,7 +283,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
projectSlug,
|
projectSlug,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
path,
|
path,
|
||||||
environment,
|
environmentSlug,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
leaseId,
|
leaseId,
|
||||||
@@ -302,10 +302,10 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ export enum DynamicSecretLeaseStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type TCreateDynamicSecretLeaseDTO = {
|
export type TCreateDynamicSecretLeaseDTO = {
|
||||||
slug: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
ttl?: string;
|
ttl?: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
@@ -15,21 +15,21 @@ export type TCreateDynamicSecretLeaseDTO = {
|
|||||||
export type TDetailsDynamicSecretLeaseDTO = {
|
export type TDetailsDynamicSecretLeaseDTO = {
|
||||||
leaseId: string;
|
leaseId: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TListDynamicSecretLeasesDTO = {
|
export type TListDynamicSecretLeasesDTO = {
|
||||||
slug: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TDeleteDynamicSecretLeaseDTO = {
|
export type TDeleteDynamicSecretLeaseDTO = {
|
||||||
leaseId: string;
|
leaseId: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
isForced?: boolean;
|
isForced?: boolean;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
@@ -37,7 +37,7 @@ export type TDeleteDynamicSecretLeaseDTO = {
|
|||||||
export type TRenewDynamicSecretLeaseDTO = {
|
export type TRenewDynamicSecretLeaseDTO = {
|
||||||
leaseId: string;
|
leaseId: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
ttl?: string;
|
ttl?: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
const create = async ({
|
const create = async ({
|
||||||
path,
|
path,
|
||||||
actor,
|
actor,
|
||||||
slug,
|
name,
|
||||||
actorId,
|
actorId,
|
||||||
maxTTL,
|
maxTTL,
|
||||||
provider,
|
provider,
|
||||||
environment,
|
environmentSlug,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
defaultTTL,
|
defaultTTL,
|
||||||
@@ -71,13 +71,13 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const existingDynamicSecret = await dynamicSecretDAL.findOne({ slug, folderId: folder.id });
|
const existingDynamicSecret = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||||
if (existingDynamicSecret)
|
if (existingDynamicSecret)
|
||||||
throw new BadRequestError({ message: "Provided dynamic secret already exist under the folder" });
|
throw new BadRequestError({ message: "Provided dynamic secret already exist under the folder" });
|
||||||
|
|
||||||
@@ -99,22 +99,22 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
maxTTL,
|
maxTTL,
|
||||||
defaultTTL,
|
defaultTTL,
|
||||||
folderId: folder.id,
|
folderId: folder.id,
|
||||||
slug
|
name
|
||||||
});
|
});
|
||||||
return dynamicSecretCfg;
|
return dynamicSecretCfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateBySlug = async ({
|
const updateByName = async ({
|
||||||
slug,
|
name,
|
||||||
maxTTL,
|
maxTTL,
|
||||||
defaultTTL,
|
defaultTTL,
|
||||||
inputs,
|
inputs,
|
||||||
environment,
|
environmentSlug,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
path,
|
path,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
newSlug,
|
newName,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod
|
actorAuthMethod
|
||||||
}: TUpdateDynamicSecretDTO) => {
|
}: TUpdateDynamicSecretDTO) => {
|
||||||
@@ -132,17 +132,17 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ slug, folderId: folder.id });
|
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||||
|
|
||||||
if (newSlug) {
|
if (newName) {
|
||||||
const existingDynamicSecret = await dynamicSecretDAL.findOne({ slug: newSlug, folderId: folder.id });
|
const existingDynamicSecret = await dynamicSecretDAL.findOne({ name: newName, folderId: folder.id });
|
||||||
if (existingDynamicSecret)
|
if (existingDynamicSecret)
|
||||||
throw new BadRequestError({ message: "Provided dynamic secret already exist under the folder" });
|
throw new BadRequestError({ message: "Provided dynamic secret already exist under the folder" });
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
keyEncoding: encryptedInput.encoding,
|
keyEncoding: encryptedInput.encoding,
|
||||||
maxTTL,
|
maxTTL,
|
||||||
defaultTTL,
|
defaultTTL,
|
||||||
slug: newSlug ?? slug,
|
name: newName ?? name,
|
||||||
status: null,
|
status: null,
|
||||||
statusDetails: null
|
statusDetails: null
|
||||||
});
|
});
|
||||||
@@ -179,15 +179,15 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
return updatedDynamicCfg;
|
return updatedDynamicCfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteBySlug = async ({
|
const deleteByName = async ({
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorId,
|
actorId,
|
||||||
actor,
|
actor,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
slug,
|
name,
|
||||||
path,
|
path,
|
||||||
environment,
|
environmentSlug,
|
||||||
isForced
|
isForced
|
||||||
}: TDeleteDynamicSecretDTO) => {
|
}: TDeleteDynamicSecretDTO) => {
|
||||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
@@ -204,13 +204,13 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ slug, folderId: folder.id });
|
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||||
|
|
||||||
const leases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id });
|
const leases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id });
|
||||||
@@ -239,10 +239,10 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDetails = async ({
|
const getDetails = async ({
|
||||||
slug,
|
name,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
path,
|
path,
|
||||||
environment,
|
environmentSlug,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorId,
|
actorId,
|
||||||
@@ -261,13 +261,13 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ slug, folderId: folder.id });
|
const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id });
|
||||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||||
const decryptedStoredInput = JSON.parse(
|
const decryptedStoredInput = JSON.parse(
|
||||||
infisicalSymmetricDecrypt({
|
infisicalSymmetricDecrypt({
|
||||||
@@ -289,7 +289,7 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
projectSlug,
|
projectSlug,
|
||||||
path,
|
path,
|
||||||
environment
|
environmentSlug
|
||||||
}: TListDynamicSecretsDTO) => {
|
}: TListDynamicSecretsDTO) => {
|
||||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
@@ -304,10 +304,10 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
subject(ProjectPermissionSub.Secrets, { environment: environmentSlug, secretPath: path })
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
const dynamicSecretCfg = await dynamicSecretDAL.find({ folderId: folder.id });
|
const dynamicSecretCfg = await dynamicSecretDAL.find({ folderId: folder.id });
|
||||||
@@ -316,8 +316,8 @@ export const dynamicSecretServiceFactory = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
create,
|
create,
|
||||||
updateBySlug,
|
updateByName,
|
||||||
deleteBySlug,
|
deleteByName,
|
||||||
getDetails,
|
getDetails,
|
||||||
list
|
list
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,39 +16,39 @@ export type TCreateDynamicSecretDTO = {
|
|||||||
defaultTTL: string;
|
defaultTTL: string;
|
||||||
maxTTL?: string | null;
|
maxTTL?: string | null;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
slug: string;
|
name: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TUpdateDynamicSecretDTO = {
|
export type TUpdateDynamicSecretDTO = {
|
||||||
slug: string;
|
name: string;
|
||||||
newSlug?: string;
|
newName?: string;
|
||||||
defaultTTL?: string;
|
defaultTTL?: string;
|
||||||
maxTTL?: string | null;
|
maxTTL?: string | null;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
inputs?: TProvider["inputs"];
|
inputs?: TProvider["inputs"];
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TDeleteDynamicSecretDTO = {
|
export type TDeleteDynamicSecretDTO = {
|
||||||
slug: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
isForced?: boolean;
|
isForced?: boolean;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TDetailsDynamicSecretDTO = {
|
export type TDetailsDynamicSecretDTO = {
|
||||||
slug: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TListDynamicSecretsDTO = {
|
export type TListDynamicSecretsDTO = {
|
||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environmentSlug: string;
|
||||||
projectSlug: string;
|
projectSlug: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import { DynamicSecretSqlDBSchema, TDynamicProviderFns } from "./models";
|
|||||||
const EXTERNAL_REQUEST_TIMEOUT = 10 * 1000;
|
const EXTERNAL_REQUEST_TIMEOUT = 10 * 1000;
|
||||||
|
|
||||||
const generatePassword = (size?: number) => {
|
const generatePassword = (size?: number) => {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*'$#";
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*$#";
|
||||||
return customAlphabet(charset, 32)(size);
|
return customAlphabet(charset, 48)(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SqlDatabaseProvider = (): TDynamicProviderFns => {
|
export const SqlDatabaseProvider = (): TDynamicProviderFns => {
|
||||||
@@ -61,13 +61,13 @@ export const SqlDatabaseProvider = (): TDynamicProviderFns => {
|
|||||||
const providerInputs = await validateProviderInputs(inputs);
|
const providerInputs = await validateProviderInputs(inputs);
|
||||||
const db = await getClient(providerInputs);
|
const db = await getClient(providerInputs);
|
||||||
|
|
||||||
const username = alphaNumericNanoId(21);
|
const username = alphaNumericNanoId(32);
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const expiration = new Date(expireAt).toISOString();
|
const expiration = new Date(expireAt).toISOString();
|
||||||
|
|
||||||
const creationStatement = handlebars.compile(providerInputs.creationStatement, { noEscape: true })({
|
const creationStatement = handlebars.compile(providerInputs.creationStatement, { noEscape: true })({
|
||||||
username,
|
username,
|
||||||
password: "infisical",
|
password,
|
||||||
expiration
|
expiration
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user