Skip to content

Commit e1edd80

Browse files
authored
Merge pull request #1456 from marmijo/systemd_storage_conflict
config/types: prevent files/links/dirs from conflicting with systemd units or dropins
2 parents 8770e14 + 2f63faa commit e1edd80

File tree

12 files changed

+1492
-0
lines changed

12 files changed

+1492
-0
lines changed

config/shared/errors/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ var (
8383
ErrDuplicateLabels = errors.New("cannot use the same partition label twice")
8484
ErrInvalidProxy = errors.New("proxies must be http(s)")
8585
ErrInsecureProxy = errors.New("insecure plaintext HTTP proxy specified for HTTPS resources")
86+
ErrPathConflictsSystemd = errors.New("path conflicts with systemd unit or dropin")
8687

8788
// Systemd section errors
8889
ErrInvalidSystemdExt = errors.New("invalid systemd unit extension")

config/v3_0/types/config.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
package types
1616

1717
import (
18+
"github.com/coreos/ignition/v2/config/shared/errors"
19+
"github.com/coreos/ignition/v2/config/util"
20+
1821
"github.com/coreos/go-semver/semver"
22+
"github.com/coreos/vcontext/path"
23+
"github.com/coreos/vcontext/report"
1924
)
2025

2126
var (
@@ -24,3 +29,36 @@ var (
2429
Minor: 0,
2530
}
2631
)
32+
33+
func (cfg Config) Validate(c path.ContextPath) (r report.Report) {
34+
systemdPath := "/etc/systemd/system/"
35+
unitPaths := map[string]struct{}{}
36+
for _, unit := range cfg.Systemd.Units {
37+
if !util.NilOrEmpty(unit.Contents) {
38+
pathString := systemdPath + unit.Name
39+
unitPaths[pathString] = struct{}{}
40+
}
41+
for _, dropin := range unit.Dropins {
42+
if !util.NilOrEmpty(dropin.Contents) {
43+
pathString := systemdPath + unit.Name + ".d/" + dropin.Name
44+
unitPaths[pathString] = struct{}{}
45+
}
46+
}
47+
}
48+
for i, f := range cfg.Storage.Files {
49+
if _, exists := unitPaths[f.Path]; exists {
50+
r.AddOnError(c.Append("storage", "files", i, "path"), errors.ErrPathConflictsSystemd)
51+
}
52+
}
53+
for i, d := range cfg.Storage.Directories {
54+
if _, exists := unitPaths[d.Path]; exists {
55+
r.AddOnError(c.Append("storage", "directories", i, "path"), errors.ErrPathConflictsSystemd)
56+
}
57+
}
58+
for i, l := range cfg.Storage.Links {
59+
if _, exists := unitPaths[l.Path]; exists {
60+
r.AddOnError(c.Append("storage", "links", i, "path"), errors.ErrPathConflictsSystemd)
61+
}
62+
}
63+
return
64+
}

config/v3_0/types/config_test.go

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
// Copyright 2020 Red Hat, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package types
16+
17+
import (
18+
"reflect"
19+
"testing"
20+
21+
"github.com/coreos/ignition/v2/config/shared/errors"
22+
"github.com/coreos/ignition/v2/config/util"
23+
24+
"github.com/coreos/vcontext/path"
25+
"github.com/coreos/vcontext/report"
26+
)
27+
28+
func TestConfigValidation(t *testing.T) {
29+
tests := []struct {
30+
in Config
31+
out error
32+
at path.ContextPath
33+
}{
34+
// test 0: file conflicts with systemd dropin file, error
35+
{
36+
in: Config{
37+
Storage: Storage{
38+
Files: []File{
39+
{
40+
Node: Node{Path: "/etc/systemd/system/foo.service.d/bar.conf"},
41+
},
42+
},
43+
},
44+
Systemd: Systemd{
45+
Units: []Unit{
46+
{
47+
Name: "foo.service",
48+
Dropins: []Dropin{
49+
{
50+
Name: "bar.conf",
51+
Contents: util.StrToPtr("[Foo]\nQux=Bar"),
52+
},
53+
},
54+
},
55+
},
56+
},
57+
},
58+
out: errors.ErrPathConflictsSystemd,
59+
at: path.New("json", "storage", "files", 0, "path"),
60+
},
61+
// test 1: file conflicts with systemd unit, error
62+
{
63+
in: Config{
64+
Storage: Storage{
65+
Files: []File{
66+
{
67+
Node: Node{Path: "/etc/systemd/system/foo.service"},
68+
},
69+
},
70+
},
71+
Systemd: Systemd{
72+
Units: []Unit{
73+
{
74+
Name: "foo.service",
75+
Contents: util.StrToPtr("[Foo]\nQux=Bar"),
76+
Enabled: util.BoolToPtr(true),
77+
},
78+
},
79+
},
80+
},
81+
out: errors.ErrPathConflictsSystemd,
82+
at: path.New("json", "storage", "files", 0, "path"),
83+
},
84+
// test 2: directory conflicts with systemd dropin file, error
85+
{
86+
in: Config{
87+
Storage: Storage{
88+
Directories: []Directory{
89+
{
90+
Node: Node{Path: "/etc/systemd/system/foo.service.d/bar.conf"},
91+
},
92+
},
93+
},
94+
Systemd: Systemd{
95+
[]Unit{
96+
{
97+
Name: "foo.service",
98+
Dropins: []Dropin{
99+
{
100+
Name: "bar.conf",
101+
Contents: util.StrToPtr("[Foo]\nQux=Bar"),
102+
},
103+
},
104+
},
105+
},
106+
},
107+
},
108+
out: errors.ErrPathConflictsSystemd,
109+
at: path.New("json", "storage", "directories", 0, "path"),
110+
},
111+
// test 3: directory conflicts with systemd unit, error
112+
{
113+
in: Config{
114+
Storage: Storage{
115+
Directories: []Directory{
116+
{
117+
Node: Node{Path: "/etc/systemd/system/foo.service"},
118+
},
119+
},
120+
},
121+
Systemd: Systemd{
122+
[]Unit{
123+
{
124+
Name: "foo.service",
125+
Contents: util.StrToPtr("[foo]\nQux=Baz"),
126+
Enabled: util.BoolToPtr(true),
127+
},
128+
},
129+
},
130+
},
131+
out: errors.ErrPathConflictsSystemd,
132+
at: path.New("json", "storage", "directories", 0, "path"),
133+
},
134+
// test 4: link conflicts with systemd dropin file, error
135+
{
136+
in: Config{
137+
Storage: Storage{
138+
Links: []Link{
139+
{
140+
Node: Node{Path: "/etc/systemd/system/foo.service.d/bar.conf"},
141+
LinkEmbedded1: LinkEmbedded1{Target: "/qux.conf"},
142+
},
143+
},
144+
},
145+
Systemd: Systemd{
146+
[]Unit{
147+
{
148+
Name: "foo.service",
149+
Dropins: []Dropin{
150+
{
151+
Name: "bar.conf",
152+
Contents: util.StrToPtr("[Foo]\nQux=Bar"),
153+
},
154+
},
155+
},
156+
},
157+
},
158+
},
159+
out: errors.ErrPathConflictsSystemd,
160+
at: path.New("json", "storage", "links", 0, "path"),
161+
},
162+
// test 5: link conflicts with systemd unit, error
163+
{
164+
in: Config{
165+
Storage: Storage{
166+
Links: []Link{
167+
{
168+
Node: Node{Path: "/etc/systemd/system/foo.service"},
169+
LinkEmbedded1: LinkEmbedded1{Target: "/qux.conf"},
170+
},
171+
},
172+
},
173+
Systemd: Systemd{
174+
[]Unit{
175+
{
176+
Name: "foo.service",
177+
Contents: util.StrToPtr("[foo]\nQux=Baz"),
178+
Enabled: util.BoolToPtr(true),
179+
},
180+
},
181+
},
182+
},
183+
out: errors.ErrPathConflictsSystemd,
184+
at: path.New("json", "storage", "links", 0, "path"),
185+
},
186+
// test 6: non-conflicting scenarios
187+
{
188+
in: Config{
189+
Storage: Storage{
190+
Files: []File{
191+
{
192+
Node: Node{Path: "/etc/systemd/system/bar.service.d/baz.conf"},
193+
},
194+
{
195+
Node: Node{Path: "/etc/systemd/system/bar.service"},
196+
},
197+
{
198+
Node: Node{Path: "/etc/systemd/system/foo.service.d/qux.conf"},
199+
},
200+
},
201+
Links: []Link{
202+
{
203+
Node: Node{Path: "/etc/systemd/system/qux.service"},
204+
LinkEmbedded1: LinkEmbedded1{Target: "/qux.conf"},
205+
},
206+
{
207+
Node: Node{Path: "/etc/systemd/system/quux.service.d/foo.conf"},
208+
LinkEmbedded1: LinkEmbedded1{Target: "/foo.conf"},
209+
},
210+
},
211+
Directories: []Directory{
212+
{
213+
Node: Node{Path: "/etc/systemd/system/quux.service.d"},
214+
},
215+
},
216+
},
217+
Systemd: Systemd{
218+
Units: []Unit{
219+
{
220+
Name: "foo.service",
221+
Contents: util.StrToPtr("[Foo]\nQux=Baz"),
222+
Enabled: util.BoolToPtr(true),
223+
},
224+
{
225+
Name: "bar.service",
226+
Dropins: []Dropin{
227+
{
228+
Name: "baz.conf",
229+
},
230+
},
231+
Enabled: util.BoolToPtr(true),
232+
},
233+
{
234+
Name: "qux.service",
235+
Dropins: []Dropin{
236+
{
237+
Name: "bar.conf",
238+
Contents: util.StrToPtr("[Foo]\nQux=Baz"),
239+
},
240+
},
241+
},
242+
{
243+
Name: "quux.service",
244+
Contents: util.StrToPtr("[Foo]\nQux=Baz"),
245+
Enabled: util.BoolToPtr(true),
246+
},
247+
},
248+
},
249+
},
250+
},
251+
}
252+
for i, test := range tests {
253+
r := test.in.Validate(path.New("json"))
254+
expected := report.Report{}
255+
expected.AddOnError(test.at, test.out)
256+
if !reflect.DeepEqual(expected, r) {
257+
t.Errorf("#%d: bad error: expected : %v, got %v", i, expected, r)
258+
}
259+
}
260+
}

config/v3_1/types/config.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
package types
1616

1717
import (
18+
"github.com/coreos/ignition/v2/config/shared/errors"
19+
"github.com/coreos/ignition/v2/config/util"
20+
1821
"github.com/coreos/go-semver/semver"
22+
"github.com/coreos/vcontext/path"
23+
"github.com/coreos/vcontext/report"
1924
)
2025

2126
var (
@@ -24,3 +29,36 @@ var (
2429
Minor: 1,
2530
}
2631
)
32+
33+
func (cfg Config) Validate(c path.ContextPath) (r report.Report) {
34+
systemdPath := "/etc/systemd/system/"
35+
unitPaths := map[string]struct{}{}
36+
for _, unit := range cfg.Systemd.Units {
37+
if !util.NilOrEmpty(unit.Contents) {
38+
pathString := systemdPath + unit.Name
39+
unitPaths[pathString] = struct{}{}
40+
}
41+
for _, dropin := range unit.Dropins {
42+
if !util.NilOrEmpty(dropin.Contents) {
43+
pathString := systemdPath + unit.Name + ".d/" + dropin.Name
44+
unitPaths[pathString] = struct{}{}
45+
}
46+
}
47+
}
48+
for i, f := range cfg.Storage.Files {
49+
if _, exists := unitPaths[f.Path]; exists {
50+
r.AddOnError(c.Append("storage", "files", i, "path"), errors.ErrPathConflictsSystemd)
51+
}
52+
}
53+
for i, d := range cfg.Storage.Directories {
54+
if _, exists := unitPaths[d.Path]; exists {
55+
r.AddOnError(c.Append("storage", "directories", i, "path"), errors.ErrPathConflictsSystemd)
56+
}
57+
}
58+
for i, l := range cfg.Storage.Links {
59+
if _, exists := unitPaths[l.Path]; exists {
60+
r.AddOnError(c.Append("storage", "links", i, "path"), errors.ErrPathConflictsSystemd)
61+
}
62+
}
63+
return
64+
}

0 commit comments

Comments
 (0)