sol 개발 블로그 로고
Published on

[ASAC 주간 스터디] AWS IAM과 실습

Authors
  • avatar
    Name
    Chan Sol OH
    Twitter

목차

이번 포스팅은 ASAC 주간 스터디AWS IAM 및 CLIAWS CLI,SDK, IAM 역할 및 정책에서 배운 내용을 실제 프로젝트에 적용할 수 있도록 개념과 사용법을 정리한다.

주요 키워드

iam user, iam policy, 최소권한원칙, iam policies inheritance, MFA, Secret access key,

IAM이란?

Identity and Access Management(IAM)에서는 사용자를 생성하고 그룹에 배치하기 때문에 글로벌 서비스에 해당된다. 계정을 생성하면 기본으로 주어지는 사용자가 Root 사용자다. Root 사용자는 계정을 생성할 때만 사용돼야한다.

IAM User란?

IAM User는 조직 내의 한 사람에 해당된다. 또한 필요에 따라 User들을 그룹으로 묶을 수도 있다. 주의 그룹은 오직 IAM User만 들어갈 수 있다. 그룹이 또 다른 그룹에 들어갈 순 없다. 또한 한 IAM User가 다수의 그룹에 속할 수 있다.

IAM 종류

IAM에는 3가지 종류가 있다.

  1. IAM 권한 : 유저나 그룹이 **어떤 행위(ex: 그룹에 유저 추가, S3에 접근)**를 할 수 있는가?
  2. IAM 역할 : 어떤 AWS 서비스가 **어떤 행위(ex: S3에 접근)**를 할 수 있는가?
  3. IAM 정책 : 유저나 그룹의 작업 권한을 정의하는 json 문서.
    • EC2, CloudWatch, ELB는 이를 통해 사용자들이 AWS 서비스를 이용하도록 허용한다. 즉 정책들을 사용해 사용자들의 권한을 정의할 수 있게 된다.
    • AWS는 최소 권한의 원칙을 적용한다. 사용자가 꼭 필요로하는 것 이상의 권한을 주지 않는 것.

IAM 정책

IAM 정책을 그룹 레벨에 적용하면 정책이 그룹의 모든 구성원에게 적용되며 정책의 상속이 가능하다. 만약 IAM 사용자가 어떤 그룹에 속해 있지 않는다면, 해당 사용자에게만 연결 가능한 인라인 정책을 생성할 수 있다. 한 유저가 여러 그룹에 속해있어도 그룹들의 권한을 상속받는다.

iam-policy

{
  "Version": "2012-10-17", # 정책 버전 (필수)
	"Id": "S3-Account-Permissions", # 정책 이름 (선택)
  "Statement": [
    {
      "Sid": "FirstStatement",			# 문장 식별자 (선택)
      "Effect": "Allow",				# 허가(Allow) 거부(Deny)
			"Principal" : { # 정책이 적용될 사용자, 계정, or 역할
				"AWS" :["arn:aws:iam::1234567865:root"]
			},
      "Action": ["iam:ChangePassword"],	# 문장이 적용되는 API 리스트
      "Resource": "*"	# 적용 리소스, 이 경우에는 모든 리소스에 적용할 수 있다. 하지만, 실질적으로 ChangePassword API 작업 요청을 수행한 사용자의 암호에만 영향을 미친다.
    },
    {
      "Sid": "SecondStatement",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets", # 사용자 자신의 버킷을 나열할 수 있다.
      "Resource": "*"
    },
    {
      "Sid": "ThirdStatement",
      "Effect": "Allow",
      "Action": [ # S3 버킷을 나열할 수 있는 API 사용가능. 단, 다른 계정의 리소스에 대한 액세스 권한을 부여하지 않으므로 사용자는 자신의 AWS 계정에 있는 버킷만 나열할 수 있다.
        "s3:List*",
        "s3:Get*"
      ],
      "Resource": [ # confidential-data라는 버킷과 객체를 다룸
        "arn:aws:s3:::confidential-data",
        "arn:aws:s3:::confidential-data/*"
      ],	# 단, MFA 인증을 수행한 경우
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    }
  ]
}

IAM - Password Policy

사용자들과 그룹의 정보가 침해당하지 않도록 보호하는 방법으로 비밀번호 정책 정의MFA

