먼저 IAM Permission Policy 를 이용하여 MFA 사용을 강제하도록 하는 방법을 살펴보도록 하겠습니다. IAM Permission Policy 는 허용하고자 하는 행위와 차단하고자 하는 행위를 적절하게 구분하여 구성할 수 있는데 이 때 “aws:MultiFactorAuthPresent” 조건을 이용하여 Policy 를 생성하여 사용자의 API 호출에 MFA 정보가 포함되어 있는지 여부를 확인한 후 MFA 를 사용하지 않은 사용자에 대한 API 호출을 차단할 수 있습니다.
이와 같은 IAM Permission Policy 를 작성할 때 한 가지 유의할 사항이 있는데요. 먼저 아래와 같은 IAM Permission Policy 를 살펴보도록 하겠습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BlockMostAccessUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:ListVirtualMFADevices",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:ListAccountAliases",
"iam:ListUsers",
"iam:ListSSHPublicKeys",
"iam:ListAccessKeys",
"iam:ListServiceSpecificCredentials",
"iam:ListMFADevices",
"iam:GetAccountSummary",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "false"
}
}
},
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
이 Policy 는 얼핏 보기에는 MFA 인증을 사용하지 않은 사용자의 행위는 차단하고 MFA 를 사용한 사용자에 대해서만 허용하도록 생성되어 있는 것 같지만 위 정책의 내용 중 Deny 와 관련한 부분만을 한글로 풀어서 정리해보면 다음과 같습니다.
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "false"
}
}API 요청이 왔을 때 "aws:MultiFactorAuthPresent" 여부를 판단할 수 있는 "mfaAuthenticated" 라는 항목이 포함되어 있고 그 값이 "false" 인 경우 즉, MFA 인증을 사용하지 않은 경우에는 모든 행위를 차단한다. 단, API 요청에 "mfaAuthenticated" 라는 항목이 포함되어 있지 않은 경우는 Condition 의 조건을 만족하지 않으므로 ("aws:MultiFactorAuthPresent" 의 값이 "false" 인지 "true" 인지 확인할 수 없으므로) 차단하지 않는다.
즉, 사용자의 API 요청에 mfaAuthenticated 라는 항목이 포함되어 있으면 그 값을 기준으로 허용 혹은 차단하지만 만일 API 요청에 mfaAuthenticated 이 포함되어 있지 않다면 차단하지 않는다는 것입니다. 여기서 중요한 점은 여러분들이 API 호출을 할 때 AssumeRole 이나 GetSessionToken 과 같은 방식을 이용하여 Token 을 발급받은 후 API 를 호출하는 것이 아니라 IAM User 에 할당된 Access Key 와 Secret Access Key 를 이용하여 API 를 호출하는 경우에는 API 요청에 mfaAuthenticated 가 포함되어 있지 않습니다. 따라서, 결과적으로는 위와 같은 정책이 적용이 되어 있는 환경에서는 IAM 사용자가 자신의 Access Key 와 Secret Access Key 를 사용하고 MFA 를 사용하지 않더라도 차단되지 않게 됩니다.
이와 같은 상황은 관리자가 의도한 상황이 아닐텐데요. 처음의 의도처럼 MFA 를 사용하지 않는 사용자를 차단하기위해서는 아래와 같이 IAM Permission Policy 를 수정하여야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BlockMostAccessUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:ListVirtualMFADevices",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:ListAccountAliases",
"iam:ListUsers",
"iam:ListSSHPublicKeys",
"iam:ListAccessKeys",
"iam:ListServiceSpecificCredentials",
"iam:ListMFADevices",
"iam:GetAccountSummary",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
},
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
이 정책이 기존 정책과 다른 점은 Condition 내의 비교 조건이 “Bool” 에서 “BoolIfExists” 로 바뀐 것인데요.
“Bool” 과 “BoolIfExists” 는 다음과 같은 차이점이 있습니다.
Bool = 해당 항목의 값이 “True” 인지 “False” 인지 검사합니다. 만일 해당 항목이 없으면 Condition 조건을 만족 여부를 판단할 수 없으므로 Condition 을 만족하지 않은 것으로 간주합니다. 즉, Condition 을 만족하지 않는다는 것은 해당 Statement 의 Action 이 적용되지 않는다는 의미입니다.
BoolIfExists = 해당 항목이 있으면 그 값이 “True” 인지 “False” 인지 검사합니다. 만일 해당 항목이 없으면 Condition 조건을 만족한 것으로 간주합니다.(다르게 표현하면, Condition 자체가 없는 정책으로 판단합니다.) 즉, Condition 의 조건을 만족하므로 해당 Statement 의 Action 이 적용되게 됩니다.
따라서, 이렇게 바뀐 정책 부분을 다시 동일하게 한글로 풀어서 정리해보면 다음과 같습니다.
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}API 요청이 왔을 때 mfaAuthenticated 라는 항목이 포함되어 있고 그 값이 "false" 인 경우 즉, MFA 인증을 사용하지 않은 경우에는 모든 행위를 차단한다. 만일, API 요청에 mfaAuthenticated 라는 항목이 포함되어 있지 않은 경우라면 컨디션 값을 만족하는 것으로 간주하므로 모든 API 요청을 차단한다.즉, mfaAuthenticated 항목이 없어도 차단되고 mfaAuthenticated 의 값이 "false" 여도 차단된다.
이제 ..IfExists 가 어떤 의미를 갖고 동작하는지에 대해 알게 되셨는데요. 비단 MFA 적용 뿐만 아니라 IAM Policy 를 사용하실 때 IfExists 를 적절하게 사용하시면 보다 효율적이고 관리자가 의도한 정책을 생성하는데 도움이 될 수 있습니다.
감사합니다.