mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 09:26:47 +00:00
fix: handle keyschema with path segments for aws parameter store
This commit is contained in:
+57
-12
@@ -34,18 +34,41 @@ const sleep = async () =>
|
|||||||
setTimeout(resolve, 1000);
|
setTimeout(resolve, 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
const getParametersByPath = async (ssm: AWS.SSM, path: string): Promise<TAWSParameterStoreRecord> => {
|
const getFullPath = ({ path, keySchema }: { path: string; keySchema?: string }) => {
|
||||||
|
if (!keySchema || !keySchema.includes("/")) return path;
|
||||||
|
|
||||||
|
const keySchemaSegments = keySchema.split("/");
|
||||||
|
|
||||||
|
const pathSegments = keySchemaSegments.slice(0, keySchemaSegments.length - 1);
|
||||||
|
|
||||||
|
if (pathSegments.some((segment) => segment.includes("{{"))) {
|
||||||
|
throw new SecretSyncError({
|
||||||
|
message: "Key schema cannot contain '/' after keys: ie {{secretKey}} or {{environment}}",
|
||||||
|
shouldRetry: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${path}${pathSegments.join("/")}/`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getParametersByPath = async (
|
||||||
|
ssm: AWS.SSM,
|
||||||
|
path: string,
|
||||||
|
keySchema: string | undefined
|
||||||
|
): Promise<TAWSParameterStoreRecord> => {
|
||||||
const awsParameterStoreSecretsRecord: TAWSParameterStoreRecord = {};
|
const awsParameterStoreSecretsRecord: TAWSParameterStoreRecord = {};
|
||||||
let hasNext = true;
|
let hasNext = true;
|
||||||
let nextToken: string | undefined;
|
let nextToken: string | undefined;
|
||||||
let attempt = 0;
|
let attempt = 0;
|
||||||
|
|
||||||
|
const fullPath = getFullPath({ path, keySchema });
|
||||||
|
|
||||||
while (hasNext) {
|
while (hasNext) {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const parameters = await ssm
|
const parameters = await ssm
|
||||||
.getParametersByPath({
|
.getParametersByPath({
|
||||||
Path: path,
|
Path: fullPath,
|
||||||
Recursive: false,
|
Recursive: false,
|
||||||
WithDecryption: true,
|
WithDecryption: true,
|
||||||
MaxResults: BATCH_SIZE,
|
MaxResults: BATCH_SIZE,
|
||||||
@@ -59,7 +82,7 @@ const getParametersByPath = async (ssm: AWS.SSM, path: string): Promise<TAWSPara
|
|||||||
parameters.Parameters.forEach((parameter) => {
|
parameters.Parameters.forEach((parameter) => {
|
||||||
if (parameter.Name) {
|
if (parameter.Name) {
|
||||||
// no leading slash if path is '/'
|
// no leading slash if path is '/'
|
||||||
const secKey = path.length > 1 ? parameter.Name.substring(path.length) : parameter.Name;
|
const secKey = fullPath.length > 1 ? parameter.Name.substring(path.length) : parameter.Name;
|
||||||
awsParameterStoreSecretsRecord[secKey] = parameter;
|
awsParameterStoreSecretsRecord[secKey] = parameter;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -83,12 +106,18 @@ const getParametersByPath = async (ssm: AWS.SSM, path: string): Promise<TAWSPara
|
|||||||
return awsParameterStoreSecretsRecord;
|
return awsParameterStoreSecretsRecord;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getParameterMetadataByPath = async (ssm: AWS.SSM, path: string): Promise<TAWSParameterStoreMetadataRecord> => {
|
const getParameterMetadataByPath = async (
|
||||||
|
ssm: AWS.SSM,
|
||||||
|
path: string,
|
||||||
|
keySchema: string | undefined
|
||||||
|
): Promise<TAWSParameterStoreMetadataRecord> => {
|
||||||
const awsParameterStoreMetadataRecord: TAWSParameterStoreMetadataRecord = {};
|
const awsParameterStoreMetadataRecord: TAWSParameterStoreMetadataRecord = {};
|
||||||
let hasNext = true;
|
let hasNext = true;
|
||||||
let nextToken: string | undefined;
|
let nextToken: string | undefined;
|
||||||
let attempt = 0;
|
let attempt = 0;
|
||||||
|
|
||||||
|
const fullPath = getFullPath({ path, keySchema });
|
||||||
|
|
||||||
while (hasNext) {
|
while (hasNext) {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
@@ -100,7 +129,7 @@ const getParameterMetadataByPath = async (ssm: AWS.SSM, path: string): Promise<T
|
|||||||
{
|
{
|
||||||
Key: "Path",
|
Key: "Path",
|
||||||
Option: "OneLevel",
|
Option: "OneLevel",
|
||||||
Values: [path]
|
Values: [fullPath]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@@ -112,7 +141,7 @@ const getParameterMetadataByPath = async (ssm: AWS.SSM, path: string): Promise<T
|
|||||||
parameters.Parameters.forEach((parameter) => {
|
parameters.Parameters.forEach((parameter) => {
|
||||||
if (parameter.Name) {
|
if (parameter.Name) {
|
||||||
// no leading slash if path is '/'
|
// no leading slash if path is '/'
|
||||||
const secKey = path.length > 1 ? parameter.Name.substring(path.length) : parameter.Name;
|
const secKey = fullPath.length > 1 ? parameter.Name.substring(path.length) : parameter.Name;
|
||||||
awsParameterStoreMetadataRecord[secKey] = parameter;
|
awsParameterStoreMetadataRecord[secKey] = parameter;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -298,9 +327,17 @@ export const AwsParameterStoreSyncFns = {
|
|||||||
|
|
||||||
const ssm = await getSSM(secretSync);
|
const ssm = await getSSM(secretSync);
|
||||||
|
|
||||||
const awsParameterStoreSecretsRecord = await getParametersByPath(ssm, destinationConfig.path);
|
const awsParameterStoreSecretsRecord = await getParametersByPath(
|
||||||
|
ssm,
|
||||||
|
destinationConfig.path,
|
||||||
|
syncOptions.keySchema
|
||||||
|
);
|
||||||
|
|
||||||
const awsParameterStoreMetadataRecord = await getParameterMetadataByPath(ssm, destinationConfig.path);
|
const awsParameterStoreMetadataRecord = await getParameterMetadataByPath(
|
||||||
|
ssm,
|
||||||
|
destinationConfig.path,
|
||||||
|
syncOptions.keySchema
|
||||||
|
);
|
||||||
|
|
||||||
const { shouldManageTags, awsParameterStoreTagsRecord } = await getParameterStoreTagsRecord(
|
const { shouldManageTags, awsParameterStoreTagsRecord } = await getParameterStoreTagsRecord(
|
||||||
ssm,
|
ssm,
|
||||||
@@ -400,22 +437,30 @@ export const AwsParameterStoreSyncFns = {
|
|||||||
await deleteParametersBatch(ssm, parametersToDelete);
|
await deleteParametersBatch(ssm, parametersToDelete);
|
||||||
},
|
},
|
||||||
getSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials): Promise<TSecretMap> => {
|
getSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials): Promise<TSecretMap> => {
|
||||||
const { destinationConfig } = secretSync;
|
const { destinationConfig, syncOptions } = secretSync;
|
||||||
|
|
||||||
const ssm = await getSSM(secretSync);
|
const ssm = await getSSM(secretSync);
|
||||||
|
|
||||||
const awsParameterStoreSecretsRecord = await getParametersByPath(ssm, destinationConfig.path);
|
const awsParameterStoreSecretsRecord = await getParametersByPath(
|
||||||
|
ssm,
|
||||||
|
destinationConfig.path,
|
||||||
|
syncOptions.keySchema
|
||||||
|
);
|
||||||
|
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(awsParameterStoreSecretsRecord).map(([key, value]) => [key, { value: value.Value ?? "" }])
|
Object.entries(awsParameterStoreSecretsRecord).map(([key, value]) => [key, { value: value.Value ?? "" }])
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
removeSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials, secretMap: TSecretMap) => {
|
removeSecrets: async (secretSync: TAwsParameterStoreSyncWithCredentials, secretMap: TSecretMap) => {
|
||||||
const { destinationConfig } = secretSync;
|
const { destinationConfig, syncOptions } = secretSync;
|
||||||
|
|
||||||
const ssm = await getSSM(secretSync);
|
const ssm = await getSSM(secretSync);
|
||||||
|
|
||||||
const awsParameterStoreSecretsRecord = await getParametersByPath(ssm, destinationConfig.path);
|
const awsParameterStoreSecretsRecord = await getParametersByPath(
|
||||||
|
ssm,
|
||||||
|
destinationConfig.path,
|
||||||
|
syncOptions.keySchema
|
||||||
|
);
|
||||||
|
|
||||||
const parametersToDelete: AWS.SSM.Parameter[] = [];
|
const parametersToDelete: AWS.SSM.Parameter[] = [];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user