비밀번호 규칙

  • 최소 길이
  • 특정 유형의 글자 타입 사용
  • IAM 사용자들의 비밀번호 변경 허용 또는 금지
  • 일정 기간이 지날 경우 비밀번호를 만료시켜 새 비밀번호 설정을 요구할 수 있다.
  • 이전에 사용한 비밀번호 사용 금지

Multi Factor Authentication(MFA)

AWS에서는 MFA를 필수적으로 사용하도록 권장한다. 사용자들은 계정으로 많은 작업을 할 수 있기 때문에 Root 계정은 무슨 일이 있어도 반드시 보호해야한다. 그렇기에 MFA를 사용해야한다.

MFA는 비밀번호와 security device를 함께 사용하는 것이다. 만약 사용자가 해킹당해 비밀번호가 유출됐더라도 사용자 소유의 물리적 장치가 추가로 필요하기 때문에 계정이 침해당하지 않는ㄴ다.

  1. Google Authenticator :(Virtual MFA device) 핸드폰에서만 사용가능
  2. Authy :(Virtual MFA device) 멀티 디바이스, 멀티 토큰 지원. 멀티 토큰은 한 장치에서 여러 계정의 인증을 수행할 수 있음을 의미한다.
  3. Universal 2nd Factor (U2F) Security Key : 물리적 usb. 하나의 보안키로 여러 계정 인증 가능
  4. Hardware Key Fob MFA Device
  5. Hardware Key Fob MFA Device for AWS GovCloud

AWS CLI & SDK

AWS API를 호출할 때는 access key나 secret key 같은 자격증명을 함께 보내야한다. 그래야 aws가 누가 보낸 요청인지 판단하고 인증하기 때문이다. SDK와 CLI는 위에 CLI Credentials Provider Chain에 따라 서명을 얻고 자동으로 API 요청할 때 함께 보낸다. 이 서명은 SigV4 프로토콜을 이용하며 Authorization header에 서명을 넣어 전달하거나 쿼리스트링으로 X-Amz-Signature 키에 서명을 넣어 전달하는 방법이 있다.

다양한 aws에 접속하는 방법

  1. AWS Management Console : 이름 및 비밀번호 (+ MFA)로 인증
  2. AWS Command Lin Interface(CLI) : protected by access keys -> 터미널에서 aws 리소스에 접속할 때 사용
  3. AWS Software Developer Kit (SDK) : protected by access keys -> 애플리케이션에서 AWS의 API를 호출할 때 사용
  4. AWS Cloud Shell : 아직 제한된 regions만 이용 가능! 서울 region은 사용못한다. -> 클라우드로 동작하는 터미널 서비스, 그리고 파일 업로드 다운로드가 가능!

access key는 AWS Console에서 생성될 수 있고, 사용자들이 자신들의 액세스 키를 직접 관리한다. 따라서 Access Key ID는 username이고, Secret Access Key는 password라고 생각할 수 있다. access key는 비밀번호와 마찬가지 역할을 하기 때문에 공유하거나 잊어버리면 안된다.

절대로 access key를 공유해서는 안된다.

AWS CLI

AWS CLI를 사용하면 AWS 서비스의 공용 API로 직접 액세스가 가능하다. 또한 CLI를 통해 스크립트를 작성해서 일부 작업을 자동화할 수 있다. 몇몇 고수들은 AWS Console 안 쓰고 cli만 사용하기도 한다.

다중 계정에서 CLI 사용법

터미널에서 aws configure을 작성하면 AWS Access Key ID 같은 기본 자격증명을 설정할 수 있다. 만약 사용하는 AWS 계정이 여러개 있고, 이에 따른 자격증명을 저장하려면 어떻게해야할까?

aws configure --profile [프로필 이름]과 같이 원하는 프로필 이름에 자격증명을 별도로 관리할 수 있다.

또한 aws s3 ls와 같이 S3의 버킷을 나열할 수 있는 명령어도 뒤에 --profile [프로필 이름]을 붙여서 해당 계정의 S3 버킷 리스트를 볼 수 있다.

MFA(다요소 인증) with CLI

이전 AWS IAM 및 CLI에서 Management console에 이름과 비밀번호에 추가적으로 MFA를 적용할 수 있다는 것을 포스팅했었다.

이번에는 CLI에도 MFA를 설정하는 방법이다.

CLI에서 MFA를 사용하려면 임시 세션을 얻어야하고, API를 호출하기 위해선 STS GetSessionToken으로 얻은 토큰을 사용해야한다. 토큰을 얻는 방법은 아래와 같다.

