Skip to content

Commit e2b4910

Browse files
dholtclaude
andcommitted
fix: address Copilot review feedback on MAAS deploy and inventory
- Move API key validation from maas_auth_header() to load_config() so exit works properly (exit in command substitution only kills subshell) - Accept MAAS_SSH_BASTION env var (consistent with inventory script) and convert to ProxyCommand; MAAS_SSH_PROXY still works as direct override - Quote ssh_bastion value in proxy command to handle spaces/special chars - Use os.environ instead of shell interpolation for network_filter in get_ip() to prevent potential code injection - Deduplicate hosts in inventory when machine has both old and aliased tags (e.g., both kube-master and kube_control_plane) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Douglas Holt <dholt@nvidia.com>
1 parent 97051de commit e2b4910

2 files changed

Lines changed: 26 additions & 7 deletions

File tree

scripts/maas_deploy.sh

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
# Configuration:
1616
# Reads config/maas-inventory.yml (same config as maas_inventory.py).
1717
# Environment variables override config file values:
18-
# MAAS_API_URL, MAAS_API_KEY, MAAS_MACHINES, MAAS_SSH_USER, MAAS_SSH_PROXY
18+
# MAAS_API_URL, MAAS_API_KEY, MAAS_MACHINES, MAAS_SSH_USER,
19+
# MAAS_SSH_BASTION (or MAAS_SSH_PROXY for full ProxyCommand override)
1920
#
2021
# Examples:
2122
# ./scripts/maas_deploy.sh --os noble --profile k8s
@@ -69,13 +70,18 @@ load_config() {
6970
api_url) [[ -z "${MAAS_API_URL:-}" ]] && MAAS_API_URL="$value" ;;
7071
api_key) [[ -z "${MAAS_API_KEY:-}" ]] && MAAS_API_KEY="$value" ;;
7172
ssh_user) [[ -z "${MAAS_SSH_USER:-}" ]] && MAAS_SSH_USER="$value" ;;
72-
ssh_bastion) [[ -z "${MAAS_SSH_PROXY:-}" ]] && MAAS_SSH_PROXY="ssh -W %h:%p -q ${value}" ;;
73+
ssh_bastion) [[ -z "${MAAS_SSH_PROXY:-}" && -z "${MAAS_SSH_BASTION:-}" ]] && MAAS_SSH_BASTION="$value" ;;
7374
network) [[ -z "${MAAS_NETWORK:-}" ]] && MAAS_NETWORK="$value" ;;
7475
machines) [[ -z "${MAAS_MACHINES:-}" ]] && MAAS_MACHINES="$value" ;;
7576
esac
7677
done < "$config_file"
7778
fi
7879

80+
# Build SSH proxy from MAAS_SSH_BASTION if MAAS_SSH_PROXY not set directly
81+
if [[ -z "${MAAS_SSH_PROXY:-}" && -n "${MAAS_SSH_BASTION:-}" ]]; then
82+
MAAS_SSH_PROXY="ssh -W %h:%p -q ${MAAS_SSH_BASTION}"
83+
fi
84+
7985
# Defaults for anything still unset
8086
MAAS_API_URL="${MAAS_API_URL:-}"
8187
MAAS_API_KEY="${MAAS_API_KEY:-}"
@@ -95,6 +101,12 @@ load_config() {
95101
echo "Set it in config/maas-inventory.yml or as an environment variable"
96102
exit 1
97103
fi
104+
105+
# Validate API key format: exactly 3 non-empty colon-separated parts
106+
if [[ ! "$MAAS_API_KEY" =~ ^[^:]+:[^:]+:[^:]+$ ]]; then
107+
echo "ERROR: MAAS_API_KEY must be in format consumer_key:token_key:token_secret"
108+
exit 1
109+
fi
98110
}
99111

100112
# --- Argument Parsing ---------------------------------------------------------
@@ -149,6 +161,7 @@ parse_args() {
149161
# --- MAAS API Helpers ---------------------------------------------------------
150162

151163
maas_auth_header() {
164+
# API key format already validated in load_config()
152165
local consumer_key token_key token_secret
153166
IFS=':' read -r consumer_key token_key token_secret <<< "$MAAS_API_KEY"
154167
local nonce timestamp
@@ -191,11 +204,10 @@ print(m['status'])
191204

192205
get_ip() {
193206
local system_id="$1"
194-
local network_filter="${MAAS_NETWORK:-}"
195-
maas_get "/machines/${system_id}/" | python3 -c "
196-
import json, sys
207+
maas_get "/machines/${system_id}/" | MAAS_NETWORK="${MAAS_NETWORK:-}" python3 -c "
208+
import json, os, sys
197209
m = json.load(sys.stdin)
198-
network = '${network_filter}'
210+
network = os.environ.get('MAAS_NETWORK', '')
199211
for iface in m.get('interface_set', []):
200212
for link in iface.get('links', []):
201213
ip = link.get('ip_address', '')

scripts/maas_inventory.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ def build_inventory(config):
193193
for parent, children in GROUP_CHILDREN.items():
194194
inventory[parent] = {"children": children, "hosts": []}
195195

196+
# Track group membership with sets to avoid O(n^2) dedup
197+
group_members = {}
198+
196199
for machine in machines:
197200
# Only include Deployed machines
198201
if machine.get("status") != 6:
@@ -242,7 +245,11 @@ def build_inventory(config):
242245
inventory[group] = {"hosts": [], "vars": {}}
243246
elif "hosts" not in inventory[group]:
244247
inventory[group]["hosts"] = []
245-
inventory[group]["hosts"].append(hostname)
248+
if group not in group_members:
249+
group_members[group] = set()
250+
if hostname not in group_members[group]:
251+
group_members[group].add(hostname)
252+
inventory[group]["hosts"].append(hostname)
246253

247254
return inventory
248255

0 commit comments

Comments
 (0)