0

我正在尝试按照此处的指南为 IAM 用户自动轮换密钥- https://awsfeed.com/whats-new/apn/automating-rotation-of-iam-user-access-and-secret-keys-与-aws-secrets-manager

本质上,我希望每 60 天获得一次新密钥,每 80 天停用旧密钥,然后每 90 天删除/删除旧密钥。

我稍微修改了它以每 60 天而不是 90 天获取新密钥,这是 lambda 函数:

import json
import boto3
import base64
import datetime
import os
from datetime import date
from botocore.exceptions import ClientError
iam = boto3.client('iam')
secretmanager = boto3.client('secretsmanager')
#IAM_UserName=os.environ['IAM_UserName']
#SecretName=os.environ['SecretName']

def create_key(uname):
    try:
        IAM_UserName=uname
        response = iam.create_access_key(UserName=IAM_UserName)
        AccessKey = response['AccessKey']['AccessKeyId']
        SecretKey = response['AccessKey']['SecretAccessKey']
        json_data=json.dumps({'AccessKey':AccessKey,'SecretKey':SecretKey})
        secmanagerv=secretmanager.put_secret_value(SecretId=IAM_UserName,SecretString=json_data)
        emailmsg="New "+AccessKey+" has been create. Please get the secret key value from secret manager"
        ops_sns_topic ='arn:aws:sns:us-east-1:redacted'
        sns_send_report = boto3.client('sns',region_name='us-east-1')
        sns_send_report.publish(TopicArn=ops_sns_topic, Message=emailmsg, Subject="New Key created for user"+ IAM_UserName)
    except ClientError as e:
        print (e)

def deactive_key(uname):
    try:
        #GET PREVIOUS AND CURRENT VERSION OF KEY FROM SECRET MANAGER
        IAM_UserName=uname
        getpresecvalue=secretmanager.get_secret_value(SecretId=IAM_UserName,VersionStage='AWSPREVIOUS')
        #getcursecvalue=secretmanager.get_secret_value(SecretId='secmanager3',VersionStage='AWSCURRENT')
        #print (getpresecvalue)
        #print (getcursecvalue)
        preSecString = json.loads(getpresecvalue['SecretString'])
        preAccKey=preSecString['AccessKey']
        #GET CREATION DATE OF CURRENT VERSION OF ACCESS KEY
        #curdate=getcursecvalue['CreatedDate']
        #GET TIMEZONE FROM CREATION DATE
        #tz=curdate.tzinfo
        #CALCULATE TIME DIFFERENCE BETWEEN CREATION DATE AND TODAY
        #diff=datetime.datetime.now(tz)-curdate
        #diffdays=diff.days
        #print (curdate)
        #print (tz)
        #print (diffdays)
        #print (preAccKey)
        #IF TIME DIFFERENCE IS MORE THAN x NUMBER OF DAYS THEN DEACTIVATE PREVIOUS KEY AND SEND A MESSAGE
        #if diffdays >= 1:
        iam.update_access_key(AccessKeyId=preAccKey,Status='Inactive',UserName=IAM_UserName)
        emailmsg="PreviousKey "+preAccKey+" has been disabled for IAM User"+IAM_UserName
        ops_sns_topic ='arn:aws:sns:us-east-1:redacted'
        sns_send_report = boto3.client('sns',region_name='us-east-1')
        sns_send_report.publish(TopicArn=ops_sns_topic, Message=emailmsg, Subject='Previous Key Deactivated')
        return
    except ClientError as e:
        print (e)
    #else:
    #    print ("Current Key is not older than 10 days")
    #print (datediff)

def delete_key(uname):
    try:
        IAM_UserName=uname
        print (IAM_UserName)
        getpresecvalue=secretmanager.get_secret_value(SecretId=IAM_UserName,VersionStage='AWSPREVIOUS')
    #getcursecvalue=secretmanager.get_secret_value(SecretId='secmanager3',VersionStage='AWSCURRENT')
        preSecString = json.loads(getpresecvalue['SecretString'])
        preAccKey=preSecString['AccessKey']
        #print (preAccKey)
    #GET CREATION DATE OF CURRENT VERSION OF ACCESS KEY
    #curdate=getcursecvalue['CreatedDate']
    #GET TIMEZONE FROM CREATION DATE
    #tz=curdate.tzinfo
    #CALCULATE TIME DIFFERENCE BETWEEN CREATION DATE AND TODAY
    #diff=datetime.datetime.now(tz)-curdate
    #diffdays=diff.days
    #IF TIME DIFFERENCE IS MORE THAN x NUMBER OF DAYS THEN DEACTIVATE PREVIOUS KEY AND SEND A MESSAGE
    #if diffdays >= 1:
        keylist=iam.list_access_keys (UserName=IAM_UserName)
    #print (keylist)
        for x in range(2):
            prevkeystatus=keylist['AccessKeyMetadata'][x]['Status']
            preacckeyvalue=keylist['AccessKeyMetadata'][x]['AccessKeyId']
            print (prevkeystatus)
            if prevkeystatus == "Inactive": 
                if preAccKey==preacckeyvalue:
                    print (preacckeyvalue)
                    iam.delete_access_key (UserName=IAM_UserName,AccessKeyId=preacckeyvalue)
                    emailmsg="PreviousKey "+preacckeyvalue+" has been deleted for user"+IAM_UserName
                    ops_sns_topic ='arn:aws:sns:us-east-1:redacted'
                    sns_send_report = boto3.client('sns',region_name='us-east-1')
                    sns_send_report.publish(TopicArn=ops_sns_topic, Message=emailmsg, Subject='Previous Key has been deleted')
                    return
                else:
                    print ("secret manager previous value doesn't match with inactive IAM key value")
            else:
                print ("previous key is still active")
        return
    except ClientError as e:
        print (e)
    #else:
    #print ("Current Key is not older than 10 days")
    
