or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

client-configuration.mddata-protection.mdindex.mdmessage-publishing.mdpagination.mdpermission-management.mdplatform-applications.mdresource-tagging.mdsms-management.mdsubscription-management.mdtopic-management.md
tile.json

resource-tagging.mddocs/

Resource Tagging

SNS resource tagging enables you to organize, track, and manage SNS resources using key-value pairs for cost allocation, access control, and operational management.

Capabilities

Tag Resource

Adds or updates tags for SNS resources including topics, subscriptions, and platform applications.

/**
 * Adds tags to an Amazon SNS resource
 * Tags are key-value pairs that help organize and manage resources
 */
class TagResourceCommand {
  constructor(input: TagResourceRequest);
}

interface TagResourceRequest {
  /** ARN of the resource to tag */
  ResourceArn: string;
  /** List of tags to add or update */
  Tags: Tag[];
}

interface TagResourceResponse {
  /** Response metadata */
  ResponseMetadata?: any;
}

interface Tag {
  /** Tag key (required) */
  Key: string;
  /** Tag value (required) */
  Value: string;
}

Usage Examples:

import { SNSClient, TagResourceCommand } from "@aws-sdk/client-sns";

const client = new SNSClient({ region: "us-east-1" });

// Tag a topic with environment and team information
await client.send(new TagResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
  Tags: [
    { Key: "Environment", Value: "Production" },
    { Key: "Team", Value: "Backend" },
    { Key: "Project", Value: "UserNotifications" },
    { Key: "CostCenter", Value: "Engineering" }
  ]
}));

// Tag a subscription
await client.send(new TagResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic:subscription-id",
  Tags: [
    { Key: "Protocol", Value: "email" },
    { Key: "Priority", Value: "high" },
    { Key: "Owner", Value: "admin@example.com" }
  ]
}));

// Tag a platform application
await client.send(new TagResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:app/APNS/MyApp",
  Tags: [
    { Key: "Platform", Value: "iOS" },
    { Key: "AppVersion", Value: "2.1.0" },
    { Key: "Environment", Value: "Production" }
  ]
}));

Untag Resource

Removes specified tags from SNS resources.

/**
 * Removes tags from an Amazon SNS resource
 * Removes the specified tag keys and their values
 */
class UntagResourceCommand {
  constructor(input: UntagResourceRequest);
}

interface UntagResourceRequest {
  /** ARN of the resource to untag */
  ResourceArn: string;
  /** List of tag keys to remove */
  TagKeys: string[];
}

interface UntagResourceResponse {
  /** Response metadata */
  ResponseMetadata?: any;
}

Usage Examples:

// Remove specific tags from a topic
await client.send(new UntagResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic",
  TagKeys: ["Environment", "CostCenter"]
}));

// Remove all specified tags from a subscription
await client.send(new UntagResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic:subscription-id",
  TagKeys: ["Priority", "Owner"]
}));

List Tags for Resource

Retrieves all tags associated with a specific SNS resource.

/**
 * Returns a list of tags associated with an Amazon SNS resource
 * Shows all current key-value pairs for the resource
 */
class ListTagsForResourceCommand {
  constructor(input: ListTagsForResourceRequest);
}

interface ListTagsForResourceRequest {
  /** ARN of the resource */
  ResourceArn: string;
}

interface ListTagsForResourceResponse {
  /** List of tags associated with the resource */
  Tags?: Tag[];
}

Usage Examples:

// List all tags for a topic
const topicTags = await client.send(new ListTagsForResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:MyTopic"
}));

topicTags.Tags?.forEach(tag => {
  console.log(`${tag.Key}: ${tag.Value}`);
});

// List tags for a platform application
const appTags = await client.send(new ListTagsForResourceCommand({
  ResourceArn: "arn:aws:sns:us-east-1:123456789012:app/APNS/MyApp"
}));

console.log("Platform Application Tags:");
appTags.Tags?.forEach(tag => {
  console.log(`  ${tag.Key}: ${tag.Value}`);
});

Tagging Strategies

Environment-Based Tagging

Organize resources by environment for clear separation and management:

const tagResourceByEnvironment = async (resourceArn: string, environment: string) => {
  const baseTags = [
    { Key: "Environment", Value: environment },
    { Key: "ManagedBy", Value: "Infrastructure" },
    { Key: "CreatedDate", Value: new Date().toISOString().split('T')[0] }
  ];
  
  // Add environment-specific tags
  const environmentTags = environment === "Production" 
    ? [
        { Key: "Backup", Value: "Required" },
        { Key: "Monitoring", Value: "Enhanced" },
        { Key: "SLA", Value: "Critical" }
      ]
    : [
        { Key: "Backup", Value: "Optional" },
        { Key: "Monitoring", Value: "Basic" },
        { Key: "AutoShutdown", Value: "Enabled" }
      ];
  
  await client.send(new TagResourceCommand({
    ResourceArn: resourceArn,
    Tags: [...baseTags, ...environmentTags]
  }));
};

