Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea/
379 changes: 379 additions & 0 deletions scripts/copy-azure-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,379 @@
#!/bin/bash
#
# Azure Blob Copy and Image Creation Script
#
# This script copies a blob from a source Azure storage account (using SAS URL)
# to a destination storage account, with automatic resource creation if needed.
# After copying, it automatically creates a managed image from the VHD blob.
#
# Quick usage - curl and run directly from GitHub gist:
# curl -s https://raw.githubusercontent.com/corelight/corelight-cloud/refs/heads/main/scripts/copy-azure-image.sh | bash -s -- --source-sas "https://sourceaccount.blob.core.windows.net/container/file.vhd?sp=r&st=..."
#
# Or download and run locally:
# curl -O https://raw.githubusercontent.com/corelight/corelight-cloud/refs/heads/main/scripts/copy-azure-image.sh
# chmod +x copy-azure-image.sh
# ./copy-azure-image.sh --source-sas "https://sourceaccount.blob.core.windows.net/container/file.vhd?sp=r&st=..."
#

set -e

usage() {
cat << EOF
Usage: $0 [OPTIONS]

Copy a blob from source to destination Azure storage account using azcopy and create a managed image.
The blob name will be automatically extracted from the source SAS URL.

OPTIONS:
--source-sas Source blob SAS URL (required)
--dest-account-name Destination storage account name (optional - will auto-create if not provided)
--dest-container-name Destination container name (optional - will auto-create if not provided)
--dest-resource-group Destination resource group name (required when using existing resources)
--dest-location Azure location for auto-created resources (default: East US)
-h, --help Show this help message

EXAMPLE:
$0 --source-sas "https://sourceaccount.blob.core.windows.net/container/example-file.vhd?sp=r&st=..." --dest-account-name "myaccount"
$0 --source-sas "https://sourceaccount.blob.core.windows.net/container/example-file.vhd?sp=r&st=..." --dest-resource-group "my-rg"
$0 --source-sas "https://sourceaccount.blob.core.windows.net/container/example-file.vhd?sp=r&st=..." # Will auto-create all resources
EOF
}

# Set defaults
SOURCE_SAS=""

# Destination parameters - now optional
DESTINATION_ACCOUNT_NAME=""
DESTINATION_CONTAINER_NAME=""
DESTINATION_RESOURCE_GROUP=""
DESTINATION_LOCATION="East US"


# Blob name will be extracted from SAS URL
BLOB_NAME=""

# Helper functions
create_random_id() {
echo "$RANDOM" | base64 | head -c 6 | tr '[:upper:]' '[:lower:]'
}

# Function to extract blob name from SAS URL
extract_blob_name_from_sas() {
local sas_url="$1"

# Remove query parameters (everything after ?)
local url_without_params="${sas_url%%\?*}"

# Extract the blob name (everything after the last /)
local blob_name="${url_without_params##*/}"

echo "$blob_name"
}

# Check if any arguments were provided
if [[ $# -eq 0 ]]; then
usage
exit 0
fi

# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--source-sas)
SOURCE_SAS="$2"
shift 2
;;
--dest-account-name)
DESTINATION_ACCOUNT_NAME="$2"
shift 2
;;
--dest-container-name)
DESTINATION_CONTAINER_NAME="$2"
shift 2
;;
--dest-resource-group)
DESTINATION_RESOURCE_GROUP="$2"
shift 2
;;
--dest-location)
DESTINATION_LOCATION="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1"
usage
exit 1
;;
esac
done

# Validate required parameters
if [[ -z "$SOURCE_SAS" ]]; then
echo "Error: --source-sas is required"
echo ""
usage
exit 1
fi

# Extract blob name from source SAS URL
BLOB_NAME=$(extract_blob_name_from_sas "$SOURCE_SAS")

if [[ -z "$BLOB_NAME" ]]; then
echo "Error: Could not extract blob name from source SAS URL"
echo "Please ensure the SAS URL is in the correct format: https://account.blob.core.windows.net/container/blobname?..."
echo ""
usage
exit 1
fi

echo "Extracted blob name: $BLOB_NAME"

