AWS CDK 100 Drill Exercises #002: IAM 기본 — 사용자, 역할 및 보안 비밀번호 관리

발행: (2025년 12월 10일 오전 01:00 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

소개

이 글은 AWS CDK 100 Drill Exercises 시리즈의 두 번째 연습문제입니다.

시리즈에 대한 자세한 내용은 이 소개 글을 참고하세요.

첫 번째 연습문제에서 S3 기본 개념을 배운 뒤(첫 번째 연습문제), 이제 AWS Identity and Access Management (IAM) 로 들어갑니다. IAM은 AWS 보안의 기반으로, 누가 리소스에 접근할 수 있는지와 어떤 작업을 할 수 있는지를 제어합니다.

왜 S3 다음에 IAM인가?

  • 보안 기반 – IAM은 모든 AWS 리소스를 보호하는 데 필수적입니다.
  • 실제 필요성 – 모든 AWS 배포에서는 적절한 접근 관리가 필요합니다.
  • CDK 통합 – CDK가 IAM 정책과 역할을 어떻게 생성하는지 이해합니다.
  • 모범 사례 – 초기부터 보안 패턴을 배우면 향후 취약점을 예방할 수 있습니다.

배울 내용

  • CDK가 IAM 사용자, 그룹, 역할을 생성하는 방법.
  • AWS Secrets Manager 로 안전한 비밀번호 관리.
  • 관리형 정책과 인라인 정책의 차이점.
  • MFA 요구 조건이 포함된 스위치‑롤 구현.
  • CloudFormation의 동적 비밀 해석.
  • IAM 보안 모범 사례.

📁 코드 저장소: 모든 예제는 GitHub 에서 확인할 수 있습니다.

아키텍처 개요

네 개의 construct에 걸쳐 여섯 가지 패턴을 구현합니다.

Construct 1: 기본 사용자 (CDKDefaultUser)

  • 패턴 1 – 최소 IAM 사용자 설정.

Construct 2: 비밀번호 관리 사용자 (IAMUserWithPassword)

  • 패턴 2A – 하드코딩된 비밀번호 (⚠️ 권장되지 않음).
  • 패턴 2B – Secrets Manager 로 안전하게 비밀번호 관리 (✅ 권장).
  • 패턴 3A – AWS 관리형 정책 연결.
  • 패턴 3B – 인라인 정책 연결.

Construct 3: 그룹 관리 사용자 (IamUserGroup)

  • 패턴 4 – 그룹 기반 권한 관리.

Construct 4: 스위치 역할 사용자 (SwitchRoleUser)

  • 패턴 5 – MFA가 요구되는 역할 가정.

사전 요구 사항

  • AWS CLI v2 설치 및 구성.
  • Node.js 20+.
  • AWS CDK CLI (npm install -g aws-cdk).
  • 기본 TypeScript 지식.
  • AWS 계정 (Free Tier 로도 가능).
  • IAM 개념에 대한 이해 (사용자, 역할, 정책).

프로젝트 디렉터리 구조

iam-basics/
├── bin/
   └── iam-basics.ts                      # 애플리케이션 진입점
├── lib/
   ├── stacks/
   └── iam-basics-stack.ts            # 메인 스택 정의
   └── constructs/
       ├── iam-user-with-password.ts      # 패턴 2‑3
       ├── iam-user-with-group.ts         # 패턴 4
       └── iam-user-with-switch-role.ts   # 패턴 5
├── test/
   ├── compliance/
   └── cdk-nag.test.ts                # 테스트 (아래 설명)
   ├── snapshot/
   └── snapshot.test.ts             # 테스트 (아래 설명)
   └── unit/
       └── iam-basics.test.ts             # 테스트 (아래 설명)
├── cdk.json
├── package.json
└── tsconfig.json

패턴 1: CDK 기본 사용자 이해

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam';

export class IamBasicsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 최소 IAM 사용자 설정
    const cdkDefaultUser = new iam.User(this, 'CDKDefaultUser', {});
  }
}

생성된 CloudFormation

{
  "Resources": {
    "CDKDefaultUserF7AAA71A": {
      "Type": "AWS::IAM::User",
      "Metadata": {
        "aws:cdk:path": "Dev/DrillexercisesIamBasics/CDKDefaultUser/Resource"
      }
    }
  }
}

기본 구성 세부 정보

  • 사용자 이름 – AWS에서 자동 생성.
  • 비밀번호 – 없음; 콘솔 접근이 기본적으로 비활성화됨.
  • 정책 – 권한 없음 (최소 권한 원칙).
  • 액세스 키 – 없음; 프로그래밍 접근이 비활성화됨.

명시적으로 권한을 부여하기 전까지 이 사용자는 어떤 리소스에도 접근할 수 없습니다.

패턴 2A: 하드코딩된 비밀번호를 가진 사용자 (⚠️ 권장되지 않음)

⚠️ 이 패턴은 프로덕션에서 비밀번호를 하드코딩하는 것이 얼마나 위험한지 보여주기 위한 예시입니다.

const userWithPassword = new iam.User(this, 'PasswordUser', {
  password: cdk.SecretValue.unsafePlainText('InitialPassword123!'),
  passwordResetRequired: true,
});

생성된 CloudFormation

{
  "UserWithPasswordPasswordUserA5E8EDB8": {
    "Type": "AWS::IAM::User",
    "Properties": {
      "LoginProfile": {
        "Password": "InitialPassword123!",
        "PasswordResetRequired": true
      }
    }
  }
}

왜 위험한가

  • 소스 코드에 비밀번호 – 버전 관리 시스템에 그대로 노출됩니다.
  • CloudFormation 템플릿 – 콘솔 및 로그에 비밀번호가 드러납니다.
  • 암호화 없음 – 평문으로 저장됩니다.
  • 감사 추적 어려움 – 비밀번호 변경 이력을 파악하기 힘듭니다.

프로덕션에서는 절대 이 패턴을 사용하지 마세요.

패턴 2B: Secrets Manager 를 이용한 사용자 (✅ 권장)

import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as cdk from 'aws-cdk-lib';

const userName = 'SecretsPasswordUser';

// 자동 생성된 비밀번호로 비밀을 생성
const userSecret = new secretsmanager.Secret(this, 'UserSecret', {
  generateSecretString: {
    secretStringTemplate: JSON.stringify({ username: userName }),
    generateStringKey: 'password',
    excludePunctuation: true,
    passwordLength: 16,
    requireEachIncludedType: true,
  },
});

// Secrets Manager 에서 비밀번호를 가져와 IAM 사용자 생성
const user = new iam.User(this, 'SecretsPasswordUser', {
  userName: userName,
  password: userSecret.secretValueFromJson('password'),
  passwordResetRequired: true,
});

// 사용자가 자신의 비밀번호를 변경할 수 있도록 AWS 관리형 정책 연결
user.addManagedPolicy(
  iam.ManagedPolicy.fromAwsManagedPolicyName('IAMUserChangePassword')
);

이 방법은 비밀번호를 Secrets Manager에 안전하게 저장하고, 비밀을 하드코딩하지 않으며, 필요 시 비밀번호 회전도 가능하게 합니다.

Back to Blog

관련 글

더 보기 »