github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/policy/basedeclaration.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 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 policy 21 22 import ( 23 "bytes" 24 "fmt" 25 "strings" 26 27 "github.com/snapcore/snapd/asserts" 28 "github.com/snapcore/snapd/interfaces" 29 "github.com/snapcore/snapd/interfaces/builtin" 30 ) 31 32 // The headers of the builtin base-declaration describing the default 33 // interface policies for all snaps. The base declaration focuses on the slot 34 // side for almost all interfaces. Importantly, items are not merged between 35 // the slots and plugs or between the base declaration and snap declaration 36 // for a particular type of rule. This means that if you specify an 37 // installation rule for both slots and plugs in the base declaration, only 38 // the plugs side is used (plugs is preferred over slots). 39 // 40 // The interfaces listed in the base declaration can be broadly categorized 41 // into: 42 // 43 // - manually connected implicit slots (eg, bluetooth-control) 44 // - auto-connected implicit slots (eg, network) 45 // - manually connected app-provided slots (eg, bluez) 46 // - auto-connected app-provided slots (eg, mir) 47 // 48 // such that they will follow this pattern: 49 // 50 // slots: 51 // manual-connected-implicit-slot: 52 // allow-installation: 53 // slot-snap-type: 54 // - core # implicit slot 55 // deny-auto-connection: true # force manual connect 56 // 57 // auto-connected-implicit-slot: 58 // allow-installation: 59 // slot-snap-type: 60 // - core # implicit slot 61 // allow-auto-connection: true # allow auto-connect 62 // 63 // manual-connected-provided-slot: 64 // allow-installation: 65 // slot-snap-type: 66 // - app # app provided slot 67 // deny-connection: true # require allow-connection in snap decl 68 // deny-auto-connection: true # force manual connect 69 // 70 // auto-connected-provided-slot: 71 // allow-installation: 72 // slot-snap-type: 73 // - app # app provided slot 74 // deny-connection: true # require allow-connection in snap decl 75 // 76 // App-provided slots use 'deny-connection: true' since slot implementations 77 // require privileged access to the system and the snap must be trusted. In 78 // this manner a snap declaration is required to override the base declaration 79 // to allow connections with the app-provided slot. 80 // 81 // Slots dealing with hardware typically will specify 'gadget' and 'core' as 82 // the slot-snap-type (eg, serial-port). Eg: 83 // 84 // slots: 85 // manual-connected-hw-slot: 86 // allow-installation: 87 // slot-snap-type: 88 // - core 89 // - gadget 90 // deny-auto-connection: true 91 // 92 // So called super-privileged slot implementations should also be disallowed 93 // installation on a system and a snap declaration is required to override the 94 // base declaration to allow installation (eg, docker). Eg: 95 // 96 // slots: 97 // manual-connected-super-privileged-slot: 98 // allow-installation: false 99 // deny-connection: true 100 // deny-auto-connection: true 101 // 102 // Like super-privileged slot implementation, super-privileged plugs should 103 // also be disallowed installation on a system and a snap declaration is 104 // required to override the base declaration to allow installation (eg, 105 // kernel-module-control). Eg: 106 // 107 // plugs: 108 // manual-connected-super-privileged-plug: 109 // allow-installation: false 110 // deny-auto-connection: true 111 // (remember this overrides slot side rules) 112 // 113 // Some interfaces have policy that is meant to be used with slot 114 // implementations and on classic images. Since the slot implementation is 115 // privileged, we require a snap declaration to be used for app-provided slot 116 // implementations on non-classic systems (eg, network-manager). Eg: 117 // 118 // slots: 119 // classic-or-not-slot: 120 // allow-installation: 121 // slot-snap-type: 122 // - app 123 // - core 124 // deny-auto-connection: true 125 // deny-connection: 126 // on-classic: false 127 // 128 // Some interfaces have policy that is only used with implicit slots on 129 // classic and should be autoconnected only there (eg, home). Eg: 130 // 131 // slots: 132 // implicit-classic-slot: 133 // allow-installation: 134 // slot-snap-type: 135 // - core 136 // deny-auto-connection: 137 // on-classic: false 138 // 139 140 const baseDeclarationHeader = ` 141 type: base-declaration 142 authority-id: canonical 143 series: 16 144 revision: 0 145 ` 146 147 const baseDeclarationPlugs = ` 148 plugs: 149 ` 150 151 const baseDeclarationSlots = ` 152 slots: 153 ` 154 155 func trimTrailingNewline(s string) string { 156 return strings.TrimRight(s, "\n") 157 } 158 159 func composeBaseDeclaration(ifaces []interfaces.Interface) ([]byte, error) { 160 var buf bytes.Buffer 161 // Trim newlines at the end of the string. All the elements may have 162 // spurious trailing newlines. All elements start with a leading newline. 163 // We don't want any blanks as that would no longer parse. 164 if _, err := buf.WriteString(trimTrailingNewline(baseDeclarationHeader)); err != nil { 165 return nil, err 166 } 167 if _, err := buf.WriteString(trimTrailingNewline(baseDeclarationPlugs)); err != nil { 168 return nil, err 169 } 170 for _, iface := range ifaces { 171 plugPolicy := interfaces.StaticInfoOf(iface).BaseDeclarationPlugs 172 if _, err := buf.WriteString(trimTrailingNewline(plugPolicy)); err != nil { 173 return nil, err 174 } 175 } 176 if _, err := buf.WriteString(trimTrailingNewline(baseDeclarationSlots)); err != nil { 177 return nil, err 178 } 179 for _, iface := range ifaces { 180 slotPolicy := interfaces.StaticInfoOf(iface).BaseDeclarationSlots 181 if _, err := buf.WriteString(trimTrailingNewline(slotPolicy)); err != nil { 182 return nil, err 183 } 184 } 185 if _, err := buf.WriteRune('\n'); err != nil { 186 return nil, err 187 } 188 return buf.Bytes(), nil 189 } 190 191 func init() { 192 decl, err := composeBaseDeclaration(builtin.Interfaces()) 193 if err != nil { 194 panic(fmt.Sprintf("cannot compose base-declaration: %v", err)) 195 } 196 if err := asserts.InitBuiltinBaseDeclaration(decl); err != nil { 197 panic(fmt.Sprintf("cannot initialize the builtin base-declaration: %v", err)) 198 } 199 }