GetSessionToken.sh
// 문법
aws sts get-session-token --serial-number [MFA 장치 시리얼 넘버] --token-code [MFA 장치로 얻은 코드] --duration-seconds 3600
// 예시
aws sts get-session-token \
    --duration-seconds 900 \
    --serial-number "YourMFADeviceSerialNumber" \
    --token-code 123456

// 요청 응답
{
    "Credentials": {
        "AccessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY",
        "SessionToken": "AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE",
        "Expiration": "2020-05-19T18:06:10+00:00"
    }
}

MFA 장치 시리얼 넘버와 MFA를 통해 얻은 코드를 입력해서 토큰을 요청하면 AccessKeyId, SecretAccessKey, 그리고 SessionToken 와 같은 임시적 자격증명 데이터가 응답된다. 이를 aws cli에 적용하기 위해 .aws/credentials에 AccessKeyId, SecretAccessKey, SessionToken을 입력한다.

AWS SDK

AWS Software Development Kit (AWS SDK)는 특정 언어로된 라이브러리의 집합. 따라서 언어에 따라 다른 라이브러리가 존재한다. CLI와 마찬가지로 AWS 서비스나 API에 프로그래밍을 위한 액세스가 가능하도록 한다. AWS SDK를 사용할 때 주의할 점은 별도로 Region을 지정하지 않으면 자동으로 us-east-1으로 설정되어 API를 호출한다. 아래는 DynamoDB에 Lambda가 문서를 가져오는 예제 코드

getChat.mjs
// 4_Remember_Chat - getChat
import { DynamoDBClient, ScanCommand } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient({});

export const handler = async function (event) {
  try {
    const command = new ScanCommand({
      ProjectionExpression: "id, sender, #TXT, #TIME",
      // 'text' is a reserved keyword
      ExpressionAttributeNames: {
        "#TXT": "text",
        "#TIME": "timestamp",
      },
    });

    const result = await client.send(command);
    const items =
      result.Items?.map((item) => {
        return {
          id: Number(item.id.N),
          sender: item.sender.S,
          text: item.text.S,
          timestamp: Number(item.timestamp.N),
        };
      }) || [];
    return done(null, items);
  } catch (err) {
    return done(err);
  }
};

AWS Credentials Provider Chain

AWS CLI Credentials Provider Chain

CLI로 API 호출할 때 자격증명 데이터를 요청한다. 그 때 찾는 과정은 다음과 같다.ㅇ 아래 순서에 따라 우선순위가 나뉘어진다.

  1. Command line options : --region, accessKeyId와 같이 명령을 작성할 때 붙이는 옵션
  2. Environment variables : AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN과 같은 환경변수
  3. CLI credentials file : aws configure로 ~/.aws/credentials에 작성한 cli 자격증명 파일에 작성된 정보
  4. CLI config file : aws configure로 ~/.aws/config에 작성한 cli 자격증명 파일에 작성된 정보
  5. Container credentials : ECS 작업의 경우에는 컨테이너 자격 증명을 확인
  6. Instance Profile credential : EC2 인스턴스 프로파일 자격 증명을 확인

AWS SDK Default Credentials Provider Chain

Java SDK는 다음과 같은 순서로 자격증명을 확인한다.

  1. Java system properties
  2. Environment variables : AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN -> CLI로 profile에 맞는 유저 권한 부여한 것
  3. default credential profiles file : 컴퓨터 전체에 적용되는 ~/.aws/credentials, ~/.aws/config 파일 -> 기본 profiles 권한
  4. ECS Container credentials
  5. Instance Profile credential : IAM Role로 설정한 권한

중요한 점은 환경 변수가 여전히 우선시 되는데 이건 EC2 인스턴스 프로파일 자격 증명이다.

사용사례

EC2 인스턴스에서 애플리케이션을 배포하고 IAM 유저로 S3 API를 호출하는 상황. 이때 IAM 유저는 S3FullAccess 권한을 가지고 있다. 또한 EC2는 한가지 S3에 접근할 수 있는 IAM 역할 및 EC2 인스턴스 프로파일을 정의하고 있다.

EC2의 IAM 역할이 Best practies처럼 필요 최소 권한인 한 버킷에 권한만 가지고 있더라도 EC2는 모든 버킷에 액세스할 수 있다. 그 이유는 Credentials Provider Chain에서 인스턴스 프로파일(사용자의 권한)이 존재이기 때문이다.

