AWS provides the ability to set a password policy on an account that will require a user to change their password after a certain period of time. However there is no method by which you can notify a user it is about to expire, nor is there anything that would expire an access key that hasn’t been rotated.
I wanted something that would implement policy that would deny any usage if the password was past-due (even if they hadn’t logged in for awhile) and would de-activate a key if it was older than the date set in the password policy. This would bring my AWS stuff into corporate compliance and prevent me from having to bother my users myself.
Since all our IAM usernames match the user’s email address, this is pretty easy to implement via automation. I’ve created a lambda that uses both the AWS Credential Report and the IAM APIs to iterate across all users and send them an SES notification when there password or key is about to expire.
The cloudformation template creates an IAM Group called UsersWithExpiredCredentials that limits the user to just the IAM actions necessary to change their password. There is the Lambda that does the work (and the appropriate Role and Invocation permissions), an Invocation Failure Alarm that will send to my account’s Alert Topic and a scheduled CloudWatch Event to trigger it to run every day.
The template takes as parameters:
- GracePeriodInDays (how far out from expiration do we warn the user)
- Boolean to indicate if we just warn or actually disable the user or key
- Boolean to indicate if we should use SES to email the user
- The SES authorized From Address
- Header and footer language for the email
- and an SNS topic where a summary of all actions taken gets published
(plus all the usual stuff needed to deploy a lambda that’s too big to fit in-line)
The Lambda itself uses the GetCredentialReport to see how long till the password will expire and it queries ListAccessKeys to see when the key was created. The Lambda only does this for IAM Users with LoginProfiles (ie they have a password), so it would not expire a IAM User that only had an access key (that’s a bit more dangerous and requires different handling)1. It uses GetAccountPasswordPolicy to determine the expiration age for both passwords and keys.
If an Access Key is past the expiration age it is not deleted and the user is not added to the BlackHole group. The key is simply flipped to deactivated.
In order to email users, you must either have had AWS support remove the sandbox limitation on your account, or you must verify all the users you intend to send to. Since the users are all IAM Users of your account, either are a viable option2.
1) Yes, a user can be dumb and embed their personal key into a production process somewhere. Said users need a flogging.
2) And adding all users to SES so you can send them system-wide notices might not be a bad thing to add to my add_user script and my RequireMFA stack.