AWS IAM Access-taster rotation ved hjælp af Lambda-funktionen
Architecutre Diagram

AWS IAM Access-taster rotation ved hjælp af Lambda-funktionen

Denne artikel er maskinoversat fra engelsk og kan indeholde unøjagtigheder. Læs mere
Se original

I henhold til AWS-sikkerhed bedste praksis bør vi regelmæssigt rotere vores IAM-adgangsnøgler for at forbedre vores AWS-kontosikkerhed.

I denne artikel vil jeg lære dig, hvordan viautomatisereprocessen med IAM-adgangstasters rotation i henhold til adgangstastens alder ved hjælp af Lambda-funktionen.

Use this link to rotate the keys manually using AWS document https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_RotateAccessKey

AWS IAM (Identitets- og adgangsstyring) giver fund-grain adgangskontrol på tværs af hele AWS.

AWS Access-tasterer langsigtede legitimationsoplysninger for en IAM-bruger. Du kan bruge adgangsnøgler til at signere programmatiske anmodninger til AWS CLI eller AWS API (direkte eller ved hjælp af AWS SDK).

AWS Lambdaer en serveruafhængig, hændelsesdrevet beregningstjeneste, der giver dig mulighed for at køre kode til stort set alle typer programmer eller backend-tjenester uden at klargøre eller administrere servere. Du kan udløse Lambda fra over 200 AWS-tjenester og software som en service (SaaS) applikationer, og betal kun for det, du bruger.

Arkitektur diagram

No alt text provided for this image

IAM-adgangstaster roterer ved hjælp af AWS lambda-funktion og sender meddelelser ved hjælp af AWS SES

Diagrammet viser følgende arbejdsgang:

1- IAM-brugere logger ind programmatisk ved hjælp af IAM-adgangsnøgler

2- CloudWatch-begivenhed starter en Lambda-funktion hver 24. time

3- Lambda-funktionen starter en Lambda-funktion for hvert AWS-konto-id og sender den metadataene til yderligere behandling. Det vil kontrollere alle brugeres adgangsnøglealder og starte e-mailen til kontoens ejer

4- I mit tilfælde har jeg opsat de tre betingelser for at sende e-mails ved hjælp af AWS SES.

Python-script i Lambda-funktionen:

Jeg har skrevet rotationsscriptet til adgangsnøgler i python. Dette python-script får først hver brugerinformation/metadata fra AWS IAM. Som du ved, AWS IAM-bruger kan være menneske eller kan være maskiner, så jeg har korrekt tagget hver bruger med følgende oplysninger:

  • Navn
  • Brugertype (medarbejder eller maskine)
  • E-mail (Abc@xyz.com)

No alt text provided for this image
No alt text provided for this image

Lambda-funktionen vil få ovenstående oplysninger fra IAM-brugertags, og hvis UserType er "ansat" og nøglen alder 70., 80. eller 90. dag, så sender den notifikations-e-mailen ved hjælp af AWS SES og inaktiverer adgangsnøglen. Hvis UserType er "maskine" og nøglealderen 70., 80. eller 90. dag, så vil den bare sende notifikations-e-mailen til det berørte team (som IT, Ops osv.).

Send advarsler og deaktiver adgangsnøglebetingelser:

Første betingelse, hvis IAM-adgangsnøglens alder er 70. dag, så send advarsels-e-mailen"I dag er den 70. dag for dine adgangsnøgler. Drej venligst din adgangsnøgle, før den fylder 90 dage".

Anden betingelse, hvis IAM-adgangsnøglens alder er 80. dag, så send advarsels-e-mailen"I dag er den 80. dag for dine adgangsnøgler. Drej venligst din adgangsnøgle, før den fylder 90 dage".

Tredje betingelse, hvis IAM-adgangsnøglens alder er 90. dag, så send advarsels-e-mailen"I dag er det 90. dag for dine adgangsnøgler, og din nøgle er blevet inaktiveret. Generer venligst ny nøgle eller kontakt IT-supportteamet".

Lambda funktionskode:

Få den korrekte formaterede kode fra mit github-lager: https://github.com/engr-usman/blogs.git

