사전 준비 확인
2분이번 랩은 시스템 경로에 파일을 배포하므로 sudo 권한이 필요합니다(Task 3, 4). 검증에 쓸 작업 폴더와 가짜 시크릿 파일도 만들어 둡니다.
sudo -v && echo "sudo OK"
node -v && npm -v
mkdir -p ~/claude-lab/ch3/src && cd ~/claude-lab/ch3
cat > .env << 'EOF'
# 실습용 가짜 값입니다. 실제 시크릿을 넣지 마세요.
DB_PASSWORD=lab-fake-password
API_TOKEN=lab-fake-token
EOF
cat > src/app.js << 'EOF'
export function hello() { return "admin lab"; }
EOF
ls -la
~/.claude/settings.json(User 스코프)에
같은 JSON을 넣으면 정책 동작 자체는 동일하게 체험할 수 있습니다.
차이는 강제성뿐입니다. User 설정은 본인이 언제든 바꿀 수 있지만, Managed는 사용자가 덮어쓸 수 없습니다.
사내 npm 미러, Verdaccio
9분npmjs를 직접 열 수 없는 사내망을 가정하고, Verdaccio 미러를 띄워 Claude Code를 미러 경유로 설치합니다. 한 번 캐시된 패키지는 npmjs가 두절돼도 배포 가능하다는 것(오프라인/에어갭의 기초)을 확인합니다.
npm install -g verdaccio
verdaccio --listen 4873 > /tmp/verdaccio.log 2>&1 &
sleep 3
npm ping --registry http://localhost:4873 # PONG이면 미러 정상
전역 registry를 바꾸는 대신 --registry 플래그를 씁니다.
실습 머신의 npm 상태를 건드리지 않으므로 원복이 필요 없습니다.
npm install -g @anthropic-ai/claude-code --registry http://localhost:4873
claude --version
ls ~/.config/verdaccio/storage/@anthropic-ai/claude-code/
claude-code-2.1.x.tgz package.json
pkill -f verdaccio && echo "미러 종료됨"
'@anthropic-ai/*': proxy: npmjs),
클라이언트에는 npm config set registry http://npm.corp.local을 MDM으로 일괄 배포합니다.
버전 통제는 managed-settings의 requiredMinimumVersion / requiredMaximumVersion으로
승인 범위를 강제할 수 있습니다.
Bedrock + SSO 자격증명 패턴
7분장기 API Key를 뿌리는 대신 IAM Identity Center(SSO)의 단기 자격증명으로 Bedrock을 호출하는 표준 패턴을 구성합니다. 프로파일 작성과 IAM 정책 이해는 전원 진행하고, 실제 로그인 검증은 AWS 계정 보유자용 선택 트랙입니다.
실습에서는 AWS_CONFIG_FILE로 격리된 설정 파일을 사용해
기존 ~/.aws/config를 건드리지 않습니다. 값은 조직 환경에 맞게 바꾸세요.
export AWS_CONFIG_FILE=~/claude-lab/ch3/aws-config
cat > "$AWS_CONFIG_FILE" << 'EOF'
[sso-session corp]
sso_start_url = https://my-org.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
[profile claude-workshop]
sso_session = corp
sso_account_id = 111122223333
sso_role_name = ClaudeCodeWorkshop
region = ap-northeast-2
EOF
cat "$AWS_CONFIG_FILE"
역할(ClaudeCodeWorkshop)에는 최소 권한 원칙으로 아래 정책을 부여합니다. 읽고 각 항목의 목적을 확인하세요.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
"bedrock:ListFoundationModels"
],
"Resource": [
"arn:aws:bedrock:*::foundation-model/anthropic.*",
"arn:aws:bedrock:*:*:inference-profile/*"
]
}]
}
InvokeModelWithResponseStream은 Claude Code가 스트리밍으로 응답을 받는 데 필수입니다.
inference-profile 리소스는 교차 리전 추론(CRIS)을 쓸 때 필요합니다.
조직 요건에 맞게 모델 ARN과 리전 범위를 더 좁힐 수 있습니다.
aws sso login --profile claude-workshop
export CLAUDE_CODE_USE_BEDROCK=1
export AWS_PROFILE=claude-workshop
export AWS_REGION=ap-northeast-2
claude doctor # API Provider: AWS Bedrock 표시 확인
user.email이 비어 있습니다.
사용자별 비용 추적이 필요하면 OTEL_RESOURCE_ATTRIBUTES="enduser.id=user@corp.com"처럼
신원 속성을 managed-settings로 부착하세요. Task 5에서 이어집니다.
unset AWS_CONFIG_FILE CLAUDE_CODE_USE_BEDROCK AWS_PROFILE AWS_REGION
managed-settings로 조직 정책 강제
10분사용자가 덮어쓸 수 없는 Managed 스코프에 권한 규칙을 배포하고, 실제로 적용되는지 검증합니다. Settings 우선순위의 최상단(Managed > CLI > Local > Project > User)을 체감하는 것이 목표입니다.
아래는 파일 기반 managed-settings의 표준 경로입니다. 본인 OS 탭의 경로를 사용하세요.
| OS | 경로 |
|---|---|
| Linux, WSL | /etc/claude-code/managed-settings.json |
| macOS | /Library/Application Support/ClaudeCode/managed-settings.json |
| Windows | C:\Program Files\ClaudeCode\managed-settings.json |
/etc/claude-code/입니다(하이픈 포함). Windows 구경로
C:\ProgramData\ClaudeCode\는 v2.1.75부터 미지원이니 C:\Program Files\ClaudeCode\를 쓰세요.
아래 실습은 Linux / WSL 경로 기준이며, macOS는 경로만 바꾸면 됩니다.
companyAnnouncements로 시작 배너를 함께 넣어, 관리 설정이 실제로 적용됐는지 눈으로 확인합니다.
sudo mkdir -p /etc/claude-code
sudo tee /etc/claude-code/managed-settings.json > /dev/null << 'EOF'
{
"permissions": {
"allow": ["Read(**)", "Grep", "Glob", "Bash(npm test:*)"],
"ask": ["Edit(**)", "Write(**)"],
"deny": ["Bash(rm -rf:*)", "Read(./.env)", "Read(./.env.*)"]
},
"companyAnnouncements": [
"[Corp Policy] Claude Code managed settings 적용됨. .env 읽기는 금지됩니다."
]
}
EOF
echo "배포 완료"
cd ~/claude-lab/ch3
claude
세션이 시작되면 상단에 배너 문구가 뜨는지 보고, 아래로 설정 소스를 확인합니다.
/status
Setting sources:
- managed (/etc/claude-code/managed-settings.json) # 이 줄이 보여야 함
- user, project ...
.env 파일의 내용을 읽어서 보여주세요
Read(./.env) 는 관리 정책(deny)에 의해 차단되었습니다.
# 프롬프트 없이 거부됨. Read(**)로 허용돼 있어도 deny가 우선
Read(**)로 전체 읽기를 allow 했더라도 deny 규칙이 우선하여 .env는 차단됩니다.
권한 규칙은 스코프 간 병합되며, deny가 항상 이깁니다. /exit로 세션을 나옵니다.
claude doctor를 돌리면 무시된 항목을 소스 파일과 필드까지 알려줍니다.
fleet 배포 전 필수 습관입니다.
DLP Hook, 시크릿 유출 차단
9분코드에 AWS 액세스 키가 섞여 들어가는 것을 PreToolUse Hook으로 실시간 차단합니다. 권한 규칙이 도구 단위 통제라면, Hook은 내용 기반 통제(DLP)라는 점이 핵심입니다.
stdin으로 들어오는 JSON에서 tool_input을 꺼내 AWS 키 패턴을 찾고,
발견 시 exit code 2로 차단합니다. stderr 메시지는 Claude에게 전달되어 차단 사유가 됩니다.
sudo mkdir -p /opt/claude
sudo tee /opt/claude/dlp.sh > /dev/null << 'EOF'
#!/bin/bash
# PreToolUse DLP: AWS Access Key ID 패턴을 도구 입력에서 차단
INPUT=$(cat)
if echo "$INPUT" | grep -qE 'AKIA[0-9A-Z]{16}'; then
echo "Blocked by DLP: AWS Access Key ID detected in tool input" >&2
exit 2
fi
exit 0
EOF
sudo chmod +x /opt/claude/dlp.sh
echo "DLP 스크립트 준비 완료"
exit 1 + JSON 방식은 현행과 다릅니다).
Task 3의 managed-settings에 hooks 블록을 더해 재배포합니다. 권한 규칙은 그대로 유지합니다.
sudo tee /etc/claude-code/managed-settings.json > /dev/null << 'EOF'
{
"permissions": {
"allow": ["Read(**)", "Grep", "Glob", "Bash(npm test:*)"],
"ask": ["Edit(**)", "Write(**)"],
"deny": ["Bash(rm -rf:*)", "Read(./.env)", "Read(./.env.*)"]
},
"hooks": {
"PreToolUse": [{
"matcher": "Bash|Edit|Write",
"hooks": [{ "type": "command", "command": "/opt/claude/dlp.sh" }]
}]
},
"companyAnnouncements": [
"[Corp Policy] DLP Hook 활성화됨. AWS 키는 코드에 쓸 수 없습니다."
]
}
EOF
echo "Hook 포함 재배포 완료"
cd ~/claude-lab/ch3
claude
Hook은 설정 핫 리로드로 적용됩니다. 세션에서 AWS 키가 포함된 파일 작성을 요청하세요.
src/aws.js 파일을 만들고 그 안에 다음 줄을 넣어주세요: const key = "AKIAIOSFODNN7EXAMPLE";
[Write 시도] → PreToolUse Hook 실행 (/opt/claude/dlp.sh)
Blocked by DLP: AWS Access Key ID detected in tool input
# exit 2로 Write가 차단됨. Claude는 차단 사유를 전달받음
키 없는 일반 파일 작성은 정상 통과하는지도 확인해 보세요(대조군). 확인 후 /exit.
sudo rm -f /etc/claude-code/managed-settings.json
sudo rm -f /opt/claude/dlp.sh
sudo rmdir /etc/claude-code /opt/claude 2>/dev/null
echo "원복 완료"
OpenTelemetry 텔레메트리 맛보기
3분사용량과 비용, 감사 이벤트를 사내 관측 스택으로 보내는 첫 단계로, console exporter로 텔레메트리가 실제로 흐르는지 눈으로 확인합니다. SIEM 연동은 이 흐름의 목적지만 바꾼 것입니다.
OTLP 수집기 없이도 console exporter로 표준 출력에서 메트릭을 볼 수 있습니다.
수집 간격을 짧게 잡아 바로 확인합니다. 세션 밖 터미널에서 실행하세요.
cd ~/claude-lab/ch3
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
export OTEL_METRIC_EXPORT_INTERVAL=5000
claude -p "src/app.js가 무엇을 하는지 한 줄로 설명해줘"
# stdout에 메트릭 스코프가 출력됨
descriptor:
name: claude_code.token.usage ...
name: claude_code.cost.usage ...
# session.count, token.usage, cost.usage 등이 흐르는지 확인
OTEL_LOGS_EXPORTER=otlp와
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT를 managed-settings의 env로 배포합니다.
감사에는 OTEL_LOG_TOOL_DETAILS=1을 켜서 tool_decision, mcp_server_connection 등
보안 이벤트에 Bash 명령과 MCP 호출 상세를 포함시킵니다.
unset CLAUDE_CODE_ENABLE_TELEMETRY OTEL_METRICS_EXPORTER OTEL_METRIC_EXPORT_INTERVAL
마무리, 학습 목표 체크리스트
Chapter 3의 관리자 학습 목표를 스스로 점검하세요. 미달성 항목은 진행자에게 질문하거나 강의 자료의 해당 Part를 다시 확인합니다.
| 목표 | 확인 질문 | 관련 |
|---|---|---|
| Deploy | 사내 미러로 오프라인 배포의 기초(캐시)를 확인했는가 | Task 1 |
| Credential | API Key 대비 SSO+Bedrock의 이점과 IAM 정책을 설명할 수 있는가 | Task 2 |
| Governance | Managed 스코프의 우선순위와 deny 우선 규칙을 체험했는가 | Task 3 |
| DLP | PreToolUse Hook(exit 2)으로 내용 기반 차단을 구현했는가 | Task 4 |
| Observe | 텔레메트리 흐름을 확인하고 SIEM 연동 경로를 이해했는가 | Task 5 |
| Cleanup | 시스템 경로의 managed-settings와 Hook을 원복했는가 | Task 4 |
| 분기 | 목표 | 주요 활동 |
|---|---|---|
| Q1 / PoC | 5-10인 시범 도입 | API Key + 사용 패턴 관찰 |
| Q2 / Foundation | 클라우드 자격증명 전환 | Bedrock + SSO 통합 |
| Q3 / Governance | 권한 정책과 감사 시스템 | managed-settings + SIEM |
| Q4 / Scale | 전 조직 확산 | 교육 + 자동화 + 모니터링 |
한 번에 모든 것을 하지 말고 점진적으로 도입하세요. 각 분기의 학습을 다음 분기 계획에 반영하는 사이클이 가장 효과적입니다.