Merge pull request #1763 from Infisical/aws-sm-ps-check

Update implementation for AWS SM/PS integration KMS ID option
This commit is contained in:
Maidul Islam
2024-04-29 20:44:54 -04:00
committed by GitHub
6 changed files with 96 additions and 106 deletions

View File

@@ -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 ({

View File

@@ -489,7 +489,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 }) => ({
@@ -572,7 +572,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 +586,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 }))
: [] : []

View File

@@ -31,7 +31,9 @@ Prerequisites:
"secretsmanager:UpdateSecret", "secretsmanager:UpdateSecret",
"secretsmanager:TagResource", // if you need to add tags to secrets "secretsmanager:TagResource", // if you need to add tags to secrets
"kms:ListKeys", // if you need to specify the KMS key "kms:ListKeys", // if you need to specify the KMS key
"kms:ListAliases" // if you need to specify the KMS key "kms:ListAliases", // if you need to specify the KMS key
"kms:Encrypt", // if you need to specify the KMS key
"kms:Decrypt" // if you need to specify the KMS key
], ],
"Resource": "*" "Resource": "*"
} }

View File

@@ -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,
region const {
}), data: { kmsKeys }
} = await apiRequest.get<{ kmsKeys: KmsKey[] }>(
`/api/v1/integration-auth/${integrationAuthId}/aws-secrets-manager/kms-keys`,
{
params: {
region
}
}
);
return kmsKeys;
},
enabled: true enabled: true
}); });
}; };

View File

@@ -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, {
value: tagValue key: tagKey,
}] 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,20 +283,16 @@ 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
> placeholder="managed-by"
<Input
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
> placeholder="infisical"
<Input
placeholder="infisical"
value={tagValue} value={tagValue}
onChange={(e) => setTagValue(e.target.value)} onChange={(e) => setTagValue(e.target.value)}
/> />
@@ -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}

View File

@@ -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, {
value: tagValue key: tagKey,
}] 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,20 +282,16 @@ 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
> placeholder="managed-by"
<Input
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
> placeholder="infisical"
<Input
placeholder="infisical"
value={tagValue} value={tagValue}
onChange={(e) => setTagValue(e.target.value)} onChange={(e) => setTagValue(e.target.value)}
/> />
@@ -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}