// Usage
await tagResourceByEnvironment(
  "arn:aws:sns:us-east-1:123456789012:ProductionAlerts",
  "Production"
);

Cost Allocation Tagging

Implement comprehensive cost tracking with standardized tags:

const applyCostAllocationTags = async (
  resourceArn: string,
  project: string,
  team: string,
  costCenter: string
) => {
  await client.send(new TagResourceCommand({
    ResourceArn: resourceArn,
    Tags: [
      { Key: "Project", Value: project },
      { Key: "Team", Value: team },
      { Key: "CostCenter", Value: costCenter },
      { Key: "BillingContact", Value: `${team.toLowerCase()}@company.com` },
      { Key: "BudgetCode", Value: `${costCenter}-${project}` }
    ]
  }));
};

// Apply cost allocation tags to multiple resources
const resources = [
  "arn:aws:sns:us-east-1:123456789012:UserNotifications",
  "arn:aws:sns:us-east-1:123456789012:OrderAlerts",
  "arn:aws:sns:us-east-1:123456789012:SystemAlerts"
];

for (const resourceArn of resources) {
  await applyCostAllocationTags(
    resourceArn,
    "ECommercePlatform",
    "Backend",
    "ENG-001"
  );
}

Operational Tagging

Tag resources with operational metadata for automation and management:

const applyOperationalTags = async (resourceArn: string) => {
  await client.send(new TagResourceCommand({
    ResourceArn: resourceArn,
    Tags: [
      { Key: "Owner", Value: "platform-team@company.com" },
      { Key: "SupportLevel", Value: "24x7" },
      { Key: "BackupSchedule", Value: "daily" },
      { Key: "PatchGroup", Value: "production-sns" },
      { Key: "SecurityScan", Value: "enabled" },
      { Key: "ComplianceRequired", Value: "HIPAA,SOX" },
      { Key: "DataClassification", Value: "confidential" },
      { Key: "AutomationEnabled", Value: "true" }
    ]
  }));
};

Bulk Tagging Operations

Efficiently tag multiple resources with common patterns:

const bulkTagResources = async (
  resourceArns: string[],
  commonTags: Tag[]
) => {
  const tagPromises = resourceArns.map(resourceArn =>
    client.send(new TagResourceCommand({
      ResourceArn: resourceArn,
      Tags: commonTags
    }))
  );
  
  try {
    await Promise.all(tagPromises);
    console.log(`Successfully tagged ${resourceArns.length} resources`);
  } catch (error) {
    console.error("Error in bulk tagging:", error);
    
    // Retry failed resources individually
    for (const resourceArn of resourceArns) {
      try {
        await client.send(new TagResourceCommand({
          ResourceArn: resourceArn,
          Tags: commonTags
        }));
        console.log(`✓ Tagged: ${resourceArn}`);
      } catch (err) {
        console.error(`✗ Failed to tag: ${resourceArn}`, err.message);
      }
    }
  }
};

// Usage
const migrationTags = [
  { Key: "Migration", Value: "Q1-2024" },
  { Key: "MigrationStatus", Value: "pending" },
  { Key: "MigrationOwner", Value: "cloud-team" }
];

await bulkTagResources([
  "arn:aws:sns:us-east-1:123456789012:Topic1",
  "arn:aws:sns:us-east-1:123456789012:Topic2",
  "arn:aws:sns:us-east-1:123456789012:Topic3"
], migrationTags);

Tag Management Patterns

Tag Validation and Standardization

Ensure consistent tagging across resources:

interface TaggingStandards {
  required: string[];
  allowedValues: { [key: string]: string[] };
  patterns: { [key: string]: RegExp };
}

const taggingStandards: TaggingStandards = {
  required: ["Environment", "Team", "Project"],
  allowedValues: {
    "Environment": ["Development", "Staging", "Production"],
    "Team": ["Frontend", "Backend", "DevOps", "QA"],
    "Priority": ["Low", "Medium", "High", "Critical"]
  },
  patterns: {
    "CostCenter": /^[A-Z]{3}-\d{3}$/,
    "Email": /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  }
};

