분석기 설정 사용자 정의

인증

인증은 헤더 또는 쿠키로 인증 토큰을 제공하여 처리됩니다. 인증 흐름을 수행하거나 토큰을 계산하는 스크립트를 제공할 수 있습니다.

HTTP 기본 인증

HTTP 기본 인증은 HTTP 프로토콜에 내장된 인증 방법으로, 전송 계층 보안 (TLS)과 함께 사용됩니다.

비밀번호를 위한 CI/CD 변수를 만들고 (예: TEST_API_PASSWORD), 마스킹되도록 설정하는 것이 좋습니다. GitLab 프로젝트 페이지의 설정 > CI/CD에서 Variables 섹션에서 CI/CD 변수를 만들 수 있습니다. 마스크된 변수에 대한 제한 사항으로 인해 변수를 추가하기 전에 패스워드를 Base64로 인코딩해야 합니다.

마지막으로, .gitlab-ci.yml 파일에 두 개의 CI/CD 변수를 추가합니다:

  • DAST_API_HTTP_USERNAME: 인증을 위한 사용자 이름입니다.
  • DAST_API_HTTP_PASSWORD_BASE64: Base64로 인코딩된 인증을 위한 비밀번호입니다.
stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_HAR: test-api-recording.har
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_HTTP_USERNAME: testuser
  DAST_API_HTTP_PASSWORD_BASE64: $TEST_API_PASSWORD

원시 패스워드

패스워드를 Base64로 인코딩하고 싶지 않거나 GitLab 15.3 이전 버전을 사용하는 경우, DAST_API_HTTP_PASSWORD_BASE64 대신에 원시 패스워드 DAST_API_HTTP_PASSWORD를 제공할 수 있습니다.

Bearer 토큰

Bearer 토큰은 OAuth2 및 JSON Web Tokens (JWT)을 포함한 여러 인증 메커니즘에서 사용됩니다. Bearer 토큰은 Authorization HTTP 헤더를 사용하여 전송됩니다. DAST API에서 Bearer 토큰을 사용하려면 다음 중 하나가 있어야 합니다:

  • 만료되지 않는 토큰
  • 테스트 기간 동안 유지되는 토큰을 생성하는 방법
  • DAST API가 호출할 수 있는 Python 스크립트

토큰이 만료되지 않음

Bearer 토큰이 만료되지 않으면, DAST_API_OVERRIDES_ENV 변수를 사용하여 제공하십시오. 이 변수의 내용은 DAST API의 발신 HTTP 요청에 추가할 헤더 및 쿠키를 제공하는 JSON 스니펫입니다.

