Configure AWS Data Lifecycle Manager Policies

The aws:dlm/lifecyclePolicy:LifecyclePolicy resource, part of the Pulumi AWS provider, defines Data Lifecycle Manager policies that automate EBS snapshot creation, retention, and cross-region replication. This guide focuses on four capabilities: schedule-based automation, cross-region disaster recovery, event-based snapshot handling, and application-consistent Windows backups.

DLM policies require IAM execution roles with DLM trust relationships and may reference KMS keys, tagged volumes, or EC2 instances. The examples are intentionally small. Combine them with your own IAM roles, tagging strategy, and backup requirements.

Create daily EBS volume snapshots with retention

Most snapshot automation begins with a schedule that creates daily backups of tagged volumes and retains them for a fixed period.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const assumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["dlm.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const dlmLifecycleRole = new aws.iam.Role("dlm_lifecycle_role", {
    name: "dlm-lifecycle-role",
    assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json),
});
const dlmLifecycle = aws.iam.getPolicyDocument({
    statements: [
        {
            effect: "Allow",
            actions: [
                "ec2:CreateSnapshot",
                "ec2:CreateSnapshots",
                "ec2:DeleteSnapshot",
                "ec2:DescribeInstances",
                "ec2:DescribeVolumes",
                "ec2:DescribeSnapshots",
            ],
            resources: ["*"],
        },
        {
            effect: "Allow",
            actions: ["ec2:CreateTags"],
            resources: ["arn:aws:ec2:*::snapshot/*"],
        },
    ],
});
const dlmLifecycleRolePolicy = new aws.iam.RolePolicy("dlm_lifecycle", {
    name: "dlm-lifecycle-policy",
    role: dlmLifecycleRole.id,
    policy: dlmLifecycle.then(dlmLifecycle => dlmLifecycle.json),
});
const example = new aws.dlm.LifecyclePolicy("example", {
    description: "example DLM lifecycle policy",
    executionRoleArn: dlmLifecycleRole.arn,
    state: "ENABLED",
    policyDetails: {
        resourceTypes: ["VOLUME"],
        schedules: [{
            name: "2 weeks of daily snapshots",
            createRule: {
                interval: 24,
                intervalUnit: "HOURS",
                times: "23:45",
            },
            retainRule: {
                count: 14,
            },
            tagsToAdd: {
                SnapshotCreator: "DLM",
            },
            copyTags: false,
        }],
        targetTags: {
            Snapshot: "true",
        },
    },
});
import pulumi
import pulumi_aws as aws

assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["dlm.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
dlm_lifecycle_role = aws.iam.Role("dlm_lifecycle_role",
    name="dlm-lifecycle-role",
    assume_role_policy=assume_role.json)
dlm_lifecycle = aws.iam.get_policy_document(statements=[
    {
        "effect": "Allow",
        "actions": [
            "ec2:CreateSnapshot",
            "ec2:CreateSnapshots",
            "ec2:DeleteSnapshot",
            "ec2:DescribeInstances",
            "ec2:DescribeVolumes",
            "ec2:DescribeSnapshots",
        ],
        "resources": ["*"],
    },
    {
        "effect": "Allow",
        "actions": ["ec2:CreateTags"],
        "resources": ["arn:aws:ec2:*::snapshot/*"],
    },
])
dlm_lifecycle_role_policy = aws.iam.RolePolicy("dlm_lifecycle",
    name="dlm-lifecycle-policy",
    role=dlm_lifecycle_role.id,
    policy=dlm_lifecycle.json)
example = aws.dlm.LifecyclePolicy("example",
    description="example DLM lifecycle policy",
    execution_role_arn=dlm_lifecycle_role.arn,
    state="ENABLED",
    policy_details={
        "resource_types": ["VOLUME"],
        "schedules": [{
            "name": "2 weeks of daily snapshots",
            "create_rule": {
                "interval": 24,
                "interval_unit": "HOURS",
                "times": "23:45",
            },
            "retain_rule": {
                "count": 14,
            },
            "tags_to_add": {
                "SnapshotCreator": "DLM",
            },
            "copy_tags": False,
        }],
        "target_tags": {
            "Snapshot": "true",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		assumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"dlm.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		dlmLifecycleRole, err := iam.NewRole(ctx, "dlm_lifecycle_role", &iam.RoleArgs{
			Name:             pulumi.String("dlm-lifecycle-role"),
			AssumeRolePolicy: pulumi.String(assumeRole.Json),
		})
		if err != nil {
			return err
		}
		dlmLifecycle, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Actions: []string{
						"ec2:CreateSnapshot",
						"ec2:CreateSnapshots",
						"ec2:DeleteSnapshot",
						"ec2:DescribeInstances",
						"ec2:DescribeVolumes",
						"ec2:DescribeSnapshots",
					},
					Resources: []string{
						"*",
					},
				},
				{
					Effect: pulumi.StringRef("Allow"),
					Actions: []string{
						"ec2:CreateTags",
					},
					Resources: []string{
						"arn:aws:ec2:*::snapshot/*",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicy(ctx, "dlm_lifecycle", &iam.RolePolicyArgs{
			Name:   pulumi.String("dlm-lifecycle-policy"),
			Role:   dlmLifecycleRole.ID(),
			Policy: pulumi.String(dlmLifecycle.Json),
		})
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("example DLM lifecycle policy"),
			ExecutionRoleArn: dlmLifecycleRole.Arn,
			State:            pulumi.String("ENABLED"),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				ResourceTypes: pulumi.StringArray{
					pulumi.String("VOLUME"),
				},
				Schedules: dlm.LifecyclePolicyPolicyDetailsScheduleArray{
					&dlm.LifecyclePolicyPolicyDetailsScheduleArgs{
						Name: pulumi.String("2 weeks of daily snapshots"),
						CreateRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs{
							Interval:     pulumi.Int(24),
							IntervalUnit: pulumi.String("HOURS"),
							Times:        pulumi.String("23:45"),
						},
						RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs{
							Count: pulumi.Int(14),
						},
						TagsToAdd: pulumi.StringMap{
							"SnapshotCreator": pulumi.String("DLM"),
						},
						CopyTags: pulumi.Bool(false),
					},
				},
				TargetTags: pulumi.StringMap{
					"Snapshot": pulumi.String("true"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var assumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "dlm.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var dlmLifecycleRole = new Aws.Iam.Role("dlm_lifecycle_role", new()
    {
        Name = "dlm-lifecycle-role",
        AssumeRolePolicy = assumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var dlmLifecycle = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ec2:CreateSnapshot",
                    "ec2:CreateSnapshots",
                    "ec2:DeleteSnapshot",
                    "ec2:DescribeInstances",
                    "ec2:DescribeVolumes",
                    "ec2:DescribeSnapshots",
                },
                Resources = new[]
                {
                    "*",
                },
            },
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ec2:CreateTags",
                },
                Resources = new[]
                {
                    "arn:aws:ec2:*::snapshot/*",
                },
            },
        },
    });

    var dlmLifecycleRolePolicy = new Aws.Iam.RolePolicy("dlm_lifecycle", new()
    {
        Name = "dlm-lifecycle-policy",
        Role = dlmLifecycleRole.Id,
        Policy = dlmLifecycle.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var example = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "example DLM lifecycle policy",
        ExecutionRoleArn = dlmLifecycleRole.Arn,
        State = "ENABLED",
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            ResourceTypes = new[]
            {
                "VOLUME",
            },
            Schedules = new[]
            {
                new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleArgs
                {
                    Name = "2 weeks of daily snapshots",
                    CreateRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs
                    {
                        Interval = 24,
                        IntervalUnit = "HOURS",
                        Times = "23:45",
                    },
                    RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs
                    {
                        Count = 14,
                    },
                    TagsToAdd = 
                    {
                        { "SnapshotCreator", "DLM" },
                    },
                    CopyTags = false,
                },
            },
            TargetTags = 
            {
                { "Snapshot", "true" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.iam.RolePolicy;
import com.pulumi.aws.iam.RolePolicyArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var assumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("dlm.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var dlmLifecycleRole = new Role("dlmLifecycleRole", RoleArgs.builder()
            .name("dlm-lifecycle-role")
            .assumeRolePolicy(assumeRole.json())
            .build());

        final var dlmLifecycle = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(            
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions(                    
                        "ec2:CreateSnapshot",
                        "ec2:CreateSnapshots",
                        "ec2:DeleteSnapshot",
                        "ec2:DescribeInstances",
                        "ec2:DescribeVolumes",
                        "ec2:DescribeSnapshots")
                    .resources("*")
                    .build(),
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("ec2:CreateTags")
                    .resources("arn:aws:ec2:*::snapshot/*")
                    .build())
            .build());

        var dlmLifecycleRolePolicy = new RolePolicy("dlmLifecycleRolePolicy", RolePolicyArgs.builder()
            .name("dlm-lifecycle-policy")
            .role(dlmLifecycleRole.id())
            .policy(dlmLifecycle.json())
            .build());

        var example = new LifecyclePolicy("example", LifecyclePolicyArgs.builder()
            .description("example DLM lifecycle policy")
            .executionRoleArn(dlmLifecycleRole.arn())
            .state("ENABLED")
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .resourceTypes("VOLUME")
                .schedules(LifecyclePolicyPolicyDetailsScheduleArgs.builder()
                    .name("2 weeks of daily snapshots")
                    .createRule(LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs.builder()
                        .interval(24)
                        .intervalUnit("HOURS")
                        .times("23:45")
                        .build())
                    .retainRule(LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs.builder()
                        .count(14)
                        .build())
                    .tagsToAdd(Map.of("SnapshotCreator", "DLM"))
                    .copyTags(false)
                    .build())
                .targetTags(Map.of("Snapshot", "true"))
                .build())
            .build());

    }
}
resources:
  dlmLifecycleRole:
    type: aws:iam:Role
    name: dlm_lifecycle_role
    properties:
      name: dlm-lifecycle-role
      assumeRolePolicy: ${assumeRole.json}
  dlmLifecycleRolePolicy:
    type: aws:iam:RolePolicy
    name: dlm_lifecycle
    properties:
      name: dlm-lifecycle-policy
      role: ${dlmLifecycleRole.id}
      policy: ${dlmLifecycle.json}
  example:
    type: aws:dlm:LifecyclePolicy
    properties:
      description: example DLM lifecycle policy
      executionRoleArn: ${dlmLifecycleRole.arn}
      state: ENABLED
      policyDetails:
        resourceTypes:
          - VOLUME
        schedules:
          - name: 2 weeks of daily snapshots
            createRule:
              interval: 24
              intervalUnit: HOURS
              times: 23:45
            retainRule:
              count: 14
            tagsToAdd:
              SnapshotCreator: DLM
            copyTags: false
        targetTags:
          Snapshot: 'true'