const validateAndTagResource = async (
  resourceArn: string,
  proposedTags: Tag[]
) => {
  // Check required tags
  const tagKeys = proposedTags.map(tag => tag.Key);
  const missingRequired = taggingStandards.required.filter(
    required => !tagKeys.includes(required)
  );
  
  if (missingRequired.length > 0) {
    throw new Error(`Missing required tags: ${missingRequired.join(', ')}`);
  }
  
  // Validate tag values
  for (const tag of proposedTags) {
    // Check allowed values
    if (taggingStandards.allowedValues[tag.Key]) {
      if (!taggingStandards.allowedValues[tag.Key].includes(tag.Value)) {
        throw new Error(
          `Invalid value '${tag.Value}' for tag '${tag.Key}'. ` +
          `Allowed values: ${taggingStandards.allowedValues[tag.Key].join(', ')}`
        );
      }
    }
    
    // Check patterns
    if (taggingStandards.patterns[tag.Key]) {
      if (!taggingStandards.patterns[tag.Key].test(tag.Value)) {
        throw new Error(
          `Tag '${tag.Key}' value '${tag.Value}' does not match required pattern`
        );
      }
    }
  }
  
  // Apply tags if validation passes
  await client.send(new TagResourceCommand({
    ResourceArn: resourceArn,
    Tags: proposedTags
  }));
  
  console.log(`Successfully tagged resource with validated tags`);
};

Tag-Based Resource Discovery

Find resources based on tag criteria:

import { ListTopicsCommand } from "@aws-sdk/client-sns";

const findResourcesByTags = async (
  targetTags: { [key: string]: string }
) => {
  const topics = await client.send(new ListTopicsCommand());
  const matchingResources: string[] = [];
  
  for (const topic of topics.Topics || []) {
    if (topic.TopicArn) {
      const tags = await client.send(new ListTagsForResourceCommand({
        ResourceArn: topic.TopicArn
      }));
      
      const resourceTags = tags.Tags || [];
      const matches = Object.entries(targetTags).every(([key, value]) =>
        resourceTags.some(tag => tag.Key === key && tag.Value === value)
      );
      
      if (matches) {
        matchingResources.push(topic.TopicArn);
      }
    }
  }
  
  return matchingResources;
};

// Find all production resources owned by backend team
const productionBackendResources = await findResourcesByTags({
  "Environment": "Production",
  "Team": "Backend"
});

console.log("Production Backend Resources:", productionBackendResources);

Tag Cleanup and Maintenance

Regular maintenance of resource tags:

const cleanupResourceTags = async (resourceArn: string) => {
  const tags = await client.send(new ListTagsForResourceCommand({
    ResourceArn: resourceArn
  }));
  
  const tagsToRemove: string[] = [];
  const tagsToUpdate: Tag[] = [];
  
  for (const tag of tags.Tags || []) {
    // Remove deprecated tags
    if (tag.Key.startsWith("deprecated-")) {
      tagsToRemove.push(tag.Key);
    }
    
    // Standardize case
    if (tag.Key === "environment" || tag.Key === "ENVIRONMENT") {
      tagsToRemove.push(tag.Key);
      tagsToUpdate.push({ Key: "Environment", Value: tag.Value });
    }
    
    // Remove empty values
    if (!tag.Value || tag.Value.trim() === "") {
      tagsToRemove.push(tag.Key);
    }
  }
  
  // Remove unwanted tags
  if (tagsToRemove.length > 0) {
    await client.send(new UntagResourceCommand({
      ResourceArn: resourceArn,
      TagKeys: tagsToRemove
    }));
  }
  
  // Add standardized tags
  if (tagsToUpdate.length > 0) {
    await client.send(new TagResourceCommand({
      ResourceArn: resourceArn,
      Tags: tagsToUpdate
    }));
  }
};

Automated Tagging on Resource Creation

Implement automatic tagging when creating resources:

import { CreateTopicCommand } from "@aws-sdk/client-sns";

const createTopicWithStandardTags = async (
  topicName: string,
  customTags: Tag[] = []
) => {
  // Create the topic first
  const createResult = await client.send(new CreateTopicCommand({
    Name: topicName
  }));
  
  if (!createResult.TopicArn) {
    throw new Error("Failed to create topic");
  }
  
  // Apply standard tags
  const standardTags: Tag[] = [
    { Key: "CreatedBy", Value: "AutomatedSystem" },
    { Key: "CreatedDate", Value: new Date().toISOString().split('T')[0] },
    { Key: "ResourceType", Value: "SNS-Topic" },
    { Key: "ManagedBy", Value: "Infrastructure" }
  ];
  
  await client.send(new TagResourceCommand({
    ResourceArn: createResult.TopicArn,
    Tags: [...standardTags, ...customTags]
  }));
  
  return createResult.TopicArn;
};

// Usage
const topicArn = await createTopicWithStandardTags("NewProductTopic", [
  { Key: "Environment", Value: "Production" },
  { Key: "Team", Value: "Backend" },
  { Key: "Project", Value: "ProductCatalog" }
]);

Tag-Based Access Control

Use tags for resource-based access control in IAM policies:

IAM Policy Example:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sns:Publish",
        "sns:Subscribe"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "sns:ResourceTag/Team": "${aws:PrincipalTag/Team}",
          "sns:ResourceTag/Environment": "Production"
        }
      }
    }
  ]
}

This policy allows users to only interact with SNS resources that:

  1. Have a "Team" tag matching the user's "Team" tag
  2. Have an "Environment" tag set to "Production"