DAST_API_OVERRIDES_ENV로 Bearer 토큰을 제공하는 단계는 다음과 같습니다:

  1. 예를 들어 TEST_API_BEARERAUTH와 같이 프로젝트를 위한 CI/CD 변수를 만들고 값을 {"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}} (토큰을 대체)로 설정합니다. GitLab 프로젝트 페이지의 설정 > CI/CD에서 Variables 섹션에서 CI/CD 변수를 만들 수 있습니다. TEST_API_BEARERAUTH의 형식 때문에 변수를 마스킹하는 것은 불가능합니다. 토큰 값을 마스킹하려면 토큰 값으로 두 번째 변수를 만들고 TEST_API_BEARERAUTH의 값으로 {"headers":{"Authorization":"Bearer $MASKED_VARIABLE"}}를 정의하세요.

  2. .gitlab-ci.yml 파일에서 DAST_API_OVERRIDES_ENV를 방금 만든 변수로 설정합니다:

    stages:
      - dast
    
    include:
      - template: DAST-API.gitlab-ci.yml
    
    variables:
      DAST_API_PROFILE: Quick
      DAST_API_OPENAPI: test-api-specification.json
      DAST_API_TARGET_URL: http://test-deployment/
      DAST_API_OVERRIDES_ENV: $TEST_API_BEARERAUTH
    
  3. 인증이 작동하는지 확인하려면, DAST API 테스트를 실행하고 작업 로그 및 테스트 API의 응용 프로그램 로그를 확인하십시오.

테스트 실행 중 생성된 토큰

Bearer 토큰이 생성되고 테스트하는 동안 만료되지 않으면, 토큰이 포함된 파일을 DAST API에 제공할 수 있습니다. 이 파일은 이전 단계 및 작업 또는 DAST API 작업의 일부가 생성할 수 있습니다.

DAST API는 다음과 같은 구조의 JSON 파일을 받도록 기대합니다:

{
  "headers" : {
    "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

이 파일은 이전 단계에서 생성되어 DAST_API_OVERRIDES_FILE CI/CD 변수를 통해 DAST API에 제공될 수 있습니다.

.gitlab-ci.yml 파일에서 DAST_API_OVERRIDES_FILE을 설정합니다:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json

인증이 작동하는지 확인하려면, DAST API 테스트를 실행하고 작업 로그 및 테스트 API의 응용 프로그램 로그를 확인하십시오.

토큰의 짧은 만료

만일 스캔이 완료되기 전에 Bearer 토큰을 생성하고 만료되어야 한다면, DAST API 스캐너를 위해 제공된 간격에서 실행될 프로그램이나 스크립트를 제공할 수 있습니다. 제공된 스크립트는 Python 3과 Bash가 설치된 Alpine Linux 컨테이너에서 실행됩니다. Python 스크립트가 추가 패키지를 필요로 하는 경우, 이를 인식하고 실행 시간에 패키지를 설치해야 합니다.

스크립트는 특정 형식으로 Bearer 토큰을 포함하는 JSON 파일을 생성해야 합니다:

{
  "headers" : {
    "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

다음과 같이 올바른 작동을 위해 설정된 세 가지의 CI/CD 변수를 제공해야 합니다:

  • DAST_API_OVERRIDES_FILE: 제공된 명령이 생성하는 JSON 파일입니다.
  • DAST_API_OVERRIDES_CMD: JSON 파일을 생성하는 명령어입니다.
  • DAST_API_OVERRIDES_INTERVAL: 명령어를 실행하는 간격(초)입니다.

예시:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json
  DAST_API_OVERRIDES_CMD: renew_token.py
  DAST_API_OVERRIDES_INTERVAL: 300

인증이 작동하는지 확인하기 위해 DAST API 테스트를 실행하고 작업 로그와 테스트 API 응용 프로그램 로그를 확인하세요. 보다 자세한 정보는 overrides section을 참조하세요.

Overrides

DAST API는 요청에 특정 항목을 추가하거나 덮어쓸 수 있는 방법을 제공합니다. 예를 들어:

  • 헤더
  • 쿠키
  • 쿼리 문자열
  • 폼 데이터
  • JSON 노드
  • XML 노드

이를 사용하여 시맨틱 버전 헤더, 인증 등을 삽입할 수 있습니다. authentication section에는 그러한 목적으로 overrides를 사용하는 예시가 포함되어 있습니다.

Overrides는 각 override 유형을 나타내는 JSON 객체로 구성된 JSON 문서를 사용합니다:

{
  "headers": {
    "header1": "value",
    "header2": "value"
  },
  "cookies": {
    "cookie1": "value",
    "cookie2": "value"
  },
  "query":      {
    "query-string1": "value",
    "query-string2": "value"
  },
  "body-form":  {
    "form-param1": "value",
    "form-param2": "value"
  },
  "body-json":  {
    "json-path1": "value",
    "json-path2": "value"
  },
  "body-xml" :  {
    "xpath1":    "value",
    "xpath2":    "value"
  }
}

단일 헤더 설정의 예:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

헤더와 쿠키를 함께 설정하는 예제:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  },
  "cookies": {
    "flags": "677"
  }
}

body-form override를 설정하기 위한 예시 사용 방법:

{
  "body-form":  {
    "username": "john.doe"
  }
}

요청 본문이 폼 데이터 내용만 포함하는 경우, override 엔진은 body-form을 사용합니다.

body-json override를 설정하는 예시:

{
  "body-json":  {
    "$.credentials.access-token": "iddqd!42.$"
  }
}

객체 body-json 안의 각 JSON 속성 이름은 JSON 경로 표현식으로 설정됩니다. JSON 경로 표현식 $.credentials.access-token은 값을 iddqd!42.$로 덮어쓸 노드를 식별합니다. override 엔진은 요청 본문이 JSON 내용만 포함하는 경우 body-json을 사용합니다.

예를 들어, 본문이 다음 JSON으로 설정된 경우:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "non-valid-password"
    }
}

다음으로 변경됩니다:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "iddqd!42.$"
    }
}

body-xml override를 설정하는 방법에 대한 예시도 제공됩니다. 첫 번째 항목은 XML 속성을 덮어씁니다. 두 번째 항목은 XML 요소를 덮어씁니다.

{
  "body-xml" :  {
    "/credentials/@isEnabled": "true",
    "/credentials/access-token/text()" : "iddqd!42.$"
  }
}

객체 body-xml 내의 각 JSON 속성 이름은 XPath v2 표현식으로 설정됩니다. XPath 표현식 /credentials/@isEnabled은 값 true로 덮어쓸 속성 노드를 식별합니다. XPath 표현식 /credentials/access-token/text()은 값 iddqd!42.$로 덮어쓸 요소 노드를 식별합니다. override 엔진은 요청 본문이 XML 내용만 포함하는 경우 body-xml을 사용합니다.

예를 들어, 본문이 다음 XML으로 설정된 경우:

<credentials isEnabled="false">
  <username>john.doe</username>
  <access-token>non-valid-password</access-token>
</credentials>

다음으로 변경됩니다:

<credentials isEnabled="true">
  <username>john.doe</username>
  <access-token>iddqd!42.$</access-token>
</credentials>

이 JSON 문서를 파일 또는 환경 변수로 제공할 수 있습니다. 또한 만료되는 값을 지원하기 위해 일정 간격으로 실행할 수 있는 명령어를 제공할 수 있습니다.

파일 사용하기

