diff --git a/tools/sep_test.sh b/tools/sep_test.sh index 495cc30..aedf117 100644 --- a/tools/sep_test.sh +++ b/tools/sep_test.sh @@ -2,13 +2,13 @@ # Function to print usage information usage() { - echo "Usage: $0 " - echo "Example: $0 tabledevil/sep 230101 230916" + echo "Usage: $0 " + echo "Example: $0 tabledevil/sep 230101 230916 username dckr_pat_8FEgaA5ovvL1V-UEWfV5T3jVABC" exit 1 } -# Check if correct number of arguments is provided -if [ "$#" -ne 3 ]; then +# Check if the correct number of arguments is provided +if [ "$#" -ne 5 ]; then usage fi @@ -16,6 +16,10 @@ fi image="$1" start_tag="$2" end_tag="$3" +DOCKER_USERNAME="$4" +DOCKER_PAT="$5" +REPOSITORY=$(echo "$image" | cut -d'/' -f2) +PATTERN="Threat Found!" # Validate that start_tag and end_tag are in the correct format if ! [[ "$start_tag" =~ ^[0-9]{6}$ ]] || ! [[ "$end_tag" =~ ^[0-9]{6}$ ]]; then @@ -23,50 +27,117 @@ if ! [[ "$start_tag" =~ ^[0-9]{6}$ ]] || ! [[ "$end_tag" =~ ^[0-9]{6}$ ]]; then usage fi -# Function to generate all possible tags between two dates -generate_tags() { - local start_date=$(date -d "20$1" +%Y%m%d) - local end_date=$(date -d "20$2" +%Y%m%d) - local current_date="$start_date" - local tags=() - - while [[ "$current_date" != "$end_date" ]]; do - if docker manifest inspect "${image}:${current_date:2}" > /dev/null 2>&1; then - tags+=("${current_date:2}") - fi - current_date=$(date -d "$current_date + 1 day" +%Y%m%d) - done - tags+=("${end_date:2}") # Include the end date as well - echo "${tags[@]}" +# Function to get Docker Hub token using PAT +get_token() { + TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${DOCKER_USERNAME}'", "password": "'${DOCKER_PAT}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) + if [ "$TOKEN" == "null" ]; then + echo "Failed to get token. Please check your credentials." + exit 1 + fi } -# Generate tags -tags=($(generate_tags "$start_tag" "$end_tag")) +# Function to get tags for a repository +get_tags() { + PAGE=1 + PAGE_SIZE=100 + TAGS=() -# Binary search setup -low=0 -high=${#tags[@]} + while true; do + RESPONSE=$(curl -s -H "Authorization: JWT ${TOKEN}" "https://hub.docker.com/v2/repositories/${DOCKER_USERNAME}/${REPOSITORY}/tags/?page_size=${PAGE_SIZE}&page=${PAGE}") + TAGS_PAGE=$(echo $RESPONSE | jq -r '.results[].name') + TAGS+=($TAGS_PAGE) -# Binary search to find the first tag detecting the virus -while [ $low -lt $high ]; do - mid=$(((low + high) / 2)) - tag=${tags[$mid]} + NEXT=$(echo $RESPONSE | jq -r '.next') + if [ "$NEXT" == "null" ]; then + break + fi + PAGE=$((PAGE + 1)) + done - # Run the Docker command with the current tag + echo "${TAGS[@]}" +} + +# Function to filter tags based on date range +filter_tags_by_date() { + local tags=("$@") + local filtered=() + local start="$start_tag" + local end="$end_tag" + + for tag in "${tags[@]}"; do + if [[ "$tag" =~ ^[0-9]{6}$ ]]; then + if [[ "$tag" -ge "$start" && "$tag" -le "$end" ]]; then + filtered+=("$tag") + fi + fi + done + + echo "${filtered[@]}" +} + +# Function to check for malware in the given Docker tag +check_malware() { + local tag=$1 + echo -n "Checking $image:$tag " result=$(docker run -it --rm -v "$(pwd):/data:ro" --network=none "$image:$tag" scan) - - if [[ $result == *"Threat Found!"* ]]; then - # Virus found, search in the lower half - high=$mid + if echo "$result" | grep -q "$PATTERN"; then + echo "Pattern found" + return 0 else - # Virus not found, search in the upper half - low=$((mid + 1)) + echo "Pattern NOT found" + return 1 fi -done +} -# Output the tag of the first image that finds the malware -if [ $high -lt ${#tags[@]} ]; then - echo "The first tag that detected the malware is: ${tags[$high]}" -else - echo "No malware detected within the tag range." -fi +# Function to run the binary search +binary_search() { + local tags=("$@") + local low=0 + local high=$(( ${#tags[@]} - 1 )) + local mid + + # Determine the initial states for low and high + check_malware "${tags[$low]}" + local low_result=$? + + check_malware "${tags[$high]}" + local high_result=$? + + # If the results for low and high are the same, there is no switch point in the range + if [ $low_result -eq $high_result ]; then + echo "No change in detection within the tag range." + return + fi + + # Binary search to find the exact switching point + while [ $((low + 1)) -lt $high ]; do + mid=$(((low + high) / 2)) + check_malware "${tags[$mid]}" + local mid_result=$? + + if [ $mid_result -eq $low_result ]; then + low=$mid + else + high=$mid + fi + done + + # Output the tag of the first image that finds the malware switch + echo "The detection changes between tags: ${tags[$low]} - ${tags[$high]}" +} + + +# Main script execution +get_token + +# Retrieve all tags from Docker Hub +echo "Retrieving all tags for $image from Docker Hub..." +all_tags=($(get_tags)) + +# Filter tags to include only those within the date range +echo "Filtering tags from $start_tag to $end_tag..." +filtered_tags=($(filter_tags_by_date "${all_tags[@]}")) + +# Run the binary search on the filtered tags +echo "Running binary search on the filtered tags..." +binary_search "${filtered_tags[@]}"