보고서 읽기 신원에 최소 권한 부여하기

AWSBeginner
지금 연습하기

소개

보고서 읽기 신원은 오늘 보고서가 필요하지만 다른 보고서와 급여는 비공개로 유지해야 합니다. 읽기 권한을 부여하고 범위를 좁힌 뒤 권한 경계를 테스트하고 정리 전에 회수합니다.

AWS Foundations에서 배운 호출자 신원과 ARN, S3에서 배운 객체 다운로드를 활용하세요. 새 VM은 CLI와 두 신원을 준비합니다. default는 연습을 관리하고 reader는 작업을 나타냅니다. /home/labex/project에서 작업하고 위쪽 AWS View에서 요청을 비교하세요.

인증 시험 관련 주제

인증 시험 태스크 실습 내용
Cloud Practitioner (CLF-C02) 태스크 2.3 IAM 정책, 작업 및 리소스 범위와 최소 권한.
Solutions Architect – Associate (SAA-C03) 태스크 1.1 IAM 정책, 작업 및 리소스 범위와 최소 권한.
Developer – Associate (DVA-C02) 태스크 2.1 IAM 정책, 작업 및 리소스 범위와 최소 권한.
CloudOps Engineer – Associate (SOA-C03) 태스크 4.1 IAM 정책, 작업 및 리소스 범위와 최소 권한.
Security – Specialty (SCS-C03) 태스크 4.2 기초 실습: IAM 정책, 작업 및 리소스 범위와 최소 권한.
Data Engineer – Associate (DEA-C01) 태스크 4.2 기초 실습: IAM 정책, 작업 및 리소스 범위와 최소 권한.
DevOps Engineer – Professional (DOP-C02) 태스크 6.1 기초 실습: IAM 정책, 작업 및 리소스 범위와 최소 권한.
Solutions Architect – Professional (SAP-C02) 태스크 2.3 기초 실습: IAM 정책, 작업 및 리소스 범위와 최소 권한.

실습 개요

개념도: IAM 자격 증명 정책으로 보고서 읽기 사용자가 S3의 오늘 보고서만 읽도록 허용하고 다른 보고서와 급여 데이터를 보호합니다.

읽기 신원에 보고서 접근 권한 부여하기

이 단계에서는 보고서 읽기를 허용하는 신원 정책을 작성하고 연결합니다. **신원 정책(identity policy)**은 사용자, 그룹, 역할에 연결됩니다. 허용하거나 거부할 작업을 설명하며 액세스 키는 포함하지 않습니다.

S3에서 객체 내용을 다운로드해 보았습니다. 여기서는 보고서 작업이 자체 제한된 신원으로 같은 다운로드를 해야 합니다. 운영자는 권한을 변경하고 조회자는 결과를 테스트합니다. 보고서 데이터는 제공되므로 권한 부여에 집중할 수 있습니다.

**AWS Identity and Access Management(IAM)**는 어떤 신원이 리소스에 어떤 작업을 수행할 수 있는지 제어합니다. 최소 권한은 작업에 필요한 권한만 부여합니다.

AWS CLI 프로필은 자격 증명과 설정을 선택하며 권한을 부여하지는 않습니다. 여기서 default는 연습 운영자이고 reader는 report-reader를 선택합니다. 먼저 두 신원을 확인하세요. --profile reader는 명령 하나에 작업 신원을 선택합니다. get-caller-identity는 자격 증명을 출력하지 않고 호출자 신원을 알려 줍니다.

cd /home/labex/project
aws sts get-caller-identity --query Arn --output text

기본 ARN은 user/iam01-operator로 끝납니다. 정책 관리에는 이 운영자 프로필을 사용하고 작업 테스트에는 reader 프로필을 사용하세요. 이 실습 운영자는 관리 작업을 위해 준비되어 있습니다. 프로덕션 보고서 애플리케이션은 제한된 역할을 사용해야 하며 이후 이를 연습합니다.

