Retrieve valid tags beforehand
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
|
||||
# Function to print usage information
|
||||
usage() {
|
||||
echo "Usage: $0 <image> <start_tag> <end_tag>"
|
||||
echo "Example: $0 tabledevil/sep 230101 230916"
|
||||
echo "Usage: $0 <image> <start_tag> <end_tag> <username> <token>"
|
||||
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}")
|
||||
# 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
|
||||
current_date=$(date -d "$current_date + 1 day" +%Y%m%d)
|
||||
done
|
||||
tags+=("${end_date:2}") # Include the end date as well
|
||||
echo "${tags[@]}"
|
||||
}
|
||||
|
||||
# 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]}
|
||||
|
||||
# Run the Docker command with the current 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
|
||||
else
|
||||
# Virus not found, search in the upper half
|
||||
low=$((mid + 1))
|
||||
NEXT=$(echo $RESPONSE | jq -r '.next')
|
||||
if [ "$NEXT" == "null" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
PAGE=$((PAGE + 1))
|
||||
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
|
||||
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 echo "$result" | grep -q "$PATTERN"; then
|
||||
echo "Pattern found"
|
||||
return 0
|
||||
else
|
||||
echo "Pattern NOT found"
|
||||
return 1
|
||||
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[@]}"
|
||||
|
||||
Reference in New Issue
Block a user