오버라이드 JSON을 파일로 제공하려면 DAST_API_OVERRIDES_FILE CI/CD 변수를 설정합니다. 경로는 작업의 현재 작업 디렉토리를 기준으로 상대적입니다.

다음은 .gitlab-ci.yml의 예시입니다:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json

CI/CD 변수 사용하기

오버라이드 JSON을 CI/CD 변수로 제공하려면 DAST_API_OVERRIDES_ENV 변수를 사용합니다. 이를 통해 변수로 JSON을 쉽게 마스킹하고 보호할 수 있습니다.

다음은 .gitlab-ci.yml의 예시에서 DAST_API_OVERRIDES_ENV 변수가 직접적으로 JSON을 설정하는 방법입니다:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'

다음은 .gitlab-ci.yml의 예시에서 SECRET_OVERRIDES 변수가 JSON을 제공하는 방법입니다. 이는 UI에서 정의된 그룹 또는 인스턴스 레벨 CI/CD 변수입니다:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_ENV: $SECRET_OVERRIDES

명령어 사용하기

값을 생성하거나 만료 시 다시 생성해야 하는 경우, DAST API 스캐너가 지정된 간격으로 실행할 프로그램 또는 스크립트를 제공할 수 있습니다. 제공된 명령어는 Python 3 및 Bash가 설치된 Alpine Linux 컨테이너에서 실행됩니다.

DAST_API_OVERRIDES_CMD 환경 변수를 원하는 프로그램이나 스크립트로 설정해야 합니다. 제공된 명령어는 이전에 정의된대로 오버라이드 JSON 파일을 생성합니다.

NodeJS나 Ruby와 같은 기타 스크립팅 런타임을 설치하거나 오버라이드 명령에 대한 종속성을 설치해야 하는 경우 DAST_API_PRE_SCRIPT를 설정하는 것이 좋습니다. DAST_API_PRE_SCRIPT에서 제공된 스크립트는 분석기가 시작하기 전에 한 번 실행됩니다.

Alpine Linux 패키지 관리에 대한 정보는 Alpine Linux package management 페이지를 참조하세요.

올바른 동작을 위해 세 개의 CI/CD 변수를 제공해야 합니다:

  • DAST_API_OVERRIDES_FILE: 제공된 명령어에 의해 생성된 파일.
  • DAST_API_OVERRIDES_CMD: 오버라이드 JSON 파일을 주기적으로 생성하는 오버라이드 명령어.
  • DAST_API_OVERRIDES_INTERVAL: 명령어를 실행할 간격(초)입니다.

선택 사항:

  • DAST_API_PRE_SCRIPT: 스캔을 시작하기 전에 런타임이나 종속성을 설치하는 스크립트.

경고: Alpine Linux에서 스크립트를 실행하려면 먼저 chmod 명령어를 사용하여 실행 권한을 설정해야 합니다. 예를 들어, script.py의 실행 권한을 모두에게 주려면 다음 명령어를 사용합니다: chmod a+x script.py. 필요하다면 실행 권한이 이미 설정된 script.py를 버전 관리할 수 있습니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json
  DAST_API_OVERRIDES_CMD: renew_token.py
  DAST_API_OVERRIDES_INTERVAL: 300

오버라이드 디버깅

기본적으로 오버라이드 명령어의 출력은 숨겨집니다. 오버라이드 명령어가 0이 아닌 종료 코드를 반환하면 해당 명령어는 작업 출력 결과에 표시됩니다. 선택적으로 DAST_API_OVERRIDES_CMD_VERBOSE 변수를 모든 값으로 설정하여 오버라이드 명령어 출력을 생성될 때 보이게 할 수 있습니다. 이는 오버라이드 스크립트를 테스트할 때 유용하지만 테스트 속도를 늦추므로 비활성화해야 합니다.

스크립트에서 작업이 완료되거나 실패한 후에 수집되는 로그 파일에 메시지를 작성할 수도 있습니다. 로그 파일은 특정 위치에 생성되고 특정한 명명 규칙을 따라야 합니다.

오버라이드 스크립트에 기본적인 로깅을 추가하면 일반적인 작업 중 스크립트가 예기치 않게 실패하는 경우 유용합니다. 로그 파일은 작업 결과물의 일부로 자동으로 포함되어 있어 작업이 완료된 후 다운로드할 수 있습니다.

이 예제에서 renew_token.pyDAST_API_OVERRIDES_CMD 환경 변수로 제공했습니다. 스크립트에서 두 가지 사항을 주의해봅니다:

  • 로그 파일은 CI_PROJECT_DIR 환경 변수에 지정된 위치에 저장됩니다.
  • 로그 파일 이름은 gl-*.log와 일치해야 합니다.
#!/usr/bin/env python

# 오버라이드 명령어 예제

# 오버라이드 명령어는 사용될 새로운 값을 가진 오버라이드 JSON 파일을 업데이트할 수 있습니다.
# 이는 테스트 중에 만료되는 인증 토큰을 업데이트하는 훌륭한 방법입니다.