# Validate blob type for image creation
if [[ ! "$BLOB_NAME" =~ \.vhd$ ]]; then
echo "Warning: The blob '$BLOB_NAME' does not appear to be a VHD file."
echo "Managed images are typically created from VHD files. Proceeding anyway..."
fi

# Check if destination parameters are provided
if [[ -z "$DESTINATION_ACCOUNT_NAME" || -z "$DESTINATION_CONTAINER_NAME" ]]; then
echo "Destination account/container not provided. Will auto-create resources..."
AUTO_CREATE_RESOURCES=true
else
AUTO_CREATE_RESOURCES=false
fi

# Function to get expiry date 24 hours from now in Azure SAS format
get_sas_expiry() {
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
date -v+1d -u +"%Y-%m-%dT%H:%M:%SZ"
else
# Linux
date -d "+1 day" -u +"%Y-%m-%dT%H:%M:%SZ"
fi
}

# Function to create resource group if it doesn't exist
create_resource_group() {
local rg_name="$1"
local location="$2"

echo "Checking if resource group '$rg_name' exists..."
if ! az group show --name "$rg_name" &>/dev/null; then
echo "Creating resource group '$rg_name' in location '$location'..."
az group create --name "$rg_name" --location "$location"
else
echo "Resource group '$rg_name' already exists."
fi
}

# Function to create storage account
create_storage_account() {
local account_name="$1"
local rg_name="$2"
local location="$3"

echo "Creating storage account '$account_name'..."
az storage account create \
--name "$account_name" \
--resource-group "$rg_name" \
--location "$location" \
--sku Standard_LRS \
--kind StorageV2
}

# Function to create container
create_container() {
local account_name="$1"
local container_name="$2"

echo "Creating container '$container_name' in storage account '$account_name'..."
az storage container create \
--name "$container_name" \
--account-name "$account_name"
}

# Function to generate unique resource group name
generate_resource_group_name() {
local prefix="corelightimages"
echo "corelightimages-$(create_random_id)"
}

# Function to generate unique storage account name
generate_storage_account_name() {
local prefix="corelightimages"
echo "corelightimages$(create_random_id)"
}

# Function to generate SAS URL and remove quotes
generate_sas_url() {
local account_name="$1"
local container_name="$2"
local blob_name="$3"
local expiry="$4"

local sas_url=$(az storage blob generate-sas \
--account-name "$account_name" \
--container-name "$container_name" \
--name "$blob_name" \
--expiry "$expiry" \
--permissions acdrw \
--full-uri)

# Remove surrounding quotes
echo "${sas_url//\"/}"
}

# Function to check if managed image already exists
check_image_exists() {
local image_name="$1"
local resource_group="$2"

echo "Checking if managed image '$image_name' exists in resource group '$resource_group'..."
if az image show --name "$image_name" --resource-group "$resource_group" &>/dev/null; then
echo "Managed image '$image_name' already exists."
return 0
else
echo "Managed image '$image_name' does not exist."
return 1
fi
}

# Function to create managed image from VHD blob
create_managed_image() {
local image_name="$1"
local resource_group="$2"
local location="$3"
local storage_account="$4"
local container_name="$5"
local blob_name="$6"

# Construct the VHD blob URI
local vhd_uri="https://${storage_account}.blob.core.windows.net/${container_name}/${blob_name}"

echo "Creating managed image '$image_name' from VHD blob..."
echo "VHD URI: $vhd_uri"

az image create \
--name "$image_name" \
--resource-group "$resource_group" \
--location "$location" \
--source "$vhd_uri" \
--os-type Linux

if [[ $? -eq 0 ]]; then
echo "Successfully created managed image '$image_name'."
else
echo "Failed to create managed image '$image_name'."
return 1
fi
}

# Function to generate image name from blob name
generate_image_name() {
local blob_name="$1"
# Remove .vhd extension
local base_name="${blob_name%.vhd}"
echo "$base_name"
}

# Auto-create resources if needed
# When AUTO_CREATE_RESOURCES=true, this creates:
# - Resource Group (if not provided)
# - Storage Account (if not provided)
# - Storage Container (if not provided)
if [[ "$AUTO_CREATE_RESOURCES" == "true" ]]; then
echo "Auto-creating destination resources..."

