Skip to content

Commit 95801ff

Browse files
committed
rework/improve check_cloud and add Azure detection
1 parent b812618 commit 95801ff

1 file changed

Lines changed: 142 additions & 39 deletions

File tree

src/splunkconf-cloud-recovery.sh

Lines changed: 142 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,9 @@ exec >> /var/log/splunkconf-cloud-recovery-debug.log 2>&1
283283
# 20260210 force permission removal for etc auth so custom certs dont have group and other permission as this is both good security practise and required for postgres sidecar
284284
# 20260302 up to 10.2.1
285285
# 20260409 up to 10.2.2
286+
# 20260419 rework/improve check_cloud and add Azure detection
286287

287-
VERSION="20260409a"
288+
VERSION="20260419a"
288289

289290
# dont break script on error as we rely on tests for this
290291
set +e
@@ -293,49 +294,142 @@ TODAY=`date '+%Y%m%d-%H%M_%u'`;
293294
TIMESTAMP=$(date +%s)
294295
echo "${TODAY} running splunkconf-cloud-recovery.sh with ${VERSION} versioni (TIMESTAMP=$TIMESTAMP)" >> /var/log/splunkconf-cloud-recovery-info.log
295296

296-
METADATA_URL="http://metadata.google.internal/computeMetadata/v1"
297+
# This function tries to autodetect when running in a cloud environment.
298+
# Sets global variable cloud_type:
299+
# 0 = unknown / on-prem
300+
# 1 = AWS
301+
# 2 = GCP
302+
# 3 = Azure
303+
# Returns 0 on success (detection ran), 1 on unexpected error.
304+
297305
function check_cloud() {
298-
cloud_type=0
299-
response=$(curl -fs -m 5 -H "Metadata-Flavor: Google" ${METADATA_URL})
300-
if [ $? -eq 0 ]; then
301-
echo 'GCP instance detected'
302-
cloud_type=2
303-
# old aws hypervisor
304-
elif [ -f /sys/hypervisor/uuid ]; then
305-
if [ `head -c 3 /sys/hypervisor/uuid` == "ec2" ]; then
306-
echo 'AWS instance detected'
307-
cloud_type=1
306+
cloud_type=0
307+
308+
# ------------------------------------------------------------------
309+
# Preflight: check required dependencies
310+
# ------------------------------------------------------------------
311+
local missing_deps=()
312+
313+
if ! command -v curl &>/dev/null; then
314+
missing_deps+=("curl")
308315
fi
309-
fi
310-
# newer aws hypervisor (test require root)
311-
if [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
312-
if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "EC2" ]; then
313-
echo 'AWS instance detected'
314-
cloud_type=1
316+
317+
if [ ${#missing_deps[@]} -gt 0 ]; then
318+
echo "WARNING: check_cloud requires missing commands: ${missing_deps[*]}" >&2
319+
echo "WARNING: Install missing dependencies for reliable cloud detection." >&2
320+
echo "WARNING: Falling back to filesystem-only checks." >&2
315321
fi
316-
if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "ec2" ]; then
317-
echo 'AWS instance detected'
318-
cloud_type=1
322+
323+
# ------------------------------------------------------------------
324+
# Condition 1: GCP — via metadata server
325+
# ------------------------------------------------------------------
326+
if command -v curl &>/dev/null; then
327+
local gcp_response
328+
gcp_response=$(curl -fs --max-time 3 \
329+
-H "Metadata-Flavor: Google" \
330+
"http://metadata.google.internal/computeMetadata/v1/instance/zone" \
331+
2>/dev/null)
332+
333+
if [ $? -eq 0 ] && [ -n "$gcp_response" ]; then
334+
echo "GCP instance detected via condition 1"
335+
cloud_type=2
336+
return 0
337+
fi
338+
else
339+
echo "WARNING: Skipping GCP IMDS check (curl missing)" >&2
319340
fi
320-
fi
321-
# if detection not yet successfull, try fallback method
322-
if [[ $cloud_type -eq "0" ]]; then
323-
# Fallback check of http://169.254.169.254/. If we wanted to be REALLY
324-
# authoritative, we could follow Amazon's suggestions for cryptographically
325-
# verifying their signature, see here:
326-
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
327-
# but this is almost certainly overkill for this purpose (and the above
328-
# checks of "EC2" prefixes have a higher false positive potential, anyway).
329-
# imdsv2 support : TOKEN should exist if inside AWS even if not enforced
330-
TOKEN=`curl --silent --show-error -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 3600"`
331-
if [ -z ${TOKEN+x} ]; then
332-
# TOKEN NOT SET , NOT inside AWS
333-
cloud_type=0
334-
elif $(curl --silent -m 5 -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document | grep -q availabilityZone) ; then
335-
echo 'AWS instance detected'
336-
cloud_type=1
341+
342+
# ------------------------------------------------------------------
343+
# Condition 2: AWS — old hypervisor UUID (no curl needed)
344+
# ------------------------------------------------------------------
345+
if [ -f /sys/hypervisor/uuid ]; then
346+
local uuid_prefix
347+
uuid_prefix=$(head -c 3 /sys/hypervisor/uuid 2>/dev/null)
348+
if [[ "${uuid_prefix,,}" == "ec2" ]]; then
349+
echo "AWS instance detected via condition 2 (hypervisor uuid)"
350+
cloud_type=1
351+
return 0
352+
fi
337353
fi
338-
fi
354+
355+
# ------------------------------------------------------------------
356+
# Condition 3: AWS — newer hypervisor DMI product_uuid (no curl needed)
357+
# ------------------------------------------------------------------
358+
if [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
359+
local product_uuid_prefix
360+
product_uuid_prefix=$(head -c 3 \
361+
/sys/devices/virtual/dmi/id/product_uuid 2>/dev/null)
362+
if [[ "${product_uuid_prefix,,}" == "ec2" ]]; then
363+
echo "AWS instance detected via condition 3 (DMI product_uuid)"
364+
cloud_type=1
365+
return 0
366+
fi
367+
fi
368+
369+
# ------------------------------------------------------------------
370+
# Condition 4: AWS — IMDSv2 (requires curl)
371+
# ------------------------------------------------------------------
372+
if command -v curl &>/dev/null; then
373+
local token
374+
token=$(curl --silent --max-time 3 \
375+
-X PUT "http://169.254.169.254/latest/api/token" \
376+
-H "X-aws-ec2-metadata-token-ttl-seconds: 3600" \
377+
2>/dev/null)
378+
379+
if [ -n "$token" ]; then
380+
local az_check
381+
az_check=$(curl --silent --max-time 3 \
382+
-H "X-aws-ec2-metadata-token: $token" \
383+
"http://169.254.169.254/latest/dynamic/instance-identity/document" \
384+
2>/dev/null)
385+
386+
if echo "$az_check" | grep -q "availabilityZone"; then
387+
echo "AWS instance detected via condition 4 (IMDSv2)"
388+
cloud_type=1
389+
return 0
390+
fi
391+
fi
392+
else
393+
echo "WARNING: Skipping AWS IMDSv2 check (curl missing)" >&2
394+
fi
395+
396+
# ------------------------------------------------------------------
397+
# Condition 5: Azure — DMI sys_vendor (no curl needed)
398+
# ------------------------------------------------------------------
399+
local dmi_file="/sys/class/dmi/id/sys_vendor"
400+
if [ -f "$dmi_file" ]; then
401+
if grep -qi "microsoft" "$dmi_file" 2>/dev/null; then
402+
echo "Azure instance detected via condition 5 (DMI sys_vendor)"
403+
cloud_type=3
404+
return 0
405+
fi
406+
fi
407+
408+
# ------------------------------------------------------------------
409+
# Condition 6: Azure — IMDS endpoint (requires curl)
410+
# ------------------------------------------------------------------
411+
if command -v curl &>/dev/null; then
412+
local azure_response
413+
azure_response=$(curl -s -f --max-time 3 \
414+
-H "Metadata: true" \
415+
"http://169.254.169.254/metadata/instance?api-version=2021-02-01" \
416+
2>/dev/null)
417+
418+
if echo "$azure_response" | grep -q "azEnvironment"; then
419+
echo "Azure instance detected via condition 6 (IMDS)"
420+
cloud_type=3
421+
return 0
422+
fi
423+
else
424+
echo "WARNING: Skipping Azure IMDS check (curl missing)" >&2
425+
fi
426+
427+
# ------------------------------------------------------------------
428+
# No cloud detected
429+
# ------------------------------------------------------------------
430+
echo "No cloud environment detected — assuming on-premises"
431+
cloud_type=0
432+
return 0
339433
}
340434

341435
# we will use SYSVER to store version type (used for packagesystem and hostname setting for example)
@@ -955,6 +1049,15 @@ ARG1=$1
9551049

9561050

9571051
check_cloud
1052+
echo "Cloud type: $cloud_type"
1053+
1054+
case "$cloud_type" in
1055+
0) echo "Environment: On-premises or unknown" ;;
1056+
1) echo "Environment: AWS" ;;
1057+
2) echo "Environment: GCP" ;;
1058+
3) echo "Environment: Azure" ;;
1059+
esac
1060+
9581061
check_sysver
9591062
cgroup_status
9601063

0 commit comments

Comments
 (0)