import logging
import json
import os
import requests
import backoff

# [1] 로그 파일을 env var CI_PROJECT_DIR에 저장
working_directory = os.environ.get( 'CI_PROJECT_DIR')
overrides_file_name = os.environ.get('DAST_API_OVERRIDES_FILE', 'dast-api-overrides.json')
overrides_file_path = os.path.join(working_directory, overrides_file_name)

# [2] 파일 이름은 아래 패턴과 일치해야함: gl-*.log
log_file_path = os.path.join(working_directory, 'gl-user-overrides.log')

# 로거 설정
logging.basicConfig(filename=log_file_path, level=logging.DEBUG)

# 일시적 오류가 발생할 경우 `backoff` 데코레이터를 사용해 다시 시도하게 함.
@backoff.on_exception(backoff.expo,
                      (requests.exceptions.Timeout,
                       requests.exceptions.ConnectionError),
                       max_time=30)
def get_auth_response():
    authorization_url = 'https://authorization.service/api/get_api_token'
    return requests.get(
        f'{authorization_url}',
        auth=(os.environ.get('AUTH_USER'), os.environ.get('AUTH_PWD'))
    )

# 예제에서는 엑세스 토큰이 특정 엔드포인트에서 검색됨
try:

    # HTTP 요청 수행, 응답 예제:
    # { "Token" : "abcdefghijklmn" }
    response = get_auth_response()

    # 요청이 성공적인지 확인. `requests.exceptions.HTTPError`를 발생시킬 수 있음
    response.raise_for_status()

    # JSON 데이터 가져오기
    response_body = response.json()

# 필요한 특정 예외를 처리할 수 있음
# requests.ConnectionError                  : 네트워크 연결 오류 문제 발생
# requests.HTTPError                        : HTTP 요청이 성공하지 못하는 상태 코드를 반환함. [Response.raise_for_status()]
# requests.ConnectTimeout                   : 원격 서버에 연결하려고 시도하는 동안 요청이 시간 초과됨
# requests.ReadTimeout                      : 서버가 주어진 시간 내에 데이터를 보내지 않음
# requests.TooManyRedirects                 : 요청이 최대 재지정 횟수를 초과함
# requests.exceptions.RequestException      : Requests에 관련된 모든 예외
except json.JSONDecodeError as json_decode_error:
    # JSON 응답 디코딩과 관련된 오류 기록
    logging.error(f'오류, JSON 응답 디코딩 중 실패. 오류 메시지: {json_decode_error}')
    raise
except requests.exceptions.RequestException as requests_error:
    # `Requests`와 관련된 예외 기록
    logging.error(f'오류, HTTP 요청 수행 중 실패. 오류 메시지: {requests_error}')
    raise
except Exception as e:
    # 다른 모든 오류 기록
    logging.error(f'오류, 알 수 없는 에러로 액세스 토큰 검색 중 실패. 오류 메시지: {e}')
    raise

# 오버라이드 파일 내용을 보유하는 개체 계산
# 이는 요청에서 가져온 데이터를 사용함
overrides_data = {
    "headers": {
        "Authorization": f"Token {response_body['Token']}"
    }
}

# 파일 오버라이드 계산에 대한 로그 기록
logging.info("오버라이드 파일 생성: %s" % overrides_file_path)

# 파일 덮어쓰기 시도
try:
    if os.path.exists(overrides_file_path):
        os.unlink(overrides_file_path)

    # 파일을 업데이트된 딕셔너리로 덮어쓰기
    with open(overrides_file_path, "wb+") as fd:
        fd.write(json.dumps(overrides_data).encode('utf-8'))
except Exception as e:
    # 다른 모든 오류 기록
    logging.error(f'오류, {overrides_file_path} 파일 덮어쓰기 중 알 수 없는 에러 발생. 오류 메시지: {e}')
    raise

# 오버라이드가 성공적으로 완료되었다는 기록
logging.info("오버라이드 파일이 업데이트되었습니다")

# end

오버라이드 명령어 예제에서 Python 스크립트는 backoff 라이브러리에 의존합니다. Python 스크립트를 실행하기 전에 해당 라이브러리가 설치되어 있는지 확인하기 위해 DAST_API_PRE_SCRIPT가 오버라이드 명령어의 종속성을 설치하는 스크립트로 설정됩니다. 예를 들어, 다음 스크립트 user-pre-scan-set-up.sh

#!/bin/bash

# user-pre-scan-set-up.sh
# python 종속성을 설치하는 스크립트

echo "**** python 종속성 설치 ****"

python3 -m ensurepip
pip3 install --no-cache --upgrade \
    pip \
    backoff

echo "**** python 종속성이 설치됨 ****"

# end

설정을 업데이트하여 새로운 user-pre-scan-set-up.sh 스크립트를 DAST_API_PRE_SCRIPT로 설정해야 합니다. 예:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_PRE_SCRIPT: user-pre-scan-set-up.sh
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json
  DAST_API_OVERRIDES_CMD: renew_token.py
  DAST_API_OVERRIDES_INTERVAL: 300

