Update impl for AWS SM/PS integrations with KMS

This commit is contained in:
Tuan Dang
2024-04-29 16:49:53 -07:00
parent c8638479a8
commit 93b65a1534
5 changed files with 170 additions and 178 deletions
@@ -566,20 +566,32 @@ export const integrationAuthServiceFactory = ({
} }
}); });
const kms = new AWS.KMS(); const kms = new AWS.KMS();
const aliases = await kms.listAliases({}).promise(); const aliases = await kms.listAliases({}).promise();
const keys = await kms.listKeys({}).promise();
const response = keys
.Keys!.map((key) => {
const keyAlias = aliases.Aliases!.find((alias) => key.KeyId === alias.TargetKeyId);
if (!keyAlias?.AliasName?.includes("alias/aws/")) {
return { id: String(key.KeyId), alias: String(keyAlias?.AliasName || key.KeyId) };
}
return { id: "null", alias: "null" };
})
.filter((elem) => elem.id !== "null");
return [...response, { id: "null", alias: "default" }]; const keyAliases = aliases.Aliases!.filter((alias) => {
if (!alias.TargetKeyId) return false;
if (integrationAuth.integration === Integrations.AWS_PARAMETER_STORE && alias.AliasName === "alias/aws/ssm")
return true;
if (
integrationAuth.integration === Integrations.AWS_SECRET_MANAGER &&
alias.AliasName === "alias/aws/secretsmanager"
)
return true;
if (alias.AliasName?.includes("alias/aws/")) return false;
return alias.TargetKeyId;
});
const keysWithAliases = keyAliases.map((alias) => {
return {
id: alias.TargetKeyId!,
alias: alias.AliasName!
};
});
return keysWithAliases;
}; };
const getQoveryProjects = async ({ const getQoveryProjects = async ({
@@ -442,6 +442,7 @@ const syncSecretsAWSParameterStore = async ({
accessId: string | null; accessId: string | null;
accessToken: string; accessToken: string;
}) => { }) => {
try {
if (!accessId) return; if (!accessId) return;
const config = new AWS.Config({ const config = new AWS.Config({
@@ -489,7 +490,7 @@ const syncSecretsAWSParameterStore = async ({
Name: `${integration.path}${key}`, Name: `${integration.path}${key}`,
Type: "SecureString", Type: "SecureString",
Value: secrets[key].value, Value: secrets[key].value,
KeyId: metadata.kmsKeyId ? metadata.kmsKeyId : undefined, ...(metadata.kmsKeyId && { KeyId: metadata.kmsKeyId }),
// Overwrite: true, // Overwrite: true,
Tags: metadata.secretAWSTag Tags: metadata.secretAWSTag
? metadata.secretAWSTag.map((tag: { key: string; value: string }) => ({ ? metadata.secretAWSTag.map((tag: { key: string; value: string }) => ({
@@ -531,6 +532,9 @@ const syncSecretsAWSParameterStore = async ({
} }
}) })
); );
} catch (err) {
console.error("syncSecretsAWSPS error: ", err);
}
}; };
/** /**
@@ -572,7 +576,6 @@ const syncSecretsAWSSecretManager = async ({
if (awsSecretManagerSecret?.SecretString) { if (awsSecretManagerSecret?.SecretString) {
awsSecretManagerSecretObj = JSON.parse(awsSecretManagerSecret.SecretString); awsSecretManagerSecretObj = JSON.parse(awsSecretManagerSecret.SecretString);
} }
if (!isEqual(awsSecretManagerSecretObj, secKeyVal)) { if (!isEqual(awsSecretManagerSecretObj, secKeyVal)) {
await secretsManager.send( await secretsManager.send(
new UpdateSecretCommand({ new UpdateSecretCommand({
@@ -587,7 +590,7 @@ const syncSecretsAWSSecretManager = async ({
new CreateSecretCommand({ new CreateSecretCommand({
Name: integration.app as string, Name: integration.app as string,
SecretString: JSON.stringify(secKeyVal), SecretString: JSON.stringify(secKeyVal),
KmsKeyId: metadata.kmsKeyId ? metadata.kmsKeyId : null, ...(metadata.kmsKeyId && { KmsKeyId: metadata.kmsKeyId }),
Tags: metadata.secretAWSTag Tags: metadata.secretAWSTag
? metadata.secretAWSTag.map((tag: { key: string; value: string }) => ({ Key: tag.key, Value: tag.value })) ? metadata.secretAWSTag.map((tag: { key: string; value: string }) => ({ Key: tag.key, Value: tag.value }))
: [] : []
@@ -48,10 +48,9 @@ const integrationAuthKeys = {
integrationAuthId, integrationAuthId,
region region
}: { }: {
integrationAuthId: string, integrationAuthId: string;
region: string region: string;
}) => }) => [{ integrationAuthId, region }, "integrationAuthAwsKmsKeyIds"] as const,
[{ integrationAuthId, region }, "integrationAuthAwsKmsKeyIds"] as const,
getIntegrationAuthQoveryOrgs: (integrationAuthId: string) => getIntegrationAuthQoveryOrgs: (integrationAuthId: string) =>
[{ integrationAuthId }, "integrationAuthQoveryOrgs"] as const, [{ integrationAuthId }, "integrationAuthQoveryOrgs"] as const,
getIntegrationAuthQoveryProjects: ({ getIntegrationAuthQoveryProjects: ({
@@ -226,27 +225,6 @@ const fetchIntegrationAuthQoveryOrgs = async (integrationAuthId: string) => {
return orgs; return orgs;
}; };
const fetchIntegrationAuthAwsKmsKeys = async ({
integrationAuthId,
region
}: {
integrationAuthId: string;
region: string;
}) => {
const {
data: { kmsKeys }
} = await apiRequest.get<{ kmsKeys: KmsKey[] }>(
`/api/v1/integration-auth/${integrationAuthId}/aws-secrets-manager/kms-keys`,
{
params: {
region
}
}
);
return kmsKeys;
};
const fetchIntegrationAuthQoveryProjects = async ({ const fetchIntegrationAuthQoveryProjects = async ({
integrationAuthId, integrationAuthId,
orgId orgId
@@ -586,11 +564,22 @@ export const useGetIntegrationAuthAwsKmsKeys = ({
integrationAuthId, integrationAuthId,
region region
}), }),
queryFn: () => queryFn: async () => {
fetchIntegrationAuthAwsKmsKeys({ if (!region) return [];
integrationAuthId,
const {
data: { kmsKeys }
} = await apiRequest.get<{ kmsKeys: KmsKey[] }>(
`/api/v1/integration-auth/${integrationAuthId}/aws-secrets-manager/kms-keys`,
{
params: {
region region
}), }
}
);
return kmsKeys;
},
enabled: true enabled: true
}); });
}; };
@@ -100,19 +100,12 @@ export default function AWSParameterStoreCreateIntegrationPage() {
} }
}, [workspace]); }, [workspace]);
const { data: integrationAuthAwsKmsKeys, isLoading: isIntegrationAuthAwsKmsKeysLoading } = const { data: integrationAuthAwsKmsKeys, isLoading: isIntegrationAuthAwsKmsKeysLoading } =
useGetIntegrationAuthAwsKmsKeys({ useGetIntegrationAuthAwsKmsKeys({
integrationAuthId: String(integrationAuthId), integrationAuthId: String(integrationAuthId),
region: selectedAWSRegion region: selectedAWSRegion
}); });
useEffect(() => {
if (integrationAuthAwsKmsKeys) {
setKmsKeyId(String(integrationAuthAwsKmsKeys?.filter(key => key.alias === "default")[0]?.id))
}
}, [integrationAuthAwsKmsKeys])
const isValidAWSParameterStorePath = (awsStorePath: string) => { const isValidAWSParameterStorePath = (awsStorePath: string) => {
const pattern = /^\/([\w-]+\/)*[\w-]+\/$/; const pattern = /^\/([\w-]+\/)*[\w-]+\/$/;
return pattern.test(awsStorePath) && awsStorePath.length <= 2048; return pattern.test(awsStorePath) && awsStorePath.length <= 2048;
@@ -143,16 +136,15 @@ export default function AWSParameterStoreCreateIntegrationPage() {
metadata: { metadata: {
...(shouldTag ...(shouldTag
? { ? {
secretAWSTag: [{ secretAWSTag: [
{
key: tagKey, key: tagKey,
value: tagValue value: tagValue
}] }
]
} }
: {}), : {}),
...((kmsKeyId && integrationAuthAwsKmsKeys?.filter(key => key.id === kmsKeyId)[0]?.alias !== "default") ? ...(kmsKeyId && { kmsKeyId })
{
kmsKeyId
}: {})
} }
}); });
@@ -165,7 +157,10 @@ export default function AWSParameterStoreCreateIntegrationPage() {
} }
}; };
return (integrationAuth && workspace && selectedSourceEnvironment && !isIntegrationAuthAwsKmsKeysLoading) ? ( return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
!isIntegrationAuthAwsKmsKeysLoading ? (
<div className="flex h-full w-full flex-col items-center justify-center"> <div className="flex h-full w-full flex-col items-center justify-center">
<Head> <Head>
<title>Set Up AWS Parameter Integration</title> <title>Set Up AWS Parameter Integration</title>
@@ -241,7 +236,10 @@ export default function AWSParameterStoreCreateIntegrationPage() {
<FormControl label="AWS Region"> <FormControl label="AWS Region">
<Select <Select
value={selectedAWSRegion} value={selectedAWSRegion}
onValueChange={(val) => setSelectedAWSRegion(val)} onValueChange={(val) => {
setSelectedAWSRegion(val);
setKmsKeyId("");
}}
className="w-full border border-mineshaft-500" className="w-full border border-mineshaft-500"
> >
{awsRegions.map((awsRegion) => ( {awsRegions.map((awsRegion) => (
@@ -285,18 +283,14 @@ export default function AWSParameterStoreCreateIntegrationPage() {
</div> </div>
{shouldTag && ( {shouldTag && (
<div className="mt-4"> <div className="mt-4">
<FormControl <FormControl label="Tag Key">
label="Tag Key"
>
<Input <Input
placeholder="managed-by" placeholder="managed-by"
value={tagKey} value={tagKey}
onChange={(e) => setTagKey(e.target.value)} onChange={(e) => setTagKey(e.target.value)}
/> />
</FormControl> </FormControl>
<FormControl <FormControl label="Tag Value">
label="Tag Value"
>
<Input <Input
placeholder="infisical" placeholder="infisical"
value={tagValue} value={tagValue}
@@ -309,7 +303,7 @@ export default function AWSParameterStoreCreateIntegrationPage() {
<Select <Select
value={kmsKeyId} value={kmsKeyId}
onValueChange={(e) => { onValueChange={(e) => {
setKmsKeyId(e) setKmsKeyId(e);
}} }}
className="w-full border border-mineshaft-500" className="w-full border border-mineshaft-500"
> >
@@ -362,7 +356,7 @@ export default function AWSParameterStoreCreateIntegrationPage() {
<title>Set Up AWS Parameter Store Integration</title> <title>Set Up AWS Parameter Store Integration</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
{(isintegrationAuthLoading || isIntegrationAuthAwsKmsKeysLoading) ? ( {isintegrationAuthLoading || isIntegrationAuthAwsKmsKeysLoading ? (
<img <img
src="/images/loading/loading.gif" src="/images/loading/loading.gif"
height={70} height={70}
@@ -96,19 +96,12 @@ export default function AWSSecretManagerCreateIntegrationPage() {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [shouldTag, setShouldTag] = useState(false); const [shouldTag, setShouldTag] = useState(false);
const { data: integrationAuthAwsKmsKeys, isLoading: isIntegrationAuthAwsKmsKeysLoading } = const { data: integrationAuthAwsKmsKeys, isLoading: isIntegrationAuthAwsKmsKeysLoading } =
useGetIntegrationAuthAwsKmsKeys({ useGetIntegrationAuthAwsKmsKeys({
integrationAuthId: String(integrationAuthId), integrationAuthId: String(integrationAuthId),
region: selectedAWSRegion region: selectedAWSRegion
}); });
useEffect(() => {
if (integrationAuthAwsKmsKeys) {
setKmsKeyId(String(integrationAuthAwsKmsKeys?.filter(key => key.alias === "alias/aws/secretsmanager")[0]?.id))
}
}, [integrationAuthAwsKmsKeys])
useEffect(() => { useEffect(() => {
if (workspace) { if (workspace) {
setSelectedSourceEnvironment(workspace.environments[0].slug); setSelectedSourceEnvironment(workspace.environments[0].slug);
@@ -142,16 +135,15 @@ export default function AWSSecretManagerCreateIntegrationPage() {
metadata: { metadata: {
...(shouldTag ...(shouldTag
? { ? {
secretAWSTag: [{ secretAWSTag: [
{
key: tagKey, key: tagKey,
value: tagValue value: tagValue
}] }
]
} }
: {}), : {}),
...((kmsKeyId && integrationAuthAwsKmsKeys?.filter(key => key.id === kmsKeyId)[0]?.alias !== "default") ? ...(kmsKeyId && { kmsKeyId })
{
kmsKeyId
}: {})
} }
}); });
@@ -164,7 +156,10 @@ export default function AWSSecretManagerCreateIntegrationPage() {
} }
}; };
return (integrationAuth && workspace && selectedSourceEnvironment && !isIntegrationAuthAwsKmsKeysLoading) ? ( return integrationAuth &&
workspace &&
selectedSourceEnvironment &&
!isIntegrationAuthAwsKmsKeysLoading ? (
<div className="flex h-full w-full flex-col items-center justify-center"> <div className="flex h-full w-full flex-col items-center justify-center">
<Head> <Head>
<title>Set Up AWS Secrets Manager Integration</title> <title>Set Up AWS Secrets Manager Integration</title>
@@ -240,7 +235,10 @@ export default function AWSSecretManagerCreateIntegrationPage() {
<FormControl label="AWS Region"> <FormControl label="AWS Region">
<Select <Select
value={selectedAWSRegion} value={selectedAWSRegion}
onValueChange={(val) => setSelectedAWSRegion(val)} onValueChange={(val) => {
setSelectedAWSRegion(val);
setKmsKeyId("");
}}
className="w-full border border-mineshaft-500" className="w-full border border-mineshaft-500"
> >
{awsRegions.map((awsRegion) => ( {awsRegions.map((awsRegion) => (
@@ -284,18 +282,14 @@ export default function AWSSecretManagerCreateIntegrationPage() {
</div> </div>
{shouldTag && ( {shouldTag && (
<div className="mt-4"> <div className="mt-4">
<FormControl <FormControl label="Tag Key">
label="Tag Key"
>
<Input <Input
placeholder="managed-by" placeholder="managed-by"
value={tagKey} value={tagKey}
onChange={(e) => setTagKey(e.target.value)} onChange={(e) => setTagKey(e.target.value)}
/> />
</FormControl> </FormControl>
<FormControl <FormControl label="Tag Value">
label="Tag Value"
>
<Input <Input
placeholder="infisical" placeholder="infisical"
value={tagValue} value={tagValue}
@@ -308,7 +302,7 @@ export default function AWSSecretManagerCreateIntegrationPage() {
<Select <Select
value={kmsKeyId} value={kmsKeyId}
onValueChange={(e) => { onValueChange={(e) => {
setKmsKeyId(e) setKmsKeyId(e);
}} }}
className="w-full border border-mineshaft-500" className="w-full border border-mineshaft-500"
> >
@@ -361,7 +355,7 @@ export default function AWSSecretManagerCreateIntegrationPage() {
<title>Set Up AWS Secrets Manager Integration</title> <title>Set Up AWS Secrets Manager Integration</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
</Head> </Head>
{(isintegrationAuthLoading || isIntegrationAuthAwsKmsKeysLoading) ? ( {isintegrationAuthLoading || isIntegrationAuthAwsKmsKeysLoading ? (
<img <img
src="/images/loading/loading.gif" src="/images/loading/loading.gif"
height={70} height={70}