Zest script in CLI

ZAP의 강력한 기능인 Scripting에서 한번 더 강력하게 만들어 주는 것이 바로 Zest script입니다. JSON 기반의 스크립트로 웹 Req/Res 그리고 Headless browser에 대한 컨트롤, 마지막으로 Assertion 등 테스팅 기능을 이용해 간단한 코드로 복잡한 테스팅을 할 수 있는 스크립트입니다. 자세한 내용은 제가 전에 작성했던 글들을 참고해주세요.

오늘은 이 Zest를 CLI에서 실행하는 방법에 대해 이야기할까 합니다.

Zest CLI

제가 쓴 글, 그리고 실제로 사용할 때에도 저는 대부분의 Zest script를 ZAP에서 작성/동작 시킵니다. 이는 Zest가 ZAP과의 궁합이 굉장히 좋기 때문인데요. 사실 Zest는 CLI도 지원합니다.

만약 Zest script가 익숙해진다면, 아니 ZAP에서 GUI로 작성하는 방법에 익숙해진다면 오히려 간단한 자동화 작업이나 Headless를 통한 작업들은 Ruby/Python 등 스크립팅 언어보다 Zest로 작성하는게 더 빠르고 편리할 것 같단 생각이 듭니다. 그래서 오늘 이 내용을 조금 더 풀어보는 것이구요.

Zest의 장점 중 하나가 GUI 기반으로도 작성할 수 있다는 점이에요. 또한 ZAP에서 Proxy Record도 지원하기 때문에 단순하겐 쿠키 처리부터 복잡한 로직까지 클릭으로 쉽게 만들어나갈 수 있습니다 😊

ZAP에서 Zest도 별도로 내장되는게 아니라 Zest libary를 포함시켜 Scripting engine으로 동작시킵니다. 그래서 이 라이브러리를 따로 빌드하면 CLI로 실행할 수 있게 되죠 :D

Build

자 그럼 Zest를 다운로드 받아줍시다. gradle tasks는 ./gradlew tasks 로 확인하실 수 있습니다.

git clone https://github.com/zaproxy/zest
cd zest
./gradlew tasks

우린 빌드를 해야하니 build task를 실행합시다.

./gradlew build

완료되면 ./build/distributions 하위에 tar,zip 파일로 배포되고 압축을 풀면 binlib 디렉토리가 나타납니다. bin 에는 실행 스크립트가 들어있고, lib에는 java에서 참조할 라이브러리가 들어있습니다.

java -jar build/distributions/zest-0.16.0-SNAPSHOT/bin/zest-0.16.0-SNAPSHOT.jar
Usage: -script <file> [-summary | -list] [-debug] [-timeout <timeout for requests in seconds>] [-prefix <http://prefix>] [-token <name>=<value>]...
    [-http-auth-site <site> -http-auth-realm <realm> -http-auth-user <user> -http-auth-password <password>]
    [-insecure <skip the SSL certificate check>]    For more information about Zest visit https://github.com/zaproxy/zest/

Test

Write zest script

테스트를 위해 ZAP에서 2가지 스크립트를 만들었습니다. 하나는 단순히 웹 요청 후 Print 하는 스크립트, 나머지 하나는 Headless 브라우저로 페이지를 열어 2개 페이지를 탐색한 후 스크린샷을 찍는 스크립트입니다.

{
  "about": "hahwulTest.zst / 스크린샷을 찍는 스크립트",
  "zestVersion": "0.8",
  "title": "Test",
  "description": "",
  "prefix": "https://www.hahwul.com",
  "type": "StandAlone",
  "parameters": {
    "tokenStart": "{{",
    "tokenEnd": "}}",
    "tokens": {},
    "elementType": "ZestVariables"
  },
  "statements": [
    {
      "windowHandle": "firefox",
      "browserType": "firefox",
      "url": "https://www.hahwul.com",
      "capabilities": "",
      "headless": false,
      "index": 1,
      "enabled": true,
      "elementType": "ZestClientLaunch"
    },
    {
      "milliseconds": 3000,
      "index": 2,
      "enabled": true,
      "elementType": "ZestActionSleep"
    },
    {
      "windowHandle": "firefox",
      "filePath": "/Users/<UserName>/123.png",
      "variableName": "screenshot",
      "index": 3,
      "enabled": true,
      "elementType": "ZestClientScreenshot"
    }
  ],
  "authentication": [],
  "index": 0,
  "enabled": true,
  "elementType": "ZestScript"
}

Run

편한 작업을 위해 디렉토리를 이동합시다.

cd ./build/distributions/zest-0.16.0-SNAPSHOT/bin/

Request-Base

./zest -script ForZestCLI.zst

Headless-Base

./zest -script hahwulTest.zst

실행이 끝나면 아래와 같이 Headless로 접근해서 찍은 스크린샷이 지정한 경로에 생성됩니다.

Conclusion

Zest 정말 좋습니다. 물론 뭐 서비스를 만들거나 도구를 만든다고 한다면 당연히 프로그래밍 언어를 택하는게 맞습니다. 다만 단순한 자동화나 테스팅을 위한 자동화 로직의 경우 Zest와 친해진다면 정말 쉽고 빠르게 구현하고 사용할 수 있습니다.

현재까지는 제 대부분의 자동화 로직 중 Headless가 필요한 경우들은 모두 Golang + Chromedp 또는 Ruby + Selenium-Driver 조합으로 진행합니다. 특히나 도구를 만드는게 아닌 단순한 자동화의 경우 Ruby를 굉장히 자주 사용하는데요, 이제는 Ruby 비중을 많이 줄이고 Zest script와 CLI 기반의 조합으로 조금씩 더 늘려볼까 생각중입니다 :D