이전 예에서 user-pre-scan-set-up.sh 스크립트를 사용하여 나중에 오버라이드 명령어에 사용할 새로운 런타임 또는 애플리케이션을 설치할 수 있습니다.

요청 헤더

요청 헤더 기능을 사용하면 스캔 세션 중에 헤더의 고정 값을 지정할 수 있습니다. 예를 들어, 구성 변수 DAST_API_REQUEST_HEADERS를 사용하여 Cache-Control 헤더에 고정 값을 설정할 수 있습니다. 필요한 헤더에 Authorization 헤더와 같이 민감한 값이 포함된 경우, 마스킹된 변수 기능과 함께 변수 DAST_API_REQUEST_HEADERS_BASE64을 사용하세요.

스캔이 진행 중인 동안 Authorization 헤더나 다른 헤더를 업데이트해야 하는 경우 overrides 기능을 고려하세요.

변수 DAST_API_REQUEST_HEADERS를 사용하면 쉼표로 구분된 헤더(,) 목록을 지정할 수 있습니다. 이러한 헤더는 스캐너가 수행하는 각 요청에 포함됩니다. 목록의 각 헤더 항목은 이름 다음에 콜론(:)으로 구분되고 그 값이 뒤따릅니다. 키나 값 앞의 공백은 무시됩니다. 예를 들어, 값이 max-age=604800Cache-Control 헤더를 선언하려면 헤더 항목은 Cache-Control: max-age=604800입니다. 두 개의 헤더, Cache-Control: max-age=604800Age: 100을 사용하려면 DAST_API_REQUEST_HEADERS 변수를 Cache-Control: max-age=604800, Age: 100으로 설정하세요.

다른 헤더가 제공될 때 변수 DAST_API_REQUEST_HEADERS에 제공된 순서는 결과에 영향을 주지 않습니다. Cache-Control: max-age=604800, Age: 100으로 설정하든 Age: 100, Cache-Control: max-age=604800으로 설정하든 동일한 결과를 얻습니다.

Base64

DAST_API_REQUEST_HEADERS_BASE64 변수는 DAST_API_REQUEST_HEADERS와 동일한 헤더 목록을 허용하지만 변수의 전체 값은 Base64로 인코딩되어야 한다는 점만 다릅니다. 예를 들어, DAST_API_REQUEST_HEADERS_BASE64 변수를 Authorization: QmVhcmVyIFRPS0VO, Cache-control: bm8tY2FjaGU=로 설정하려면 목록을 해당 Base64로 변환한 후 사용해야 합니다. 이것은 문자 집합 제한을 가진 마스킹된 변수에 비밀 헤더 값을 저장하는 경우에 유용합니다.

경고: Base64는 마스킹된 변수를 지원하기 위해 사용됩니다. 민감한 값은 쉽게 디코딩될 수 있기 때문에 Base64 인코딩 자체가 보안 조치가 되지는 않습니다.

예: 평문 사용하여 각 요청에 헤더 목록 추가

다음 .gitlab-ci.yml 예제에서 DAST_API_REQUEST_HEADERS 구성 변수를 설정하여 요청 헤더에서 설명한 대로 두 개의 헤더 값을 제공합니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_REQUEST_HEADERS: 'Cache-control: no-cache, Save-Data: on'

예: 마스킹된 CI/CD 변수 사용하기

다음 .gitlab-ci.yml 샘플은 마스킹된 변수 SECRET_REQUEST_HEADERS_BASE64UI에서 정의된 그룹 또는 인스턴스 수준 CI/CD 변수로 가정합니다. SECRET_REQUEST_HEADERS_BASE64의 값은 X-ACME-Secret: s3cr3t!, X-ACME-Token: 705d16f5e3fb의 Base64로 인코딩된 텍스트 버전인 WC1BQ01FLVNlY3JldDogc31jcnt0ISwgWC1BQ01FLVRva2VuOiA3MDVkMTZmNWUzZmI=으로 설정됩니다. 그런 다음 다음과 같이 사용할 수 있습니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_REQUEST_HEADERS_BASE64: $SECRET_REQUEST_HEADERS_BASE64

마스킹된 변수에 비밀 헤더 값을 저장하는 경우 DAST_API_REQUEST_HEADERS_BASE64을 사용하는 것을 고려하세요.

제외 경로

API를 테스트할 때 특정 경로를 제외하는 것이 유용할 수 있습니다. 예를 들어, 인증 서비스나 API의 이전 버전을 테스트에서 제외할 수 있습니다. 경로를 제외하려면 .gitlab-ci.yml 파일에 지정된 DAST_API_EXCLUDE_PATHS CI/CD 변수를 사용하십시오. 여러 경로를 제외하려면 ; 문자로 항목을 구분하십시오. 제공된 경로에서는 단일 문자 와일드카드 ? 및 다중 문자 와일드카드 * 를 사용할 수 있습니다.

제외된 경로를 확인하려면 작업 출력의 테스트된 작업제외된 작업을 검토하십시오. 테스트된 작업 아래에 나열된 제외된 경로를 보지 않아야 합니다.

