개요

AWS 클라우드에서는 콘솔 로그인 시 디바이스 핑거프린트 정보를 활용한 지정 단말 로그인 기능을 제공하지 않기 때문에 지정된 단말(PC)에서만 클라우드 콘솔 접근이 허용되도록 Lambda를 이용해 모바일 접속을 제한하는 기능을 만들어보자,

* User-Agent 헤더를 이용하여 접속을 제한하는 것이 완벽한 방법은 아니지만 손쉽게 구현 가능한 최선의 방법이다.

 

Lambda 구성 방안

 1. 사용자 계정에 로그인 단말 정보를 입력하는 태그 생성

 2. 콘솔 로그인 시 해당 사용자의 단말 정보를 확인하는 서버리스 함수 생성

 3. 실시간 API 호출내역에서 콘솔 로그인 성공 이벤트가 발생할 경우 트리거

 4. 발생한 이벤트의 User-Agent 값을 확인하여 사전 정의된 문구가 포함될 경우 모바일 단말로 판단 및 태그 값 변경(True/False)

 5. 해당 태그 값이 Ture(모바일 단말) 일 경우 계정 비활성화(모든 리소스 접근 권한 Deny)

 

Lambda 생성 및 적용

Step 1) IAM 계정 IP 접근제어

 - 경로: IAM > 사용자 >

 - 그룹 또는 사용자 별 IP 접근제어 정책 적용

 

Step 2) 모바일 접속 확인 태그 생성

 - 경로: IAM > 사용자 > 태그 관리

 - IAM 계정 로그인 시, 모바일 로그인 확인 용도 태그 생성 및 초기화(FALSE)

 

Step 3) 모바일 접속 계정 잠금 정책 생성

 - 경로: IAM > 정책

 - LOGIN_MOBILE 태그 값이 “TRUE”인 경우 모든  액션 Deny 정책 생성

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalTag/LOGIN_MOBILE": "TRUE"
                }}}]}

 

Step 4) Labmda 정책, 역할, 함수, 트리거 생성

 - 트리거 생성 시 ConsoleLogin 이벤트 성공(Success) 패턴 작성

 - https://mokpo.tistory.com/595 참고

{
  "source": ["aws.signin"],
  "detail": {
    "eventName": ["ConsoleLogin"],
    "responseElements.ConsoleLogin": ["Success"]
  }
}

 

Step 5) Lambda 코드 작성

 - 경로: Lambda > 함수 >

 - User-Agent로 모바일 단말을 판단하는 입력하는 코드 작성(us-east-1)

    > ConsoleLogin 이벤트는 us-east-1 리전 CloudTrail에서 확인 가능

import boto3
import re
import json

def lambda_handler(event, context):
    # 트리거 이벤트로부터 계정 명 가져오기
    user_name = event['detail']['userIdentity']['userName']
    
    # 트리거 이벤트로부터 User-Agent 값 가져오기
    user_agent = event['detail']['userAgent']
    print(user_agent)
    # IAM 클라이언트 객체 생성
    
    print(is_mobile(user_agent))
    iam_client = boto3.client('iam')
    
    # is_mobile 함수로 모바일 접속을 판단하여 LOGIN_MOBILE 태그 값 변경(TRUE/FALSE)
    if is_mobile(user_agent):
        iam_client.tag_user(UserName=user_name, Tags=[{'Key': 'LOGIN_MOBILE', 'Value': 'TRUE'}])
        print(f"{user_name} 계정 로그인 단말이 모바일로 확인되어 모든 권한을 제한합니다.")
    else:
        iam_client.tag_user(UserName=user_name, Tags=[{'Key': 'LOGIN_MOBILE', 'Value': 'FALSE'}])
        print(f"{user_name} 계정 로그인 단말이 모바일이 아닙니다.")

# User-Agent 값에 Keyword가 포함된 경우 모바일 단말 접속으로 판단하는 함수
def is_mobile(user_agent):
    mobile_keywords = ['Mobile', 'Android', 'iPhone', 'iPad', 'iPod', 'BlackBerry', 'Windows Phone']
    pattern = r'(' + '|'.join(mobile_keywords) + ')'
    regex = re.compile(pattern, re.IGNORECASE)
    
    return bool(regex.search(user_agent))

 

Step 6) Lambda 테스트 이벤트 작성

 - 경로: Lambda > 함수 > 테스트 이벤트

 - Lambda 함수 테스트 용 이벤트 생성 및 테스트

{
  "version": "0",
  "id": "",
  "detail-type": "AWS Console Sign In via CloudTrail",
  "source": "aws.signin",
  "account": "",
  "time": "2023-04-21T07:08:40Z",
  "region": "us-east-1",
  "resources": [],
  "detail": {
    "eventVersion": "1.08",
    "userIdentity": {
      "type": "IAMUser",
      "principalId": "",
      "accountId": "",
      "accessKeyId": "",
      "userName": "12345678"
    },
    "eventTime": "2023-04-21T07:08:40Z",
    "eventSource": "signin.amazonaws.com",
    "eventName": "ConsoleLogin",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "0.0.0.0",
    "userAgent": "userAgent": "AWSBFF BFFDroid/2.6.6 (Linux; Android 29) Mobile Android/sdk1912000174 [arm64-v8a, armeabi-v7a, armeabi] samsung_SM-N960N",
    "errorMessage": "Failed authentication",
    "requestParameters": null,
    "responseElements": {
      "ConsoleLogin": "Failure"
    },
    "additionalEventData": {
      "LoginTo": "https://console.aws.amazon.com/console/home?hashArgs=%23&isauthcode=true&state=hashArgsFromTB_us-east-2_07a754f6c8efb02b",
      "MobileVersion": "No",
      "MFAUsed": "No"
    },
    "eventID": "1b4eb2f7-bd36-429d-beb7-feb02fa47f70",
    "readOnly": false,
    "eventType": "AwsConsoleSignIn",
    "managementEvent": true,
    "recipientAccountId": "123456789999",
    "eventCategory": "Management",
    "tlsDetails": {
      "tlsVersion": "TLSv1.2",
      "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
      "clientProvidedHostHeader": "us-east-1.signin.aws.amazon.com"
    }
  }
}
복사했습니다!