Skip to main content
CloudMask Logo

CloudMask-AWS 🎭

Anonymize AWS infrastructure identifiers for secure LLM processing

PyPI version Python Versions License: MIT

CloudMask helps you safely share AWS infrastructure data with Large Language Models by anonymizing sensitive identifiers while maintaining structure and reversibility.

Features

  • 🔒 Secure Anonymization: Hash-based deterministic anonymization
  • 🔄 Reversible: Complete mapping for unanonymization
  • 🏗️ Structure-Preserving: Maintains AWS resource ID prefixes (vpc-, i-, etc.)
  • ⚙️ Configurable: YAML-based configuration for company names and custom patterns
  • 🐍 Dual Interface: Use as CLI tool or Python library
  • 📋 Clipboard Support: Direct clipboard anonymization for quick workflows
  • 📦 Modern Python: Built with Python 3.10+ features (pattern matching, union types)
  • 🚀 Minimal Dependencies: Only requires PyYAML and pyperclip

Requirements

  • Python 3.10 or higher
  • PyYAML 6.0+

CloudMask leverages modern Python features including structural pattern matching, union type operators, and built-in generic types.

Installation

pip install cloudmask-aws

Quick Start

CLI Usage

# Generate config file
cloudmask init-config

# Anonymize (mapping stored in ~/.cloudmask/mapping.json by default)
cloudmask anonymize -i infrastructure.txt -o anonymized.txt

# Anonymize clipboard content
cloudmask anonymize --clipboard

# Restore original values
cloudmask unanonymize -i llm-response.txt -o restored.txt

# Restore clipboard content
cloudmask unanonymize --clipboard

# Use custom mapping location if needed
cloudmask anonymize --clipboard -m /path/to/custom-mapping.json

Python Library Usage

from cloudmask import CloudMask, CloudUnmask, Storage

# Anonymize text
mask = CloudMask(seed="my-secret-seed")
anonymized = mask.anonymize("""
    Instance i-1234567890abcdef0 is running in vpc-abcdef123456
    Account: 123456789012
    Company: Acme Corp
""")

# Save mapping to secure central location (~/.cloudmask/mapping.json)
mask.save_mapping(Storage.DefaultMappingPath)

# Unanonymize later
unmask = CloudUnmask(mapping_file=Storage.DefaultMappingPath)
original = unmask.unanonymize(anonymized)

Quick Function Usage

from cloudmask import anonymize, unanonymize

# One-liner anonymization
text, mapping = anonymize(
    "Instance i-123 in account 123456789012",
    seed="my-seed",
    company_names=["Acme Corp"]
)

# Restore original
original = unanonymize(text, mapping)

Configuration

Create a ~/.cloudmask/config.yml file (or use cloudmask init-config):

company_names:
  - Acme Corp
  - Example Inc
  - MyCompany LLC

custom_patterns:
  - pattern: '\bTICKET-\d{4,6}\b'
    name: ticket
  - pattern: '\bPROJ-[A-Z0-9]+'
    name: project
  # Example: Match company domains
  - pattern: '[a-zA-Z0-9][-a-zA-Z0-9.]*\.acme\.local\b'
    name: domain
  # Example: Match company emails
  - pattern: '[a-zA-Z0-9._%+-]+@acme-corp\.local\b'
    name: email

preserve_prefixes: true
anonymize_ips: true
anonymize_domains: false
seed: my-secret-seed

Custom Pattern Edge Cases

When creating custom patterns, be aware of:

  • Case sensitivity: Patterns are case-insensitive by default
  • Multi-level subdomains: Use [-a-zA-Z0-9.]* to match app.corp.acme.local
  • HTML entities: " in data is handled automatically
  • Email variations: Pattern supports user+tag@domain and user.name@domain
  • URLs and paths: Patterns work in https://server.acme.local/path
  • Trailing punctuation: Word boundaries (\b) handle server.acme.local.

Test your patterns:

cloudmask anonymize -i test.txt -o output.txt
grep -i "sensitive-term" output.txt  # Should return nothing

What Gets Anonymized?

  • ✅ AWS Resource IDs (vpc-, i-, sg-, ami-, etc.)
  • ✅ AWS Account IDs (12-digit numbers)
  • ✅ AWS ARNs
  • ✅ IP Addresses
  • ✅ Company names (from config)
  • ✅ Custom patterns (via regex)
  • ✅ Domain names (optional)

Use Cases

  • 🤖 LLM Assistance: Get help with infrastructure without exposing sensitive IDs
  • 📊 Data Sharing: Share infrastructure diagrams and configs safely
  • 🔍 Security Analysis: Analyze configs with external tools
  • 📝 Documentation: Create shareable examples from real infrastructure