# Generate resource group name if not provided
if [[ -z "$DESTINATION_RESOURCE_GROUP" ]]; then
DESTINATION_RESOURCE_GROUP=$(generate_resource_group_name)
echo "Generated resource group name: $DESTINATION_RESOURCE_GROUP"
fi

# Create resource group
create_resource_group "$DESTINATION_RESOURCE_GROUP" "$DESTINATION_LOCATION"

# Generate unique storage account name if not provided
if [[ -z "$DESTINATION_ACCOUNT_NAME" ]]; then
DESTINATION_ACCOUNT_NAME=$(generate_storage_account_name)
echo "Generated storage account name: $DESTINATION_ACCOUNT_NAME"
fi

# Set default container name if not provided
if [[ -z "$DESTINATION_CONTAINER_NAME" ]]; then
DESTINATION_CONTAINER_NAME="corelightsensor"
echo "Using default container name: $DESTINATION_CONTAINER_NAME"
fi

# Create storage account
create_storage_account "$DESTINATION_ACCOUNT_NAME" "$DESTINATION_RESOURCE_GROUP" "$DESTINATION_LOCATION"

# Wait a bit for storage account to be fully provisioned
echo "Waiting for storage account to be ready..."
sleep 10

# Create container
create_container "$DESTINATION_ACCOUNT_NAME" "$DESTINATION_CONTAINER_NAME"
else
# When using existing resources, ensure resource group is set
if [[ -z "$DESTINATION_RESOURCE_GROUP" ]]; then
echo "Error: When using existing resources, --dest-resource-group must be provided for image creation"
exit 1
fi

echo "Using existing resources:"
echo " Resource Group: $DESTINATION_RESOURCE_GROUP"
echo " Storage Account: $DESTINATION_ACCOUNT_NAME"
echo " Container: $DESTINATION_CONTAINER_NAME"
fi

EXPIRY_DATE=$(get_sas_expiry)

echo "Generating destination SAS URL..."
DESTINATION_SAS=$(generate_sas_url "$DESTINATION_ACCOUNT_NAME" "$DESTINATION_CONTAINER_NAME" "$BLOB_NAME" "$EXPIRY_DATE")

echo "Copying blob from source to destination..."
echo "Source SAS: $SOURCE_SAS"
echo "Destination: $DESTINATION_ACCOUNT_NAME/$DESTINATION_CONTAINER_NAME/$BLOB_NAME"

azcopy cp "$SOURCE_SAS" "$DESTINATION_SAS"

echo "Copy completed successfully!"
if [[ "$AUTO_CREATE_RESOURCES" == "true" ]]; then
echo "Created resources:"
echo " Resource Group: $DESTINATION_RESOURCE_GROUP"
echo " Storage Account: $DESTINATION_ACCOUNT_NAME"
echo " Container: $DESTINATION_CONTAINER_NAME"
fi

# Create managed image
echo ""
echo "Processing managed image creation..."

# Generate image name from blob name (without .vhd extension)
IMAGE_NAME=$(generate_image_name "$BLOB_NAME")
echo "Using image name: $IMAGE_NAME"

# Check if image already exists
if check_image_exists "$IMAGE_NAME" "$DESTINATION_RESOURCE_GROUP"; then
echo "Managed image '$IMAGE_NAME' already exists. Skipping image creation."
else
# Create the managed image
echo "Creating managed image from VHD blob..."
if create_managed_image "$IMAGE_NAME" "$DESTINATION_RESOURCE_GROUP" "$DESTINATION_LOCATION" "$DESTINATION_ACCOUNT_NAME" "$DESTINATION_CONTAINER_NAME" "$BLOB_NAME"; then
echo "Managed image creation completed successfully!"
echo " Image Name: $IMAGE_NAME"
echo " Resource Group: $DESTINATION_RESOURCE_GROUP"
echo " Location: $DESTINATION_LOCATION"
else
echo "Failed to create managed image. Please check Azure CLI output for details."
exit 1
fi
fi