Detect configuration drift between deployed resources and CloudFormation templates.
Initiates drift detection for an entire stack to identify configuration changes.
/**
* Initiates drift detection for all resources in a stack
* Compares actual resource configuration with template definitions
*/
class DetectStackDriftCommand {
constructor(input: DetectStackDriftCommandInput);
}
interface DetectStackDriftCommandInput {
/** Name or ARN of the stack to check for drift */
StackName: string;
/** Specific logical resource IDs to check (optional) */
LogicalResourceIds?: string[];
}
interface DetectStackDriftCommandOutput {
/** Unique identifier for the drift detection operation */
StackDriftDetectionId: string;
}Usage Examples:
import {
CloudFormationClient,
DetectStackDriftCommand,
DescribeStackDriftDetectionStatusCommand
} from "@aws-sdk/client-cloudformation";
const client = new CloudFormationClient({ region: "us-east-1" });
// Detect drift for entire stack
const detectCommand = new DetectStackDriftCommand({
StackName: "my-production-stack"
});
const detection = await client.send(detectCommand);
console.log("Drift detection ID:", detection.StackDriftDetectionId);
// Detect drift for specific resources only
const specificDetectCommand = new DetectStackDriftCommand({
StackName: "my-stack",
LogicalResourceIds: ["MyDatabase", "MyBucket", "MySecurityGroup"]
});
const specificDetection = await client.send(specificDetectCommand);Detects drift for a specific resource within a stack.
/**
* Detects configuration drift for a specific resource
* Returns immediate drift status for the resource
*/
class DetectStackResourceDriftCommand {
constructor(input: DetectStackResourceDriftCommandInput);
}
interface DetectStackResourceDriftCommandInput {
/** Name or ARN of the stack containing the resource */
StackName: string;
/** Logical ID of the resource to check */
LogicalResourceId: string;
}
interface DetectStackResourceDriftCommandOutput {
/** Drift information for the resource */
StackResourceDrift: StackResourceDrift;
}
interface StackResourceDrift {
/** Stack ID */
StackId: string;
/** Logical resource ID */
LogicalResourceId: string;
/** Physical resource ID */
PhysicalResourceId?: string;
/** Resource type */
ResourceType: string;
/** Expected properties from template */
ExpectedProperties?: string;
/** Actual properties from AWS */
ActualProperties?: string;
/** Property differences */
PropertyDifferences?: PropertyDifference[];
/** Drift status */
StackResourceDriftStatus: StackResourceDriftStatus;
/** Timestamp of drift check */
Timestamp: Date;
/** Module information */
ModuleInfo?: ModuleInfo;
}
interface PropertyDifference {
/** Property path */
PropertyPath: string;
/** Expected value */
ExpectedValue: string;
/** Actual value */
ActualValue: string;
/** Difference type */
DifferenceType: DifferenceType;
}
interface ModuleInfo {
/** Type hierarchy */
TypeHierarchy?: string;
/** Logical ID hierarchy */
LogicalIdHierarchy?: string;
}
type StackResourceDriftStatus =
| "IN_SYNC"
| "MODIFIED"
| "DELETED"
| "NOT_CHECKED";
type DifferenceType =
| "ADD"
| "REMOVE"
| "NOT_EQUAL";Retrieves the status and results of a drift detection operation.
/**
* Retrieves drift detection status and summary results
* Shows overall drift status and resource counts
*/
class DescribeStackDriftDetectionStatusCommand {
constructor(input: DescribeStackDriftDetectionStatusCommandInput);
}
interface DescribeStackDriftDetectionStatusCommandInput {
/** Drift detection ID from DetectStackDrift operation */
StackDriftDetectionId: string;
}
interface DescribeStackDriftDetectionStatusCommandOutput {
/** Stack ID */
StackId: string;
/** Drift detection ID */
StackDriftDetectionId: string;
/** Overall drift status for the stack */
StackDriftStatus?: StackDriftStatus;
/** Detection operation status */
DetectionStatus: StackDriftDetectionStatus;
/** Status reason */
DetectionStatusReason?: string;
/** Number of resources checked */
DriftedStackResourceCount?: number;
/** Detection start timestamp */
Timestamp: Date;
}
type StackDriftStatus =
| "DRIFTED"
| "IN_SYNC"
| "UNKNOWN"
| "NOT_CHECKED";
type StackDriftDetectionStatus =
| "DETECTION_IN_PROGRESS"
| "DETECTION_FAILED"
| "DETECTION_COMPLETE";Usage Examples:
// Monitor drift detection progress
async function checkDriftStatus(detectionId: string) {
const statusCommand = new DescribeStackDriftDetectionStatusCommand({
StackDriftDetectionId: detectionId
});
const status = await client.send(statusCommand);
if (status.DetectionStatus === "DETECTION_COMPLETE") {
console.log("Drift detection completed");
console.log("Stack drift status:", status.StackDriftStatus);
console.log("Drifted resources:", status.DriftedStackResourceCount);
return status;
} else if (status.DetectionStatus === "DETECTION_FAILED") {
console.error("Drift detection failed:", status.DetectionStatusReason);
throw new Error("Drift detection failed");
} else {
console.log("Drift detection in progress...");
// Poll again after delay
await new Promise(resolve => setTimeout(resolve, 5000));
return checkDriftStatus(detectionId);
}
}
// Check drift for specific resource
const resourceDriftCommand = new DetectStackResourceDriftCommand({
StackName: "my-stack",
LogicalResourceId: "MyS3Bucket"
});
const resourceDrift = await client.send(resourceDriftCommand);
console.log("Resource drift status:", resourceDrift.StackResourceDrift.StackResourceDriftStatus);
if (resourceDrift.StackResourceDrift.PropertyDifferences) {
console.log("Property differences:");
resourceDrift.StackResourceDrift.PropertyDifferences.forEach(diff => {
console.log(`${diff.PropertyPath}: expected ${diff.ExpectedValue}, actual ${diff.ActualValue}`);
});
}Retrieves drift information for resources in a stack with pagination support.
/**
* Retrieves detailed drift information for stack resources
* Supports filtering and pagination for large stacks
*/
class DescribeStackResourceDriftsCommand {
constructor(input: DescribeStackResourceDriftsCommandInput);
}
interface DescribeStackResourceDriftsCommandInput {
/** Name or ARN of the stack */
StackName: string;
/** Filter by drift status */
StackResourceDriftStatusFilters?: StackResourceDriftStatus[];
/** Token for pagination */
NextToken?: string;
/** Maximum number of results */
MaxResults?: number;
}
interface DescribeStackResourceDriftsCommandOutput {
/** Resource drift details */
StackResourceDrifts: StackResourceDrift[];
/** Pagination token */
NextToken?: string;
}Initiates drift detection for a stack set to check all instances.
/**
* Initiates drift detection for all stack instances in a stack set
* Checks configuration drift across multiple accounts and regions
*/
class DetectStackSetDriftCommand {
constructor(input: DetectStackSetDriftCommandInput);
}
interface DetectStackSetDriftCommandInput {
/** Name of the stack set */
StackSetName: string;
/** Operation preferences for drift detection */
OperationPreferences?: StackSetOperationPreferences;
/** Operation ID for idempotency */
OperationId?: string;
/** Call context */
CallAs?: CallAs;
}
interface DetectStackSetDriftCommandOutput {
/** Operation ID for the drift detection */
OperationId?: string;
}
interface StackSetOperationPreferences {
/** Region concurrency type */
RegionConcurrencyType?: RegionConcurrencyType;
/** Region order */
RegionOrder?: string[];
/** Failure tolerance count */
FailureToleranceCount?: number;
/** Failure tolerance percentage */
FailureTolerancePercentage?: number;
/** Maximum concurrent count */
MaxConcurrentCount?: number;
/** Maximum concurrent percentage */
MaxConcurrentPercentage?: number;
/** Concurrency mode */
ConcurrencyMode?: ConcurrencyMode;
}
type RegionConcurrencyType =
| "SEQUENTIAL"
| "PARALLEL";
type ConcurrencyMode =
| "STRICT_FAILURE_TOLERANCE"
| "SOFT_FAILURE_TOLERANCE";
type CallAs =
| "SELF"
| "DELEGATED_ADMIN";Lists resource drifts for stack instances in a stack set.
/**
* Lists resource drift information for stack set instances
* Provides drift details across multiple accounts and regions
*/
class ListStackInstanceResourceDriftsCommand {
constructor(input: ListStackInstanceResourceDriftsCommandInput);
}
interface ListStackInstanceResourceDriftsCommandInput {
/** Stack set name */
StackSetName: string;
/** Stack instance account */
StackInstanceAccount: string;
/** Stack instance region */
StackInstanceRegion: string;
/** Operation ID that performed drift detection */
OperationId: string;
/** Token for pagination */
NextToken?: string;
/** Maximum results */
MaxResults?: number;
/** Filter by drift status */
StackInstanceResourceDriftStatuses?: StackResourceDriftStatus[];
/** Call context */
CallAs?: CallAs;
}
interface ListStackInstanceResourceDriftsCommandOutput {
/** Resource drift summaries */
Summaries?: StackInstanceResourceDriftSummary[];
/** Pagination token */
NextToken?: string;
}
interface StackInstanceResourceDriftSummary {
/** Stack ID */
StackId?: string;
/** Logical resource ID */
LogicalResourceId?: string;
/** Physical resource ID */
PhysicalResourceId?: string;
/** Physical resource ID context */
PhysicalResourceIdContext?: PhysicalResourceIdContextKeyValuePair[];
/** Resource type */
ResourceType?: string;
/** Property differences */
PropertyDifferences?: PropertyDifference[];
/** Drift status */
StackResourceDriftStatus?: StackResourceDriftStatus;
/** Timestamp */
Timestamp?: Date;
}
interface PhysicalResourceIdContextKeyValuePair {
/** Key */
Key?: string;
/** Value */
Value?: string;
}Usage Examples:
// Detect drift for stack set
const stackSetDriftCommand = new DetectStackSetDriftCommand({
StackSetName: "my-cross-account-stack-set",
OperationPreferences: {
RegionConcurrencyType: "PARALLEL",
MaxConcurrentPercentage: 25,
FailureTolerancePercentage: 10
}
});
const stackSetOperation = await client.send(stackSetDriftCommand);
console.log("Stack set drift operation:", stackSetOperation.OperationId);
// List resource drifts for specific stack instance
const instanceDriftsCommand = new ListStackInstanceResourceDriftsCommand({
StackSetName: "my-cross-account-stack-set",
StackInstanceAccount: "123456789012",
StackInstanceRegion: "us-east-1",
OperationId: stackSetOperation.OperationId!
});
const instanceDrifts = await client.send(instanceDriftsCommand);
console.log("Instance resource drifts:", instanceDrifts.Summaries);
// Get detailed drift information for all resources in a stack
const allDriftsCommand = new DescribeStackResourceDriftsCommand({
StackName: "my-stack",
StackResourceDriftStatusFilters: ["MODIFIED", "DELETED"]
});
const allDrifts = await client.send(allDriftsCommand);
allDrifts.StackResourceDrifts.forEach(drift => {
console.log(`Resource ${drift.LogicalResourceId}: ${drift.StackResourceDriftStatus}`);
if (drift.PropertyDifferences) {
drift.PropertyDifferences.forEach(diff => {
console.log(` ${diff.PropertyPath}: ${diff.DifferenceType}`);
});
}
});async function analyzeDrift(stackName: string) {
// Start drift detection
const detectCommand = new DetectStackDriftCommand({ StackName: stackName });
const detection = await client.send(detectCommand);
// Wait for completion
const status = await checkDriftStatus(detection.StackDriftDetectionId);
if (status.StackDriftStatus === "DRIFTED") {
// Get detailed drift information
const driftsCommand = new DescribeStackResourceDriftsCommand({
StackName: stackName,
StackResourceDriftStatusFilters: ["MODIFIED", "DELETED"]
});
const drifts = await client.send(driftsCommand);
// Analyze each drifted resource
for (const drift of drifts.StackResourceDrifts) {
console.log(`\nResource: ${drift.LogicalResourceId} (${drift.ResourceType})`);
console.log(`Status: ${drift.StackResourceDriftStatus}`);
if (drift.PropertyDifferences) {
console.log("Property changes:");
drift.PropertyDifferences.forEach(diff => {
console.log(` ${diff.PropertyPath}:`);
console.log(` Expected: ${diff.ExpectedValue}`);
console.log(` Actual: ${diff.ActualValue}`);
console.log(` Change: ${diff.DifferenceType}`);
});
}
}
return drifts.StackResourceDrifts;
}
return [];
}class DriftMonitor {
private client: CloudFormationClient;
private monitoredStacks: Set<string> = new Set();
constructor(client: CloudFormationClient) {
this.client = client;
}
async monitorStack(stackName: string, intervalMinutes: number = 60) {
if (this.monitoredStacks.has(stackName)) {
return;
}
this.monitoredStacks.add(stackName);
const monitor = async () => {
try {
console.log(`Checking drift for stack: ${stackName}`);
const detection = await this.client.send(
new DetectStackDriftCommand({ StackName: stackName })
);
const status = await checkDriftStatus(detection.StackDriftDetectionId);
if (status.StackDriftStatus === "DRIFTED") {
await this.handleDriftDetected(stackName, status);
} else {
console.log(`Stack ${stackName} is in sync`);
}
} catch (error) {
console.error(`Error monitoring stack ${stackName}:`, error);
}
// Schedule next check
setTimeout(monitor, intervalMinutes * 60 * 1000);
};
// Start monitoring
monitor();
}
private async handleDriftDetected(
stackName: string,
status: DescribeStackDriftDetectionStatusCommandOutput
) {
console.log(`ALERT: Drift detected in stack ${stackName}`);
console.log(`Drifted resources: ${status.DriftedStackResourceCount}`);
// Get detailed drift information
const drifts = await this.client.send(
new DescribeStackResourceDriftsCommand({
StackName: stackName,
StackResourceDriftStatusFilters: ["MODIFIED", "DELETED"]
})
);
// Send notifications or trigger remediation
await this.sendDriftNotification(stackName, drifts.StackResourceDrifts);
}
private async sendDriftNotification(
stackName: string,
drifts: StackResourceDrift[]
) {
// Implementation would send notifications via SNS, email, etc.
console.log(`Sending drift notification for stack: ${stackName}`);
drifts.forEach(drift => {
console.log(`- ${drift.LogicalResourceId}: ${drift.StackResourceDriftStatus}`);
});
}
}
// Usage
const monitor = new DriftMonitor(client);
await monitor.monitorStack("production-infrastructure", 30); // Check every 30 minutesinterface StackResourceDrift {
StackId: string;
LogicalResourceId: string;
PhysicalResourceId?: string;
ResourceType: string;
ExpectedProperties?: string;
ActualProperties?: string;
PropertyDifferences?: PropertyDifference[];
StackResourceDriftStatus: StackResourceDriftStatus;
Timestamp: Date;
ModuleInfo?: ModuleInfo;
}
interface PropertyDifference {
PropertyPath: string;
ExpectedValue: string;
ActualValue: string;
DifferenceType: DifferenceType;
}
type StackResourceDriftStatus =
| "IN_SYNC"
| "MODIFIED"
| "DELETED"
| "NOT_CHECKED";
type StackDriftStatus =
| "DRIFTED"
| "IN_SYNC"
| "UNKNOWN"
| "NOT_CHECKED";
type DifferenceType =
| "ADD"
| "REMOVE"
| "NOT_EQUAL";