[Fortify] FPR 파일에서 스캔 시간 추출 스크립트

#!/bin/bash
#####################################################################
#
# Fortify SCA Scan 시간 추출 스크립트
#
# 이 스크립트는 FPR파일을 분석하여 아래의 파일을 출력한다.
# - CSV포맷의 스캔 시간 정리
# - 스케줄링을 추가하는 윈도우 배치파일 작성
#
# 윈도우에서 실행 시:
# bash -c "./get_fpr_scantime.sh ./fpr/*.fpr"
#
# by 이존석(hasu0707@esvali.com)
#
#####################################################################
DEBUG_ON=0
VERSION=0.1
WIN_MINGW_DIR="/cygdrive/c/PortableApps/cmd_cygwin_x86_64"
CSV_FILENAME="fpr_scantime_list.csv"
BAT_FILENAME="set_schedule.bat"
SCA_SCRIPT_DIR="D:\fortify_work\scripts"
SCHTASKS_FOLDER_NAME="Fortify_SCA"
START_TIME=32400  # 3600*9 (09:00부터 시작시간까지 초) = 18:00
END_SEC=46800     # 3600*13 (09:00부터 끝시간까지 초) = 07:00
TMP_DIR1="./fpr_tmp"
TMP_FILE1="tmp_file001.txt"
TMP_FILE2="tmp_file002.txt"

#####################################################################
#
# 사용방법 출력
#
#####################################################################
func_usage() {
  echo "$0 ver.${VERSION}"
  echo
  echo "usage: $0 <wildcard>"
  echo "  example: $0 ./fpr/*.fpr"
}

#####################################################################
#
# 초기화
# $1 : FPR 파일명
#
#####################################################################
func_init() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_init()"
  fi

  if [ -z "${WINDIR}" ]; then
    IS_WINDOWS=0
  else
    IS_WINDOWS=1
  fi

  if [ ${IS_WINDOWS} -eq 1 ]; then
    DEVNULL=null.dev
    WINCMD="/cygdrive/c/Windows/System32/cmd.exe /C"
    PATH=${WIN_MINGW_DIR}/bin:${PATH}
  else
    DEVNULL=/dev/null
    WINCMD=""
    PATH=${PATH}
  fi

  BUILD_ID=$(basename $1 .fpr)
}

#####################################################################
#
# 필요한 유틸리티가 있는지 검사
#
#####################################################################
func_check_utils() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_check_utils()"
  fi

  local IS_EXIT=0;
  UTILNAMES=("grep" "unzip" "ls" "sort" "date")

  # 윈도우 유틸리티 체킹
  if [ ${IS_WINDOWS} -eq 1 ]; then
    if [ ! -x ${WIN_MINGW_DIR}/bin/grep ] || [ ! -x ${WIN_MINGW_DIR}/bin/unzip ] || [ ! -x ${WIN_MINGW_DIR}/bin/ls ] || [ ! -x ${WIN_MINGW_DIR}/bin/sort ] || [ ! -x ${WIN_MINGW_DIR}/bin/date ]; then
      echo "ERROR: ${WIN_MINGW_DIR} not found !"
      IS_EXIT=1
    fi

    if [ ${IS_EXIT} -ne 0 ]; then
      exit 1
    fi
    return

  fi

  # 리눅스 유틸리티 체킹
  for LOOP1 in "${UTILNAMES[@]}"
  do
    which ${LOOP1} > ${DEVNULL}
    if [ $? -ne 0 ]; then
      echo "ERROR: ${LOOP1} not found !"
      IS_EXIT=1
    fi
  done

  # 없는 유틸리티가 있으면 스크립트 종료
  if [ ${IS_EXIT} -ne 0 ]; then
    exit 1
  fi

  unset UTILNAMES
}

#####################################################################
#
# 초를 HH:MM:SS 형태로 계산하여 TIMESTAMP 변수에 대입한다.
# $1 : 초
#
#####################################################################
func_conv_sec2timestamp() {
  SEC_VAL=${1}

  ((h=${SEC_VAL}/3600))
  ((m=(${SEC_VAL}%3600)/60))
  ((s=${SEC_VAL}%60))
  TIMESTAMP=$(printf "%02d:%02d:%02d\n" $h $m $s)
}

#####################################################################
#
# FPR파일 unzip
# $1 : fpr 파일명
#
#####################################################################
func_unzip() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_unzip()"
  fi

  if [ -d ${TMP_DIR1} ]
  then
    rm -rf ${TMP_DIR1}
  fi
  mkdir ${TMP_DIR1}
  unzip $1 -d ${TMP_DIR1} audit.fvdl &> ${DEVNULL}
}

#####################################################################
#
# audit.fvdl에서 scantime을 뽑아낸다.
#
#####################################################################
func_get_scantime() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_get_scantime()"
  fi

  if [ ! -f ${TMP_DIR1}/audit.fvdl ]; then
    echo "ERROR: ${TMP_DIR1}/audit.fvdl not found !"
    func_usage
    exit 2
  fi

  SCANTIME=$(grep -Po '<ScanTime value=\"\K.*?(?=")' ${TMP_DIR1}/audit.fvdl)

  # 빌드 시간을 스캔시간의 1/6로 잡아서 더한다.
  ((ADD_BUILD_SEC=${SCANTIME}/6))
  ((SCANTIME=${SCANTIME}+${ADD_BUILD_SEC}))

  func_conv_sec2timestamp ${SCANTIME}
  echo "${1},${SCANTIME},${TIMESTAMP}" >> ${TMP_FILE1}
}

