mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-21 19:34:05 +00:00
Compare commits
15 Commits
feat/resou
...
auth0-saml
Author | SHA1 | Date | |
---|---|---|---|
e6103d2d3f | |||
0cefd6f837 | |||
f632847dc6 | |||
faa6d1cf40 | |||
7fb18870e3 | |||
ae841715e5 | |||
baac87c16a | |||
b726187ba3 | |||
d98ff32b07 | |||
1fa510b32f | |||
c57f0d8120 | |||
00490f2cff | |||
ee58f538c0 | |||
1190ca2d77 | |||
2fb60201bc |
backend/src
@types
db
migrations
schemas
ee
routes/v1
services
saml-config
secret-approval-request
secret-approval-request-secret-dal.tssecret-approval-request-service.tssecret-approval-request-types.ts
secret-replication
lib/api-docs
server/routes
services
external-migration
integration-auth
integration
resource-metadata
secret-import
secret-v2-bridge
secret
docs
documentation/platform
images
integrations/aws
sso/auth0-saml
integrations/cloud
mint.jsonfrontend/src
const
hooks/api
pages
organization/SettingsPage/components/OrgAuthTab
secret-manager
IntegrationsDetailsByIDPage/components
IntegrationsListPage
SecretApprovalsPage/components/SecretApprovalRequest/components
SecretDashboardPage/components/SecretListView
integrations
AwsSecretManagerConfigurePage
AzureAppConfigurationConfigurePage
AzureKeyVaultAuthorizePage
CircleCIConfigurePage
8
backend/src/@types/knex.d.ts
vendored
8
backend/src/@types/knex.d.ts
vendored
@ -218,9 +218,6 @@ import {
|
||||
TRateLimit,
|
||||
TRateLimitInsert,
|
||||
TRateLimitUpdate,
|
||||
TResourceMetadata,
|
||||
TResourceMetadataInsert,
|
||||
TResourceMetadataUpdate,
|
||||
TSamlConfigs,
|
||||
TSamlConfigsInsert,
|
||||
TSamlConfigsUpdate,
|
||||
@ -890,11 +887,6 @@ declare module "knex/types/tables" {
|
||||
TProjectSplitBackfillIdsInsert,
|
||||
TProjectSplitBackfillIdsUpdate
|
||||
>;
|
||||
[TableName.ResourceMetadata]: KnexOriginal.CompositeTableType<
|
||||
TResourceMetadata,
|
||||
TResourceMetadataInsert,
|
||||
TResourceMetadataUpdate
|
||||
>;
|
||||
[TableName.AppConnection]: KnexOriginal.CompositeTableType<
|
||||
TAppConnections,
|
||||
TAppConnectionsInsert,
|
||||
|
@ -1,40 +0,0 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.ResourceMetadata))) {
|
||||
await knex.schema.createTable(TableName.ResourceMetadata, (tb) => {
|
||||
tb.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
tb.string("key").notNullable();
|
||||
tb.string("value", 1020).notNullable();
|
||||
tb.uuid("orgId").notNullable();
|
||||
tb.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
tb.uuid("userId");
|
||||
tb.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
tb.uuid("identityId");
|
||||
tb.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
tb.uuid("secretId");
|
||||
tb.foreign("secretId").references("id").inTable(TableName.SecretV2).onDelete("CASCADE");
|
||||
tb.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
const hasSecretMetadataField = await knex.schema.hasColumn(TableName.SecretApprovalRequestSecretV2, "secretMetadata");
|
||||
if (!hasSecretMetadataField) {
|
||||
await knex.schema.alterTable(TableName.SecretApprovalRequestSecretV2, (t) => {
|
||||
t.jsonb("secretMetadata");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.ResourceMetadata);
|
||||
|
||||
const hasSecretMetadataField = await knex.schema.hasColumn(TableName.SecretApprovalRequestSecretV2, "secretMetadata");
|
||||
if (hasSecretMetadataField) {
|
||||
await knex.schema.alterTable(TableName.SecretApprovalRequestSecretV2, (t) => {
|
||||
t.dropColumn("secretMetadata");
|
||||
});
|
||||
}
|
||||
}
|
@ -71,7 +71,6 @@ export * from "./project-user-additional-privilege";
|
||||
export * from "./project-user-membership-roles";
|
||||
export * from "./projects";
|
||||
export * from "./rate-limit";
|
||||
export * from "./resource-metadata";
|
||||
export * from "./saml-configs";
|
||||
export * from "./scim-tokens";
|
||||
export * from "./secret-approval-policies";
|
||||
|
@ -80,7 +80,6 @@ export enum TableName {
|
||||
IdentityProjectAdditionalPrivilege = "identity_project_additional_privilege",
|
||||
// used by both identity and users
|
||||
IdentityMetadata = "identity_metadata",
|
||||
ResourceMetadata = "resource_metadata",
|
||||
ScimToken = "scim_tokens",
|
||||
AccessApprovalPolicy = "access_approval_policies",
|
||||
AccessApprovalPolicyApprover = "access_approval_policies_approvers",
|
||||
|
@ -1,24 +0,0 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const ResourceMetadataSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
key: z.string(),
|
||||
value: z.string(),
|
||||
orgId: z.string().uuid(),
|
||||
userId: z.string().uuid().nullable().optional(),
|
||||
identityId: z.string().uuid().nullable().optional(),
|
||||
secretId: z.string().uuid().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
export type TResourceMetadata = z.infer<typeof ResourceMetadataSchema>;
|
||||
export type TResourceMetadataInsert = Omit<z.input<typeof ResourceMetadataSchema>, TImmutableDBKeys>;
|
||||
export type TResourceMetadataUpdate = Partial<Omit<z.input<typeof ResourceMetadataSchema>, TImmutableDBKeys>>;
|
@ -24,8 +24,7 @@ export const SecretApprovalRequestsSecretsV2Schema = z.object({
|
||||
requestId: z.string().uuid(),
|
||||
op: z.string(),
|
||||
secretId: z.string().uuid().nullable().optional(),
|
||||
secretVersion: z.string().uuid().nullable().optional(),
|
||||
secretMetadata: z.unknown().nullable().optional()
|
||||
secretVersion: z.string().uuid().nullable().optional()
|
||||
});
|
||||
|
||||
export type TSecretApprovalRequestsSecretsV2 = z.infer<typeof SecretApprovalRequestsSecretsV2Schema>;
|
||||
|
@ -84,7 +84,10 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
||||
samlConfig.audience = `spn:${ssoConfig.issuer}`;
|
||||
}
|
||||
}
|
||||
if (ssoConfig.authProvider === SamlProviders.GOOGLE_SAML) {
|
||||
if (
|
||||
ssoConfig.authProvider === SamlProviders.GOOGLE_SAML ||
|
||||
ssoConfig.authProvider === SamlProviders.AUTH0_SAML
|
||||
) {
|
||||
samlConfig.wantAssertionsSigned = false;
|
||||
}
|
||||
|
||||
@ -123,7 +126,10 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
||||
`email: ${email} firstName: ${profile.firstName as string}`
|
||||
);
|
||||
|
||||
throw new Error("Invalid saml request. Missing email or first name");
|
||||
throw new BadRequestError({
|
||||
message:
|
||||
"Missing email or first name. Please double check your SAML attribute mapping for the selected provider."
|
||||
});
|
||||
}
|
||||
|
||||
const userMetadata = Object.keys(profile.attributes || {})
|
||||
|
@ -12,7 +12,6 @@ import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { secretRawSchema } from "@app/server/routes/sanitizedSchemas";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ResourceMetadataSchema } from "@app/services/resource-metadata/resource-metadata-schema";
|
||||
|
||||
const approvalRequestUser = z.object({ userId: z.string().nullable().optional() }).merge(
|
||||
UsersSchema.pick({
|
||||
@ -275,7 +274,6 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
|
||||
.extend({
|
||||
op: z.string(),
|
||||
tags: tagSchema,
|
||||
secretMetadata: ResourceMetadataSchema.nullish(),
|
||||
secret: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
@ -293,8 +291,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
|
||||
secretKey: z.string(),
|
||||
secretValue: z.string().optional(),
|
||||
secretComment: z.string().optional(),
|
||||
tags: tagSchema,
|
||||
secretMetadata: ResourceMetadataSchema.nullish()
|
||||
tags: tagSchema
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
|
@ -6,7 +6,8 @@ export enum SamlProviders {
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml",
|
||||
GOOGLE_SAML = "google-saml",
|
||||
KEYCLOAK_SAML = "keycloak-saml"
|
||||
KEYCLOAK_SAML = "keycloak-saml",
|
||||
AUTH0_SAML = "auth0-saml"
|
||||
}
|
||||
|
||||
export type TCreateSamlCfgDTO = {
|
||||
|
@ -256,7 +256,6 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
|
||||
`${TableName.SecretVersionV2Tag}.${TableName.SecretTag}Id`,
|
||||
db.ref("id").withSchema("secVerTag")
|
||||
)
|
||||
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
|
||||
.select(selectAllTableCols(TableName.SecretApprovalRequestSecretV2))
|
||||
.select({
|
||||
secVerTagId: "secVerTag.id",
|
||||
@ -280,11 +279,6 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
|
||||
db.ref("key").withSchema(TableName.SecretVersionV2).as("secVerKey"),
|
||||
db.ref("encryptedValue").withSchema(TableName.SecretVersionV2).as("secVerValue"),
|
||||
db.ref("encryptedComment").withSchema(TableName.SecretVersionV2).as("secVerComment")
|
||||
)
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
|
||||
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
|
||||
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
|
||||
);
|
||||
const formatedDoc = sqlNestRelationships({
|
||||
data: doc,
|
||||
@ -344,19 +338,9 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
|
||||
})
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "metadataId",
|
||||
label: "oldSecretMetadata" as const,
|
||||
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||
id: metadataId,
|
||||
key: metadataKey,
|
||||
value: metadataValue
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
return formatedDoc?.map(({ secret, secretVersion, ...el }) => ({
|
||||
...el,
|
||||
secret: secret?.[0],
|
||||
|
@ -22,8 +22,6 @@ import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
||||
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
|
||||
import { TResourceMetadataDALFactory } from "@app/services/resource-metadata/resource-metadata-dal";
|
||||
import { ResourceMetadataDTO } from "@app/services/resource-metadata/resource-metadata-schema";
|
||||
import { TSecretDALFactory } from "@app/services/secret/secret-dal";
|
||||
import {
|
||||
decryptSecretWithBot,
|
||||
@ -93,7 +91,6 @@ type TSecretApprovalRequestServiceFactoryDep = {
|
||||
secretBlindIndexDAL: Pick<TSecretBlindIndexDALFactory, "findOne">;
|
||||
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
|
||||
secretVersionDAL: Pick<TSecretVersionDALFactory, "findLatestVersionMany" | "insertMany">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
|
||||
smtpService: Pick<TSmtpService, "sendMail">;
|
||||
userDAL: Pick<TUserDALFactory, "find" | "findOne" | "findById">;
|
||||
@ -141,8 +138,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretVersionV2BridgeDAL,
|
||||
secretVersionTagV2BridgeDAL,
|
||||
licenseService,
|
||||
projectSlackConfigDAL,
|
||||
resourceMetadataDAL
|
||||
projectSlackConfigDAL
|
||||
}: TSecretApprovalRequestServiceFactoryDep) => {
|
||||
const requestCount = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod }: TApprovalRequestCountDTO) => {
|
||||
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
|
||||
@ -245,7 +241,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretKey: el.key,
|
||||
id: el.id,
|
||||
version: el.version,
|
||||
secretMetadata: el.secretMetadata as ResourceMetadataDTO,
|
||||
secretValue: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
|
||||
secretComment: el.encryptedComment
|
||||
? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString()
|
||||
@ -274,8 +269,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretComment: el.secretVersion.encryptedComment
|
||||
? secretManagerDecryptor({ cipherTextBlob: el.secretVersion.encryptedComment }).toString()
|
||||
: "",
|
||||
tags: el.secretVersion.tags,
|
||||
secretMetadata: el.oldSecretMetadata as ResourceMetadataDTO
|
||||
tags: el.secretVersion.tags
|
||||
}
|
||||
: undefined
|
||||
}));
|
||||
@ -549,7 +543,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
? await fnSecretV2BridgeBulkInsert({
|
||||
tx,
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
inputSecrets: secretCreationCommits.map((el) => ({
|
||||
tagIds: el?.tags.map(({ id }) => id),
|
||||
version: 1,
|
||||
@ -557,7 +550,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
encryptedValue: el.encryptedValue,
|
||||
skipMultilineEncoding: el.skipMultilineEncoding,
|
||||
key: el.key,
|
||||
secretMetadata: el.secretMetadata as ResourceMetadataDTO,
|
||||
references: el.encryptedValue
|
||||
? getAllSecretReferencesV2Bridge(
|
||||
secretManagerDecryptor({
|
||||
@ -567,7 +559,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
: [],
|
||||
type: SecretType.Shared
|
||||
})),
|
||||
resourceMetadataDAL,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
secretVersionDAL: secretVersionV2BridgeDAL,
|
||||
secretTagDAL,
|
||||
@ -577,7 +568,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
const updatedSecrets = secretUpdationCommits.length
|
||||
? await fnSecretV2BridgeBulkUpdate({
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
tx,
|
||||
inputSecrets: secretUpdationCommits.map((el) => {
|
||||
const encryptedValue =
|
||||
@ -602,7 +592,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
skipMultilineEncoding: el.skipMultilineEncoding,
|
||||
key: el.key,
|
||||
tags: el?.tags.map(({ id }) => id),
|
||||
secretMetadata: el.secretMetadata as ResourceMetadataDTO,
|
||||
...encryptedValue
|
||||
}
|
||||
};
|
||||
@ -610,8 +599,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
secretVersionDAL: secretVersionV2BridgeDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL: secretVersionTagV2BridgeDAL,
|
||||
resourceMetadataDAL
|
||||
secretVersionTagDAL: secretVersionTagV2BridgeDAL
|
||||
})
|
||||
: [];
|
||||
const deletedSecret = secretDeletionCommits.length
|
||||
@ -836,7 +824,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
}
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
secretPath: folder.path,
|
||||
environmentSlug: folder.environmentSlug,
|
||||
actorId,
|
||||
@ -1221,7 +1208,6 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
),
|
||||
skipMultilineEncoding: createdSecret.skipMultilineEncoding,
|
||||
key: createdSecret.secretKey,
|
||||
secretMetadata: createdSecret.secretMetadata,
|
||||
type: SecretType.Shared
|
||||
}))
|
||||
);
|
||||
@ -1277,14 +1263,12 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
reminderNote,
|
||||
secretComment,
|
||||
metadata,
|
||||
skipMultilineEncoding,
|
||||
secretMetadata
|
||||
skipMultilineEncoding
|
||||
}) => {
|
||||
const secretId = updatingSecretsGroupByKey[secretKey][0].id;
|
||||
if (tagIds?.length) commitTagIds[secretKey] = tagIds;
|
||||
return {
|
||||
...latestSecretVersions[secretId],
|
||||
secretMetadata,
|
||||
key: newSecretName || secretKey,
|
||||
encryptedComment: setKnexStringValue(
|
||||
secretComment,
|
||||
@ -1386,8 +1370,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
reminderRepeatDays,
|
||||
encryptedValue,
|
||||
secretId,
|
||||
secretVersion,
|
||||
secretMetadata
|
||||
secretVersion
|
||||
}) => ({
|
||||
version,
|
||||
requestId: doc.id,
|
||||
@ -1400,8 +1383,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
reminderRepeatDays,
|
||||
reminderNote,
|
||||
encryptedComment,
|
||||
key,
|
||||
secretMetadata: JSON.stringify(secretMetadata)
|
||||
key
|
||||
})
|
||||
),
|
||||
tx
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { TImmutableDBKeys, TSecretApprovalPolicies, TSecretApprovalRequestsSecrets } from "@app/db/schemas";
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
import { ResourceMetadataDTO } from "@app/services/resource-metadata/resource-metadata-schema";
|
||||
import { SecretOperations } from "@app/services/secret/secret-types";
|
||||
|
||||
export enum RequestState {
|
||||
@ -35,7 +34,6 @@ export type TApprovalCreateSecretV2Bridge = {
|
||||
reminderRepeatDays?: number | null;
|
||||
skipMultilineEncoding?: boolean;
|
||||
metadata?: Record<string, string>;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
tagIds?: string[];
|
||||
};
|
||||
|
||||
|
@ -13,8 +13,6 @@ import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
||||
import { TResourceMetadataDALFactory } from "@app/services/resource-metadata/resource-metadata-dal";
|
||||
import { ResourceMetadataDTO } from "@app/services/resource-metadata/resource-metadata-schema";
|
||||
import { TSecretDALFactory } from "@app/services/secret/secret-dal";
|
||||
import { fnSecretBulkInsert, fnSecretBulkUpdate } from "@app/services/secret/secret-fns";
|
||||
import { TSecretQueueFactory, uniqueSecretQueueKey } from "@app/services/secret/secret-queue";
|
||||
@ -58,7 +56,6 @@ type TSecretReplicationServiceFactoryDep = {
|
||||
>;
|
||||
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "find" | "insertMany">;
|
||||
secretVersionV2TagBridgeDAL: Pick<TSecretVersionV2TagDALFactory, "find" | "insertMany">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets" | "replicateSecrets">;
|
||||
queueService: Pick<TQueueServiceFactory, "start" | "listen" | "queue" | "stopJobById">;
|
||||
secretApprovalPolicyService: Pick<TSecretApprovalPolicyServiceFactory, "getSecretApprovalPolicy">;
|
||||
@ -124,8 +121,7 @@ export const secretReplicationServiceFactory = ({
|
||||
secretVersionV2TagBridgeDAL,
|
||||
secretVersionV2BridgeDAL,
|
||||
secretV2BridgeDAL,
|
||||
kmsService,
|
||||
resourceMetadataDAL
|
||||
kmsService
|
||||
}: TSecretReplicationServiceFactoryDep) => {
|
||||
const $getReplicatedSecrets = (
|
||||
botKey: string,
|
||||
@ -155,10 +151,8 @@ export const secretReplicationServiceFactory = ({
|
||||
};
|
||||
|
||||
const $getReplicatedSecretsV2 = (
|
||||
localSecrets: (TSecretsV2 & { secretKey: string; secretValue?: string; secretMetadata?: ResourceMetadataDTO })[],
|
||||
importedSecrets: {
|
||||
secrets: (TSecretsV2 & { secretKey: string; secretValue?: string; secretMetadata?: ResourceMetadataDTO })[];
|
||||
}[]
|
||||
localSecrets: (TSecretsV2 & { secretKey: string; secretValue?: string })[],
|
||||
importedSecrets: { secrets: (TSecretsV2 & { secretKey: string; secretValue?: string })[] }[]
|
||||
) => {
|
||||
const deDupe = new Set<string>();
|
||||
const secrets = [...localSecrets];
|
||||
@ -184,7 +178,6 @@ export const secretReplicationServiceFactory = ({
|
||||
secretPath,
|
||||
environmentSlug,
|
||||
projectId,
|
||||
orgId,
|
||||
actorId,
|
||||
actor,
|
||||
pickOnlyImportIds,
|
||||
@ -229,7 +222,6 @@ export const secretReplicationServiceFactory = ({
|
||||
.map(({ folderId }) =>
|
||||
secretQueueService.replicateSecrets({
|
||||
projectId,
|
||||
orgId,
|
||||
secretPath: foldersGroupedById[folderId][0]?.path as string,
|
||||
environmentSlug: foldersGroupedById[folderId][0]?.environmentSlug as string,
|
||||
actorId,
|
||||
@ -275,7 +267,6 @@ export const secretReplicationServiceFactory = ({
|
||||
? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString()
|
||||
: undefined
|
||||
}));
|
||||
|
||||
const sourceSecrets = $getReplicatedSecretsV2(sourceDecryptedLocalSecrets, sourceImportedSecrets);
|
||||
const sourceSecretsGroupByKey = groupBy(sourceSecrets, (i) => i.key);
|
||||
|
||||
@ -342,29 +333,13 @@ export const secretReplicationServiceFactory = ({
|
||||
.map((el) => ({ ...el, operation: SecretOperations.Create })); // rewrite update ops to create
|
||||
|
||||
const locallyUpdatedSecrets = sourceSecrets
|
||||
.filter(({ key, secretKey, secretValue, secretMetadata }) => {
|
||||
const sourceSecretMetadataJson = JSON.stringify(
|
||||
(secretMetadata ?? []).map((entry) => ({
|
||||
key: entry.key,
|
||||
value: entry.value
|
||||
}))
|
||||
);
|
||||
|
||||
const destinationSecretMetadataJson = JSON.stringify(
|
||||
(destinationLocalSecretsGroupedByKey[key]?.[0]?.secretMetadata ?? []).map((entry) => ({
|
||||
key: entry.key,
|
||||
value: entry.value
|
||||
}))
|
||||
);
|
||||
|
||||
return (
|
||||
.filter(
|
||||
({ key, secretKey, secretValue }) =>
|
||||
destinationLocalSecretsGroupedByKey[key]?.[0] &&
|
||||
// if key or value changed
|
||||
(destinationLocalSecretsGroupedByKey[key]?.[0]?.secretKey !== secretKey ||
|
||||
destinationLocalSecretsGroupedByKey[key]?.[0]?.secretValue !== secretValue ||
|
||||
sourceSecretMetadataJson !== destinationSecretMetadataJson)
|
||||
);
|
||||
})
|
||||
destinationLocalSecretsGroupedByKey[key]?.[0]?.secretValue !== secretValue)
|
||||
)
|
||||
.map((el) => ({ ...el, operation: SecretOperations.Update })); // rewrite update ops to create
|
||||
|
||||
const locallyDeletedSecrets = destinationLocalSecrets
|
||||
@ -412,7 +387,6 @@ export const secretReplicationServiceFactory = ({
|
||||
op: operation,
|
||||
requestId: approvalRequestDoc.id,
|
||||
metadata: doc.metadata,
|
||||
secretMetadata: JSON.stringify(doc.secretMetadata),
|
||||
key: doc.key,
|
||||
encryptedValue: doc.encryptedValue,
|
||||
encryptedComment: doc.encryptedComment,
|
||||
@ -432,12 +406,10 @@ export const secretReplicationServiceFactory = ({
|
||||
if (locallyCreatedSecrets.length) {
|
||||
await fnSecretV2BridgeBulkInsert({
|
||||
folderId: destinationReplicationFolderId,
|
||||
orgId,
|
||||
secretVersionDAL: secretVersionV2BridgeDAL,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
tx,
|
||||
secretTagDAL,
|
||||
resourceMetadataDAL,
|
||||
secretVersionTagDAL: secretVersionV2TagBridgeDAL,
|
||||
inputSecrets: locallyCreatedSecrets.map((doc) => {
|
||||
return {
|
||||
@ -447,7 +419,6 @@ export const secretReplicationServiceFactory = ({
|
||||
encryptedValue: doc.encryptedValue,
|
||||
encryptedComment: doc.encryptedComment,
|
||||
skipMultilineEncoding: doc.skipMultilineEncoding,
|
||||
secretMetadata: doc.secretMetadata,
|
||||
references: doc.secretValue ? getAllSecretReferences(doc.secretValue).nestedReferences : []
|
||||
};
|
||||
})
|
||||
@ -455,12 +426,10 @@ export const secretReplicationServiceFactory = ({
|
||||
}
|
||||
if (locallyUpdatedSecrets.length) {
|
||||
await fnSecretV2BridgeBulkUpdate({
|
||||
orgId,
|
||||
folderId: destinationReplicationFolderId,
|
||||
secretVersionDAL: secretVersionV2BridgeDAL,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
tx,
|
||||
resourceMetadataDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL: secretVersionV2TagBridgeDAL,
|
||||
inputSecrets: locallyUpdatedSecrets.map((doc) => {
|
||||
@ -476,7 +445,6 @@ export const secretReplicationServiceFactory = ({
|
||||
encryptedValue: doc.encryptedValue as Buffer,
|
||||
encryptedComment: doc.encryptedComment,
|
||||
skipMultilineEncoding: doc.skipMultilineEncoding,
|
||||
secretMetadata: doc.secretMetadata,
|
||||
references: doc.secretValue ? getAllSecretReferences(doc.secretValue).nestedReferences : []
|
||||
}
|
||||
};
|
||||
@ -498,7 +466,6 @@ export const secretReplicationServiceFactory = ({
|
||||
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId,
|
||||
orgId,
|
||||
secretPath: destinationFolder.path,
|
||||
environmentSlug: destinationFolder.environmentSlug,
|
||||
actorId,
|
||||
@ -784,7 +751,6 @@ export const secretReplicationServiceFactory = ({
|
||||
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId,
|
||||
orgId,
|
||||
secretPath: destinationFolder.path,
|
||||
environmentSlug: destinationFolder.environmentSlug,
|
||||
actorId,
|
||||
|
@ -1150,8 +1150,7 @@ export const INTEGRATION = {
|
||||
shouldMaskSecrets: "Specifies if the secrets synced from Infisical to Gitlab should be marked as 'Masked'.",
|
||||
shouldProtectSecrets: "Specifies if the secrets synced from Infisical to Gitlab should be marked as 'Protected'.",
|
||||
shouldEnableDelete: "The flag to enable deletion of secrets.",
|
||||
octopusDeployScopeValues: "Specifies the scope values to set on synced secrets to Octopus Deploy.",
|
||||
metadataSyncMode: "The mode for syncing metadata to external system"
|
||||
octopusDeployScopeValues: "Specifies the scope values to set on synced secrets to Octopus Deploy."
|
||||
}
|
||||
},
|
||||
UPDATE: {
|
||||
|
@ -181,7 +181,6 @@ import { projectUserMembershipRoleDALFactory } from "@app/services/project-membe
|
||||
import { projectRoleDALFactory } from "@app/services/project-role/project-role-dal";
|
||||
import { projectRoleServiceFactory } from "@app/services/project-role/project-role-service";
|
||||
import { dailyResourceCleanUpQueueServiceFactory } from "@app/services/resource-cleanup/resource-cleanup-queue";
|
||||
import { resourceMetadataDALFactory } from "@app/services/resource-metadata/resource-metadata-dal";
|
||||
import { secretDALFactory } from "@app/services/secret/secret-dal";
|
||||
import { secretQueueFactory } from "@app/services/secret/secret-queue";
|
||||
import { secretServiceFactory } from "@app/services/secret/secret-service";
|
||||
@ -375,7 +374,6 @@ export const registerRoutes = async (
|
||||
const externalGroupOrgRoleMappingDAL = externalGroupOrgRoleMappingDALFactory(db);
|
||||
|
||||
const projectTemplateDAL = projectTemplateDALFactory(db);
|
||||
const resourceMetadataDAL = resourceMetadataDALFactory(db);
|
||||
|
||||
const permissionService = permissionServiceFactory({
|
||||
permissionDAL,
|
||||
@ -856,8 +854,7 @@ export const registerRoutes = async (
|
||||
secretApprovalRequestDAL,
|
||||
projectKeyDAL,
|
||||
projectUserMembershipRoleDAL,
|
||||
orgService,
|
||||
resourceMetadataDAL
|
||||
orgService
|
||||
});
|
||||
|
||||
const projectService = projectServiceFactory({
|
||||
@ -983,8 +980,7 @@ export const registerRoutes = async (
|
||||
secretApprovalPolicyService,
|
||||
secretApprovalRequestSecretDAL,
|
||||
kmsService,
|
||||
snapshotService,
|
||||
resourceMetadataDAL
|
||||
snapshotService
|
||||
});
|
||||
|
||||
const secretApprovalRequestService = secretApprovalRequestServiceFactory({
|
||||
@ -1011,8 +1007,7 @@ export const registerRoutes = async (
|
||||
projectEnvDAL,
|
||||
userDAL,
|
||||
licenseService,
|
||||
projectSlackConfigDAL,
|
||||
resourceMetadataDAL
|
||||
projectSlackConfigDAL
|
||||
});
|
||||
|
||||
const secretService = secretServiceFactory({
|
||||
@ -1091,10 +1086,8 @@ export const registerRoutes = async (
|
||||
kmsService,
|
||||
secretV2BridgeDAL,
|
||||
secretVersionV2TagBridgeDAL: secretVersionTagV2BridgeDAL,
|
||||
secretVersionV2BridgeDAL,
|
||||
resourceMetadataDAL
|
||||
secretVersionV2BridgeDAL
|
||||
});
|
||||
|
||||
const secretRotationQueue = secretRotationQueueFactory({
|
||||
telemetryService,
|
||||
secretRotationDAL,
|
||||
@ -1346,8 +1339,7 @@ export const registerRoutes = async (
|
||||
folderDAL,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
queueService,
|
||||
secretV2BridgeService,
|
||||
resourceMetadataDAL
|
||||
secretV2BridgeService
|
||||
});
|
||||
|
||||
const migrationService = externalMigrationServiceFactory({
|
||||
|
@ -17,7 +17,6 @@ import { getUserAgentType } from "@app/server/plugins/audit-log";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { SanitizedDynamicSecretSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ResourceMetadataSchema } from "@app/services/resource-metadata/resource-metadata-schema";
|
||||
import { SecretsOrderBy } from "@app/services/secret/secret-types";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
@ -117,7 +116,6 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
secrets: secretRawSchema
|
||||
.extend({
|
||||
secretPath: z.string().optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
@ -410,7 +408,6 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
secrets: secretRawSchema
|
||||
.extend({
|
||||
secretPath: z.string().optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
@ -696,7 +693,6 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
secrets: secretRawSchema
|
||||
.extend({
|
||||
secretPath: z.string().optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
@ -868,7 +864,6 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
secrets: secretRawSchema
|
||||
.extend({
|
||||
secretPath: z.string().optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
|
@ -18,7 +18,6 @@ import { getUserAgentType } from "@app/server/plugins/audit-log";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectFilterType } from "@app/services/project/project-types";
|
||||
import { ResourceMetadataSchema } from "@app/services/resource-metadata/resource-metadata-schema";
|
||||
import { SecretOperations, SecretProtectionType } from "@app/services/secret/secret-types";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
@ -206,7 +205,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
secrets: secretRawSchema
|
||||
.extend({
|
||||
secretPath: z.string().optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tags: SecretTagsSchema.pick({
|
||||
id: true,
|
||||
slug: true,
|
||||
@ -222,12 +220,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
secretPath: z.string(),
|
||||
environment: z.string(),
|
||||
folderId: z.string().optional(),
|
||||
secrets: secretRawSchema
|
||||
.omit({ createdAt: true, updatedAt: true })
|
||||
.extend({
|
||||
secretMetadata: ResourceMetadataSchema.optional()
|
||||
})
|
||||
.array()
|
||||
secrets: secretRawSchema.omit({ createdAt: true, updatedAt: true }).array()
|
||||
})
|
||||
.array()
|
||||
.optional()
|
||||
@ -355,8 +348,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
})
|
||||
.extend({ name: z.string() })
|
||||
.array()
|
||||
.optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional()
|
||||
.optional()
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -458,7 +450,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim()))
|
||||
.describe(RAW_SECRETS.CREATE.secretValue),
|
||||
secretComment: z.string().trim().optional().default("").describe(RAW_SECRETS.CREATE.secretComment),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tagIds: z.string().array().optional().describe(RAW_SECRETS.CREATE.tagIds),
|
||||
skipMultilineEncoding: z.boolean().optional().describe(RAW_SECRETS.CREATE.skipMultilineEncoding),
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.CREATE.type),
|
||||
@ -493,7 +484,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
secretValue: req.body.secretValue,
|
||||
skipMultilineEncoding: req.body.skipMultilineEncoding,
|
||||
secretComment: req.body.secretComment,
|
||||
secretMetadata: req.body.secretMetadata,
|
||||
tagIds: req.body.tagIds,
|
||||
secretReminderNote: req.body.secretReminderNote,
|
||||
secretReminderRepeatDays: req.body.secretReminderRepeatDays
|
||||
@ -568,7 +558,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.UPDATE.type),
|
||||
tagIds: z.string().array().optional().describe(RAW_SECRETS.UPDATE.tagIds),
|
||||
metadata: z.record(z.string()).optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.UPDATE.secretReminderNote),
|
||||
secretReminderRepeatDays: z
|
||||
.number()
|
||||
@ -606,10 +595,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
secretReminderNote: req.body.secretReminderNote,
|
||||
metadata: req.body.metadata,
|
||||
newSecretName: req.body.newSecretName,
|
||||
secretComment: req.body.secretComment,
|
||||
secretMetadata: req.body.secretMetadata
|
||||
secretComment: req.body.secretComment
|
||||
});
|
||||
|
||||
if (secretOperation.type === SecretProtectionType.Approval) {
|
||||
return { approval: secretOperation.approval };
|
||||
}
|
||||
@ -1863,7 +1850,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
secretComment: z.string().trim().optional().default("").describe(RAW_SECRETS.CREATE.secretComment),
|
||||
skipMultilineEncoding: z.boolean().optional().describe(RAW_SECRETS.CREATE.skipMultilineEncoding),
|
||||
metadata: z.record(z.string()).optional(),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
tagIds: z.string().array().optional().describe(RAW_SECRETS.CREATE.tagIds)
|
||||
})
|
||||
.array()
|
||||
@ -1966,7 +1952,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
newSecretName: z.string().min(1).optional().describe(RAW_SECRETS.UPDATE.newSecretName),
|
||||
tagIds: z.string().array().optional().describe(RAW_SECRETS.UPDATE.tagIds),
|
||||
secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.UPDATE.secretReminderNote),
|
||||
secretMetadata: ResourceMetadataSchema.optional(),
|
||||
secretReminderRepeatDays: z
|
||||
.number()
|
||||
.optional()
|
||||
|
@ -16,7 +16,6 @@ import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TProjectServiceFactory } from "../project/project-service";
|
||||
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||
import { TProjectEnvServiceFactory } from "../project-env/project-env-service";
|
||||
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
|
||||
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
|
||||
@ -36,8 +35,6 @@ export type TImportDataIntoInfisicalDTO = {
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "create">;
|
||||
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany" | "create">;
|
||||
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">;
|
||||
|
||||
folderDAL: Pick<TSecretFolderDALFactory, "create" | "findBySecretPath" | "findById">;
|
||||
projectService: Pick<TProjectServiceFactory, "createProject">;
|
||||
projectEnvService: Pick<TProjectEnvServiceFactory, "createEnvironment">;
|
||||
@ -506,7 +503,6 @@ export const importDataIntoInfisicalFn = async ({
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
folderDAL,
|
||||
resourceMetadataDAL,
|
||||
input: { data, actor, actorId, actorOrgId, actorAuthMethod }
|
||||
}: TImportDataIntoInfisicalDTO) => {
|
||||
// Import data to infisical
|
||||
@ -766,8 +762,6 @@ export const importDataIntoInfisicalFn = async ({
|
||||
};
|
||||
}),
|
||||
folderId: selectedFolder.id,
|
||||
orgId: actorOrgId,
|
||||
resourceMetadataDAL,
|
||||
secretDAL,
|
||||
secretVersionDAL,
|
||||
secretTagDAL,
|
||||
|
@ -8,7 +8,6 @@ import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TProjectServiceFactory } from "../project/project-service";
|
||||
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||
import { TProjectEnvServiceFactory } from "../project-env/project-env-service";
|
||||
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
|
||||
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
|
||||
@ -36,8 +35,6 @@ export type TExternalMigrationQueueFactoryDep = {
|
||||
projectService: Pick<TProjectServiceFactory, "createProject">;
|
||||
projectEnvService: Pick<TProjectEnvServiceFactory, "createEnvironment">;
|
||||
secretV2BridgeService: Pick<TSecretV2BridgeServiceFactory, "createManySecret">;
|
||||
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
};
|
||||
|
||||
export type TExternalMigrationQueueFactory = ReturnType<typeof externalMigrationQueueFactory>;
|
||||
@ -55,8 +52,7 @@ export const externalMigrationQueueFactory = ({
|
||||
secretVersionDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
folderDAL,
|
||||
resourceMetadataDAL
|
||||
folderDAL
|
||||
}: TExternalMigrationQueueFactoryDep) => {
|
||||
const startImport = async (dto: {
|
||||
actorEmail: string;
|
||||
@ -113,8 +109,7 @@ export const externalMigrationQueueFactory = ({
|
||||
kmsService,
|
||||
projectService,
|
||||
projectEnvService,
|
||||
secretV2BridgeService,
|
||||
resourceMetadataDAL
|
||||
secretV2BridgeService
|
||||
});
|
||||
|
||||
if (projectsNotImported.length) {
|
||||
|
@ -427,8 +427,3 @@ export const getIntegrationOptions = async () => {
|
||||
|
||||
return INTEGRATION_OPTIONS;
|
||||
};
|
||||
|
||||
export enum IntegrationMetadataSyncMode {
|
||||
CUSTOM = "custom",
|
||||
SECRET_METADATA = "secret-metadata"
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ import { TCreateManySecretsRawFn, TUpdateManySecretsRawFn } from "@app/services/
|
||||
|
||||
import { TIntegrationDALFactory } from "../integration/integration-dal";
|
||||
import { IntegrationMetadataSchema } from "../integration/integration-schema";
|
||||
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
|
||||
import { IntegrationAuthMetadataSchema } from "./integration-auth-schema";
|
||||
import {
|
||||
CircleCiScope,
|
||||
@ -49,7 +48,6 @@ import {
|
||||
import {
|
||||
IntegrationInitialSyncBehavior,
|
||||
IntegrationMappingBehavior,
|
||||
IntegrationMetadataSyncMode,
|
||||
Integrations,
|
||||
IntegrationUrls
|
||||
} from "./integration-list";
|
||||
@ -1084,14 +1082,14 @@ const syncSecretsAWSSecretManager = async ({
|
||||
projectId
|
||||
}: {
|
||||
integration: TIntegrations;
|
||||
secrets: Record<string, { value: string; comment?: string; secretMetadata?: ResourceMetadataDTO }>;
|
||||
secrets: Record<string, { value: string; comment?: string }>;
|
||||
accessId: string | null;
|
||||
accessToken: string;
|
||||
awsAssumeRoleArn: string | null;
|
||||
projectId?: string;
|
||||
}) => {
|
||||
const appCfg = getConfig();
|
||||
const metadata = IntegrationMetadataSchema.parse(integration.metadata || {});
|
||||
const metadata = z.record(z.any()).parse(integration.metadata || {});
|
||||
|
||||
if (!accessId && !awsAssumeRoleArn) {
|
||||
throw new Error("AWS access ID/AWS Assume Role is required");
|
||||
@ -1139,25 +1137,8 @@ const syncSecretsAWSSecretManager = async ({
|
||||
|
||||
const processAwsSecret = async (
|
||||
secretId: string,
|
||||
secretValue: Record<string, string | null | undefined> | string,
|
||||
secretMetadata?: ResourceMetadataDTO
|
||||
secretValue: Record<string, string | null | undefined> | string
|
||||
) => {
|
||||
const secretAWSTag = metadata.secretAWSTag as { key: string; value: string }[] | undefined;
|
||||
const shouldTag =
|
||||
(secretAWSTag && secretAWSTag.length) ||
|
||||
(metadata.metadataSyncMode === IntegrationMetadataSyncMode.SECRET_METADATA &&
|
||||
metadata.mappingBehavior === IntegrationMappingBehavior.ONE_TO_ONE);
|
||||
const tagArray =
|
||||
(metadata.metadataSyncMode === IntegrationMetadataSyncMode.SECRET_METADATA ? secretMetadata : secretAWSTag) ?? [];
|
||||
|
||||
const integrationTagObj = tagArray.reduce(
|
||||
(acc, item) => {
|
||||
acc[item.key] = item.value;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
try {
|
||||
const awsSecretManagerSecret = await secretsManager.send(
|
||||
new GetSecretValueCommand({
|
||||
@ -1193,7 +1174,9 @@ const syncSecretsAWSSecretManager = async ({
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldTag) {
|
||||
const secretAWSTag = metadata.secretAWSTag as { key: string; value: string }[] | undefined;
|
||||
|
||||
if (secretAWSTag && secretAWSTag.length) {
|
||||
const describedSecret = await secretsManager.send(
|
||||
// requires secretsmanager:DescribeSecret policy
|
||||
new DescribeSecretCommand({
|
||||
@ -1203,6 +1186,14 @@ const syncSecretsAWSSecretManager = async ({
|
||||
|
||||
if (!describedSecret.Tags) return;
|
||||
|
||||
const integrationTagObj = secretAWSTag.reduce(
|
||||
(acc, item) => {
|
||||
acc[item.key] = item.value;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
const awsTagObj = (describedSecret.Tags || []).reduce(
|
||||
(acc, item) => {
|
||||
if (item.Key && item.Value) {
|
||||
@ -1234,7 +1225,7 @@ const syncSecretsAWSSecretManager = async ({
|
||||
}
|
||||
});
|
||||
|
||||
tagArray.forEach((tag) => {
|
||||
secretAWSTag?.forEach((tag) => {
|
||||
if (!(tag.key in awsTagObj)) {
|
||||
// create tag in AWS secret manager
|
||||
tagsToUpdate.push({
|
||||
@ -1271,8 +1262,8 @@ const syncSecretsAWSSecretManager = async ({
|
||||
Name: secretId,
|
||||
SecretString: typeof secretValue === "string" ? secretValue : JSON.stringify(secretValue),
|
||||
...(metadata.kmsKeyId && { KmsKeyId: metadata.kmsKeyId }),
|
||||
Tags: shouldTag
|
||||
? tagArray.map((tag: { key: string; value: string }) => ({
|
||||
Tags: metadata.secretAWSTag
|
||||
? metadata.secretAWSTag.map((tag: { key: string; value: string }) => ({
|
||||
Key: tag.key,
|
||||
Value: tag.value
|
||||
}))
|
||||
@ -1289,7 +1280,7 @@ const syncSecretsAWSSecretManager = async ({
|
||||
|
||||
if (metadata.mappingBehavior === IntegrationMappingBehavior.ONE_TO_ONE) {
|
||||
for await (const [key, value] of Object.entries(secrets)) {
|
||||
await processAwsSecret(key, value.value, value.secretMetadata);
|
||||
await processAwsSecret(key, value.value);
|
||||
}
|
||||
} else {
|
||||
await processAwsSecret(integration.app as string, getSecretKeyValuePair(secrets));
|
||||
@ -4449,7 +4440,7 @@ export const syncIntegrationSecrets = async ({
|
||||
secretPath: string;
|
||||
};
|
||||
integrationAuth: TIntegrationAuths;
|
||||
secrets: Record<string, { value: string; comment?: string; secretMetadata?: ResourceMetadataDTO }>;
|
||||
secrets: Record<string, { value: string; comment?: string }>;
|
||||
accessId: string | null;
|
||||
awsAssumeRoleArn: string | null;
|
||||
accessToken: string;
|
||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
||||
|
||||
import { INTEGRATION } from "@app/lib/api-docs";
|
||||
|
||||
import { IntegrationMappingBehavior, IntegrationMetadataSyncMode } from "../integration-auth/integration-list";
|
||||
import { IntegrationMappingBehavior } from "../integration-auth/integration-list";
|
||||
|
||||
export const IntegrationMetadataSchema = z.object({
|
||||
initialSyncBehavior: z.string().optional().describe(INTEGRATION.CREATE.metadata.initialSyncBehavoir),
|
||||
@ -50,11 +50,6 @@ export const IntegrationMetadataSchema = z.object({
|
||||
shouldMaskSecrets: z.boolean().optional().describe(INTEGRATION.CREATE.metadata.shouldMaskSecrets),
|
||||
shouldProtectSecrets: z.boolean().optional().describe(INTEGRATION.CREATE.metadata.shouldProtectSecrets),
|
||||
|
||||
metadataSyncMode: z
|
||||
.nativeEnum(IntegrationMetadataSyncMode)
|
||||
.optional()
|
||||
.describe(INTEGRATION.CREATE.metadata.metadataSyncMode),
|
||||
|
||||
octopusDeployScopeValues: z
|
||||
.object({
|
||||
// in Octopus Deploy Scope Value Format
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { ormify } from "@app/lib/knex";
|
||||
|
||||
export type TResourceMetadataDALFactory = ReturnType<typeof resourceMetadataDALFactory>;
|
||||
|
||||
export const resourceMetadataDALFactory = (db: TDbClient) => {
|
||||
const orm = ormify(db, TableName.ResourceMetadata);
|
||||
|
||||
return orm;
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
import z from "zod";
|
||||
|
||||
export const ResourceMetadataSchema = z
|
||||
.object({
|
||||
key: z.string().trim().min(1),
|
||||
value: z.string().trim().default("")
|
||||
})
|
||||
.array();
|
||||
|
||||
export type ResourceMetadataDTO = z.infer<typeof ResourceMetadataSchema>;
|
@ -1,7 +1,6 @@
|
||||
import { SecretType, TSecretImports, TSecrets, TSecretsV2 } from "@app/db/schemas";
|
||||
import { groupBy, unique } from "@app/lib/fn";
|
||||
|
||||
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
|
||||
import { TSecretDALFactory } from "../secret/secret-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
|
||||
@ -40,7 +39,6 @@ type TSecretImportSecretsV2 = {
|
||||
// But for somereason ts consider ? and undefined explicit as different just ts things
|
||||
secretValue: string;
|
||||
secretComment: string;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
})[];
|
||||
};
|
||||
|
||||
|
@ -160,7 +160,6 @@ export const secretImportServiceFactory = ({
|
||||
if (secImport.isReplication && sourceFolder) {
|
||||
await secretQueueService.replicateSecrets({
|
||||
secretPath: secImport.importPath,
|
||||
orgId: actorOrgId,
|
||||
projectId,
|
||||
environmentSlug: importEnv.slug,
|
||||
pickOnlyImportIds: [secImport.id],
|
||||
@ -170,7 +169,6 @@ export const secretImportServiceFactory = ({
|
||||
} else {
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath,
|
||||
orgId: actorOrgId,
|
||||
projectId,
|
||||
environmentSlug: environment,
|
||||
actorId,
|
||||
@ -342,7 +340,6 @@ export const secretImportServiceFactory = ({
|
||||
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath,
|
||||
orgId: actorOrgId,
|
||||
projectId,
|
||||
environmentSlug: environment,
|
||||
actor,
|
||||
@ -418,7 +415,6 @@ export const secretImportServiceFactory = ({
|
||||
|
||||
if (membership && sourceFolder) {
|
||||
await secretQueueService.replicateSecrets({
|
||||
orgId: actorOrgId,
|
||||
secretPath: secretImportDoc.importPath,
|
||||
projectId,
|
||||
environmentSlug: secretImportDoc.importEnv.slug,
|
||||
|
@ -78,12 +78,6 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
|
||||
`${TableName.SecretTag}.id`
|
||||
)
|
||||
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
|
||||
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
|
||||
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
|
||||
)
|
||||
.select(selectAllTableCols(TableName.SecretV2))
|
||||
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
|
||||
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
|
||||
@ -109,15 +103,6 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
slug,
|
||||
name: slug
|
||||
})
|
||||
},
|
||||
{
|
||||
key: "metadataId",
|
||||
label: "secretMetadata" as const,
|
||||
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||
id: metadataId,
|
||||
key: metadataKey,
|
||||
value: metadataValue
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
@ -236,9 +221,7 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
const secs = await (tx || db.replicaNode())(TableName.SecretV2)
|
||||
.where({ folderId })
|
||||
.where((bd) => {
|
||||
void bd
|
||||
.whereNull(`${TableName.SecretV2}.userId`)
|
||||
.orWhere({ [`${TableName.SecretV2}.userId` as "userId"]: userId || null });
|
||||
void bd.whereNull("userId").orWhere({ userId: userId || null });
|
||||
})
|
||||
.leftJoin(
|
||||
TableName.SecretV2JnTag,
|
||||
@ -250,16 +233,10 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
|
||||
`${TableName.SecretTag}.id`
|
||||
)
|
||||
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
|
||||
.select(selectAllTableCols(TableName.SecretV2))
|
||||
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
|
||||
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
|
||||
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
|
||||
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
|
||||
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
|
||||
)
|
||||
.orderBy("id", "asc");
|
||||
|
||||
const data = sqlNestRelationships({
|
||||
@ -276,15 +253,6 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
slug,
|
||||
name: slug
|
||||
})
|
||||
},
|
||||
{
|
||||
key: "metadataId",
|
||||
label: "secretMetadata" as const,
|
||||
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||
id: metadataId,
|
||||
key: metadataKey,
|
||||
value: metadataValue
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
@ -399,9 +367,7 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
})
|
||||
.where((bd) => {
|
||||
void bd
|
||||
.whereNull(`${TableName.SecretV2}.userId`)
|
||||
.orWhere({ [`${TableName.SecretV2}.userId` as "userId"]: userId || null });
|
||||
void bd.whereNull(`${TableName.SecretV2}.userId`).orWhere({ userId: userId || null });
|
||||
})
|
||||
.leftJoin(
|
||||
TableName.SecretV2JnTag,
|
||||
@ -413,23 +379,13 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
|
||||
`${TableName.SecretTag}.id`
|
||||
)
|
||||
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
|
||||
.select(
|
||||
selectAllTableCols(TableName.SecretV2),
|
||||
db.raw(
|
||||
`DENSE_RANK() OVER (ORDER BY "${TableName.SecretV2}".key ${
|
||||
filters?.orderDirection ?? OrderByDirection.ASC
|
||||
}) as rank`
|
||||
)
|
||||
db.raw(`DENSE_RANK() OVER (ORDER BY "key" ${filters?.orderDirection ?? OrderByDirection.ASC}) as rank`)
|
||||
)
|
||||
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
|
||||
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
|
||||
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
|
||||
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
|
||||
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
|
||||
)
|
||||
.where((bd) => {
|
||||
const slugs = filters?.tagSlugs?.filter(Boolean);
|
||||
if (slugs && slugs.length > 0) {
|
||||
@ -469,15 +425,6 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
slug,
|
||||
name: slug
|
||||
})
|
||||
},
|
||||
{
|
||||
key: "metadataId",
|
||||
label: "secretMetadata" as const,
|
||||
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||
id: metadataId,
|
||||
key: metadataKey,
|
||||
value: metadataValue
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
@ -598,17 +545,10 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
|
||||
`${TableName.SecretTag}.id`
|
||||
)
|
||||
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
|
||||
.select(selectAllTableCols(TableName.SecretV2))
|
||||
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
|
||||
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
|
||||
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
|
||||
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
|
||||
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
|
||||
);
|
||||
|
||||
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"));
|
||||
const docs = sqlNestRelationships({
|
||||
data: rawDocs,
|
||||
key: "id",
|
||||
@ -623,15 +563,6 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
|
||||
slug,
|
||||
name: slug
|
||||
})
|
||||
},
|
||||
{
|
||||
key: "metadataId",
|
||||
label: "secretMetadata" as const,
|
||||
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||
id: metadataId,
|
||||
key: metadataKey,
|
||||
value: metadataValue
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -6,7 +6,6 @@ import { groupBy } from "@app/lib/fn";
|
||||
import { logger } from "@app/lib/logger";
|
||||
|
||||
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
|
||||
import { TFnSecretBulkDelete, TFnSecretBulkInsert, TFnSecretBulkUpdate } from "./secret-v2-bridge-types";
|
||||
@ -55,11 +54,9 @@ export const getAllSecretReferences = (maybeSecretReference: string) => {
|
||||
export const fnSecretBulkInsert = async ({
|
||||
// TODO: Pick types here
|
||||
folderId,
|
||||
orgId,
|
||||
inputSecrets,
|
||||
secretDAL,
|
||||
secretVersionDAL,
|
||||
resourceMetadataDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
tx
|
||||
@ -94,7 +91,6 @@ export const fnSecretBulkInsert = async ({
|
||||
sanitizedInputSecrets.map((el) => ({ ...el, folderId })),
|
||||
tx
|
||||
);
|
||||
|
||||
const newSecretGroupedByKeyName = groupBy(newSecrets, (item) => item.key);
|
||||
const newSecretTags = inputSecrets.flatMap(({ tagIds: secretTags = [], key }) =>
|
||||
secretTags.map((tag) => ({
|
||||
@ -110,7 +106,6 @@ export const fnSecretBulkInsert = async ({
|
||||
})),
|
||||
tx
|
||||
);
|
||||
|
||||
await secretDAL.upsertSecretReferences(
|
||||
inputSecrets.map(({ references = [], key }) => ({
|
||||
secretId: newSecretGroupedByKeyName[key][0].id,
|
||||
@ -118,22 +113,6 @@ export const fnSecretBulkInsert = async ({
|
||||
})),
|
||||
tx
|
||||
);
|
||||
|
||||
await resourceMetadataDAL.insertMany(
|
||||
inputSecrets.flatMap(({ key: secretKey, secretMetadata }) => {
|
||||
if (secretMetadata) {
|
||||
return secretMetadata.map(({ key, value }) => ({
|
||||
key,
|
||||
value,
|
||||
secretId: newSecretGroupedByKeyName[secretKey][0].id,
|
||||
orgId
|
||||
}));
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
tx
|
||||
);
|
||||
|
||||
if (newSecretTags.length) {
|
||||
const secTags = await secretTagDAL.saveTagsToSecretV2(newSecretTags, tx);
|
||||
const secVersionsGroupBySecId = groupBy(secretVersions, (i) => i.secretId);
|
||||
@ -141,7 +120,6 @@ export const fnSecretBulkInsert = async ({
|
||||
[`${TableName.SecretVersionV2}Id` as const]: secVersionsGroupBySecId[secrets_v2Id][0].id,
|
||||
[`${TableName.SecretTag}Id` as const]: secret_tagsId
|
||||
}));
|
||||
|
||||
await secretVersionTagDAL.insertMany(newSecretVersionTags, tx);
|
||||
}
|
||||
|
||||
@ -152,12 +130,10 @@ export const fnSecretBulkUpdate = async ({
|
||||
tx,
|
||||
inputSecrets,
|
||||
folderId,
|
||||
orgId,
|
||||
secretDAL,
|
||||
secretVersionDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
resourceMetadataDAL
|
||||
secretVersionTagDAL
|
||||
}: TFnSecretBulkUpdate) => {
|
||||
const sanitizedInputSecrets = inputSecrets.map(
|
||||
({
|
||||
@ -255,34 +231,6 @@ export const fnSecretBulkUpdate = async ({
|
||||
}
|
||||
}
|
||||
|
||||
const inputSecretIdsWithMetadata = inputSecrets
|
||||
.filter((sec) => Boolean(sec.data.secretMetadata))
|
||||
.map((sec) => sec.filter.id);
|
||||
|
||||
await resourceMetadataDAL.delete(
|
||||
{
|
||||
$in: {
|
||||
secretId: inputSecretIdsWithMetadata
|
||||
}
|
||||
},
|
||||
tx
|
||||
);
|
||||
|
||||
await resourceMetadataDAL.insertMany(
|
||||
inputSecrets.flatMap(({ filter: { id }, data: { secretMetadata } }) => {
|
||||
if (secretMetadata) {
|
||||
return secretMetadata.map(({ key, value }) => ({
|
||||
key,
|
||||
value,
|
||||
secretId: id,
|
||||
orgId
|
||||
}));
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
tx
|
||||
);
|
||||
|
||||
return newSecrets.map((secret) => ({ ...secret, _id: secret.id }));
|
||||
};
|
||||
|
||||
@ -622,7 +570,6 @@ export const reshapeBridgeSecret = (
|
||||
color?: string | null;
|
||||
name: string;
|
||||
}[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
}
|
||||
) => ({
|
||||
secretKey: secret.key,
|
||||
@ -641,7 +588,6 @@ export const reshapeBridgeSecret = (
|
||||
secretReminderRepeatDays: secret.reminderRepeatDays,
|
||||
secretReminderNote: secret.reminderNote,
|
||||
metadata: secret.metadata,
|
||||
secretMetadata: secret.secretMetadata,
|
||||
createdAt: secret.createdAt,
|
||||
updatedAt: secret.updatedAt
|
||||
});
|
||||
|
@ -18,7 +18,6 @@ import { ActorType } from "../auth/auth-type";
|
||||
import { TKmsServiceFactory } from "../kms/kms-service";
|
||||
import { KmsDataKey } from "../kms/kms-types";
|
||||
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
|
||||
import { TSecretQueueFactory } from "../secret/secret-queue";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
||||
@ -75,7 +74,6 @@ type TSecretV2BridgeServiceFactoryDep = {
|
||||
"insertV2Bridge" | "insertApprovalSecretV2Tags"
|
||||
>;
|
||||
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
};
|
||||
|
||||
export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>;
|
||||
@ -97,8 +95,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
secretApprovalPolicyService,
|
||||
secretApprovalRequestDAL,
|
||||
secretApprovalRequestSecretDAL,
|
||||
kmsService,
|
||||
resourceMetadataDAL
|
||||
kmsService
|
||||
}: TSecretV2BridgeServiceFactoryDep) => {
|
||||
const $validateSecretReferences = async (
|
||||
projectId: string,
|
||||
@ -144,7 +141,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
},
|
||||
{
|
||||
operator: "eq",
|
||||
field: `${TableName.SecretV2}.key` as "key",
|
||||
field: "key",
|
||||
value: el.secretKey
|
||||
}
|
||||
]
|
||||
@ -189,7 +186,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
projectId,
|
||||
secretPath,
|
||||
secretMetadata,
|
||||
...inputSecret
|
||||
}: TCreateSecretDTO) => {
|
||||
const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission(
|
||||
@ -259,7 +255,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
const secret = await secretDAL.transaction((tx) =>
|
||||
fnSecretBulkInsert({
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
inputSecrets: [
|
||||
{
|
||||
version: 1,
|
||||
@ -277,11 +272,9 @@ export const secretV2BridgeServiceFactory = ({
|
||||
key: secretName,
|
||||
userId: inputSecret.type === SecretType.Personal ? actorId : null,
|
||||
tagIds: inputSecret.tagIds,
|
||||
references: nestedReferences,
|
||||
secretMetadata
|
||||
references: nestedReferences
|
||||
}
|
||||
],
|
||||
resourceMetadataDAL,
|
||||
secretDAL,
|
||||
secretVersionDAL,
|
||||
secretTagDAL,
|
||||
@ -294,7 +287,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
await snapshotService.performSnapshot(folderId);
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath,
|
||||
orgId: actorOrgId,
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
@ -317,7 +309,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
projectId,
|
||||
secretPath,
|
||||
secretMetadata,
|
||||
...inputSecret
|
||||
}: TUpdateSecretDTO) => {
|
||||
const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission(
|
||||
@ -444,8 +435,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
const updatedSecret = await secretDAL.transaction(async (tx) =>
|
||||
fnSecretBulkUpdate({
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
resourceMetadataDAL,
|
||||
inputSecrets: [
|
||||
{
|
||||
filter: { id: secretId },
|
||||
@ -459,7 +448,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
skipMultilineEncoding: inputSecret.skipMultilineEncoding,
|
||||
key: inputSecret.newSecretName || secretName,
|
||||
tags: inputSecret.tagIds,
|
||||
secretMetadata,
|
||||
...encryptedValue
|
||||
}
|
||||
}
|
||||
@ -487,7 +475,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
}
|
||||
@ -575,7 +562,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
}
|
||||
@ -975,8 +961,8 @@ export const secretV2BridgeServiceFactory = ({
|
||||
? secretDAL.findOneWithTags({
|
||||
folderId,
|
||||
type: secretType,
|
||||
[`${TableName.SecretV2}.key` as "key"]: secretName,
|
||||
[`${TableName.SecretV2}.userId` as "userId"]: secretType === SecretType.Personal ? actorId : null
|
||||
key: secretName,
|
||||
userId: secretType === SecretType.Personal ? actorId : null
|
||||
})
|
||||
: secretVersionDAL
|
||||
.findOne({
|
||||
@ -1127,7 +1113,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
value: [
|
||||
{
|
||||
operator: "eq",
|
||||
field: `${TableName.SecretV2}.key` as "key",
|
||||
field: "key",
|
||||
value: el.secretKey
|
||||
},
|
||||
{
|
||||
@ -1199,14 +1185,11 @@ export const secretV2BridgeServiceFactory = ({
|
||||
key: el.secretKey,
|
||||
tagIds: el.tagIds,
|
||||
references,
|
||||
secretMetadata: el.secretMetadata,
|
||||
type: SecretType.Shared
|
||||
};
|
||||
}),
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
secretDAL,
|
||||
resourceMetadataDAL,
|
||||
secretVersionDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
@ -1220,7 +1203,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorId,
|
||||
secretPath,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
|
||||
@ -1272,7 +1254,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
value: [
|
||||
{
|
||||
operator: "eq",
|
||||
field: `${TableName.SecretV2}.key` as "key",
|
||||
field: "key",
|
||||
value: el.secretKey
|
||||
},
|
||||
{
|
||||
@ -1337,7 +1319,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
value: [
|
||||
{
|
||||
operator: "eq",
|
||||
field: `${TableName.SecretV2}.key` as "key",
|
||||
field: "key",
|
||||
value: el.secretKey
|
||||
},
|
||||
{
|
||||
@ -1389,7 +1371,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
const secrets = await secretDAL.transaction(async (tx) =>
|
||||
fnSecretBulkUpdate({
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
tx,
|
||||
inputSecrets: inputSecrets.map((el) => {
|
||||
const originalSecret = secretsToUpdateInDBGroupedByKey[el.secretKey][0];
|
||||
@ -1413,7 +1394,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
skipMultilineEncoding: el.skipMultilineEncoding,
|
||||
key: el.newSecretName || el.secretKey,
|
||||
tags: el.tagIds,
|
||||
secretMetadata: el.secretMetadata,
|
||||
...encryptedValue
|
||||
}
|
||||
};
|
||||
@ -1421,8 +1401,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
secretDAL,
|
||||
secretVersionDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
resourceMetadataDAL
|
||||
secretVersionTagDAL
|
||||
})
|
||||
);
|
||||
await snapshotService.performSnapshot(folderId);
|
||||
@ -1431,7 +1410,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorId,
|
||||
secretPath,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
|
||||
@ -1483,7 +1461,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
value: [
|
||||
{
|
||||
operator: "eq",
|
||||
field: `${TableName.SecretV2}.key` as "key",
|
||||
field: "key",
|
||||
value: el.secretKey
|
||||
},
|
||||
{
|
||||
@ -1534,7 +1512,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
actorId,
|
||||
secretPath,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
|
||||
@ -1838,12 +1815,10 @@ export const secretV2BridgeServiceFactory = ({
|
||||
if (locallyCreatedSecrets.length) {
|
||||
await fnSecretBulkInsert({
|
||||
folderId: destinationFolder.id,
|
||||
orgId: actorOrgId,
|
||||
secretVersionDAL,
|
||||
secretDAL,
|
||||
tx,
|
||||
secretTagDAL,
|
||||
resourceMetadataDAL,
|
||||
secretVersionTagDAL,
|
||||
inputSecrets: locallyCreatedSecrets.map((doc) => {
|
||||
return {
|
||||
@ -1855,7 +1830,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
skipMultilineEncoding: doc.skipMultilineEncoding,
|
||||
reminderNote: doc.reminderNote,
|
||||
reminderRepeatDays: doc.reminderRepeatDays,
|
||||
secretMetadata: doc.secretMetadata,
|
||||
references: doc.value ? getAllSecretReferences(doc.value).nestedReferences : []
|
||||
};
|
||||
})
|
||||
@ -1864,8 +1838,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
if (locallyUpdatedSecrets.length) {
|
||||
await fnSecretBulkUpdate({
|
||||
folderId: destinationFolder.id,
|
||||
orgId: actorOrgId,
|
||||
resourceMetadataDAL,
|
||||
secretVersionDAL,
|
||||
secretDAL,
|
||||
tx,
|
||||
@ -1883,7 +1855,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
encryptedComment: doc.encryptedComment,
|
||||
skipMultilineEncoding: doc.skipMultilineEncoding,
|
||||
reminderNote: doc.reminderNote,
|
||||
secretMetadata: doc.secretMetadata,
|
||||
reminderRepeatDays: doc.reminderRepeatDays,
|
||||
...(doc.encryptedValue
|
||||
? {
|
||||
@ -1967,7 +1938,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
await snapshotService.performSnapshot(destinationFolder.id);
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
secretPath: destinationFolder.path,
|
||||
environmentSlug: destinationFolder.environment.slug,
|
||||
actorId,
|
||||
@ -1979,7 +1949,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
await snapshotService.performSnapshot(sourceFolder.id);
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
secretPath: sourceFolder.path,
|
||||
environmentSlug: sourceFolder.environment.slug,
|
||||
actorId,
|
||||
|
@ -7,8 +7,6 @@ import { SecretsOrderBy } from "@app/services/secret/secret-types";
|
||||
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
||||
import { TSecretTagDALFactory } from "@app/services/secret-tag/secret-tag-dal";
|
||||
|
||||
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
|
||||
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
|
||||
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
|
||||
import { TSecretVersionV2DALFactory } from "./secret-version-dal";
|
||||
import { TSecretVersionV2TagDALFactory } from "./secret-version-tag-dal";
|
||||
@ -60,7 +58,6 @@ export type TCreateSecretDTO = TProjectPermission & {
|
||||
skipMultilineEncoding?: boolean;
|
||||
secretReminderRepeatDays?: number | null;
|
||||
secretReminderNote?: string | null;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
};
|
||||
|
||||
export type TUpdateSecretDTO = TProjectPermission & {
|
||||
@ -78,7 +75,6 @@ export type TUpdateSecretDTO = TProjectPermission & {
|
||||
metadata?: {
|
||||
source?: string;
|
||||
};
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
};
|
||||
|
||||
export type TDeleteSecretDTO = TProjectPermission & {
|
||||
@ -98,7 +94,6 @@ export type TCreateManySecretDTO = Omit<TProjectPermission, "projectId"> & {
|
||||
secretComment?: string;
|
||||
skipMultilineEncoding?: boolean;
|
||||
tagIds?: string[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
metadata?: {
|
||||
source?: string;
|
||||
};
|
||||
@ -118,7 +113,6 @@ export type TUpdateManySecretDTO = Omit<TProjectPermission, "projectId"> & {
|
||||
tagIds?: string[];
|
||||
secretReminderRepeatDays?: number | null;
|
||||
secretReminderNote?: string | null;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
}[];
|
||||
};
|
||||
|
||||
@ -142,16 +136,8 @@ export type TSecretReference = { environment: string; secretPath: string; secret
|
||||
|
||||
export type TFnSecretBulkInsert = {
|
||||
folderId: string;
|
||||
orgId: string;
|
||||
tx?: Knex;
|
||||
inputSecrets: Array<
|
||||
Omit<TSecretsV2Insert, "folderId"> & {
|
||||
tagIds?: string[];
|
||||
references: TSecretReference[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
}
|
||||
>;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">;
|
||||
inputSecrets: Array<Omit<TSecretsV2Insert, "folderId"> & { tagIds?: string[]; references: TSecretReference[] }>;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences">;
|
||||
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2">;
|
||||
@ -170,12 +156,10 @@ type TRequireReferenceIfValue =
|
||||
|
||||
export type TFnSecretBulkUpdate = {
|
||||
folderId: string;
|
||||
orgId: string;
|
||||
inputSecrets: {
|
||||
filter: Partial<TSecretsV2>;
|
||||
data: TRequireReferenceIfValue & { tags?: string[]; secretMetadata?: ResourceMetadataDTO };
|
||||
data: TRequireReferenceIfValue & { tags?: string[] };
|
||||
}[];
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences">;
|
||||
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "deleteTagsToSecretV2">;
|
||||
|
@ -749,8 +749,7 @@ export const createManySecretsRawFnFactory = ({
|
||||
secretVersionV2BridgeDAL,
|
||||
secretV2BridgeDAL,
|
||||
secretVersionTagV2BridgeDAL,
|
||||
kmsService,
|
||||
resourceMetadataDAL
|
||||
kmsService
|
||||
}: TCreateManySecretsRawFnFactory) => {
|
||||
const getBotKeyFn = getBotKeyFnFactory(projectBotDAL, projectDAL);
|
||||
const createManySecretsRawFn = async ({
|
||||
@ -761,7 +760,7 @@ export const createManySecretsRawFnFactory = ({
|
||||
userId
|
||||
}: TCreateManySecretsRawFn) => {
|
||||
const { botKey, shouldUseSecretV2Bridge } = await getBotKeyFn(projectId);
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
||||
if (!folder)
|
||||
throw new NotFoundError({
|
||||
@ -815,9 +814,7 @@ export const createManySecretsRawFnFactory = ({
|
||||
tagIds: el.tags
|
||||
})),
|
||||
folderId,
|
||||
orgId: project.orgId,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
resourceMetadataDAL,
|
||||
secretVersionDAL: secretVersionV2BridgeDAL,
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL: secretVersionTagV2BridgeDAL,
|
||||
@ -912,7 +909,6 @@ export const updateManySecretsRawFnFactory = ({
|
||||
secretVersionTagV2BridgeDAL,
|
||||
secretVersionV2BridgeDAL,
|
||||
secretV2BridgeDAL,
|
||||
resourceMetadataDAL,
|
||||
kmsService
|
||||
}: TUpdateManySecretsRawFnFactory) => {
|
||||
const getBotKeyFn = getBotKeyFnFactory(projectBotDAL, projectDAL);
|
||||
@ -924,7 +920,6 @@ export const updateManySecretsRawFnFactory = ({
|
||||
userId
|
||||
}: TUpdateManySecretsRawFn): Promise<Array<{ id: string }>> => {
|
||||
const { botKey, shouldUseSecretV2Bridge } = await getBotKeyFn(projectId);
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
||||
if (!folder)
|
||||
@ -993,13 +988,11 @@ export const updateManySecretsRawFnFactory = ({
|
||||
const updatedSecrets = await secretDAL.transaction(async (tx) =>
|
||||
fnSecretV2BridgeBulkUpdate({
|
||||
folderId,
|
||||
orgId: project.orgId,
|
||||
tx,
|
||||
inputSecrets: inputSecrets.map((el) => ({
|
||||
filter: { id: secretsToUpdateInDBGroupedByKey[el.key][0].id, type: SecretType.Shared },
|
||||
data: el
|
||||
})),
|
||||
resourceMetadataDAL,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
secretVersionDAL: secretVersionV2BridgeDAL,
|
||||
secretTagDAL,
|
||||
|
@ -47,8 +47,6 @@ import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||
import { TProjectKeyDALFactory } from "../project-key/project-key-dal";
|
||||
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
|
||||
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
|
||||
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
|
||||
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
||||
import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
|
||||
@ -106,7 +104,6 @@ type TSecretQueueFactoryDep = {
|
||||
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
|
||||
orgService: Pick<TOrgServiceFactory, "addGhostUser">;
|
||||
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
};
|
||||
|
||||
export type TGetSecrets = {
|
||||
@ -123,12 +120,7 @@ export const uniqueSecretQueueKey = (environment: string, secretPath: string) =>
|
||||
|
||||
type TIntegrationSecret = Record<
|
||||
string,
|
||||
{
|
||||
value: string;
|
||||
comment?: string;
|
||||
skipMultilineEncoding?: boolean | null | undefined;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
}
|
||||
{ value: string; comment?: string; skipMultilineEncoding?: boolean | null | undefined }
|
||||
>;
|
||||
|
||||
// TODO(akhilmhdh): split this into multiple queue
|
||||
@ -165,8 +157,7 @@ export const secretQueueFactory = ({
|
||||
auditLogService,
|
||||
orgService,
|
||||
projectUserMembershipRoleDAL,
|
||||
projectKeyDAL,
|
||||
resourceMetadataDAL
|
||||
projectKeyDAL
|
||||
}: TSecretQueueFactoryDep) => {
|
||||
const integrationMeter = opentelemetry.metrics.getMeter("Integrations");
|
||||
const errorHistogram = integrationMeter.createHistogram("integration_secret_sync_errors", {
|
||||
@ -315,8 +306,7 @@ export const secretQueueFactory = ({
|
||||
kmsService,
|
||||
secretVersionV2BridgeDAL,
|
||||
secretV2BridgeDAL,
|
||||
secretVersionTagV2BridgeDAL,
|
||||
resourceMetadataDAL
|
||||
secretVersionTagV2BridgeDAL
|
||||
});
|
||||
|
||||
const updateManySecretsRawFn = updateManySecretsRawFnFactory({
|
||||
@ -331,8 +321,7 @@ export const secretQueueFactory = ({
|
||||
kmsService,
|
||||
secretVersionV2BridgeDAL,
|
||||
secretV2BridgeDAL,
|
||||
secretVersionTagV2BridgeDAL,
|
||||
resourceMetadataDAL
|
||||
secretVersionTagV2BridgeDAL
|
||||
});
|
||||
|
||||
/**
|
||||
@ -383,7 +372,6 @@ export const secretQueueFactory = ({
|
||||
}
|
||||
|
||||
content[secretKey].skipMultilineEncoding = Boolean(secret.skipMultilineEncoding);
|
||||
content[secretKey].secretMetadata = secret.secretMetadata;
|
||||
})
|
||||
);
|
||||
|
||||
@ -409,8 +397,7 @@ export const secretQueueFactory = ({
|
||||
content[importedSecret.key] = {
|
||||
skipMultilineEncoding: importedSecret.skipMultilineEncoding,
|
||||
comment: importedSecret.secretComment,
|
||||
value: importedSecret.secretValue || "",
|
||||
secretMetadata: importedSecret.secretMetadata
|
||||
value: importedSecret.secretValue || ""
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -610,7 +597,6 @@ export const secretQueueFactory = ({
|
||||
_depth: depth,
|
||||
secretPath,
|
||||
projectId,
|
||||
orgId,
|
||||
environmentSlug: environment,
|
||||
excludeReplication,
|
||||
actorId,
|
||||
@ -639,7 +625,6 @@ export const secretQueueFactory = ({
|
||||
_deDupeReplicationQueue: deDupeReplicationQueue,
|
||||
_depth: depth,
|
||||
projectId,
|
||||
orgId,
|
||||
secretPath,
|
||||
actorId,
|
||||
actor,
|
||||
@ -696,7 +681,6 @@ export const secretQueueFactory = ({
|
||||
if (!folder) {
|
||||
throw new Error("Secret path not found");
|
||||
}
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
// find all imports made with the given environment and secret path
|
||||
const linkSourceDto = {
|
||||
@ -731,7 +715,6 @@ export const secretQueueFactory = ({
|
||||
.map(({ folderId }) =>
|
||||
syncSecrets({
|
||||
projectId,
|
||||
orgId: project.orgId,
|
||||
secretPath: foldersGroupedById[folderId][0]?.path as string,
|
||||
environmentSlug: foldersGroupedById[folderId][0]?.environmentSlug as string,
|
||||
_deDupeQueue: deDupeQueue,
|
||||
@ -784,7 +767,6 @@ export const secretQueueFactory = ({
|
||||
.map((folderId) =>
|
||||
syncSecrets({
|
||||
projectId,
|
||||
orgId: project.orgId,
|
||||
secretPath: referencedFoldersGroupedById[folderId][0]?.path as string,
|
||||
environmentSlug: referencedFoldersGroupedById[folderId][0]?.environmentSlug as string,
|
||||
_deDupeQueue: deDupeQueue,
|
||||
|
@ -288,7 +288,6 @@ export const secretServiceFactory = ({
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
}
|
||||
@ -430,7 +429,6 @@ export const secretServiceFactory = ({
|
||||
await snapshotService.performSnapshot(folderId);
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath: path,
|
||||
orgId: actorOrgId,
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
@ -528,7 +526,6 @@ export const secretServiceFactory = ({
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
}
|
||||
@ -823,7 +820,6 @@ export const secretServiceFactory = ({
|
||||
actorId,
|
||||
secretPath: path,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
|
||||
@ -932,7 +928,6 @@ export const secretServiceFactory = ({
|
||||
actorId,
|
||||
secretPath: path,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
|
||||
@ -1019,7 +1014,6 @@ export const secretServiceFactory = ({
|
||||
actorId,
|
||||
secretPath: path,
|
||||
projectId,
|
||||
orgId: actorOrgId,
|
||||
environmentSlug: folder.environment.slug
|
||||
});
|
||||
|
||||
@ -1391,8 +1385,7 @@ export const secretServiceFactory = ({
|
||||
skipMultilineEncoding,
|
||||
tagIds,
|
||||
secretReminderNote,
|
||||
secretReminderRepeatDays,
|
||||
secretMetadata
|
||||
secretReminderRepeatDays
|
||||
}: TCreateSecretRawDTO) => {
|
||||
const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
|
||||
const policy =
|
||||
@ -1419,8 +1412,7 @@ export const secretServiceFactory = ({
|
||||
secretValue,
|
||||
tagIds,
|
||||
reminderNote: secretReminderNote,
|
||||
reminderRepeatDays: secretReminderRepeatDays,
|
||||
secretMetadata
|
||||
reminderRepeatDays: secretReminderRepeatDays
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1443,8 +1435,7 @@ export const secretServiceFactory = ({
|
||||
tagIds,
|
||||
secretReminderNote,
|
||||
skipMultilineEncoding,
|
||||
secretReminderRepeatDays,
|
||||
secretMetadata
|
||||
secretReminderRepeatDays
|
||||
});
|
||||
return { secret, type: SecretProtectionType.Direct as const };
|
||||
}
|
||||
@ -1534,8 +1525,7 @@ export const secretServiceFactory = ({
|
||||
secretReminderRepeatDays,
|
||||
metadata,
|
||||
secretComment,
|
||||
newSecretName,
|
||||
secretMetadata
|
||||
newSecretName
|
||||
}: TUpdateSecretRawDTO) => {
|
||||
const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
|
||||
const policy =
|
||||
@ -1563,8 +1553,7 @@ export const secretServiceFactory = ({
|
||||
secretValue,
|
||||
tagIds,
|
||||
reminderNote: secretReminderNote,
|
||||
reminderRepeatDays: secretReminderRepeatDays,
|
||||
secretMetadata
|
||||
reminderRepeatDays: secretReminderRepeatDays
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1588,8 +1577,7 @@ export const secretServiceFactory = ({
|
||||
secretName,
|
||||
newSecretName,
|
||||
metadata,
|
||||
secretValue,
|
||||
secretMetadata
|
||||
secretValue
|
||||
});
|
||||
return { type: SecretProtectionType.Direct as const, secret };
|
||||
}
|
||||
@ -1805,8 +1793,7 @@ export const secretServiceFactory = ({
|
||||
secretComment: el.secretComment,
|
||||
metadata: el.metadata,
|
||||
skipMultilineEncoding: el.skipMultilineEncoding,
|
||||
secretKey: el.secretKey,
|
||||
secretMetadata: el.secretMetadata
|
||||
secretKey: el.secretKey
|
||||
}))
|
||||
}
|
||||
});
|
||||
@ -1932,8 +1919,7 @@ export const secretServiceFactory = ({
|
||||
secretValue: el.secretValue,
|
||||
secretComment: el.secretComment,
|
||||
skipMultilineEncoding: el.skipMultilineEncoding,
|
||||
secretKey: el.secretKey,
|
||||
secretMetadata: el.secretMetadata
|
||||
secretKey: el.secretKey
|
||||
}))
|
||||
}
|
||||
});
|
||||
@ -2276,7 +2262,6 @@ export const secretServiceFactory = ({
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath,
|
||||
projectId: project.id,
|
||||
orgId: project.orgId,
|
||||
environmentSlug: environment,
|
||||
excludeReplication: true
|
||||
});
|
||||
@ -2385,7 +2370,6 @@ export const secretServiceFactory = ({
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath,
|
||||
projectId: project.id,
|
||||
orgId: project.orgId,
|
||||
environmentSlug: environment,
|
||||
excludeReplication: true
|
||||
});
|
||||
@ -2844,7 +2828,6 @@ export const secretServiceFactory = ({
|
||||
await snapshotService.performSnapshot(destinationFolder.id);
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId: project.id,
|
||||
orgId: project.orgId,
|
||||
secretPath: destinationFolder.path,
|
||||
environmentSlug: destinationFolder.environment.slug,
|
||||
actorId,
|
||||
@ -2856,7 +2839,6 @@ export const secretServiceFactory = ({
|
||||
await snapshotService.performSnapshot(sourceFolder.id);
|
||||
await secretQueueService.syncSecrets({
|
||||
projectId: project.id,
|
||||
orgId: project.orgId,
|
||||
secretPath: sourceFolder.path,
|
||||
environmentSlug: sourceFolder.environment.slug,
|
||||
actorId,
|
||||
|
@ -14,8 +14,6 @@ import { TSecretTagDALFactory } from "@app/services/secret-tag/secret-tag-dal";
|
||||
|
||||
import { ActorType } from "../auth/auth-type";
|
||||
import { TKmsServiceFactory } from "../kms/kms-service";
|
||||
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
|
||||
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
|
||||
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
|
||||
import { TSecretVersionV2DALFactory } from "../secret-v2-bridge/secret-version-dal";
|
||||
import { TSecretVersionV2TagDALFactory } from "../secret-v2-bridge/secret-version-tag-dal";
|
||||
@ -213,7 +211,6 @@ export type TCreateSecretRawDTO = TProjectPermission & {
|
||||
skipMultilineEncoding?: boolean;
|
||||
secretReminderRepeatDays?: number | null;
|
||||
secretReminderNote?: string | null;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
};
|
||||
|
||||
export type TUpdateSecretRawDTO = TProjectPermission & {
|
||||
@ -231,7 +228,6 @@ export type TUpdateSecretRawDTO = TProjectPermission & {
|
||||
metadata?: {
|
||||
source?: string;
|
||||
};
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
};
|
||||
|
||||
export type TDeleteSecretRawDTO = TProjectPermission & {
|
||||
@ -252,7 +248,6 @@ export type TCreateManySecretRawDTO = Omit<TProjectPermission, "projectId"> & {
|
||||
secretComment?: string;
|
||||
skipMultilineEncoding?: boolean;
|
||||
tagIds?: string[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
metadata?: {
|
||||
source?: string;
|
||||
};
|
||||
@ -271,7 +266,6 @@ export type TUpdateManySecretRawDTO = Omit<TProjectPermission, "projectId"> & {
|
||||
secretComment?: string;
|
||||
skipMultilineEncoding?: boolean;
|
||||
tagIds?: string[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
secretReminderRepeatDays?: number | null;
|
||||
secretReminderNote?: string | null;
|
||||
}[];
|
||||
@ -299,13 +293,7 @@ export type TSecretReference = { environment: string; secretPath: string };
|
||||
export type TFnSecretBulkInsert = {
|
||||
folderId: string;
|
||||
tx?: Knex;
|
||||
inputSecrets: Array<
|
||||
Omit<TSecretsInsert, "folderId"> & {
|
||||
tags?: string[];
|
||||
references?: TSecretReference[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
}
|
||||
>;
|
||||
inputSecrets: Array<Omit<TSecretsInsert, "folderId"> & { tags?: string[]; references?: TSecretReference[] }>;
|
||||
secretDAL: Pick<TSecretDALFactory, "insertMany" | "upsertSecretReferences">;
|
||||
secretVersionDAL: Pick<TSecretVersionDALFactory, "insertMany">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecret">;
|
||||
@ -401,7 +389,6 @@ export type TCreateManySecretsRawFnFactory = {
|
||||
>;
|
||||
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
|
||||
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">;
|
||||
};
|
||||
|
||||
export type TCreateManySecretsRawFn = {
|
||||
@ -438,7 +425,6 @@ export type TUpdateManySecretsRawFnFactory = {
|
||||
>;
|
||||
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
|
||||
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
};
|
||||
|
||||
export type TUpdateManySecretsRawFn = {
|
||||
@ -474,7 +460,6 @@ export type TSyncSecretsDTO<T extends boolean = false> = {
|
||||
_depth?: number;
|
||||
secretPath: string;
|
||||
projectId: string;
|
||||
orgId: string;
|
||||
environmentSlug: string;
|
||||
// cases for just doing sync integration and webhook
|
||||
excludeReplication?: T;
|
||||
|
@ -4,6 +4,13 @@ sidebarTitle: "Overview"
|
||||
description: "Learn how to generate secrets dynamically on-demand."
|
||||
---
|
||||
|
||||
<Info>
|
||||
Note that Dynamic Secrets is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Enterprise Tier**
|
||||
If you're self-hosting Infisical, then you should contact sales@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
## Introduction
|
||||
|
||||
Contrary to static key-value secrets, which require manual input of data into the secure Infisical storage, **dynamic secrets are generated on-demand upon access**.
|
||||
|
@ -3,6 +3,13 @@ title: "Approval Workflows"
|
||||
description: "Learn how to enable a set of policies to manage changes to sensitive secrets and environments."
|
||||
---
|
||||
|
||||
<Info>
|
||||
Approval Workflows is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Pro Tier** and **Enterprise Tire**.
|
||||
If you're self-hosting Infisical, then you should contact sales@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
## Problem at hand
|
||||
|
||||
Updating secrets in high-stakes environments (e.g., production) can have a number of problematic issues:
|
||||
@ -40,4 +47,4 @@ When a user submits a change to an enviropnment that is under a particular polic
|
||||
|
||||
Approvers are notified by email and/or Slack as soon as the request is initiated. In the Infisical Dashboard, they will be able to `approve` and `merge` (or `deny`) a request for a change in a particular environment. After that, depending on the workflows setup, the change will be automatically propagated to the right applications (e.g., using [Infisical Kubernetes Operator](https://infisical.com/docs/integrations/platforms/kubernetes)).
|
||||
|
||||

|
||||

|
||||
|
@ -15,7 +15,7 @@ Prerequisites:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a SCIM token in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SCIM Configuration and
|
||||
In Infisical, head to your Organization Settings > Security > SCIM Configuration and
|
||||
press the **Enable SCIM provisioning** toggle to allow Azure to provision/deprovision users for your organization.
|
||||
|
||||

|
||||
|
@ -15,7 +15,7 @@ Prerequisites:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a SCIM token in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SCIM Configuration and
|
||||
In Infisical, head to your Organization Settings > Security > SCIM Configuration and
|
||||
press the **Enable SCIM provisioning** toggle to allow JumpCloud to provision/deprovision users and user groups for your organization.
|
||||
|
||||

|
||||
|
@ -15,7 +15,7 @@ Prerequisites:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a SCIM token in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SCIM Configuration and
|
||||
In Infisical, head to your Organization Settings > Security > SCIM Configuration and
|
||||
press the **Enable SCIM provisioning** toggle to allow Okta to provision/deprovision users and user groups for your organization.
|
||||
|
||||

|
||||
|
93
docs/documentation/platform/sso/auth0-saml.mdx
Normal file
93
docs/documentation/platform/sso/auth0-saml.mdx
Normal file
@ -0,0 +1,93 @@
|
||||
---
|
||||
title: "Auth0 SAML"
|
||||
description: "Learn how to configure Auth0 SAML for Infisical SSO."
|
||||
---
|
||||
|
||||
<Info>
|
||||
Auth0 SAML SSO feature is a paid feature. If you're using Infisical Cloud,
|
||||
then it is available under the **Pro Tier**. If you're self-hosting Infisical,
|
||||
then you should contact sales@infisical.com to purchase an enterprise license
|
||||
to use it.
|
||||
</Info>
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Auth0, then click **Connect** again.
|
||||
|
||||
Next, note the **Application Callback URL** and **Audience** to use when configuring the Auth0 SAML application.
|
||||
|
||||

|
||||
|
||||
</Step>
|
||||
<Step title="Create a SAML application in Auth0">
|
||||
2.1. In your Auth0 account, head to Applications and create an application.
|
||||
|
||||

|
||||
|
||||
Select **Regular Web Application** and press **Create**.
|
||||
|
||||

|
||||
|
||||
2.2. In the Application head to Settings > Application URIs and add the **Application Callback URL** from step 1 into the **Allowed Callback URLs** field.
|
||||
|
||||

|
||||
|
||||
2.3. In the Application head to Addons > SAML2 Web App and copy the **Issuer**, **Identity Provider Login URL**, and **Identity Provider Certificate** from the **Usage** tab.
|
||||
|
||||

|
||||
|
||||
2.4. Back in Infisical, set **Issuer**, **Identity Provider Login URL**, and **Certificate** to the corresponding items from step 2.3.
|
||||
|
||||

|
||||
|
||||
2.5. Back in Auth0, in the **Settings** tab, set the **Application Callback URL** to the **Application Callback URL** from step 1
|
||||
and update the **Settings** field with the JSON under the picture below (replacing `<audience-from-infisical>` with the **Audience** from step 1).
|
||||
|
||||

|
||||
|
||||
```json
|
||||
{
|
||||
"audience": "<audience-from-infisical>",
|
||||
"mappings": {
|
||||
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email",
|
||||
"given_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/firstName",
|
||||
"family_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/lastName"
|
||||
},
|
||||
"signatureAlgorithm": "rsa-sha256",
|
||||
"digestAlgorithm": "sha256",
|
||||
"signResponse": true
|
||||
}
|
||||
```
|
||||
|
||||
Click **Save**.
|
||||
</Step>
|
||||
<Step title="Enable SAML SSO in Infisical">
|
||||
Enabling SAML SSO allows members in your organization to log into Infisical via Auth0.
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="Enforce SAML SSO in Infisical">
|
||||
Enforcing SAML SSO ensures that members in your organization can only access Infisical
|
||||
by logging into the organization via Auth0.
|
||||
|
||||
To enforce SAML SSO, you're required to test out the SAML connection by successfully authenticating at least one Auth0 user with Infisical;
|
||||
Once you've completed this requirement, you can toggle the **Enforce SAML SSO** button to enforce SAML SSO.
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
If you are only using one organization on your Infisical instance, you can configure a default organization in the [Server Admin Console](../admin-panel/server-admin#default-organization) to expedite SAML login.
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
If you're configuring SAML SSO on a self-hosted instance of Infisical, make
|
||||
sure to set the `AUTH_SECRET` and `SITE_URL` environment variable for it to
|
||||
work:
|
||||
<div class="height:1px;"/>
|
||||
- `AUTH_SECRET`: A secret key used for signing and verifying JWT. This
|
||||
can be a random 32-byte base64 string generated with `openssl rand -base64
|
||||
32`.
|
||||
<div class="height:1px;"/>
|
||||
- `SITE_URL`: The absolute URL of your self-hosted instance of Infisical including the protocol (e.g. https://app.infisical.com)
|
||||
</Note>
|
@ -12,7 +12,7 @@ description: "Learn how to configure Microsoft Entra ID for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Azure / Entra, then click **Connect** again.
|
||||
|
||||
Next, copy the **Reply URL (Assertion Consumer Service URL)** and **Identifier (Entity ID)** to use when configuring the Azure SAML application.
|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure Google SAML for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Google, then click **Connect** again.
|
||||
|
||||
Next, note the **ACS URL** and **SP Entity ID** to use when configuring the Google SAML application.
|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure JumpCloud SAML for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select JumpCloud, then click **Connect** again.
|
||||
|
||||
Next, copy the **ACS URL** and **SP Entity ID** to use when configuring the JumpCloud SAML application.
|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure Keycloak SAML for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Manage**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Keycloak, then click **Connect** again.
|
||||
|
||||

|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure Okta SAML 2.0 for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Okta, then click **Connect** again.
|
||||
|
||||
Next, copy the **Single sign-on URL** and **Audience URI (SP Entity ID)** to use when configuring the Okta SAML 2.0 application.
|
||||

|
||||
|
@ -28,6 +28,7 @@ Infisical supports these and many other identity providers:
|
||||
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)
|
||||
- [Keycloak SAML](/documentation/platform/sso/keycloak-saml)
|
||||
- [Google SAML](/documentation/platform/sso/google-saml)
|
||||
- [Auth0 SAML](/documentation/platform/sso/auth0-saml)
|
||||
- [Keycloak OIDC](/documentation/platform/sso/keycloak-oidc)
|
||||
- [Auth0 OIDC](/documentation/platform/sso/auth0-oidc)
|
||||
- [General OIDC](/documentation/platform/sso/general-oidc)
|
||||
|
Binary file not shown.
Before ![]() (image error) Size: 580 KiB After ![]() (image error) Size: 74 KiB ![]() ![]() |
BIN
docs/images/sso/auth0-saml/auth0-config-2.png
Normal file
BIN
docs/images/sso/auth0-saml/auth0-config-2.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 612 KiB |
BIN
docs/images/sso/auth0-saml/auth0-config-3.png
Normal file
BIN
docs/images/sso/auth0-saml/auth0-config-3.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 366 KiB |
BIN
docs/images/sso/auth0-saml/auth0-config.png
Normal file
BIN
docs/images/sso/auth0-saml/auth0-config.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 431 KiB |
BIN
docs/images/sso/auth0-saml/create-application-2.png
Normal file
BIN
docs/images/sso/auth0-saml/create-application-2.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 352 KiB |
BIN
docs/images/sso/auth0-saml/create-application.png
Normal file
BIN
docs/images/sso/auth0-saml/create-application.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 253 KiB |
BIN
docs/images/sso/auth0-saml/enable-saml.png
Normal file
BIN
docs/images/sso/auth0-saml/enable-saml.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 605 KiB |
BIN
docs/images/sso/auth0-saml/infisical-config.png
Normal file
BIN
docs/images/sso/auth0-saml/infisical-config.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 605 KiB |
BIN
docs/images/sso/auth0-saml/init-config.png
Normal file
BIN
docs/images/sso/auth0-saml/init-config.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 539 KiB |
@ -17,7 +17,6 @@ Prerequisites:
|
||||
If your instance is deployed on AWS, the aws-sdk will automatically retrieve the credentials. Ensure that you assign the provided permission policy to your deployed instance, such as ECS or EC2.
|
||||
|
||||
The following steps are for instances not deployed on AWS
|
||||
|
||||
<Steps>
|
||||
<Step title="Create an IAM User">
|
||||
Navigate to [Create IAM User](https://console.aws.amazon.com/iamv2/home#/users/create) in your AWS Console.
|
||||
@ -41,10 +40,9 @@ The following steps are for instances not deployed on AWS
|
||||
<Step title="Obtain the IAM User Credentials">
|
||||
Obtain the AWS access key ID and secret access key for your IAM User by navigating to IAM > Users > [Your User] > Security credentials > Access keys.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||

|
||||
</Step>
|
||||
<Step title="Set Up Integration Keys">
|
||||
1. Set the access key as **CLIENT_ID_AWS_INTEGRATION**.
|
||||
@ -61,7 +59,6 @@ The following steps are for instances not deployed on AWS
|
||||
2. Select **AWS Account** as the **Trusted Entity Type**.
|
||||
3. Choose **Another AWS Account** and enter **381492033652** (Infisical AWS Account ID). This restricts the role to be assumed only by Infisical. If self-hosting, provide your AWS account number instead.
|
||||
4. Optionally, enable **Require external ID** and enter your **project ID** to further enhance security.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add Required Permissions for the IAM Role">
|
||||
@ -92,13 +89,11 @@ The following steps are for instances not deployed on AWS
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Copy the AWS IAM Role ARN">
|
||||

|
||||
</Step>
|
||||
<Step title="Copy the AWS IAM Role ARN">
|
||||

|
||||
</Step>
|
||||
|
||||
<Step title="Authorize Infisical for AWS Secrets Manager">
|
||||
1. Navigate to your project's integrations tab in Infisical.
|
||||
@ -109,7 +104,6 @@ The following steps are for instances not deployed on AWS
|
||||

|
||||
|
||||
4. Provide the **AWS IAM Role ARN** obtained from the previous step.
|
||||
|
||||
</Step> <Step title="Start integration">
|
||||
Select how you want to integration to work by specifying a number of parameters:
|
||||
|
||||
@ -133,12 +127,6 @@ The following steps are for instances not deployed on AWS
|
||||
|
||||
Optionally, you can add tags or specify the encryption key of all the secrets created via this integration:
|
||||
|
||||
<ParamField path="Tag Sync Mode" type="string" optional>
|
||||
The sync mode for AWS tags. The supported options are `Secret Metadata` and `Custom`. If `Secret Metadata` is selected,
|
||||
the metadata of the Infisical secrets are used as tags in AWS. If custom is selected, then the key/value of the **Secret Tag** field is used. `Secret Metadata` mode
|
||||
is only supported for one-to-one integrations.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="Secret Tag" type="string" optional>
|
||||
The Key/Value of a tag that will be added to secrets in AWS. Please note that it is possible to add multiple tags via API.
|
||||
</ParamField>
|
||||
|
@ -248,6 +248,7 @@
|
||||
"documentation/platform/sso/jumpcloud",
|
||||
"documentation/platform/sso/keycloak-saml",
|
||||
"documentation/platform/sso/google-saml",
|
||||
"documentation/platform/sso/auth0-saml",
|
||||
"documentation/platform/sso/keycloak-oidc",
|
||||
"documentation/platform/sso/auth0-oidc",
|
||||
"documentation/platform/sso/general-oidc"
|
||||
|
@ -101,6 +101,10 @@ export const ROUTE_PATHS = Object.freeze({
|
||||
"/secret-manager/$projectId/integrations/azure-devops/create",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/create"
|
||||
),
|
||||
AzureKeyVaultAuthorizePage: setRoute(
|
||||
"/secret-manager/$projectId/integrations/azure-key-vault/authorize",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize"
|
||||
),
|
||||
AzureKeyVaultOauthCallbackPage: setRoute(
|
||||
"/secret-manager/$projectId/integrations/azure-key-vault/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/oauth2/callback"
|
||||
|
@ -4,12 +4,7 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { workspaceKeys } from "../workspace";
|
||||
import {
|
||||
IntegrationMetadataSyncMode,
|
||||
TCloudIntegration,
|
||||
TIntegrationWithEnv,
|
||||
TOctopusDeployScopeValues
|
||||
} from "./types";
|
||||
import { TCloudIntegration, TIntegrationWithEnv, TOctopusDeployScopeValues } from "./types";
|
||||
|
||||
export const integrationQueryKeys = {
|
||||
getIntegrations: () => ["integrations"] as const,
|
||||
@ -93,7 +88,6 @@ export const useCreateIntegration = () => {
|
||||
shouldProtectSecrets?: boolean;
|
||||
shouldEnableDelete?: boolean;
|
||||
octopusDeployScopeValues?: TOctopusDeployScopeValues;
|
||||
metadataSyncMode?: IntegrationMetadataSyncMode;
|
||||
};
|
||||
}) => {
|
||||
const {
|
||||
|
@ -62,7 +62,6 @@ export type TIntegration = {
|
||||
octopusDeployScopeValues?: TOctopusDeployScopeValues;
|
||||
awsIamRole?: string;
|
||||
region?: string;
|
||||
metadataSyncMode?: IntegrationMetadataSyncMode;
|
||||
};
|
||||
};
|
||||
|
||||
@ -93,8 +92,3 @@ export enum IntegrationMappingBehavior {
|
||||
ONE_TO_ONE = "one-to-one",
|
||||
MANY_TO_ONE = "many-to-one"
|
||||
}
|
||||
|
||||
export enum IntegrationMetadataSyncMode {
|
||||
CUSTOM = "custom",
|
||||
SECRET_METADATA = "secret-metadata"
|
||||
}
|
||||
|
@ -82,7 +82,6 @@ export type TSecretApprovalRequest = {
|
||||
conflicts: Array<{ secretId: string; op: CommitType.UPDATE }>;
|
||||
commits: ({
|
||||
// if there is no secret means it was creation
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
secret?: { version: number };
|
||||
secretVersion: SecretV3Raw;
|
||||
// if there is no new version its for Delete
|
||||
|
@ -84,8 +84,7 @@ export const useUpdateSecretV3 = ({
|
||||
secretReminderRepeatDays,
|
||||
secretReminderNote,
|
||||
newSecretName,
|
||||
skipMultilineEncoding,
|
||||
secretMetadata
|
||||
skipMultilineEncoding
|
||||
}) => {
|
||||
const { data } = await apiRequest.patch(`/api/v3/secrets/raw/${secretKey}`, {
|
||||
workspaceId,
|
||||
@ -98,8 +97,7 @@ export const useUpdateSecretV3 = ({
|
||||
newSecretName,
|
||||
secretComment,
|
||||
tagIds,
|
||||
secretValue,
|
||||
secretMetadata
|
||||
secretValue
|
||||
});
|
||||
return data;
|
||||
},
|
||||
|
@ -67,8 +67,7 @@ export const mergePersonalSecrets = (rawSecrets: SecretV3Raw[]) => {
|
||||
updatedAt: el.updatedAt,
|
||||
version: el.version,
|
||||
skipMultilineEncoding: el.skipMultilineEncoding,
|
||||
path: el.secretPath,
|
||||
secretMetadata: el.secretMetadata
|
||||
path: el.secretPath
|
||||
};
|
||||
|
||||
if (el.type === SecretType.Personal) {
|
||||
|
@ -48,7 +48,6 @@ export type SecretV3RawSanitized = {
|
||||
overrideAction?: string;
|
||||
folderId?: string;
|
||||
skipMultilineEncoding?: boolean;
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
};
|
||||
|
||||
export type SecretV3Raw = {
|
||||
@ -64,7 +63,6 @@ export type SecretV3Raw = {
|
||||
secretComment?: string;
|
||||
secretReminderNote?: string;
|
||||
secretReminderRepeatDays?: number;
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
skipMultilineEncoding?: boolean;
|
||||
metadata?: Record<string, string>;
|
||||
tags?: WsTag[];
|
||||
@ -150,7 +148,6 @@ export type TUpdateSecretsV3DTO = {
|
||||
secretReminderRepeatDays?: number | null;
|
||||
secretReminderNote?: string | null;
|
||||
tagIds?: string[];
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
};
|
||||
|
||||
export type TDeleteSecretsV3DTO = {
|
||||
|
@ -25,7 +25,8 @@ enum AuthProvider {
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml",
|
||||
KEYCLOAK_SAML = "keycloak-saml",
|
||||
GOOGLE_SAML = "google-saml"
|
||||
GOOGLE_SAML = "google-saml",
|
||||
AUTH0_SAML = "auth0-saml"
|
||||
}
|
||||
|
||||
const ssoAuthProviders = [
|
||||
@ -33,7 +34,8 @@ const ssoAuthProviders = [
|
||||
{ label: "Azure / Entra SAML", value: AuthProvider.AZURE_SAML },
|
||||
{ label: "JumpCloud SAML", value: AuthProvider.JUMPCLOUD_SAML },
|
||||
{ label: "Keycloak SAML", value: AuthProvider.KEYCLOAK_SAML },
|
||||
{ label: "Google SAML", value: AuthProvider.GOOGLE_SAML }
|
||||
{ label: "Google SAML", value: AuthProvider.GOOGLE_SAML },
|
||||
{ label: "Auth0 SAML", value: AuthProvider.AUTH0_SAML }
|
||||
];
|
||||
|
||||
const schema = z
|
||||
@ -191,6 +193,15 @@ export const SSOModal = ({ popUp, handlePopUpClose, handlePopUpToggle, hideDelet
|
||||
issuer: "Issuer",
|
||||
issuerPlaceholder: window.origin
|
||||
};
|
||||
case AuthProvider.AUTH0_SAML:
|
||||
return {
|
||||
acsUrl: "Application Callback URL",
|
||||
entityId: "Audience",
|
||||
entryPoint: "Identity Provider Login URL",
|
||||
entryPointPlaceholder: "https://xxx.auth0.com/samlp/xxx",
|
||||
issuer: "Issuer",
|
||||
issuerPlaceholder: "urn:xxx-xxx.us.auth0.com"
|
||||
};
|
||||
default:
|
||||
return {
|
||||
acsUrl: "ACS URL",
|
||||
|
@ -32,8 +32,7 @@ const metadataMappings: Record<keyof NonNullable<TIntegrationWithEnv["metadata"]
|
||||
shouldEnableDelete: "GitHub Secret Deletion Enabled",
|
||||
octopusDeployScopeValues: "Octopus Deploy Scope Values",
|
||||
awsIamRole: "AWS IAM Role",
|
||||
region: "Region",
|
||||
metadataSyncMode: "Metadata Sync Mode"
|
||||
region: "Region"
|
||||
} as const;
|
||||
|
||||
export const IntegrationSettingsSection = ({ integration }: Props) => {
|
||||
|
@ -80,8 +80,16 @@ export const redirectForProviderAuth = (
|
||||
createIntegrationMissingEnvVarsNotification(integrationOption.slug);
|
||||
return;
|
||||
}
|
||||
const link = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${window.location.origin}/integrations/azure-key-vault/oauth2/callback&response_mode=query&scope=https://vault.azure.net/.default openid offline_access&state=${state}`;
|
||||
window.location.assign(link);
|
||||
navigate({
|
||||
to: "/secret-manager/$projectId/integrations/azure-key-vault/authorize",
|
||||
params: {
|
||||
projectId
|
||||
},
|
||||
search: {
|
||||
clientId: integrationOption.clientId,
|
||||
state,
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "azure-app-configuration": {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { faExclamationTriangle, faInfo, faKey } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faExclamationTriangle, faInfo } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import {
|
||||
@ -18,10 +18,7 @@ import { CommitType, SecretV3Raw, TSecretApprovalSecChange, WsTag } from "@app/h
|
||||
export type Props = {
|
||||
op: CommitType;
|
||||
secretVersion?: SecretV3Raw;
|
||||
newVersion?: Omit<TSecretApprovalSecChange, "tags"> & {
|
||||
tags?: WsTag[];
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
};
|
||||
newVersion?: Omit<TSecretApprovalSecChange, "tags"> & { tags?: WsTag[] };
|
||||
presentSecretVersionNumber: number;
|
||||
hasMerged?: boolean;
|
||||
conflicts: Array<{ secretId: string; op: CommitType }>;
|
||||
@ -83,12 +80,11 @@ export const SecretApprovalRequestChangeItem = ({
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
{op === CommitType.UPDATE && <Th className="w-12 shrink-0" />}
|
||||
<Th className="w-48 shrink-0">Secret</Th>
|
||||
<Th className="min-w-0 flex-1">Value</Th>
|
||||
<Th className="w-24 shrink-0">Comment</Th>
|
||||
<Th className="w-24 shrink-0">Tags</Th>
|
||||
<Th className="w-40 shrink-0">Metadata</Th>
|
||||
{op === CommitType.UPDATE && <Th className="w-12" />}
|
||||
<Th className="min-table-row">Secret</Th>
|
||||
<Th>Value</Th>
|
||||
<Th className="min-table-row">Comment</Th>
|
||||
<Th className="min-table-row">Tags</Th>
|
||||
</Tr>
|
||||
</THead>
|
||||
{op === CommitType.UPDATE ? (
|
||||
@ -114,33 +110,6 @@ export const SecretApprovalRequestChangeItem = ({
|
||||
</Tag>
|
||||
))}
|
||||
</Td>
|
||||
<Td>
|
||||
{secretVersion?.secretMetadata?.length ? (
|
||||
<div className="mt-1 flex flex-wrap gap-2 text-sm text-mineshaft-300">
|
||||
{secretVersion.secretMetadata?.map((el) => (
|
||||
<div key={el.key} className="flex items-center">
|
||||
<Tag
|
||||
size="xs"
|
||||
className="mr-0 flex items-center rounded-r-none border border-mineshaft-500"
|
||||
>
|
||||
<FontAwesomeIcon icon={faKey} size="xs" className="mr-1" />
|
||||
<div>{el.key}</div>
|
||||
</Tag>
|
||||
<Tag
|
||||
size="xs"
|
||||
className="flex items-center rounded-l-none border border-mineshaft-500 bg-mineshaft-900 pl-1"
|
||||
>
|
||||
<div className="max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{el.value}
|
||||
</div>
|
||||
</Tag>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-mineshaft-300">-</p>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
<Tr>
|
||||
<Td className="text-green-600">NEW</Td>
|
||||
@ -163,33 +132,6 @@ export const SecretApprovalRequestChangeItem = ({
|
||||
</Tag>
|
||||
))}
|
||||
</Td>
|
||||
<Td>
|
||||
{newVersion?.secretMetadata?.length ? (
|
||||
<div className="mt-1 flex flex-wrap gap-2 text-sm text-mineshaft-300">
|
||||
{newVersion.secretMetadata?.map((el) => (
|
||||
<div key={el.key} className="flex items-center">
|
||||
<Tag
|
||||
size="xs"
|
||||
className="mr-0 flex items-center rounded-r-none border border-mineshaft-500"
|
||||
>
|
||||
<FontAwesomeIcon icon={faKey} size="xs" className="mr-1" />
|
||||
<div>{el.key}</div>
|
||||
</Tag>
|
||||
<Tag
|
||||
size="xs"
|
||||
className="flex items-center rounded-l-none border border-mineshaft-500 bg-mineshaft-900 pl-1"
|
||||
>
|
||||
<div className="max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{el.value}
|
||||
</div>
|
||||
</Tag>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-mineshaft-300">-</p>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
</TBody>
|
||||
) : (
|
||||
@ -231,33 +173,6 @@ export const SecretApprovalRequestChangeItem = ({
|
||||
)
|
||||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
{newVersion?.secretMetadata?.length ? (
|
||||
<div className="mt-1 flex flex-wrap gap-2 text-sm text-mineshaft-300">
|
||||
{newVersion.secretMetadata?.map((el) => (
|
||||
<div key={el.key} className="flex items-center">
|
||||
<Tag
|
||||
size="xs"
|
||||
className="mr-0 flex items-center rounded-r-none border border-mineshaft-500"
|
||||
>
|
||||
<FontAwesomeIcon icon={faKey} size="xs" className="mr-1" />
|
||||
<div>{el.key}</div>
|
||||
</Tag>
|
||||
<Tag
|
||||
size="xs"
|
||||
className="flex items-center rounded-l-none border border-mineshaft-500 bg-mineshaft-900 pl-1"
|
||||
>
|
||||
<div className="max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{el.value}
|
||||
</div>
|
||||
</Tag>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-mineshaft-300">-</p>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
</TBody>
|
||||
)}
|
||||
|
@ -8,8 +8,7 @@ import {
|
||||
faClock,
|
||||
faPlus,
|
||||
faShare,
|
||||
faTag,
|
||||
faTrash
|
||||
faTag
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@ -27,7 +26,6 @@ import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
IconButton,
|
||||
Input,
|
||||
Switch,
|
||||
@ -89,16 +87,11 @@ export const SecretDetailSidebar = ({
|
||||
|
||||
const { permission } = useProjectPermission();
|
||||
|
||||
const tagFields = useFieldArray({
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
control,
|
||||
name: "tags"
|
||||
});
|
||||
|
||||
const metadataFormFields = useFieldArray({
|
||||
control,
|
||||
name: "secretMetadata"
|
||||
});
|
||||
|
||||
const secretKey = secret?.key || "";
|
||||
const selectedTags = watch("tags", []) || [];
|
||||
const selectedTagsGroupById = selectedTags.reduce<Record<string, boolean>>(
|
||||
@ -160,10 +153,10 @@ export const SecretDetailSidebar = ({
|
||||
if (selectedTagsGroupById?.[tag.id]) {
|
||||
const tagPos = selectedTags.findIndex(({ id }) => id === tag.id);
|
||||
if (tagPos !== -1) {
|
||||
tagFields.remove(tagPos);
|
||||
remove(tagPos);
|
||||
}
|
||||
} else {
|
||||
tagFields.append(tag);
|
||||
append(tag);
|
||||
}
|
||||
};
|
||||
|
||||
@ -284,73 +277,9 @@ export const SecretDetailSidebar = ({
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<FormControl label="Metadata">
|
||||
<div className="flex flex-col space-y-2">
|
||||
{metadataFormFields.fields.map(({ id: metadataFieldId }, i) => (
|
||||
<div key={metadataFieldId} className="flex items-end space-x-2">
|
||||
<div className="flex-grow">
|
||||
{i === 0 && <span className="text-xs text-mineshaft-400">Key</span>}
|
||||
<Controller
|
||||
control={control}
|
||||
name={`secretMetadata.${i}.key`}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error?.message)}
|
||||
errorText={error?.message}
|
||||
className="mb-0"
|
||||
>
|
||||
<Input {...field} className="max-h-8" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-grow">
|
||||
{i === 0 && (
|
||||
<FormLabel
|
||||
label="Value"
|
||||
className="text-xs text-mineshaft-400"
|
||||
isOptional
|
||||
/>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
name={`secretMetadata.${i}.value`}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error?.message)}
|
||||
errorText={error?.message}
|
||||
className="mb-0"
|
||||
>
|
||||
<Input {...field} className="max-h-8" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<IconButton
|
||||
ariaLabel="delete key"
|
||||
className="bottom-0.5 max-h-8"
|
||||
variant="outline_bg"
|
||||
onClick={() => metadataFormFields.remove(i)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrash} />
|
||||
</IconButton>
|
||||
</div>
|
||||
))}
|
||||
<div className="mt-2">
|
||||
<Button
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
size="xs"
|
||||
variant="outline_bg"
|
||||
onClick={() => metadataFormFields.append({ key: "", value: "" })}
|
||||
>
|
||||
Add Key
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormControl label="Tags" className="">
|
||||
<div className="grid auto-cols-min grid-flow-col gap-2 overflow-hidden pt-2">
|
||||
{tagFields.fields.map(({ tagColor, id: formId, slug, id }) => (
|
||||
{fields.map(({ tagColor, id: formId, slug, id }) => (
|
||||
<Tag
|
||||
className="flex w-min items-center space-x-2"
|
||||
key={formId}
|
||||
|
21
frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx
21
frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx
@ -78,8 +78,7 @@ export const SecretListView = ({
|
||||
tags,
|
||||
skipMultilineEncoding,
|
||||
newKey,
|
||||
secretId,
|
||||
secretMetadata
|
||||
secretId
|
||||
}: Partial<{
|
||||
value: string;
|
||||
comment: string;
|
||||
@ -89,7 +88,6 @@ export const SecretListView = ({
|
||||
skipMultilineEncoding: boolean;
|
||||
newKey: string;
|
||||
secretId: string;
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
}> = {}
|
||||
) => {
|
||||
if (operation === "delete") {
|
||||
@ -117,8 +115,7 @@ export const SecretListView = ({
|
||||
secretReminderRepeatDays: reminderRepeatDays,
|
||||
secretReminderNote: reminderNote,
|
||||
skipMultilineEncoding,
|
||||
newSecretName: newKey,
|
||||
secretMetadata
|
||||
newSecretName: newKey
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -141,10 +138,7 @@ export const SecretListView = ({
|
||||
const handleSaveSecret = useCallback(
|
||||
async (
|
||||
orgSecret: SecretV3RawSanitized,
|
||||
modSecret: Omit<SecretV3RawSanitized, "tags"> & {
|
||||
tags?: { id: string }[];
|
||||
secretMetadata?: { key: string; value: string }[];
|
||||
},
|
||||
modSecret: Omit<SecretV3RawSanitized, "tags"> & { tags?: { id: string }[] },
|
||||
cb?: () => void
|
||||
) => {
|
||||
const { key: oldKey } = orgSecret;
|
||||
@ -157,8 +151,7 @@ export const SecretListView = ({
|
||||
tags,
|
||||
comment,
|
||||
reminderRepeatDays,
|
||||
reminderNote,
|
||||
secretMetadata
|
||||
reminderNote
|
||||
} = modSecret;
|
||||
const hasKeyChanged = oldKey !== key && key;
|
||||
|
||||
@ -173,8 +166,7 @@ export const SecretListView = ({
|
||||
"comment",
|
||||
"skipMultilineEncoding",
|
||||
"reminderRepeatDays",
|
||||
"reminderNote",
|
||||
"secretMetadata"
|
||||
"reminderNote"
|
||||
] as const
|
||||
).every((el) => orgSecret[el] === modSecret[el]) && isSameTags;
|
||||
|
||||
@ -207,8 +199,7 @@ export const SecretListView = ({
|
||||
reminderNote,
|
||||
secretId: orgSecret.id,
|
||||
newKey: hasKeyChanged ? key : undefined,
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding,
|
||||
secretMetadata
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding
|
||||
});
|
||||
if (cb) cb();
|
||||
}
|
||||
|
@ -47,13 +47,7 @@ export const formSchema = z.object({
|
||||
.nullable()
|
||||
.optional(),
|
||||
reminderNote: z.string().trim().nullable().optional(),
|
||||
secretMetadata: z
|
||||
.object({
|
||||
key: z.string().trim().min(1),
|
||||
value: z.string().trim().default("")
|
||||
})
|
||||
.array()
|
||||
.optional(),
|
||||
|
||||
tags: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
|
@ -34,10 +34,7 @@ import { useWorkspace } from "@app/context";
|
||||
import { useCreateIntegration } from "@app/hooks/api";
|
||||
import { useGetIntegrationAuthById } from "@app/hooks/api/integrationAuth";
|
||||
import { useGetIntegrationAuthAwsKmsKeys } from "@app/hooks/api/integrationAuth/queries";
|
||||
import {
|
||||
IntegrationMappingBehavior,
|
||||
IntegrationMetadataSyncMode
|
||||
} from "@app/hooks/api/integrations/types";
|
||||
import { IntegrationMappingBehavior } from "@app/hooks/api/integrations/types";
|
||||
|
||||
enum TabSections {
|
||||
Connection = "connection",
|
||||
@ -97,7 +94,6 @@ const schema = z
|
||||
mappingBehavior: z.nativeEnum(IntegrationMappingBehavior),
|
||||
kmsKeyId: z.string().optional(),
|
||||
shouldTag: z.boolean().optional(),
|
||||
metadataSyncMode: z.nativeEnum(IntegrationMetadataSyncMode).optional(),
|
||||
tags: z
|
||||
.object({
|
||||
key: z.string(),
|
||||
@ -140,7 +136,6 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
});
|
||||
|
||||
const shouldTagState = watch("shouldTag");
|
||||
const selectedMetadataSyncMode = watch("metadataSyncMode");
|
||||
const selectedSourceEnvironment = watch("sourceEnvironment");
|
||||
const selectedAWSRegion = watch("awsRegion");
|
||||
const selectedMappingBehavior = watch("mappingBehavior");
|
||||
@ -176,8 +171,7 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
tags,
|
||||
secretPrefix,
|
||||
kmsKeyId,
|
||||
mappingBehavior,
|
||||
metadataSyncMode
|
||||
mappingBehavior
|
||||
}: TFormSchema) => {
|
||||
try {
|
||||
if (!integrationAuth?.id) return;
|
||||
@ -192,8 +186,7 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
metadata: {
|
||||
...(shouldTag
|
||||
? {
|
||||
secretAWSTag: tags,
|
||||
metadataSyncMode
|
||||
secretAWSTag: tags
|
||||
}
|
||||
: {}),
|
||||
...(secretPrefix && { secretPrefix }),
|
||||
@ -303,7 +296,7 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<SecretPathInput {...field} />
|
||||
<SecretPathInput {...field} environment={selectedSourceEnvironment} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
@ -346,12 +339,7 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
>
|
||||
<Select
|
||||
defaultValue={field.value}
|
||||
onValueChange={(e) => {
|
||||
if (e === IntegrationMappingBehavior.MANY_TO_ONE) {
|
||||
setValue("metadataSyncMode", IntegrationMetadataSyncMode.CUSTOM);
|
||||
}
|
||||
onChange(e);
|
||||
}}
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full border border-mineshaft-500"
|
||||
dropdownContainerClassName="max-w-full"
|
||||
>
|
||||
@ -398,25 +386,14 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
animate={{ opacity: 1, translateX: 0 }}
|
||||
exit={{ opacity: 0, translateX: 30 }}
|
||||
>
|
||||
<div className="mb-3 ml-1 mt-2">
|
||||
<div className="ml-1 mt-2">
|
||||
<Controller
|
||||
control={control}
|
||||
name="shouldTag"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Switch
|
||||
id="tag-aws"
|
||||
onCheckedChange={(isChecked) => {
|
||||
if (
|
||||
isChecked &&
|
||||
selectedMappingBehavior === IntegrationMappingBehavior.ONE_TO_ONE
|
||||
) {
|
||||
setValue(
|
||||
"metadataSyncMode",
|
||||
IntegrationMetadataSyncMode.SECRET_METADATA
|
||||
);
|
||||
}
|
||||
onChange(isChecked);
|
||||
}}
|
||||
onCheckedChange={(isChecked) => onChange(isChecked)}
|
||||
isChecked={value}
|
||||
>
|
||||
Tag in AWS Secrets Manager
|
||||
@ -424,76 +401,37 @@ export const AwsSecretManagerConfigurePage = () => {
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{shouldTagState &&
|
||||
selectedMappingBehavior === IntegrationMappingBehavior.ONE_TO_ONE && (
|
||||
{shouldTagState && (
|
||||
<div className="mt-4 flex justify-between">
|
||||
<Controller
|
||||
control={control}
|
||||
name="metadataSyncMode"
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
name="tags.0.key"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Tag Sync Mode"
|
||||
label="Tag Key"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Select
|
||||
defaultValue={field.value}
|
||||
onValueChange={(e) => {
|
||||
setValue("tags", []);
|
||||
onChange(e);
|
||||
}}
|
||||
className="w-full border border-mineshaft-500"
|
||||
dropdownContainerClassName="max-w-full"
|
||||
>
|
||||
<SelectItem
|
||||
value={IntegrationMetadataSyncMode.SECRET_METADATA}
|
||||
className="text-left"
|
||||
key={`sync-mode-${IntegrationMetadataSyncMode.SECRET_METADATA}`}
|
||||
>
|
||||
Secret Metadata
|
||||
</SelectItem>
|
||||
<SelectItem
|
||||
value={IntegrationMetadataSyncMode.CUSTOM}
|
||||
className="text-left"
|
||||
key={`sync-mode-${IntegrationMetadataSyncMode.CUSTOM}`}
|
||||
>
|
||||
Custom
|
||||
</SelectItem>
|
||||
</Select>
|
||||
<Input placeholder="managed-by" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{shouldTagState &&
|
||||
selectedMetadataSyncMode === IntegrationMetadataSyncMode.CUSTOM && (
|
||||
<div className="mt-4 flex justify-between">
|
||||
<Controller
|
||||
control={control}
|
||||
name="tags.0.key"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Tag Key"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Input placeholder="managed-by" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="tags.0.value"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Tag Value"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Input placeholder="infisical" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
name="tags.0.value"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Tag Value"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Input placeholder="infisical" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="secretPrefix"
|
||||
|
@ -76,6 +76,7 @@ export const AzureAppConfigurationConfigurePage = () => {
|
||||
}
|
||||
});
|
||||
|
||||
const selectedEnvironment = watch("sourceEnvironment");
|
||||
const { mutateAsync } = useCreateIntegration();
|
||||
|
||||
const integrationAuthId = useSearch({
|
||||
@ -248,7 +249,7 @@ export const AzureAppConfigurationConfigurePage = () => {
|
||||
name="secretPath"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Secrets Path" errorText={error?.message} isError={Boolean(error)}>
|
||||
<SecretPathInput {...field} />
|
||||
<SecretPathInput {...field} environment={selectedEnvironment} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
97
frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/AzureKeyVaultAuthorizePage.tsx
Normal file
97
frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/AzureKeyVaultAuthorizePage.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import z from "zod";
|
||||
|
||||
import { Button, Card, CardTitle, FormControl, Input } from "@app/components/v2";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { useSearch } from "@tanstack/react-router";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
|
||||
const schema = z.object({
|
||||
tenantId: z.string().trim().optional()
|
||||
});
|
||||
|
||||
type FormData = z.infer<typeof schema>;
|
||||
|
||||
export function AzureKeyVaultAuthorizePage() {
|
||||
const { state, clientId } = useSearch({
|
||||
from: ROUTE_PATHS.SecretManager.Integratons.AzureKeyVaultAuthorizePage.id,
|
||||
});
|
||||
|
||||
const { control, handleSubmit } = useForm<FormData>({
|
||||
resolver: zodResolver(schema)
|
||||
});
|
||||
|
||||
const onFormSubmit = async ({ tenantId }: FormData) => {
|
||||
const link = `https://login.microsoftonline.com/${
|
||||
tenantId ?? "common"
|
||||
}/oauth2/v2.0/authorize?client_id=${clientId}&response_type=code&redirect_uri=${
|
||||
window.location.origin
|
||||
}/integrations/azure-key-vault/oauth2/callback&response_mode=query&scope=https://vault.azure.net/.default openid offline_access&state=${state}`;
|
||||
|
||||
window.location.assign(link);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<Helmet>
|
||||
<title>Authorize Azure Key Vault Integration</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Helmet>
|
||||
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
|
||||
<CardTitle
|
||||
className="px-6 text-left text-xl"
|
||||
subTitle="Authenticate with a specific tenant ID or let OAuth handle it automatically."
|
||||
>
|
||||
<div className="flex flex-row items-center">
|
||||
<div className="flex items-center pb-0.5">
|
||||
<img src="/images/integrations/GitHub.png" height={30} width={30} alt="Github logo" />
|
||||
</div>
|
||||
<span className="ml-2.5">Azure Key Vault Integration </span>
|
||||
<a
|
||||
href="https://infisical.com/docs/integrations/cloud/azure-key-vault"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
|
||||
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||
Docs
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowUpRightFromSquare}
|
||||
className="ml-1.5 mb-[0.07rem] text-xxs"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</CardTitle>
|
||||
<form onSubmit={handleSubmit(onFormSubmit)} className="px-6 pb-8 text-right">
|
||||
<Controller
|
||||
control={control}
|
||||
name="tenantId"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Tenant ID (optional)"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Input {...field} placeholder="2e39537c-9a01-4bd6-a7b8-c3b88cbb8db9" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
className="mt-2 w-min"
|
||||
size="sm"
|
||||
type="submit"
|
||||
>
|
||||
Connect to Azure Key Vault
|
||||
</Button>
|
||||
</form>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import z from 'zod'
|
||||
|
||||
import { AzureKeyVaultAuthorizePage } from "./AzureKeyVaultAuthorizePage";
|
||||
|
||||
|
||||
const PageQueryParamsSchema = z.object({
|
||||
state: z.string(),
|
||||
clientId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize"
|
||||
)({
|
||||
component: AzureKeyVaultAuthorizePage,
|
||||
validateSearch: PageQueryParamsSchema
|
||||
});
|
@ -62,6 +62,7 @@ export const CircleCIConfigurePage = () => {
|
||||
|
||||
const selectedScope = watch("scope");
|
||||
const selectedOrg = watch("targetOrg");
|
||||
const selectedEnvironment = watch("sourceEnvironment");
|
||||
|
||||
const { data: circleCIOrganizations, isPending: isCircleCIOrganizationsLoading } =
|
||||
useGetIntegrationAuthCircleCIOrganizations(integrationAuthId);
|
||||
@ -186,7 +187,7 @@ export const CircleCIConfigurePage = () => {
|
||||
name="secretPath"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Secrets Path" errorText={error?.message} isError={Boolean(error)}>
|
||||
<SecretPathInput {...field} />
|
||||
<SecretPathInput {...field} environment={selectedEnvironment.slug}/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
@ -159,6 +159,7 @@ import { Route as secretManagerIntegrationsChecklyConfigurePageRouteImport } fro
|
||||
import { Route as secretManagerIntegrationsChecklyAuthorizePageRouteImport } from './pages/secret-manager/integrations/ChecklyAuthorizePage/route'
|
||||
import { Route as secretManagerIntegrationsBitbucketConfigurePageRouteImport } from './pages/secret-manager/integrations/BitbucketConfigurePage/route'
|
||||
import { Route as secretManagerIntegrationsAzureKeyVaultConfigurePageRouteImport } from './pages/secret-manager/integrations/AzureKeyVaultConfigurePage/route'
|
||||
import { Route as secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteImport } from './pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/route'
|
||||
import { Route as secretManagerIntegrationsAzureDevopsConfigurePageRouteImport } from './pages/secret-manager/integrations/AzureDevopsConfigurePage/route'
|
||||
import { Route as secretManagerIntegrationsAzureDevopsAuthorizePageRouteImport } from './pages/secret-manager/integrations/AzureDevopsAuthorizePage/route'
|
||||
import { Route as secretManagerIntegrationsAzureAppConfigurationConfigurePageRouteImport } from './pages/secret-manager/integrations/AzureAppConfigurationConfigurePage/route'
|
||||
@ -1352,6 +1353,14 @@ const secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute =
|
||||
AuthenticateInjectOrgDetailsSecretManagerProjectIdSecretManagerLayoutIntegrationsRoute,
|
||||
} as any)
|
||||
|
||||
const secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute =
|
||||
secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteImport.update({
|
||||
id: '/azure-key-vault/authorize',
|
||||
path: '/azure-key-vault/authorize',
|
||||
getParentRoute: () =>
|
||||
AuthenticateInjectOrgDetailsSecretManagerProjectIdSecretManagerLayoutIntegrationsRoute,
|
||||
} as any)
|
||||
|
||||
const secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute =
|
||||
secretManagerIntegrationsAzureDevopsConfigurePageRouteImport.update({
|
||||
id: '/azure-devops/create',
|
||||
@ -2251,6 +2260,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof secretManagerIntegrationsAzureDevopsConfigurePageRouteImport
|
||||
parentRoute: typeof AuthenticateInjectOrgDetailsSecretManagerProjectIdSecretManagerLayoutIntegrationsImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize': {
|
||||
id: '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize'
|
||||
path: '/azure-key-vault/authorize'
|
||||
fullPath: '/secret-manager/$projectId/integrations/azure-key-vault/authorize'
|
||||
preLoaderRoute: typeof secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteImport
|
||||
parentRoute: typeof AuthenticateInjectOrgDetailsSecretManagerProjectIdSecretManagerLayoutIntegrationsImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/create': {
|
||||
id: '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/create'
|
||||
path: '/azure-key-vault/create'
|
||||
@ -2944,6 +2960,7 @@ interface AuthenticateInjectOrgDetailsSecretManagerProjectIdSecretManagerLayoutI
|
||||
secretManagerIntegrationsAzureAppConfigurationConfigurePageRouteRoute: typeof secretManagerIntegrationsAzureAppConfigurationConfigurePageRouteRoute
|
||||
secretManagerIntegrationsAzureDevopsAuthorizePageRouteRoute: typeof secretManagerIntegrationsAzureDevopsAuthorizePageRouteRoute
|
||||
secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute: typeof secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute
|
||||
secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute: typeof secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute
|
||||
secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute: typeof secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute
|
||||
secretManagerIntegrationsBitbucketConfigurePageRouteRoute: typeof secretManagerIntegrationsBitbucketConfigurePageRouteRoute
|
||||
secretManagerIntegrationsChecklyAuthorizePageRouteRoute: typeof secretManagerIntegrationsChecklyAuthorizePageRouteRoute
|
||||
@ -3034,6 +3051,8 @@ const AuthenticateInjectOrgDetailsSecretManagerProjectIdSecretManagerLayoutInteg
|
||||
secretManagerIntegrationsAzureDevopsAuthorizePageRouteRoute,
|
||||
secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute:
|
||||
secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute,
|
||||
secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute:
|
||||
secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute,
|
||||
secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute:
|
||||
secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute,
|
||||
secretManagerIntegrationsBitbucketConfigurePageRouteRoute:
|
||||
@ -3513,6 +3532,7 @@ export interface FileRoutesByFullPath {
|
||||
'/secret-manager/$projectId/integrations/azure-app-configuration/create': typeof secretManagerIntegrationsAzureAppConfigurationConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-devops/authorize': typeof secretManagerIntegrationsAzureDevopsAuthorizePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-devops/create': typeof secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-key-vault/authorize': typeof secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-key-vault/create': typeof secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/bitbucket/create': typeof secretManagerIntegrationsBitbucketConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/checkly/authorize': typeof secretManagerIntegrationsChecklyAuthorizePageRouteRoute
|
||||
@ -3676,6 +3696,7 @@ export interface FileRoutesByTo {
|
||||
'/secret-manager/$projectId/integrations/azure-app-configuration/create': typeof secretManagerIntegrationsAzureAppConfigurationConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-devops/authorize': typeof secretManagerIntegrationsAzureDevopsAuthorizePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-devops/create': typeof secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-key-vault/authorize': typeof secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/azure-key-vault/create': typeof secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/bitbucket/create': typeof secretManagerIntegrationsBitbucketConfigurePageRouteRoute
|
||||
'/secret-manager/$projectId/integrations/checkly/authorize': typeof secretManagerIntegrationsChecklyAuthorizePageRouteRoute
|
||||
@ -3854,6 +3875,7 @@ export interface FileRoutesById {
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-app-configuration/create': typeof secretManagerIntegrationsAzureAppConfigurationConfigurePageRouteRoute
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/authorize': typeof secretManagerIntegrationsAzureDevopsAuthorizePageRouteRoute
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/create': typeof secretManagerIntegrationsAzureDevopsConfigurePageRouteRoute
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize': typeof secretManagerIntegrationsAzureKeyVaultAuthorizePageRouteRoute
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/create': typeof secretManagerIntegrationsAzureKeyVaultConfigurePageRouteRoute
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/bitbucket/create': typeof secretManagerIntegrationsBitbucketConfigurePageRouteRoute
|
||||
'/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/checkly/authorize': typeof secretManagerIntegrationsChecklyAuthorizePageRouteRoute
|
||||
@ -4024,6 +4046,7 @@ export interface FileRouteTypes {
|
||||
| '/secret-manager/$projectId/integrations/azure-app-configuration/create'
|
||||
| '/secret-manager/$projectId/integrations/azure-devops/authorize'
|
||||
| '/secret-manager/$projectId/integrations/azure-devops/create'
|
||||
| '/secret-manager/$projectId/integrations/azure-key-vault/authorize'
|
||||
| '/secret-manager/$projectId/integrations/azure-key-vault/create'
|
||||
| '/secret-manager/$projectId/integrations/bitbucket/create'
|
||||
| '/secret-manager/$projectId/integrations/checkly/authorize'
|
||||
@ -4186,6 +4209,7 @@ export interface FileRouteTypes {
|
||||
| '/secret-manager/$projectId/integrations/azure-app-configuration/create'
|
||||
| '/secret-manager/$projectId/integrations/azure-devops/authorize'
|
||||
| '/secret-manager/$projectId/integrations/azure-devops/create'
|
||||
| '/secret-manager/$projectId/integrations/azure-key-vault/authorize'
|
||||
| '/secret-manager/$projectId/integrations/azure-key-vault/create'
|
||||
| '/secret-manager/$projectId/integrations/bitbucket/create'
|
||||
| '/secret-manager/$projectId/integrations/checkly/authorize'
|
||||
@ -4362,6 +4386,7 @@ export interface FileRouteTypes {
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-app-configuration/create'
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/authorize'
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/create'
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize'
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/create'
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/bitbucket/create'
|
||||
| '/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/checkly/authorize'
|
||||
@ -4925,6 +4950,7 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-app-configuration/create",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/authorize",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-devops/create",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/create",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/bitbucket/create",
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/checkly/authorize",
|
||||
@ -5105,6 +5131,10 @@ export const routeTree = rootRoute
|
||||
"filePath": "secret-manager/integrations/AzureDevopsConfigurePage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize": {
|
||||
"filePath": "secret-manager/integrations/AzureKeyVaultAuthorizePage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations/azure-key-vault/create": {
|
||||
"filePath": "secret-manager/integrations/AzureKeyVaultConfigurePage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/integrations"
|
||||
|
@ -75,6 +75,10 @@ const secretManagerRoutes = route("/secret-manager/$projectId", [
|
||||
"/azure-devops/create",
|
||||
"secret-manager/integrations/AzureDevopsConfigurePage/route.tsx"
|
||||
),
|
||||
route(
|
||||
"/azure-key-vault/authorize",
|
||||
"secret-manager/integrations/AzureKeyVaultAuthorizePage/route.tsx"
|
||||
),
|
||||
route(
|
||||
"/azure-key-vault/oauth2/callback",
|
||||
"secret-manager/integrations/AzureKeyVaultOauthCallbackPage/route.tsx"
|
||||
|
Reference in New Issue
Block a user