Skip to main content

Encryption

JustSaying supports server-side encryption for messages using AWS Key Management Service (KMS). Encrypt messages at rest in SNS topics and SQS queues to meet compliance and security requirements.

Why Use Encryption​

Use encryption when:

  • Compliance requirements mandate encryption at rest
  • Messages contain sensitive data (PII, financial data, etc.)
  • Industry regulations require encrypted messaging (HIPAA, PCI-DSS, etc.)
  • Security policies require encryption for all data

Configuration​

Configure encryption using WithWriteConfiguration for publications:

Topic Encryption (SNS)​

services.AddJustSaying(config =>
{
config.Messaging(x => x.WithRegion("us-east-1"));

config.Publications(x =>
{
x.WithTopic<SecureOrderEvent>(cfg =>
{
cfg.WithWriteConfiguration(w =>
{
w.Encryption = new ServerSideEncryption
{
KmsMasterKeyId = "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
};
});
});
});
});

Queue Encryption (SQS)​

config.Publications(x =>
{
x.WithQueue<SecurePaymentCommand>(cfg =>
{
cfg.WithWriteConfiguration(w =>
{
w.WithEncryption("your-kms-key-id");
});
});
});

KMS Key Specification​

You can specify the KMS key in several formats:

Key ID​

w.WithEncryption("1234abcd-12ab-34cd-56ef-1234567890ab");

Key ARN​

w.Encryption = new ServerSideEncryption
{
KmsMasterKeyId = "arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"
};

Alias Name​

w.WithEncryption("alias/my-app-key");

Alias ARN​

w.Encryption = new ServerSideEncryption
{
KmsMasterKeyId = "arn:aws:kms:us-east-1:123456789012:alias/my-app-key"
};

IAM Permissions​

Applications using encryption require additional IAM permissions. See AWS IAM for complete details.

Publisher Permissions​

Publishers need kms:GenerateDataKey to encrypt messages:

{
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
}

Subscriber Permissions​

Subscribers need kms:Decrypt to decrypt messages:

{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
}

Complete Example​

Publisher Application​

services.AddJustSaying(config =>
{
config.Messaging(x => x.WithRegion("us-east-1"));

config.Publications(x =>
{
x.WithTopic<PatientRecordEvent>(cfg =>
{
cfg.WithWriteConfiguration(w =>
{
// Encrypt using KMS
w.Encryption = new ServerSideEncryption
{
KmsMasterKeyId = configuration["AWS:KMS:KeyId"]
};
});
});
});
});

// Publish encrypted message
var publisher = serviceProvider.GetRequiredService<IMessagePublisher>();
await publisher.PublishAsync(new PatientRecordEvent
{
PatientId = 12345,
MedicalData = "Sensitive information"
});

Subscriber Application​

services.AddJustSaying(config =>
{
config.Messaging(x => x.WithRegion("us-east-1"));

config.Subscriptions(x =>
{
// Automatic decryption - no encryption config needed
x.ForTopic<PatientRecordEvent>();
});
});

services.AddJustSayingHandler<PatientRecordEvent, PatientRecordEventHandler>();

Handler​

Handlers receive decrypted messages automatically:

public class PatientRecordEventHandler : IHandlerAsync<PatientRecordEvent>
{
public Task<bool> Handle(PatientRecordEvent message)
{
// Message is automatically decrypted
Console.WriteLine($"Processing patient {message.PatientId}");
return Task.FromResult(true);
}
}

KMS Key Management​

Creating a KMS Key​

Create a KMS key using AWS CLI:

aws kms create-key \
--description "JustSaying message encryption" \
--key-usage ENCRYPT_DECRYPT

aws kms create-alias \
--alias-name alias/justsaying-messages \
--target-key-id <key-id-from-previous-command>

Key Policies​

Ensure your KMS key policy allows the application to use it:

{
"Sid": "Allow application to use the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/YourApplicationRole"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*"
}

How It Works​

  1. Publisher: JustSaying requests a data encryption key from KMS
  2. Encryption: Message body is encrypted using the data key
  3. Storage: Encrypted message is stored in SNS/SQS
  4. Subscriber: JustSaying requests decryption from KMS
  5. Decryption: Message is decrypted and delivered to the handler

All encryption and decryption is transparent to application code.

Performance Considerations​

Latency​

  • Each encryption operation calls KMS, adding latency
  • Decryption also requires KMS API calls
  • KMS has rate limits that may affect high-throughput applications

Cost​

  • KMS charges per API call ($0.03 per 10,000 requests)
  • Data key caching reduces KMS calls but adds complexity
  • For high-volume scenarios, consider the cost impact

Caching​

AWS SDK caches data encryption keys to reduce KMS calls. Cache duration is typically 5 minutes but can be configured at the SDK level.

Security Best Practices​

  1. Use Separate Keys: Use different KMS keys for different sensitivity levels
  2. Rotate Keys: Enable automatic key rotation in KMS
  3. Audit: Enable CloudTrail logging for KMS operations
  4. Least Privilege: Grant only necessary KMS permissions
  5. Regional Keys: Use region-specific keys to meet compliance requirements

Troubleshooting​

"Access denied" when publishing​

Your IAM role lacks kms:GenerateDataKey permission. Add the permission for your KMS key:

{
"Effect": "Allow",
"Action": ["kms:GenerateDataKey"],
"Resource": "arn:aws:kms:region:account:key/key-id"
}

"Access denied" when subscribing​

Your IAM role lacks kms:Decrypt permission. Add the permission for your KMS key.

Messages not encrypting​

Verify:

  1. Encryption or WithEncryption() is configured on the publication
  2. KMS key ID is valid and accessible
  3. IAM role has required permissions

See Also​