본문으로 건너뛰기

감사 로그

감사 로그는 Semaphore의 중요한 작업을 기록합니다. 누가 로그인했는지, 누가 사용자나 역할을 변경했는지, 누가 API 토큰을 만들었는지 등입니다. 각 이벤트에는 누가, 언제, 어떤 주소에서 작업했고 성공했는지가 담깁니다. 설치 환경에서 무슨 일이 있었는지 확인하거나, 이벤트를 SIEM으로 보내 다른 로그와 함께 보관할 수 있습니다.

감사 로그는 모든 에디션에서 사용할 수 있습니다. 필터링, 파일로 내보내기, SIEM으로 이벤트 보내기에는 Semaphore Pro가 필요합니다.

기록되는 내용​

현재 Semaphore는 로그인, 계정, 프로젝트, 태스크 활동을 기록합니다.

  • 로그인, 실패한 로그인 시도, 로그아웃, 2단계 인증 확인
  • 거부된 API 토큰, 거부된 요청, 차단된 교차 사이트 요청
  • 사용자, 비밀번호, 2단계 인증, 외부 ID, API 토큰 변경
  • 프로젝트 멤버, 역할, 템플릿 권한 변경
  • 프로젝트, 인벤토리, 저장소, 템플릿, 스케줄, 통합, 호스트 설정, 환경, 자격 증명, 비밀 저장소 변경, 그리고 프로젝트 백업 내보내기와 복원
  • 시스템 설정 변경과 Pro 라이선스 활성화
  • 트리거(API, 일정, 통합, 자동 실행, 워크플로)가 포함된 태스크 시작, 승인, 중지, 완료 및 삭제된 태스크 기록
  • 러너 변경, 등록(거부된 등록 토큰 포함), 등록 해제, 잘못된 상태의 러너 보고
  • 감사 로그를 파일로 내보내기
  • 서버 시작

전체 목록은 감사 이벤트를 참고하세요.

비밀번호, 토큰, 비밀 값, 작업 출력은 감사 이벤트에 절대 포함되지 않습니다. API 토큰은 값 대신 지문으로 표시됩니다. 로그인에 실패하면 입력한 로그인 이름이 남으므로 이메일 주소가 포함될 수 있습니다.

태스크의 완료 이벤트에서 metadata.result는 Semaphore가 태스크에 부여한 상태를 보여 주고, metadata.end_reason은 Semaphore가 태스크를 종료한 이유를 알려 줍니다. 너무 오래 실행되면 timeout, 러너가 응답을 멈추면 runner_lost입니다. 태스크 인수, 변수, 러너 태그, 토큰은 기록되지 않습니다.

HA 클러스터의 롤링 업그레이드 중에 업그레이드된 노드에서 시작되어 아직 업그레이드되지 않은 노드에서 끝난 태스크에는 완료 이벤트가 없습니다.

저장소 URL, 호스트 설정 URL, 통합 별칭도 기록되지 않습니다.

Semaphore가 객체를 저장하거나 삭제했지만 같은 요청의 이후 단계가 실패하는 경우가 있습니다. 이때 UI나 API는 오류를 표시하지만 객체는 이미 생성되었거나 삭제된 상태입니다. 이러한 이벤트는 성공으로 기록되며 metadata.partial=true가 포함되고, reason에 완료되지 않은 내용이 표시됩니다.

  • secret_failed: 환경은 저장되거나 삭제되었지만 일부 비밀이 저장되거나 제거되지 않았습니다.
  • inventory_failed: 템플릿은 생성되었지만 해당 Terraform 워크스페이스 인벤토리는 생성되지 않았습니다.
  • restore_failed: 프로젝트는 백업에서 복원되었지만 일부 객체는 복원되지 않았습니다.
  • setup_failed: 프로젝트는 생성되었지만 설정이 완료되지 않았습니다. 예를 들어 생성자가 소유자로 추가되지 않았습니다.

감사 로그 켜기​

감사 로그는 기본적으로 꺼져 있습니다. 켜려면 audit.enabled를 설정하고 audit.instance_id에 설치 환경의 이름을 지정하세요.

{
"audit": {
"enabled": true,
"instance_id": "prod-eu"
}
}

또는 환경 변수를 사용합니다.

SEMAPHORE_AUDIT_ENABLED=true
SEMAPHORE_AUDIT_INSTANCE_ID=prod-eu

인스턴스 ID는 공백 없는 1~255자입니다. 모든 이벤트에 추가되므로 여러 설치 환경이 같은 곳으로 이벤트를 보내도 구분할 수 있습니다.