위 문제를 해결하기 위해선 환경변수 설정을 해제하고 인스턴스 프로파일의 자격증명을 사용하도록 한다.

모법 사용사례

  1. 무조건 자격증명을 코드에 사용하면 안된다.
  2. AWS에서는 IAM 역할을 최대한 많이 사용해야한다. EC2 인스턴스에는 EC2 인스턴스 역할을, ECS task에는 ECS 역할을 각각 부여해야한다.
  3. 터미널에서 자격증명을 설정할때는 환경변수named prodiles를 사용해아한다.

IAM 사용자와 그룹 생성법

IAM 사용자 생성법

aws 계정을 만들면, 모든 권한을 가진 root 계정이 생성된다. 하지만, 이 root 계정을 직접 사용하는 것은 위험하기 때문에 권한이 설정된 그룹을 생성하고, 그 그룹에 유저를 추가해서 사용해야한다. 정리하면 아래와 같다.

iam 그룹 실습 오버뷰
  1. root 계정으로 IAM 대시보드

IAM은 글로벌 서비스기 때문에 region을 선택할 필요가 없다.

root 계정으로 대시보드 들어가기
  1. IAM 유저 생성하기

IAM 유저를 생성해서 제공할 수 있다. 사용자 아래 숫자를 클릭하면 사용자 대시보드가 나온다.

IAM 사용자 생성하기1

그 다음 사용자 이름과 사용자 지정 암호를 입력하고 다음을 클릭한다.

IAM 사용자 생성하기2

사용자의 권한을 설정하기 위해 그룹에 사용자 추가를 선택하고 그룹 생성 버튼을 누른다.

그룹 생성하기

그 다음 security 그룹을 생성하고, 그룹에 유저를 추가한다. 마지막으로 유저에 태그를 추가하여 보안팀임을 알린다.

태그 설정

IAM 그룹 만들기

개발팀1개발팀2 그룹을 만들고 권한을 부여하려고 한다.

  1. IAM 유저 로그인

IAM 유저는 아래와 같은 특정한 URL을 통해 접속하거나 AWS 콘솔에서 IAM 사용자로 로그인할 수 있고, 이 때 계정 생성할 때 작성한 사용자 이름암호를 작성해야한다.

https://533385215525.signin.aws.amazon.com/console

로그인을 성공하면 아래와 같이 securityUser1 계정으로 접속할 수 있다.

iam 유저 로그인
  1. 개발팀 그룹 만들기

사용자를 생성할 때처럼 IAM 대시보드에서 사용자 그룹 아래 숫자를 클릭하면 사용자 그룹 대시보드가 뜬다. 대시보드에서 그룹 생성 버튼을 누르면 그룹을 만들 수 있다.

사용자 만들 때와 동일하게 그룹 생성할 때도 권한을 추가할 수 있다. 그룹을 생성하면 아래와 같이 볼 수 있다.

개발1팀 그룹 권한

개발팀의 사용자를 만드는 것은 IAM 사용자 생성법을 참고하면된다. 또한 개발2팀 그룹 생성도 위와 같이 하면된다.

IAM 정책 - inline으로 권한 부여하기

팀장님 IAM 계정 만들기위해서 두 팀이 가진 모든 권한을 가진 IAM 정책을 생성하고 부여해야한다. IAM 정책 구조는 간단히 Statement 안에 어떤 권한을 허가할지 거부할지 작성한다.

실제로 그룹에 권한을 추가할 때 아래처럼 정책을 추가할 수 있다.

그룹 정책 추가

하지만 아래처럼 inline으로 정책을 설정할 수 있다.

iam-policy.json
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Statement1",
			"Effect": "Deny",
			"Action": [
				"rds-db:*",
				"ec2:*"
			],
			"Resource": [
				"*"
			]
		},
		{
			"Sid": "Statement2",
			"Effect": "Allow",
			"Action": [
				"iam:*",
				"rolesanywhere:*"
			],
			"Resource": [
				"*"
			]
		}
	]
}
그룹 정책 정리

엑세스 관리자를 통해 사용한 권한 확인하기

그룹이 허용되는 서비스 중에 가장 최근 액세스 날짜를 확인할 수 있다. 클라우드 관리자는 이를 통해 그룹이 현재 필요한 권한을 확인할 수 있고, 최소권한원칙을 위해 필요하지 않는 권한을 제거할 수 있다.

그룹 엑세스 메니지