2021-05-27 21:51:08 [INF] DAST API: --[ 테스트된 작업 ]-------------------------
2021-05-27 21:51:08 [INF] DAST API: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------
2021-05-27 21:51:08 [INF] DAST API: --[ 제외된 작업 ]-----------------------
2021-05-27 21:51:08 [INF] DAST API: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------

예제

다음 예에서는 /auth 리소스를 제외합니다. 이 경우 하위 리소스(/auth/child)는 제외되지 않습니다.

variables:
  DAST_API_EXCLUDE_PATHS: /auth

/auth 및 하위 리소스(/auth/child)를 제외하려면 와일드카드를 사용합니다.

variables:
  DAST_API_EXCLUDE_PATHS: /auth*

여러 경로를 제외하려면 ; 문자를 사용합니다. 다음 예에서는 /auth*/v1/*를 제외합니다.

variables:
  DAST_API_EXCLUDE_PATHS: /auth*;/v1/*

경로 내의 하나 이상의 중첩된 수준을 제외하려면 **를 사용합니다. 다음 예에서는 API 엔드포인트를 테스트합니다. planet, moon, star, 및 satellite 객체에 대한 mass, brightness, 및 coordinates 데이터를 요청하는 /api/v1//api/v2/를 테스트하고 있습니다. 스캔할 수 있는 예시 경로는 다음과 같습니다(제한을 받지 않음).

  • /api/v2/planet/coordinates
  • /api/v1/star/mass
  • /api/v2/satellite/brightness

다음 예에서는 brightness 엔드포인트만 테스트합니다.

variables:
  DAST_API_EXCLUDE_PATHS: /api/**/mass;/api/**/coordinates

매개변수 제외

API를 테스트하는 동안 매개변수(쿼리 문자열, 헤더 또는 본문 요소)를 제외하고 싶을 수 있습니다. 이는 매개변수가 항상 실패를 유발하거나 테스트를 늦추는 등의 이유로 필요할 수 있습니다. 매개변수를 제외하려면 다음 중 하나의 변수를 설정할 수 있습니다: DAST_API_EXCLUDE_PARAMETER_ENV 또는 DAST_API_EXCLUDE_PARAMETER_FILE.

DAST_API_EXCLUDE_PARAMETER_ENV를 사용하면 제외할 매개변수가 포함된 JSON 문자열을 제공할 수 있습니다. 이 옵션은 JSON이 짧고 자주 변경되지 않을 때 좋은 선택입니다. 또 다른 옵션은 DAST_API_EXCLUDE_PARAMETER_FILE 변수입니다. 이 변수는 저장소에 체크인할 수 있는 파일 경로로 설정되며, 다른 작업에서 생성된 아티팩트 또는 DAST_API_PRE_SCRIPT를 사용하여 런타임에 생성할 수 있습니다.

예시

단일 헤더 제외

Upgrade-Insecure-Requests 헤더를 제외하려면 header 속성의 값을 헤더 이름으로 된 배열로 설정하십시오: [ "Upgrade-Insecure-Requests" ]. 예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "headers": [ "Upgrade-Insecure-Requests" ]
}

헤더 이름은 대소문자를 구분하지 않으므로 UPGRADE-INSECURE-REQUESTS 헤더 이름은 Upgrade-Insecure-Requests와 동등합니다.

헤더와 두 개의 쿠키 모두 제외

Authorization 헤더와 PHPSESSID, csrftoken 쿠키를 제외하려면 headers 속성의 값을 헤더 이름으로 된 배열로 설정하고, cookies 속성의 값을 쿠키의 이름으로 된 배열로 설정하십시오. 예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "headers": [ "Authorization" ],
  "cookies": [ "PHPSESSID", "csrftoken" ]
}
‘body-form’ 매개변수 제외

application/x-www-form-urlencoded를 사용하는 요청에서 password 필드를 제외하려면 body-form 속성의 값을 필드 이름으로 된 배열로 설정하십시오. 예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "body-form":  [ "password" ]
}

제외 매개변수는 요청이 콘텐츠 유형 application/x-www-form-urlencoded를 사용할 때 body-form를 사용합니다.

JSON Path를 사용하여 특정 JSON 노드 제외

루트 오브젝트에서 schema 속성을 제외하려면 body-json 속성의 값을 JSON Path 표현으로 된 배열로 설정하십시오: [ "$.schema" ].

JSON Path 표현은 JSON 노드를 식별하는 특수 구문을 사용합니다: $는 JSON 문서의 루트를 나타내며, .은 현재 오브젝트를 나타냅니다 (여기서 우리의 경우 루트 오브젝트), 그리고 schema는 속성 이름을 나타냅니다. 따라서, JSON path 표현 $.schema는 루트 오브젝트에서 schema 속성을 나타냅니다.

예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "body-json": [ "$.schema" ]
}

