mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-02 04:51:29 +02:00
The mobile bridges only carried the policy fetcher, leaving every enforcement decision to the native apps: the desktop derived its UI restrictions in the Wails service layer, the daemon kept the conflict machinery in the server package, and both mobile bridges duplicated the JSON fetch adapter. Anything the native side had to reimplement was a place for iOS and Android to drift apart. Enforcement now lives in client/mdm and is consumed identically by all three platforms: - conflicts.go holds the value-aware conflict checks lifted out of the daemon, so the same normalization (canonical URLs, PSK sentinel echo) applies wherever a config change is validated. - restrictions.go derives the UI enforcement snapshot from a policy and renders it in the JSON shape the desktop frontend already consumes. The service-layer types become aliases, keeping one source of truth. - jsonloader.go replaces the adapter that was copy-pasted into both bridges. - changedetector.go moves change detection off the native side: the caller forwards the OS notification and asks whether the managed configuration actually changed, instead of diffing dictionaries itself. The mobile bridges gain the enforcement the daemon already had. The Preferences getters resolve managed keys from the policy, so a naive UI shows the enforced value; Commit rejects a staged change that diverges from a managed key; NewAuth resolves the managed management URL before persisting the config and overlays the policy on it, so a login can no longer run against a URL the policy forbids. Android's profile mutations fail closed when disableProfiles is set. NewAuth takes the fetcher as a required argument rather than keeping a policy-blind overload: the apps consume this code as a submodule, so a compile error at the bump is the point. The mobile PSK getter is replaced by a presence check — the key has no reason to cross the bridge, and not returning it means the native side needs no redaction sentinel of its own.
90 lines
3.2 KiB
Go
90 lines
3.2 KiB
Go
package mdm
|
|
|
|
import "encoding/json"
|
|
|
|
// Fields carries the per-key MDM enforcement state for a UI: value-typed
|
|
// fields hold the enforced value, boolean fields report that the key is
|
|
// managed.
|
|
type Fields struct {
|
|
ManagementURL string `json:"managementURL"`
|
|
PreSharedKey bool `json:"preSharedKey"`
|
|
WireguardPort bool `json:"wireguardPort"`
|
|
RosenpassEnabled bool `json:"rosenpassEnabled"`
|
|
RosenpassPermissive bool `json:"rosenpassPermissive"`
|
|
DisableClientRoutes bool `json:"disableClientRoutes"`
|
|
DisableServerRoutes bool `json:"disableServerRoutes"`
|
|
AllowServerSSH *bool `json:"allowServerSSH"`
|
|
DisableAutoConnect bool `json:"disableAutoConnect"`
|
|
DisableAutostart bool `json:"disableAutostart"`
|
|
BlockInbound bool `json:"blockInbound"`
|
|
DisableMetricsCollection bool `json:"disableMetricsCollection"`
|
|
SplitTunnelMode bool `json:"splitTunnelMode"`
|
|
SplitTunnelApps bool `json:"splitTunnelApps"`
|
|
DisableAdvancedView bool `json:"disableAdvancedView"`
|
|
}
|
|
|
|
// Features carries the feature gates a UI must honor.
|
|
type Features struct {
|
|
DisableProfiles bool `json:"disableProfiles"`
|
|
DisableNetworks bool `json:"disableNetworks"`
|
|
DisableUpdateSettings bool `json:"disableUpdateSettings"`
|
|
}
|
|
|
|
// Restrictions is the UI-facing enforcement snapshot; the JSON shape is
|
|
// shared by the desktop frontend and the mobile bridges.
|
|
type Restrictions struct {
|
|
MDM Fields `json:"mdm"`
|
|
Features Features `json:"features"`
|
|
}
|
|
|
|
// BuildRestrictions derives the UI enforcement snapshot from the active
|
|
// policy.
|
|
func BuildRestrictions(policy *Policy) Restrictions {
|
|
var r Restrictions
|
|
if policy.IsEmpty() {
|
|
return r
|
|
}
|
|
|
|
if v, ok := policy.GetString(KeyManagementURL); ok {
|
|
r.MDM.ManagementURL = CanonicalURL(v)
|
|
}
|
|
r.MDM.PreSharedKey = policy.HasKey(KeyPreSharedKey)
|
|
r.MDM.WireguardPort = policy.HasKey(KeyWireguardPort)
|
|
r.MDM.RosenpassEnabled = policy.HasKey(KeyRosenpassEnabled)
|
|
r.MDM.RosenpassPermissive = policy.HasKey(KeyRosenpassPermissive)
|
|
r.MDM.DisableClientRoutes = policy.HasKey(KeyDisableClientRoutes)
|
|
r.MDM.DisableServerRoutes = policy.HasKey(KeyDisableServerRoutes)
|
|
r.MDM.DisableAutoConnect = policy.HasKey(KeyDisableAutoConnect)
|
|
r.MDM.DisableAutostart = policy.HasKey(KeyDisableAutostart)
|
|
r.MDM.BlockInbound = policy.HasKey(KeyBlockInbound)
|
|
r.MDM.DisableMetricsCollection = policy.HasKey(KeyDisableMetricsCollection)
|
|
r.MDM.SplitTunnelMode = policy.HasKey(KeySplitTunnelMode)
|
|
r.MDM.SplitTunnelApps = policy.HasKey(KeySplitTunnelApps)
|
|
if v, ok := policy.GetBool(KeyAllowServerSSH); ok {
|
|
r.MDM.AllowServerSSH = &v
|
|
}
|
|
if v, ok := policy.GetBool(KeyDisableAdvancedView); ok {
|
|
r.MDM.DisableAdvancedView = v
|
|
}
|
|
|
|
if v, ok := policy.GetBool(KeyDisableProfiles); ok {
|
|
r.Features.DisableProfiles = v
|
|
}
|
|
if v, ok := policy.GetBool(KeyDisableNetworks); ok {
|
|
r.Features.DisableNetworks = v
|
|
}
|
|
if v, ok := policy.GetBool(KeyDisableUpdateSettings); ok {
|
|
r.Features.DisableUpdateSettings = v
|
|
}
|
|
return r
|
|
}
|
|
|
|
// JSON renders the snapshot in the shared UI JSON shape.
|
|
func (r Restrictions) JSON() (string, error) {
|
|
b, err := json.Marshal(r)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(b), nil
|
|
}
|