Skip to content

Commit 5596177

Browse files
committed
validate that caps can't be in weird places
1 parent ef7af3a commit 5596177

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

artifacts.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package dalec
22

33
import (
4+
"errors"
5+
"fmt"
46
"io/fs"
57
"maps"
68
"path/filepath"
@@ -254,3 +256,33 @@ func (a Artifacts) HasDocs() bool {
254256
}
255257
return false
256258
}
259+
260+
// validate checks for errors in artifact configuration
261+
func (a *Artifacts) validate() error {
262+
var errs []error
263+
264+
// Check for capabilities on non-executable artifacts
265+
checkCapabilities := func(artifactType string, artifacts map[string]ArtifactConfig) {
266+
for path, cfg := range artifacts {
267+
if len(cfg.Capabilities) > 0 {
268+
errs = append(errs, fmt.Errorf("capabilities can only be set on executable files (binaries, libs, libexec); cannot set capabilities on %s '%s'", artifactType, path))
269+
}
270+
}
271+
}
272+
273+
// These artifact types should not have capabilities
274+
checkCapabilities("manpages", a.Manpages)
275+
checkCapabilities("data_dirs", a.DataDirs)
276+
checkCapabilities("configFiles", a.ConfigFiles)
277+
checkCapabilities("docs", a.Docs)
278+
checkCapabilities("licenses", a.Licenses)
279+
checkCapabilities("headers", a.Headers)
280+
281+
// Note: We don't error for Binaries, Libs, or Libexec as these are executable
282+
// and capabilities are appropriate for them
283+
284+
if len(errs) > 0 {
285+
return errors.Join(errs...)
286+
}
287+
return nil
288+
}

load.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ func (s Spec) Validate() error {
575575
errs = append(errs, errors.Wrap(err, "build"))
576576
}
577577

578+
if err := s.Artifacts.validate(); err != nil {
579+
errs = append(errs, errors.Wrap(err, "artifacts"))
580+
}
581+
578582
return goerrors.Join(errs...)
579583
}
580584

load_test.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,6 +2039,171 @@ func TestArtifactBuildValidation(t *testing.T) {
20392039
}
20402040
}
20412041

