OTCA — 오픈텔레메트리 인증 어소시에이트 · 컨텍스트 경계: 옆 주문의 태그 찾기 · 이론
잘 전달된 baggage도 권한 증명서는 아니다
한 줄 요약
baggage 전파는 정보를 옮기는 기능입니다. 이 실습에서는 외부 값을 로컬 요청과 섞지
않고 읽은 다음, 정해진 목적지로 정해진 키와 값만 내보냅니다. 읽을 수 있다는 사실을
인증·인가나 개인정보 안전의 보증으로 바꾸지 않습니다.
왜 이게 필요했나
재고 서비스로 향하는 주문 요청에 region과 channel을 붙였다고 합시다. 운영자는
지역·유입 경로별로 느린 구간을 나누어 보고 싶습니다. 그런데 같은 baggage에 누군가
role=admin이나 이메일 형태의 값도 넣었습니다. 전체를 다른 서버로 주입하는 코드는
문법상 올바르지만, 필요하지 않은 정보까지 경계를 넘깁니다.
더 위험한 오해는 role=admin이 보이니 관리자 요청이라고 판단하는 것입니다.
이 모듈의 입력은 누구나 만들 수 있는 합성 헤더입니다. 값을 읽는 함수와 사용자의
권한을 검증하는 시스템은 완전히 별개이며, 실습에는 인증 서버 자체가 없습니다.
헤더를 통과시켰다는 관측으로 권한 검증의 성공을 주장할 수 없습니다.
OpenTelemetry 문서는 baggage에 무결성 확인 기능이 내장되어 있지 않으며, 전달되는
정보의 노출을 주의해야 한다고 설명합니다. 또한 baggage가 스팬 속성에 자동으로
들어가는 것은 아닙니다. [공식 Baggage 설명](https://opentelemetry.io/docs/concepts/signals/baggage/).
이 모듈은 그 경고를 작은 입출력 함수의 반례로 확인합니다.
어떻게 동작하나
들어온 Context와 이미 붙어 있던 Context
사전 실험에서 호출자에게 request=alpha를 붙인 뒤 외부 baggage를 추출했습니다.
기본 추출 결과에는 외부 값뿐 아니라 기존 로컬 request도 함께 남았습니다.
빈 OpenTelemetry Context를 명시한 추출에서는 외부 값만 남았습니다. 처음에는 두
결과가 같을 것이라고 예상했지만 실제 실행에서 틀렸고, 그 차이를 과제로 삼았습니다.
| 이 실습의 추출 조건 | 관측한 baggage |
| --- | --- |
| 로컬 request가 있는 상태의 기본 추출 | 로컬 request와 외부 값이 함께 있음 |
| 빈 Context를 지정한 추출 | 외부 값만 있음 |
| 빈 Context와 빈 헤더 | 빈 baggage |
6단계의 inbound는 외부 헤더를 별도 문맥으로 읽는 함수입니다. 입력 dict와 호출자의
현재 상태를 바꾸지 않고 새로운 OTel Context를 반환해야 합니다. 외부 role=admin도
이 단계에서는 읽은 결과에 남습니다. 이것은 신뢰하거나 사용하라는 뜻이 아니라,
“추출”과 “정책에 따른 선택”을 서로 다른 동작으로 관측하기 위한 조건입니다.
여기서 빈 Context는 OpenTelemetry의 Context입니다. 앞에서 executor에 쓴
contextvars.Context와 이름이 비슷하지만 반환 계약까지 같은 객체는 아닙니다.
함수별로 무엇을 반환하라고 했는지 확인하세요. 자료형이 틀리면 값이 우연히 같아도
그다음 전파 API에 맞게 연결되지 않습니다.
빈 문맥에서 읽으면 기존 요청과의 혼합은 막을 수 있습니다. 그러나 외부 값 자체의
진위를 알 수 있게 되는 것은 아닙니다. 이 한계를 분명히 적어 두어야 “새 Context라
안전하다”라는 또 다른 만능 규칙이 생기지 않습니다. 업무 권한은 별도의 검증된
신원과 정책에서 판단해야 합니다.
키만 허용하면 충분할까
7단계는 outbound(source, destination) 함수를 고칩니다. region이라는 이름만
허용한다고 해서 그 안에 들어간 아무 문자열이나 보내도 되는 것은 아닙니다.
누군가 region 값으로 긴 설명이나 식별자를 넣었다면 이름은 허용 목록에 있어도
내용은 과제의 분류 체계를 벗어납니다. 그래서 이번 과제는 값의 집합까지 닫습니다.
| 조건 | 이 과제에서 허용하는 것 |
| --- | --- |
| 목적지 문자열 | warehouse.internal과 정확히 같음 |
| region 값 | test-east 또는 test-west |
| channel 값 | web 또는 batch |
| 그 외 키·값·목적지 | 전파하지 않음 |
이름과 값은 실제 운영 정보가 아닌 실습용 합성 분류입니다. 허용 값이 유한한 짧은
문자열이므로 과제 안에서는 임의 길이의 문자열도 배제됩니다. 하지만 이것을 모든
서비스에 맞는 일반 개인정보 정책이라고 부르지 않습니다. 실제 정책은 정보의 목적,
수신자, 보존 기간, 접근 주체와 함께 정해야 하며 이 실습은 그 전체 시스템을 시험하지
않습니다. 여기서 검증하는 것은 위 표를 함수가 정확히 지켰는지입니다.
대소문자나 공백도 임의로 고치지 않습니다. WEB이나 test-east 뒤 공백은 이 계약의
허용 값이 아닙니다. 입력을 정규화할지 거절할지는 인터페이스 설계에서 정해야 할
선택입니다. 이 과제는 조용한 정규화 대신 허용된 문자열만 전달하도록 명시했습니다.
목적지 경계는 문자열 접두어가 아니다
warehouse.internal.evil은 warehouse.internal로 시작하지만 같은 목적지가 아닙니다.
실습은 이 반례를 실제 함수에 넣습니다. startswith 하나로 허용하면 지역 값의 필터가
맞아도 목적지 정책에서 실패합니다. 다른 목적지에는 빈 dict를 반환해야 하고,
허용 목적지라도 남은 값이 없으면 빈 baggage 헤더조차 만들지 않습니다.
중요한 범위 제한이 있습니다. 여기서 destination은 논리적 목적지 식별자입니다.
DNS 조회, URL 파싱, TLS 인증서, HTTP 리다이렉트는 실행하지 않습니다. 따라서 이
함수의 문자열 비교가 통과했다고 해서 실제 HTTP 클라이언트의 목적지 검증이나
SSRF 방어를 완료했다고 말해서는 안 됩니다. 네트워크 연결이 있는 시스템이라면
그 경계는 별도로 설계하고 시험해야 합니다.
원본을 지우는 대신 보낼 문맥을 만든다
학생 함수는 source에서 필요한 값만 골라 새 Context에 담고 W3C 전파기로 헤더를
만듭니다. 원본의 role이나 다른 값이 불필요하다고 해서 원본 자체를 바꾸는 과제가
아닙니다. 원본은 다른 정책의 처리에서도 쓰일 수 있으므로 이 함수의 계약은 보존입니다.
채점기는 전파 결과를 다시 추출해 비교하고, 원본도 전후 대조합니다.
헤더 문자열의 순서가 정답과 완전히 같아야 하는 것은 아닙니다. 의미가 같은 W3C
baggage라면 키 순서를 이유로 떨어뜨리지 않습니다. 대신 허용되지 않은 키가 다른
헤더 이름으로 새어 나가면 실패합니다. 반환 dict는 baggage 문자열 헤더 하나 또는
빈 dict만 허용합니다. 순서에 엄격하고 누출에는 느슨한 채점이 되지 않게 한 것입니다.
baggage와 스팬 속성은 다른 관측이다
사전 실험에서는 baggage를 붙인 상태로 실제 SDK 스팬을 끝내고 익스포터에서 읽었습니다.
baggage는 스팬 속성에 자동으로 나타나지 않았습니다. 8단계 보고서의 해당 가설은
이 관측과 공식 설명에 근거해 답합니다. 현재 실습의 1~7단계는 Context 함수의 동작을
검증하며, 매 단계마다 스팬을 만들거나 Collector에 저장하는 것은 아닙니다.
전파할 정보와 스팬에 기록할 정보를 구분하면 조사 계획도 더 선명해집니다.
어떤 키가 헤더로 나갔는지, 수신 Context에 들어왔는지, 스팬 속성에 선택적으로 기록됐는지,
저장소에 남았는지는 각각 다른 질문입니다. 한 곳에서 값을 봤다고 나머지 경계를
확인한 것처럼 보고하지 마세요.
현장에서 만나는 모습
이 연습을 바탕으로 코드 리뷰를 한다면 정상 헤더 하나만 보지 않습니다. 빈 헤더,
알 수 없는 키, 알려진 키의 잘못된 값, 다른 목적지, 허용 호스트처럼 보이는 접두어,
원래 요청의 로컬 값이 있는 경우를 함께 대조합니다. 실제 데이터가 없어도 각 경계의
반례를 만들 수 있습니다. 합성 자료로 실패 조건을 먼저 재현하면 불필요한 운영 정보
수집 없이 코드의 책임을 좁힐 수 있습니다.
다음 실습에서 할 것
6단계는 들어온 값을 기존 요청과 분리해 읽습니다. 7단계는 표의 목적지·키·값 정책으로
내보낼 헤더를 만듭니다. 8단계는 전파 시점·복구·신뢰 범위에 관한 여덟 가설을 판정합니다.
보고서만 맞아도 통과하는 과제가 아닙니다. 앞 일곱 함수의 실제 동작이 모두 맞아야
종합 검증을 통과하며, 통과 범위를 외부 인증이나 네트워크 보안 전체로 넓히지 않습니다.