Zuletzt aktiv 1 month ago

nuno hat die Gist bearbeitet 1 month ago. Zu Änderung gehen

1 file changed, 296 insertions

policy.command.sh(Datei erstellt)

@@ -0,0 +1,296 @@
1 + #!/usr/bin/env bash
2 + # policy.command.sh — manage policies
3 + #
4 + # Subcommands:
5 + # wgctl policy list
6 + # wgctl policy show --name <name>
7 + # wgctl policy add --name <name> [--tunnel-mode split|full]
8 + # [--default-rule <rule>] [--strict-rule] [--no-auto-apply]
9 + # [--desc <desc>]
10 + # wgctl policy rm --name <name>
11 + # wgctl policy set --name <name> --field <field> --value <value>
12 +
13 + # ============================================
14 + # Lifecycle
15 + # ============================================
16 +
17 + function cmd::policy::on_load() {
18 + load_module policy
19 +
20 + flag::register --name
21 + flag::register --tunnel-mode
22 + flag::register --default-rule
23 + flag::register --strict-rule
24 + flag::register --no-strict-rule
25 + flag::register --auto-apply
26 + flag::register --no-auto-apply
27 + flag::register --desc
28 + flag::register --field
29 + flag::register --value
30 +
31 + command::mixin json_output
32 + }
33 +
34 + # ============================================
35 + # Help
36 + # ============================================
37 +
38 + function cmd::policy::help() {
39 + cat <<EOF
40 + Usage: wgctl policy <subcommand> [options]
41 +
42 + Manage policies. Policies define behavioral flags for subnets and identities.
43 +
44 + Subcommands:
45 + list List all policies
46 + show --name <name> Show policy details
47 + add --name <name> Add a new policy
48 + [--tunnel-mode split|full]
49 + [--default-rule <rule>]
50 + [--strict-rule]
51 + [--no-auto-apply]
52 + [--desc <desc>]
53 + rm --name <name> Remove a policy (built-ins cannot be removed)
54 + set --name <name> Set a single field on a policy
55 + --field <field>
56 + --value <value>
57 +
58 + Fields:
59 + tunnel_mode split|full
60 + default_rule rule name (or empty to clear)
61 + strict_rule true|false
62 + auto_apply true|false
63 + desc description string
64 +
65 + Built-in policies (cannot be removed): default, guest, trusted, server, iot
66 +
67 + Examples:
68 + wgctl policy list
69 + wgctl policy show --name guest
70 + wgctl policy add --name contractor --default-rule contractor --strict-rule
71 + wgctl policy set --name contractor --field tunnel-mode --value full
72 + wgctl policy rm --name contractor
73 + EOF
74 + }
75 +
76 + # ============================================
77 + # Run
78 + # ============================================
79 +
80 + function cmd::policy::run() {
81 + local subcmd="${1:-list}"
82 + shift || true
83 +
84 + if command::json; then
85 + cmd::policy::_output_json
86 + return 0
87 + fi
88 +
89 + case "$subcmd" in
90 + list) cmd::policy::_list "$@" ;;
91 + show) cmd::policy::_show "$@" ;;
92 + add) cmd::policy::_add "$@" ;;
93 + rm) cmd::policy::_rm "$@" ;;
94 + set) cmd::policy::_set "$@" ;;
95 + --help) cmd::policy::help ;;
96 + *)
97 + log::error "Unknown subcommand '${subcmd}'. Available: list, show, add, rm, set"
98 + return 1
99 + ;;
100 + esac
101 + }
102 +
103 + # ============================================
104 + # Subcommands
105 + # ============================================
106 +
107 + function cmd::policy::_list() {
108 + local data
109 + data=$(policy::list_data | ui::sort_rows 1)
110 +
111 + if [[ -z "$data" ]]; then
112 + log::info "No policies defined."
113 + return 0
114 + fi
115 +
116 + if display::is_table "policy_list"; then
117 + cmd::policy::_render_table "$data"
118 + return 0
119 + fi
120 +
121 + echo ""
122 + while IFS='|' read -r name tunnel default_rule strict auto desc; do
123 + ui::policy::list_row "$name" "$default_rule" "$strict" "$auto"
124 + done <<< "$data"
125 + echo ""
126 + }
127 +
128 + function cmd::policy::_render_table() {
129 + local data="${1:-}"
130 + [[ -z "$data" ]] && return 0
131 +
132 + ui::policy::list_header_table
133 + while IFS='|' read -r name tunnel default_rule strict auto desc; do
134 + [[ -z "$name" ]] && continue
135 + ui::policy::list_row_table "$name" "$tunnel" "$default_rule" "$strict" "$auto"
136 + done <<< "$data"
137 + printf "\n"
138 + }
139 +
140 +
141 + function cmd::policy::_show() {
142 + local name=""
143 + while [[ $# -gt 0 ]]; do
144 + case "$1" in
145 + --name) name="$2"; shift 2 ;;
146 + --help) cmd::policy::help; return ;;
147 + *) log::error "Unknown flag: $1"; return 1 ;;
148 + esac
149 + done
150 +
151 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
152 + policy::require_exists "$name" || return 1
153 +
154 + local dr tunnel strict auto
155 + dr=$(policy::default_rule "$name")
156 + tunnel=$(policy::tunnel_mode "$name")
157 + strict=$(policy::strict_rule "$name" && echo "yes" || echo "no")
158 + auto=$(policy::auto_apply "$name" && echo "yes" || echo "no")
159 +
160 + local rule_val="-"
161 + [[ -n "$dr" ]] && rule_val="$dr"
162 +
163 + local strict_padded
164 + strict_padded=$(printf "%-4s" "$strict")
165 +
166 + # First line — mirrors list format
167 + echo ""
168 + printf " \033[1m%-14s\033[0m \033[2mrule:\033[0m %-16s \033[2mstrict:\033[0m %s\n" \
169 + "$name" "$rule_val" "$strict_padded"
170 + echo ""
171 +
172 + # Detail section
173 + local desc
174 + desc=$(policy::get "$name" "desc")
175 + [[ -n "$desc" ]] && printf " \033[2mDescription:\033[0m %s\n" "$desc"
176 + printf " \033[2mTunnel:\033[0m %s\n" "$tunnel"
177 + printf " \033[2mAuto apply:\033[0m %s\n" "$auto"
178 + echo ""
179 + }
180 +
181 + function cmd::policy::_add() {
182 + local name="" tunnel_mode="split" default_rule="" \
183 + strict_rule="false" auto_apply="true" desc=""
184 +
185 + while [[ $# -gt 0 ]]; do
186 + case "$1" in
187 + --name) name="$2"; shift 2 ;;
188 + --tunnel-mode) tunnel_mode="$2"; shift 2 ;;
189 + --default-rule) default_rule="$2"; shift 2 ;;
190 + --strict-rule) strict_rule="true"; shift ;;
191 + --no-strict-rule) strict_rule="false"; shift ;;
192 + --no-auto-apply) auto_apply="false"; shift ;;
193 + --auto-apply) auto_apply="true"; shift ;;
194 + --desc) desc="$2"; shift 2 ;;
195 + --help) cmd::policy::help; return ;;
196 + *) log::error "Unknown flag: $1"; return 1 ;;
197 + esac
198 + done
199 +
200 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
201 +
202 + case "$tunnel_mode" in
203 + split|full) ;;
204 + *) log::error "Invalid --tunnel-mode '${tunnel_mode}'. Use: split, full"; return 1 ;;
205 + esac
206 +
207 + json::policy_add "$(ctx::policies)" "$name" "$tunnel_mode" \
208 + "$default_rule" "$strict_rule" "$auto_apply" "$desc"
209 + log::ok "Policy '${name}' added"
210 + }
211 +
212 + function cmd::policy::_rm() {
213 + local name=""
214 + while [[ $# -gt 0 ]]; do
215 + case "$1" in
216 + --name) name="$2"; shift 2 ;;
217 + --help) cmd::policy::help; return ;;
218 + *) log::error "Unknown flag: $1"; return 1 ;;
219 + esac
220 + done
221 +
222 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
223 + policy::require_exists "$name" || return 1
224 +
225 + json::policy_remove "$(ctx::policies)" "$name"
226 + log::ok "Policy '${name}' removed"
227 + }
228 +
229 + function cmd::policy::_set() {
230 + local name="" field="" value=""
231 + while [[ $# -gt 0 ]]; do
232 + case "$1" in
233 + --name) name="$2"; shift 2 ;;
234 + --field) field="$2"; shift 2 ;;
235 + --value) value="$2"; shift 2 ;;
236 + --help) cmd::policy::help; return ;;
237 + *) log::error "Unknown flag: $1"; return 1 ;;
238 + esac
239 + done
240 +
241 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
242 + [[ -z "$field" ]] && { log::error "Missing required flag: --field"; return 1; }
243 + [[ -z "$value" ]] && { log::error "Missing required flag: --value"; return 1; }
244 +
245 + policy::require_exists "$name" || return 1
246 +
247 + # Normalise field name (allow tunnel-mode as well as tunnel_mode)
248 + field="${field//-/_}"
249 +
250 + case "$field" in
251 + tunnel_mode)
252 + case "$value" in
253 + split|full) ;;
254 + *) log::error "Invalid value '${value}' for tunnel_mode. Use: split, full"; return 1 ;;
255 + esac
256 + ;;
257 + strict_rule|auto_apply)
258 + case "$value" in
259 + true|false) ;;
260 + *) log::error "Invalid value '${value}' for ${field}. Use: true, false"; return 1 ;;
261 + esac
262 + ;;
263 + default_rule|desc) ;;
264 + *)
265 + log::error "Unknown field '${field}'. Valid: tunnel_mode, default_rule, strict_rule, auto_apply, desc"
266 + return 1
267 + ;;
268 + esac
269 +
270 + json::policy_set_field "$(ctx::policies)" "$name" "$field" "$value"
271 + log::ok "Policy '${name}': ${field} = ${value}"
272 + }
273 +
274 + function cmd::policy::_output_json() {
275 + local data
276 + data=$(policy::list_data 2>/dev/null)
277 +
278 + local -a policies=()
279 + while IFS='|' read -r name tunnel_mode default_rule strict_rule auto_apply desc; do
280 + [[ -z "$name" ]] && continue
281 +
282 + local strict_json="false"
283 + [[ "$strict_rule" == "true" ]] && strict_json="true"
284 + local auto_json="true"
285 + [[ "$auto_apply" == "false" ]] && auto_json="false"
286 +
287 + policies+=("$(printf '{"name":"%s","tunnel_mode":"%s","default_rule":"%s","strict_rule":%s,"auto_apply":%s,"desc":"%s"}' \
288 + "$name" "$tunnel_mode" "${default_rule:-}" \
289 + "$strict_json" "$auto_json" "$desc")")
290 + done <<< "$data"
291 +
292 + local count=${#policies[@]}
293 + local array
294 + array=$(printf '%s\n' "${policies[@]:-}" | paste -sd ',' -)
295 + printf '{"policies":[%s]}' "${array:-}" | json::envelope "policy list" "$count"
296 + }
Neuer Älter