사설 네트워크와 결코 통신하지 않는 공개 양식도 사설 네트워크가 판단해야 할 데이터를 만들어 냅니다. 터널은 누가 누구에게 접속하는지만 바꿉니다. 다운로드 이후의 모든 것은 가져오기 결정이며 사설 쪽에 속합니다. 이 안내는 하나의 제출물을 브라우저에서 커밋된 내부 기록까지 따라갑니다.

제출물이 도착하는 지점에서 시작하기

브라우저는 공개 엔드포인트로 요청을 보내고, 그 엔드포인트는 통제된 접수 저장소에 한 행을 기록한 뒤 승인 응답 외에는 아무것도 반환하지 않습니다. 그 저장소가 인계 지점이며, 공개 계층이 쓸 수 있는 유일한 대상이어야 합니다. 원시 페이로드는 도착 시각과 안정적인 기록 식별자와 함께 그대로 보관하십시오.

그다음 사설 작업자는 터널을 통해 대기 중인 행을 가져와 각 행을 어떻게 처리할지 결정합니다. 그것은 자체 신원으로 실행되며, 이는 다음 절의 주제입니다.

curl --silent --fail \
  --cert /etc/importer/client.crt --key /etc/importer/client.key \
  "https://intake.corp.internal/api/pending?limit=20" \
  -o /var/lib/importer/pending.json

가져오기 도구에 필요한 권한만 부여하기

공개 웹 프로세스와 내부 애플리케이션에 기록하는 신원은 서로 다른 두 주체여야 합니다. 공개 서버는 양식 데이터를 전달해야 한다는 이유만으로 내부 관리 권한을 가질 필요가 없으며, 양쪽이 하나의 공유 계정을 쓰면 어떤 웹 버그든 내부 쓰기로 바뀝니다. 작업자에게 자체 자격 증명을 발급하고, 하나의 가져오기 작업으로 범위를 한정하며, 각 가져오기를 어느 주체가 수행했는지 기록하십시오. 그 분리가 터널 경계를 장식이 아니라 의미 있는 것으로 만듭니다.

작업자가 읽을 수 있는 원본도 제한하십시오. 구현이 큐나 전송 서비스를 사용한다면 그 서비스는 자체 인증과 접근 정책을 유지해야 하는데, VPN은 페이로드 내부의 무엇도 인증하지 않기 때문입니다.

수명이 짧은 함수도 같은 검토에서 예외가 아닙니다. 실행되는 동안에는 네트워크상의 위치와 자격 증명이 여전히 권한을 부여하며, 수명이 짧다는 것은 창을 좁힐 뿐입니다. 수명은 그 신원이 어떤 작업을 수행할 수 있는지 결정하는 일을 대신하지 못합니다.

내부에서 무엇이든 바뀌기 전에 검증하기

공개 양식 필드는 반증될 때까지 공격자가 통제하는 텍스트이며, OWASP의 입력 검증 지침이 바로 그 이유로 백엔드 피드를 신뢰할 수 없는 원본에 포함합니다. 암호화된 전송은 바이트가 온전히 도착했다는 뜻이지, 그것이 허용 가능한 요청을 기술한다는 뜻은 아닙니다. 권한 있는 단계보다 먼저 파싱하고 검증하여, 잘못된 행이 동작할 수 있는 코드 경로에 도달하지 않게 하십시오.

허용되는 필드, 그 형식과 크기, 지켜져야 할 비즈니스 규칙을 정의하십시오. 날짜는 형식이 올바르더라도 요청된 작업에는 틀릴 수 있고, 내부 계정이나 승인 상태를 지정한 페이로드는 스스로 그중 무엇도 부여할 수 없어야 합니다.

거부된 행은 수정을 추측하거나 셸이나 원시 데이터베이스 인터페이스로 넘기지 말고 검토 결과로 보내십시오. 신청자가 입력한 모든 필드가 아니라 기록 식별자와 실패한 규칙을 기록하십시오.

하나의 작업에 재시도 지점 만들기

첫 승인이 유실되어 submission-1042 기록이 두 번 가져와진다면, 작업자는 원본 기록과 커밋된 결과를 알아볼 지속적인 방법이 필요합니다. 작업을 한 번 실행하는 스케줄은 각 행이 한 번 적용되었음을 보장하지 않습니다. 중복 전달은 정상이므로 설계가 이를 흡수해야 합니다.

내부 애플리케이션 자체의 트랜잭션과 중복 처리 메커니즘을 사용하고, 원본 식별자와 결과, 승인을 하나의 일관된 순서로 유지하십시오. 의도한 작업이 커밋되거나 지속적으로 할당된 뒤에만 승인하고, 바이트를 내려받았다는 이유만으로 접수 행을 삭제하지 마십시오.

그다음 세 가지 픽스처로 증명하십시오: 유효한 행, 형식이 잘못된 행, 그리고 같은 통제된 원본 식별자가 두 번 전달된 경우입니다. 각각은 작업자가 사용하는 같은 엔드포인트를 통과합니다.

for f in fixtures/valid-submission.json fixtures/bad-date.json; do
  curl --silent --fail --cert /etc/importer/client.crt \
    -X POST --data @"$f" https://intake.corp.internal/api/records
done
curl --silent --fail --cert /etc/importer/client.crt \
  -X POST --data @fixtures/valid-submission.json https://intake.corp.internal/api/records

처음 두 행은 서로 다른 내부 상태로 끝나야 하고, 세 번째는 두 번째 기록을 만들지 않고 해당 원본 기록에 이미 커밋된 식별자를 반환해야 합니다. 그 밖의 결과는 가져오기가 아직 반복 가능하지 않다는 뜻입니다.

관련 글