Semaphore를 다시 시작하세요. 기록은 다시 시작한 후부터 시작되며 이전 작업은 추가되지 않습니다. 모든 옵션은 구성 옵션을 참고하세요.

프록시 뒤에서 클라이언트 주소 기록하기​

Semaphore가 리버스 프록시 뒤에서 실행되면 이벤트에 사용자 대신 프록시의 주소가 표시됩니다. 실제 클라이언트 주소를 기록하려면 audit.trusted_proxy_cidrs에 프록시 네트워크를 나열하세요.

{
"audit": {
"enabled": true,
"instance_id": "prod-eu",
"trusted_proxy_cidrs": ["10.0.0.0/8"]
}
}

또는 환경 변수를 사용합니다.

SEMAPHORE_AUDIT_TRUSTED_PROXY_CIDRS='["10.0.0.0/8"]'

그러면 Semaphore는 이 네트워크에서 온 요청에 한해 X-Forwarded-For 또는 X-Real-IP에서 클라이언트 주소를 가져옵니다. 요청이 여러 프록시를 거친다면 모두 나열하세요. 사용자가 접속하는 네트워크는 나열하지 마세요. 그 네트워크의 누구든 이 헤더에 임의의 주소를 넣을 수 있습니다.

저장​

이벤트는 Semaphore 데이터베이스에 저장되므로 평소의 데이터베이스 백업에 포함됩니다. 기본적으로 모든 이벤트를 보관합니다. 오래된 이벤트를 삭제하려면 보존 기간을 일 단위로 설정하세요.

{
"audit": {
"retention_days": 365
}
}

환경 변수로 설정할 수도 있습니다: SEMAPHORE_AUDIT_RETENTION_DAYS=365.

Semaphore는 오래된 이벤트를 한 시간에 한 번 삭제하고, 삭제한 이벤트 수가 담긴 audit.retention/delete 이벤트를 기록합니다. 이벤트를 SIEM으로 내보내는 경우, 견뎌야 할 가장 긴 SIEM 중단 시간보다 긴 기간을 선택하세요. 기간보다 오래된 이벤트는 전송되지 않았더라도 삭제됩니다.

보존 기간에 따른 삭제는 Semaphore가 시작될 때도 실행됩니다. HA 설치에서는 모든 노드에서 같은 retention_days를 사용하세요.

감사 로그는 사용자의 작업을 방해하지 않습니다. 이벤트를 저장하지 못하면 Semaphore는 서버 로그에 오류를 기록하고 작업은 평소처럼 계속됩니다.

SIEM으로 내보내기 Pro​

Semaphore Pro는 rsyslog나 Vector 같은 Syslog 수신기로 TLS를 통해 감사 이벤트를 보낼 수 있고, Splunk, Vector, Fluent Bit, OpenTelemetry Collector, Cribl 같은 Splunk HTTP Event Collector(HEC) 프로토콜 수신기로도 보낼 수 있습니다. Syslog 대상과 HEC 대상을 각각 하나씩 설정하거나 둘 다 동시에 설정할 수 있습니다.

필요한 것:

  • 수신기의 호스트 이름과 포트
  • 이 대상의 이름(예: security-syslog)
  • Semaphore 호스트가 아직 신뢰하지 않는 경우 수신기의 CA 인증서

config.json에 audit.syslog를 추가하세요.

{
"audit": {
"enabled": true,
"instance_id": "prod-eu",
"syslog": {
"id": "security-syslog",
"address": "siem.example.com:6514",
"ca_file": "/etc/semaphore/siem-ca.pem",
"server_name": "siem.example.com",
"timeout": "10s"
}
}
}

또는 환경 변수를 사용합니다.

SEMAPHORE_AUDIT_SYSLOG_ID=security-syslog
SEMAPHORE_AUDIT_SYSLOG_ADDRESS=siem.example.com:6514
SEMAPHORE_AUDIT_SYSLOG_CA_FILE=/etc/semaphore/siem-ca.pem
SEMAPHORE_AUDIT_SYSLOG_SERVER_NAME=siem.example.com
SEMAPHORE_AUDIT_SYSLOG_TIMEOUT=10s

id와 address는 필수입니다. Semaphore는 각 대상에 어떤 이벤트를 이미 보냈는지 기억하므로 주소나 인증서를 바꿀 때도 같은 id를 유지하세요. 새 id는 새 이벤트부터 보냅니다.

Semaphore는 항상 수신기의 인증서를 확인하며 TLS 1.2 이상을 사용합니다. ca_file은 CA를 신뢰할 수 있는 인증서에 추가하고, server_name은 주소와 다를 때 인증서에서 확인할 이름을 지정합니다.

