감사 이벤트 개발 가이드라인
GitLab v19.4요약
이 가이드는 감사 이벤트의 동작 방식과 새 감사 이벤트를 계측하는 방법을 설명합니다. 감사 이벤트는 GitLab Owner와 관리자가 애플리케이션 전반에서 수행된 중요한 작업의 기록을 확인할 수 있게 해 주는 도구입니다.
이 가이드는 감사 이벤트의 동작 방식과 새 감사 이벤트를 계측하는 방법을 설명합니다.
감사 이벤트 개요#
감사 이벤트는 GitLab Owner와 관리자가 애플리케이션 전반에서 수행된 중요한 작업의 기록을 확인할 수 있게 해 주는 도구입니다.
감사 이벤트로 적합하지 않은 경우#
어떤 이벤트든 감사 이벤트를 트리거할 수 있지만, 모든 이벤트가 그래야 하는 것은 아닙니다. 일반적으로 다음과 같은 이벤트는 감사 이벤트로 적합하지 않습니다.
- 특정 사용자 한 명에게 귀속되지 않는 이벤트.
- 관리자나 Owner 페르소나가 특별히 관심을 두지 않는 이벤트.
- 제품 기능 도입 현황을 추적하는 정보에 해당하는 이벤트.
- 방향 페이지의 계획에 없는 항목 논의에서 다루는 이벤트.
궁금한 점이 있으면 @gitlab-org/software-supply-chain-security/compliance에 문의해 해당 이벤트에 감사 이벤트가 적합한지, 아니면 다른 방식이 나은지 확인합니다.
감사 이벤트 스키마#
감사 이벤트를 계측하려면 다음 속성을 제공해야 합니다.
| 속성 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
name |
String | false | 감사할 작업 이름입니다. 이벤트 유형을 나타내며 오류 추적에 사용됩니다 |
author |
User | true | 변경을 수행한 사용자입니다. 내부 사용자일 수 있습니다. 예를 들어 휴면 프로젝트 삭제 감사 이벤트는 GitLab-Admin-Bot 이 수행합니다. |
scope |
User, Project, Group, or Instance | true | 감사 이벤트가 속하는 범위입니다 |
target |
Object | true | 감사 대상 객체입니다 |
message |
String | true | 작업을 설명하는 메시지입니다(번역하지 않음) |
created_at |
DateTime | false | 작업이 발생한 시간입니다. 기본값은 DateTime.current 입니다 |
새 감사 이벤트 계측 방법#
- 새 감사 이벤트에 대한 YAML 타입 정의를 만듭니다.
- 작업 블록을 전달해
Gitlab::Audit::Auditor.audit를 호출합니다.
Gitlab::Audit::Auditor 서비스로 감사 이벤트를 계측하는 방법은 두 가지입니다.
- 여러 이벤트에는 블록을 사용합니다.
- 단일 이벤트에는 표준 메서드 호출을 사용합니다.
블록을 사용한 여러 이벤트 기록#
호출 스택 깊은 곳에서 이벤트가 발생할 때 이 방법을 사용할 수 있습니다.
예를 들어 사용자가 머지 리퀘스트 승인 규칙을 수정할 때 여러 감사 이벤트를 기록할 수 있습니다.
이 사용자 흐름에서는 승인자 변경과 승인 그룹 변경을 모두 감사하려고 합니다.
시작 서비스(예: MergeRequestRuleUpdateService)에서 다음과 같이
execute 호출을 감쌀 수 있습니다.
# in the initiating service
audit_context = {
name: 'update_merge_approval_rule',
author: current_user,
scope: project_alpha,
target: merge_approval_rule,
message: 'Attempted to update an approval rule'
}
::Gitlab::Audit::Auditor.audit(audit_context) do
service.execute
end
모델(예: ApprovalProjectRule)에서는 모델 콜백(예: after_save 또는 after_add)에서
감사 이벤트를 푸시할 수 있습니다.
# in the model
include Auditable
def audit_add(model)
push_audit_event('Added an approver on Security rule')
end
def audit_remove(model)
push_audit_event('Removed an approver on Security rule')
end
이 방법은 비동기 작업이나 여러 프로세스에 걸친 작업(예: 백그라운드 job)은 지원하지 않습니다.
표준 메서드 호출을 사용한 단일 이벤트 기록#
이 방법은 감사 이벤트를 하나만 기록하며 관여하는 요소가 더 적습니다.
if merge_approval_rule.save
audit_context = {
name: 'create_merge_approval_rule',
author: current_user,
scope: project_alpha,
target: merge_approval_rule,
message: 'Created a new approval rule',
created_at: DateTime.current # Useful for pre-dating an audit event when created asynchronously.
}
::Gitlab::Audit::Auditor.audit(audit_context)
end
데이터 볼륨 고려 사항#
모든 감사 이벤트는 데이터베이스에 저장되므로, 새 감사 이벤트가 만들어 낼 데이터의 양과 생성 빈도를
고려해야 합니다. 데이터베이스에 많은 데이터를 만드는 새 감사 이벤트라면 대신
스트리밍 전용 감사 이벤트 추가를 검토합니다. 이에 관해 궁금한 점이 있으면 이슈나 머지 리퀘스트에서
@gitlab-org/govern/compliance/backend를 멘션해도 됩니다.
감사 이벤트 계측 흐름#
감사 이벤트를 계측하는 두 가지 방법은 흐름이 서로 다릅니다.
블록을 사용한 여러 이벤트 기록#
작업 블록을 Gitlab::Audit::Auditor로 감싸면, 작업이 시작되는 시점에 사용할 수 있는
초기 감사 컨텍스트 객체(즉 author, scope, target)를
포착합니다.
Gitlab::Audit::EventQueue를 통해 감사 이벤트 큐에 감사 이벤트를 추가하려면, 호출 체인에서 상호 작용하는
클래스에 Auditable 믹스인으로 추가 계측이 필요합니다.
EventQueue는 SafeRequestStore를 통해 로컬 스레드에 저장되며,
이후 Gitlab::Audit::Auditor에서 감사 이벤트를 기록할 때 추출됩니다.
소스 코드 보기
skinparam shadowing false
skinparam BoxPadding 10
skinparam ParticipantPadding 20
participant "Instrumented Class" as A
participant "Audit::Auditor" as A1 #LightBlue
participant "Audit::EventQueue" as B #LightBlue
participant "Interacted Class" as C
participant "AuditEvent" as D
A->A1: audit <b>{ block }</b>
activate A1
A1->B: begin!
A1->C: <b>block.call</b>
activate A1 #FFBBBB
activate C
C-->B: push [ message ]
C-->A1: true
deactivate A1
deactivate C
A1->B: read
activate A1 #FFBBBB
activate B
B-->A1: [ messages ]
deactivate B
A1->D: bulk_insert!
deactivate A1
A1->B: end!
A1-->A:
deactivate A1
표준 메서드 호출을 사용한 단일 이벤트 기록#
이 방법은 흐름이 더 단순하며 EventQueue와 로컬 스레드에
의존하지 않습니다.
소스 코드 보기
skinparam shadowing false
skinparam BoxPadding 10
skinparam ParticipantPadding 20
participant "Instrumented Class" as A
participant "Audit::Auditor" as B #LightBlue
participant "AuditEvent" as C
A->B: audit
activate B
B->C: bulk_insert!
B-->A:
deactivate B
데이터베이스에 기록하는 것 외에, 이러한 이벤트는 로그 파일에도 기록됩니다.
이벤트 타입 정의#
모든 새 감사 이벤트에는 config/audit_events/types/ 또는 ee/config/audit_events/types/에 저장된 타입 정의가 있어야 하며, 이 정의는 GitLab의 모든 감사 대상 이벤트에 대한 단일 진실 공급원(Single Source Of Truth, SSOT)입니다.
새 감사 이벤트 타입 추가#
새 감사 이벤트 타입을 추가하는 방법은 다음과 같습니다.
- YAML 정의를 만듭니다. 다음 중 하나를 선택할 수 있습니다.
bin/audit-event-typeCLI로 YAML 정의를 자동으로 만듭니다.- 수동으로
config/audit_events/types/에 이벤트 타입 이름과 같은 파일 이름으로 새 파일을 만듭니다. 예를 들어 사용자가 프로젝트에 추가될 때 트리거되는 이벤트 타입의 정의는config/audit_events/types/project_add_user.yml에 저장할 수 있습니다.
config/audit_events/types/type_schema.json에 정의된 스키마를 따르는 내용을 파일에 추가합니다.Gitlab::Audit::Auditor를 호출하는 모든 곳에서 해당 파일에 정의한name을 사용하는지 확인합니다.
스키마#
| 필드 | 필수 여부 | 설명 |
|---|---|---|
name |
yes | 이벤트 타입을 설명하는 고유한 소문자 언더스코어 이름입니다. 파일 이름과 일치해야 합니다 |
description |
yes | 이 이벤트가 트리거되는 방식에 대한 사람이 읽을 수 있는 설명입니다 |
group |
yes | 이 감사 이벤트를 도입한 그룹 이름입니다. 예: manage::compliance |
introduced_by_issue |
yes | 이 타입의 추가를 제안한 이슈 URL 입니다 |
introduced_by_mr |
yes | 이 새 타입을 추가한 MR URL 입니다 |
milestone |
yes | 이 타입이 추가된 마일스톤입니다 |
saved_to_database |
yes | 이벤트를 데이터베이스와 JSON 로그에 저장할지 여부를 나타냅니다 |
streamed |
yes | 이벤트를 외부 서비스로 스트리밍할지 여부를 나타냅니다(구성된 경우) |
scope |
yes | 이 감사 이벤트 타입을 사용할 수 있는 범위 목록입니다. Project, User, Group, Instance 중 하나 이상을 포함하는 배열이어야 합니다 |
문서 생성#
감사 이벤트 타입 문서는 자동으로 생성되어 GitLab 문서 사이트에 게시됩니다.
새 감사 이벤트 타입을 추가했다면
gitlab:audit_event_types:compile_docs Rake 작업을
실행해 문서를 갱신합니다.
bundle exec rake gitlab:audit_event_types:compile_docs
gitlab:audit_event_types:check_docs Rake 작업을
실행해 문서가 최신 상태인지 확인합니다.
bundle exec rake gitlab:audit_event_types:check_docs
이벤트 스트리밍#
엔터티가 Group 또는 Project 인 모든 이벤트는 감사 로그에 기록되며, 하나 이상의
이벤트 스트리밍 대상으로도 스트리밍됩니다. 엔터티가 다음과 같을 때 동작은 이렇습니다.
Group이면 해당 그룹의 최상위 상위 그룹에 설정된 이벤트 스트리밍 대상으로 스트리밍됩니다.Project면 해당 프로젝트의 최상위 상위 그룹에 설정된 이벤트 스트리밍 대상으로 스트리밍됩니다.
GitLab 데이터베이스에 저장되지 않는 스트리밍 전용 이벤트를 추가할 수 있습니다. 스트리밍 전용 이벤트는 주로 많은 양의 데이터를 만들어 내는 작업에 사용하도록 만들어졌습니다. 예시는 이 머지 리퀘스트를 참고합니다. 이 기능은 활발히 개발 중입니다. 기능 개발 소식은 상위 에픽에서 확인할 수 있습니다.
I18N과 감사 이벤트 :message 속성#
번역된 메시지는 데이터베이스에 저장되어 로케일 설정과 무관하게 사용자에게 제공되므로, 감사 이벤트 메시지는 의도적으로 번역하지 않습니다.
예를 들어 인증된 사용자의 로케일로 감사 이벤트 메시지를 기록하면, 외부 스트리밍 대상에 그 대상에 맞지 않는 언어로 메시지가 전달될 수 있습니다. 사용자는 이를 혼란스럽게 느낄 수 있습니다.