제외 매개변수는 요청이 콘텐츠 유형 application/json를 사용할 때 body-json를 사용합니다. body-json의 각 항목은 JSON Path 표현으로 예상됩니다. JSON Path에는 $, *, . 등의 문자가 특별한 의미를 가지고 있습니다.

JSON Path를 사용하여 여러 개의 JSON 노드 제외

루트 레벨의 users 배열의 각 항목에서 password 속성을 제외하려면 body-json 속성의 값을 JSON Path 표현으로 된 배열로 설정하십시오: [ "$.users[*].password" ].

JSON Path 표현은 $로 루트 노드를 참조하고 .로 현재 노드를 참조합니다. 그런 다음 users를 사용하여 속성을 참조하고 [] 문자를 사용하여 제공한 배열에서 인덱스를 감싸고, 인덱스로 숫자를 제공하는 대신에 *를 사용하여 모든 인덱스를 지정합니다. 인덱스 참조 후, 이제 속성 이름인 password 앞에 .가 옵니다.

예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "body-json": [ "$.users[*].paswword" ]
}

제외 매개변수는 요청이 콘텐츠 유형 application/json를 사용할 때 body-json를 사용합니다. body-json의 각 항목은 JSON Path 표현으로 예상됩니다. JSON Path에는 $, *, . 등의 문자가 특별한 의미를 가지고 있습니다.

XML 속성 제외

루트 엘리먼트 credentials에서 isEnabled라는 속성을 제외하려면 body-xml 속성의 값을 XPath 표현으로 된 배열로 설정하십시오: [ "/credentials/@isEnabled" ].

XPath 표현 /credentials/@isEnabled은 XML 문서의 루트를 나타내기 위해 /로 시작하고, 그 다음에 일치할 엘리먼트의 이름인 credentials가 옵니다. 이전 XML 엘리먼트의 노드를 나타내기 위해 /를 사용하고, 이름 isEnable이 속성임을 나타내기 위해 @ 문자가 사용됩니다.

예를 들어, 다음과 같은 JSON 문서가 됩니다:

{
  "body-xml": [
    "/credentials/@isEnabled"
  ]
}

제외 매개변수는 요청이 콘텐츠 유형 application/xml를 사용할 때 body-xml를 사용합니다. body-xml의 각 항목은 XPath v2 표현으로 예상됩니다. XPath 표현에는 @, /, :, [, ] 등의 문자가 특별한 의미를 가지고 있습니다.

XML 텍스트의 요소 제외

