In this PR, we add the tailscale syspolicy command with two subcommands: list, which displays policy settings, and reload, which forces a reload of those settings. We also update the LocalAPI and LocalClient to facilitate these additions. Updates #12687 Signed-off-by: Nick Khyl <nickk@tailscale.com>main
parent
45354dab9b
commit
3f626c0d77
@ -0,0 +1,110 @@ |
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package cli |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"encoding/json" |
||||||
|
"flag" |
||||||
|
"fmt" |
||||||
|
"os" |
||||||
|
"slices" |
||||||
|
"text/tabwriter" |
||||||
|
|
||||||
|
"github.com/peterbourgon/ff/v3/ffcli" |
||||||
|
"tailscale.com/util/syspolicy/setting" |
||||||
|
) |
||||||
|
|
||||||
|
var syspolicyArgs struct { |
||||||
|
json bool // JSON output mode
|
||||||
|
} |
||||||
|
|
||||||
|
var syspolicyCmd = &ffcli.Command{ |
||||||
|
Name: "syspolicy", |
||||||
|
ShortHelp: "Diagnose the MDM and system policy configuration", |
||||||
|
LongHelp: "The 'tailscale syspolicy' command provides tools for diagnosing the MDM and system policy configuration.", |
||||||
|
ShortUsage: "tailscale syspolicy <subcommand>", |
||||||
|
UsageFunc: usageFuncNoDefaultValues, |
||||||
|
Subcommands: []*ffcli.Command{ |
||||||
|
{ |
||||||
|
Name: "list", |
||||||
|
ShortUsage: "tailscale syspolicy list", |
||||||
|
Exec: runSysPolicyList, |
||||||
|
ShortHelp: "Prints effective policy settings", |
||||||
|
LongHelp: "The 'tailscale syspolicy list' subcommand displays the effective policy settings and their sources (e.g., MDM or environment variables).", |
||||||
|
FlagSet: (func() *flag.FlagSet { |
||||||
|
fs := newFlagSet("syspolicy list") |
||||||
|
fs.BoolVar(&syspolicyArgs.json, "json", false, "output in JSON format") |
||||||
|
return fs |
||||||
|
})(), |
||||||
|
}, |
||||||
|
{ |
||||||
|
Name: "reload", |
||||||
|
ShortUsage: "tailscale syspolicy reload", |
||||||
|
Exec: runSysPolicyReload, |
||||||
|
ShortHelp: "Forces a reload of policy settings, even if no changes are detected, and prints the result", |
||||||
|
LongHelp: "The 'tailscale syspolicy reload' subcommand forces a reload of policy settings, even if no changes are detected, and prints the result.", |
||||||
|
FlagSet: (func() *flag.FlagSet { |
||||||
|
fs := newFlagSet("syspolicy reload") |
||||||
|
fs.BoolVar(&syspolicyArgs.json, "json", false, "output in JSON format") |
||||||
|
return fs |
||||||
|
})(), |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
func runSysPolicyList(ctx context.Context, args []string) error { |
||||||
|
policy, err := localClient.GetEffectivePolicy(ctx, setting.DefaultScope()) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
printPolicySettings(policy) |
||||||
|
return nil |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func runSysPolicyReload(ctx context.Context, args []string) error { |
||||||
|
policy, err := localClient.ReloadEffectivePolicy(ctx, setting.DefaultScope()) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
printPolicySettings(policy) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func printPolicySettings(policy *setting.Snapshot) { |
||||||
|
if syspolicyArgs.json { |
||||||
|
json, err := json.MarshalIndent(policy, "", "\t") |
||||||
|
if err != nil { |
||||||
|
errf("syspolicy marshalling error: %v", err) |
||||||
|
} else { |
||||||
|
outln(string(json)) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
if policy.Len() == 0 { |
||||||
|
outln("No policy settings") |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) |
||||||
|
fmt.Fprintln(w, "Name\tOrigin\tValue\tError") |
||||||
|
fmt.Fprintln(w, "----\t------\t-----\t-----") |
||||||
|
for _, k := range slices.Sorted(policy.Keys()) { |
||||||
|
setting, _ := policy.GetSetting(k) |
||||||
|
var origin string |
||||||
|
if o := setting.Origin(); o != nil { |
||||||
|
origin = o.String() |
||||||
|
} |
||||||
|
if err := setting.Error(); err != nil { |
||||||
|
fmt.Fprintf(w, "%s\t%s\t\t{%s}\n", k, origin, err) |
||||||
|
} else { |
||||||
|
fmt.Fprintf(w, "%s\t%s\t%s\t\n", k, origin, setting.Value()) |
||||||
|
} |
||||||
|
} |
||||||
|
w.Flush() |
||||||
|
|
||||||
|
fmt.Println() |
||||||
|
return |
||||||
|
} |
||||||
Loading…
Reference in new issue