CloudTrail로 Amazon S3 요청 식별
CloudTrail로 Amazon S3 요청 식별
Amazon S3에서 AWS CloudTrail 이벤트 로그로 요청을 식별할 수 있어요. AWS CloudTrail은 Amazon S3 요청을 식별하는 데 권장되는 방법이에요. 하지만 Amazon S3 서버 접근 로그를 사용 중이라면 "Amazon S3 서버 접근 로그로 요청 식별"을 참고하세요.
출처: 문서
본문
CloudTrail 로그에서 Amazon S3에 이루어진 요청 식별
CloudTrail이 버킷으로 이벤트를 전달하도록 설정한 후에는 Amazon S3 콘솔에서 목적지 버킷으로 객체가 들어오는 것을 보기 시작할 거예요. 이들은 다음과 같이 형식화돼요.
s3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/Region/yyyy/mm/dd
CloudTrail이 기록한 이벤트는 S3 버킷에 압축되고 gzip된 JSON 객체로 저장돼요. 요청을 효율적으로 찾으려면 Amazon Athena 같은 서비스를 사용해 CloudTrail 로그를 인덱싱하고 조회하는 것이 좋아요.
CloudTrail과 Athena에 대한 자세한 내용은 Amazon Athena User Guide의 파티션 프로젝션을 사용해 Athena에서 AWS CloudTrail 로그용 테이블 만들기를 참고하세요.
CloudTrail로 Amazon S3 Signature Version 2 요청 식별
CloudTrail 이벤트 로그로 Amazon S3에서 요청을 서명하는 데 사용된 API 서명 버전을 식별할 수 있어요. Signature Version 2 지원이 중단(더 이상 사용되지 않음)될 예정이므로 이 기능은 중요해요. 이후 Amazon S3는 Signature Version 2를 사용한 요청을 더 이상 받지 않으며, 모든 요청은 Signature Version 4 서명을 사용해야 해요.
워크플로 중 어떤 것이 Signature Version 2 서명을 사용하는지 확인하려면 CloudTrail을 사용할 것을 강력히 권장해요. 비즈니스에 영향을 방지하려면 대신 Signature Version 4를 사용하도록 라이브러리와 코드를 업그레이드해 해결하세요.
자세한 내용은 AWS re:Post의 발표: Amazon S3용 AWS CloudTrail이 강화된 보안 감사를 위한 새 필드 추가를 참고하세요.
참고: Amazon S3에 대한 CloudTrail 이벤트는
additionalEventData키 이름 아래의 요청 세부 정보에 서명 버전을 포함해요. Amazon S3의 객체에 이루어진GET,PUT,DELETE요청 같은 요청에서 서명 버전을 찾으려면 CloudTrail 데이터 이벤트를 활성화해야 해요. (이 기능은 기본적으로 꺼져 있어요.)
AWS CloudTrail은 Signature Version 2 요청을 식별하는 데 권장되는 방법이에요. Amazon S3 서버 접근 로그를 사용 중이라면 "Signature Version 2 요청 식별"을 참고하세요.
Amazon S3 Signature Version 2 요청 식별을 위한 Athena 쿼리 예시
예시 — 모든 Signature Version 2 이벤트를 선택하고 EventTime, S3_Action, Request_Parameters, Region, SourceIP, UserAgent만 출력 — 다음 Athena 쿼리에서 s3_cloudtrail_events_db.cloudtrail_table을 Athena 정보로 바꾸고, 필요에 따라 한도를 늘리거나 제거하세요.
SELECT EventTime, EventName as S3_Action, requestParameters as Request_Parameters, awsregion as AWS_Region, sourceipaddress as Source_IP, useragent as User_Agent
FROM s3_cloudtrail_events_db.cloudtrail_table
WHERE eventsource='s3.amazonaws.com'
AND json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'
LIMIT 10;
예시 — Signature Version 2 트래픽을 보내는 모든 요청자 선택
SELECT useridentity.arn, Count(requestid) as RequestCount
FROM s3_cloudtrail_events_db.cloudtrail_table
WHERE eventsource='s3.amazonaws.com'
and json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'
Group by useridentity.arn
Signature Version 2 데이터 파티셔닝
조회할 데이터가 많으면 파티션 테이블을 만들어 Athena의 비용과 실행 시간을 줄일 수 있어요.
이를 위해 다음과 같이 파티션이 있는 새 테이블을 만드세요.
CREATE EXTERNAL TABLE s3_cloudtrail_events_db.cloudtrail_table_partitioned(
eventversion STRING,
userIdentity STRUCT<
type:STRING,
principalid:STRING,
arn:STRING,
accountid:STRING,
invokedby:STRING,
accesskeyid:STRING,
userName:STRING,
sessioncontext:STRUCT<
attributes:STRUCT<
mfaauthenticated:STRING,
creationdate:STRING>,
sessionIssuer:STRUCT<
type:STRING,
principalId:STRING,
arn:STRING,
accountId:STRING,
userName:STRING>
>
>,
eventTime STRING,
eventSource STRING,
eventName STRING,
awsRegion STRING,
sourceIpAddress STRING,
userAgent STRING,
errorCode STRING,
errorMessage STRING,
requestParameters STRING,
responseElements STRING,
additionalEventData STRING,
requestId STRING,
eventId STRING,
resources ARRAY<STRUCT<ARN:STRING,accountId: STRING,type:STRING>>,
eventType STRING,
apiVersion STRING,
readOnly STRING,
recipientAccountId STRING,
serviceEventDetails STRING,
sharedEventID STRING,
vpcEndpointId STRING
)
PARTITIONED BY (region string, year string, month string, day string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.orc.OrcSerde'
STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.SymlinkTextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/';
그런 다음 파티션을 개별적으로 만들고, 만들지 않은 날짜의 결과는 얻을 수 없어요.
ALTER TABLE s3_cloudtrail_events_db.cloudtrail_table_partitioned ADD
PARTITION (region= 'us-east-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/us-east-1/2019/02/19/'
PARTITION (region= 'us-west-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/us-west-1/2019/02/19/'
PARTITION (region= 'us-west-2', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/us-west-2/2019/02/19/'
PARTITION (region= 'ap-southeast-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/ap-southeast-1/2019/02/19/'
PARTITION (region= 'ap-southeast-2', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/ap-southeast-2/2019/02/19/'
PARTITION (region= 'ap-northeast-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/ap-northeast-1/2019/02/19/'
PARTITION (region= 'eu-west-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/eu-west-1/2019/02/19/'
PARTITION (region= 'sa-east-1', year= '2019', month= '02', day= '19') LOCATION 's3://amzn-s3-demo-bucket1/AWSLogs/111122223333/CloudTrail/sa-east-1/2019/02/19/';
그런 다음 이 파티션을 기반으로 요청을 만들 수 있고, 전체 버킷을 로드할 필요가 없어요.
SELECT useridentity.arn,
Count(requestid) AS RequestCount
FROM s3_cloudtrail_events_db.cloudtrail_table_partitioned
WHERE eventsource='s3.amazonaws.com'
AND json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'
AND region='us-east-1'
AND year='2019'
AND month='02'
AND day='19'
Group by useridentity.arn
CloudTrail로 S3 객체 접근 식별
AWS CloudTrail 이벤트 로그로 GetObject, DeleteObject, PutObject 같은 데이터 이벤트에 대한 Amazon S3 객체 접근 요청을 식별하고 그 요청에 대한 추가 정보를 알아낼 수 있어요.
참고: AWS CloudTrail로 데이터 활동을 기록하는 경우 Amazon S3
DeleteObjects데이터 이벤트의 이벤트 레코드에는DeleteObjects이벤트와 해당 작업의 일부로 삭제된 각 객체에 대한DeleteObject이벤트가 모두 포함돼요. 이벤트 레코드에서 삭제된 객체에 대한 추가 가시성을 제외할 수 있어요. 자세한 내용은 AWS CloudTrail User Guide의 데이터 이벤트 필터링을 위한 AWS CLI 예시를 참고하세요.
다음 예시는 AWS CloudTrail 이벤트 로그에서 Amazon S3의 모든 PUT 객체 요청을 가져오는 방법을 보여줘요.
Amazon S3 객체 접근 요청 식별을 위한 Athena 쿼리 예시
다음 Athena 쿼리 예시에서 s3_cloudtrail_events_db.cloudtrail_table을 Athena 정보로 바꾸고 필요에 따라 날짜 범위를 수정하세요.
예시 — PUT 객체 접근 요청이 있는 모든 이벤트를 선택하고 EventTime, EventSource, SourceIP, UserAgent, BucketName, object, UserARN만 출력
SELECT
eventTime,
eventName,
eventSource,
sourceIpAddress,
userAgent,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName,
json_extract_scalar(requestParameters, '$.key') as object,
userIdentity.arn as userArn
FROM
s3_cloudtrail_events_db.cloudtrail_table
WHERE
eventName = 'PutObject'
AND eventTime BETWEEN '2019-07-05T00:00:00Z' and '2019-07-06T00:00:00Z'
예시 — GET 객체 접근 요청이 있는 모든 이벤트를 선택하고 EventTime, EventSource, SourceIP, UserAgent, BucketName, object, UserARN만 출력
SELECT
eventTime,
eventName,
eventSource,
sourceIpAddress,
userAgent,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName,
json_extract_scalar(requestParameters, '$.key') as object,
userIdentity.arn as userArn
FROM
s3_cloudtrail_events_db.cloudtrail_table
WHERE
eventName = 'GetObject'
AND eventTime BETWEEN '2019-07-05T00:00:00Z' and '2019-07-06T00:00:00Z'
예시 — 특정 기간에 버킷에 대한 모든 익명 요청자 이벤트를 선택하고 EventTime, EventName, EventSource, SourceIP, UserAgent, BucketName, UserARN, AccountID만 출력
SELECT
eventTime,
eventName,
eventSource,
sourceIpAddress,
userAgent,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName,
userIdentity.arn as userArn,
userIdentity.accountId
FROM
s3_cloudtrail_events_db.cloudtrail_table
WHERE
userIdentity.accountId = 'anonymous'
AND eventTime BETWEEN '2019-07-05T00:00:00Z' and '2019-07-06T00:00:00Z'
예시 — 인증에 ACL이 필요했던 모든 요청 식별 — 다음 Amazon Athena 쿼리 예시는 인증에 액세스 제어 목록(ACL)이 필요했던 S3 버킷에 대한 모든 요청을 식별하는 방법을 보여줘요. 요청 인증에 ACL이 필요했다면 additionalEventData의 aclRequired 값은 Yes예요. ACL이 필요 없었다면 aclRequired는 존재하지 않아요. 이 정보로 해당 ACL 권한을 적절한 버킷 정책으로 마이그레이션할 수 있어요. 버킷 정책을 만든 후에는 이 버킷에 대해 ACL을 비활성화할 수 있어요. ACL 비활성화에 대한 자세한 내용은 "ACL 비활성화를 위한 사전 요구 사항"을 참고하세요.
SELECT
eventTime,
eventName,
eventSource,
sourceIpAddress,
userAgent,
userIdentity.arn as userArn,
json_extract_scalar(requestParameters, '$.bucketName') as bucketName,
json_extract_scalar(requestParameters, '$.key') as object,
json_extract_scalar(additionalEventData, '$.aclRequired') as aclRequired
FROM
s3_cloudtrail_events_db.cloudtrail_table
WHERE
json_extract_scalar(additionalEventData, '$.aclRequired') = 'Yes'
AND eventTime BETWEEN '2022-05-10T00:00:00Z' and '2022-08-10T00:00:00Z'
참고:
- 이 쿼리 예시는 보안 모니터링에도 유용할 수 있어요. 예상하지 못했거나 권한이 없는 IP 주소나 요청자의
PutObject,GetObject호출 결과와 버킷에 대한 익명 요청을 검토할 수 있어요.- 이 쿼리는 로깅이 활성화된 시점부터의 정보만 검색해요.
Amazon S3 서버 접근 로그를 사용 중이라면 "객체 접근 요청 식별"을 참고하세요.