Setting the file. One moment. Generate Test Traffic · AKS Network Capture · microsoft/azure-skills · Skills Docsscripts/generate-test-traffic.ps1
scripts/generate-test-traffic.ps1
PowerShell·149 lines·5 KB
=
"default"
,
10 [string]$Duration = "30s",
11 [string]$Interval = "1",
12 [switch]$AllowDebugContainer,
13 [switch]$Help
14)
15
16$DebugImage = "mcr.microsoft.com/cbl-mariner/busybox:2.0@sha256:e4fb4d51fc9b70d6cdc1ce66a0af02ab40554d2ca632e1d188fabc760e432fdd"
17
18function Write-Usage {
19 @"
20Usage: generate-test-traffic.ps1 -SourcePod <pod> -Target <host> [options]
21
22Options:
23 -Type <type> http, https, dns, tcp, or ping (default: http)
24 -TargetPort <1-65535> Target port; required for tcp
25 -SourceNamespace <ns> Source namespace (default: default)
26 -Duration <Ns|Nm|Nh> Duration (default: 30s; maximum: 1h)
27 -Interval <seconds> Whole seconds between attempts (default: 1)
28 -AllowDebugContainer Use an ephemeral debug container after separate approval
29"@
30}
31
32function Stop-Usage {
33 param([string]$Message)
34 [Console]::Error.WriteLine("Error: $Message")
35 [Console]::Error.WriteLine((Write-Usage))
36 exit 2
37}
38
39function Stop-Failure {
40 param([string]$Message)
41 [Console]::Error.WriteLine("Error: $Message")
42 exit 1
43}
44
45function Test-DnsSubdomain {
46 param([string]$Value)
47 return $Value.Length -le 253 -and
48 $Value -cmatch "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"
49}
50
51if ($Help) {
52 Write-Usage
53 exit 0
54}
55if ([string]::IsNullOrWhiteSpace($SourcePod)) {
56 Stop-Usage "-SourcePod is required"
57}
58if ([string]::IsNullOrWhiteSpace($Target)) {
59 Stop-Usage "-Target is required"
60}
61if (-not (Test-DnsSubdomain $SourcePod)) {
62 Stop-Usage "-SourcePod must be a DNS subdomain"
63}
64if (-not (Test-DnsSubdomain $SourceNamespace)) {
65 Stop-Usage "-SourceNamespace must be a DNS subdomain"
66}
67if ($Target.Length -gt 253 -or $Target -notmatch "^[A-Za-z0-9._:-]+$") {
68 Stop-Usage "-Target has invalid characters"
69}
70if ($Duration -cnotmatch "^([0-9]+)([smh])$") {
71 Stop-Usage "-Duration must look like 30s, 5m, or 1h"
72}
73$durationNumber = [int64]$Matches[1]
74$durationSeconds = switch ($Matches[2]) {
75 "s" { $durationNumber }
76 "m" { $durationNumber * 60 }
77 "h" { $durationNumber * 3600 }
78}
79if ($durationSeconds -lt 1 -or $durationSeconds -gt 3600) {
80 Stop-Usage "-Duration must be between 1s and 1h"
81}
82if ($Interval -notmatch "^[0-9]+$") {
83 Stop-Usage "-Interval must be a non-negative integer"
84}
85
86switch -CaseSensitive ($Type) {
87 "dns" { if (-not $TargetPort) { $TargetPort = "53" } }
88 "https" { if (-not $TargetPort) { $TargetPort = "443" } }
89 "http" { if (-not $TargetPort) { $TargetPort = "80" } }
90 "tcp" { if (-not $TargetPort) { Stop-Usage "-TargetPort is required for tcp" } }
91 "ping" { $TargetPort = "0" }
92 default { Stop-Usage "-Type must be one of: http https dns tcp ping" }
93}
94if ($TargetPort -notmatch "^[0-9]+$") {
95 Stop-Usage "-TargetPort must be an integer"
96}
97$targetPortValue = [int64]$TargetPort
98if ($Type -ne "ping" -and ($targetPortValue -lt 1 -or $targetPortValue -gt 65535)) {
99 Stop-Usage "-TargetPort must be between 1 and 65535"
100}
101if (-not (Get-Command kubectl -ErrorAction SilentlyContinue)) {
102 Stop-Failure "kubectl is not installed or not on PATH"
103}
104
105$PodScript = @'
106set -u
107target="$1"; port="$2"; duration="$3"; interval="$4"; traffic_type="$5"
108case "$target" in *:*) url_host="[$target]";; *) url_host="$target";; esac
109end=$(( $(date +%s) + duration ))
110while [ "$(date +%s)" -lt "$end" ]; do
111 case "$traffic_type" in
112 http) wget -q -O /dev/null -T 5 "http://$url_host:$port/" && echo "http ok" || echo "http fail" ;;
113 https) wget -q -O /dev/null -T 5 --no-check-certificate "https://$url_host:$port/" && echo "https ok" || echo "https fail" ;;
114 dns) nslookup "$target" >/dev/null 2>&1 && echo "dns ok" || echo "dns fail" ;;
115 tcp) nc -z -w 5 "$target" "$port" && echo "tcp ok" || echo "tcp fail" ;;
116 ping) ping -c 1 -W 5 "$target" >/dev/null 2>&1 && echo "ping ok" || echo "ping fail" ;;
117 esac
118 [ "$interval" -eq 0 ] || sleep "$interval"
119done
120'@
121
122Write-Output "Generating $Type traffic from $SourcePod to $Target for ${durationSeconds}s"
123& kubectl exec -n $SourceNamespace $SourcePod -- sh -c "exit 0" 2>$null
124$directExecAvailable = $LASTEXITCODE -eq 0
125
126if ($directExecAvailable) {
127 & kubectl exec -n $SourceNamespace $SourcePod -- sh -c $PodScript _ `
128 $Target $targetPortValue $durationSeconds $Interval $Type
129 if ($LASTEXITCODE -ne 0) {
130 Stop-Failure "traffic generation failed in the source pod"
131 }
132} else {
133 if (-not $AllowDebugContainer) {
134 Stop-Failure "direct pod exec is unavailable; obtain separate approval before retrying with -AllowDebugContainer"
135 }
136 $targetContainer = (& kubectl get pod -n $SourceNamespace $SourcePod `
137 -o 'jsonpath={.spec.containers[0].name}' 2>&1) -join "`n"
138 if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($targetContainer)) {
139 Stop-Failure "could not resolve the source pod container: $targetContainer"
140 }
141 & kubectl debug -n $SourceNamespace $SourcePod --image=$DebugImage `
142 --target=$($targetContainer.Trim()) -q -- sh -c $PodScript _ `
143 $Target $targetPortValue $durationSeconds $Interval $Type
144 if ($LASTEXITCODE -ne 0) {
145 Stop-Failure "traffic generation failed in the ephemeral debug container"
146 }
147}
148
149Write-Output "Traffic generation complete"