From a961fe020d69544c9e75465662f6f1a31bf393f0 Mon Sep 17 00:00:00 2001 From: Andre Sterba <andre.sterba@stud.h-da.de> Date: Mon, 2 May 2022 12:53:56 +0000 Subject: [PATCH] Ensure default role and user will be created at controller startup See merge request danet/gosdn!299 --- controller/controller.go | 116 +++++++++++++++++++++++++++++++++------ go.mod | 2 + go.sum | 2 + 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/controller/controller.go b/controller/controller.go index 570c7439a..93cd300d0 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -2,6 +2,7 @@ package controller import ( "context" + "fmt" "net" "net/http" "os" @@ -11,6 +12,7 @@ import ( "time" "github.com/google/uuid" + "github.com/sethvargo/go-password/password" log "github.com/sirupsen/logrus" "github.com/spf13/viper" "google.golang.org/grpc" @@ -39,13 +41,13 @@ var coreOnce sync.Once // Core is the representation of the controller's core type Core struct { - pndc networkdomain.PndStore - userc rbac.UserService - rolec rbac.RoleService - httpServer *http.Server - grpcServer *grpc.Server - nbi *nbi.NorthboundInterface - stopChan chan os.Signal + pndStore networkdomain.PndStore + userService rbac.UserService + roleService rbac.RoleService + httpServer *http.Server + grpcServer *grpc.Server + nbi *nbi.NorthboundInterface + stopChan chan os.Signal csbiClient cpb.CsbiServiceClient } @@ -60,10 +62,10 @@ func initialize() error { } c = &Core{ - pndc: nucleus.NewPndStore(), - userc: rbacImpl.NewUserService(rbacImpl.NewUserStore()), - rolec: rbacImpl.NewRoleService(rbacImpl.NewRoleStore()), - stopChan: make(chan os.Signal, 1), + pndStore: nucleus.NewPndStore(), + userService: rbacImpl.NewUserService(rbacImpl.NewUserStore()), + roleService: rbacImpl.NewRoleService(rbacImpl.NewRoleStore()), + stopChan: make(chan os.Signal, 1), } // Setting up signal capturing @@ -87,6 +89,16 @@ func initialize() error { return err } + err = ensureDefaultRoleExists() + if err != nil { + return err + } + + err = ensureDefaultUserExists() + if err != nil { + return err + } + return nil } @@ -101,7 +113,7 @@ func startGrpc() error { jwtManager := rbacImpl.NewJWTManager("", (10000 * time.Hour)) //TODO(faseid): add real secret and proper duration data here! setupGRPCServerWithCorrectSecurityLevel(jwtManager) - c.nbi = nbi.NewNBI(c.pndc, c.userc, c.rolec) + c.nbi = nbi.NewNBI(c.pndStore, c.userService, c.roleService) c.nbi.Auth = nbi.NewAuthServer(jwtManager) pb.RegisterCoreServiceServer(c.grpcServer, c.nbi.Core) @@ -136,7 +148,7 @@ func createSouthboundInterfaces() (southbound.SouthboundInterface, error) { // createPrincipalNetworkDomain initializes the controller with an initial PND func createPrincipalNetworkDomain() error { - basePnd, err := c.pndc.Get(store.Query{ID: config.BasePndUUID}) + basePnd, err := c.pndStore.Get(store.Query{ID: config.BasePndUUID}) if err != nil { log.Info(err) } @@ -152,7 +164,7 @@ func createPrincipalNetworkDomain() error { if err != nil { return err } - err = c.pndc.Add(pnd) + err = c.pndStore.Add(pnd) if err != nil { return err } @@ -162,6 +174,78 @@ func createPrincipalNetworkDomain() error { return nil } +func ensureDefaultRoleExists() error { + defaultAdminRoleName := "admin" + adminRole, err := c.roleService.Get(store.Query{ID: uuid.Nil, Name: defaultAdminRoleName}) + if err != nil { + log.Info(err) + } + + if adminRole == nil { + err := c.roleService.Add(rbacImpl.NewRole(uuid.New(), defaultAdminRoleName, "admin role", []string{ + "/gosdn.core.CoreService/GetPnd", + "/gosdn.core.CoreService/GetPndList", + "/gosdn.core.CoreService/CreatePndList", + "/gosdn.core.CoreService/DeletePnd", + "/gosdn.rbac.AuthService/CreateUsers", + "/gosdn.rbac.AuthService/GetUser", + "/gosdn.rbac.AuthService/GetUsers", + "/gosdn.rbac.AuthService/UpdateUsers", + "/gosdn.rbac.AuthService/DeleteUsers", + "/gosdn.rbac.AuthService/CreateRoles", + "/gosdn.rbac.AuthService/GetRole", + "/gosdn.rbac.AuthService/GetRoles", + "/gosdn.rbac.AuthService/UpdateRoles", + "/gosdn.rbac.AuthService/DeletePermissionsForRole", + "/gosdn.rbac.AuthService/DeleteRoles", + "/gosdn.pnd.PndService/GetOnd", + "/gosdn.pnd.PndService/GetOndList", + "/gosdn.pnd.PndService/GetSbi", + "/gosdn.pnd.PndService/GetSbiList", + "/gosdn.pnd.PndService/GetPath", + "/gosdn.pnd.PndService/GetChange", + "/gosdn.pnd.PndService/GetChangeList", + "/gosdn.pnd.PndService/SetOndList", + "/gosdn.pnd.PndService/SetChangeList", + "/gosdn.pnd.PndService/SetPathList", + "/gosdn.pnd.PndService/SetSbiList", + "/gosdn.pnd.PndService/DeleteOnd", + "/gosdn.southbound.SbiService/GetSchema", + })) + if err != nil { + return err + } + } + + return nil +} + +func ensureDefaultUserExists() error { + defaultUserName := "admin" + adminUser, err := c.userService.Get(store.Query{ID: uuid.Nil, Name: defaultUserName}) + if err != nil { + log.Info(err) + } + + if adminUser == nil { + // Generate a password that is 16 characters long with 3 digits, 0 symbols, + // allowing upper and lower case letters, disallowing repeat characters. + generatedPassword, err := password.Generate(16, 3, 0, true, false) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("########\n Generated admin password: %s\n ########\n", generatedPassword) + + err = c.userService.Add(rbacImpl.NewUser(uuid.New(), defaultUserName, map[string]string{config.BasePndUUID.String(): "admin"}, generatedPassword, "")) + if err != nil { + return err + } + } + + return nil +} + // Run calls initialize to start the controller func Run(ctx context.Context) error { var initError error @@ -193,10 +277,10 @@ func shutdown() error { func callback(id uuid.UUID, ch chan device.Details) { if ch != nil { - c.pndc.AddPendingChannel(id, ch) + c.pndStore.AddPendingChannel(id, ch) log.Infof("pending channel %v added", id) } else { - c.pndc.RemovePendingChannel(id) + c.pndStore.RemovePendingChannel(id) log.Infof("pending channel %v removed", id) } } diff --git a/go.mod b/go.mod index f14f10e38..866ab3d64 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,8 @@ require ( google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa ) +require github.com/sethvargo/go-password v0.2.0 // indirect + require ( github.com/Microsoft/go-winio v0.5.1 // indirect github.com/Microsoft/hcsshim v0.9.2 // indirect diff --git a/go.sum b/go.sum index f59c16085..2c50c5676 100644 --- a/go.sum +++ b/go.sum @@ -979,6 +979,8 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= +github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -- GitLab