This commit is contained in:
x032205
2025-05-26 12:56:15 -04:00
110 changed files with 2204 additions and 489 deletions
@@ -0,0 +1,3 @@
export enum OnePassConnectionMethod {
ApiToken = "api-token"
}
@@ -0,0 +1,66 @@
import { AxiosError } from "axios";
import { request } from "@app/lib/config/request";
import { BadRequestError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn";
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { OnePassConnectionMethod } from "./1password-connection-enums";
import { TOnePassConnection, TOnePassConnectionConfig, TOnePassVault } from "./1password-connection-types";
export const getOnePassInstanceUrl = async (config: TOnePassConnectionConfig) => {
const instanceUrl = removeTrailingSlash(config.credentials.instanceUrl);
await blockLocalAndPrivateIpAddresses(instanceUrl);
return instanceUrl;
};
export const getOnePassConnectionListItem = () => {
return {
name: "1Password" as const,
app: AppConnection.OnePass as const,
methods: Object.values(OnePassConnectionMethod) as [OnePassConnectionMethod.ApiToken]
};
};
export const validateOnePassConnectionCredentials = async (config: TOnePassConnectionConfig) => {
const instanceUrl = await getOnePassInstanceUrl(config);
const { apiToken } = config.credentials;
try {
await request.get(`${instanceUrl}/v1/vaults`, {
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
});
} catch (error: unknown) {
if (error instanceof AxiosError) {
throw new BadRequestError({
message: `Failed to validate credentials: ${error.message || "Unknown error"}`
});
}
throw new BadRequestError({
message: "Unable to validate connection: verify credentials"
});
}
return config.credentials;
};
export const listOnePassVaults = async (appConnection: TOnePassConnection) => {
const instanceUrl = await getOnePassInstanceUrl(appConnection);
const { apiToken } = appConnection.credentials;
const resp = await request.get<TOnePassVault[]>(`${instanceUrl}/v1/vaults`, {
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
});
return resp.data;
};
@@ -0,0 +1,64 @@
import z from "zod";
import { AppConnections } from "@app/lib/api-docs";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import {
BaseAppConnectionSchema,
GenericCreateAppConnectionFieldsSchema,
GenericUpdateAppConnectionFieldsSchema
} from "@app/services/app-connection/app-connection-schemas";
import { OnePassConnectionMethod } from "./1password-connection-enums";
export const OnePassConnectionAccessTokenCredentialsSchema = z.object({
apiToken: z.string().trim().min(1, "API Token required").describe(AppConnections.CREDENTIALS.ONEPASS.apiToken),
instanceUrl: z
.string()
.trim()
.url("Invalid Connect Server instance URL")
.min(1, "Instance URL required")
.describe(AppConnections.CREDENTIALS.ONEPASS.instanceUrl)
});
const BaseOnePassConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.OnePass) });
export const OnePassConnectionSchema = BaseOnePassConnectionSchema.extend({
method: z.literal(OnePassConnectionMethod.ApiToken),
credentials: OnePassConnectionAccessTokenCredentialsSchema
});
export const SanitizedOnePassConnectionSchema = z.discriminatedUnion("method", [
BaseOnePassConnectionSchema.extend({
method: z.literal(OnePassConnectionMethod.ApiToken),
credentials: OnePassConnectionAccessTokenCredentialsSchema.pick({
instanceUrl: true
})
})
]);
export const ValidateOnePassConnectionCredentialsSchema = z.discriminatedUnion("method", [
z.object({
method: z.literal(OnePassConnectionMethod.ApiToken).describe(AppConnections.CREATE(AppConnection.OnePass).method),
credentials: OnePassConnectionAccessTokenCredentialsSchema.describe(
AppConnections.CREATE(AppConnection.OnePass).credentials
)
})
]);
export const CreateOnePassConnectionSchema = ValidateOnePassConnectionCredentialsSchema.and(
GenericCreateAppConnectionFieldsSchema(AppConnection.OnePass)
);
export const UpdateOnePassConnectionSchema = z
.object({
credentials: OnePassConnectionAccessTokenCredentialsSchema.optional().describe(
AppConnections.UPDATE(AppConnection.OnePass).credentials
)
})
.and(GenericUpdateAppConnectionFieldsSchema(AppConnection.OnePass));
export const OnePassConnectionListItemSchema = z.object({
name: z.literal("1Password"),
app: z.literal(AppConnection.OnePass),
methods: z.nativeEnum(OnePassConnectionMethod).array()
});
@@ -0,0 +1,30 @@
import { logger } from "@app/lib/logger";
import { OrgServiceActor } from "@app/lib/types";
import { AppConnection } from "../app-connection-enums";
import { listOnePassVaults } from "./1password-connection-fns";
import { TOnePassConnection } from "./1password-connection-types";
type TGetAppConnectionFunc = (
app: AppConnection,
connectionId: string,
actor: OrgServiceActor
) => Promise<TOnePassConnection>;
export const onePassConnectionService = (getAppConnection: TGetAppConnectionFunc) => {
const listVaults = async (connectionId: string, actor: OrgServiceActor) => {
const appConnection = await getAppConnection(AppConnection.OnePass, connectionId, actor);
try {
const vaults = await listOnePassVaults(appConnection);
return vaults;
} catch (error) {
logger.error(error, "Failed to establish connection with 1Password");
return [];
}
};
return {
listVaults
};
};
@@ -0,0 +1,35 @@
import z from "zod";
import { DiscriminativePick } from "@app/lib/types";
import { AppConnection } from "../app-connection-enums";
import {
CreateOnePassConnectionSchema,
OnePassConnectionSchema,
ValidateOnePassConnectionCredentialsSchema
} from "./1password-connection-schemas";
export type TOnePassConnection = z.infer<typeof OnePassConnectionSchema>;
export type TOnePassConnectionInput = z.infer<typeof CreateOnePassConnectionSchema> & {
app: AppConnection.OnePass;
};
export type TValidateOnePassConnectionCredentialsSchema = typeof ValidateOnePassConnectionCredentialsSchema;
export type TOnePassConnectionConfig = DiscriminativePick<TOnePassConnectionInput, "method" | "app" | "credentials"> & {
orgId: string;
};
export type TOnePassVault = {
id: string;
name: string;
type: string;
items: number;
attributeVersion: number;
contentVersion: number;
createdAt: string;
updatedAt: string;
};
@@ -0,0 +1,4 @@
export * from "./1password-connection-enums";
export * from "./1password-connection-fns";
export * from "./1password-connection-schemas";
export * from "./1password-connection-types";
@@ -18,7 +18,8 @@ export enum AppConnection {
HCVault = "hashicorp-vault",
LDAP = "ldap",
TeamCity = "teamcity",
OCI = "oci"
OCI = "oci",
OnePass = "1password"
}
export enum AWSRegion {
@@ -14,6 +14,11 @@ import {
} from "@app/services/app-connection/shared/sql";
import { KmsDataKey } from "@app/services/kms/kms-types";
import {
getOnePassConnectionListItem,
OnePassConnectionMethod,
validateOnePassConnectionCredentials
} from "./1password";
import { AppConnection, AppConnectionPlanType } from "./app-connection-enums";
import { TAppConnectionServiceFactoryDep } from "./app-connection-service";
import {
@@ -101,7 +106,8 @@ export const listAppConnectionOptions = () => {
getHCVaultConnectionListItem(),
getLdapConnectionListItem(),
getTeamCityConnectionListItem(),
getOCIConnectionListItem()
getOCIConnectionListItem(),
getOnePassConnectionListItem()
].sort((a, b) => a.name.localeCompare(b.name));
};
@@ -172,7 +178,8 @@ export const validateAppConnectionCredentials = async (
[AppConnection.HCVault]: validateHCVaultConnectionCredentials as TAppConnectionCredentialsValidator,
[AppConnection.LDAP]: validateLdapConnectionCredentials as TAppConnectionCredentialsValidator,
[AppConnection.TeamCity]: validateTeamCityConnectionCredentials as TAppConnectionCredentialsValidator,
[AppConnection.OCI]: validateOCIConnectionCredentials as TAppConnectionCredentialsValidator
[AppConnection.OCI]: validateOCIConnectionCredentials as TAppConnectionCredentialsValidator,
[AppConnection.OnePass]: validateOnePassConnectionCredentials as TAppConnectionCredentialsValidator
};
return VALIDATE_APP_CONNECTION_CREDENTIALS_MAP[appConnection.app](appConnection);
@@ -201,6 +208,7 @@ export const getAppConnectionMethodName = (method: TAppConnection["method"]) =>
case HumanitecConnectionMethod.ApiToken:
case TerraformCloudConnectionMethod.ApiToken:
case VercelConnectionMethod.ApiToken:
case OnePassConnectionMethod.ApiToken:
return "API Token";
case PostgresConnectionMethod.UsernameAndPassword:
case MsSqlConnectionMethod.UsernameAndPassword:
@@ -266,7 +274,8 @@ export const TRANSITION_CONNECTION_CREDENTIALS_TO_PLATFORM: Record<
[AppConnection.HCVault]: platformManagedCredentialsNotSupported,
[AppConnection.LDAP]: platformManagedCredentialsNotSupported, // we could support this in the future
[AppConnection.TeamCity]: platformManagedCredentialsNotSupported,
[AppConnection.OCI]: platformManagedCredentialsNotSupported
[AppConnection.OCI]: platformManagedCredentialsNotSupported,
[AppConnection.OnePass]: platformManagedCredentialsNotSupported
};
export const enterpriseAppCheck = async (
@@ -20,7 +20,8 @@ export const APP_CONNECTION_NAME_MAP: Record<AppConnection, string> = {
[AppConnection.HCVault]: "Hashicorp Vault",
[AppConnection.LDAP]: "LDAP",
[AppConnection.TeamCity]: "TeamCity",
[AppConnection.OCI]: "OCI"
[AppConnection.OCI]: "OCI",
[AppConnection.OnePass]: "1Password"
};
export const APP_CONNECTION_PLAN_MAP: Record<AppConnection, AppConnectionPlanType> = {
@@ -43,5 +44,6 @@ export const APP_CONNECTION_PLAN_MAP: Record<AppConnection, AppConnectionPlanTyp
[AppConnection.LDAP]: AppConnectionPlanType.Regular,
[AppConnection.TeamCity]: AppConnectionPlanType.Regular,
[AppConnection.OCI]: AppConnectionPlanType.Enterprise,
[AppConnection.OnePass]: AppConnectionPlanType.Regular,
[AppConnection.MySql]: AppConnectionPlanType.Regular
};
@@ -21,6 +21,8 @@ import {
import { auth0ConnectionService } from "@app/services/app-connection/auth0/auth0-connection-service";
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { ValidateOnePassConnectionCredentialsSchema } from "./1password";
import { onePassConnectionService } from "./1password/1password-connection-service";
import { TAppConnectionDALFactory } from "./app-connection-dal";
import { AppConnection } from "./app-connection-enums";
import { APP_CONNECTION_NAME_MAP } from "./app-connection-maps";
@@ -93,7 +95,8 @@ const VALIDATE_APP_CONNECTION_CREDENTIALS_MAP: Record<AppConnection, TValidateAp
[AppConnection.HCVault]: ValidateHCVaultConnectionCredentialsSchema,
[AppConnection.LDAP]: ValidateLdapConnectionCredentialsSchema,
[AppConnection.TeamCity]: ValidateTeamCityConnectionCredentialsSchema,
[AppConnection.OCI]: ValidateOCIConnectionCredentialsSchema
[AppConnection.OCI]: ValidateOCIConnectionCredentialsSchema,
[AppConnection.OnePass]: ValidateOnePassConnectionCredentialsSchema
};
export const appConnectionServiceFactory = ({
@@ -495,6 +498,7 @@ export const appConnectionServiceFactory = ({
hcvault: hcVaultConnectionService(connectAppConnectionById),
windmill: windmillConnectionService(connectAppConnectionById),
teamcity: teamcityConnectionService(connectAppConnectionById),
oci: ociConnectionService(connectAppConnectionById, licenseService)
oci: ociConnectionService(connectAppConnectionById, licenseService),
onepass: onePassConnectionService(connectAppConnectionById)
};
};
@@ -1,13 +1,19 @@
import { TAppConnectionDALFactory } from "@app/services/app-connection/app-connection-dal";
import { TSqlConnectionConfig } from "@app/services/app-connection/shared/sql/sql-connection-types";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import {
TOCIConnection,
TOCIConnectionConfig,
TOCIConnectionInput,
TValidateOCIConnectionCredentialsSchema
} from "../../ee/services/app-connections/oci";
} from "@app/ee/services/app-connections/oci";
import { TAppConnectionDALFactory } from "@app/services/app-connection/app-connection-dal";
import { TSqlConnectionConfig } from "@app/services/app-connection/shared/sql/sql-connection-types";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import {
TOnePassConnection,
TOnePassConnectionConfig,
TOnePassConnectionInput,
TValidateOnePassConnectionCredentialsSchema
} from "./1password";
import { AWSRegion } from "./app-connection-enums";
import {
TAuth0Connection,
@@ -134,6 +140,7 @@ export type TAppConnection = { id: string } & (
| TLdapConnection
| TTeamCityConnection
| TOCIConnection
| TOnePassConnection
);
export type TAppConnectionRaw = NonNullable<Awaited<ReturnType<TAppConnectionDALFactory["findById"]>>>;
@@ -161,6 +168,7 @@ export type TAppConnectionInput = { id: string } & (
| TLdapConnectionInput
| TTeamCityConnectionInput
| TOCIConnectionInput
| TOnePassConnectionInput
);
export type TSqlConnectionInput = TPostgresConnectionInput | TMsSqlConnectionInput | TMySqlConnectionInput;
@@ -192,7 +200,8 @@ export type TAppConnectionConfig =
| THCVaultConnectionConfig
| TLdapConnectionConfig
| TTeamCityConnectionConfig
| TOCIConnectionConfig;
| TOCIConnectionConfig
| TOnePassConnectionConfig;
export type TValidateAppConnectionCredentialsSchema =
| TValidateAwsConnectionCredentialsSchema
@@ -214,7 +223,8 @@ export type TValidateAppConnectionCredentialsSchema =
| TValidateHCVaultConnectionCredentialsSchema
| TValidateLdapConnectionCredentialsSchema
| TValidateTeamCityConnectionCredentialsSchema
| TValidateOCIConnectionCredentialsSchema;
| TValidateOCIConnectionCredentialsSchema
| TValidateOnePassConnectionCredentialsSchema;
export type TListAwsConnectionKmsKeys = {
connectionId: string;
@@ -0,0 +1,10 @@
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import { TSecretSyncListItem } from "@app/services/secret-sync/secret-sync-types";
export const ONEPASS_SYNC_LIST_OPTION: TSecretSyncListItem = {
name: "1Password",
destination: SecretSync.OnePass,
connection: AppConnection.OnePass,
canImportSecrets: true
};
@@ -0,0 +1,226 @@
import { request } from "@app/lib/config/request";
import { getOnePassInstanceUrl } from "@app/services/app-connection/1password";
import {
TDeleteOnePassVariable,
TOnePassListVariables,
TOnePassListVariablesResponse,
TOnePassSyncWithCredentials,
TOnePassVariable,
TOnePassVariableDetails,
TPostOnePassVariable,
TPutOnePassVariable
} from "@app/services/secret-sync/1password/1password-sync-types";
import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns";
import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
const listOnePassItems = async ({ instanceUrl, apiToken, vaultId }: TOnePassListVariables) => {
const { data } = await request.get<TOnePassListVariablesResponse>(`${instanceUrl}/v1/vaults/${vaultId}/items`, {
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
});
const result: Record<string, TOnePassVariable & { value: string; fieldId: string }> = {};
for await (const s of data) {
const { data: secret } = await request.get<TOnePassVariableDetails>(
`${instanceUrl}/v1/vaults/${vaultId}/items/${s.id}`,
{
headers: {
Authorization: `Bearer ${apiToken}`,
Accept: "application/json"
}
}
);
const value = secret.fields.find((f) => f.label === "value")?.value;
const fieldId = secret.fields.find((f) => f.label === "value")?.id;
// eslint-disable-next-line no-continue
if (!value || !fieldId) continue;
result[s.title] = {
...secret,
value,
fieldId
};
}
return result;
};
const createOnePassItem = async ({ instanceUrl, apiToken, vaultId, itemTitle, itemValue }: TPostOnePassVariable) => {
return request.post(
`${instanceUrl}/v1/vaults/${vaultId}/items`,
{
title: itemTitle,
category: "API_CREDENTIAL",
vault: {
id: vaultId
},
tags: ["synced-from-infisical"],
fields: [
{
label: "value",
value: itemValue,
type: "CONCEALED"
}
]
},
{
headers: {
Authorization: `Bearer ${apiToken}`,
"Content-Type": "application/json"
}
}
);
};
const updateOnePassItem = async ({
instanceUrl,
apiToken,
vaultId,
itemId,
fieldId,
itemTitle,
itemValue
}: TPutOnePassVariable) => {
return request.put(
`${instanceUrl}/v1/vaults/${vaultId}/items/${itemId}`,
{
id: itemId,
title: itemTitle,
category: "API_CREDENTIAL",
vault: {
id: vaultId
},
tags: ["synced-from-infisical"],
fields: [
{
id: fieldId,
label: "value",
value: itemValue,
type: "CONCEALED"
}
]
},
{
headers: {
Authorization: `Bearer ${apiToken}`,
"Content-Type": "application/json"
}
}
);
};
const deleteOnePassItem = async ({ instanceUrl, apiToken, vaultId, itemId }: TDeleteOnePassVariable) => {
return request.delete(`${instanceUrl}/v1/vaults/${vaultId}/items/${itemId}`, {
headers: {
Authorization: `Bearer ${apiToken}`
}
});
};
export const OnePassSyncFns = {
syncSecrets: async (secretSync: TOnePassSyncWithCredentials, secretMap: TSecretMap) => {
const {
connection,
destinationConfig: { vaultId }
} = secretSync;
const instanceUrl = await getOnePassInstanceUrl(connection);
const { apiToken } = connection.credentials;
const items = await listOnePassItems({ instanceUrl, apiToken, vaultId });
for await (const entry of Object.entries(secretMap)) {
const [key, { value }] = entry;
try {
if (key in items) {
await updateOnePassItem({
instanceUrl,
apiToken,
vaultId,
itemTitle: key,
itemValue: value,
itemId: items[key].id,
fieldId: items[key].fieldId
});
} else {
await createOnePassItem({ instanceUrl, apiToken, vaultId, itemTitle: key, itemValue: value });
}
} catch (error) {
throw new SecretSyncError({
error,
secretKey: key
});
}
}
if (secretSync.syncOptions.disableSecretDeletion) return;
for await (const [key, variable] of Object.entries(items)) {
// eslint-disable-next-line no-continue
if (!matchesSchema(key, secretSync.syncOptions.keySchema)) continue;
if (!(key in secretMap)) {
try {
await deleteOnePassItem({
instanceUrl,
apiToken,
vaultId,
itemId: variable.id
});
} catch (error) {
throw new SecretSyncError({
error,
secretKey: key
});
}
}
}
},
removeSecrets: async (secretSync: TOnePassSyncWithCredentials, secretMap: TSecretMap) => {
const {
connection,
destinationConfig: { vaultId }
} = secretSync;
const instanceUrl = await getOnePassInstanceUrl(connection);
const { apiToken } = connection.credentials;
const items = await listOnePassItems({ instanceUrl, apiToken, vaultId });
for await (const [key, item] of Object.entries(items)) {
if (key in secretMap) {
try {
await deleteOnePassItem({
apiToken,
vaultId,
instanceUrl,
itemId: item.id
});
} catch (error) {
throw new SecretSyncError({
error,
secretKey: key
});
}
}
}
},
getSecrets: async (secretSync: TOnePassSyncWithCredentials) => {
const {
connection,
destinationConfig: { vaultId }
} = secretSync;
const instanceUrl = await getOnePassInstanceUrl(connection);
const { apiToken } = connection.credentials;
return listOnePassItems({ instanceUrl, apiToken, vaultId });
}
};
@@ -0,0 +1,43 @@
import { z } from "zod";
import { SecretSyncs } from "@app/lib/api-docs";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import {
BaseSecretSyncSchema,
GenericCreateSecretSyncFieldsSchema,
GenericUpdateSecretSyncFieldsSchema
} from "@app/services/secret-sync/secret-sync-schemas";
import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types";
const OnePassSyncDestinationConfigSchema = z.object({
vaultId: z.string().trim().min(1, "Vault required").describe(SecretSyncs.DESTINATION_CONFIG.ONEPASS.vaultId)
});
const OnePassSyncOptionsConfig: TSyncOptionsConfig = { canImportSecrets: true };
export const OnePassSyncSchema = BaseSecretSyncSchema(SecretSync.OnePass, OnePassSyncOptionsConfig).extend({
destination: z.literal(SecretSync.OnePass),
destinationConfig: OnePassSyncDestinationConfigSchema
});
export const CreateOnePassSyncSchema = GenericCreateSecretSyncFieldsSchema(
SecretSync.OnePass,
OnePassSyncOptionsConfig
).extend({
destinationConfig: OnePassSyncDestinationConfigSchema
});
export const UpdateOnePassSyncSchema = GenericUpdateSecretSyncFieldsSchema(
SecretSync.OnePass,
OnePassSyncOptionsConfig
).extend({
destinationConfig: OnePassSyncDestinationConfigSchema.optional()
});
export const OnePassSyncListItemSchema = z.object({
name: z.literal("1Password"),
connection: z.literal(AppConnection.OnePass),
destination: z.literal(SecretSync.OnePass),
canImportSecrets: z.literal(true)
});
@@ -0,0 +1,54 @@
import { z } from "zod";
import { TOnePassConnection } from "@app/services/app-connection/1password";
import { CreateOnePassSyncSchema, OnePassSyncListItemSchema, OnePassSyncSchema } from "./1password-sync-schemas";
export type TOnePassSync = z.infer<typeof OnePassSyncSchema>;
export type TOnePassSyncInput = z.infer<typeof CreateOnePassSyncSchema>;
export type TOnePassSyncListItem = z.infer<typeof OnePassSyncListItemSchema>;
export type TOnePassSyncWithCredentials = TOnePassSync & {
connection: TOnePassConnection;
};
export type TOnePassVariable = {
id: string;
title: string;
category: string; // API_CREDENTIAL, SECURE_NOTE, LOGIN, etc
};
export type TOnePassVariableDetails = TOnePassVariable & {
fields: {
id: string;
type: string; // CONCEALED, STRING
label: string;
value: string;
}[];
};
export type TOnePassListVariablesResponse = TOnePassVariable[];
export type TOnePassListVariables = {
apiToken: string;
instanceUrl: string;
vaultId: string;
};
export type TPostOnePassVariable = TOnePassListVariables & {
itemTitle: string;
itemValue: string;
};
export type TPutOnePassVariable = TOnePassListVariables & {
itemId: string;
fieldId: string;
itemTitle: string;
itemValue: string;
};
export type TDeleteOnePassVariable = TOnePassListVariables & {
itemId: string;
};
@@ -0,0 +1,4 @@
export * from "./1password-sync-constants";
export * from "./1password-sync-fns";
export * from "./1password-sync-schemas";
export * from "./1password-sync-types";
@@ -13,7 +13,8 @@ export enum SecretSync {
Windmill = "windmill",
HCVault = "hashicorp-vault",
TeamCity = "teamcity",
OCIVault = "oci-vault"
OCIVault = "oci-vault",
OnePass = "1password"
}
export enum SecretSyncInitialSyncBehavior {
@@ -24,6 +24,7 @@ import {
import { TAppConnectionDALFactory } from "../app-connection/app-connection-dal";
import { TKmsServiceFactory } from "../kms/kms-service";
import { ONEPASS_SYNC_LIST_OPTION, OnePassSyncFns } from "./1password";
import { AZURE_APP_CONFIGURATION_SYNC_LIST_OPTION, azureAppConfigurationSyncFactory } from "./azure-app-configuration";
import { AZURE_KEY_VAULT_SYNC_LIST_OPTION, azureKeyVaultSyncFactory } from "./azure-key-vault";
import { CAMUNDA_SYNC_LIST_OPTION, camundaSyncFactory } from "./camunda";
@@ -53,7 +54,8 @@ const SECRET_SYNC_LIST_OPTIONS: Record<SecretSync, TSecretSyncListItem> = {
[SecretSync.Windmill]: WINDMILL_SYNC_LIST_OPTION,
[SecretSync.HCVault]: HC_VAULT_SYNC_LIST_OPTION,
[SecretSync.TeamCity]: TEAMCITY_SYNC_LIST_OPTION,
[SecretSync.OCIVault]: OCI_VAULT_SYNC_LIST_OPTION
[SecretSync.OCIVault]: OCI_VAULT_SYNC_LIST_OPTION,
[SecretSync.OnePass]: ONEPASS_SYNC_LIST_OPTION
};
export const listSecretSyncOptions = () => {
@@ -174,6 +176,8 @@ export const SecretSyncFns = {
return TeamCitySyncFns.syncSecrets(secretSync, schemaSecretMap);
case SecretSync.OCIVault:
return OCIVaultSyncFns.syncSecrets(secretSync, schemaSecretMap);
case SecretSync.OnePass:
return OnePassSyncFns.syncSecrets(secretSync, schemaSecretMap);
default:
throw new Error(
`Unhandled sync destination for sync secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
@@ -242,6 +246,9 @@ export const SecretSyncFns = {
case SecretSync.OCIVault:
secretMap = await OCIVaultSyncFns.getSecrets(secretSync);
break;
case SecretSync.OnePass:
secretMap = await OnePassSyncFns.getSecrets(secretSync);
break;
default:
throw new Error(
`Unhandled sync destination for get secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
@@ -300,6 +307,8 @@ export const SecretSyncFns = {
return TeamCitySyncFns.removeSecrets(secretSync, schemaSecretMap);
case SecretSync.OCIVault:
return OCIVaultSyncFns.removeSecrets(secretSync, schemaSecretMap);
case SecretSync.OnePass:
return OnePassSyncFns.removeSecrets(secretSync, schemaSecretMap);
default:
throw new Error(
`Unhandled sync destination for remove secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
@@ -16,7 +16,8 @@ export const SECRET_SYNC_NAME_MAP: Record<SecretSync, string> = {
[SecretSync.Windmill]: "Windmill",
[SecretSync.HCVault]: "Hashicorp Vault",
[SecretSync.TeamCity]: "TeamCity",
[SecretSync.OCIVault]: "OCI Vault"
[SecretSync.OCIVault]: "OCI Vault",
[SecretSync.OnePass]: "1Password"
};
export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
@@ -34,7 +35,8 @@ export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
[SecretSync.Windmill]: AppConnection.Windmill,
[SecretSync.HCVault]: AppConnection.HCVault,
[SecretSync.TeamCity]: AppConnection.TeamCity,
[SecretSync.OCIVault]: AppConnection.OCI
[SecretSync.OCIVault]: AppConnection.OCI,
[SecretSync.OnePass]: AppConnection.OnePass
};
export const SECRET_SYNC_PLAN_MAP: Record<SecretSync, SecretSyncPlanType> = {
@@ -52,5 +54,6 @@ export const SECRET_SYNC_PLAN_MAP: Record<SecretSync, SecretSyncPlanType> = {
[SecretSync.Windmill]: SecretSyncPlanType.Regular,
[SecretSync.HCVault]: SecretSyncPlanType.Regular,
[SecretSync.TeamCity]: SecretSyncPlanType.Regular,
[SecretSync.OCIVault]: SecretSyncPlanType.Enterprise
[SecretSync.OCIVault]: SecretSyncPlanType.Enterprise,
[SecretSync.OnePass]: SecretSyncPlanType.Regular
};
@@ -42,6 +42,12 @@ import {
TWindmillSyncWithCredentials
} from "@app/services/secret-sync/windmill";
import {
TOnePassSync,
TOnePassSyncInput,
TOnePassSyncListItem,
TOnePassSyncWithCredentials
} from "./1password/1password-sync-types";
import {
TAwsParameterStoreSync,
TAwsParameterStoreSyncInput,
@@ -102,7 +108,8 @@ export type TSecretSync =
| TWindmillSync
| THCVaultSync
| TTeamCitySync
| TOCIVaultSync;
| TOCIVaultSync
| TOnePassSync;
export type TSecretSyncWithCredentials =
| TAwsParameterStoreSyncWithCredentials
@@ -119,7 +126,8 @@ export type TSecretSyncWithCredentials =
| TWindmillSyncWithCredentials
| THCVaultSyncWithCredentials
| TTeamCitySyncWithCredentials
| TOCIVaultSyncWithCredentials;
| TOCIVaultSyncWithCredentials
| TOnePassSyncWithCredentials;
export type TSecretSyncInput =
| TAwsParameterStoreSyncInput
@@ -136,7 +144,8 @@ export type TSecretSyncInput =
| TWindmillSyncInput
| THCVaultSyncInput
| TTeamCitySyncInput
| TOCIVaultSyncInput;
| TOCIVaultSyncInput
| TOnePassSyncInput;
export type TSecretSyncListItem =
| TAwsParameterStoreSyncListItem
@@ -153,7 +162,8 @@ export type TSecretSyncListItem =
| TWindmillSyncListItem
| THCVaultSyncListItem
| TTeamCitySyncListItem
| TOCIVaultSyncListItem;
| TOCIVaultSyncListItem
| TOnePassSyncListItem;
export type TSyncOptionsConfig = {
canImportSecrets: boolean;
@@ -12,6 +12,7 @@ interface SecretApprovalRequestBypassedTemplateProps
environment: string;
bypassReason: string;
approvalUrl: string;
requestType: "change" | "access";
}
export const SecretApprovalRequestBypassedTemplate = ({
@@ -22,7 +23,8 @@ export const SecretApprovalRequestBypassedTemplate = ({
secretPath,
environment,
bypassReason,
approvalUrl
approvalUrl,
requestType = "change"
}: SecretApprovalRequestBypassedTemplateProps) => {
return (
<BaseEmailWrapper
@@ -39,8 +41,9 @@ export const SecretApprovalRequestBypassedTemplate = ({
<Link href={`mailto:${requesterEmail}`} className="text-slate-700 no-underline">
{requesterEmail}
</Link>
) has merged a secret to <strong>{secretPath}</strong> in the <strong>{environment}</strong> environment
without obtaining the required approval.
) has {requestType === "change" ? "merged" : "accessed"} a secret {requestType === "change" ? "to" : "in"}{" "}
<strong>{secretPath}</strong> in the <strong>{environment}</strong> environment without obtaining the required
approval.
</Text>
<Text className="text-[14px] text-slate-700 leading-[24px]">
<strong className="text-black">The following reason was provided for bypassing the policy:</strong> "