aws sts get-caller-identity --profile reader --query Arn --output text

reader ARN은 user/report-reader로 끝납니다. ARN, 즉 Amazon Resource Name은 리소스를 식별합니다. S3 객체의 ARN에는 버킷과 완전한 객체 키가 포함됩니다. 버킷 ARN만으로는 그 안의 객체를 식별하지 않습니다.

reader에는 처음에 정책이 없습니다. 권한을 부여하기 전에 읽기를 테스트하세요.

aws s3api get-object --profile reader --bucket labex-iam01-reports --key reports/today.txt before.txt || true

보고서 다운로드가 아닌 AccessDenied를 예상하세요. || true는 의도적으로 실패하는 이 명령이 붙여 넣은 명령 순서를 중단하지 않고 끝나도록 합니다. 오류를 읽으세요. 연결 오류는 IAM 거부의 증거가 아닙니다.

JSON 정책은 세 가지 핵심 필드를 사용합니다. Effect는 Allow 또는 Deny이고 Action은 서비스 작업의 이름이며 Resource는 해당 작업이 영향을 줄 수 있는 ARN을 제한합니다. s3:GetObject는 객체 바이트 읽기를 허용합니다. 아래의 *는 오늘과 어제를 포함하여 reports/ 접두사의 객체 키와 일치합니다. private/나 다른 버킷과는 일치하지 않습니다. Version은 보고서 버전이 아닌 정책 언어를 선택합니다.

다음 히어 도큐먼트는 JSON 마커 사이의 줄을 report-policy.json에 기록합니다. >는 로컬 파일을 교체하고 따옴표로 감싼 마커는 셸이 내용을 확장하지 않도록 합니다.

