mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
* interfaces: introduce SnapAppSet and forward one to the security backends
* snap: implement methods on snap.Info for getting apps and hooks for slots and plugs
This will enable us to remove the Hooks fields from the SlotInfo and
PlugInfo structs.
* interfaces: implement methods on SnapAppSet in terms of methods on snap.Info
* snap, interfaces: replace usage of {Plug,Slot}Info.SecurityTags with methods on SnapAppSet
* i/builtin: replace slotAppLabelExpr and plugAppLabelExpr with corresponding methods on SnapAppSet
* snap, o/snapstate, interfaces: remove Hooks field on snap.PlugInfo and snap.SlotInfo
* builtin, interfaces: fix tests that use Specification that now have a SnapAppSet
* snap: add tests for new methods on Info
* interfaces, i/builtin: port over some tests for SnapAppSet methods {Plug,Slot}LabelExpression
* interfaces: test PlugSecurityTags and SlotSecurityTags methods
* interfaces: add doc comments to SnapAppSet and methods
* i/builtin: remove ported over tests
* interfaces, many: require that SnapAppSet methods for getting security tags are called with plug/slot that comes from correct snap
Many tests did not properly adhere to this requirment, so they had to be
modifed to modify this rule.
Additionally, a hack was inroduced in the methods for getting label
expressions on the SnapAppSet. If a plug/slot did not originate from the
same snap that the SnapAppSet was created from, then we will use the
snap.Info that the plug/slot carries in the method instead. This will
fail to work once component hooks are introduced, so this will need to
be resolved by then.
* interfaces: test fallback for using LabelExpr methods with mismatch plug/slot
* snap: correct placement of TODOs to preserve doc comments
* snap: add doc comments for Plug/Slot.Unscoped
* interfaces: test for using SecurityTagsForPlug and SecurityTagsForSlot with wrong snap
* interfaces: tweak error messages in SnapAppSet SecurityTags methods
* i/builtin: fix missed conflict
* i/apparmor: add doc comment to Specification.appSet
* snap: fix doc coment on PlugInfo.Unscoped
162 lines
4.8 KiB
Go
162 lines
4.8 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2017 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
package dbus
|
|
|
|
import (
|
|
"bytes"
|
|
"sort"
|
|
|
|
"github.com/snapcore/snapd/interfaces"
|
|
"github.com/snapcore/snapd/snap"
|
|
)
|
|
|
|
// Specification keeps all the dbus snippets.
|
|
type Specification struct {
|
|
// Snippets are indexed by security tag.
|
|
appSet *interfaces.SnapAppSet
|
|
snippets map[string][]string
|
|
securityTags []string
|
|
}
|
|
|
|
func NewSpecification(appSet *interfaces.SnapAppSet) *Specification {
|
|
return &Specification{appSet: appSet}
|
|
}
|
|
|
|
func (spec *Specification) SnapAppSet() *interfaces.SnapAppSet {
|
|
return spec.appSet
|
|
}
|
|
|
|
// AddSnippet adds a new dbus snippet.
|
|
func (spec *Specification) AddSnippet(snippet string) {
|
|
if len(spec.securityTags) == 0 {
|
|
return
|
|
}
|
|
if spec.snippets == nil {
|
|
spec.snippets = make(map[string][]string)
|
|
}
|
|
for _, tag := range spec.securityTags {
|
|
spec.snippets[tag] = append(spec.snippets[tag], snippet)
|
|
}
|
|
}
|
|
|
|
// Snippets returns a deep copy of all the added snippets.
|
|
func (spec *Specification) Snippets() map[string][]string {
|
|
result := make(map[string][]string, len(spec.snippets))
|
|
for k, v := range spec.snippets {
|
|
result[k] = append([]string(nil), v...)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// SnippetForTag returns a combined snippet for given security tag with individual snippets
|
|
// joined with newline character. Empty string is returned for non-existing security tag.
|
|
func (spec *Specification) SnippetForTag(tag string) string {
|
|
var buffer bytes.Buffer
|
|
for _, snippet := range spec.snippets[tag] {
|
|
buffer.WriteString(snippet)
|
|
buffer.WriteRune('\n')
|
|
}
|
|
return buffer.String()
|
|
}
|
|
|
|
// SecurityTags returns a list of security tags which have a snippet.
|
|
func (spec *Specification) SecurityTags() []string {
|
|
var tags []string
|
|
for t := range spec.snippets {
|
|
tags = append(tags, t)
|
|
}
|
|
sort.Strings(tags)
|
|
return tags
|
|
}
|
|
|
|
// Implementation of methods required by interfaces.Specification
|
|
|
|
// AddConnectedPlug records dbus-specific side-effects of having a connected plug.
|
|
func (spec *Specification) AddConnectedPlug(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
|
|
type definer interface {
|
|
DBusConnectedPlug(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
|
|
}
|
|
if iface, ok := iface.(definer); ok {
|
|
tags, err := spec.appSet.SecurityTagsForConnectedPlug(plug)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
spec.securityTags = tags
|
|
defer func() { spec.securityTags = nil }()
|
|
return iface.DBusConnectedPlug(spec, plug, slot)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AddConnectedSlot records dbus-specific side-effects of having a connected slot.
|
|
func (spec *Specification) AddConnectedSlot(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
|
|
type definer interface {
|
|
DBusConnectedSlot(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
|
|
}
|
|
if iface, ok := iface.(definer); ok {
|
|
tags, err := spec.appSet.SecurityTagsForConnectedSlot(slot)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
spec.securityTags = tags
|
|
defer func() { spec.securityTags = nil }()
|
|
return iface.DBusConnectedSlot(spec, plug, slot)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AddPermanentPlug records dbus-specific side-effects of having a plug.
|
|
func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {
|
|
type definer interface {
|
|
DBusPermanentPlug(spec *Specification, plug *snap.PlugInfo) error
|
|
}
|
|
if iface, ok := iface.(definer); ok {
|
|
tags, err := spec.appSet.SecurityTagsForPlug(plug)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
spec.securityTags = tags
|
|
defer func() { spec.securityTags = nil }()
|
|
return iface.DBusPermanentPlug(spec, plug)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AddPermanentSlot records dbus-specific side-effects of having a slot.
|
|
func (spec *Specification) AddPermanentSlot(iface interfaces.Interface, slot *snap.SlotInfo) error {
|
|
type definer interface {
|
|
DBusPermanentSlot(spec *Specification, slot *snap.SlotInfo) error
|
|
}
|
|
if iface, ok := iface.(definer); ok {
|
|
tags, err := spec.appSet.SecurityTagsForSlot(slot)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
spec.securityTags = tags
|
|
defer func() { spec.securityTags = nil }()
|
|
return iface.DBusPermanentSlot(spec, slot)
|
|
}
|
|
return nil
|
|
}
|