credentials 루트 노드에 포함된 username 요소의 텍스트를 제외하려면 body-xml 속성의 값을 XPath 표현식이 포함된 배열로 설정하십시오. [/credentials/username/text()" ].

XPath 표현식 /credentials/username/text()에서 첫 번째 문자 /는 루트 XML 노드를 나타내며 이후에는 XML 요소의 이름 credentials을 나타냅니다. 비슷하게 문자 /는 현재 요소를 나타내고, 그 뒤에 새 XML 요소의 이름 username이 옵니다. 마지막 부분에 /는 현재 요소를 나타내며 text()라는 XPath 함수를 사용하여 현재 요소의 텍스트를 식별합니다.

예를 들어, JSON 문서는 다음과 같습니다.

{
  "body-xml": [
    "/credentials/username/text()"
  ]
}

요청에 content type application/xml을 사용할 때 제외 매개변수는 body-xml을 사용합니다. body-xml의 각 항목은 XPath v2 표현식으로 예상됩니다. XPath 표현식에서 @, /, :, [, ]와 같은 문자에는 특별한 의미가 있습니다.

XML 요소 제외

credentials 루트 노드에 포함된 username 요소를 제외하려면 body-xml 속성의 값을 XPath 표현식이 포함된 배열로 설정하십시오. [/credentials/username" ].

XPath 표현식 /credentials/username에서 첫 번째 문자 /는 루트 XML 노드를 나타내며 이후에는 XML 요소의 이름 credentials을 나타냅니다. 비슷하게 문자 /는 현재 요소를 나타내고, 그 뒤에 새 XML 요소의 이름 username이 옵니다.

예를 들어, JSON 문서는 다음과 같습니다.

{
  "body-xml": [
    "/credentials/username"
  ]
}

요청에 content type application/xml을 사용할 때 제외 매개변수는 body-xml을 사용합니다. body-xml의 각 항목은 XPath v2 표현식으로 예상됩니다. XPath 표현식에서 @, /, :, [, ]와 같은 문자에는 특별한 의미가 있습니다.

네임스페이스가 포함된 XML 노드 제외

네임스페이스 s에 정의된 login XML 요소를 credentials 루트 노드에 포함하여 제외하려면 body-xml 속성의 값을 XPath 표현식이 포함된 배열로 설정하십시오. ["/credentials/s:login" ].

XPath 표현식 /credentials/s:login에서 첫 번째 문자 /는 루트 XML 노드를 나타내며 이후에는 XML 요소의 이름 credentials를 나타냅니다. 비슷하게 문자 /는 현재 요소를 나타내고, 그 뒤에는 새 XML 요소의 이름 s:login이 옵니다. 이름에 : 문자가 포함되어 있는데, 이 문자는 네임스페이스와 노드 이름을 구분합니다.

네임스페이스 이름은 요청의 본문에 포함된 XML 문서에 정의되어야 합니다. 네임스페이스는 사양 문서 HAR, OpenAPI 또는 Postman Collection 파일에서 확인할 수 있습니다.

{
  "body-xml": [
    "/credentials/s:login"
  ]
}

요청에 content type application/xml을 사용할 때 제외 매개변수는 body-xml을 사용합니다. body-xml의 각 항목은 XPath v2 표현식으로 예상됩니다. XPath 표현식에서 @, /, :, [, ]와 같은 문자에는 특별한 의미가 있습니다.

JSON 문자열 사용

제외 JSON 문서를 제공하려면 변수 DAST_API_EXCLUDE_PARAMETER_ENV를 JSON 문자열로 설정하십시오. 다음 예제에서 .gitlab-ci.yml에서 DAST_API_EXCLUDE_PARAMETER_ENV 변수는 JSON 문자열로 설정됩니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_EXCLUDE_PARAMETER_ENV: '{ "headers": [ "Upgrade-Insecure-Requests" ] }'

파일 사용

제외 JSON 문서를 제공하려면 변수 DAST_API_EXCLUDE_PARAMETER_FILE을 JSON 파일 경로로 설정하십시오. 파일 경로는 작업의 현재 작업 디렉토리를 기준으로 상대적입니다. 다음 예제 .gitlab-ci.yml에서 DAST_API_EXCLUDE_PARAMETER_FILE 변수는 JSON 파일 경로로 설정됩니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_EXCLUDE_PARAMETER_FILE: dast-api-exclude-parameters.json

dast-api-exclude-parameters.jsonexclude parameters 문서 구조를 따르는 JSON 문서입니다.

URL 제외

경로별로 제외하는 대신, DAST_API_EXCLUDE_URLS CI/CD 변수를 사용하여 URL의 다른 구성요소별로 필터링할 수 있습니다. 이 변수는 .gitlab-ci.yml 파일에 설정할 수 있습니다. 변수는 쉼표(,)로 구분된 여러 값과 정규 표현식으로 이루어진 값을 저장할 수 있습니다. 각 값은 정규 표현식입니다. 따라서 .*와 같은 항목은 모든 URL을 제외하므로 모든 것과 일치하는 정규 표현식입니다.

작업 출력에서 DAST_API_EXCLUDE_URLS에서 제공된 정규 표현식과 일치하는 URL을 확인할 수 있습니다. 일치하는 작업은 제외된 작업 섹션에 나열됩니다. 제외된 작업에 나열된 작업은 테스트된 작업 섹션에 나열되어서는 안 됩니다. 예를 들어, 작업 출력의 다음 부분:

2021-05-27 21:51:08 [INF] DAST API: --[ 테스트된 작업 ]-------------------------
2021-05-27 21:51:08 [INF] DAST API: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------
2021-05-27 21:51:08 [INF] DAST API: --[ 제외된 작업 ]-----------------------
2021-05-27 21:51:08 [INF] DAST API: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------

참고: DAST_API_EXCLUDE_URLS의 각 값은 정규 표현식입니다. ., *, $ 등의 문자는 정규 표현식에서 특별한 의미를 가집니다.

예시

URL 및 하위 리소스 제외

다음 예시는 http://target/api/auth URL과 해당 하위 리소스를 제외합니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: http://target/api/auth
두 개의 URL 제외 및 하위 리소스 허용

http://target/api/buyhttp://target/api/sell URL을 제외하지만, 해당하는 하위 리소스를 스캔할 수 있도록하기 위한 예시입니다. 예를 들어: http://target/api/buy/toy 또는 http://target/api/sell/chair과 같이요. http://target/api/buy/$,http://target/api/sell/$ 값을 사용할 수 있습니다. 이 값은 두 개의 정규 표현식을 사용하며 각각 쉼표(,)로 분리됩니다. 따라서 http://target/api/buy$http://target/api/sell$를 포함합니다. 각 정규 표현식에서 후행하는 $ 문자는 일치하는 URL이 끝나는 지점을 나타냅니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: http://target/api/buy/$,http://target/api/sell/$
두 개의 URL과 해당 하위 리소스 제외

http://target/api/buyhttp://target/api/sell URL 및 해당 하위 리소스를 제외하기 위한 예시입니다. 여러 URL을 제공하기 위해 쉼표(,) 문자를 사용합니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: http://target/api/buy,http://target/api/sell
정규 표현식을 사용하여 URL 제외

정확히 https://target/api/v1/user/createhttps://target/api/v2/user/create 또는 다른 버전(v3, v4 등)을 제외하려면 https://target/api/v.*/user/create$를 사용할 수 있습니다. 이전의 정규 표현식에서 .는 모든 문자를, *는 0회 이상을, 추가로 $는 URL이 그 지점에서 끝나야 함을 나타냅니다.

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: https://target/api/v.*/user/create$