internal/system: integrate PipeWire SecurityContext
All checks were successful
Test / Create distribution (push) Successful in 29s
Test / Sandbox (race detector) (push) Successful in 42s
Test / Sandbox (push) Successful in 43s
Test / Hakurei (push) Successful in 47s
Test / Hakurei (race detector) (push) Successful in 46s
Test / Hpkg (push) Successful in 43s
Test / Flake checks (push) Successful in 1m32s
All checks were successful
Test / Create distribution (push) Successful in 29s
Test / Sandbox (race detector) (push) Successful in 42s
Test / Sandbox (push) Successful in 43s
Test / Hakurei (push) Successful in 47s
Test / Hakurei (race detector) (push) Successful in 46s
Test / Hpkg (push) Successful in 43s
Test / Flake checks (push) Successful in 1m32s
Tests for this Op happens to be the best out of everything due to the robust infrastructure offered by internal/pipewire. This is now ready to use in internal/outcome for implementing #26. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
99
internal/system/pipewire.go
Normal file
99
internal/system/pipewire.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"hakurei.app/container/check"
|
||||
"hakurei.app/hst"
|
||||
"hakurei.app/internal/acl"
|
||||
"hakurei.app/internal/pipewire"
|
||||
)
|
||||
|
||||
// PipeWire maintains a pipewire socket with SecurityContext attached via [pipewire].
|
||||
// The socket stops accepting connections once the pipe referred to by sync is closed.
|
||||
// The socket is pathname only and is destroyed on revert.
|
||||
func (sys *I) PipeWire(dst *check.Absolute) *I {
|
||||
sys.ops = append(sys.ops, &pipewireOp{nil, dst})
|
||||
return sys
|
||||
}
|
||||
|
||||
// pipewireOp implements [I.PipeWire].
|
||||
type pipewireOp struct {
|
||||
scc io.Closer
|
||||
dst *check.Absolute
|
||||
}
|
||||
|
||||
func (p *pipewireOp) Type() hst.Enablement { return Process }
|
||||
|
||||
func (p *pipewireOp) apply(sys *I) (err error) {
|
||||
var ctx *pipewire.Context
|
||||
if ctx, err = sys.pipewireConnect(); err != nil {
|
||||
return newOpError("pipewire", err, false)
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := ctx.Close(); closeErr != nil && err == nil {
|
||||
err = newOpError("pipewire", closeErr, false)
|
||||
}
|
||||
}()
|
||||
|
||||
sys.msg.Verbosef("pipewire pathname socket on %q", p.dst)
|
||||
|
||||
var registry *pipewire.Registry
|
||||
if registry, err = ctx.GetRegistry(); err != nil {
|
||||
return newOpError("pipewire", err, false)
|
||||
} else if err = ctx.GetCore().Sync(); err != nil {
|
||||
return newOpError("pipewire", err, false)
|
||||
}
|
||||
|
||||
var securityContext *pipewire.SecurityContext
|
||||
if securityContext, err = registry.GetSecurityContext(); err != nil {
|
||||
return newOpError("pipewire", err, false)
|
||||
} else if err = ctx.Roundtrip(); err != nil {
|
||||
return newOpError("pipewire", err, false)
|
||||
}
|
||||
|
||||
if p.scc, err = securityContext.BindAndCreate(p.dst.String(), pipewire.SPADict{
|
||||
{Key: pipewire.PW_KEY_SEC_ENGINE, Value: "app.hakurei"},
|
||||
{Key: pipewire.PW_KEY_ACCESS, Value: "restricted"},
|
||||
}); err != nil {
|
||||
return newOpError("pipewire", err, false)
|
||||
} else if err = ctx.GetCore().Sync(); err != nil {
|
||||
_ = p.scc.Close()
|
||||
return newOpError("pipewire", err, false)
|
||||
}
|
||||
|
||||
if err = sys.chmod(p.dst.String(), 0); err != nil {
|
||||
if closeErr := p.scc.Close(); closeErr != nil {
|
||||
return newOpError("pipewire", errors.Join(err, closeErr), false)
|
||||
}
|
||||
return newOpError("pipewire", err, false)
|
||||
}
|
||||
|
||||
if err = sys.aclUpdate(p.dst.String(), sys.uid, acl.Read, acl.Write, acl.Execute); err != nil {
|
||||
if closeErr := p.scc.Close(); closeErr != nil {
|
||||
return newOpError("pipewire", errors.Join(err, closeErr), false)
|
||||
}
|
||||
return newOpError("pipewire", err, false)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pipewireOp) revert(sys *I, _ *Criteria) error {
|
||||
if p.scc != nil {
|
||||
sys.msg.Verbosef("hanging up pipewire socket on %q", p.dst)
|
||||
return newOpError("pipewire", p.scc.Close(), true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pipewireOp) Is(o Op) bool {
|
||||
target, ok := o.(*pipewireOp)
|
||||
return ok && p != nil && target != nil &&
|
||||
p.dst.Is(target.dst)
|
||||
}
|
||||
|
||||
func (p *pipewireOp) Path() string { return p.dst.String() }
|
||||
func (p *pipewireOp) String() string { return fmt.Sprintf("pipewire socket at %q", p.dst) }
|
||||
Reference in New Issue
Block a user