import boto3, os, time, datetime, sys, jso
from datetime import date
from botocore.exceptions import ClientError
iam = boto3.client('iam')
def lambda_handler(event, context):
email_70_list = []
email_80_list = []
email_90_list = []
# print("All IAM user emails that have AccessKeys 70 days or older")
unique_user_list = (iam.list_users()['Users'])
for userlist in unique_user_list:
userKeys = iam.list_access_keys(UserName=userlist['UserName'])
for keyValue in userKeys['AccessKeyMetadata']:
UserAccessKeyID = keyValue['AccessKeyId']
IAMUserName = keyValue['UserName']
#print(f"IAMUserName IAM Users:{len(IAMUserName)}: {IAMUserName}")
if keyValue['Status'] == 'Active':
currentdate = date.today()
active_days = currentdate - keyValue['CreateDate'].date()
#print ("The active days details are: ", active_days)
#print ("datetime details are: ", datetime.timedelta(days=15))
# if Access key age is greater then or equal to 70 days, send warning
if active_days == datetime.timedelta(days=int(os.environ['days_70'])):
userTags = iam.list_user_tags(UserName=keyValue['UserName'])
email_tag = list(filter(lambda tag: tag['Key'] == 'email', userTags['Tags']))
if(len(email_tag) == 1):
email = email_tag[0]['Value']
email_70_list.append(email)
print("This User: ", IAMUserName, ", with the email: ", email, ", is having access key age is 70 days")
email_unique = list(set(email_70_list))
print("Email list: ", email_unique)
RECIPIENTS = email_unique
SENDER = os.environ['sender_email']
AWS_REGION = os.environ['region']
SUBJECT_70 = os.environ['SUBJECT_70']
BODY_TEXT_70 = os.environ['BODY_TEXT_70']
BODY_HTML_70 = os.environ['BODY_HTML_70']
CHARSET = "UTF-8"
client = boto3.client('ses',region_name=AWS_REGION)
try:
response = client.send_email(
Destination={
'ToAddresses': RECIPIENTS,
},
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML_70,
},
'Text': {
'Charset': CHARSET,
'Data': BODY_TEXT_70,
},
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT_70,
},
},
Source=SENDER,
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])
# if Access Key Age is greater then 80 days, send email alert
if active_days == datetime.timedelta(days=int(os.environ['days_80'])):
userTags = iam.list_user_tags(UserName=keyValue['UserName'])
email_tag = list(filter(lambda tag: tag['Key'] == 'email', userTags['Tags']))
if(len(email_tag) == 1):
email = email_tag[0]['Value']
email_80_list.append(email)
print("The User: ", IAMUserName, ", with the email: ", email, ", is having access key age is 80 days")
email_unique = list(set(email_80_list))
print("Email list: ", email_unique)
RECIPIENTS = email_unique
SENDER = os.environ['sender_email']
print("Sender: ", SENDER)
AWS_REGION = os.environ['region']
SUBJECT_80 = os.environ['SUBJECT_80']
BODY_TEXT_80 = os.environ['BODY_TEXT_80']
BODY_HTML_80 = os.environ['BODY_HTML_80']
CHARSET = "UTF-8"
client = boto3.client('ses',region_name=AWS_REGION)
try:
response = client.send_email(
Destination={
'ToAddresses': RECIPIENTS,
},
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML_80,
},
'Text': {
'Charset': CHARSET,
'Data': BODY_TEXT_80,
},
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT_80,
},
},
Source=SENDER,
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])
# if Access Key Age is greater then 90 days, send email alert and inactive access keys
if active_days >= datetime.timedelta(days=int(os.environ['days_90'])):
userTags = iam.list_user_tags(UserName=keyValue['UserName'])
email_tag = list(filter(lambda tag: tag['Key'] == 'email', userTags['Tags']))
user1_tag = list(filter(lambda tag: tag['Key'] == 'UserType', userTags['Tags']))
if(len(email_tag) == 1):
email = email_tag[0]['Value']
email_90_list.append(email)
print("The User: ", IAMUserName, ", with the email: ", email, ", is having access key age is greater then 90 days")
if(len(user1_tag) == 1):
user1tag = user1_tag[0]['Value']
if user1tag == "Employee":
iam.update_access_key(AccessKeyId=UserAccessKeyID,Status='Inactive',UserName=IAMUserName)
print("Status has been updated to Inactive")
email_unique = list(set(email_90_list))
print("Email list: ", email_unique)
RECIPIENTS = email_unique
SENDER = os.environ['sender_email']
print("Sender: ", SENDER)
AWS_REGION = os.environ['region']
SUBJECT_90 = os.environ['SUBJECT_90']
BODY_TEXT_90 = os.environ['BODY_TEXT_90']
BODY_HTML_90 = os.environ['BODY_HTML_90']
CHARSET = "UTF-8"
client = boto3.client('ses',region_name=AWS_REGION)
try:
response = client.send_email(
Destination={
'ToAddresses': RECIPIENTS,
},
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML_90,
},
'Text': {
'Charset': CHARSET,
'Data': BODY_TEXT_90,
},
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT_90,
},
},
Source=SENDER,
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])n        

Bemærk: Indrykning er ikke korrekt af ovenstående kode:( og jeg ved, at der er masser af kodeforbedringer, det er bare for en idé.

Aktiver CloudWatch-hændelsesregel:

Nu skal vi bare oprette en CloudWatch-hændelsesregel (nu AWS EventBridge) for at udløse denne Lambda-funktion på et bestemt tidspunkt. I mit tilfælde har jeg aktiveret dette cron-job kl. 9 om morgenen.

No alt text provided for this image

AWS EventBridge-planlægning og mål

Konklusion

Dette er AWS-sikkerhed bedste praksis for at rotere IAM-adgangsnøgler, så ingen kan få adgang til dine kontoressourcer. Lambda-funktionen er det bedste værktøj til at udføre denne slags opgaver og udløse det fra andre tjenester som CloudWatch.

Jeg håber, du nød at læse denne artikel, er du velkommen til at kontakte mig, hvis du har spørgsmål.

Usman Ahmad what are the roles you provided your lambda function ?

Hi Usman Ahmad I am trying to fetch the details of both sender and region details here. bot its not happening. pls let me know whats this sender refers to? how i should try in my code. as you said in the post i have created the mail in ses and mentioned the VAULE in the IAM user tags. can you help me what i am missing inorder to get to get the region and sender details

  • Der er ingen alternativ tekst for dette billede

Hi Usman! Can you publish script in the correct format (at least screenshot), please? I'm not Python specialist for now, maybe in the future. Thank you.

Hvis du vil se eller tilføje en kommentar, skal du logge ind

Andre kiggede også på