Skip to content

Commit 3b1714d

Browse files
JoshVanLelena-kolevska
authored andcommitted
Disk Loader: Scope filtering (dapr#7616)
* Disk Loader: Scope filtering Adds scope filtering to the disk manifest loader. Though this doesn't have any security benefits, it does mean manifests are filtered much sooner in the runtime when running in self-hosted mode and prevents logging/errors downstream in modules like the hot reloading reconciler. Signed-off-by: joshvanl <[email protected]> * Update internal disk loader unit test with Options param Signed-off-by: joshvanl <[email protected]> * Pass appID to hotreload disk loader for scope filtering Signed-off-by: joshvanl <[email protected]> --------- Signed-off-by: joshvanl <[email protected]> Signed-off-by: Elena Kolevska <[email protected]>
1 parent a159be8 commit 3b1714d

File tree

11 files changed

+271
-30
lines changed

11 files changed

+271
-30
lines changed

pkg/internal/loader/disk/components.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ import (
1818
"github.com/dapr/dapr/pkg/internal/loader"
1919
)
2020

21-
func NewComponents(paths ...string) loader.Loader[compapi.Component] {
22-
return new[compapi.Component](paths...)
21+
func NewComponents(opts Options) loader.Loader[compapi.Component] {
22+
return new[compapi.Component](opts)
2323
}

pkg/internal/loader/disk/disk.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/dapr/dapr/pkg/runtime/meta"
2323
"github.com/dapr/dapr/pkg/security"
24+
"github.com/dapr/dapr/utils"
2425
)
2526

2627
// disk loads a specific manifest kind from a folder.
@@ -29,16 +30,23 @@ type disk[T meta.Resource] struct {
2930
apiVersion string
3031
dirs []string
3132
namespace string
33+
appID string
34+
}
35+
36+
type Options struct {
37+
AppID string
38+
Paths []string
3239
}
3340

3441
// new creates a new manifest loader for the given paths and kind.
35-
func new[T meta.Resource](dirs ...string) *disk[T] {
42+
func new[T meta.Resource](opts Options) *disk[T] {
3643
var zero T
3744
return &disk[T]{
38-
dirs: dirs,
45+
dirs: opts.Paths,
3946
kind: zero.Kind(),
4047
apiVersion: zero.APIVersion(),
4148
namespace: security.CurrentNamespace(),
49+
appID: opts.AppID,
4250
}
4351
}
4452

@@ -52,7 +60,7 @@ func (d *disk[T]) Load(context.Context) ([]T, error) {
5260
nsDefined := len(os.Getenv("NAMESPACE")) != 0
5361

5462
names := make(map[string]string)
55-
goodManifests := make([]T, 0)
63+
filteredManifests := make([]T, 0)
5664
var errs []error
5765
for i := range set.ts {
5866
// If the process or manifest namespace are not defined, ignore the
@@ -70,15 +78,21 @@ func (d *disk[T]) Load(context.Context) ([]T, error) {
7078
continue
7179
}
7280

81+
// Skip manifests which are not in scope
82+
scopes := set.ts[i].GetScopes()
83+
if !(len(scopes) == 0 || utils.Contains(scopes, d.appID)) {
84+
continue
85+
}
86+
7387
names[set.ts[i].GetName()] = set.ts[i].LogName()
74-
goodManifests = append(goodManifests, set.ts[i])
88+
filteredManifests = append(filteredManifests, set.ts[i])
7589
}
7690

7791
if len(errs) > 0 {
7892
return nil, errors.Join(errs...)
7993
}
8094

81-
return goodManifests, nil
95+
return filteredManifests, nil
8296
}
8397

8498
func (d *disk[T]) loadWithOrder() (*manifestSet[T], error) {

pkg/internal/loader/disk/disk_test.go

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ import (
2626
"github.com/stretchr/testify/require"
2727
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2828

29+
"github.com/dapr/dapr/pkg/apis/common"
2930
compapi "github.com/dapr/dapr/pkg/apis/components/v1alpha1"
3031
"github.com/dapr/kit/ptr"
3132
)
3233

3334
func TestLoad(t *testing.T) {
3435
t.Run("valid yaml content", func(t *testing.T) {
3536
tmp := t.TempDir()
36-
request := NewComponents(tmp)
37+
request := NewComponents(Options{
38+
Paths: []string{tmp},
39+
})
3740
filename := "test-component-valid.yaml"
3841
yaml := `
3942
apiVersion: dapr.io/v1alpha1
@@ -56,7 +59,9 @@ spec:
5659

5760
t.Run("invalid yaml head", func(t *testing.T) {
5861
tmp := t.TempDir()
59-
request := NewComponents(tmp)
62+
request := NewComponents(Options{
63+
Paths: []string{tmp},
64+
})
6065

6166
filename := "test-component-invalid.yaml"
6267
yaml := `
@@ -72,23 +77,29 @@ name: statestore`
7277
})
7378

7479
t.Run("load components file not exist", func(t *testing.T) {
75-
request := NewComponents("test-path-no-exists")
80+
request := NewComponents(Options{
81+
Paths: []string{"test-path-no-exists"},
82+
})
7683

7784
components, err := request.Load(context.Background())
7885
require.Error(t, err)
7986
assert.Empty(t, components)
8087
})
8188

8289
t.Run("error and namespace", func(t *testing.T) {
83-
buildComp := func(name string, namespace *string) string {
90+
buildComp := func(name string, namespace *string, scopes ...string) string {
8491
var ns string
8592
if namespace != nil {
8693
ns = fmt.Sprintf("\n namespace: %s\n", *namespace)
8794
}
95+
var scopeS string
96+
if len(scopes) > 0 {
97+
scopeS = fmt.Sprintf("\nscopes:\n- %s", strings.Join(scopes, "\n- "))
98+
}
8899
return fmt.Sprintf(`apiVersion: dapr.io/v1alpha1
89100
kind: Component
90101
metadata:
91-
name: %s%s`, name, ns)
102+
name: %s%s%s`, name, ns, scopeS)
92103
}
93104

94105
tests := map[string]struct {
@@ -183,6 +194,26 @@ metadata:
183194
},
184195
expErr: false,
185196
},
197+
"only return manifests in scope": {
198+
comps: []string{
199+
buildComp("comp1", nil, "myappid"),
200+
buildComp("comp2", nil, "myappid", "anotherappid"),
201+
buildComp("comp3", nil, "anotherappid"),
202+
},
203+
namespace: ptr.Of("foo"),
204+
expComps: []compapi.Component{
205+
{
206+
TypeMeta: metav1.TypeMeta{APIVersion: "dapr.io/v1alpha1", Kind: "Component"},
207+
ObjectMeta: metav1.ObjectMeta{Name: "comp1", Namespace: ""},
208+
Scoped: common.Scoped{Scopes: []string{"myappid"}},
209+
},
210+
{
211+
TypeMeta: metav1.TypeMeta{APIVersion: "dapr.io/v1alpha1", Kind: "Component"},
212+
ObjectMeta: metav1.ObjectMeta{Name: "comp2", Namespace: ""},
213+
Scoped: common.Scoped{Scopes: []string{"myappid", "anotherappid"}},
214+
},
215+
},
216+
},
186217
}
187218

188219
for name, test := range tests {
@@ -195,7 +226,10 @@ metadata:
195226
if test.namespace != nil {
196227
t.Setenv("NAMESPACE", *test.namespace)
197228
}
198-
loader := NewComponents(tmp)
229+
loader := NewComponents(Options{
230+
Paths: []string{tmp},
231+
AppID: "myappid",
232+
})
199233
components, err := loader.Load(context.Background())
200234
assert.Equal(t, test.expErr, err != nil, "%v", err)
201235
assert.Equal(t, test.expComps, components)
@@ -207,7 +241,7 @@ metadata:
207241
func Test_loadWithOrder(t *testing.T) {
208242
t.Run("no file should return empty set", func(t *testing.T) {
209243
tmp := t.TempDir()
210-
d := NewComponents(tmp).(*disk[compapi.Component])
244+
d := NewComponents(Options{Paths: []string{tmp}}).(*disk[compapi.Component])
211245
set, err := d.loadWithOrder()
212246
require.NoError(t, err)
213247
assert.Empty(t, set.order)
@@ -225,7 +259,7 @@ spec:
225259
type: state.couchbase
226260
`), fs.FileMode(0o600)))
227261

228-
d := NewComponents(tmp).(*disk[compapi.Component])
262+
d := NewComponents(Options{Paths: []string{tmp}}).(*disk[compapi.Component])
229263
set, err := d.loadWithOrder()
230264
require.NoError(t, err)
231265
assert.Equal(t, []manifestOrder{
@@ -259,7 +293,7 @@ spec:
259293
type: state.couchbase
260294
`), fs.FileMode(0o600)))
261295

262-
d := NewComponents(tmp).(*disk[compapi.Component])
296+
d := NewComponents(Options{Paths: []string{tmp}}).(*disk[compapi.Component])
263297
set, err := d.loadWithOrder()
264298
require.NoError(t, err)
265299
assert.Equal(t, []manifestOrder{
@@ -300,7 +334,9 @@ spec:
300334
}
301335
}
302336

303-
d := NewComponents(tmp1, tmp2, tmp3).(*disk[compapi.Component])
337+
d := NewComponents(Options{
338+
Paths: []string{tmp1, tmp2, tmp3},
339+
}).(*disk[compapi.Component])
304340
set, err := d.loadWithOrder()
305341
require.NoError(t, err)
306342
assert.Equal(t, []manifestOrder{

pkg/internal/loader/disk/httpendpoints.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ import (
1818
"github.com/dapr/dapr/pkg/internal/loader"
1919
)
2020

21-
func NewHTTPEndpoints(paths ...string) loader.Loader[endpointapi.HTTPEndpoint] {
22-
return new[endpointapi.HTTPEndpoint](paths...)
21+
func NewHTTPEndpoints(opts Options) loader.Loader[endpointapi.HTTPEndpoint] {
22+
return new[endpointapi.HTTPEndpoint](opts)
2323
}

pkg/internal/loader/disk/subscriptions.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ type subscriptions struct {
2727
v2 *disk[v2alpha1.Subscription]
2828
}
2929

30-
func NewSubscriptions(paths ...string) loader.Loader[v2alpha1.Subscription] {
30+
func NewSubscriptions(opts Options) loader.Loader[v2alpha1.Subscription] {
3131
return &subscriptions{
32-
v1: new[v1alpha1.Subscription](paths...),
33-
v2: new[v2alpha1.Subscription](paths...),
32+
v1: new[v1alpha1.Subscription](opts),
33+
v2: new[v2alpha1.Subscription](opts),
3434
}
3535
}
3636

pkg/runtime/hotreload/hotreload.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var log = logger.NewLogger("dapr.runtime.hotreload")
3535

3636
type OptionsReloaderDisk struct {
3737
Config *config.Configuration
38+
AppID string
3839
Dirs []string
3940
ComponentStore *compstore.ComponentStore
4041
Authorizer *authorizer.Authorizer
@@ -60,6 +61,7 @@ type Reloader struct {
6061

6162
func NewDisk(opts OptionsReloaderDisk) (*Reloader, error) {
6263
loader, err := disk.New(disk.Options{
64+
AppID: opts.AppID,
6365
Dirs: opts.Dirs,
6466
ComponentStore: opts.ComponentStore,
6567
})

pkg/runtime/hotreload/loader/disk/disk.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
var log = logger.NewLogger("dapr.runtime.hotreload.loader.disk")
3636

3737
type Options struct {
38+
AppID string
3839
Dirs []string
3940
ComponentStore *compstore.ComponentStore
4041
}
@@ -63,14 +64,20 @@ func New(opts Options) (loader.Interface, error) {
6364
fs: fs,
6465
components: newResource[compapi.Component](
6566
resourceOptions[compapi.Component]{
66-
loader: loaderdisk.NewComponents(opts.Dirs...),
67+
loader: loaderdisk.NewComponents(loaderdisk.Options{
68+
AppID: opts.AppID,
69+
Paths: opts.Dirs,
70+
}),
6771
store: store.NewComponents(opts.ComponentStore),
6872
batcher: batcher,
6973
},
7074
),
7175
subscriptions: newResource[subapi.Subscription](
7276
resourceOptions[subapi.Subscription]{
73-
loader: loaderdisk.NewSubscriptions(opts.Dirs...),
77+
loader: loaderdisk.NewSubscriptions(loaderdisk.Options{
78+
AppID: opts.AppID,
79+
Paths: opts.Dirs,
80+
}),
7481
store: store.NewSubscriptions(opts.ComponentStore),
7582
batcher: batcher,
7683
},

pkg/runtime/hotreload/loader/disk/resource_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ func Test_Stream(t *testing.T) {
148148
r := newResource[componentsapi.Component](resourceOptions[componentsapi.Component]{
149149
store: loadercompstore.NewComponents(store),
150150
batcher: batcher,
151-
loader: loaderdisk.NewComponents(dir),
151+
loader: loaderdisk.NewComponents(loaderdisk.Options{
152+
Paths: []string{dir},
153+
}),
152154
})
153155

154156
errCh := make(chan error)
@@ -229,7 +231,9 @@ func Test_Stream(t *testing.T) {
229231
r := newResource[componentsapi.Component](resourceOptions[componentsapi.Component]{
230232
store: loadercompstore.NewComponents(store),
231233
batcher: batcher,
232-
loader: loaderdisk.NewComponents(dir),
234+
loader: loaderdisk.NewComponents(loaderdisk.Options{
235+
Paths: []string{dir},
236+
}),
233237
})
234238

235239
errCh := make(chan error)
@@ -311,7 +315,9 @@ func Test_Stream(t *testing.T) {
311315
r := newResource[componentsapi.Component](resourceOptions[componentsapi.Component]{
312316
store: loadercompstore.NewComponents(store),
313317
batcher: batcher,
314-
loader: loaderdisk.NewComponents(dir),
318+
loader: loaderdisk.NewComponents(loaderdisk.Options{
319+
Paths: []string{dir},
320+
}),
315321
})
316322

317323
errCh := make(chan error)

pkg/runtime/runtime.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ func newDaprRuntime(ctx context.Context,
218218
ComponentStore: compStore,
219219
Authorizer: authz,
220220
Processor: processor,
221+
AppID: runtimeConfig.id,
221222
})
222223
if err != nil {
223224
return nil, err
@@ -1005,7 +1006,10 @@ func (a *DaprRuntime) loadComponents(ctx context.Context) error {
10051006
PodName: a.podName,
10061007
})
10071008
case modes.StandaloneMode:
1008-
loader = disk.NewComponents(a.runtimeConfig.standalone.ResourcesPath...)
1009+
loader = disk.NewComponents(disk.Options{
1010+
AppID: a.runtimeConfig.id,
1011+
Paths: a.runtimeConfig.standalone.ResourcesPath,
1012+
})
10091013
default:
10101014
return nil
10111015
}
@@ -1052,7 +1056,10 @@ func (a *DaprRuntime) loadDeclarativeSubscriptions(ctx context.Context) error {
10521056
PodName: a.podName,
10531057
})
10541058
case modes.StandaloneMode:
1055-
loader = disk.NewSubscriptions(a.runtimeConfig.standalone.ResourcesPath...)
1059+
loader = disk.NewSubscriptions(disk.Options{
1060+
AppID: a.runtimeConfig.id,
1061+
Paths: a.runtimeConfig.standalone.ResourcesPath,
1062+
})
10561063
default:
10571064
return nil
10581065
}
@@ -1100,7 +1107,10 @@ func (a *DaprRuntime) loadHTTPEndpoints(ctx context.Context) error {
11001107
PodName: a.podName,
11011108
})
11021109
case modes.StandaloneMode:
1103-
loader = disk.NewHTTPEndpoints(a.runtimeConfig.standalone.ResourcesPath...)
1110+
loader = disk.NewHTTPEndpoints(disk.Options{
1111+
AppID: a.runtimeConfig.id,
1112+
Paths: a.runtimeConfig.standalone.ResourcesPath,
1113+
})
11041114
default:
11051115
return nil
11061116
}

0 commit comments

Comments
 (0)