package conf import ( "encoding/xml" `io/fs` `net` `os/user` `text/template` `time` `r00t2.io/gobroke/tplCmd` `r00t2.io/goutils/logging` ) // Config represents a configuration file. type Config struct { XMLName xml.Name `json:"-" toml:"-" xml:"config" yaml:"-" ` /* Username, if provided, will be the default username used for any Tunnel that does not specify one (via Tunnel.Username). This should be the username used when authenticating to tunnelbroker.net. It is optional, as the username can be specified/overridden for each Tunnel, but at least one or the other *must* be provided. This makes it easier if you have multiple tunnels under the same account. If a username is specified in Tunnel.Username, it will be used. If not (and, of course, Config.Username is specified), then Config.Username will be used for that Tunnel. */ Username *string `json:"default_username,omitempty" toml:"DefaultUsername,omitempty" xml:"defaultUser,attr,omitempty" yaml:"Default Username,omitempty"` // Freq indicates the (check, not update) frequency. Freq time.Duration `json:"freq,omitempty" toml:"Frequency,omitempty" xml:"freq,attr,omitempty" yaml:"Frequency,omitempty" default:"5m" validate:"gt=0"` // SingleTunnel, if true, will suppress goroutine-management of tunnels and instead execute them sequentially instead. SingleTunnel bool `json:"1tun,omitempty" toml:"SingleTunnel,omitempty" xml:"oneTun,attr,omitempty" yaml:"Single Tunnel,omitempty"` // Tunnels contains one or more tunnel configurations. Tunnels []*Tunnel `json:"tunnels" toml:"Tunnel" xml:"tunnels>tunnel" yaml:"Tunnels" validate:"required,dive,required"` /* Cmds are executed, in order, *after* all Tunnel configurations have been run. Unlike in Tunnel and ConfigTemplate, no templating on these commands is performed. */ Cmds []*tplCmd.Cmd `json:"cmds,omitempty" toml:"Command,omitempty" xml:"commands>cmd,omitempty" yaml:"Commands,omitempty" validate:"omitempty,dive"` confPath *string debug bool log logging.Logger cksum []byte } // Tunnel represents a single tunnel configuration from tunnelbroker.net. type Tunnel struct { XMLName xml.Name `json:"-" toml:"-" xml:"tunnel" yaml:"-"` /* TunnelID can be found by logging into https://tunnelbroker.net/ and, at the "Main Page" that loads when logging in, clicking on the desired tunnel name. The tunnel ID is then displayed in both the URL bar: https://tunnelbroker.net/tunnel_detail.php?tid= And as the first line on the first tab ("IPv6 Tunnel" tab), labeled "Tunnel ID". */ TunnelID uint `json:"tun_id" toml:"TunnelID" xml:"id,attr" yaml:"Tunnel ID" validate:"required,ge=1"` /* ExplicitAddr, if provided, will be used as the tunnelbroker.Tunnel.ClientIPv4 for tunnelbroker.Tunnel.Update. If not provided, this will be fetched dynamically from an external source. */ ExplicitAddr *net.IP `json:"addr,omitempty" toml:"ExplicitClientIP,omitempty" xml:"addr,attr,omitempty" yaml:"Explicit Client IP Address,omitempty" validate:"omitempty,ipv4"` /* MTU should be specified if you have defined a custom one (under the "Advanced" tab for this tunnel at tunnlebroker.net). If you did not change this, the default is 1480 (the maximum allowed), and the default value of this struct field on configuration parsing will reflect this. This is not used by anything directly in GoBroke, but is contained here to assist in templating that may be configured. */ MTU uint `json:"mtu,omitempty" toml:"MTU,omitempty" xml:"mtu,attr,omitempty" yaml:"MTU,omitempty" default:"1480" validate:"required,gt=0,le=1480"` /* Username field is optional IF DefaultUsername was specified. This also allows you to specify tunnels from different accounts by providing a tunnel-specific username. */ Username *string `json:"username,omitempty" toml:"Username,omitempty" xml:"username,attr,omitempty" yaml:"Username,omitempty"` /* UpdateKey can be found under the "Advanced" tab on your tunnelbroker.net tunnel's page, labeled "Update Key". This token is used to not only update the client-side tunnel IP but also to query the HE Tunnelbroker "API" (it's really just a single endpoint) to get the tunnel information necessary for local configuration. */ UpdateKey string `json:"update_key" toml:"UpdateKey" xml:"key,attr" yaml:"Update Key" validate:"required"` // TemplateConfgs is optional. It holds templates that will be executed in order given. See ConfigTemplate. TemplateConfigs []*ConfigTemplate `json:"cfg_tpls" toml:"ConfigTemplate" xml:"config>tpl" yaml:"Configuration File Templates" validate:"omitempty,dive"` /* Cmds are executed, in order, *after* all tunnel updates/fetching and the templating has completed (if any specified). Each command will also have runner.TunnelResult templated to it like TemplateConfigs/ConfigTemplate.Cmds, so they may be templated as necessary. */ Cmds []*tplCmd.TemplateCmd `json:"cmds,omitempty" toml:"Command,omitempty" xml:"commands>cmd,omitempty" yaml:"Commands,omitempty" validate:"omitempty,dive"` cfg *Config } /* ConfigTemplate allows the templating of configuration files, etc. from the tunnel information. Templates are executed *after* the IP update (if an update was necessary), but are always *run*. ConfigTemplate.Dest will only be written to if: * The file does not exist (yet), or * The templated content differs from the file on disk */ type ConfigTemplate struct { XMLName xml.Name `json:"-" toml:"-" xml:"tpl" yaml:"-"` /* Template is the path to the template file on disk. It must follow the syntax, rules, etc. of a Golang (text/)template.Template (https://pkg.go.dev/text/template#Template). The struct passed to it is a runner.TunnelResult. */ Template string `json:"tpl" toml:"Template" xml:"tpl,attr" yaml:"Template File Path" validate:"required,filepath"` // Dest contains the filepath that the Template should be written out to. Dest string `json:"dest" toml:"Destination" xml:"dest,attr" yaml:"Destination File Path" validate:"required,filepath"` // Perms allows specifying permissions/ownerships, if the curent user has the capability to do so. Perms *Perms `json:"perms,omitempty" toml:"Permissions,omitempty" xml:"perms,omitempty" yaml:"Permissions and Ownership,omitempty"` // Cmds specifiies commands to run after this ConfigTemplate run. Cmds []*tplCmd.TemplateCmd `json:"cmds,omitempty" toml:"Command,omitempty" xml:"cmds>cmd,omitempty" yaml:"Commands,omitempty" validate:"omitempty,dive"` // Tpl is the parsed template from Template. Tpl *template.Template `json:"-" toml:"-" xml:"-" yaml:"-"` } // Perms specify permissions for a file and its parent directory. type Perms struct { // File specifies the desired permissions/ownership of the target file. File *PermSpec `json:"file,omitempty" toml:"File,omitempty" xml:"file,omitempty" yaml:"File,omitempty"` // ParentDir specifies the desired permissions/ownership of the parent ("dirname") of File. ParentDir *PermSpec `json:"dir,omitempty" toml:"Dir,omitempty" xml:"dir,omitempty" yaml:"Directory,omitempty"` curUser *user.User curGroup *user.Group curUid int curGid int } // PermSpec is used to define contextual permissions. It is used for both files and their parent directories. type PermSpec struct { /* User is the username or UID (tried in that order) to chown. If specified as an empty string, the current/runtime UID will be used. If unspecified, UID will not be enforced. */ User string `json:"user,omitempty" toml:"User,omitempty" xml:"user,attr,omitempty" yaml:"User,omitempty"` /* Group is the groupname or GID (tried in that order) to chown. If specified as an empty string, the current/runtime GID will be used. If unspecified, GID will not be enforced. */ Group string `json:"group,omitempty" toml:"Group,omitempty" xml:"group,attr,omitempty" yaml:"Group,omitempty"` // Mode is the permission mode bitset. If unspecified, mode will not be enforced. Mode *fs.FileMode `json:"mode,omitempty" toml:"Mode,omitempty" xml:"mode,attr,omitempty" yaml:"Mode,omitempty" validate:"omitempty,ge=0,le=4095"` explicitMode bool realUid int realGid int idsSet bool parent *Perms }