google_guest_agent/cfg/cfg.go (226 lines of code) (raw):

// Copyright 2023 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package cfg is package responsible to loading and accessing the guest environment configuration. package cfg import ( "fmt" "runtime" "github.com/go-ini/ini" ) var ( // instance is the single instance of configuration sections, once loaded this package // should always return it. instance *Sections // configFile is a pointer to a function which takes the current OS name and returns // an appropriate config file name. Replaceable by unit tests. configFile = defaultConfigFile // dataSource is a pointer to a data source loading/defining function, unit tests will // want to change this pointer to whatever makes sense to its implementation. dataSources = defaultDataSources ) const ( winConfigPath = `C:\Program Files\Google\Compute Engine\instance_configs.cfg` unixConfigPath = `/etc/default/instance_configs.cfg` defaultConfig = ` [Core] cloud_logging_enabled = true [Accounts] deprovision_remove = false gpasswd_add_cmd = gpasswd -a {user} {group} gpasswd_remove_cmd = gpasswd -d {user} {group} groupadd_cmd = groupadd {group} groups = adm,dip,docker,lxd,plugdev,video reuse_homedir = false useradd_cmd = useradd -m -s /bin/bash -p * {user} userdel_cmd = userdel -r {user} [Daemons] accounts_daemon = true clock_skew_daemon = true network_daemon = true [IpForwarding] ethernet_proto_id = 66 ip_aliases = true target_instance_ips = true [Instance] instance_id = instance_id_dir = /etc/google_instance_id [InstanceSetup] host_key_dir = /etc/ssh host_key_types = ecdsa,ed25519,rsa network_enabled = true optimize_local_ssd = true set_boto_config = true set_host_keys = true set_multiqueue = true [MetadataScripts] default_shell = /bin/bash run_dir = shutdown = true shutdown-windows = true startup = true startup-windows = true sysprep-specialize = true [NetworkInterfaces] dhcp_command = ip_forwarding = true setup = true manage_primary_nic = restore_debian12_netplan_config = true vlan_setup_enabled = false [OSLogin] cert_authentication = true [MDS] disable-https-mds-setup = true enable-https-mds-native-cert-store = false [Snapshots] enabled = false snapshot_service_ip = 169.254.169.254 snapshot_service_port = 8081 timeout_in_seconds = 60 [Unstable] command_monitor_enabled = false command_pipe_mode = 0770 command_pipe_group = command_request_timeout = 10s systemd_config_dir = /usr/lib/systemd/network ` ) // Core contains the core configuration entries of guest agent, all // configurations not tied/specific to a subsystem are defined in here. type Core struct { // CloudLoggingEnabled config toggle controls Guest Agent cloud logger. // Disabling it will stop Guest Agent for configuring and logging to Cloud Logging. CloudLoggingEnabled bool `ini:"cloud_logging_enabled,omitempty"` } // Sections encapsulates all the configuration sections. type Sections struct { // Core defines the core guest-agent's configuration entries/keys. Core *Core `ini:"Core,omitempty"` // AccountManager defines the address management configurations. It takes precedence over instance's // and project's metadata configuration. The default configuration doesn't define values to it, if the // user has defined it then we shouldn't even consider metadata values. Users must check if this // pointer is nil or not. AccountManager *AccountManager `ini:"accountManager,omitempty"` // Accounts defines the non windows account management options, behaviors and commands. Accounts *Accounts `ini:"Accounts,omitempty"` // AddressManager defines the address management configurations. It takes precedence over instance's // and project's metadata configuration. The default configuration doesn't define values to it, if the // user has defined it then we shouldn't even consider metadata values. Users must check if this // pointer is nil or not. AddressManager *AddressManager `ini:"addressManager,omitempty"` // Daemons defines the availability of clock skew, network and account managers. Daemons *Daemons `ini:"Daemons,omitempty"` // Diagnostics defines the diagnostics configurations. It takes precedence over instance's // and project's metadata configuration. The default configuration doesn't define values to it, if the // user has defined it then we shouldn't even consider metadata values. Users must check if this // pointer is nil or not. Diagnostics *Diagnostics `ini:"diagnostics,omitempty"` // IPForwarding defines the ip forwarding configuration options. IPForwarding *IPForwarding `ini:"IpForwarding,omitempty"` // Instance defines the instance ID handling behaviors, i.e. where to read the ID from etc. Instance *Instance `ini:"Instance,omitempty"` // InstanceSetup defines options to basic instance setup options i.e. optimize local ssd, network, // host keys etc. InstanceSetup *InstanceSetup `ini:"InstanceSetup,omitempty"` // MetadataScripts contains the configurations of the metadata-scripts service. MetadataScripts *MetadataScripts `ini:"MetadataScripts,omitempty"` // NetworkInterfaces defines if the network interfaces should be managed/configured by guest-agent // as well as the commands definitions for network configuration. NetworkInterfaces *NetworkInterfaces `ini:"NetworkInterfaces,omitempty"` // OSLogin defines the OS Login configuration options. OSLogin *OSLogin `ini:"OSLogin,omitempty"` // MDS defines the MDS configuration options. MDS *MDS `ini:"MDS,omitempty"` // Snpashots defines the snapshot listener configuration and behavior i.e. the server address and port. Snapshots *Snapshots `ini:"Snapshots,omitempty"` // Unstable is a "under development feature flags" section. No stability or long term support is // guaranteed for any keys under this section. No application, script or utility should rely on it. Unstable *Unstable `ini:"Unstable,omitempty"` // WSFC defines the wsfc configurations. It takes precedence over instance's and project's // metadata configuration. The default configuration doesn't define values to it, if the user // has defined it then we shouldn't even consider metadata values. Users must check if this // pointer is nil or not. WSFC *WSFC `ini:"wsfc,omitempty"` } // AccountManager contains the configurations of AccountManager section. type AccountManager struct { Disable bool `ini:"disable,omitempty"` } // Accounts contains the configurations of Accounts section. type Accounts struct { DeprovisionRemove bool `ini:"deprovision_remove,omitempty"` GPasswdAddCmd string `ini:"gpasswd_add_cmd,omitempty"` GPasswdRemoveCmd string `ini:"gpasswd_remove_cmd,omitempty"` GroupAddCmd string `ini:"groupadd_cmd,omitempty"` Groups string `ini:"groups,omitempty"` ReuseHomedir bool `ini:"reuse_homedir,omitempty"` UserAddCmd string `ini:"useradd_cmd,omitempty"` UserDelCmd string `ini:"userdel_cmd,omitempty"` } // AddressManager contains the configuration of addressManager section. type AddressManager struct { Disable bool `ini:"disable,omitempty"` } // Daemons contains the configurations of Daemons section. type Daemons struct { AccountsDaemon bool `ini:"accounts_daemon,omitempty"` ClockSkewDaemon bool `ini:"clock_skew_daemon,omitempty"` NetworkDaemon bool `ini:"network_daemon,omitempty"` } // Diagnostics contains the configurations of Diagnostics section. type Diagnostics struct { Enable bool `ini:"enable,omitempty"` } // IPForwarding contains the configurations of IPForwarding section. type IPForwarding struct { EthernetProtoID string `ini:"ethernet_proto_id,omitempty"` IPAliases bool `ini:"ip_aliases,omitempty"` TargetInstanceIPs bool `ini:"target_instance_ips,omitempty"` } // Instance contains the configurations of Instance section. type Instance struct { // InstanceID is a backward compatible key. In the past the instance id was only // supported/setup via config file, if we can't read the instance_id file then // try honoring this configuration key. InstanceID string `ini:"instance_id,omitempty"` // InstanceIDDir defines where the instance id file should be read from. InstanceIDDir string `ini:"instance_id_dir,omitempty"` } // InstanceSetup contains the configurations of InstanceSetup section. type InstanceSetup struct { HostKeyDir string `ini:"host_key_dir,omitempty"` HostKeyTypes string `ini:"host_key_types,omitempty"` NetworkEnabled bool `ini:"network_enabled,omitempty"` OptimizeLocalSSD bool `ini:"optimize_local_ssd,omitempty"` SetBotoConfig bool `ini:"set_boto_config,omitempty"` SetHostKeys bool `ini:"set_host_keys,omitempty"` SetMultiqueue bool `ini:"set_multiqueue,omitempty"` } // MetadataScripts contains the configurations of MetadataScripts section. type MetadataScripts struct { DefaultShell string `ini:"default_shell,omitempty"` RunDir string `ini:"run_dir,omitempty"` Shutdown bool `ini:"shutdown,omitempty"` ShutdownWindows bool `ini:"shutdown-windows,omitempty"` Startup bool `ini:"startup,omitempty"` StartupWindows bool `ini:"startup-windows,omitempty"` SysprepSpecialize bool `ini:"sysprep_specialize,omitempty"` } // OSLogin contains the configurations of OSLogin section. type OSLogin struct { CertAuthentication bool `ini:"cert_authentication,omitempty"` } // MDS contains the configurations for MDS section. Currently its opt-in only // and should not assume any defaults. Setting any [defaultConfig] values will // override user settings from Metadata. type MDS struct { // DisableHTTPSMdsSetup enables/disables the mTLS credential refresher. DisableHTTPSMdsSetup bool `ini:"disable-https-mds-setup,omitempty"` // HTTPSMDSEnableNativeStore enables/disables the use of OSs native store. Native // store is Certificate Store on Windows which hosts both Client Credential and // Root certificate where as its trust store that hosts root certs like // `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` on Linux. HTTPSMDSEnableNativeStore bool `ini:"enable-https-mds-native-cert-store,omitempty"` } // NetworkInterfaces contains the configurations of NetworkInterfaces section. type NetworkInterfaces struct { DHCPCommand string `ini:"dhcp_command,omitempty"` IPForwarding bool `ini:"ip_forwarding,omitempty"` Setup bool `ini:"setup,omitempty"` ManagePrimaryNIC bool `ini:"manage_primary_nic,omitempty"` RestoreDebian12NetplanConfig bool `ini:"restore_debian12_netplan_config,omitempty"` VlanSetupEnabled bool `ini:"vlan_setup_enabled,omitempty"` } // Snapshots contains the configurations of Snapshots section. type Snapshots struct { Enabled bool `ini:"enabled,omitempty"` SnapshotServiceIP string `ini:"snapshot_service_ip,omitempty"` SnapshotServicePort int `ini:"snapshot_service_port,omitempty"` TimeoutInSeconds int `ini:"timeout_in_seconds,omitempty"` } // Unstable contains the configurations of Unstable section. No long term stability or support // is guaranteed for configurations defined in the Unstable section. By default all flags defined // in this section is disabled and is intended to isolate under development features. type Unstable struct { CommandMonitorEnabled bool `ini:"command_monitor_enabled,omitempty"` CommandPipePath string `ini:"command_pipe_path,omitempty"` CommandRequestTimeout string `ini:"command_request_timeout,omitempty"` CommandPipeMode string `ini:"command_pipe_mode,omitempty"` CommandPipeGroup string `ini:"command_pipe_group,omitempty"` SystemdConfigDir string `ini:"systemd_config_dir,omitempty"` } // WSFC contains the configurations of WSFC section. type WSFC struct { Addresses string `ini:"addresses,omitempty"` Enable bool `ini:"enable,omitempty"` Port string `ini:"port,omitempty"` } func defaultConfigFile(osName string) string { if osName == "windows" { return winConfigPath } return unixConfigPath } func defaultDataSources(extraDefaults []byte) []interface{} { var res = []interface{}{[]byte(defaultConfig)} config := configFile(runtime.GOOS) if len(extraDefaults) > 0 { res = append(res, extraDefaults) } return append(res, []interface{}{ config, config + ".distro", config + ".template", }...) } // Load loads default configuration and the configuration from default config files. func Load(extraDefaults []byte) error { opts := ini.LoadOptions{ Loose: true, Insensitive: true, } sources := dataSources(extraDefaults) cfg, err := ini.LoadSources(opts, sources[0], sources[1:]...) if err != nil { return fmt.Errorf("failed to load configuration: %+v", err) } sections := new(Sections) if err := cfg.MapTo(sections); err != nil { return fmt.Errorf("failed to map configuration to object: %+v", err) } instance = sections return nil } // Get returns the configuration's instance previously loaded with Load(). func Get() *Sections { if instance == nil { panic("cfg package was not initialized, Load() " + "should be called in the early initialization code path") } return instance }