Semaphore를 다시 시작하세요. 설정이 잘못되었거나 CA 파일을 읽을 수 없으면 Semaphore가 시작되지 않습니다.

이벤트 도착 확인하기​

Semaphore는 시작할 때마다 이벤트를 기록합니다. 다시 시작한 후 수신기에서 해당 이벤트를 찾으세요. event_code는 audit.lifecycle, action은 start이고, metadata.destinations에 대상 ID가 들어 있습니다.

HEC로 이벤트 보내기​

HEC 엔드포인트 URL, HEC 토큰, 이 대상의 이름(예: security-hec)이 필요하며, Semaphore 호스트가 수신기를 아직 신뢰하지 않는다면 수신기의 CA 인증서도 필요합니다.

{
"audit": {
"enabled": true,
"instance_id": "prod-eu",
"splunk_hec": {
"id": "security-hec",
"url": "https://splunk.example.com:8088/services/collector/event",
"token": "<HEC token>",
"index": "security",
"ca_file": "/etc/semaphore/siem-ca.pem"
}
}
}

환경 변수를 사용하는 경우:

SEMAPHORE_AUDIT_SPLUNK_HEC_ID=security-hec
SEMAPHORE_AUDIT_SPLUNK_HEC_URL=https://splunk.example.com:8088/services/collector/event
SEMAPHORE_AUDIT_SPLUNK_HEC_TOKEN='<HEC token>'
SEMAPHORE_AUDIT_SPLUNK_HEC_INDEX=security
SEMAPHORE_AUDIT_SPLUNK_HEC_CA_FILE=/etc/semaphore/siem-ca.pem

id, url, token은 필수이며 URL은 https://로 시작해야 합니다. Syslog와는 다른 id를 사용하세요. source와 sourcetype의 기본값은 semaphore와 semaphore:audit입니다. 인증서는 Syslog와 같은 방식으로 검증되며, 표준 HTTPS_PROXY와 NO_PROXY 변수가 적용됩니다.

Semaphore는 요청 하나에 최대 100개의 이벤트를 보냅니다. 각 HEC 이벤트의 event 필드에는 감사 이벤트 JSON이 들어 있고, time은 이벤트 시각이며, host는 HA 노드 ID(단일 노드에서는 인스턴스 ID)입니다.

Semaphore를 다시 시작한 다음, 위에서 설명한 대로 이벤트가 도착하는지 확인하세요.

이벤트 전달 방식​

  • 수신기가 중단되면 이벤트는 데이터베이스에서 기다렸다가 수신기가 복구되면 전송됩니다. 사용자는 아무것도 알아차리지 못합니다.
  • 네트워크 오류, 재시작, HA 장애 조치 후에는 일부 이벤트가 두 번 도착할 수 있습니다. event_id로 중복을 제거하고 seq로 순서를 맞추세요.
  • Syslog에서는 오류 없이 연결이 끊기면 그 순간에 보낸 이벤트가 유실될 수 있습니다.
  • HA 설치에서는 한 번에 하나의 노드가 각 대상에 이벤트를 보냅니다. Redis를 사용할 수 없으면 전송이 일시 중지되고 이벤트 기록은 계속됩니다.
  • HEC에서는 수신기가 2xx 상태로 응답한 뒤에야 이벤트가 전송된 것으로 처리됩니다. 4xx를 포함한 다른 모든 응답은 재시도됩니다. 수신기가 응답한 뒤에 중단되면, 아직 저장하지 못한 이벤트가 유실될 수 있습니다.

Syslog에서는 각 이벤트가 이벤트 JSON을 본문으로 하는 RFC 5424 Syslog 메시지로 전송됩니다. HOSTNAME은 HA 노드 ID(단일 노드에서는 인스턴스 ID)이고 MSGID는 이벤트 코드입니다.

아래 예시는 최소 구성이며 이벤트를 받는 방법만 보여 줍니다. 포트에 접근할 수 있는 모든 클라이언트의 연결을 받습니다. 운영 환경에서는 Semaphore 서버만 이벤트를 보낼 수 있도록 수신기를 보호하세요.

rsyslog 예시​

이 rsyslog 구성은 TLS 연결을 받아 한 줄에 하나의 이벤트를 기록합니다.

global(
DefaultNetstreamDriver="gtls"
DefaultNetstreamDriverCAFile="/etc/rsyslog.d/ca.pem"
DefaultNetstreamDriverCertFile="/etc/rsyslog.d/cert.pem"
DefaultNetstreamDriverKeyFile="/etc/rsyslog.d/key.pem"
)

module(load="imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon")
input(type="imtcp" port="6514" ruleset="semaphore-audit")