cat > report-policy.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::labex-iam01-reports/reports/*"
    }
  ]
}
JSON

파일 작성만으로는 reader에 권한이 부여되지 않습니다. put-user-policy는 이 사용자에 직접 저장되는 정책인 **인라인 정책(inline policy)**을 연결합니다. --policy-name은 정책을 식별하며 이후 같은 이름을 사용하면 업데이트합니다. file://는 CLI가 로컬 파일에서 문서를 읽도록 합니다.

aws iam put-user-policy \
  --user-name report-reader \
  --policy-name ReportRead \
  --policy-document file://report-policy.json

업데이트에 성공하면 보통 출력이 없습니다. 이제 reader의 자격 증명으로 보고서를 요청하세요. 마지막 인수는 로컬 대상 파일입니다.

aws s3api get-object \
  --profile reader \
  --bucket labex-iam01-reports \
  --key reports/today.txt today.txt
cat today.txt

Daily orders: 145를 예상하세요. ETag 같은 S3 응답 필드는 다운로드한 객체를 식별하며 파일 자체에는 보고서 바이트가 들어 있습니다.

aws s3api get-object \
  --profile reader \
  --bucket labex-iam01-reports \
  --key reports/yesterday.txt yesterday.txt

정책이 전체 reports 접두사를 포함하므로 어제도 성공합니다. 업무에는 오늘 보고서만 필요하므로 이제 범위를 줄입니다.

리소스를 오늘 보고서로 좁히기

이 단계에서는 접두사 권한을 객체 ARN 하나로 교체하고 다른 리소스에 계속 접근할 수 없음을 증명합니다. **암시적 거부(implicit deny)**는 적용 가능한 정책 중 요청을 허용하는 정책이 없음을 뜻합니다. 관련 없는 객체마다 별도 Deny를 지정할 필요는 없습니다.

정책 범위를 좁히면 reader는 오늘 보고서를 다운로드할 수 있지만 다른 객체를 읽거나 변경 사항을 업로드할 수 없습니다.

로컬 정책을 교체하세요. 변경되는 것은 Resource뿐입니다. 정확한 키 reports/today.txt가 reports/*를 대체합니다.

cat > report-policy.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::labex-iam01-reports/reports/today.txt"
    }
  ]
}
JSON

같은 reader의 같은 인라인 정책을 업데이트하세요. 이 명령을 보내기 전에는 파일을 편집해도 IAM이 업데이트되지 않습니다.

aws iam put-user-policy \
  --user-name report-reader \
  --policy-name ReportRead \
  --policy-document file://report-policy.json

저장된 정책을 다시 읽으세요. --query PolicyDocument는 응답에서 문서를 선택하며 권한을 변경하지 않습니다.

aws iam get-user-policy \
  --user-name report-reader \
  --policy-name ReportRead \
  --query PolicyDocument

Resource가 reports/today.txt로 끝나는지 확인한 뒤 reader를 다시 테스트하세요.

aws s3api get-object \
  --profile reader \
  --bucket labex-iam01-reports \
  --key reports/today.txt today.txt

필요한 보고서는 여전히 다운로드됩니다. 다음 각 요청은 객체 ARN이 부여된 권한과 일치하지 않으므로 AccessDenied로 실패해야 합니다.

aws s3api get-object --profile reader --bucket labex-iam01-reports --key reports/yesterday.txt yesterday-denied.txt || true
aws s3api get-object --profile reader --bucket labex-iam01-reports --key private/payroll.txt payroll-denied.txt || true
aws s3api get-object --profile reader --bucket labex-iam01-reference --key reference.txt reference-denied.txt || true

이 객체들은 존재하며 운영자는 읽을 수 있습니다. NoSuchKey 응답은 객체 누락을 뜻하지만 이 권한 오류들은 reader의 리소스 경계를 보여 줍니다. AWS View에서 오늘은 Readable이고 다른 객체 세 개는 Denied입니다. 이 뷰는 같은 reader로 실제 읽기 요청을 보냅니다.

보고서 하나로 제한된 reader. 예시: 오늘만 읽을 수 있고 다른 기존 객체는 거부됩니다. 왼쪽 문서는 저장된 IAM 정책입니다.

명시적 거부와 Allow 부재 구분하기

이 단계에서는 비공개 접두사를 명시적으로 보호하고 작업 경계를 테스트합니다. **명시적 거부(explicit deny)**는 일치하는 Deny 문입니다. 다른 적용 가능한 신원 정책의 Allow보다 우선합니다. 문 순서로 Allow가 이를 무시하게 할 수는 없습니다.

정확한 읽기 권한을 유지하면서 두 번째 문을 추가하세요. s3:*는 모든 S3 작업과 일치하지만 이 Deny는 이 버킷의 private/ 접두사 아래 객체로 제한됩니다. 오늘 보고서에 대한 접근은 거부하지 않습니다.

cat > report-policy.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::labex-iam01-reports/reports/today.txt"
    },
    {
      "Effect": "Deny",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::labex-iam01-reports/private/*"
    }
  ]
}
JSON
aws iam put-user-policy \
  --user-name report-reader \
  --policy-name ReportRead \
  --policy-document file://report-policy.json

Deny는 비공개 경계를 강화합니다. 우선순위를 관찰하려면 이 버킷에 대한 두 번째 읽기 권한을 임시로 연결하세요. 통제된 테스트이므로 직후 제거합니다.

cat > temporary-read.json <<'JSON'
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam01-reports/*"}]}
JSON
aws iam put-user-policy \
  --user-name report-reader \
  --policy-name TemporaryRead \
  --policy-document file://temporary-read.json
aws s3api get-object --profile reader --bucket labex-iam01-reports --key private/payroll.txt payroll-denied.txt || true

TemporaryRead가 이 키를 허용해도 AccessDenied를 예상하세요. 일치하는 명시적 Deny가 우선합니다. 임시 권한을 제거하여 최소 권한을 복구하세요.

aws iam delete-user-policy --user-name report-reader --policy-name TemporaryRead

읽기 권한은 쓰기를 허용하지 않습니다. upload.txt는 제공된 미승인 대체 파일입니다. put-object는 바이트를 오늘 키에 저장하려고 시도하며 reader는 거부되어야 합니다.

aws s3api put-object --profile reader --bucket labex-iam01-reports --key reports/today.txt --body upload.txt || true

PutObject에 대해 AccessDenied를 예상하세요. 파일 누락이나 서비스 실패를 이 결과로 간주하지 마세요. 오늘을 다시 읽어 실패한 쓰기가 내용을 변경하지 않았는지 확인하세요.

aws s3api get-object \
  --profile reader \
  --bucket labex-iam01-reports \
  --key reports/today.txt today.txt
cat today.txt

여전히 Daily orders: 145가 들어 있어야 합니다. 최종 정책을 다시 읽고 좁은 Allow와 비공개 Deny를 확인하세요.

aws iam get-user-policy \
  --user-name report-reader \
  --policy-name ReportRead \
  --query PolicyDocument

접근을 회수하고 소유한 리소스 정리하기

이 단계에서는 reader의 정책을 회수하고 이 연습의 보고서 버킷만 삭제합니다. IAM 정책 정리와 데이터 정리는 별개입니다. 정책을 삭제해도 객체는 삭제되지 않고 객체를 삭제해도 자격 증명은 회수되지 않습니다.

기본 운영자로 ReportRead를 제거하세요. delete-user-policy는 이름으로 인라인 정책을 제거합니다.

aws iam delete-user-policy --user-name report-reader --policy-name ReportRead
aws iam list-user-policies --user-name report-reader

PolicyNames가 비어 있어야 합니다. 보고서가 아직 존재하는 동안 reader가 접근을 잃었는지 테스트하세요.

aws s3api get-object --profile reader --bucket labex-iam01-reports --key reports/today.txt revoked.txt || true

AccessDenied를 예상하세요. 이제 운영자로 소유한 키 세 개를 정확히 삭제합니다. 참조 버킷은 준비된 플랫폼 제공 리소스에 속하므로 온전히 유지해야 합니다.

aws s3api delete-object --bucket labex-iam01-reports --key reports/today.txt
aws s3api delete-object --bucket labex-iam01-reports --key reports/yesterday.txt
aws s3api delete-object --bucket labex-iam01-reports --key private/payroll.txt
aws s3api list-objects-v2 --bucket labex-iam01-reports

KeyCount가 0이고 Contents에 객체가 없는지 확인하세요. 성공한 이 인증 응답은 삭제 전에 소유한 버킷이 비어 있음을 보여 줍니다.

aws s3api delete-bucket --bucket labex-iam01-reports
aws s3api list-buckets --query 'Buckets[].Name'

labex-iam01-reference만 남습니다. 원래 바이트를 확인하세요.

aws s3api get-object --bucket labex-iam01-reference --key reference.txt reference.txt
cat reference.txt

Platform reference: keep을 예상하세요. AWS View에는 이제 No inline policy와 Reports bucket removed가 표시됩니다. 서비스 중단은 정리 성공이 아닌 사용 불가 상태로 표시됩니다. 일회성으로 준비된 신원은 실습 환경이 끝날 때 회수됩니다. 관련 없는 제공 리소스를 보존하면서 학습자가 만든 권한과 연습 데이터를 삭제했습니다.

요약

IAM 신원 정책을 연결하고 수정하며 Action과 Resource로 보고서 작업을 제한했습니다. 암시적 거부와 명시적 거부를 비교하고 읽기 권한이 쓰기를 허용하지 않음을 증명했습니다. 정책을 회수하고 소유한 데이터만 삭제했습니다. 접근을 검토할 때마다 의도한 성공과 금지된 작업을 모두 테스트하세요. 저장된 정책만으로는 애플리케이션에 올바른 권한이 부여되었음을 증명할 수 없습니다.

자세한 내용은 AWS 공식 문서를 참고하세요: IAM 정책 유형과 권한 문.