github.com/rigado/snapd@v2.42.5-go-mod+incompatible/overlord/configstate/configcore/services.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package configcore 21 22 import ( 23 "fmt" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 "time" 28 29 "github.com/snapcore/snapd/dirs" 30 "github.com/snapcore/snapd/overlord/configstate/config" 31 "github.com/snapcore/snapd/systemd" 32 ) 33 34 var services = []struct{ configName, systemdName string }{ 35 {"ssh", "ssh.service"}, 36 {"rsyslog", "rsyslog.service"}, 37 } 38 39 func init() { 40 for _, service := range services { 41 s := fmt.Sprintf("core.service.%s.disable", service.configName) 42 supportedConfigurations[s] = true 43 } 44 } 45 46 type sysdLogger struct{} 47 48 func (l *sysdLogger) Notify(status string) { 49 fmt.Fprintf(Stderr, "sysd: %s\n", status) 50 } 51 52 // switchDisableSSHService handles the special case of disabling/enabling ssh 53 // service on core devices. 54 func switchDisableSSHService(serviceName, value string) error { 55 sysd := systemd.New(dirs.GlobalRootDir, systemd.SystemMode, &sysdLogger{}) 56 sshCanary := filepath.Join(dirs.GlobalRootDir, "/etc/ssh/sshd_not_to_be_run") 57 58 switch value { 59 case "true": 60 if err := ioutil.WriteFile(sshCanary, []byte("SSH has been disabled by snapd system configuration\n"), 0644); err != nil { 61 return err 62 } 63 return sysd.Stop(serviceName, 5*time.Minute) 64 case "false": 65 err := os.Remove(sshCanary) 66 if err != nil && !os.IsNotExist(err) { 67 return err 68 } 69 // Unmask both sshd.service and ssh.service and ignore the 70 // errors, if any. This undoes the damage done by earlier 71 // versions of snapd. 72 sysd.Unmask("sshd.service") 73 sysd.Unmask("ssh.service") 74 return sysd.Start(serviceName) 75 default: 76 return fmt.Errorf("option %q has invalid value %q", serviceName, value) 77 } 78 } 79 80 // switchDisableTypicalService switches a service in/out of disabled state 81 // where "true" means disabled and "false" means enabled. 82 func switchDisableService(serviceName, value string) error { 83 if serviceName == "ssh.service" { 84 return switchDisableSSHService(serviceName, value) 85 } 86 87 sysd := systemd.New(dirs.GlobalRootDir, systemd.SystemMode, &sysdLogger{}) 88 89 switch value { 90 case "true": 91 if err := sysd.Disable(serviceName); err != nil { 92 return err 93 } 94 if err := sysd.Mask(serviceName); err != nil { 95 return err 96 } 97 return sysd.Stop(serviceName, 5*time.Minute) 98 case "false": 99 if err := sysd.Unmask(serviceName); err != nil { 100 return err 101 } 102 if err := sysd.Enable(serviceName); err != nil { 103 return err 104 } 105 return sysd.Start(serviceName) 106 default: 107 return fmt.Errorf("option %q has invalid value %q", serviceName, value) 108 } 109 } 110 111 // services that can be disabled 112 func handleServiceDisableConfiguration(tr config.Conf) error { 113 for _, service := range services { 114 output, err := coreCfg(tr, fmt.Sprintf("service.%s.disable", service.configName)) 115 if err != nil { 116 return err 117 } 118 if output != "" { 119 if err := switchDisableService(service.systemdName, output); err != nil { 120 return err 121 } 122 } 123 } 124 125 return nil 126 }