variables:
  assumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - dlm.amazonaws.com
            actions:
              - sts:AssumeRole
  dlmLifecycle:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            actions:
              - ec2:CreateSnapshot
              - ec2:CreateSnapshots
              - ec2:DeleteSnapshot
              - ec2:DescribeInstances
              - ec2:DescribeVolumes
              - ec2:DescribeSnapshots
            resources:
              - '*'
          - effect: Allow
            actions:
              - ec2:CreateTags
            resources:
              - arn:aws:ec2:*::snapshot/*

The policy evaluates volumes with the targetTags you specify (here, Snapshot=true) and creates snapshots according to the createRule schedule. The retainRule controls how many snapshots to keep; older snapshots are automatically deleted. The executionRoleArn grants DLM permissions to create, tag, and delete snapshots.

Use simplified default policies for volume backups

AWS provides default policies that apply standard backup schedules account-wide, with optional exclusions for specific volume types or tags.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.dlm.LifecyclePolicy("example", {
    description: "tf-acc-basic",
    executionRoleArn: exampleAwsIamRole.arn,
    defaultPolicy: "VOLUME",
    policyDetails: {
        createInterval: 5,
        resourceType: "VOLUME",
        policyLanguage: "SIMPLIFIED",
        exclusions: {
            excludeBootVolumes: false,
            excludeTags: {
                test: "exclude",
            },
            excludeVolumeTypes: ["gp2"],
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.dlm.LifecyclePolicy("example",
    description="tf-acc-basic",
    execution_role_arn=example_aws_iam_role["arn"],
    default_policy="VOLUME",
    policy_details={
        "create_interval": 5,
        "resource_type": "VOLUME",
        "policy_language": "SIMPLIFIED",
        "exclusions": {
            "exclude_boot_volumes": False,
            "exclude_tags": {
                "test": "exclude",
            },
            "exclude_volume_types": ["gp2"],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("tf-acc-basic"),
			ExecutionRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			DefaultPolicy:    pulumi.String("VOLUME"),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				CreateInterval: pulumi.Int(5),
				ResourceType:   pulumi.String("VOLUME"),
				PolicyLanguage: pulumi.String("SIMPLIFIED"),
				Exclusions: &dlm.LifecyclePolicyPolicyDetailsExclusionsArgs{
					ExcludeBootVolumes: pulumi.Bool(false),
					ExcludeTags: pulumi.StringMap{
						"test": pulumi.String("exclude"),
					},
					ExcludeVolumeTypes: pulumi.StringArray{
						pulumi.String("gp2"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "tf-acc-basic",
        ExecutionRoleArn = exampleAwsIamRole.Arn,
        DefaultPolicy = "VOLUME",
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            CreateInterval = 5,
            ResourceType = "VOLUME",
            PolicyLanguage = "SIMPLIFIED",
            Exclusions = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsExclusionsArgs
            {
                ExcludeBootVolumes = false,
                ExcludeTags = 
                {
                    { "test", "exclude" },
                },
                ExcludeVolumeTypes = new[]
                {
                    "gp2",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsExclusionsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LifecyclePolicy("example", LifecyclePolicyArgs.builder()
            .description("tf-acc-basic")
            .executionRoleArn(exampleAwsIamRole.arn())
            .defaultPolicy("VOLUME")
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .createInterval(5)
                .resourceType("VOLUME")
                .policyLanguage("SIMPLIFIED")
                .exclusions(LifecyclePolicyPolicyDetailsExclusionsArgs.builder()
                    .excludeBootVolumes(false)
                    .excludeTags(Map.of("test", "exclude"))
                    .excludeVolumeTypes("gp2")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:dlm:LifecyclePolicy
    properties:
      description: tf-acc-basic
      executionRoleArn: ${exampleAwsIamRole.arn}
      defaultPolicy: VOLUME
      policyDetails:
        createInterval: 5
        resourceType: VOLUME
        policyLanguage: SIMPLIFIED
        exclusions:
          excludeBootVolumes: false
          excludeTags:
            test: exclude
          excludeVolumeTypes:
            - gp2

Setting defaultPolicy to VOLUME and policyLanguage to SIMPLIFIED activates AWS-managed backup logic. The createInterval sets snapshot frequency in hours. The exclusions block lets you skip boot volumes, specific tags, or volume types like gp2.

Copy snapshots to another region for disaster recovery

Organizations with multi-region requirements replicate snapshots to alternate regions with separate retention policies.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// ...other configuration...
const current = aws.getCallerIdentity({});
const key = current.then(current => aws.iam.getPolicyDocument({
    statements: [{
        sid: "Enable IAM User Permissions",
        effect: "Allow",
        principals: [{
            type: "AWS",
            identifiers: [`arn:aws:iam::${current.accountId}:root`],
        }],
        actions: ["kms:*"],
        resources: ["*"],
    }],
}));
const dlmCrossRegionCopyCmk = new aws.kms.Key("dlm_cross_region_copy_cmk", {
    description: "Example Alternate Region KMS Key",
    policy: key.then(key => key.json),
});
const example = new aws.dlm.LifecyclePolicy("example", {
    description: "example DLM lifecycle policy",
    executionRoleArn: dlmLifecycleRole.arn,
    state: "ENABLED",
    policyDetails: {
        resourceTypes: ["VOLUME"],
        schedules: [{
            name: "2 weeks of daily snapshots",
            createRule: {
                interval: 24,
                intervalUnit: "HOURS",
                times: "23:45",
            },
            retainRule: {
                count: 14,
            },
            tagsToAdd: {
                SnapshotCreator: "DLM",
            },
            copyTags: false,
            crossRegionCopyRules: [{
                target: "us-west-2",
                encrypted: true,
                cmkArn: dlmCrossRegionCopyCmk.arn,
                copyTags: true,
                retainRule: {
                    interval: 30,
                    intervalUnit: "DAYS",
                },
            }],
        }],
        targetTags: {
            Snapshot: "true",
        },
    },
});
import pulumi
import pulumi_aws as aws

# ...other configuration...
current = aws.get_caller_identity()
key = aws.iam.get_policy_document(statements=[{
    "sid": "Enable IAM User Permissions",
    "effect": "Allow",
    "principals": [{
        "type": "AWS",
        "identifiers": [f"arn:aws:iam::{current.account_id}:root"],
    }],
    "actions": ["kms:*"],
    "resources": ["*"],
}])
dlm_cross_region_copy_cmk = aws.kms.Key("dlm_cross_region_copy_cmk",
    description="Example Alternate Region KMS Key",
    policy=key.json)
example = aws.dlm.LifecyclePolicy("example",
    description="example DLM lifecycle policy",
    execution_role_arn=dlm_lifecycle_role["arn"],
    state="ENABLED",
    policy_details={
        "resource_types": ["VOLUME"],
        "schedules": [{
            "name": "2 weeks of daily snapshots",
            "create_rule": {
                "interval": 24,
                "interval_unit": "HOURS",
                "times": "23:45",
            },
            "retain_rule": {
                "count": 14,
            },
            "tags_to_add": {
                "SnapshotCreator": "DLM",
            },
            "copy_tags": False,
            "cross_region_copy_rules": [{
                "target": "us-west-2",
                "encrypted": True,
                "cmk_arn": dlm_cross_region_copy_cmk.arn,
                "copy_tags": True,
                "retain_rule": {
                    "interval": 30,
                    "interval_unit": "DAYS",
                },
            }],
        }],
        "target_tags": {
            "Snapshot": "true",
        },
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// ...other configuration...
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		key, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Sid:    pulumi.StringRef("Enable IAM User Permissions"),
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "AWS",
							Identifiers: []string{
								fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
							},
						},
					},
					Actions: []string{
						"kms:*",
					},
					Resources: []string{
						"*",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		dlmCrossRegionCopyCmk, err := kms.NewKey(ctx, "dlm_cross_region_copy_cmk", &kms.KeyArgs{
			Description: pulumi.String("Example Alternate Region KMS Key"),
			Policy:      pulumi.String(key.Json),
		})
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("example DLM lifecycle policy"),
			ExecutionRoleArn: pulumi.Any(dlmLifecycleRole.Arn),
			State:            pulumi.String("ENABLED"),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				ResourceTypes: pulumi.StringArray{
					pulumi.String("VOLUME"),
				},
				Schedules: dlm.LifecyclePolicyPolicyDetailsScheduleArray{
					&dlm.LifecyclePolicyPolicyDetailsScheduleArgs{
						Name: pulumi.String("2 weeks of daily snapshots"),
						CreateRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs{
							Interval:     pulumi.Int(24),
							IntervalUnit: pulumi.String("HOURS"),
							Times:        pulumi.String("23:45"),
						},
						RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs{
							Count: pulumi.Int(14),
						},
						TagsToAdd: pulumi.StringMap{
							"SnapshotCreator": pulumi.String("DLM"),
						},
						CopyTags: pulumi.Bool(false),
						CrossRegionCopyRules: dlm.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArray{
							&dlm.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArgs{
								Target:    pulumi.String("us-west-2"),
								Encrypted: pulumi.Bool(true),
								CmkArn:    dlmCrossRegionCopyCmk.Arn,
								CopyTags:  pulumi.Bool(true),
								RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleRetainRuleArgs{
									Interval:     pulumi.Int(30),
									IntervalUnit: pulumi.String("DAYS"),
								},
							},
						},
					},
				},
				TargetTags: pulumi.StringMap{
					"Snapshot": pulumi.String("true"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    // ...other configuration...
    var current = Aws.GetCallerIdentity.Invoke();

    var key = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Sid = "Enable IAM User Permissions",
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "AWS",
                        Identifiers = new[]
                        {
                            $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                        },
                    },
                },
                Actions = new[]
                {
                    "kms:*",
                },
                Resources = new[]
                {
                    "*",
                },
            },
        },
    });

    var dlmCrossRegionCopyCmk = new Aws.Kms.Key("dlm_cross_region_copy_cmk", new()
    {
        Description = "Example Alternate Region KMS Key",
        Policy = key.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var example = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "example DLM lifecycle policy",
        ExecutionRoleArn = dlmLifecycleRole.Arn,
        State = "ENABLED",
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            ResourceTypes = new[]
            {
                "VOLUME",
            },
            Schedules = new[]
            {
                new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleArgs
                {
                    Name = "2 weeks of daily snapshots",
                    CreateRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs
                    {
                        Interval = 24,
                        IntervalUnit = "HOURS",
                        Times = "23:45",
                    },
                    RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs
                    {
                        Count = 14,
                    },
                    TagsToAdd = 
                    {
                        { "SnapshotCreator", "DLM" },
                    },
                    CopyTags = false,
                    CrossRegionCopyRules = new[]
                    {
                        new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArgs
                        {
                            Target = "us-west-2",
                            Encrypted = true,
                            CmkArn = dlmCrossRegionCopyCmk.Arn,
                            CopyTags = true,
                            RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleRetainRuleArgs
                            {
                                Interval = 30,
                                IntervalUnit = "DAYS",
                            },
                        },
                    },
                },
            },
            TargetTags = 
            {
                { "Snapshot", "true" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        // ...other configuration...
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        final var key = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .sid("Enable IAM User Permissions")
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("AWS")
                    .identifiers(String.format("arn:aws:iam::%s:root", current.accountId()))
                    .build())
                .actions("kms:*")
                .resources("*")
                .build())
            .build());

        var dlmCrossRegionCopyCmk = new Key("dlmCrossRegionCopyCmk", KeyArgs.builder()
            .description("Example Alternate Region KMS Key")
            .policy(key.json())
            .build());

        var example = new LifecyclePolicy("example", LifecyclePolicyArgs.builder()
            .description("example DLM lifecycle policy")
            .executionRoleArn(dlmLifecycleRole.arn())
            .state("ENABLED")
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .resourceTypes("VOLUME")
                .schedules(LifecyclePolicyPolicyDetailsScheduleArgs.builder()
                    .name("2 weeks of daily snapshots")
                    .createRule(LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs.builder()
                        .interval(24)
                        .intervalUnit("HOURS")
                        .times("23:45")
                        .build())
                    .retainRule(LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs.builder()
                        .count(14)
                        .build())
                    .tagsToAdd(Map.of("SnapshotCreator", "DLM"))
                    .copyTags(false)
                    .crossRegionCopyRules(LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArgs.builder()
                        .target("us-west-2")
                        .encrypted(true)
                        .cmkArn(dlmCrossRegionCopyCmk.arn())
                        .copyTags(true)
                        .retainRule(LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleRetainRuleArgs.builder()
                            .interval(30)
                            .intervalUnit("DAYS")
                            .build())
                        .build())
                    .build())
                .targetTags(Map.of("Snapshot", "true"))
                .build())
            .build());

    }
}
resources:
  dlmCrossRegionCopyCmk:
    type: aws:kms:Key
    name: dlm_cross_region_copy_cmk
    properties:
      description: Example Alternate Region KMS Key
      policy: ${key.json}
  example:
    type: aws:dlm:LifecyclePolicy
    properties:
      description: example DLM lifecycle policy
      executionRoleArn: ${dlmLifecycleRole.arn}
      state: ENABLED
      policyDetails:
        resourceTypes:
          - VOLUME
        schedules:
          - name: 2 weeks of daily snapshots
            createRule:
              interval: 24
              intervalUnit: HOURS
              times: 23:45
            retainRule:
              count: 14
            tagsToAdd:
              SnapshotCreator: DLM
            copyTags: false
            crossRegionCopyRules:
              - target: us-west-2
                encrypted: true
                cmkArn: ${dlmCrossRegionCopyCmk.arn}
                copyTags: true
                retainRule:
                  interval: 30
                  intervalUnit: DAYS
        targetTags:
          Snapshot: 'true'
variables:
  # ...other configuration...
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}
  key:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - sid: Enable IAM User Permissions
            effect: Allow
            principals:
              - type: AWS
                identifiers:
                  - arn:aws:iam::${current.accountId}:root
            actions:
              - kms:*
            resources:
              - '*'

The crossRegionCopyRules array defines replication targets. Each rule specifies a target region, encryption settings, and a KMS key ARN for the destination. The retainRule in the copy rule controls how long replicated snapshots persist, independent of the source region’s retention.

Respond to snapshot sharing events automatically

Event-based policies trigger actions when CloudWatch Events occur, such as when snapshots are shared with your account.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const current = aws.getCallerIdentity({});
const exampleLifecyclePolicy = new aws.dlm.LifecyclePolicy("example", {
    description: "tf-acc-basic",
    executionRoleArn: exampleAwsIamRole.arn,
    policyDetails: {
        policyType: "EVENT_BASED_POLICY",
        action: {
            name: "tf-acc-basic",
            crossRegionCopies: [{
                encryptionConfiguration: {},
                retainRule: {
                    interval: 15,
                    intervalUnit: "MONTHS",
                },
                target: "us-east-1",
            }],
        },
        eventSource: {
            type: "MANAGED_CWE",
            parameters: {
                descriptionRegex: "^.*Created for policy: policy-1234567890abcdef0.*$",
                eventType: "shareSnapshot",
                snapshotOwners: [current.then(current => current.accountId)],
            },
        },
    },
});
const example = aws.iam.getPolicy({
    name: "AWSDataLifecycleManagerServiceRole",
});
const exampleRolePolicyAttachment = new aws.iam.RolePolicyAttachment("example", {
    role: exampleAwsIamRole.id,
    policyArn: example.then(example => example.arn),
});
import pulumi
import pulumi_aws as aws

current = aws.get_caller_identity()
example_lifecycle_policy = aws.dlm.LifecyclePolicy("example",
    description="tf-acc-basic",
    execution_role_arn=example_aws_iam_role["arn"],
    policy_details={
        "policy_type": "EVENT_BASED_POLICY",
        "action": {
            "name": "tf-acc-basic",
            "cross_region_copies": [{
                "encryption_configuration": {},
                "retain_rule": {
                    "interval": 15,
                    "interval_unit": "MONTHS",
                },
                "target": "us-east-1",
            }],
        },
        "event_source": {
            "type": "MANAGED_CWE",
            "parameters": {
                "description_regex": "^.*Created for policy: policy-1234567890abcdef0.*$",
                "event_type": "shareSnapshot",
                "snapshot_owners": [current.account_id],
            },
        },
    })
example = aws.iam.get_policy(name="AWSDataLifecycleManagerServiceRole")
example_role_policy_attachment = aws.iam.RolePolicyAttachment("example",
    role=example_aws_iam_role["id"],
    policy_arn=example.arn)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("tf-acc-basic"),
			ExecutionRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				PolicyType: pulumi.String("EVENT_BASED_POLICY"),
				Action: &dlm.LifecyclePolicyPolicyDetailsActionArgs{
					Name: pulumi.String("tf-acc-basic"),
					CrossRegionCopies: dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyArray{
						&dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyArgs{
							EncryptionConfiguration: &dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyEncryptionConfigurationArgs{},
							RetainRule: &dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyRetainRuleArgs{
								Interval:     pulumi.Int(15),
								IntervalUnit: pulumi.String("MONTHS"),
							},
							Target: pulumi.String("us-east-1"),
						},
					},
				},
				EventSource: &dlm.LifecyclePolicyPolicyDetailsEventSourceArgs{
					Type: pulumi.String("MANAGED_CWE"),
					Parameters: &dlm.LifecyclePolicyPolicyDetailsEventSourceParametersArgs{
						DescriptionRegex: pulumi.String("^.*Created for policy: policy-1234567890abcdef0.*$"),
						EventType:        pulumi.String("shareSnapshot"),
						SnapshotOwners: pulumi.StringArray{
							pulumi.String(current.AccountId),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		example, err := iam.LookupPolicy(ctx, &iam.LookupPolicyArgs{
			Name: pulumi.StringRef("AWSDataLifecycleManagerServiceRole"),
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "example", &iam.RolePolicyAttachmentArgs{
			Role:      pulumi.Any(exampleAwsIamRole.Id),
			PolicyArn: pulumi.String(example.Arn),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var exampleLifecyclePolicy = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "tf-acc-basic",
        ExecutionRoleArn = exampleAwsIamRole.Arn,
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            PolicyType = "EVENT_BASED_POLICY",
            Action = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsActionArgs
            {
                Name = "tf-acc-basic",
                CrossRegionCopies = new[]
                {
                    new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsActionCrossRegionCopyArgs
                    {
                        EncryptionConfiguration = null,
                        RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsActionCrossRegionCopyRetainRuleArgs
                        {
                            Interval = 15,
                            IntervalUnit = "MONTHS",
                        },
                        Target = "us-east-1",
                    },
                },
            },
            EventSource = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsEventSourceArgs
            {
                Type = "MANAGED_CWE",
                Parameters = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsEventSourceParametersArgs
                {
                    DescriptionRegex = "^.*Created for policy: policy-1234567890abcdef0.*$",
                    EventType = "shareSnapshot",
                    SnapshotOwners = new[]
                    {
                        current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId),
                    },
                },
            },
        },
    });

    var example = Aws.Iam.GetPolicy.Invoke(new()
    {
        Name = "AWSDataLifecycleManagerServiceRole",
    });

    var exampleRolePolicyAttachment = new Aws.Iam.RolePolicyAttachment("example", new()
    {
        Role = exampleAwsIamRole.Id,
        PolicyArn = example.Apply(getPolicyResult => getPolicyResult.Arn),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsActionArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsEventSourceArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsEventSourceParametersArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var exampleLifecyclePolicy = new LifecyclePolicy("exampleLifecyclePolicy", LifecyclePolicyArgs.builder()
            .description("tf-acc-basic")
            .executionRoleArn(exampleAwsIamRole.arn())
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .policyType("EVENT_BASED_POLICY")
                .action(LifecyclePolicyPolicyDetailsActionArgs.builder()
                    .name("tf-acc-basic")
                    .crossRegionCopies(LifecyclePolicyPolicyDetailsActionCrossRegionCopyArgs.builder()
                        .encryptionConfiguration(LifecyclePolicyPolicyDetailsActionCrossRegionCopyEncryptionConfigurationArgs.builder()
                            .build())
                        .retainRule(LifecyclePolicyPolicyDetailsActionCrossRegionCopyRetainRuleArgs.builder()
                            .interval(15)
                            .intervalUnit("MONTHS")
                            .build())
                        .target("us-east-1")
                        .build())
                    .build())
                .eventSource(LifecyclePolicyPolicyDetailsEventSourceArgs.builder()
                    .type("MANAGED_CWE")
                    .parameters(LifecyclePolicyPolicyDetailsEventSourceParametersArgs.builder()
                        .descriptionRegex("^.*Created for policy: policy-1234567890abcdef0.*$")
                        .eventType("shareSnapshot")
                        .snapshotOwners(current.accountId())
                        .build())
                    .build())
                .build())
            .build());

        final var example = IamFunctions.getPolicy(GetPolicyArgs.builder()
            .name("AWSDataLifecycleManagerServiceRole")
            .build());

        var exampleRolePolicyAttachment = new RolePolicyAttachment("exampleRolePolicyAttachment", RolePolicyAttachmentArgs.builder()
            .role(exampleAwsIamRole.id())
            .policyArn(example.arn())
            .build());

    }
}
resources:
  exampleLifecyclePolicy:
    type: aws:dlm:LifecyclePolicy
    name: example
    properties:
      description: tf-acc-basic
      executionRoleArn: ${exampleAwsIamRole.arn}
      policyDetails:
        policyType: EVENT_BASED_POLICY
        action:
          name: tf-acc-basic
          crossRegionCopies:
            - encryptionConfiguration: {}
              retainRule:
                interval: 15
                intervalUnit: MONTHS
              target: us-east-1
        eventSource:
          type: MANAGED_CWE
          parameters:
            descriptionRegex: '^.*Created for policy: policy-1234567890abcdef0.*$'
            eventType: shareSnapshot
            snapshotOwners:
              - ${current.accountId}
  exampleRolePolicyAttachment:
    type: aws:iam:RolePolicyAttachment
    name: example
    properties:
      role: ${exampleAwsIamRole.id}
      policyArn: ${example.arn}
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}
  example:
    fn::invoke:
      function: aws:iam:getPolicy
      arguments:
        name: AWSDataLifecycleManagerServiceRole

Setting policyType to EVENT_BASED_POLICY shifts from schedules to event triggers. The eventSource block defines which CloudWatch Events to monitor; here, it watches for shareSnapshot events matching a description pattern. The action block specifies what to do: copy the shared snapshot to us-east-1 with 15-month retention.

Run application-consistent Windows VSS backups

Windows workloads require VSS coordination to ensure application-consistent snapshots of running instances.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const test = aws.iam.getPolicy({
    name: "AWSDataLifecycleManagerSSMFullAccess",
});
const example = new aws.iam.RolePolicyAttachment("example", {
    role: testAwsIamRole.id,
    policyArn: exampleAwsIamPolicy.arn,
});
const exampleLifecyclePolicy = new aws.dlm.LifecyclePolicy("example", {
    description: "tf-acc-basic",
    executionRoleArn: exampleAwsIamRole.arn,
    policyDetails: {
        resourceTypes: ["INSTANCE"],
        schedules: [{
            name: "Windows VSS",
            createRule: {
                interval: 12,
                scripts: {
                    executeOperationOnScriptFailure: false,
                    executionHandler: "AWS_VSS_BACKUP",
                    maximumRetryCount: 2,
                },
            },
            retainRule: {
                count: 10,
            },
        }],
        targetTags: {
            tag1: "Windows",
        },
    },
});
import pulumi
import pulumi_aws as aws

test = aws.iam.get_policy(name="AWSDataLifecycleManagerSSMFullAccess")
example = aws.iam.RolePolicyAttachment("example",
    role=test_aws_iam_role["id"],
    policy_arn=example_aws_iam_policy["arn"])
example_lifecycle_policy = aws.dlm.LifecyclePolicy("example",
    description="tf-acc-basic",
    execution_role_arn=example_aws_iam_role["arn"],
    policy_details={
        "resource_types": ["INSTANCE"],
        "schedules": [{
            "name": "Windows VSS",
            "create_rule": {
                "interval": 12,
                "scripts": {
                    "execute_operation_on_script_failure": False,
                    "execution_handler": "AWS_VSS_BACKUP",
                    "maximum_retry_count": 2,
                },
            },
            "retain_rule": {
                "count": 10,
            },
        }],
        "target_tags": {
            "tag1": "Windows",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := iam.LookupPolicy(ctx, &iam.LookupPolicyArgs{
			Name: pulumi.StringRef("AWSDataLifecycleManagerSSMFullAccess"),
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "example", &iam.RolePolicyAttachmentArgs{
			Role:      pulumi.Any(testAwsIamRole.Id),
			PolicyArn: pulumi.Any(exampleAwsIamPolicy.Arn),
		})
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("tf-acc-basic"),
			ExecutionRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				ResourceTypes: pulumi.StringArray{
					pulumi.String("INSTANCE"),
				},
				Schedules: dlm.LifecyclePolicyPolicyDetailsScheduleArray{
					&dlm.LifecyclePolicyPolicyDetailsScheduleArgs{
						Name: pulumi.String("Windows VSS"),
						CreateRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs{
							Interval: pulumi.Int(12),
							Scripts: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleScriptsArgs{
								ExecuteOperationOnScriptFailure: pulumi.Bool(false),
								ExecutionHandler:                pulumi.String("AWS_VSS_BACKUP"),
								MaximumRetryCount:               pulumi.Int(2),
							},
						},
						RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs{
							Count: pulumi.Int(10),
						},
					},
				},
				TargetTags: pulumi.StringMap{
					"tag1": pulumi.String("Windows"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var test = Aws.Iam.GetPolicy.Invoke(new()
    {
        Name = "AWSDataLifecycleManagerSSMFullAccess",
    });

    var example = new Aws.Iam.RolePolicyAttachment("example", new()
    {
        Role = testAwsIamRole.Id,
        PolicyArn = exampleAwsIamPolicy.Arn,
    });

    var exampleLifecyclePolicy = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "tf-acc-basic",
        ExecutionRoleArn = exampleAwsIamRole.Arn,
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            ResourceTypes = new[]
            {
                "INSTANCE",
            },
            Schedules = new[]
            {
                new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleArgs
                {
                    Name = "Windows VSS",
                    CreateRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs
                    {
                        Interval = 12,
                        Scripts = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleScriptsArgs
                        {
                            ExecuteOperationOnScriptFailure = false,
                            ExecutionHandler = "AWS_VSS_BACKUP",
                            MaximumRetryCount = 2,
                        },
                    },
                    RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs
                    {
                        Count = 10,
                    },
                },
            },
            TargetTags = 
            {
                { "tag1", "Windows" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var test = IamFunctions.getPolicy(GetPolicyArgs.builder()
            .name("AWSDataLifecycleManagerSSMFullAccess")
            .build());

        var example = new RolePolicyAttachment("example", RolePolicyAttachmentArgs.builder()
            .role(testAwsIamRole.id())
            .policyArn(exampleAwsIamPolicy.arn())
            .build());

        var exampleLifecyclePolicy = new LifecyclePolicy("exampleLifecyclePolicy", LifecyclePolicyArgs.builder()
            .description("tf-acc-basic")
            .executionRoleArn(exampleAwsIamRole.arn())
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .resourceTypes("INSTANCE")
                .schedules(LifecyclePolicyPolicyDetailsScheduleArgs.builder()
                    .name("Windows VSS")
                    .createRule(LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs.builder()
                        .interval(12)
                        .scripts(LifecyclePolicyPolicyDetailsScheduleCreateRuleScriptsArgs.builder()
                            .executeOperationOnScriptFailure(false)
                            .executionHandler("AWS_VSS_BACKUP")
                            .maximumRetryCount(2)
                            .build())
                        .build())
                    .retainRule(LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs.builder()
                        .count(10)
                        .build())
                    .build())
                .targetTags(Map.of("tag1", "Windows"))
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:iam:RolePolicyAttachment
    properties:
      role: ${testAwsIamRole.id}
      policyArn: ${exampleAwsIamPolicy.arn}
  exampleLifecyclePolicy:
    type: aws:dlm:LifecyclePolicy
    name: example
    properties:
      description: tf-acc-basic
      executionRoleArn: ${exampleAwsIamRole.arn}
      policyDetails:
        resourceTypes:
          - INSTANCE
        schedules:
          - name: Windows VSS
            createRule:
              interval: 12
              scripts:
                executeOperationOnScriptFailure: false
                executionHandler: AWS_VSS_BACKUP
                maximumRetryCount: 2
            retainRule:
              count: 10
        targetTags:
          tag1: Windows
variables:
  test:
    fn::invoke:
      function: aws:iam:getPolicy
      arguments:
        name: AWSDataLifecycleManagerSSMFullAccess

Setting resourceTypes to INSTANCE targets EC2 instances instead of volumes. The scripts block configures VSS behavior: executionHandler specifies AWS_VSS_BACKUP, and executeOperationOnScriptFailure controls whether to proceed if VSS fails. This ensures database and application state is flushed before the snapshot.

Beyond these examples

These snippets focus on specific DLM policy features: schedule-based and event-based policies, cross-region replication and encryption, and application-consistent snapshots with VSS. They’re intentionally minimal rather than full backup solutions.

The examples may reference pre-existing infrastructure such as IAM execution roles with DLM trust policy, KMS keys for cross-region encryption, and EBS volumes or EC2 instances with target tags. They focus on configuring the policy rather than provisioning the surrounding infrastructure.

To keep things focused, common DLM patterns are omitted, including:

  • Fast snapshot restore configuration (fastRestoreRule)
  • Snapshot sharing with other accounts (shareRules)
  • Archive tier lifecycle transitions
  • Variable schedule intervals and cron expressions

These omissions are intentional: the goal is to illustrate how each DLM feature is wired, not provide drop-in backup modules. See the DLM Lifecycle Policy resource reference for all available configuration options.

Let's configure AWS Data Lifecycle Manager Policies

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

IAM & Permissions
What IAM permissions does the DLM execution role need?
The execution role needs EC2 permissions: ec2:CreateSnapshot, ec2:CreateSnapshots, ec2:DeleteSnapshot, ec2:DescribeInstances, ec2:DescribeVolumes, ec2:DescribeSnapshots on all resources, plus ec2:CreateTags on snapshot resources. The role must also allow dlm.amazonaws.com to assume it via sts:AssumeRole.
What managed policies are available for DLM?
AWS provides AWSDataLifecycleManagerServiceRole for event-based policies and AWSDataLifecycleManagerSSMFullAccess for policies using pre/post scripts with Windows VSS backups.
Policy Types & Configuration
What's the difference between default and custom lifecycle policies?
Default policies use defaultPolicy set to VOLUME or INSTANCE with simplified configuration (policyLanguage: SIMPLIFIED). Custom policies use full policyDetails with schedules, retention rules, and resource targeting via targetTags.
What are event-based policies used for?
Event-based policies (policyType: EVENT_BASED_POLICY) trigger on CloudWatch Events like snapshot sharing, rather than running on a schedule. They use eventSource configuration instead of schedules.
How does DLM target which resources to snapshot?
Use targetTags in policyDetails to specify key-value pairs. DLM creates snapshots only for volumes or instances matching those tags.
Advanced Features
How do I set up cross-region snapshot copies?
Configure crossRegionCopyRules in the schedule with a target region. For encryption, create a KMS key in the target region and specify its ARN in cmkArn. You can set independent retention rules for cross-region copies.
Can I use DLM with Windows VSS backups?
Yes, set resourceTypes to INSTANCE and configure scripts in the createRule with executionHandler: AWS_VSS_BACKUP. The execution role needs the AWSDataLifecycleManagerSSMFullAccess managed policy.

Using a different cloud?

Explore storage guides for other cloud providers: