SNS data protection provides policy-based controls for protecting sensitive data in messages, including detection, auditing, and blocking of personally identifiable information (PII) and other sensitive content.
Creates or updates a data protection policy for an SNS topic to control how sensitive data is handled.
/**
* Sets a data protection policy for an Amazon SNS topic
* Enables automatic detection and handling of sensitive data in messages
*/
class PutDataProtectionPolicyCommand {
constructor(input: PutDataProtectionPolicyInput);
}
interface PutDataProtectionPolicyInput {
/** ARN of the resource (topic) to apply the policy to */
ResourceArn: string;
/** JSON data protection policy document */
DataProtectionPolicy: string;
}
interface PutDataProtectionPolicyResponse {
/** Response metadata */
ResponseMetadata?: any;
}Usage Examples:
import { SNSClient, PutDataProtectionPolicyCommand } from "@aws-sdk/client-sns";
const client = new SNSClient({ region: "us-east-1" });
// Basic PII detection and audit policy
const basicPolicy = {
Version: "2021-06-01",
Statement: [
{
Sid: "AuditPII",
DataIdentifier: [
"arn:aws:dataprotection::aws:data-identifier/EmailAddress",
"arn:aws:dataprotection::aws:data-identifier/CreditCardNumber",
"arn:aws:dataprotection::aws:data-identifier/SSN"
],
Operation: {
Audit: {
SampleRate: 100,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: "sns-data-protection-audit"
}
}
}
}
}
]
};
await client.send(new PutDataProtectionPolicyCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:SensitiveDataTopic",
DataProtectionPolicy: JSON.stringify(basicPolicy)
}));
// Policy with message blocking for sensitive data
const blockingPolicy = {
Version: "2021-06-01",
Statement: [
{
Sid: "BlockCreditCards",
DataIdentifier: [
"arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"
],
Operation: {
Deny: {}
}
},
{
Sid: "AuditEmailAndSSN",
DataIdentifier: [
"arn:aws:dataprotection::aws:data-identifier/EmailAddress",
"arn:aws:dataprotection::aws:data-identifier/SSN"
],
Operation: {
Audit: {
SampleRate: 50,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: "sns-pii-audit"
},
S3: {
Bucket: "my-data-protection-logs",
Prefix: "sns-audit/"
}
}
}
}
}
]
};
await client.send(new PutDataProtectionPolicyCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:UserDataTopic",
DataProtectionPolicy: JSON.stringify(blockingPolicy)
}));Retrieves the current data protection policy for an SNS topic.
/**
* Returns the data protection policy for an Amazon SNS topic
* Shows current settings for sensitive data handling
*/
class GetDataProtectionPolicyCommand {
constructor(input: GetDataProtectionPolicyInput);
}
interface GetDataProtectionPolicyInput {
/** ARN of the resource (topic) */
ResourceArn: string;
}
interface GetDataProtectionPolicyResponse {
/** JSON data protection policy document */
DataProtectionPolicy?: string;
}Usage Example:
const policyResult = await client.send(new GetDataProtectionPolicyCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:SensitiveDataTopic"
}));
if (policyResult.DataProtectionPolicy) {
const policy = JSON.parse(policyResult.DataProtectionPolicy);
console.log("Data Protection Policy:");
console.log(JSON.stringify(policy, null, 2));
policy.Statement?.forEach((statement: any, index: number) => {
console.log(`\nStatement ${index + 1} (${statement.Sid}):`);
console.log(` Data Identifiers: ${statement.DataIdentifier?.join(', ')}`);
console.log(` Operation: ${Object.keys(statement.Operation)[0]}`);
});
} else {
console.log("No data protection policy configured");
}A data protection policy consists of several key components:
interface DataProtectionPolicy {
Version: "2021-06-01";
Statement: DataProtectionStatement[];
}
interface DataProtectionStatement {
Sid: string;
DataIdentifier: string[];
Operation: DataProtectionOperation;
Principal?: string[];
Condition?: any;
}
interface DataProtectionOperation {
Audit?: AuditOperation;
Deny?: DenyOperation;
Deidentify?: DeidentifyOperation;
}
interface AuditOperation {
SampleRate: number; // 0-100
FindingsDestination: FindingsDestination;
}
interface DenyOperation {} // Empty object for blocking
interface DeidentifyOperation {
MaskConfig?: MaskConfig;
RedactConfig?: RedactConfig;
}
interface FindingsDestination {
CloudWatchLogs?: {
LogGroup: string;
};
S3?: {
Bucket: string;
Prefix?: string;
};
}AWS provides built-in data identifiers for common sensitive data types:
const DataIdentifiers = {
// Personal Information
EMAIL: "arn:aws:dataprotection::aws:data-identifier/EmailAddress",
PHONE_US: "arn:aws:dataprotection::aws:data-identifier/PhoneNumber-US",
PHONE_UK: "arn:aws:dataprotection::aws:data-identifier/PhoneNumber-UK",
SSN: "arn:aws:dataprotection::aws:data-identifier/SSN",
// Financial Information
CREDIT_CARD: "arn:aws:dataprotection::aws:data-identifier/CreditCardNumber",
BANK_ACCOUNT_US: "arn:aws:dataprotection::aws:data-identifier/BankAccountNumber-US",
BANK_ROUTING_US: "arn:aws:dataprotection::aws:data-identifier/BankRoutingNumber-US",
// Government IDs
PASSPORT_US: "arn:aws:dataprotection::aws:data-identifier/PassportNumber-US",
DRIVERS_LICENSE_US: "arn:aws:dataprotection::aws:data-identifier/DriversLicense-US",
// Healthcare
DRUG_ENFORCEMENT_NUMBER: "arn:aws:dataprotection::aws:data-identifier/DrugEnforcementAgencyNumber",
// Address Information
ADDRESS: "arn:aws:dataprotection::aws:data-identifier/Address",
ZIP_CODE: "arn:aws:dataprotection::aws:data-identifier/ZipCode-US",
// International
PASSPORT_CA: "arn:aws:dataprotection::aws:data-identifier/PassportNumber-CA",
INSURANCE_NUMBER_CA: "arn:aws:dataprotection::aws:data-identifier/InsuranceNumber-CA",
HEALTH_NUMBER_CA: "arn:aws:dataprotection::aws:data-identifier/HealthNumber-CA"
};Implement comprehensive protection for various types of PII:
const createComprehensivePIIPolicy = (
auditLogGroup: string,
s3Bucket?: string
) => {
const policy = {
Version: "2021-06-01",
Statement: [
{
Sid: "BlockHighRiskPII",
DataIdentifier: [
DataIdentifiers.CREDIT_CARD,
DataIdentifiers.SSN,
DataIdentifiers.BANK_ACCOUNT_US,
DataIdentifiers.PASSPORT_US
],
Operation: {
Deny: {}
}
},
{
Sid: "AuditMediumRiskPII",
DataIdentifier: [
DataIdentifiers.EMAIL,
DataIdentifiers.PHONE_US,
DataIdentifiers.DRIVERS_LICENSE_US,
DataIdentifiers.ADDRESS
],
Operation: {
Audit: {
SampleRate: 100,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: auditLogGroup
},
...(s3Bucket && {
S3: {
Bucket: s3Bucket,
Prefix: "pii-audit/"
}
})
}
}
}
}
]
};
return JSON.stringify(policy);
};
// Apply comprehensive PII protection
await client.send(new PutDataProtectionPolicyCommand({
ResourceArn: "arn:aws:sns:us-east-1:123456789012:CustomerDataTopic",
DataProtectionPolicy: createComprehensivePIIPolicy(
"customer-data-audit",
"my-compliance-logs"
)
}));Create policies tailored to specific industries:
// Healthcare-specific data protection
const createHIPAACompliantPolicy = () => {
return JSON.stringify({
Version: "2021-06-01",
Statement: [
{
Sid: "BlockAllPHI",
DataIdentifier: [
DataIdentifiers.SSN,
DataIdentifiers.PHONE_US,
DataIdentifiers.EMAIL,
DataIdentifiers.ADDRESS,
DataIdentifiers.DRUG_ENFORCEMENT_NUMBER
],
Operation: {
Deny: {}
}
},
{
Sid: "AuditPotentialPHI",
DataIdentifier: [
DataIdentifiers.ZIP_CODE
],
Operation: {
Audit: {
SampleRate: 100,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: "hipaa-compliance-audit"
}
}
}
}
}
]
});
};
// Financial services data protection
const createPCICompliantPolicy = () => {
return JSON.stringify({
Version: "2021-06-01",
Statement: [
{
Sid: "BlockPaymentData",
DataIdentifier: [
DataIdentifiers.CREDIT_CARD,
DataIdentifiers.BANK_ACCOUNT_US,
DataIdentifiers.BANK_ROUTING_US
],
Operation: {
Deny: {}
}
},
{
Sid: "AuditCustomerData",
DataIdentifier: [
DataIdentifiers.EMAIL,
DataIdentifiers.PHONE_US,
DataIdentifiers.SSN
],
Operation: {
Audit: {
SampleRate: 25,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: "pci-compliance-audit"
},
S3: {
Bucket: "financial-compliance-logs",
Prefix: "pci-audit/"
}
}
}
}
}
]
});
};Apply different protection levels based on environment:
const applyEnvironmentSpecificDataProtection = async (
topicArn: string,
environment: string
) => {
let policy: string;
switch (environment.toLowerCase()) {
case 'production':
// Strict protection in production
policy = JSON.stringify({
Version: "2021-06-01",
Statement: [{
Sid: "ProductionPIIProtection",
DataIdentifier: [
DataIdentifiers.CREDIT_CARD,
DataIdentifiers.SSN,
DataIdentifiers.EMAIL,
DataIdentifiers.PHONE_US
],
Operation: {
Deny: {}
}
}]
});
break;
case 'staging':
// Audit but allow in staging
policy = JSON.stringify({
Version: "2021-06-01",
Statement: [{
Sid: "StagingPIIAudit",
DataIdentifier: [
DataIdentifiers.CREDIT_CARD,
DataIdentifiers.SSN,
DataIdentifiers.EMAIL,
DataIdentifiers.PHONE_US
],
Operation: {
Audit: {
SampleRate: 100,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: `staging-data-protection-${Date.now()}`
}
}
}
}
}]
});
break;
case 'development':
// Minimal protection in development
policy = JSON.stringify({
Version: "2021-06-01",
Statement: [{
Sid: "DevPIIAudit",
DataIdentifier: [
DataIdentifiers.CREDIT_CARD,
DataIdentifiers.SSN
],
Operation: {
Audit: {
SampleRate: 10,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: "dev-data-protection"
}
}
}
}
}]
});
break;
default:
throw new Error(`Unsupported environment: ${environment}`);
}
await client.send(new PutDataProtectionPolicyCommand({
ResourceArn: topicArn,
DataProtectionPolicy: policy
}));
console.log(`Applied ${environment} data protection policy to ${topicArn}`);
};Manage data protection policies lifecycle:
const updateDataProtectionPolicy = async (
topicArn: string,
updates: {
addIdentifiers?: string[];
removeIdentifiers?: string[];
updateSampleRate?: number;
}
) => {
// Get current policy
const current = await client.send(new GetDataProtectionPolicyCommand({
ResourceArn: topicArn
}));
if (!current.DataProtectionPolicy) {
throw new Error("No existing data protection policy found");
}
const policy = JSON.parse(current.DataProtectionPolicy);
// Update the policy
for (const statement of policy.Statement) {
if (updates.addIdentifiers) {
statement.DataIdentifier = [
...new Set([...statement.DataIdentifier, ...updates.addIdentifiers])
];
}
if (updates.removeIdentifiers) {
statement.DataIdentifier = statement.DataIdentifier.filter(
(id: string) => !updates.removeIdentifiers!.includes(id)
);
}
if (updates.updateSampleRate && statement.Operation.Audit) {
statement.Operation.Audit.SampleRate = updates.updateSampleRate;
}
}
// Apply updated policy
await client.send(new PutDataProtectionPolicyCommand({
ResourceArn: topicArn,
DataProtectionPolicy: JSON.stringify(policy)
}));
console.log("Data protection policy updated successfully");
};
// Usage
await updateDataProtectionPolicy(
"arn:aws:sns:us-east-1:123456789012:MyTopic",
{
addIdentifiers: [DataIdentifiers.PASSPORT_US],
updateSampleRate: 75
}
);Generate compliance reports from data protection findings:
const generateComplianceReport = async (
logGroupName: string,
startTime: Date,
endTime: Date
) => {
// This would typically use CloudWatch Logs API to query findings
// Simplified example showing the structure
const report = {
reportPeriod: {
start: startTime.toISOString(),
end: endTime.toISOString()
},
summary: {
totalMessagesScanned: 0,
piiDetected: 0,
messagesBlocked: 0,
dataTypes: {} as { [key: string]: number }
},
findings: [] as any[]
};
// In practice, you would query CloudWatch Logs here
console.log("Compliance report generated:", report);
return report;
};Implement proper data classification before applying protection policies:
const classifyTopicData = (topicName: string) => {
const dataClassification = {
"CustomerNotifications": ["email", "phone"],
"PaymentProcessing": ["credit_card", "bank_account", "ssn"],
"HealthRecords": ["ssn", "address", "phone", "email"],
"PublicAnnouncements": []
};
return dataClassification[topicName] || [];
};
const applyClassificationBasedProtection = async (topicArn: string) => {
const topicName = topicArn.split(':').pop()!;
const sensitiveDataTypes = classifyTopicData(topicName);
if (sensitiveDataTypes.length === 0) {
console.log("No sensitive data classification found - no policy needed");
return;
}
const identifiers = sensitiveDataTypes.map(type => DataIdentifiers[type.toUpperCase()]);
const policy = {
Version: "2021-06-01",
Statement: [{
Sid: "ClassificationBasedProtection",
DataIdentifier: identifiers,
Operation: {
Audit: {
SampleRate: 100,
FindingsDestination: {
CloudWatchLogs: {
LogGroup: `data-protection-${topicName.toLowerCase()}`
}
}
}
}
}]
};
await client.send(new PutDataProtectionPolicyCommand({
ResourceArn: topicArn,
DataProtectionPolicy: JSON.stringify(policy)
}));
};Test policies in safe environments before production deployment:
const testDataProtectionPolicy = async (
testTopicArn: string,
testMessages: string[]
) => {
console.log("Testing data protection policy...");
for (const message of testMessages) {
try {
const { PublishCommand } = await import("@aws-sdk/client-sns");
await client.send(new PublishCommand({
TopicArn: testTopicArn,
Message: message
}));
console.log(`✓ Message allowed: "${message.substring(0, 50)}..."`);
} catch (error) {
console.log(`✗ Message blocked: "${message.substring(0, 50)}..." - ${error.message}`);
}
}
};
// Test with various message types
const testMessages = [
"Hello, this is a normal message",
"Contact us at support@example.com",
"Your credit card 4111-1111-1111-1111 was charged",
"SSN: 123-45-6789 for verification"
];
await testDataProtectionPolicy(
"arn:aws:sns:us-east-1:123456789012:TestTopic",
testMessages
);