2042+
func TestArtifactsValidation(t *testing.T) {
2043+
cases := []struct {
2044+
name string
2045+
artifacts Artifacts
2046+
expectErr string
2047+
}{
2048+
{
2049+
name: "capabilities on binaries is valid",
2050+
artifacts: Artifacts{
2051+
Binaries: map[string]ArtifactConfig{
2052+
"/tmp/mybinary": {
2053+
Capabilities: []ArtifactCapability{
2054+
{Name: "cap_net_raw", Effective: true, Permitted: true},
2055+
},
2056+
},
2057+
},
2058+
},
2059+
},
2060+
{
2061+
name: "capabilities on libs is valid",
2062+
artifacts: Artifacts{
2063+
Libs: map[string]ArtifactConfig{
2064+
"/tmp/mylib.so": {
2065+
Capabilities: []ArtifactCapability{
2066+
{Name: "cap_net_raw", Effective: true},
2067+
},
2068+
},
2069+
},
2070+
},
2071+
},
2072+
{
2073+
name: "capabilities on libexec is valid",
2074+
artifacts: Artifacts{
2075+
Libexec: map[string]ArtifactConfig{
2076+
"/tmp/helper": {
2077+
Capabilities: []ArtifactCapability{
2078+
{Name: "cap_net_bind_service", Effective: true, Permitted: true},
2079+
},
2080+
},
2081+
},
2082+
},
2083+
},
2084+
{
2085+
name: "capabilities on docs is invalid",
2086+
artifacts: Artifacts{
2087+
Docs: map[string]ArtifactConfig{
2088+
"README.md": {
2089+
Capabilities: []ArtifactCapability{
2090+
{Name: "cap_net_raw", Effective: true},
2091+
},
2092+
},
2093+
},
2094+
},
2095+
expectErr: "cannot set capabilities on docs 'README.md'",
2096+
},
2097+
{
2098+
name: "capabilities on configFiles is invalid",
2099+
artifacts: Artifacts{
2100+
ConfigFiles: map[string]ArtifactConfig{
2101+
"config.yaml": {
2102+
Capabilities: []ArtifactCapability{
2103+
{Name: "cap_net_bind_service", Effective: true},
2104+
},
2105+
},
2106+
},
2107+
},
2108+
expectErr: "cannot set capabilities on configFiles 'config.yaml'",
2109+
},
2110+
{
2111+
name: "capabilities on manpages is invalid",
2112+
artifacts: Artifacts{
2113+
Manpages: map[string]ArtifactConfig{
2114+
"tool.1": {
2115+
Capabilities: []ArtifactCapability{
2116+
{Name: "cap_net_raw", Effective: true},
2117+
},
2118+
},
2119+
},
2120+
},
2121+
expectErr: "cannot set capabilities on manpages 'tool.1'",
2122+
},
2123+
{
2124+
name: "capabilities on data_dirs is invalid",
2125+
artifacts: Artifacts{
2126+
DataDirs: map[string]ArtifactConfig{
2127+
"data": {
2128+
Capabilities: []ArtifactCapability{
2129+
{Name: "cap_net_raw", Effective: true},
2130+
},
2131+
},
2132+
},
2133+
},
2134+
expectErr: "cannot set capabilities on data_dirs 'data'",
2135+
},
2136+
{
2137+
name: "capabilities on licenses is invalid",
2138+
artifacts: Artifacts{
2139+
Licenses: map[string]ArtifactConfig{
2140+
"LICENSE": {
2141+
Capabilities: []ArtifactCapability{
2142+
{Name: "cap_net_raw", Effective: true},
2143+
},
2144+
},
2145+
},
2146+
},
2147+
expectErr: "cannot set capabilities on licenses 'LICENSE'",
2148+
},
2149+
{
2150+
name: "capabilities on headers is invalid",
2151+
artifacts: Artifacts{
2152+
Headers: map[string]ArtifactConfig{
2153+
"myheader.h": {
2154+
Capabilities: []ArtifactCapability{
2155+
{Name: "cap_net_raw", Effective: true},
2156+
},
2157+
},
2158+
},
2159+
},
2160+
expectErr: "cannot set capabilities on headers 'myheader.h'",
2161+
},
2162+
{
2163+
name: "multiple capability errors",
2164+
artifacts: Artifacts{
2165+
Docs: map[string]ArtifactConfig{
2166+
"README.md": {
2167+
Capabilities: []ArtifactCapability{
2168+
{Name: "cap_net_raw", Effective: true},
2169+
},
2170+
},
2171+
},
2172+
ConfigFiles: map[string]ArtifactConfig{
2173+
"config.yaml": {
2174+
Capabilities: []ArtifactCapability{
2175+
{Name: "cap_net_bind_service", Effective: true},
2176+
},
2177+
},
2178+
},
2179+
},
2180+
expectErr: "cannot set capabilities on",
2181+
},
2182+
{
2183+
name: "no capabilities is valid",
2184+
artifacts: Artifacts{
2185+
Binaries: map[string]ArtifactConfig{
2186+
"/tmp/mybinary": {},
2187+
},
2188+
Docs: map[string]ArtifactConfig{
2189+
"README.md": {},
2190+
},
2191+
},
2192+
},
2193+
}
2194+
2195+
for _, tc := range cases {
2196+
t.Run(tc.name, func(t *testing.T) {
2197+
err := tc.artifacts.validate()
2198+
if tc.expectErr == "" {
2199+
assert.NilError(t, err)
2200+
} else {
2201+
assert.ErrorContains(t, err, tc.expectErr)
2202+
}
2203+
})
2204+
}
2205+
}
2206+
20422207
func FuzzLoad(f *testing.F) {
20432208
// Add some initial test cases
20442209
f.Add("name: test\n")

0 commit comments

Comments
 (0)