def lambda_handler(event, context):
    # TODO implement
    faction=event ["action"]
    fuser_name=event ["username"]
    if faction == "create":
        status = create_key(fuser_name)
        print (status)
    elif faction == "deactivate":
        status = deactive_key(fuser_name)
        print (status)
    elif faction == "delete":
        status = delete_key(fuser_name)
        print (status)

测试该功能时,我收到以下错误消息:

Response
{
  "errorMessage": "'action'",
  "errorType": "KeyError",
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      108,
      "lambda_handler",
      "faction=event [\"action\"]"
    ]
  ]
}

Function Logs
START RequestId: 45b13b13-e992-40fe-b2e8-1f2cc53a86e5 Version: $LATEST
'action': KeyError
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 108, in lambda_handler
    faction=event ["action"]
KeyError: 'action'

我对我的用户的角色和组有以下策略:

IAM只读访问

AmazonSNSFullAccess

以及具有以下操作的自定义策略:

"iam:ListUsers",
"iam:CreateAccessKey",
"iam:DeleteAccessKey",
"iam:GetAccessKeyLastUsed",
"iam:GetUser",
"iam:ListAccessKeys",
"iam:UpdateAccessKey"
        

我的 EventBridge 的常量(JSON 文本)为 {"action":"create","username":"secmanagert3"}

看看为什么我在 lambda 处理程序上不断收到错误

编辑:

在打印出环境变量甚至之后,我有这些函数日志:

Function Logs
START RequestId: c5cabedf-d806-4ca5-a8c6-1ded84c39a39 Version: $LATEST
## ENVIRONMENT VARIABLES
environ({'PATH': '/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin', 'LD_LIBRARY_PATH': '/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib', 'LANG': 'en_US.UTF-8', 'TZ': ':UTC', '_HANDLER': 'lambda_function.lambda_handler', 'LAMBDA_TASK_ROOT': '/var/task', 'LAMBDA_RUNTIME_DIR': '/var/runtime', 'AWS_REGION': 'us-east-2', 'AWS_DEFAULT_REGION': 'us-east-2', 'AWS_LAMBDA_LOG_GROUP_NAME': '/aws/lambda/AutomatedKeyRotation', 'AWS_LAMBDA_LOG_STREAM_NAME': '2021/10/14/[$LATEST]7f05c89773e240788lda232ec5dh8hg04', 'AWS_LAMBDA_FUNCTION_NAME': 'AutomatedKeyRotation', 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE': '128', 'AWS_LAMBDA_FUNCTION_VERSION': '$LATEST', '_AWS_XRAY_DAEMON_ADDRESS': 'xxx.xxx.xx.xxx', '_AWS_XRAY_DAEMON_PORT': '2000', 'AWS_XRAY_DAEMON_ADDRESS': 'xxx.xxx.xx.xxx:2000', 'AWS_XRAY_CONTEXT_MISSING': 'LOG_ERROR', '_X_AMZN_TRACE_ID': 'Root=1-61686a72-0v9fgta25cb9ca19568ae978;Parent=523645975780233;Sampled=0', 'AWS_EXECUTION_ENV': 'AWS_Lambda_python3.6', 'AWS_LAMBDA_INITIALIZATION_TYPE': 'on-demand', 'AWS_ACCESS_KEY_ID': 'key-id-number', 'AWS_SECRET_ACCESS_KEY': 'top-secret-key', 'AWS_SESSION_TOKEN': 'very-long-token', 'PYTHONPATH': '/var/runtime'})
## EVENT
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
'action': KeyError
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 112, in lambda_handler
    faction=event["action"]
KeyError: 'action'
4

1 回答 1

1

正如您从日志文件中看到的那样,您event没有actionusername变量。这就是为什么你得到KeyError.

问题是您是通过从 Lambda 函数而不是通过 Cloudwatch 运行测试来测试的。要解决这个问题:

  1. 在您的 Lambda 函数中,打开“测试”选项卡。在那里,你可以看到你的event样子。您可以手动更改它,在 JSON 中添加您需要的值,或者您可以从给定的模板中进行选择(其中有 Cloudwatch 作为模板)。一旦你添加actionusernameJSON,它就不会抛出这个错误

  2. 您可以按照您分享的帖子中的说明创建 Cloudwatch 事件,然后调用该事件。这样,当您在生产中实际调用它时,您将准确地看到该事件的样子。

于 2021-10-14T19:08:12.310 回答