#####################################################################
#
# 초를 시:분으로 변환
#
#####################################################################
func_sec_to_formatstring() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_sec_to_formatstring()"
  fi

  local NUM=${1}
  local SECVAL=$((START_TIME+NUM))

  if [ ${IS_WINDOWS} -eq 1 ]; then
    DATE_FMT_STR=$(${WIN_MINGW_DIR}/bin/date +'%H:%M' -d @${SECVAL})
  else
    DATE_FMT_STR=$(date +'%H:%M' -d @${SECVAL})
  fi
}

#####################################################################
#
# 숫자를 주 이름으로 대입
#
#####################################################################
func_get_weekname() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_get_weekname()"
  fi

  local WEEKVAL=${1}

  WEEKNAME="SUN"
  if [ ${WEEKVAL} -eq 1 ]; then
    WEEKNAME="MON"
  elif [ ${WEEKVAL} -eq 2 ]; then
    WEEKNAME="TUE"
  elif [ ${WEEKVAL} -eq 3 ]; then
    WEEKNAME="WED"
  elif [ ${WEEKVAL} -eq 4 ]; then
    WEEKNAME="THU"
  elif [ ${WEEKVAL} -eq 5 ]; then
    WEEKNAME="FRI"
  elif [ ${WEEKVAL} -eq 6 ]; then
    WEEKNAME="SAT"
  elif [ ${WEEKVAL} -eq 7 ]; then
    WEEKNAME="SUN"
  fi
}

#####################################################################
#
# SCHTASKS 배치 파일 쓰기
#
#####################################################################
func_write_schtasks_bat() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_write_schtasks_bat() $1 $2 $3 $4"
  fi

  echo -n "SCHTASKS /CREATE /F " >> ${TMP_FILE2}
  echo -n "/TN \"${SCHTASKS_FOLDER_NAME}\\${1}\" " >> ${TMP_FILE2}
  echo -n "/TR \"${2}\" " >> ${TMP_FILE2}
  echo -n "/SC WEEKLY " >> ${TMP_FILE2}

  func_get_weekname ${3}
  echo -n "/D ${WEEKNAME} " >> ${TMP_FILE2}

  func_sec_to_formatstring ${4}
  echo -n "/ST ${DATE_FMT_STR} " >> ${TMP_FILE2}

  echo "/MO 1" >> ${TMP_FILE2}
}

#####################################################################
#
# CSV를 분석해서 SCHTASKS 배치 파일을 만든다
#
#####################################################################
func_parse_csv() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_parse_csv()"
  fi

  local LINE_CNT=0
  local SEC_TOTAL=0
  local WEEK_NO=1

  rm -f ${TMP_FILE2}

  OLDIFS=${IFS}
  IFS=','
  while read FPR SEC TIMESTAMP
  do
    SCH_NAME=$(basename -s .fpr ${FPR})
    SH_FILENAME="${SCA_SCRIPT_DIR}\\$(basename -s .fpr ${FPR}).bat"

    func_write_schtasks_bat ${SCH_NAME} ${SH_FILENAME} ${WEEK_NO} ${SEC_TOTAL}

    SEC_TOTAL=$((SEC_TOTAL+SEC))

    # 시간 체크
    if [ ${SEC_TOTAL} -gt ${END_SEC} ]; then
      SEC_TOTAL=0
      WEEK_NO=$((WEEK_NO+1))
    fi

    # 일요일이 지나면 다시 월요일
    if [ ${WEEK_NO} -gt 7 ]; then
      WEEK_NO=1
    fi

    # 토요일, 일요일은 24시간
    if [ ${WEEK_NO} -eq 6 -o ${WEEK_NO} -eq 7 ]
    then
      START_TIME=0
      END_SEC=86400
    fi

  done < ${CSV_FILENAME}
  IFS=${OLDIFS}
}

#####################################################################
#
# 임시 및 불필요한 파일 삭제
#
#####################################################################
func_clean() {
  if [ ${DEBUG_ON} -eq 1 ]
  then
    echo ">> func_clean()"
  fi

  if [ ${IS_WINDOWS} -eq 1 ]; then
    rm -f ${DEVNULL}
  fi

  rm -f ${TMP_FILE1}
  rm -f ${TMP_FILE2}
  rm -rf ${TMP_DIR1}
  rm -f ${BUILD_ID}.xml
}

#####################################################################
#
# main
#
#####################################################################

# 명령행 인수가 없으면 사용방법 출력하고 끝냄
if [ $# -lt 1 ]; then
  func_usage
  exit 3
fi

if [ -f ${CSV_FILENAME} ]; then
  rm -f ${CSV_FILENAME}
fi

func_init
func_check_utils

#####################################################################
# wildcard에 부합하는 파일들에 대한 처리
#####################################################################
for LOOP1 in $(ls -1 -SS $*)
do
  if [ -f ${LOOP1} ]
    then
      echo ${LOOP1}
      func_unzip ${LOOP1}
      func_get_scantime ${LOOP1}
    else
      break
  fi
done

#####################################################################
# CSV 타이틀 출력
#####################################################################
#echo "Filename,Second,Timestamp(HH:MM:SS)" > ${CSV_FILENAME}

#####################################################################
# 스캔 시간에 따라 역순 Sort
#####################################################################
if [ ${IS_WINDOWS} -eq 1 ]; then
  ${WIN_MINGW_DIR}/bin/sort -t, -r -k3 ${TMP_FILE1} >> ${CSV_FILENAME}
else
  sort -t, -r -k3 ${TMP_FILE1} >> ${CSV_FILENAME}
fi

func_parse_csv

#####################################################################
# 윈도우 배치파일의 개행문자 및 코드셋 변경
#####################################################################
sed -i 's/$/\r/' ${TMP_FILE2}
iconv -f utf8 -t euc-kr ${TMP_FILE2} > ${BAT_FILENAME}

func_clean
위로 스크롤