Последняя активность 1 month ago

gistfile1.txt Исходник
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
17function 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
32# ============================================
33# Help
34# ============================================
35
36function cmd::policy::help() {
37 cat <<EOF
38Usage: wgctl policy <subcommand> [options]
39
40Manage policies. Policies define behavioral flags for subnets and identities.
41
42Subcommands:
43 list List all policies
44 show --name <name> Show policy details
45 add --name <name> Add a new policy
46 [--tunnel-mode split|full]
47 [--default-rule <rule>]
48 [--strict-rule]
49 [--no-auto-apply]
50 [--desc <desc>]
51 rm --name <name> Remove a policy (built-ins cannot be removed)
52 set --name <name> Set a single field on a policy
53 --field <field>
54 --value <value>
55
56Fields:
57 tunnel_mode split|full
58 default_rule rule name (or empty to clear)
59 strict_rule true|false
60 auto_apply true|false
61 desc description string
62
63Built-in policies (cannot be removed): default, guest, trusted, server, iot
64
65Examples:
66 wgctl policy list
67 wgctl policy show --name guest
68 wgctl policy add --name contractor --default-rule contractor --strict-rule
69 wgctl policy set --name contractor --field tunnel-mode --value full
70 wgctl policy rm --name contractor
71EOF
72}
73
74# ============================================
75# Run
76# ============================================
77
78function cmd::policy::run() {
79 local subcmd="${1:-list}"
80 shift || true
81
82 case "$subcmd" in
83 list) cmd::policy::_list "$@" ;;
84 show) cmd::policy::_show "$@" ;;
85 add) cmd::policy::_add "$@" ;;
86 rm) cmd::policy::_rm "$@" ;;
87 set) cmd::policy::_set "$@" ;;
88 --help) cmd::policy::help ;;
89 *)
90 log::error "Unknown subcommand '${subcmd}'. Available: list, show, add, rm, set"
91 return 1
92 ;;
93 esac
94}
95
96# ============================================
97# Subcommands
98# ============================================
99
100function cmd::policy::_list() {
101 local data
102 data=$(policy::list_data)
103
104 if [[ -z "$data" ]]; then
105 log::info "No policies defined."
106 return 0
107 fi
108
109 echo ""
110 while IFS='|' read -r name tunnel default_rule strict auto desc; do
111 ui::policy::list_row "$name" "$default_rule" "$strict" "$auto"
112 done <<< "$data"
113 echo ""
114}
115
116function cmd::policy::_show() {
117 local name=""
118 while [[ $# -gt 0 ]]; do
119 case "$1" in
120 --name) name="$2"; shift 2 ;;
121 --help) cmd::policy::help; return ;;
122 *) log::error "Unknown flag: $1"; return 1 ;;
123 esac
124 done
125
126 [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
127 policy::require_exists "$name" || return 1
128
129 echo ""
130 ui::row "Name" "$name"
131 ui::row "Tunnel mode" "$(policy::tunnel_mode "$name")"
132 local dr
133 dr=$(policy::default_rule "$name")
134 ui::row "Default rule" "${dr:-—}"
135 ui::row "Strict rule" "$(policy::strict_rule "$name" && echo "yes" || echo "no")"
136 ui::row "Auto apply" "$(policy::auto_apply "$name" && echo "yes" || echo "no")"
137 echo ""
138}
139
140function cmd::policy::_add() {
141 local name="" tunnel_mode="split" default_rule="" \
142 strict_rule="false" auto_apply="true" desc=""
143
144 while [[ $# -gt 0 ]]; do
145 case "$1" in
146 --name) name="$2"; shift 2 ;;
147 --tunnel-mode) tunnel_mode="$2"; shift 2 ;;
148 --default-rule) default_rule="$2"; shift 2 ;;
149 --strict-rule) strict_rule="true"; shift ;;
150 --no-strict-rule) strict_rule="false"; shift ;;
151 --no-auto-apply) auto_apply="false"; shift ;;
152 --auto-apply) auto_apply="true"; shift ;;
153 --desc) desc="$2"; shift 2 ;;
154 --help) cmd::policy::help; return ;;
155 *) log::error "Unknown flag: $1"; return 1 ;;
156 esac
157 done
158
159 [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
160
161 case "$tunnel_mode" in
162 split|full) ;;
163 *) log::error "Invalid --tunnel-mode '${tunnel_mode}'. Use: split, full"; return 1 ;;
164 esac
165
166 json::policy_add "$(ctx::policies)" "$name" "$tunnel_mode" \
167 "$default_rule" "$strict_rule" "$auto_apply" "$desc"
168 log::ok "Policy '${name}' added"
169}
170
171function cmd::policy::_rm() {
172 local name=""
173 while [[ $# -gt 0 ]]; do
174 case "$1" in
175 --name) name="$2"; shift 2 ;;
176 --help) cmd::policy::help; return ;;
177 *) log::error "Unknown flag: $1"; return 1 ;;
178 esac
179 done
180
181 [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
182 policy::require_exists "$name" || return 1
183
184 json::policy_remove "$(ctx::policies)" "$name"
185 log::ok "Policy '${name}' removed"
186}
187
188function cmd::policy::_set() {
189 local name="" field="" value=""
190 while [[ $# -gt 0 ]]; do
191 case "$1" in
192 --name) name="$2"; shift 2 ;;
193 --field) field="$2"; shift 2 ;;
194 --value) value="$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 [[ -z "$field" ]] && { log::error "Missing required flag: --field"; return 1; }
202 [[ -z "$value" ]] && { log::error "Missing required flag: --value"; return 1; }
203
204 policy::require_exists "$name" || return 1
205
206 # Normalise field name (allow tunnel-mode as well as tunnel_mode)
207 field="${field//-/_}"
208
209 case "$field" in
210 tunnel_mode)
211 case "$value" in
212 split|full) ;;
213 *) log::error "Invalid value '${value}' for tunnel_mode. Use: split, full"; return 1 ;;
214 esac
215 ;;
216 strict_rule|auto_apply)
217 case "$value" in
218 true|false) ;;
219 *) log::error "Invalid value '${value}' for ${field}. Use: true, false"; return 1 ;;
220 esac
221 ;;
222 default_rule|desc) ;;
223 *)
224 log::error "Unknown field '${field}'. Valid: tunnel_mode, default_rule, strict_rule, auto_apply, desc"
225 return 1
226 ;;
227 esac
228
229 json::policy_set_field "$(ctx::policies)" "$name" "$field" "$value"
230 log::ok "Policy '${name}': ${field} = ${value}"
231}