顧客はログを外に送れないと言った
한국어 원문으로 표시합니다.
목표
고객 서버에서 고객 담당자가 직접 돌릴 지원 번들 수집기를 만든다. 허용 목록으로 모으고, 비밀을 가리고, manifest 와 크기 상한을 두고, 같은 입력이면 같은 바이트가 나오는 tar.gz 로 묶는다.
왜 중요한가
로그를 밖으로 보낼 수 없는 고객에게 번들을 받으려면 고객 보안 담당자가 승인해야 한다. 무엇이 들어갔는지, 무엇을 몇 건 가렸는지, 받은 파일이 검토한 그 파일인지를 보여 주지 못하면 번들은 나가지 못한다. 매번 사람이 파일을 고르면 비밀이 새거나 쓸모없는 번들이 나온다.
재료: /opt/lab/p1a-bundle/site — 고객 서버 사본(VERSION, etc, logs, run/environ, data). /opt/lab/p1a-bundle/rules.tsv — 고객 보안팀의 추가 가림 규칙. 작업 디렉터리는 /root/bundle 이다. 예상 60분이고, 세션이 끝나면 /root/bundle 은 사라진다.
수집 규칙(이 실습의 약속):
- 넣는 것:
VERSION,etc/아래 일반 파일(심볼릭 링크 제외),logs/바로 아래*.log,run/environ(stage 에서는env.txt, NUL 을 줄바꿈으로 바꾸고 이름순 정렬). - 가리는 것: 개인키 블록 전체 →
[REDACTED:private_key],Bearer뒤의 값 →[REDACTED:token], 키 이름이 password·passwd·secret 으로 끝나는 값 →[REDACTED:password], token·api_key 로 끝나는 값 →[REDACTED:token], 이메일 →[REDACTED:email]. 키와 값은:또는=로 나뉜다. 키 이름과 구분자는 남긴다. - 로그 상한: 파일마다 65536 바이트. 가린 뒤 에 최근 쪽 온전한 줄만 남긴다.
단계
- 재료 site 에서 수집 규칙에 맞는 파일의 상대 경로를 /root/bundle/scope.txt 에 한 줄씩 적는다.
- 표준입력을 가려 표준출력으로 내보내고 표준오류에
redactions=N을 찍는 /root/bundle/redact.py 를 만든다. python3 collect.py SRC OUT이 OUT/stage 에 허용 목록 파일을 가려서 두는 /root/bundle/collect.py 를 만든다.- collect.py 가 OUT/stage/manifest.json 을 만들게 한다(files 배열: path·size·sha256·redactions·truncated, path 순 정렬, total_redactions).
- 로그 파일에 65536 바이트 상한을 적용하고 manifest 의 truncated·redactions 를 실제에 맞춘다.
- collect.py 가 OUT/support-bundle.tar.gz 를 만들게 한다. 항목은
support-bundle/아래 이름순이고, 같은 입력이면 언제 어디서 묶어도 sha256 이 같아야 한다. --rules FILE을 받아kind<TAB>정규식규칙을 기본 규칙 뒤에 적용하고[REDACTED:kind]로 가리게 한다.- 재료 site 와 rules.tsv 로 /root/bundle/delivery/support-bundle.tar.gz, SHA256SUMS, REDACTION-REPORT.tsv 를 만든다.
참고
- 채점기는 여러분의 redact.py·collect.py 를 매번 비밀을 새로 심은 서버 트리로 직접 실행한다. 재료 값에 맞춘 규칙이나 하드코딩은 떨어진다.
- 과잉 가림도 실패다:
password_min_length: 12,token_ttl_sec: 3600,passwordless_login: false,orders-api@sha256:…같은 줄은 그대로 남아야 한다. - 3단계부터 collect.py 한 파일을 계속 키운다. 앞 단계 기능을 지우면 앞 단계 채점이 다시 떨어진다.
- NUL 구분 파일 보기:
tr '\0' '\n' < /opt/lab/p1a-bundle/site/run/environ - 결정성 확인: 같은 명령을 두 번(사이에
touch로 원본 mtime 을 바꿔) 돌리고sha256sum을 비교한다. - 흔한 실수:
tarfile.open(..., "w:gz")그대로 쓰기, manifest 에 생성 시각 넣기, 자른 뒤 가리기.
무엇을 넣을지 허용 목록으로 정하기
재료 site 에서 수집 규칙에 맞는 파일의 상대 경로를 /root/bundle/scope.txt 에 한 줄에 하나씩 적는다.
site 전체를 find 로 먼저 훑어보세요. 규칙에 이름으로 적힌 것만 넣고, 회전된 로그와 하위 디렉터리 로그, 고객 데이터, pid 파일은 규칙에 없으니 빠집니다. 경로는 site 기준 상대 경로입니다.
좁고 정확한 가림 필터
표준입력을 가려 표준출력으로 내보내고 표준오류에 redactions=N 을 찍는 /root/bundle/redact.py 를 만든다.
정규식은 모양으로 정합니다. 개인키는 여러 줄이라 줄 규칙보다 먼저 re.S 로 블록째 바꾸세요. 키 이름은 password 가 '들어간' 것이 아니라 '끝나는' 것이어야 password_min_length 가 살아남습니다. 값은 따옴표로 감싸였을 수도, & 나 공백에서 끝날 수도 있습니다.
허용 목록만 모아 가린 stage 만들기
python3 /root/bundle/collect.py SRC OUT 이 OUT/stage 에 허용 목록 파일을 가려서 두는 /root/bundle/collect.py 를 만든다.
redact.py 를 같은 디렉터리에서 import 하면 규칙을 두 번 쓰지 않아도 됩니다. etc 아래를 걸을 때 os.path.islink 로 링크를 거르고, run/environ 은 NUL 로 쪼갠 뒤 정렬해 env.txt 로 둡니다. 다시 돌렸을 때 지난 stage 의 파일이 남지 않게 하세요.
검토자가 대조할 manifest
collect.py 가 OUT/stage/manifest.json 을 만들게 한다(files: path·size·sha256·redactions·truncated, path 순, total_redactions).
sha256 과 size 는 가린 뒤 stage 에 실제로 쓴 바이트로 계산합니다. redactions 는 그 파일에서 가린 건수입니다. 이 파일에 생성 시각을 넣으면 6단계에서 무엇이 문제가 될지 먼저 생각해 보세요.
큰 로그는 가린 뒤 최근 줄만
logs 의 파일마다 65536 바이트 상한을 적용하고, manifest 의 truncated·redactions 를 잘린 결과에 맞춘다.
가린 결과의 끝에서 65536 바이트를 잘라 온 뒤, 그 창의 첫 줄이 온전하지 않으면 버립니다. 창 바로 앞 바이트가 줄바꿈인지 보면 판단할 수 있습니다. 건수는 잘려 나간 부분을 빼고 남은 부분에서 다시 세야 합니다.
같은 입력이면 같은 바이트
collect.py 가 OUT/support-bundle.tar.gz 를 만들게 한다. 항목은 support-bundle/ 아래 이름순이고, 다른 시각·다른 OUT 에서 묶어도 sha256 이 같아야 한다.
tar 에는 수정 시각·소유자·권한·순서가 들어가고, gzip 머리에는 시각이 한 번 더 들어갑니다. Python 이면 TarInfo 를 직접 만들어 값을 고정하고 GzipFile 의 mtime 을 정하세요. GNU tar 로 묶는다면 reproducible-builds 문서의 옵션들을 보세요.
고객 보안팀의 추가 규칙을 파일로 받기
collect.py 가 --rules FILE(kind정규식)을 받아 기본 규칙 뒤에 적용하고, 건수를 manifest 에 합치게 한다.
주석(#)과 빈 줄은 건너뜁니다. 규칙은 코드에 박지 말고 파일에서 읽으세요 — 채점기는 매번 다른 종류 이름과 정규식을 주고, 규칙 없이 돌렸을 때 그 값이 남는지도 봅니다.
전달 번들과 검토용 보고서
재료 site 와 rules.tsv 로 /root/bundle/delivery/support-bundle.tar.gz, /root/bundle/delivery/SHA256SUMS, /root/bundle/delivery/REDACTION-REPORT.tsv 를 만든다.
SHA256SUMS 는 받는 쪽이 sha256sum -c 로 확인할 수 있는 형식입니다. 보고서의 건수는 manifest 를 베끼지 말고 번들 속 파일의 표식을 종류별로 세서 적으세요. 채점기는 지금의 collect.py 로 재료에서 다시 묶어 전달본과 바이트가 같은지 봅니다.