template(name="semaphore-audit-json" type="string" string="%msg%\n")

ruleset(name="semaphore-audit") {
action(type="omfile" file="/var/log/semaphore-audit.json" template="semaphore-audit-json")
}

Vector 예시​

이 Vector 구성은 TLS 연결을 받아 이벤트 JSON을 읽고 파일에 기록합니다.

[sources.semaphore_audit]
type = "syslog"
mode = "tcp"
address = "0.0.0.0:6514"
tls.enabled = true
tls.crt_file = "/etc/vector/cert.pem"
tls.key_file = "/etc/vector/key.pem"

[transforms.semaphore_audit_event]
type = "remap"
inputs = ["semaphore_audit"]
source = ". = parse_json!(.message)"

[sinks.semaphore_audit_file]
type = "file"
inputs = ["semaphore_audit_event"]
path = "/var/log/semaphore-audit.json"
encoding.codec = "json"

Vector HEC 예시​

[sources.semaphore_audit_hec]
type = "splunk_hec"
address = "0.0.0.0:8088"
valid_tokens = ["<HEC token>"]
tls.enabled = true
tls.crt_file = "/etc/vector/cert.pem"
tls.key_file = "/etc/vector/key.pem"

[sinks.semaphore_audit_file]
type = "file"
inputs = ["semaphore_audit_hec"]
path = "/var/log/semaphore-audit.json"
encoding.codec = "json"

Splunk 예시​

Splunk에서 HEC 토큰을 만들고(Settings → Data inputs → HTTP Event Collector), 토큰에 security 인덱스를 허용한 다음 url을 https://<splunk>:8088/services/collector/event로 설정합니다. 이벤트를 찾으려면 index=security sourcetype="semaphore:audit"을 검색하세요.

이 토큰에서는 Enable indexer acknowledgement를 꺼 두세요. Semaphore는 이 기능을 사용하지 않습니다.

내보내기 모니터링​

메트릭이 활성화되어 있으면 Semaphore Pro는 대상별로 다음을 보고합니다.

메트릭의미
semaphore_audit_export_oldest_pending_seconds아직 전송되지 않은 가장 오래된 이벤트의 경과 시간, 모두 전송되었으면 0
semaphore_audit_export_pending_events전송을 기다리는 이벤트 수
semaphore_audit_export_errors_total실패한 전송 시도

semaphore_audit_export_errors_total은 전송한 노드가 집계하므로 노드 간에 합산하세요. 예: sum by (destination) (increase(semaphore_audit_export_errors_total[15m]))

각 메트릭에는 대상의 id를 값으로 하는 destination 레이블이 있습니다. SIEM이 이벤트를 받지 못할 때 알림을 받으려면 대기 중인 가장 오래된 이벤트의 경과 시간을 확인하세요.

- alert: SemaphoreAuditExportStalled
expr: max by (destination) (semaphore_audit_export_oldest_pending_seconds) > 900
for: 5m

내보내기 문제 해결​

  • Semaphore가 시작되지 않습니다. audit.syslog.id와 audit.syslog.address가 모두 설정되어 있는지(HEC는 audit.splunk_hec.id, url, token), CA 파일에 PEM 인증서가 들어 있는지 확인하세요.
  • TLS 연결이 실패합니다. 수신기의 인증서가 server_name과 일치하고 Semaphore가 신뢰하는 CA가 서명했는지 확인하세요.
  • 이벤트가 도착하지 않습니다. Semaphore 서버 로그와 수신기 로그를 확인하세요. 실패 후 Semaphore는 잠시 기다렸다가 다시 시도합니다.
  • 일부 이벤트가 두 번 도착합니다. 재시도와 장애 조치 후에 생길 수 있습니다. event_id로 중복을 제거하세요.
  • HEC가 400, 401 또는 403으로 응답합니다. 토큰, 토큰이 쓸 수 있는 인덱스, 그리고 토큰에서 인덱서 확인 응답이 꺼져 있는지 확인하세요. 토큰은 Semaphore 로그에 나타나지 않습니다.

기록되지 않는 작업​

명령줄 도구 semaphore는 데이터베이스를 직접 다루므로 user add, user token 같은 명령은 기록되지 않습니다.

UI의 일부 작업은 기록되지 않습니다. 라이선스 제거, 앱 설정, HA 작업 상태 초기화, Terraform 인벤토리 별칭, Terraform 상태 삭제, 워크플로 실행, 프로젝트 초대입니다. 템플릿 설명, 뷰, 프로젝트 캐시 삭제, 예약된 비밀 저장소 동기화도 기록되지 않습니다.

다음 단계​