GITHUB
이 문서에서는 Amazon S3를 사용하여 GitHub 감사 로그를 Google Security Operations에 수집하는 방법을 설명합니다. 파서는 다양한 grok 패턴을 사용하여 'message' 필드에서 데이터를 추출하려고 시도하며 JSON 형식과 비 JSON 형식을 모두 처리합니다. 추출된 'process_type'을 기반으로 grok, kv, 기타 필터를 사용하여 원시 로그 데이터를 통합 데이터 모델 (UDM) 스키마에 매핑하는 특정 파싱 로직을 적용합니다.
시작하기 전에
다음 기본 요건이 충족되었는지 확인합니다.
- Google SecOps 인스턴스
- 엔터프라이즈 소유자 권한이 있는 GitHub Enterprise Cloud 테넌트에 대한 권한 액세스
- AWS (S3, IAM)에 대한 권한 액세스
GitHub Enterprise Cloud 필수사항 수집 (엔터프라이즈 액세스)
- GitHub Enterprise Cloud 관리 콘솔에 로그인합니다.
- 엔터프라이즈 설정 > 설정 > 감사 로그 > 로그 스트리밍으로 이동합니다.
- 감사 로그 스트리밍을 구성하려면 엔터프라이즈 소유자 권한이 있어야 합니다.
- 다음 세부정보를 복사하여 안전한 위치에 저장합니다.
- GitHub Enterprise 이름
- 엔터프라이즈의 조직 이름
Google SecOps용 AWS S3 버킷 및 ID 및 액세스 관리 구성
- 이 사용자 가이드(버킷 만들기)에 따라 Amazon S3 버킷을 만듭니다.
- 나중에 참조할 수 있도록 버킷 이름과 리전을 저장합니다 (예:
github-audit-logs
). - 이 사용자 가이드(IAM 사용자 만들기)에 따라 사용자를 만듭니다.
- 생성된 사용자를 선택합니다.
- 보안 사용자 인증 정보 탭을 선택합니다.
- 액세스 키 섹션에서 액세스 키 만들기를 클릭합니다.
- 사용 사례로 서드 파티 서비스를 선택합니다.
- 다음을 클릭합니다.
- 선택사항: 설명 태그를 추가합니다.
- 액세스 키 만들기를 클릭합니다.
- .CSV 파일 다운로드를 클릭하여 향후 참조할 수 있도록 액세스 키와 비밀 액세스 키를 저장합니다.
- 완료를 클릭합니다.
GitHub S3 스트리밍의 IAM 정책 구성
- AWS 콘솔에서 IAM > 정책 > 정책 만들기 > JSON 탭으로 이동합니다.
- 다음 정책을 복사하여 붙여넣습니다.
정책 JSON (다른 버킷 이름을 입력한 경우
github-audit-logs
대체):{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::github-audit-logs/*" } ] }
다음 > 정책 만들기를 클릭합니다.
정책 이름을
GitHubAuditStreamingPolicy
로 지정하고 정책 만들기를 클릭합니다.이전에 만든 IAM 사용자로 돌아갑니다.
권한 탭을 선택합니다.
권한 추가 > 정책 직접 연결을 클릭합니다.
GitHubAuditStreamingPolicy
을 검색하여 선택합니다.다음 > 권한 추가를 클릭합니다.
GitHub Enterprise Cloud 감사 로그 스트리밍 구성
- 엔터프라이즈 소유자로 GitHub Enterprise Cloud에 로그인합니다.
- 프로필 사진을 클릭한 다음 엔터프라이즈 설정을 클릭합니다.
- 엔터프라이즈 계정 사이드바에서 설정 > 감사 로그 > 로그 스트리밍을 클릭합니다.
- 스트림 구성을 선택하고 Amazon S3를 클릭합니다.
- 인증에서 액세스 키를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 리전: 버킷의 리전을 선택합니다 (예:
us-east-1
). - 버킷: 스트리밍할 버킷의 이름을 입력합니다 (예:
github-audit-logs
). - 액세스 키 ID: IAM 사용자의 액세스 키 ID를 입력합니다.
- 보안 비밀 키: IAM 사용자의 보안 비밀 키를 입력합니다.
- 리전: 버킷의 리전을 선택합니다 (예:
- 엔드포인트 확인을 클릭하여 GitHub가 Amazon S3 엔드포인트에 연결하고 쓸 수 있는지 확인합니다.
- 엔드포인트 인증이 완료되면 저장을 클릭합니다.
Google SecOps용 읽기 전용 IAM 사용자 및 키 만들기
- AWS 콘솔 > IAM > 사용자 > 사용자 추가로 이동합니다.
- Add users를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 사용자:
secops-reader
를 입력합니다. - 액세스 유형: 액세스 키 – 프로그래매틱 액세스를 선택합니다.
- 사용자:
- 사용자 만들기를 클릭합니다.
- 최소 읽기 정책 (맞춤)을 연결합니다. 사용자 > secops-reader > 권한 > 권한 추가 > 정책 직접 연결 > 정책 만들기
JSON:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::github-audit-logs/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::github-audit-logs" } ] }
이름 =
secops-reader-policy
정책 만들기 > 검색/선택 > 다음 > 권한 추가를 클릭합니다.
secops-reader
의 액세스 키를 만듭니다. 보안 사용자 인증 정보 > 액세스 키 > 액세스 키 만들기 >.CSV
다운로드 (이 값을 피드에 붙여넣음).
GitHub 로그를 수집하도록 Google SecOps에서 피드 구성
- SIEM 설정> 피드로 이동합니다.
- + 새 피드 추가를 클릭합니다.
- 피드 이름 필드에 피드 이름을 입력합니다 (예:
GitHub audit logs
). - 소스 유형으로 Amazon S3 V2를 선택합니다.
- 로그 유형으로 GitHub를 선택합니다.
- 다음을 클릭합니다.
- 다음 입력 파라미터의 값을 지정합니다.
- S3 URI:
s3://github-audit-logs/
- 소스 삭제 옵션: 환경설정에 따라 삭제 옵션을 선택합니다.
- 최대 파일 기간: 지난 일수 동안 수정된 파일을 포함합니다. 기본값은 180일입니다.
- 액세스 키 ID: S3 버킷에 액세스할 수 있는 사용자 액세스 키입니다.
- 보안 비밀 액세스 키: S3 버킷에 액세스할 수 있는 사용자 보안 비밀 키입니다.
- 애셋 네임스페이스: 애셋 네임스페이스입니다.
- 수집 라벨: 이 피드의 이벤트에 적용된 라벨입니다.
- S3 URI:
- 다음을 클릭합니다.
- 확정 화면에서 새 피드 구성을 검토한 다음 제출을 클릭합니다.
UDM 매핑 테이블
로그 필드 | UDM 매핑 | 논리 |
---|---|---|
actor |
principal.user.userid |
값은 actor 필드에서 가져옵니다. |
actor_id |
principal.user.attribute.labels.value |
값은 actor_id 필드에서 가져옵니다. |
actor_ip |
principal.ip |
값은 actor_ip 필드에서 가져옵니다. |
actor_location.country_code |
principal.location.country_or_region |
값은 actor_location.country_code 필드에서 가져옵니다. |
application_name |
target.application |
값은 application_name 필드에서 가져옵니다. |
business |
target.user.company_name |
값은 business 필드에서 가져옵니다. |
business_id |
target.resource.attribute.labels.value |
값은 business_id 필드에서 가져옵니다. |
config.url |
target.url |
값은 config.url 필드에서 가져옵니다. |
created_at |
metadata.event_timestamp |
값은 UNIX 밀리초에서 타임스탬프로 변환됩니다. |
data.cancelled_at |
extensions.vulns.vulnerabilities.scan_end_time |
값이 ISO8601 형식에서 타임스탬프로 변환됩니다. |
data.email |
target.email |
값은 data.email 필드에서 가져옵니다. |
data.event |
security_result.about.labels.value |
값은 data.event 필드에서 가져옵니다. |
data.events |
security_result.about.labels.value |
값은 data.events 필드에서 가져옵니다. |
data.head_branch |
security_result.about.labels.value |
값은 data.head_branch 필드에서 가져옵니다. |
data.head_sha |
target.file.sha256 |
값은 data.head_sha 필드에서 가져옵니다. |
data.hook_id |
target.resource.attribute.labels.value |
값은 data.hook_id 필드에서 가져옵니다. |
data.started_at |
extensions.vulns.vulnerabilities.scan_start_time |
값이 ISO8601 형식에서 타임스탬프로 변환됩니다. |
data.team |
target.user.group_identifiers |
값은 data.team 필드에서 가져옵니다. |
data.trigger_id |
security_result.about.labels.value |
값은 data.trigger_id 필드에서 가져옵니다. |
data.workflow_id |
security_result.about.labels.value |
값은 data.workflow_id 필드에서 가져옵니다. |
data.workflow_run_id |
security_result.about.labels.value |
값은 data.workflow_run_id 필드에서 가져옵니다. |
enterprise.name |
additional.fields.value.string_value |
값은 enterprise.name 필드에서 가져옵니다. |
external_identity_nameid |
target.user.email_addresses |
값이 이메일 주소인 경우 target.user.email_addresses 배열에 추가됩니다. |
external_identity_nameid |
target.user.userid |
값은 external_identity_nameid 필드에서 가져옵니다. |
external_identity_username |
target.user.user_display_name |
값은 external_identity_username 필드에서 가져옵니다. |
hashed_token |
network.session_id |
값은 hashed_token 필드에서 가져옵니다. |
job_name |
target.resource.attribute.labels.value |
값은 job_name 필드에서 가져옵니다. |
job_workflow_ref |
target.resource.attribute.labels.value |
값은 job_workflow_ref 필드에서 가져옵니다. |
org |
target.administrative_domain |
값은 org 필드에서 가져옵니다. |
org_id |
additional.fields.value.string_value |
값은 org_id 필드에서 가져옵니다. |
programmatic_access_type |
additional.fields.value.string_value |
값은 programmatic_access_type 필드에서 가져옵니다. |
public_repo |
additional.fields.value.string_value |
값은 public_repo 필드에서 가져옵니다. |
public_repo |
target.location.name |
값이 'false'이면 'PRIVATE'에 매핑됩니다. 그렇지 않으면 'PUBLIC'으로 매핑됩니다. |
query_string |
additional.fields.value.string_value |
값은 query_string 필드에서 가져옵니다. |
rate_limit_remaining |
additional.fields.value.string_value |
값은 rate_limit_remaining 필드에서 가져옵니다. |
repo |
target.resource.name |
값은 repo 필드에서 가져옵니다. |
repo_id |
additional.fields.value.string_value |
값은 repo_id 필드에서 가져옵니다. |
repository_public |
additional.fields.value.string_value |
값은 repository_public 필드에서 가져옵니다. |
request_body |
additional.fields.value.string_value |
값은 request_body 필드에서 가져옵니다. |
request_method |
network.http.method |
값이 대문자로 변환됩니다. |
route |
additional.fields.value.string_value |
값은 route 필드에서 가져옵니다. |
status_code |
network.http.response_code |
값이 정수로 변환됩니다. |
timestamp |
metadata.event_timestamp |
값은 UNIX 밀리초에서 타임스탬프로 변환됩니다. |
token_id |
additional.fields.value.string_value |
값은 token_id 필드에서 가져옵니다. |
token_scopes |
additional.fields.value.string_value |
값은 token_scopes 필드에서 가져옵니다. |
transport_protocol_name |
network.application_protocol |
값이 대문자로 변환됩니다. |
url_path |
target.url |
값은 url_path 필드에서 가져옵니다. |
user |
target.user.user_display_name |
값은 user 필드에서 가져옵니다. |
user_agent |
network.http.user_agent |
값은 user_agent 필드에서 가져옵니다. |
user_agent |
network.http.parsed_user_agent |
값이 파싱됩니다. |
user_id |
target.user.userid |
값은 user_id 필드에서 가져옵니다. |
workflow.name |
security_result.about.labels.value |
값은 workflow.name 필드에서 가져옵니다. |
workflow_run.actor.login |
principal.user.userid |
값은 workflow_run.actor.login 필드에서 가져옵니다. |
workflow_run.event |
additional.fields.value.string_value |
값은 workflow_run.event 필드에서 가져옵니다. |
workflow_run.head_branch |
security_result.about.labels.value |
값은 workflow_run.head_branch 필드에서 가져옵니다. |
workflow_run.head_sha |
target.file.sha256 |
값은 workflow_run.head_sha 필드에서 가져옵니다. |
workflow_run.id |
target.resource.attribute.labels.value |
값은 workflow_run.id 필드에서 가져옵니다. |
workflow_run.workflow_id |
security_result.about.labels.value |
값은 workflow_run.workflow_id 필드에서 가져옵니다. |
해당 사항 없음 | metadata.event_type |
값은 action 및 actor 필드를 기반으로 결정됩니다. action 필드에 '_member'가 포함된 경우 값은 'USER_RESOURCE_UPDATE_PERMISSIONS'로 설정됩니다. action 필드가 비어 있지 않고 actor 필드가 비어 있지 않으면 값이 'USER_RESOURCE_UPDATE_CONTENT'로 설정됩니다. 그 외에는 값이 'USER_RESOURCE_ACCESS'로 설정됩니다. |
해당 사항 없음 | metadata.log_type |
값은 'GITHUB'로 설정됩니다. |
해당 사항 없음 | metadata.product_name |
값은 'GITHUB'로 설정됩니다. |
해당 사항 없음 | metadata.vendor_name |
값은 'GITHUB'로 설정됩니다. |
해당 사항 없음 | target.resource.resource_type |
값은 'STORAGE_OBJECT'로 설정됩니다. |
해당 사항 없음 | security_result.about.labels.key |
값은 해당 data 필드를 기반으로 상수 문자열로 설정됩니다. 예를 들어 data.workflow_id 의 경우 키가 'Workflow Id'로 설정됩니다. |
해당 사항 없음 | target.resource.attribute.labels.key |
값은 해당 data 필드를 기반으로 상수 문자열로 설정됩니다. 예를 들어 data.hook_id 의 경우 키가 'Hook Id'로 설정됩니다. |
도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가로부터 답변을 받으세요.