Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions codegen/src/iam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,16 @@ type Principal =
};

type Action =
| "cloudformation:*"
| `${string}:*`
| `${iam.AwsBackupActions}`
| `${iam.AwsCloudformationActions}`
| "logs:*"
| `${iam.AwsLogsActions}`
| "iam:*"
| `${iam.AwsEbsActions}`
| `${iam.AwsEc2Actions}`
| `${iam.AwsIamActions}`
| "lambda:*"
| `${iam.AwsKmsActions}`
| `${iam.AwsLambdaActions}`
| "s3:*"
| `${iam.AwsLogsActions}`
| `${iam.AwsS3Actions}`
| "ssm:*"
| `${iam.AwsSsmActions}`;

type KnownTag =
Expand All @@ -65,7 +64,11 @@ type KnownTag =
| "elastio:authorize"

// Set on every resource deployed by Elastio
| "elastio:resource";
| "elastio:resource"

// Set by AWS Backup on resources created as part of AWS Backup restore testing.
// The value of this tag is the ID of the AWS Backup restore job.
| "awsbackup-restore-test";

export function hasResourceTag(tag: KnownTag) {
return hasTags("aws:ResourceTag", tag);
Expand Down
114 changes: 114 additions & 0 deletions codegen/src/policies/ElastioAwsBackupEc2Scan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import * as iam from "../iam";

export default {
description: "Allows Elastio to scan AWS Backup recovery points.",

statements: [
{
Sid: "ReadBackupInventory",
Action: [
// Vaults
"backup:ListBackupVaults",
"backup:DescribeBackupVault",

// Recovery points
"backup:ListRecoveryPointsByResource",
"backup:DescribeRecoveryPoint",
"backup:ListRecoveryPointsByBackupVault",
"backup:GetRecoveryPointRestoreMetadata",

// Common for all resources
"backup:ListTags",

// Misc.
"backup:ListProtectedResources",
"backup:ListProtectedResourcesByBackupVault",
],
Resource: "*",
},

{
Sid: "ReadEbsInventory",
Action: [
// Volumes
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",

// Snapshots
"ec2:DescribeSnapshots",
"ec2:DescribeSnapshotAttribute",

// Common for all resources
"ec2:DescribeTags",

// Used for cost estimation
"ebs:ListSnapshotBlocks",
"ebs:ListChangedBlocks",
],
Resource: "*",
},

{
Sid: "ReadEbsSnapshotsData",
Action: ["ebs:GetSnapshotBlock"],
Resource: "*",
},

{
Sid: "ReadEc2Inventory",
Action: [
"ec2:DescribeInstances",
"ec2:DescribeImages",
"ec2:DescribeHosts",
"ssm:DescribeInstanceInformation",
],
Resource: "*",
},

{
Sid: "ShareEbsSnapshot",
Action: ["ec2:ModifySnapshotAttribute"],
Resource: "*",
Condition: {
// Needed to add createVolumePermission for the sharing the snapshot
// with the connector account.
StringLike: {
"ec2:Add/userId": "*",
},
},
},

{
Sid: "KmsAccess",

// Users need to put a special tag on their KMS keys to allow Elastio
// use them for decrypting their data. It must be documented in public
// Elastio documentation.
Condition: iam.hasResourceTag("elastio:authorize"),

Action: [
// These actions are needed to reencrypt the volumes that were encrypted
// by the KMS key.
"kms:ReEncryptFrom",
"kms:ReEncryptTo",
"kms:CreateGrant",
"kms:Encrypt",

// Needed only for some cases. For example, when we want to snapshot an EBS
// volume that was created from a snapshot of the root volume of an EC2 instance.
// These calls are made by the ebs.amazonaws.com and not by our code.
"kms:DescribeKey",

// GenerateDataKeyWithoutPlaintext in particular is required in case when
// we create a volume from an unencrypted snapshot but there is a default
// KMS encryption key set in EBS for the volume.
"kms:GenerateDataKey",
"kms:GenerateDataKeyWithoutPlaintext",

// This is required when reading S3 buckets encrypted with a KMS key
"kms:Decrypt",
],
Resource: "*",
},
],
} satisfies iam.Policy;
2 changes: 2 additions & 0 deletions iam-policies/terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ See the basic [usage example](./examples/basic/main.tf).
| Policy | Description |
| ------------------------------------------------------------ | -------------------------------------------------------------- |
| [`ElastioAssetAccountDeployer`][ElastioAssetAccountDeployer] | Permissions required to deploy the Elastio Asset Account stack |
| [`ElastioAwsBackupEc2Scan`][ElastioAwsBackupEc2Scan] | Allows Elastio to scan AWS Backup recovery points. |

[ElastioAssetAccountDeployer]: ../../codegen/src/policies/ElastioAssetAccountDeployer.ts
[ElastioAwsBackupEc2Scan]: ../../codegen/src/policies/ElastioAwsBackupEc2Scan.ts

<!-- ELASTIO_END_POLICY_NAMES -->

Expand Down
86 changes: 86 additions & 0 deletions iam-policies/terraform/policies/ElastioAwsBackupEc2Scan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"Description": "Allows Elastio to scan AWS Backup recovery points.",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadBackupInventory",
"Action": [
"backup:ListBackupVaults",
"backup:DescribeBackupVault",
"backup:ListRecoveryPointsByResource",
"backup:DescribeRecoveryPoint",
"backup:ListRecoveryPointsByBackupVault",
"backup:GetRecoveryPointRestoreMetadata",
"backup:ListTags",
"backup:ListProtectedResources",
"backup:ListProtectedResourcesByBackupVault"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Sid": "ReadEbsInventory",
"Action": [
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",
"ec2:DescribeSnapshots",
"ec2:DescribeSnapshotAttribute",
"ec2:DescribeTags",
"ebs:ListSnapshotBlocks",
"ebs:ListChangedBlocks"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Sid": "ReadEbsSnapshotsData",
"Action": ["ebs:GetSnapshotBlock"],
"Resource": "*",
"Effect": "Allow"
},
{
"Sid": "ReadEc2Inventory",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeImages",
"ec2:DescribeHosts",
"ssm:DescribeInstanceInformation"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Sid": "ShareEbsSnapshot",
"Action": ["ec2:ModifySnapshotAttribute"],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:Add/userId": "*"
}
},
"Effect": "Allow"
},
{
"Sid": "KmsAccess",
"Condition": {
"StringLike": {
"aws:ResourceTag/elastio:authorize": "*"
}
},
"Action": [
"kms:ReEncryptFrom",
"kms:ReEncryptTo",
"kms:CreateGrant",
"kms:Encrypt",
"kms:DescribeKey",
"kms:GenerateDataKey",
"kms:GenerateDataKeyWithoutPlaintext",
"kms:Decrypt"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
}