Advanced Usage

Using in Scripts

from cloudmask import CloudMask, Config
from pathlib import Path

# Load custom config
config = Config.from_yaml(Path("custom-config.yaml"))

# Create anonymizer
mask = CloudMask(config=config, seed="production-seed")

# Process multiple files
for file in Path("configs").glob("*.yaml"):
    output = Path("anonymized") / file.name
    mask.anonymize_file(file, output)

# Save single mapping for all files
mask.save_mapping("master-mapping.json")

Context Manager

from cloudmask import TemporaryMask

with TemporaryMask(seed="temp-seed") as mask:
    anonymized = mask.anonymize("vpc-123 i-456")
    # Process anonymized data
    # Mapping is discarded after context exits

Batch Processing

from cloudmask import create_batch_anonymizer

# Create reusable anonymizer
anon = create_batch_anonymizer(seed="batch-seed")

# Use it multiple times
result1 = anon("vpc-123")
result2 = anon("i-456")

Central Storage

CloudMask stores mapping files in a secure central location by default:

~/.cloudmask/mapping.json

Benefits

  • 🔐 Automatic Security: Files created with 600 permissions (owner read/write only)
  • 📍 Centralized: All mappings in one location
  • 🔄 Auto-Merge: New mappings are merged with existing ones (same seed required)
  • ⚡ Convenient: No need to specify -m flag for common workflows

Seed Verification

CloudMask tracks which seed created each mapping file. Mappings can only be merged if they use the same seed:

# First use
mask1 = CloudMask(seed="prod-seed")
mask1.anonymize("vpc-11111")
mask1.save_mapping(Storage.DefaultMappingPath)  # Creates mapping

# Later use with SAME seed - mappings merge automatically
mask2 = CloudMask(seed="prod-seed")
mask2.anonymize("vpc-22222")
mask2.save_mapping(Storage.DefaultMappingPath)  # Merges with existing

# Different seed - prevents accidental corruption
mask3 = CloudMask(seed="different-seed")
mask3.save_mapping(Storage.DefaultMappingPath)  # ERROR: Seed mismatch

Custom Locations

You can still use custom mapping locations:

cloudmask anonymize -i file.txt -m /custom/path/mapping.json
mask.save_mapping("/custom/path/mapping.json")

Security Notes

⚠️ Keep your mapping files secure! They contain the reversible mappings.

  • The ~/.cloudmask/ directory is automatically secured with 700 permissions
  • Mapping files are created with 600 permissions (owner only)
  • Store mapping files separately from anonymized data
  • Use strong, unique seeds for different projects
  • Don't commit mapping files to version control
  • Consider encrypting mapping files for sensitive data
  • Always use the same seed for a project to enable mapping merges

Contributing

Contributions welcome! Please check out the GitHub repository.

License

MIT License - see LICENSE file for details

Troubleshooting

Pattern Not Matching?

  1. Test the regex: python -c "import re; print(re.search(r'your-pattern', 'test-string'))"
  2. Check case sensitivity: Patterns are case-insensitive
  3. Verify word boundaries: \b may not work with special characters
  4. Test with real data: Use small samples first

Data Still Leaking?

  1. Check pattern order: Custom patterns run before company names
  2. Verify pattern name: Use generic names like domain, not acme-domain
  3. Test thoroughly: grep -i "sensitive" output.txt

Support

Metadata

Release files for cloudmask-aws 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cloudmask-aws 0.4.1
File Size Uploaded
cloudmask_aws-0.4.1.tar.gz 448.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cloudmask-aws 0.4.1
File Interpreter ABI Platform
cloudmask_aws-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 479.6 kB

Release files / cloudmask_aws-0.4.1.tar.gz

Download URL cloudmask_aws-0.4.1.tar.gz
Size 448.1 kB
Tags Source
SHA-256 checksum
How to use checksums
4557e509b9710784c78cf236e95a404c25ff87d3ccd7545ae1eab5177b929706
BLAKE2b-256 checksum
How to use checksums
749731d9a29a44e09f475c2157f3a13f862cca7a3df952f3541e9324edbae5b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / cloudmask_aws-0.4.1-py3-none-any.whl

Download URL cloudmask_aws-0.4.1-py3-none-any.whl
Size 31.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2ba455ed8836cf1ed264aaeebc80adf3a8ade1bbd3fb20e5932b472ff243ea70
BLAKE2b-256 checksum
How to use checksums
edd8d5a7343f086d664f0df7f3679066a31abe45b9df8c9d3fac85df435965ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.5

2 release files

0.1.3

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page