aws-samples / aws-samples/resource-autotagger
Fix for Email-Based IAM Users: SSM Parameter Validation Error
- Dominant language
- JavaScript
- Stars
- 11
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
## Fix for Email-Based IAM Users: SSM Parameter Validation Error
### Issue
When using email addresses as IAM usernames (common in organizations), the auto-tagging Lambda function fails with SSM parameter validation errors, preventing all resource tagging from working.
### Error Encountered
```
ValidationException: The parameter doesn't meet the parameter name requirements. The parameter name must begin with a forward slash "/". It can't be prefixed with "aws" or "ssm" (case-insensitive). It must use only letters, numbers, or the following symbols: . (period), - (hyphen), _ (underscore). Special characters are not allowed.
```
### Environment
- **Region**: ap-northeast-1 (Tokyo)
- **Runtime**: nodejs18.x
- **CDK Version**: 2.1020.2
- **Repository Version**: Latest (commit: 9bc80e8)
- **Use Case**: Organization using email addresses for IAM usernames (e.g., `john.doe@company.com`)
### Root Cause
The `get_ssm_parameter_tags` function creates SSM parameter paths using usernames directly, but email addresses contain `@` symbols which are invalid for SSM parameter names:
```javascript
// This fails when iam_user_name = "john.doe@company.com"
path_string = `/auto-tag/${iam_user_name}/tag`; // → /auto-tag/john.doe@company.com/tag (invalid)
```
### ✅ Working Solution
I successfully fixed this issue by modifying the `get_ssm_parameter_tags` function in `handlers/resource-auto-tag/index.mjs`. Here's what worked:
```javascript
async function get_ssm_parameter_tags(iam_user_name, role_name, user_id) {
// Sanitize function to handle email addresses and other special characters
function sanitizeParameterName(name) {
return name ? name.replace(/[^a-zA-Z0-9._-]/g, '') : '';
}
var path_string = '';
if (iam_user_name != null) {
const sanitized_user = sanitizeParameterName(iam_user_name);
path_string = `/auto-tag/${sanitized_user}/tag`;
}
else {
if (role_name != null && user_id !=null) {
const sanitized_role = sanitizeParameterName(role_name);
const sanitized_user_id = sanitizeParameterName(user_id);
path_string = `/auto-tag/${sanitized_role}/${sanitized_user_id}/tag`;
} else {
path_string = '';
}
}
if (path_string != '') {
try {
var params = { Path: path_string, Recursive: true, WithDecryption: true };
var command = new GetParametersByPathCommand(params);
var get_parameter_response = await ssmClient.send(command);
if (get_parameter_response.Parameters != undefined && get_parameter_response.Parameters != null && get_parameter_response.Parameters.length > 0) {
var tag_list = [];
for (var i=0; i< get_parameter_response.Parameters.length;i++) {
var path_components = get_parameter_response.Parameters[i]["Name"].split("/");
var tag_key = path_components[path_components.length-1];
tag_list.push({"Key": tag_key, "Value": get_parameter_response.Parameters[i]["Value"]});
}
return tag_list;
} else {
return null;
}
} catch (error) {
console.warn('SSM parameter access failed, continuing without SSM tags:', error.message);
return null;
}
} else {
return null;
}
}
```
### How to Apply the Fix
1. Open AWS Lambda console
2. Find the main auto-tagging function (usually named `ResourceAutoTagCdkStack-resourceautotag...`)
3. Go to the Code tab
4. Find the `get_ssm_parameter_tags` function (around line 186)
5. Replace the entire function with the code above
6. Click "Deploy"
### Test Results
**Before Fix:**
- ❌ Lambda function crashed with ValidationException
- ❌ No resources got tagged
- ❌ Error: `The parameter doesn't meet the parameter name requirements`
**After Fix:**
- ✅ Auto-tagging works successfully
- ✅ Resources get tagged with: `IAM User Name`, `Date created`, etc.
- ✅ Graceful handling when SSM parameters don't exist
- ✅ Email addresses like `john.doe@company.com` now work
### Example Transformation
```
Email: john.doe@company.com
SSM Path Before: /auto-tag/john.doe@company.com/tag (INVALID ❌)
SSM Path After: /auto-tag/johndoecompanycom/tag (VALID ✅)
```
### Benefits of This Approach
1. **Works for all organizations** using email-based IAM usernames
2. **Non-breaking**: Existing functionality preserved
3. **Error resilient**: Continues tagging even if SSM access fails
4. **Easy to implement**: Just replace one function
5. **Handles edge cases**: Null values, special characters, etc.
### Alternative Quick Fix
If you only want to handle email addresses specifically, you can use this simpler approach:
```javascript
// Quick fix for email addresses only
const sanitized_user = iam_user_name.split('@')[0];
path_string = `/auto-tag/${sanitized_user}/tag`;
```
But the comprehensive solution above is recommended as it handles all special characters, not just email addresses.
### Impact
This fix resolves the issue for organizations using email addresses as IAM usernames, which is a common pattern in enterprise environments. The auto-tagging functionality now works reliably without requiring changes to existing IAM user naming conventions.
Contributor guide
Assessment
This issue has not been assessed yet.