diff --git a/.gitignore b/.gitignore
index 6c56d29b92f43a22cd9d291e791c613a303ed15c..5fa2ffa0ffd521c3989ebc87ca0a4b36679083d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@ controller/api/stores_testing/**
 controller/northbound/server/stores_testing/**
 controller/nucleus/stores_testing/**
 controller/nucleus/**/gostructs.go
+controller/rbac/stores_testing/**
 
 # stores
 stores/*.json
diff --git a/.gitlab/ci/.test.yml b/.gitlab/ci/.test.yml
index 60fea0a976322b297da439ccb425fd3acebd8336..4d033d2ead17f57d1e84c299cca384504122d8a7 100644
--- a/.gitlab/ci/.test.yml
+++ b/.gitlab/ci/.test.yml
@@ -5,7 +5,7 @@
         - when: on_success
     variables:
         GOSDN_LOG: "nolog"
-        GOSDN_CHANGE_TIMEOUT: "100ms"
+        GOSDN_CHANGE_TIMEOUT: "5000ms"
     artifacts:
         when: always
         reports:
diff --git a/cli/cmd/deviceSet.go b/cli/cmd/deviceSet.go
index 1c18443b5705897b2e3997a31e92ff64149b9ce8..15806d356c22f43b5719685abe7d30baf2e3e041 100644
--- a/cli/cmd/deviceSet.go
+++ b/cli/cmd/deviceSet.go
@@ -119,6 +119,6 @@ func fileContentToString(path string) (string, error) {
 func init() {
 	deviceCmd.AddCommand(deviceSetCmd)
 	deviceSetCmd.Flags().BoolVarP(&replace, "replace", "r", false, "enables replace behaviour")
-	deviceSetCmd.Flags().StringVar(&file, "json file", "", "reference the path to a file containing your changes as JSON")
+	deviceSetCmd.Flags().StringVar(&file, "file", "", "reference the path to a file containing your changes as JSON")
 	deviceSetCmd.Flags().BoolVar(&forcePush, "force-push", false, "enables the possibility to instantly push the set without commit/confirm")
 }
diff --git a/controller/interfaces/transport/transport.go b/controller/interfaces/transport/transport.go
index a0209d9b7f90f9b7d89a0b19e5bbfeb4158b4044..9d732c370599062776d9151c52fa4395df7c3d6f 100644
--- a/controller/interfaces/transport/transport.go
+++ b/controller/interfaces/transport/transport.go
@@ -12,7 +12,7 @@ import (
 // like RESTCONF or gnmi
 type Transport interface {
 	Get(ctx context.Context, params ...string) (interface{}, error)
-	Set(ctx context.Context, payload change.Payload) error
+	Set(ctx context.Context, payload change.Payload, path string, schema *ytypes.Schema) error
 	Subscribe(ctx context.Context, params ...string) error
 	Type() string
 	ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error
diff --git a/controller/mocks/Transport.go b/controller/mocks/Transport.go
index ae80536a4f465db7af6e5d47ec8beebd7ee027c4..10fa882e37cf54a9c81a7652ec0da45694e472ef 100644
--- a/controller/mocks/Transport.go
+++ b/controller/mocks/Transport.go
@@ -63,13 +63,13 @@ func (_m *Transport) ProcessResponse(resp interface{}, root interface{}, models
 	return r0
 }
 
-// Set provides a mock function with given fields: ctx, payload
-func (_m *Transport) Set(ctx context.Context, payload change.Payload) error {
-	ret := _m.Called(ctx, payload)
+// Set provides a mock function with given fields: ctx, payload, path, schema
+func (_m *Transport) Set(ctx context.Context, payload change.Payload, path string, schema *ytypes.Schema) error {
+	ret := _m.Called(ctx, payload, path, schema)
 
 	var r0 error
-	if rf, ok := ret.Get(0).(func(context.Context, change.Payload) error); ok {
-		r0 = rf(ctx, payload)
+	if rf, ok := ret.Get(0).(func(context.Context, change.Payload, string, *ytypes.Schema) error); ok {
+		r0 = rf(ctx, payload, path, schema)
 	} else {
 		r0 = ret.Error(0)
 	}
diff --git a/controller/northbound/server/role.go b/controller/northbound/server/role.go
index fd742a96e6f21497de4985357d36447fe0090729..4cb05b6e16e885082f2e6a1b88466f000f2a7961 100644
--- a/controller/northbound/server/role.go
+++ b/controller/northbound/server/role.go
@@ -117,7 +117,6 @@ func (r Role) UpdateRoles(ctx context.Context, request *apb.UpdateRolesRequest)
 		if err != nil {
 			return nil, handleRPCError(labels, err)
 		}
-
 		_, err = r.roleService.Get(store.Query{ID: rid})
 		if err != nil {
 			return nil, status.Errorf(codes.Canceled, "role not found %v", err)
diff --git a/controller/nucleus/deviceFilesystemStore.go b/controller/nucleus/deviceFilesystemStore.go
index fc57e48cfce24269e906cff34d6f2fb8ac013786..0d9db1f893eacc3d958424b44e1feafead591248 100644
--- a/controller/nucleus/deviceFilesystemStore.go
+++ b/controller/nucleus/deviceFilesystemStore.go
@@ -8,7 +8,6 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
-	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 	"github.com/google/uuid"
 )
@@ -23,7 +22,7 @@ type FilesystemDeviceStore struct {
 
 // NewFilesystemDeviceStore returns a filesystem implementation for a pnd store.
 func NewFilesystemDeviceStore(pndUUID uuid.UUID) device.Store {
-	deviceFilenameForUUID := store.GetStoreFilenameForUUID(pndUUID, filesystem.DeviceFilenameSuffix)
+	deviceFilenameForUUID := store.GetStoreFilenameForUUID(pndUUID, store.DeviceFilenameSuffix)
 
 	store.EnsureFilesystemStorePathExists(deviceFilenameForUUID)
 	return &FilesystemDeviceStore{
diff --git a/controller/nucleus/deviceFilesystemStore_test.go b/controller/nucleus/deviceFilesystemStore_test.go
index e3179ad319e491b1911c4fe9035e73cdf36dc542..520a30a520901d75ad4e0cedf3197e97433717f5 100644
--- a/controller/nucleus/deviceFilesystemStore_test.go
+++ b/controller/nucleus/deviceFilesystemStore_test.go
@@ -9,14 +9,13 @@ import (
 	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
-	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 	"github.com/google/uuid"
 )
 
 func ensureDeviceFilesForTestAreRemoved() {
-	store.EnsureFilesystemStorePathExists(filesystem.DeviceFilenameSuffix)
-	wildcartFilename := "*-" + filesystem.DeviceFilenameSuffix
+	store.EnsureFilesystemStorePathExists(store.DeviceFilenameSuffix)
+	wildcartFilename := "*-" + store.DeviceFilenameSuffix
 	path := store.GetCompletePathToFileStore(wildcartFilename)
 
 	files, err := filepath.Glob(path)
diff --git a/controller/nucleus/errors/errors.go b/controller/nucleus/errors/errors.go
index 7883c35987cb9557c16d6d9af66aceb6617b167d..54be6a61744b799cabc3ee1d7cd79a5c3db7bb4a 100644
--- a/controller/nucleus/errors/errors.go
+++ b/controller/nucleus/errors/errors.go
@@ -3,6 +3,8 @@ package errors
 import (
 	"fmt"
 	"reflect"
+
+	"github.com/openconfig/ygot/ygot"
 )
 
 // ErrNilClient implements the Error interface and is called if a GNMI Client is nil.
@@ -29,7 +31,7 @@ type ErrNotFound struct {
 }
 
 func (e *ErrNotFound) Error() string {
-	return fmt.Sprintf("ID: %v or Name: %vnot found", e.ID, e.Name)
+	return fmt.Sprintf("ID: %v or Name: %v not found", e.ID, e.Name)
 }
 
 // ErrAlreadyExists implements the Error interface and is called if a specific ID
@@ -72,6 +74,17 @@ func (e ErrUnsupportedPath) Error() string {
 	return fmt.Sprintf("path %v is not supported", e.Path)
 }
 
+// ErrPathNotFound implements the Error interface and is called if the
+// given path is not supported.
+type ErrPathNotFound struct {
+	Path interface{}
+	Err  error
+}
+
+func (e ErrPathNotFound) Error() string {
+	return fmt.Sprintf("path %v not found: %v", e.Path, e.Err)
+}
+
 // ErrNotYetImplemented implements the Error interface and is called if a function
 // is not implemented yet.
 type ErrNotYetImplemented struct{}
@@ -206,3 +219,15 @@ type ErrCouldNotDelete struct {
 func (e ErrCouldNotDelete) Error() string {
 	return fmt.Sprintf("could not delete %s", e.StoreName)
 }
+
+// ErrNoNewChanges implements the Error interface and is called if a the
+// gNMI-Notification created from ygot.Diff does not contain any `updates` or
+// `deletes`.
+type ErrNoNewChanges struct {
+	Original ygot.GoStruct
+	Modified ygot.GoStruct
+}
+
+func (e ErrNoNewChanges) Error() string {
+	return fmt.Sprintf("There are no changes between %v and %v", e.Original, e.Modified)
+}
diff --git a/controller/nucleus/gnmi_transport.go b/controller/nucleus/gnmi_transport.go
index ff19f96a6afb52f1feeb944980397226d7285910..84b9e3b3d7e06d755de9cb45d733b512b11846d0 100644
--- a/controller/nucleus/gnmi_transport.go
+++ b/controller/nucleus/gnmi_transport.go
@@ -15,6 +15,7 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/forks/goarista/gnmi"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	"github.com/openconfig/goyang/pkg/yang"
+	"github.com/openconfig/ygot/util"
 	"github.com/openconfig/ygot/ygot"
 	"github.com/openconfig/ygot/ytypes"
 	log "github.com/sirupsen/logrus"
@@ -85,37 +86,109 @@ func (g *Gnmi) Get(ctx context.Context, params ...string) (interface{}, error) {
 }
 
 // Set takes a change.Payload struct.
-func (g *Gnmi) Set(ctx context.Context, payload change.Payload) error {
+func (g *Gnmi) Set(ctx context.Context, payload change.Payload, path string, schema *ytypes.Schema) error {
+	p, err := ygot.StringToStructuredPath(path)
+	if err != nil {
+		return err
+	}
 	if g.client == nil {
 		return &errors.ErrNilClient{}
 	}
 	ctx = gnmi.NewContext(ctx, g.config)
-	return g.applyDiff(ctx, payload)
+	return g.applyDiff(ctx, payload, p, schema)
 }
 
-func (g *Gnmi) applyDiff(ctx context.Context, payload change.Payload) error {
-	op := ctx.Value(types.CtxKeyOperation)
+// isGNMINotificationEmpty checks if the given gnmi.Notification does not
+// contain any updates or deletes.
+func isGNMINotificationEmpty(n *gpb.Notification) bool {
+	if n.Update == nil || len(n.Update) == 0 {
+		if n.Delete == nil || len(n.Delete) == 0 {
+			return true
+		}
+	}
+	return false
+}
 
+func (g *Gnmi) applyDiff(ctx context.Context, payload change.Payload, path *gpb.Path, schema *ytypes.Schema) error {
 	diff, err := ygot.Diff(payload.Original, payload.Modified)
 	if err != nil {
 		return err
 	}
+
+	if isGNMINotificationEmpty(diff) {
+		return errors.ErrNoNewChanges{Original: payload.Original, Modified: payload.Modified}
+	}
+
+	var json []byte
+	if op := ctx.Value(types.CtxKeyOperation); op == ppb.ApiOperation_API_OPERATION_UPDATE || op == ppb.ApiOperation_API_OPERATION_REPLACE {
+		rootCopy, err := ygot.DeepCopy(schema.Root)
+		if err != nil {
+			return err
+		}
+
+		for _, u := range diff.Update {
+			opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
+			if err := g.SetNode(schema.RootSchema(), rootCopy, u.GetPath(), u.GetVal(), opts...); err != nil {
+				return err
+			}
+		}
+
+		ygot.PruneEmptyBranches(rootCopy)
+
+		opts := []ytypes.GetNodeOpt{
+			&ytypes.GetHandleWildcards{},
+		}
+		nodes, err := ytypes.GetNode(schema.RootSchema(), rootCopy, path, opts...)
+		if err != nil {
+			return err
+		}
+
+		if len(nodes) == 0 || err != nil || util.IsValueNil(nodes[0].Data) {
+			return errors.ErrPathNotFound{Path: path, Err: err}
+		}
+
+		json, err = ygot.Marshal7951(nodes[0].Data, &ygot.RFC7951JSONConfig{AppendModuleName: true})
+		if err != nil {
+			return err
+		}
+	}
+
+	req, err := createSetRequest(ctx, diff, json, path)
+	if err != nil {
+		return err
+	}
+
+	resp, err := g.client.Set(ctx, req)
+	log.Info(resp)
+	return err
+}
+
+func createSetRequest(ctx context.Context, diff *gpb.Notification, json []byte, path *gpb.Path) (*gpb.SetRequest, error) {
+	op := ctx.Value(types.CtxKeyOperation)
 	req := &gpb.SetRequest{}
 	if diff.Update != nil {
 		switch op {
 		case ppb.ApiOperation_API_OPERATION_UPDATE:
-			req.Update = diff.Update
+			req.Update = []*gpb.Update{{
+				Path: path,
+				Val: &gpb.TypedValue{
+					Value: &gpb.TypedValue_JsonIetfVal{JsonIetfVal: json},
+				},
+			}}
 		case ppb.ApiOperation_API_OPERATION_REPLACE:
-			req.Replace = diff.Update
+			req.Replace = []*gpb.Update{{
+				Path: path,
+				Val: &gpb.TypedValue{
+					Value: &gpb.TypedValue_JsonIetfVal{JsonIetfVal: json},
+				},
+			}}
 		default:
-			return &errors.ErrOperationNotSupported{Op: op}
+			return nil, &errors.ErrOperationNotSupported{Op: op}
 		}
 	} else if diff.Delete != nil {
 		req.Delete = diff.Delete
 	}
-	resp, err := g.client.Set(ctx, req)
-	log.Info(resp)
-	return err
+	return req, nil
 }
 
 //Subscribe subscribes to a gNMI target
diff --git a/controller/nucleus/gnmi_transport_test.go b/controller/nucleus/gnmi_transport_test.go
index e7715e7fd6c2dd0184ec80de4b9ee71bf493f1e5..deb6742db9cf6255483cbf4fd0b2a627d8910c65 100644
--- a/controller/nucleus/gnmi_transport_test.go
+++ b/controller/nucleus/gnmi_transport_test.go
@@ -7,9 +7,11 @@ import (
 	"testing"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/change"
+	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/types"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 
+	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
 
@@ -18,6 +20,7 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/models/generated/openconfig"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	"github.com/openconfig/goyang/pkg/yang"
+	"github.com/openconfig/ygot/ygot"
 	"github.com/openconfig/ygot/ytypes"
 	"github.com/stretchr/testify/mock"
 )
@@ -271,11 +274,21 @@ func TestGnmi_ProcessResponse(t *testing.T) {
 }
 
 func TestGnmi_Set(t *testing.T) {
+	schema, err := openconfig.Schema()
+	if err != nil {
+		t.Errorf("Set() error = %v", err)
+	}
+
+	setResponse := &gpb.SetResponse{}
+
 	type fields struct {
-		transport *Gnmi
+		transport           Gnmi
+		mockArgumentMatcher any
 	}
 	type args struct {
 		payload change.Payload
+		path    string
+		ctx     context.Context
 	}
 	tests := []struct {
 		name    string
@@ -285,17 +298,88 @@ func TestGnmi_Set(t *testing.T) {
 	}{
 		{
 			name:   "uninitialised",
-			fields: fields{&Gnmi{}},
+			fields: fields{transport: mockTransport()},
 			args: args{
 				payload: change.Payload{},
+				path:    "/",
+				ctx:     context.WithValue(context.Background(), types.CtxKeyOperation, ppb.ApiOperation_API_OPERATION_UPDATE), // nolint
 			},
 			wantErr: true,
 		},
-		// TODO: Positive test cases
+		{
+			name: "updateValue",
+			fields: fields{
+				transport: mockTransport(),
+				mockArgumentMatcher: mock.MatchedBy(func(input *gpb.SetRequest) bool {
+					if len(input.Update) == 0 {
+						return false
+					}
+					test, _ := ygot.PathToString(input.Update[0].Path)
+					return test == "/system/config/hostname"
+				}),
+			},
+			args: args{
+				payload: change.Payload{
+					Original: &openconfig.Device{
+						System: &openconfig.OpenconfigSystem_System{
+							Config: &openconfig.OpenconfigSystem_System_Config{
+								Hostname: ygot.String("oldName"),
+							},
+						},
+					},
+					Modified: &openconfig.Device{
+						System: &openconfig.OpenconfigSystem_System{
+							Config: &openconfig.OpenconfigSystem_System_Config{
+								Hostname: ygot.String("newName"),
+							},
+						},
+					},
+				},
+				path: "/system/config/hostname",
+				ctx:  context.WithValue(context.Background(), types.CtxKeyOperation, ppb.ApiOperation_API_OPERATION_UPDATE), // nolint
+			},
+			wantErr: false,
+		},
+		{
+			name: "removeValue",
+			fields: fields{
+				transport: mockTransport(),
+				mockArgumentMatcher: mock.MatchedBy(func(input *gpb.SetRequest) bool {
+					if len(input.Delete) == 0 {
+						return false
+					}
+					test, _ := ygot.PathToString(input.Delete[0])
+					return test == "/system/config/hostname"
+				}),
+			},
+			args: args{
+				payload: change.Payload{
+					Original: &openconfig.Device{
+						System: &openconfig.OpenconfigSystem_System{
+							Config: &openconfig.OpenconfigSystem_System_Config{
+								Hostname: ygot.String("oldName"),
+							},
+						},
+					},
+					Modified: &openconfig.Device{
+						System: &openconfig.OpenconfigSystem_System{
+							Config: &openconfig.OpenconfigSystem_System_Config{
+								Hostname: nil,
+							},
+						},
+					},
+				},
+				path: "/system/config/hostname",
+				ctx:  context.WithValue(context.Background(), types.CtxKeyOperation, ppb.ApiOperation_API_OPERATION_DELETE), // nolint
+			},
+			wantErr: false,
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			err := tt.fields.transport.Set(context.Background(), tt.args.payload)
+			tt.fields.transport.client.(*mocks.GNMIClient).
+				On("Set", mockContext, tt.fields.mockArgumentMatcher).Return(setResponse, nil)
+			err := tt.fields.transport.Set(tt.args.ctx, tt.args.payload, tt.args.path, schema)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
 			}
diff --git a/controller/nucleus/initialise_test.go b/controller/nucleus/initialise_test.go
index ed1d2b16cdaea11009dc59c33a68edf61ec980a8..958991f27435204cc0f977126d6195929f6e4fca 100644
--- a/controller/nucleus/initialise_test.go
+++ b/controller/nucleus/initialise_test.go
@@ -87,7 +87,7 @@ func targetRunner() {
 
 func mockTransport() Gnmi {
 	return Gnmi{
-		SetNode:  nil,
+		SetNode:  getMockSbi(defaultSbiID).SetNode,
 		RespChan: make(chan *gpb.SubscribeResponse),
 		Options:  newGnmiTransportOptions(),
 		client:   &mocks.GNMIClient{},
diff --git a/controller/nucleus/pndFilesystemStore.go b/controller/nucleus/pndFilesystemStore.go
index 61a42808c0b25112083c1ee0d11e094abd3052aa..beba95994fef0a9cf1c94dca37096efa9987e2d3 100644
--- a/controller/nucleus/pndFilesystemStore.go
+++ b/controller/nucleus/pndFilesystemStore.go
@@ -9,7 +9,6 @@ import (
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
 	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
-	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
@@ -28,10 +27,10 @@ type FilesystemPndStore struct {
 
 // NewFilesystemPndStore returns a filesystem implementation for a pnd store.
 func NewFilesystemPndStore() FilesystemPndStore {
-	store.EnsureFilesystemStorePathExists(filesystem.PndFilename)
+	store.EnsureFilesystemStorePathExists(store.PndFilename)
 	return FilesystemPndStore{
 		pendingChannels: make(map[uuid.UUID]chan device.Details),
-		pathToPndFile:   store.GetCompletePathToFileStore(filesystem.PndFilename),
+		pathToPndFile:   store.GetCompletePathToFileStore(store.PndFilename),
 		fileMutex:       sync.Mutex{},
 	}
 }
diff --git a/controller/nucleus/pndFilesystemStore_test.go b/controller/nucleus/pndFilesystemStore_test.go
index 3480c6a5392c90c7f0ac59e14906c63bcea722fb..29119f9f343710cf91d6500b2393686d65c68734 100644
--- a/controller/nucleus/pndFilesystemStore_test.go
+++ b/controller/nucleus/pndFilesystemStore_test.go
@@ -6,14 +6,13 @@ import (
 	"testing"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
-	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 	"github.com/google/uuid"
 )
 
 func ensurePndFileForTestIsRemoved() {
-	store.EnsureFilesystemStorePathExists(filesystem.PndFilename)
-	path := store.GetCompletePathToFileStore(filesystem.PndFilename)
+	store.EnsureFilesystemStorePathExists(store.PndFilename)
+	path := store.GetCompletePathToFileStore(store.PndFilename)
 
 	err := os.Remove(path)
 	if err != nil {
diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go
index 3c75a1ae1fdbab46977dc636f72e2e30b8d608ef..ad53c9694b1c85e87f9702cbaed130e2edd278c4 100644
--- a/controller/nucleus/principalNetworkDomain.go
+++ b/controller/nucleus/principalNetworkDomain.go
@@ -472,7 +472,8 @@ func (pnd *pndImplementation) ChangeOND(duid uuid.UUID, operation ppb.ApiOperati
 			if err != nil {
 				return uuid.Nil, err
 			}
-			if err := ytypes.SetNode(d.SBI().Schema().RootSchema(), validatedCpy, p, typedValue); err != nil {
+			opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
+			if err := ytypes.SetNode(d.SBI().Schema().RootSchema(), validatedCpy, p, typedValue, opts...); err != nil {
 				return uuid.Nil, err
 			}
 		}
@@ -488,7 +489,9 @@ func (pnd *pndImplementation) ChangeOND(duid uuid.UUID, operation ppb.ApiOperati
 	callback := func(original ygot.GoStruct, modified ygot.GoStruct) error {
 		ctx := context.WithValue(context.Background(), types.CtxKeyOperation, operation) // nolint
 		payload := change.Payload{Original: original, Modified: modified}
-		return d.Transport().Set(ctx, payload)
+		pathToSet := path
+		schema := d.SBI().Schema()
+		return d.Transport().Set(ctx, payload, pathToSet, schema)
 	}
 
 	ch := NewChange(duid, d.GetModel(), validatedCpy, callback)
diff --git a/controller/nucleus/principalNetworkDomain_test.go b/controller/nucleus/principalNetworkDomain_test.go
index 907e027ab78ee1740d262247d985d76bd11778e5..ac28816d94daad4aaa19d070a72e79fdfb73af71 100644
--- a/controller/nucleus/principalNetworkDomain_test.go
+++ b/controller/nucleus/principalNetworkDomain_test.go
@@ -959,7 +959,7 @@ func Test_pndImplementation_Confirm(t *testing.T) {
 
 			d := mockDevice()
 			tr := d.Transport().(*mocks.Transport)
-			tr.On("Set", mockContext, mock.Anything, mock.Anything).Return(nil)
+			tr.On("Set", mockContext, mock.Anything, mock.Anything, mock.Anything).Return(nil)
 			_, err := pnd.addDevice(d)
 			if err != nil {
 				t.Error(err)
diff --git a/controller/nucleus/sbiFilesystemStore.go b/controller/nucleus/sbiFilesystemStore.go
index 52d0f98944ee93b1d8bef02f2f128d3af85f4b6b..64fdeb48104572f8e268c1e53c4a43d3bfb35024 100644
--- a/controller/nucleus/sbiFilesystemStore.go
+++ b/controller/nucleus/sbiFilesystemStore.go
@@ -7,7 +7,6 @@ import (
 
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
-	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 
 	"github.com/google/uuid"
@@ -23,7 +22,7 @@ type FilesystemSbiStore struct {
 
 // NewFilesystemSbiStore returns a filesystem implementation for a pnd store.
 func NewFilesystemSbiStore(pndUUID uuid.UUID) southbound.Store {
-	sbiFilenameForUUID := store.GetStoreFilenameForUUID(pndUUID, filesystem.SbiFilenameSuffix)
+	sbiFilenameForUUID := store.GetStoreFilenameForUUID(pndUUID, store.SbiFilenameSuffix)
 
 	store.EnsureFilesystemStorePathExists(sbiFilenameForUUID)
 	return &FilesystemSbiStore{
diff --git a/controller/nucleus/sbiFilesystemStore_test.go b/controller/nucleus/sbiFilesystemStore_test.go
index 38ea67d4723ee950e00ba74c05d5b08b286549ae..4ec3de489742d87d2fabef6b02e4ec3fcbb25615 100644
--- a/controller/nucleus/sbiFilesystemStore_test.go
+++ b/controller/nucleus/sbiFilesystemStore_test.go
@@ -8,14 +8,13 @@ import (
 
 	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
-	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 	"github.com/google/uuid"
 )
 
 func ensureSbiFilesForTestAreRemoved() {
-	store.EnsureFilesystemStorePathExists(filesystem.SbiFilenameSuffix)
-	wildcartFilename := "*-" + filesystem.SbiFilenameSuffix
+	store.EnsureFilesystemStorePathExists(store.SbiFilenameSuffix)
+	wildcartFilename := "*-" + store.SbiFilenameSuffix
 	path := store.GetCompletePathToFileStore(wildcartFilename)
 
 	files, err := filepath.Glob(path)
diff --git a/controller/rbac/roleFileSystemStore.go b/controller/rbac/roleFileSystemStore.go
new file mode 100644
index 0000000000000000000000000000000000000000..02a2baaeeea0e89aa0021695d9cebec19c6dd985
--- /dev/null
+++ b/controller/rbac/roleFileSystemStore.go
@@ -0,0 +1,166 @@
+package rbac
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"sync"
+
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
+	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
+	"code.fbi.h-da.de/danet/gosdn/controller/store"
+)
+
+// FileSystemRoleStore is the filesystem implementation of the role store
+type FileSystemRoleStore struct {
+	fileMutex      sync.Mutex
+	pathToRoleFile string
+}
+
+// NewFileSystemRoleStore returns a filesystem implementation for a role store.
+func NewFileSystemRoleStore() rbac.RoleStore {
+	store.EnsureFilesystemStorePathExists(store.RoleFilename)
+	return &FileSystemRoleStore{
+		fileMutex:      sync.Mutex{},
+		pathToRoleFile: store.GetCompletePathToFileStore(store.RoleFilename),
+	}
+}
+
+func (s *FileSystemRoleStore) readAllRolesFromFile() ([]rbac.LoadedRole, error) {
+	var loadedRoles []rbac.LoadedRole
+	content, err := ioutil.ReadFile(s.pathToRoleFile)
+	if err != nil {
+		return nil, err
+	}
+
+	err = json.Unmarshal(content, &loadedRoles)
+	if err != nil {
+		return nil, err
+	}
+
+	return loadedRoles, nil
+}
+
+func (s *FileSystemRoleStore) writeAllRolesToFile(Roles []rbac.LoadedRole) error {
+	serializedData, err := json.Marshal(Roles)
+	if err != nil {
+		return err
+	}
+
+	err = ioutil.WriteFile(s.pathToRoleFile, serializedData, 0600)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// Add adds a Role to the Role store
+func (s *FileSystemRoleStore) Add(RoleToAdd rbac.Role) error {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	roles, err := s.readAllRolesFromFile()
+	if err != nil {
+		return err
+	}
+
+	var loadedRole rbac.LoadedRole
+	loadedRole, err = store.TransformObjectToLoadedObject[rbac.Role, rbac.LoadedRole](RoleToAdd)
+	if err != nil {
+		return err
+	}
+
+	roles = append(roles, loadedRole)
+
+	err = s.writeAllRolesToFile(roles)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+//Delete deletes a Role from the Role store
+func (s *FileSystemRoleStore) Delete(RoleToDelete rbac.Role) error {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	roles, err := s.readAllRolesFromFile()
+	if err != nil {
+		return err
+	}
+
+	for i, role := range roles {
+		if role.ID == RoleToDelete.ID().String() {
+			//remove item from slice
+			roles[i] = roles[len(roles)-1]
+			roles = roles[:len(roles)-1]
+
+			err = s.writeAllRolesToFile(roles)
+			if err != nil {
+				return err
+			}
+
+			return nil
+		}
+	}
+
+	return &errors.ErrNotFound{ID: RoleToDelete.ID}
+}
+
+//Get takes a Roles ID and return the Role if found
+func (s *FileSystemRoleStore) Get(query store.Query) (rbac.LoadedRole, error) {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	var role rbac.LoadedRole
+	roles, err := s.readAllRolesFromFile()
+	if err != nil {
+		return role, err
+	}
+
+	for _, role := range roles {
+		if role.ID == query.ID.String() || role.RoleName == query.Name {
+			return role, nil
+		}
+	}
+
+	return role, &errors.ErrNotFound{ID: query.ID, Name: query.Name}
+}
+
+// GetAll returns all the Roles
+func (s *FileSystemRoleStore) GetAll() ([]rbac.LoadedRole, error) {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	Roles, err := s.readAllRolesFromFile()
+	return Roles, err
+}
+
+//Update updates an exsisting Role
+func (s *FileSystemRoleStore) Update(roleToUpdate rbac.Role) error {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	loadedRole, err := store.TransformObjectToLoadedObject[rbac.Role, rbac.LoadedRole](roleToUpdate)
+	if err != nil {
+		return err
+	}
+	Roles, err := s.readAllRolesFromFile()
+	if err != nil {
+		return err
+	}
+
+	for i, Role := range Roles {
+		if Role.ID == roleToUpdate.ID().String() {
+			Roles[i] = loadedRole
+			err = s.writeAllRolesToFile(Roles)
+			if err != nil {
+				return err
+			}
+			return nil
+		}
+	}
+
+	return &errors.ErrNotFound{ID: roleToUpdate.ID().String()}
+}
diff --git a/controller/rbac/roleFileSystemStore_test.go b/controller/rbac/roleFileSystemStore_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..cfc033ee8b3dd537b7b4421c11e73ffa9b79a814
--- /dev/null
+++ b/controller/rbac/roleFileSystemStore_test.go
@@ -0,0 +1,185 @@
+package rbac
+
+import (
+	"log"
+	"os"
+	"path/filepath"
+	"reflect"
+	"testing"
+
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
+	"code.fbi.h-da.de/danet/gosdn/controller/store"
+	"github.com/google/uuid"
+)
+
+func ensureRoleFilesForTestAreRemoved() {
+	store.EnsureFilesystemStorePathExists(store.RoleFilename)
+	path := store.GetCompletePathToFileStore(store.RoleFilename)
+
+	files, err := filepath.Glob(path)
+
+	if err != nil {
+		log.Println(err)
+	}
+	for _, f := range files {
+		if err := os.Remove(f); err != nil {
+			log.Println(err)
+		}
+	}
+}
+
+func TestFileSystemRoleStore_Add(t *testing.T) {
+	ensureRoleFilesForTestAreRemoved()
+
+	type args struct {
+		RoleToAdd rbac.Role
+	}
+	var AddRole rbac.Role
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{"AddRole1", args{AddRole}, false},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewRoleStore()
+			if err := s.Add(tt.args.RoleToAdd); (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemRoleStore.Add() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestFileSystemRoleStore_Delete(t *testing.T) {
+	ensureRoleFilesForTestAreRemoved()
+
+	type args struct {
+		RoleToDelete rbac.Role
+	}
+	var idtest uuid.UUID
+	addRole := NewRole(idtest, "testRole", "role", []string{})
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{"AddRole1", args{
+			addRole,
+		}, false},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewRoleStore()
+			s.Add(addRole)
+			if err := s.Delete(tt.args.RoleToDelete); (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemRoleStore.Delete() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestFileSystemRoleStore_Get(t *testing.T) {
+	ensureRoleFilesForTestAreRemoved()
+
+	type args struct {
+		query store.Query
+	}
+	var idtest uuid.UUID
+	var arrTest []string
+	addRole := NewRole(idtest, "testRole", "role", arrTest)
+	tests := []struct {
+		name    string
+		args    args
+		want    rbac.LoadedRole
+		wantErr bool
+	}{
+		{"AddRole1", args{
+			store.Query{
+				ID: idtest, Name: "test",
+			},
+		},
+			rbac.LoadedRole{ID: idtest.String(), RoleName: "testRole", Description: "role", Permissions: arrTest},
+			false},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewRoleStore()
+			s.Add(addRole)
+			got, err := s.Get(tt.args.query)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemRoleStore.Get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("FileSystemRoleStore.Get() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestFileSystemRoleStore_GetAll(t *testing.T) {
+	ensureRoleFilesForTestAreRemoved()
+	var idtest uuid.UUID
+	var arrTest []string
+	addRole1 := NewRole(idtest, "testRole1", "role1", arrTest)
+	addRole2 := NewRole(idtest, "testRole2", "role2", arrTest)
+	addRole3 := NewRole(idtest, "testRole3", "role3", arrTest)
+	tests := []struct {
+		name    string
+		want    []rbac.LoadedRole
+		wantErr bool
+	}{
+		{
+			"testRole",
+			[]rbac.LoadedRole{{ID: idtest.String(), RoleName: "testRole1", Description: "role1", Permissions: arrTest}, {ID: idtest.String(), RoleName: "testRole2", Description: "role2", Permissions: arrTest}, {ID: idtest.String(), RoleName: "testRole3", Description: "role3", Permissions: arrTest}},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewRoleStore()
+			s.Add(addRole1)
+			s.Add(addRole2)
+			s.Add(addRole3)
+			got, err := s.GetAll()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemRoleStore.GetAll() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("FileSystemRoleStore.GetAll() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestFileSystemRoleStore_Update(t *testing.T) {
+	ensureRoleFilesForTestAreRemoved()
+
+	var idtest uuid.UUID
+	var arrTest []string
+	addRole1 := NewRole(idtest, "testRole1", "role1", arrTest)
+	type args struct {
+		roleToUpdate rbac.Role
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{"AddRole1", args{
+			addRole1,
+		}, false},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewRoleStore()
+			s.Add(addRole1)
+			if err := s.Update(tt.args.roleToUpdate); (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemRoleStore.Update() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
diff --git a/controller/rbac/roleStore.go b/controller/rbac/roleStore.go
index 4482168fa331fbe70fbee6830df0283d5e49a194..35b9a51276641d34745acf5613f35191580a27cb 100644
--- a/controller/rbac/roleStore.go
+++ b/controller/rbac/roleStore.go
@@ -19,13 +19,10 @@ func NewRoleStore() rbac.RoleStore {
 	storeMode := store.GetStoreMode()
 
 	switch storeMode {
-	case store.Filesystem:
-		return NewMemoryRoleStore()
 	case store.Database:
 		return &DatabaseRoleStore{"role.json"}
-	case store.Memory:
-		return NewMemoryRoleStore()
 	default:
-		return nil
+		store := NewFileSystemRoleStore()
+		return store
 	}
 }
diff --git a/controller/rbac/userFileSystemStore.go b/controller/rbac/userFileSystemStore.go
new file mode 100644
index 0000000000000000000000000000000000000000..11f2184c78bd233fd5cde3c0d42e710e8d2c7fa0
--- /dev/null
+++ b/controller/rbac/userFileSystemStore.go
@@ -0,0 +1,166 @@
+package rbac
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"sync"
+
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
+	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
+	"code.fbi.h-da.de/danet/gosdn/controller/store"
+)
+
+// FileSystemUserStore is the filesystem implementation of the user store
+type FileSystemUserStore struct {
+	fileMutex      sync.Mutex
+	pathToUserFile string
+}
+
+// NewFileSystemUserStore returns a filesystem implementation for a user store.
+func NewFileSystemUserStore() rbac.UserStore {
+	store.EnsureFilesystemStorePathExists(store.UserFilename)
+	return &FileSystemUserStore{
+		fileMutex:      sync.Mutex{},
+		pathToUserFile: store.GetCompletePathToFileStore(store.UserFilename),
+	}
+}
+
+func (s *FileSystemUserStore) readAllUsersFromFile() ([]rbac.LoadedUser, error) {
+	var loadedUsers []rbac.LoadedUser
+	content, err := ioutil.ReadFile(s.pathToUserFile)
+	if err != nil {
+		return nil, err
+	}
+
+	err = json.Unmarshal(content, &loadedUsers)
+	if err != nil {
+		return nil, err
+	}
+
+	return loadedUsers, nil
+}
+
+func (s *FileSystemUserStore) writeAllUsersToFile(users []rbac.LoadedUser) error {
+	serializedData, err := json.Marshal(users)
+	if err != nil {
+		return err
+	}
+
+	err = ioutil.WriteFile(s.pathToUserFile, serializedData, 0600)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// Add adds a User to the User store
+func (s *FileSystemUserStore) Add(UserToAdd rbac.User) error {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	users, err := s.readAllUsersFromFile()
+	if err != nil {
+		return err
+	}
+
+	var loadedUser rbac.LoadedUser
+	loadedUser, err = store.TransformObjectToLoadedObject[rbac.User, rbac.LoadedUser](UserToAdd)
+	if err != nil {
+		return err
+	}
+
+	users = append(users, loadedUser)
+
+	err = s.writeAllUsersToFile(users)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+//Delete deletes a User from the User store
+func (s *FileSystemUserStore) Delete(userToDelete rbac.User) error {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	users, err := s.readAllUsersFromFile()
+	if err != nil {
+		return err
+	}
+
+	for i, user := range users {
+		if user.ID == userToDelete.ID().String() {
+			//remove item from slice
+			users[i] = users[len(users)-1]
+			users = users[:len(users)-1]
+
+			err = s.writeAllUsersToFile(users)
+			if err != nil {
+				return err
+			}
+
+			return nil
+		}
+	}
+
+	return &errors.ErrNotFound{ID: userToDelete.ID}
+}
+
+//Get takes a Users ID and return the User if found
+func (s *FileSystemUserStore) Get(query store.Query) (rbac.LoadedUser, error) {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	var user rbac.LoadedUser
+
+	users, err := s.readAllUsersFromFile()
+	if err != nil {
+		return user, err
+	}
+
+	for _, user := range users {
+		if user.ID == query.ID.String() || user.UserName == query.Name {
+			return user, nil
+		}
+	}
+	return user, &errors.ErrNotFound{ID: query.ID, Name: query.Name}
+}
+
+// GetAll returns all the Users
+func (s *FileSystemUserStore) GetAll() ([]rbac.LoadedUser, error) {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	Users, err := s.readAllUsersFromFile()
+	return Users, err
+}
+
+//Update updates an exsisting user
+func (s *FileSystemUserStore) Update(userToUpdate rbac.User) error {
+	s.fileMutex.Lock()
+	defer s.fileMutex.Unlock()
+
+	loadedUser, err := store.TransformObjectToLoadedObject[rbac.User, rbac.LoadedUser](userToUpdate)
+	if err != nil {
+		return err
+	}
+	users, err := s.readAllUsersFromFile()
+	if err != nil {
+		return err
+	}
+
+	for i, user := range users {
+		if user.ID == userToUpdate.ID().String() {
+			users[i] = loadedUser
+			err = s.writeAllUsersToFile(users)
+			if err != nil {
+				return err
+			}
+			return nil
+		}
+	}
+
+	return &errors.ErrNotFound{ID: userToUpdate.ID().String()}
+}
diff --git a/controller/rbac/userFileSystemStore_test.go b/controller/rbac/userFileSystemStore_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..4261e982ec15079bfee2240858fba617e724a21e
--- /dev/null
+++ b/controller/rbac/userFileSystemStore_test.go
@@ -0,0 +1,201 @@
+package rbac
+
+import (
+	"log"
+	"os"
+	"path/filepath"
+	"reflect"
+	"testing"
+
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/rbac"
+	"code.fbi.h-da.de/danet/gosdn/controller/store"
+	"github.com/google/uuid"
+)
+
+func ensureUserFilesForTestAreRemoved() {
+	store.EnsureFilesystemStorePathExists(store.UserFilename)
+	path := store.GetCompletePathToFileStore(store.UserFilename)
+
+	files, err := filepath.Glob(path)
+
+	if err != nil {
+		log.Println(err)
+	}
+	for _, f := range files {
+		if err := os.Remove(f); err != nil {
+			log.Println(err)
+		}
+	}
+}
+
+func TestFileSystemUserStore_Add(t *testing.T) {
+	ensureUserFilesForTestAreRemoved()
+
+	type args struct {
+		UserToAdd rbac.User
+	}
+	var idtest uuid.UUID
+	var role map[string]string
+	testingUser := NewUser(idtest, "testUser", role, "xyz", "svsvsfbdwbwbev", "svswvasfbw")
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			"testUser",
+			args{testingUser},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewUserStore()
+
+			if err := s.Add(tt.args.UserToAdd); (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemUserStore.Add() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestFileSystemUserStore_Delete(t *testing.T) {
+	ensureUserFilesForTestAreRemoved()
+
+	type args struct {
+		UserToDelete rbac.User
+	}
+	var idtest uuid.UUID
+	var role map[string]string
+	testingUser := NewUser(idtest, "", role, "xyz", "svsvsfbdwbwbev", "svswvasfbw")
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			"testUser",
+			args{testingUser},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewUserStore()
+			s.Add(testingUser)
+			if err := s.Delete(tt.args.UserToDelete); (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemUserStore.Delete() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestFileSystemUserStore_Get(t *testing.T) {
+	ensureUserFilesForTestAreRemoved()
+
+	type args struct {
+		query store.Query
+	}
+	var idtest uuid.UUID
+	var role map[string]string
+	testingUser := NewUser(idtest, "", role, "xyz", "svsvsfbdwbwbev", "svswvasfbw")
+	tests := []struct {
+		name    string
+		args    args
+		want    rbac.LoadedUser
+		wantErr bool
+	}{
+		{
+			"testUser",
+			args{
+				store.Query{ID: idtest, Name: "test"},
+			},
+			rbac.LoadedUser{ID: idtest.String(), UserName: "", Roles: role, Password: "xyz", Token: "svsvsfbdwbwbev", Salt: "svswvasfbw"},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewUserStore()
+			s.Add(testingUser)
+			got, err := s.Get(tt.args.query)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemUserStore.Get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("FileSystemUserStore.Get() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestFileSystemUserStore_GetAll(t *testing.T) {
+	ensureUserFilesForTestAreRemoved()
+
+	var idtest uuid.UUID
+	var role map[string]string
+	testingUser1 := NewUser(idtest, "", role, "xyz", "svsvsfbdwbwbevasf", "svswvasfbwasv")
+	testingUser2 := NewUser(idtest, "", role, "abc", "svsvsfbdwbwbevsav", "svswvasfbwadf")
+	testingUser3 := NewUser(idtest, "", role, "lmn", "svsvsfbdwbwbevscv", "svswvasfbwasd")
+	tests := []struct {
+		name    string
+		want    []rbac.LoadedUser
+		wantErr bool
+	}{
+		{
+			"testUser",
+			[]rbac.LoadedUser{{ID: idtest.String(), UserName: "", Roles: role, Password: "xyz", Token: "svsvsfbdwbwbevasf", Salt: "svswvasfbwasv"}, {ID: idtest.String(), UserName: "", Roles: role, Password: "abc", Token: "svsvsfbdwbwbevsav", Salt: "svswvasfbwadf"}, {ID: idtest.String(), UserName: "", Roles: role, Password: "lmn", Token: "svsvsfbdwbwbevscv", Salt: "svswvasfbwasd"}},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewUserStore()
+			s.Add(testingUser1)
+			s.Add(testingUser2)
+			s.Add(testingUser3)
+			got, err := s.GetAll()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemUserStore.GetAll() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("FileSystemUserStore.GetAll() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestFileSystemUserStore_Update(t *testing.T) {
+	ensureUserFilesForTestAreRemoved()
+
+	type args struct {
+		userToUpdate rbac.User
+	}
+	var idtest uuid.UUID
+	var role map[string]string
+	testingUser := NewUser(idtest, "", role, "xyz", "svsvsfbdwbwbev", "svswvasfbw")
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			"testUser",
+			args{
+				testingUser,
+			},
+			false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := NewUserStore()
+			s.Add(testingUser)
+			if err := s.Update(tt.args.userToUpdate); (err != nil) != tt.wantErr {
+				t.Errorf("FileSystemUserStore.Update() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
diff --git a/controller/rbac/userStore.go b/controller/rbac/userStore.go
index 1524abe9c14f286b8fa641e5b3ab8a5ad1df003d..e157d8bf0db359df1e839e4b71529b34ed8aca2c 100644
--- a/controller/rbac/userStore.go
+++ b/controller/rbac/userStore.go
@@ -19,13 +19,10 @@ func NewUserStore() rbac.UserStore {
 	storeMode := store.GetStoreMode()
 
 	switch storeMode {
-	case store.Filesystem:
-		return NewMemoryUserStore()
 	case store.Database:
 		return &DatabaseUserStore{"user.json"}
-	case store.Memory:
-		return NewMemoryUserStore()
 	default:
-		return nil
+		store := NewFileSystemUserStore()
+		return store
 	}
 }
diff --git a/controller/nucleus/filesystem/filesystem-settings.go b/controller/store/filesystem-settings.go
similarity index 61%
rename from controller/nucleus/filesystem/filesystem-settings.go
rename to controller/store/filesystem-settings.go
index 8df6e31e7ea541fa4484c7c83c125bfe8925682d..5a23dd0b9f54d556b795ec0c5ec6a7cac248980f 100644
--- a/controller/nucleus/filesystem/filesystem-settings.go
+++ b/controller/store/filesystem-settings.go
@@ -1,4 +1,4 @@
-package filesystem
+package store
 
 const (
 	// PndFilename is the name of the file where the pnds are stored
@@ -7,4 +7,8 @@ const (
 	DeviceFilenameSuffix string = "deviceStore.json"
 	// SbiFilenameSuffix is the suffix of the file where the sbis are stored
 	SbiFilenameSuffix string = "sbiStore.json"
+	// UserFilename is the name of the file where the users are stored
+	UserFilename string = "userStore.json"
+	// RoleFilename is the name of the file where the roles are stored
+	RoleFilename string = "roleStore.json"
 )
diff --git a/controller/test/integration/nucleusIntegration_test.go b/controller/test/integration/nucleusIntegration_test.go
index 333efb1778f6acf0a22cc9f54f9ed57e82d150bc..b85058a46a6c8b4a1d691bb8633db8f63aff2f94 100644
--- a/controller/test/integration/nucleusIntegration_test.go
+++ b/controller/test/integration/nucleusIntegration_test.go
@@ -14,6 +14,7 @@ import (
 	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/change"
+	"code.fbi.h-da.de/danet/gosdn/models/generated/openconfig"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/nucleus"
 	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
@@ -92,6 +93,11 @@ func testSetupIntegration() {
 }
 
 func TestGnmi_SetInvalidIntegration(t *testing.T) {
+	schema, err := openconfig.Schema()
+	if err != nil {
+		t.Errorf("Set ")
+
+	}
 	if testing.Short() {
 		t.Skip("skipping integration test")
 	}
@@ -101,6 +107,7 @@ func TestGnmi_SetInvalidIntegration(t *testing.T) {
 	type args struct {
 		ctx     context.Context
 		payload change.Payload
+		path    string
 	}
 	tests := []struct {
 		name    string
@@ -120,6 +127,7 @@ func TestGnmi_SetInvalidIntegration(t *testing.T) {
 			args: args{
 				ctx:     context.Background(),
 				payload: change.Payload{},
+				path:    "/",
 			},
 			wantErr: true,
 		},
@@ -129,6 +137,7 @@ func TestGnmi_SetInvalidIntegration(t *testing.T) {
 			args: args{
 				ctx:     context.Background(),
 				payload: change.Payload{},
+				path:    "/",
 			},
 			wantErr: true,
 		},
@@ -145,7 +154,7 @@ func TestGnmi_SetInvalidIntegration(t *testing.T) {
 				t.Errorf("SetInvalidIntegration() error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
-			err = g.Set(tt.args.ctx, tt.args.payload)
+			err = g.Set(tt.args.ctx, tt.args.payload, tt.args.path, schema)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("SetInvalidIntegration() error = %v, wantErr %v", err, tt.wantErr)
 				return