From 99bdf5bda433f04fbb89cc56e28d3a137f6bba04 Mon Sep 17 00:00:00 2001 From: huerni <1547156325@qq.com> Date: Tue, 15 Oct 2024 16:45:36 +0800 Subject: [PATCH 01/11] feat: external tls --- internal/util/grpc.go | 46 ++++++------------------------------------- internal/util/util.go | 12 ++++++----- 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/internal/util/grpc.go b/internal/util/grpc.go index e6d229f4..7a1253f2 100644 --- a/internal/util/grpc.go +++ b/internal/util/grpc.go @@ -28,17 +28,18 @@ import ( "os" "path/filepath" + "google.golang.org/grpc/credentials" + log "github.com/sirupsen/logrus" "google.golang.org/grpc" grpccodes "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" grpcstatus "google.golang.org/grpc/status" ) func GetTCPSocket(bindAddr string, config *Config) (net.Listener, error) { if config.UseTls { - CaCertContent, err := os.ReadFile(config.ServerCertFilePath) + CaCertContent, err := os.ReadFile(config.InternalCaFilePath) if err != nil { return nil, err } @@ -48,7 +49,7 @@ func GetTCPSocket(bindAddr string, config *Config) (net.Listener, error) { return nil, err } - cert, err := tls.LoadX509KeyPair(config.ServerCertFilePath, config.ServerKeyFilePath) + cert, err := tls.LoadX509KeyPair(config.CforedCertFilePath, config.CforedKeyFilePath) if err != nil { return nil, err } @@ -115,46 +116,11 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { if config.UseTls { serverAddr = fmt.Sprintf("%s.%s:%s", config.ControlMachine, config.DomainSuffix, config.CraneCtldListenPort) - - ServerCertContent, err := os.ReadFile(config.ServerCertFilePath) - if err != nil { - log.Errorln("Read server certificate error: " + err.Error()) - os.Exit(ErrorGeneric) - } - - ServerKeyContent, err := os.ReadFile(config.ServerKeyFilePath) - if err != nil { - log.Errorln("Read server key error: " + err.Error()) - os.Exit(ErrorGeneric) - } - - CaCertContent, err := os.ReadFile(config.CaCertFilePath) - if err != nil { - log.Errorln("Read CA certifacate error: " + err.Error()) - os.Exit(ErrorGeneric) - } - - tlsKeyPair, err := tls.X509KeyPair(ServerCertContent, ServerKeyContent) + creds, err := credentials.NewClientTLSFromFile(config.ExternalCertFilePath, fmt.Sprintf("*.%s", config.DomainSuffix)) if err != nil { - log.Errorln("tlsKeyPair error: " + err.Error()) + log.Errorln("Failed to create TLS credentials " + err.Error()) os.Exit(ErrorGeneric) } - - caPool := x509.NewCertPool() - if ok := caPool.AppendCertsFromPEM(CaCertContent); !ok { - log.Errorln("AppendCertsFromPEM error: " + err.Error()) - os.Exit(ErrorGeneric) - } - - creds := credentials.NewTLS(&tls.Config{ - Certificates: []tls.Certificate{tlsKeyPair}, - RootCAs: caPool, - InsecureSkipVerify: false, - // NextProtos is a list of supported application level protocols, in - // order of preference. - NextProtos: []string{"h2"}, - }) - conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds)) if err != nil { log.Errorln("Cannot connect to CraneCtld: " + err.Error()) diff --git a/internal/util/util.go b/internal/util/util.go index a4f60597..3663dd54 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -28,11 +28,13 @@ type Config struct { ControlMachine string `yaml:"ControlMachine"` CraneCtldListenPort string `yaml:"CraneCtldListenPort"` - UseTls bool `yaml:"UseTls"` - ServerCertFilePath string `yaml:"ServerCertFilePath"` - ServerKeyFilePath string `yaml:"ServerKeyFilePath"` - CaCertFilePath string `yaml:"CaCertFilePath"` - DomainSuffix string `yaml:"DomainSuffix"` + UseTls bool `yaml:"UseTls"` + ExternalCertFilePath string `yaml:"CranectldExternalCertFilePath"` + ServerKeyFilePath string `yaml:"ServerKeyFilePath"` + CforedCertFilePath string `yaml:"CforedCertFilePath"` + CforedKeyFilePath string `yaml:"CforedKeyFilePath"` + InternalCaFilePath string `yaml:"InternalCaFilePath"` + DomainSuffix string `yaml:"DomainSuffix"` CraneBaseDir string `yaml:"CraneBaseDir"` CranedCforedSockPath string `yaml:"CranedCforedSockPath"` From 96626cd82819e99791122ee1bcad58c3879363eb Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:41:06 +0800 Subject: [PATCH 02/11] feat: Cfored Tls --- internal/cfored/cfored.go | 2 +- internal/cfored/client.go | 6 ++--- internal/util/grpc.go | 47 +++++++++++++++++++++++++++++++++++++++ internal/util/util.go | 6 +++-- protos/Crane.proto | 18 +++++++++------ 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/internal/cfored/cfored.go b/internal/cfored/cfored.go index db7d9ff4..13b83861 100644 --- a/internal/cfored/cfored.go +++ b/internal/cfored/cfored.go @@ -979,7 +979,7 @@ func StartCfored() { var wgAllRoutines sync.WaitGroup ctldClient := &GrpcCtldClient{ - ctldClientStub: util.GetStubToCtldByConfig(config), + ctldClientStub: util.GetStubToCtldForCfored(config), ctldReplyChannel: make(chan *protos.StreamCtldReply, 8), } wgAllRoutines.Add(1) diff --git a/internal/cfored/client.go b/internal/cfored/client.go index 1281a831..e1145841 100644 --- a/internal/cfored/client.go +++ b/internal/cfored/client.go @@ -28,7 +28,7 @@ import ( ) type GrpcCtldClient struct { - ctldClientStub protos.CraneCtldClient + ctldClientStub protos.CraneCtldForCforedClient ctldReplyChannel chan *protos.StreamCtldReply } @@ -42,7 +42,7 @@ const ( GracefulExit StateOfCtldClient = 4 ) -func (client *GrpcCtldClient) CtldReplyReceiveRoutine(stream protos.CraneCtld_CforedStreamClient) { +func (client *GrpcCtldClient) CtldReplyReceiveRoutine(stream protos.CraneCtldForCfored_CforedStreamClient) { for { m := new(protos.StreamCtldReply) if err := stream.RecvMsg(m); err != nil { @@ -57,7 +57,7 @@ func (client *GrpcCtldClient) CtldReplyReceiveRoutine(stream protos.CraneCtld_Cf func (client *GrpcCtldClient) StartCtldClientStream(wg *sync.WaitGroup) { var request *protos.StreamCforedRequest - var stream protos.CraneCtld_CforedStreamClient + var stream protos.CraneCtldForCfored_CforedStreamClient var err error state := StartReg diff --git a/internal/util/grpc.go b/internal/util/grpc.go index 7a1253f2..23c4b4a8 100644 --- a/internal/util/grpc.go +++ b/internal/util/grpc.go @@ -143,6 +143,53 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { return stub } +func GetStubToCtldForCfored(config *Config) protos.CraneCtldForCforedClient { + var serverAddr string + var stub protos.CraneCtldForCforedClient + + if config.UseTls { + serverAddr = fmt.Sprintf("%s.%s:%s", + config.ControlMachine, config.DomainSuffix, config.CraneCtldForCforedListenPort) + cert, _ := tls.LoadX509KeyPair(config.CforedCertFilePath, config.CforedKeyFilePath) + + CaCertContent, err := os.ReadFile(config.InternalCertFilePath) + if err != nil { + log.Errorln("Failed to read InternalCertFile: " + err.Error()) + os.Exit(ErrorGeneric) + } + + caPool := x509.NewCertPool() + if ok := caPool.AppendCertsFromPEM(CaCertContent); !ok { + log.Errorln("Failed to append cert Content.") + os.Exit(ErrorGeneric) + } + + creds := credentials.NewTLS(&tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caPool, + }) + conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds)) + if err != nil { + log.Errorln("Cannot connect to CraneCtld: " + err.Error()) + os.Exit(ErrorBackend) + } + + stub = protos.NewCraneCtldForCforedClient(conn) + } else { + serverAddr = fmt.Sprintf("%s:%s", config.ControlMachine, config.CraneCtldForCforedListenPort) + + conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + log.Errorf("Cannot connect to CraneCtld %s: %s", serverAddr, err.Error()) + os.Exit(ErrorBackend) + } + + stub = protos.NewCraneCtldForCforedClient(conn) + } + + return stub +} + func GrpcErrorPrintf(err error, format string, a ...any) { s := fmt.Sprintf(format, a...) if rpcErr, ok := grpcstatus.FromError(err); ok { diff --git a/internal/util/util.go b/internal/util/util.go index 3663dd54..a9080289 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -25,11 +25,13 @@ import ( ) type Config struct { - ControlMachine string `yaml:"ControlMachine"` - CraneCtldListenPort string `yaml:"CraneCtldListenPort"` + ControlMachine string `yaml:"ControlMachine"` + CraneCtldListenPort string `yaml:"CraneCtldListenPort"` + CraneCtldForCforedListenPort string `yaml:"CraneCtldForCforedListenPort"` UseTls bool `yaml:"UseTls"` ExternalCertFilePath string `yaml:"CranectldExternalCertFilePath"` + InternalCertFilePath string `yaml:"CranectldInternalCertFilePath"` ServerKeyFilePath string `yaml:"ServerKeyFilePath"` CforedCertFilePath string `yaml:"CforedCertFilePath"` CforedKeyFilePath string `yaml:"CforedKeyFilePath"` diff --git a/protos/Crane.proto b/protos/Crane.proto index 5d7280b1..84e429e2 100644 --- a/protos/Crane.proto +++ b/protos/Crane.proto @@ -750,13 +750,6 @@ message StreamCforedTaskIOReply { // We need to distinguish the message sender // and have some kind of authentication service CraneCtld { - /* RPCs called from Craned */ - rpc TaskStatusChange(TaskStatusChangeRequest) returns (TaskStatusChangeReply); - rpc CranedRegister(CranedRegisterRequest) returns (CranedRegisterReply); - - /* RPCs called from Cfored */ - rpc CforedStream(stream StreamCforedRequest) returns(stream StreamCtldReply); - /* RPCs called from ccancel */ rpc CancelTask(CancelTaskRequest) returns (CancelTaskReply); @@ -796,6 +789,17 @@ service CraneCtld { rpc QueryTasksInfo(QueryTasksInfoRequest) returns (QueryTasksInfoReply); } +service CraneCtldForCraned { + /* RPCs called from Craned */ + rpc TaskStatusChange(TaskStatusChangeRequest) returns (TaskStatusChangeReply); + rpc CranedRegister(CranedRegisterRequest) returns (CranedRegisterReply); +} + +service CraneCtldForCfored { + /* RPCs called from Cfored */ + rpc CforedStream(stream StreamCforedRequest) returns(stream StreamCtldReply); +} + service Craned { /* ----------------------------------- Called from CraneCtld ---------------------------------------------------- */ rpc ExecuteTask(ExecuteTasksRequest) returns(ExecuteTasksReply); From 70549fecb51bfd26b2754fe6097f6a5f79b3761d Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:38:48 +0800 Subject: [PATCH 03/11] feat: token --- internal/util/grpc.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/internal/util/grpc.go b/internal/util/grpc.go index 23c4b4a8..0a87082c 100644 --- a/internal/util/grpc.go +++ b/internal/util/grpc.go @@ -20,6 +20,7 @@ package util import ( "CraneFrontEnd/generated/protos" + "context" "crypto/tls" "crypto/x509" "fmt" @@ -109,6 +110,20 @@ func GetUnixSocket(path string, mode fs.FileMode) (net.Listener, error) { return socket, nil } +type TokeAuth struct { + Token string +} + +func (t *TokeAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { + return map[string]string{ + "Authorization": t.Token, + }, nil +} + +func (t *TokeAuth) RequireTransportSecurity() bool { + return false +} + func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { var serverAddr string var stub protos.CraneCtldClient @@ -121,7 +136,7 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { log.Errorln("Failed to create TLS credentials " + err.Error()) os.Exit(ErrorGeneric) } - conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds)) + conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&TokeAuth{Token: "token"})) if err != nil { log.Errorln("Cannot connect to CraneCtld: " + err.Error()) os.Exit(ErrorBackend) @@ -131,7 +146,7 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { } else { serverAddr = fmt.Sprintf("%s:%s", config.ControlMachine, config.CraneCtldListenPort) - conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithPerRPCCredentials(&TokeAuth{Token: "token"})) if err != nil { log.Errorf("Cannot connect to CraneCtld %s: %s", serverAddr, err.Error()) os.Exit(ErrorBackend) From 927a949d7add6e5180b572bb96a3221b8383f3b6 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:30:43 +0800 Subject: [PATCH 04/11] feat: token --- internal/util/grpc.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/internal/util/grpc.go b/internal/util/grpc.go index 0a87082c..b2818036 100644 --- a/internal/util/grpc.go +++ b/internal/util/grpc.go @@ -110,23 +110,25 @@ func GetUnixSocket(path string, mode fs.FileMode) (net.Listener, error) { return socket, nil } -type TokeAuth struct { - Token string +type TokenAuth struct { + Token string + UseTls bool } -func (t *TokeAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { +func (t *TokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return map[string]string{ "Authorization": t.Token, }, nil } -func (t *TokeAuth) RequireTransportSecurity() bool { - return false +func (t *TokenAuth) RequireTransportSecurity() bool { + return t.UseTls } func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { var serverAddr string var stub protos.CraneCtldClient + token_auth := TokenAuth{Token: "token", UseTls: config.UseTls} if config.UseTls { serverAddr = fmt.Sprintf("%s.%s:%s", @@ -136,7 +138,7 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { log.Errorln("Failed to create TLS credentials " + err.Error()) os.Exit(ErrorGeneric) } - conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&TokeAuth{Token: "token"})) + conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&token_auth)) if err != nil { log.Errorln("Cannot connect to CraneCtld: " + err.Error()) os.Exit(ErrorBackend) @@ -146,7 +148,7 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { } else { serverAddr = fmt.Sprintf("%s:%s", config.ControlMachine, config.CraneCtldListenPort) - conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithPerRPCCredentials(&TokeAuth{Token: "token"})) + conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithPerRPCCredentials(&token_auth)) if err != nil { log.Errorf("Cannot connect to CraneCtld %s: %s", serverAddr, err.Error()) os.Exit(ErrorBackend) From 629a164d7d6ac0bb2e6e322360f5746fe4560542 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:05:15 +0800 Subject: [PATCH 05/11] feat: User adds password information. --- internal/cacctmgr/CmdArgParser.go | 4 ++++ protos/PublicDefs.proto | 11 ++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/internal/cacctmgr/CmdArgParser.go b/internal/cacctmgr/CmdArgParser.go index e395c0f9..8492b6d0 100644 --- a/internal/cacctmgr/CmdArgParser.go +++ b/internal/cacctmgr/CmdArgParser.go @@ -468,6 +468,7 @@ func init() { addCmd.AddCommand(addUserCmd) { addUserCmd.Flags().StringVarP(&FlagUser.Name, "name", "N", "", "Set the name of the user") + addUserCmd.Flags().StringVarP(&FlagUser.Password, "password", "P", "", "Set the password of the user") addUserCmd.Flags().StringVarP(&FlagUser.Account, "account", "A", "", "Set the account of the user") addUserCmd.Flags().StringSliceVarP(&FlagUserPartitions, "partition", "p", nil, "Set allowed partitions of the user (comma seperated list)") addUserCmd.Flags().StringVarP(&FlagLevel, "level", "L", "none", "Set admin level (none/operator) of the user") @@ -475,6 +476,9 @@ func init() { if err := addUserCmd.MarkFlagRequired("name"); err != nil { log.Fatalln("Can't mark 'name' flag required") } + if err := addUserCmd.MarkFlagRequired("password"); err != nil { + log.Fatalln("Can't mark 'password' flag required") + } if err := addUserCmd.MarkFlagRequired("account"); err != nil { log.Fatalln("Can't mark 'account' flag required") } diff --git a/protos/PublicDefs.proto b/protos/PublicDefs.proto index bdef921f..349a77e3 100644 --- a/protos/PublicDefs.proto +++ b/protos/PublicDefs.proto @@ -445,11 +445,12 @@ message UserInfo { uint32 uid = 1; string name = 2; - string account = 3; - bool blocked = 4; - repeated AllowedPartitionQos allowed_partition_qos_list = 5; - repeated string coordinator_accounts = 6; - AdminLevel admin_level = 7; + string password = 3; + string account = 4; + bool blocked = 5; + repeated AllowedPartitionQos allowed_partition_qos_list = 6; + repeated string coordinator_accounts = 7; + AdminLevel admin_level = 8; } message QosInfo { From 25b2bd60e812cc642456c65a2a7ab62b4affafbd Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:12:45 +0800 Subject: [PATCH 06/11] feat: clogin --- cmd/clogin/clogin.go | 25 ++++++++++++++ internal/clogin/CmdArgParser.go | 60 +++++++++++++++++++++++++++++++++ internal/clogin/clogin.go | 34 +++++++++++++++++++ internal/util/os.go | 13 +++++++ internal/util/util.go | 2 ++ protos/Crane.proto | 13 +++++++ 6 files changed, 147 insertions(+) create mode 100644 cmd/clogin/clogin.go create mode 100644 internal/clogin/CmdArgParser.go create mode 100644 internal/clogin/clogin.go diff --git a/cmd/clogin/clogin.go b/cmd/clogin/clogin.go new file mode 100644 index 00000000..70aa193d --- /dev/null +++ b/cmd/clogin/clogin.go @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2023 Peking University and Peking University + * Changsha Institute for Computing and Digital Economy + * + * CraneSched is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of + * the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package main + +import ( + "CraneFrontEnd/internal/clogin" +) + +func main() { + clogin.ParseCmdArgs() +} diff --git a/internal/clogin/CmdArgParser.go b/internal/clogin/CmdArgParser.go new file mode 100644 index 00000000..353e96ae --- /dev/null +++ b/internal/clogin/CmdArgParser.go @@ -0,0 +1,60 @@ +package clogin + +import ( + "CraneFrontEnd/internal/util" + "os" + + log "github.com/sirupsen/logrus" + + "github.com/spf13/cobra" +) + +var ( + FlagUserName string + FlagPassword string + FlagConfigFilePath string + + RootCmd = &cobra.Command{ + Use: "login [flags]", + Short: "Login with your username and password", + Long: "", + Version: util.Version(), + Args: func(cmd *cobra.Command, args []string) error { + if FlagUserName == "" { + log.Error("Username must be provided") + os.Exit(util.ErrorCmdArg) + } + + if FlagPassword == "" { + log.Error("Password must be provided") + os.Exit(util.ErrorCmdArg) + } + + return nil + }, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + util.DetectNetworkProxy() + config := util.ParseConfig(FlagConfigFilePath) + stub = util.GetStubToCtldByConfig(config) + }, + Run: func(cmd *cobra.Command, args []string) { + if err := Login(FlagUserName, FlagPassword); err != util.ErrorSuccess { + os.Exit(err) + } + }, + } +) + +func ParseCmdArgs() { + if err := RootCmd.Execute(); err != nil { + os.Exit(util.ErrorGeneric) + } +} + +func init() { + RootCmd.SetVersionTemplate(util.VersionTemplate()) + RootCmd.PersistentFlags().StringVarP(&FlagConfigFilePath, "config", "C", + util.DefaultConfigPath, "Path to configuration file") + RootCmd.Flags().StringVarP(&FlagUserName, "name", "N", "", "Set the name of the user") + RootCmd.Flags().StringVarP(&FlagPassword, "password", "P", "", "Set the password of the user") +} diff --git a/internal/clogin/clogin.go b/internal/clogin/clogin.go new file mode 100644 index 00000000..ca89121a --- /dev/null +++ b/internal/clogin/clogin.go @@ -0,0 +1,34 @@ +package clogin + +import ( + "CraneFrontEnd/generated/protos" + "CraneFrontEnd/internal/util" + "context" + + log "github.com/sirupsen/logrus" +) + +var ( + stub protos.CraneCtldClient +) + +func Login(username string, password string) util.CraneCmdError { + config := util.ParseConfig(FlagConfigFilePath) + stub = util.GetStubToCtldByConfig(config) + req := protos.LoginRequest{Username: username, Password: password} + var reply *protos.LoginReply + var err error + + reply, err = stub.Login(context.Background(), &req) + if err != nil { + util.GrpcErrorPrintf(err, "Failed to login") + return util.ErrorNetwork + } + // TODO: 保存token + err = util.SaveFileWithPermissions(util.DefaultJwtTokenPath, []byte(reply.GetToken()), 0600) + if err != nil { + log.Errorf(err.Error()) + return util.ErrorGeneric + } + return util.ErrorSuccess +} diff --git a/internal/util/os.go b/internal/util/os.go index 150c831f..75569039 100644 --- a/internal/util/os.go +++ b/internal/util/os.go @@ -28,6 +28,19 @@ import ( log "github.com/sirupsen/logrus" ) +func SaveFileWithPermissions(path string, content []byte, perm os.FileMode) error { + err := os.WriteFile(path, content, perm) + if err != nil { + return fmt.Errorf("error writing file: %w", err) + } + + err = os.Chmod(path, perm) + if err != nil { + return fmt.Errorf("error setting file permissions: %w", err) + } + return nil +} + func RemoveFileIfExists(path string) bool { if _, err := os.Stat(path); err == nil { err := os.Remove(path) diff --git a/internal/util/util.go b/internal/util/util.go index a9080289..0e7a794c 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -49,6 +49,8 @@ const ( DefaultPlugindSocketPath = "cplugind/cplugind.sock" + DefaultJwtTokenPath = "~/.config/crane/token" + DefaultCforedSocketPath = "craned/cfored.sock" DefaultCforedServerListenAddress = "0.0.0.0" DefaultCforedServerListenPort = "10012" diff --git a/protos/Crane.proto b/protos/Crane.proto index 84e429e2..07061d77 100644 --- a/protos/Crane.proto +++ b/protos/Crane.proto @@ -746,6 +746,16 @@ message StreamCforedTaskIOReply { } } +message LoginRequest { + string username = 1; + string password = 2; +} + +message LoginReply { + bool ok = 1; + string token = 2; +} + // Todo: Divide service into two parts: one for Craned and one for Crun // We need to distinguish the message sender // and have some kind of authentication @@ -785,6 +795,9 @@ service CraneCtld { /* RPCs called from cinfo */ rpc QueryClusterInfo(QueryClusterInfoRequest) returns (QueryClusterInfoReply); + /* RPCs called from clogin */ + rpc Login(LoginRequest) returns (LoginReply); + /* common RPCs */ rpc QueryTasksInfo(QueryTasksInfoRequest) returns (QueryTasksInfoReply); } From dd3e3efc74aac8117e2f70e2e3a87b979fc75623 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:13:13 +0800 Subject: [PATCH 07/11] refactor login --- go.mod | 2 ++ go.sum | 4 ++++ internal/clogin/CmdArgParser.go | 26 ++++++++++++-------------- internal/clogin/clogin.go | 7 ++++--- internal/util/util.go | 2 +- protos/Crane.proto | 3 ++- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 2b862662..96d678af 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/tidwall/gjson v1.17.3 github.com/tidwall/sjson v1.2.5 github.com/xlab/treeprint v1.2.0 + golang.org/x/crypto v0.26.0 golang.org/x/sys v0.24.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 @@ -33,6 +34,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect golang.org/x/net v0.28.0 // indirect + golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index 359cd7ef..e0245ca8 100644 --- a/go.sum +++ b/go.sum @@ -70,12 +70,16 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= diff --git a/internal/clogin/CmdArgParser.go b/internal/clogin/CmdArgParser.go index 353e96ae..19b324bc 100644 --- a/internal/clogin/CmdArgParser.go +++ b/internal/clogin/CmdArgParser.go @@ -2,33 +2,32 @@ package clogin import ( "CraneFrontEnd/internal/util" + "fmt" "os" - log "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh/terminal" "github.com/spf13/cobra" ) var ( - FlagUserName string FlagPassword string FlagConfigFilePath string RootCmd = &cobra.Command{ Use: "login [flags]", - Short: "Login with your username and password", + Short: "Login with your password", Long: "", Version: util.Version(), Args: func(cmd *cobra.Command, args []string) error { - if FlagUserName == "" { - log.Error("Username must be provided") - os.Exit(util.ErrorCmdArg) - } - - if FlagPassword == "" { - log.Error("Password must be provided") - os.Exit(util.ErrorCmdArg) + fmt.Print("Enter Password: ") + bytePassword, err := terminal.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + fmt.Println("\nError reading password:", err) + os.Exit(1) } + FlagPassword = string(bytePassword) + fmt.Println() return nil }, @@ -36,9 +35,10 @@ var ( util.DetectNetworkProxy() config := util.ParseConfig(FlagConfigFilePath) stub = util.GetStubToCtldByConfig(config) + userUid = uint32(os.Getuid()) }, Run: func(cmd *cobra.Command, args []string) { - if err := Login(FlagUserName, FlagPassword); err != util.ErrorSuccess { + if err := Login(FlagPassword); err != util.ErrorSuccess { os.Exit(err) } }, @@ -55,6 +55,4 @@ func init() { RootCmd.SetVersionTemplate(util.VersionTemplate()) RootCmd.PersistentFlags().StringVarP(&FlagConfigFilePath, "config", "C", util.DefaultConfigPath, "Path to configuration file") - RootCmd.Flags().StringVarP(&FlagUserName, "name", "N", "", "Set the name of the user") - RootCmd.Flags().StringVarP(&FlagPassword, "password", "P", "", "Set the password of the user") } diff --git a/internal/clogin/clogin.go b/internal/clogin/clogin.go index ca89121a..71ca928e 100644 --- a/internal/clogin/clogin.go +++ b/internal/clogin/clogin.go @@ -9,13 +9,14 @@ import ( ) var ( - stub protos.CraneCtldClient + userUid uint32 + stub protos.CraneCtldClient ) -func Login(username string, password string) util.CraneCmdError { +func Login(password string) util.CraneCmdError { config := util.ParseConfig(FlagConfigFilePath) stub = util.GetStubToCtldByConfig(config) - req := protos.LoginRequest{Username: username, Password: password} + req := protos.LoginRequest{Uid: userUid, Password: password} var reply *protos.LoginReply var err error diff --git a/internal/util/util.go b/internal/util/util.go index 0e7a794c..8112d7bb 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -49,7 +49,7 @@ const ( DefaultPlugindSocketPath = "cplugind/cplugind.sock" - DefaultJwtTokenPath = "~/.config/crane/token" + DefaultJwtTokenPath = "~/.config/crane/token.pem" DefaultCforedSocketPath = "craned/cfored.sock" DefaultCforedServerListenAddress = "0.0.0.0" diff --git a/protos/Crane.proto b/protos/Crane.proto index 07061d77..b2fe161d 100644 --- a/protos/Crane.proto +++ b/protos/Crane.proto @@ -747,13 +747,14 @@ message StreamCforedTaskIOReply { } message LoginRequest { - string username = 1; + uint32 uid = 1; string password = 2; } message LoginReply { bool ok = 1; string token = 2; + string reason = 3; } // Todo: Divide service into two parts: one for Craned and one for Crun From a9547d883a27f1feb915f38cdc9341541d04dd03 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:02:17 +0800 Subject: [PATCH 08/11] feat: save token file --- internal/clogin/clogin.go | 13 +++++++++---- internal/util/grpc.go | 8 +++++++- internal/util/os.go | 31 +++++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/internal/clogin/clogin.go b/internal/clogin/clogin.go index 71ca928e..43952561 100644 --- a/internal/clogin/clogin.go +++ b/internal/clogin/clogin.go @@ -4,8 +4,7 @@ import ( "CraneFrontEnd/generated/protos" "CraneFrontEnd/internal/util" "context" - - log "github.com/sirupsen/logrus" + "fmt" ) var ( @@ -25,11 +24,17 @@ func Login(password string) util.CraneCmdError { util.GrpcErrorPrintf(err, "Failed to login") return util.ErrorNetwork } - // TODO: 保存token + + if !reply.GetOk() { + fmt.Printf("Login failed: %s.\n", reply.GetReason()) + return util.ErrorBackend + } + err = util.SaveFileWithPermissions(util.DefaultJwtTokenPath, []byte(reply.GetToken()), 0600) if err != nil { - log.Errorf(err.Error()) + fmt.Printf("Failed to save token file: %s. \n", err.Error()) return util.ErrorGeneric } + fmt.Println("Login succeeded.") return util.ErrorSuccess } diff --git a/internal/util/grpc.go b/internal/util/grpc.go index b2818036..ab5c5e41 100644 --- a/internal/util/grpc.go +++ b/internal/util/grpc.go @@ -128,8 +128,14 @@ func (t *TokenAuth) RequireTransportSecurity() bool { func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { var serverAddr string var stub protos.CraneCtldClient - token_auth := TokenAuth{Token: "token", UseTls: config.UseTls} + tokenFilePath, err := ExpandPath(DefaultJwtTokenPath) + if err != nil { + log.Errorln("Failed to get home dir: " + err.Error()) + os.Exit(ErrorGeneric) + } + TokenContent, _ := os.ReadFile(tokenFilePath) + token_auth := TokenAuth{Token: string(TokenContent), UseTls: config.UseTls} if config.UseTls { serverAddr = fmt.Sprintf("%s.%s:%s", config.ControlMachine, config.DomainSuffix, config.CraneCtldListenPort) diff --git a/internal/util/os.go b/internal/util/os.go index 75569039..6fe967a2 100644 --- a/internal/util/os.go +++ b/internal/util/os.go @@ -21,6 +21,7 @@ package util import ( "fmt" "os" + "path/filepath" "strconv" "strings" "syscall" @@ -28,15 +29,37 @@ import ( log "github.com/sirupsen/logrus" ) +func ExpandPath(path string) (string, error) { + if len(path) > 0 && path[0] == '~' { + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + return filepath.Join(home, path[1:]), nil + } + return path, nil +} + func SaveFileWithPermissions(path string, content []byte, perm os.FileMode) error { - err := os.WriteFile(path, content, perm) + filePath, err := ExpandPath(path) + if err != nil { + return err + } + dir := filepath.Dir(filePath) + if _, err := os.Stat(dir); os.IsNotExist(err) { + err := os.MkdirAll(dir, 0755) + if err != nil { + return err + } + } + err = os.WriteFile(filePath, content, perm) if err != nil { - return fmt.Errorf("error writing file: %w", err) + return err } - err = os.Chmod(path, perm) + err = os.Chmod(filePath, perm) if err != nil { - return fmt.Errorf("error setting file permissions: %w", err) + return err } return nil } From 708f3757fcfea915b9297e346efda01b1c10e193 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:49:18 +0800 Subject: [PATCH 09/11] refactor: config --- internal/util/grpc.go | 14 +++++++------- internal/util/util.go | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/internal/util/grpc.go b/internal/util/grpc.go index ab5c5e41..a1abd533 100644 --- a/internal/util/grpc.go +++ b/internal/util/grpc.go @@ -40,7 +40,7 @@ import ( func GetTCPSocket(bindAddr string, config *Config) (net.Listener, error) { if config.UseTls { - CaCertContent, err := os.ReadFile(config.InternalCaFilePath) + CaCertContent, err := os.ReadFile(config.SslConfig.InternalCaFilePath) if err != nil { return nil, err } @@ -50,7 +50,7 @@ func GetTCPSocket(bindAddr string, config *Config) (net.Listener, error) { return nil, err } - cert, err := tls.LoadX509KeyPair(config.CforedCertFilePath, config.CforedKeyFilePath) + cert, err := tls.LoadX509KeyPair(config.SslConfig.CforedCertFilePath, config.SslConfig.CforedKeyFilePath) if err != nil { return nil, err } @@ -138,8 +138,8 @@ func GetStubToCtldByConfig(config *Config) protos.CraneCtldClient { token_auth := TokenAuth{Token: string(TokenContent), UseTls: config.UseTls} if config.UseTls { serverAddr = fmt.Sprintf("%s.%s:%s", - config.ControlMachine, config.DomainSuffix, config.CraneCtldListenPort) - creds, err := credentials.NewClientTLSFromFile(config.ExternalCertFilePath, fmt.Sprintf("*.%s", config.DomainSuffix)) + config.ControlMachine, config.SslConfig.DomainSuffix, config.CraneCtldListenPort) + creds, err := credentials.NewClientTLSFromFile(config.SslConfig.ExternalCertFilePath, fmt.Sprintf("*.%s", config.SslConfig.DomainSuffix)) if err != nil { log.Errorln("Failed to create TLS credentials " + err.Error()) os.Exit(ErrorGeneric) @@ -172,10 +172,10 @@ func GetStubToCtldForCfored(config *Config) protos.CraneCtldForCforedClient { if config.UseTls { serverAddr = fmt.Sprintf("%s.%s:%s", - config.ControlMachine, config.DomainSuffix, config.CraneCtldForCforedListenPort) - cert, _ := tls.LoadX509KeyPair(config.CforedCertFilePath, config.CforedKeyFilePath) + config.ControlMachine, config.SslConfig.DomainSuffix, config.CraneCtldForCforedListenPort) + cert, _ := tls.LoadX509KeyPair(config.SslConfig.CforedCertFilePath, config.SslConfig.CforedKeyFilePath) - CaCertContent, err := os.ReadFile(config.InternalCertFilePath) + CaCertContent, err := os.ReadFile(config.SslConfig.InternalCertFilePath) if err != nil { log.Errorln("Failed to read InternalCertFile: " + err.Error()) os.Exit(ErrorGeneric) diff --git a/internal/util/util.go b/internal/util/util.go index 8112d7bb..bf892e57 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -24,12 +24,7 @@ import ( "strings" ) -type Config struct { - ControlMachine string `yaml:"ControlMachine"` - CraneCtldListenPort string `yaml:"CraneCtldListenPort"` - CraneCtldForCforedListenPort string `yaml:"CraneCtldForCforedListenPort"` - - UseTls bool `yaml:"UseTls"` +type SSLConfig struct { ExternalCertFilePath string `yaml:"CranectldExternalCertFilePath"` InternalCertFilePath string `yaml:"CranectldInternalCertFilePath"` ServerKeyFilePath string `yaml:"ServerKeyFilePath"` @@ -37,9 +32,15 @@ type Config struct { CforedKeyFilePath string `yaml:"CforedKeyFilePath"` InternalCaFilePath string `yaml:"InternalCaFilePath"` DomainSuffix string `yaml:"DomainSuffix"` - - CraneBaseDir string `yaml:"CraneBaseDir"` - CranedCforedSockPath string `yaml:"CranedCforedSockPath"` +} +type Config struct { + ControlMachine string `yaml:"ControlMachine"` + CraneCtldListenPort string `yaml:"CraneCtldListenPort"` + CraneCtldForCforedListenPort string `yaml:"CraneCtldForCforedListenPort"` + SslConfig SSLConfig `yaml:"SSL"` + UseTls bool `yaml:"UseTls"` + CraneBaseDir string `yaml:"CraneBaseDir"` + CranedCforedSockPath string `yaml:"CranedCforedSockPath"` } // Path = BaseDir + Dir + Name From da14caee7f510eeefc99c8876ed46a9ff7cbf407 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:07:15 +0800 Subject: [PATCH 10/11] refactor --- internal/cacctmgr/CmdArgParser.go | 32 ++++++------ internal/cacctmgr/cacctmgr.go | 4 +- internal/clogin/clogin.go | 2 +- internal/util/err.go | 2 + protos/Crane.proto | 6 +-- protos/PublicDefs.proto | 81 ++++++++++++++++--------------- 6 files changed, 65 insertions(+), 62 deletions(-) diff --git a/internal/cacctmgr/CmdArgParser.go b/internal/cacctmgr/CmdArgParser.go index 8492b6d0..08ca3d12 100644 --- a/internal/cacctmgr/CmdArgParser.go +++ b/internal/cacctmgr/CmdArgParser.go @@ -185,7 +185,7 @@ var ( Run: func(cmd *cobra.Command, args []string) { err := util.ErrorSuccess if cmd.Flags().Changed("description") { //See if a flag was set by the user - err = ModifyAccount(protos.ModifyField_Description, FlagAccount.Description, FlagAccount.Name, protos.OperatorType_Overwrite) + err = ModifyAccount(protos.ModifyField_Description, FlagAccount.Description, FlagAccount.Name, protos.OperationType_Overwrite) } if err != util.ErrorSuccess { os.Exit(err) @@ -194,27 +194,27 @@ var ( // ModifyAccount("parent_account", FlagAccount.ParentAccount, FlagName, protos.ModifyEntityRequest_Overwrite) //} if cmd.Flags().Changed("set-allowed-partition") { - err = ModifyAccount(protos.ModifyField_Partition, strings.Join(FlagAccount.AllowedPartitions, ","), FlagAccount.Name, protos.OperatorType_Overwrite) + err = ModifyAccount(protos.ModifyField_Partition, strings.Join(FlagAccount.AllowedPartitions, ","), FlagAccount.Name, protos.OperationType_Overwrite) } else if cmd.Flags().Changed("add-allowed-partition") { - err = ModifyAccount(protos.ModifyField_Partition, FlagSetPartition, FlagAccount.Name, protos.OperatorType_Add) + err = ModifyAccount(protos.ModifyField_Partition, FlagSetPartition, FlagAccount.Name, protos.OperationType_Add) } else if cmd.Flags().Changed("delete-allowed-partition") { - err = ModifyAccount(protos.ModifyField_Partition, FlagSetPartition, FlagAccount.Name, protos.OperatorType_Delete) + err = ModifyAccount(protos.ModifyField_Partition, FlagSetPartition, FlagAccount.Name, protos.OperationType_Delete) } if err != util.ErrorSuccess { os.Exit(err) } if cmd.Flags().Changed("set-allowed-qos-list") { - err = ModifyAccount(protos.ModifyField_Qos, strings.Join(FlagAccount.AllowedQosList, ","), FlagAccount.Name, protos.OperatorType_Overwrite) + err = ModifyAccount(protos.ModifyField_Qos, strings.Join(FlagAccount.AllowedQosList, ","), FlagAccount.Name, protos.OperationType_Overwrite) } else if cmd.Flags().Changed("add-allowed-qos-list") { - err = ModifyAccount(protos.ModifyField_Qos, FlagQos.Name, FlagAccount.Name, protos.OperatorType_Add) + err = ModifyAccount(protos.ModifyField_Qos, FlagQos.Name, FlagAccount.Name, protos.OperationType_Add) } else if cmd.Flags().Changed("delete-allowed-qos-list") { - err = ModifyAccount(protos.ModifyField_Qos, FlagQos.Name, FlagAccount.Name, protos.OperatorType_Delete) + err = ModifyAccount(protos.ModifyField_Qos, FlagQos.Name, FlagAccount.Name, protos.OperationType_Delete) } if err != util.ErrorSuccess { os.Exit(err) } if cmd.Flags().Changed("default-qos") { - err = ModifyAccount(protos.ModifyField_DefaultQos, FlagAccount.DefaultQos, FlagAccount.Name, protos.OperatorType_Overwrite) + err = ModifyAccount(protos.ModifyField_DefaultQos, FlagAccount.DefaultQos, FlagAccount.Name, protos.OperationType_Overwrite) } if err != util.ErrorSuccess { os.Exit(err) @@ -239,33 +239,33 @@ var ( err := util.ErrorSuccess // Check if a flag was set explicitly if cmd.Flags().Changed("admin-level") { - err = ModifyUser(protos.ModifyField_AdminLevel, FlagSetLevel, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Overwrite) + err = ModifyUser(protos.ModifyField_AdminLevel, FlagSetLevel, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Overwrite) } if err != util.ErrorSuccess { os.Exit(err) } if cmd.Flags().Changed("set-allowed-partition") { - err = ModifyUser(protos.ModifyField_Partition, strings.Join(FlagUserPartitions, ","), FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Overwrite) + err = ModifyUser(protos.ModifyField_Partition, strings.Join(FlagUserPartitions, ","), FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Overwrite) } else if cmd.Flags().Changed("add-allowed-partition") { - err = ModifyUser(protos.ModifyField_Partition, FlagSetPartition, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Add) + err = ModifyUser(protos.ModifyField_Partition, FlagSetPartition, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Add) } else if cmd.Flags().Changed("delete-allowed-partition") { - err = ModifyUser(protos.ModifyField_Partition, FlagSetPartition, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Delete) + err = ModifyUser(protos.ModifyField_Partition, FlagSetPartition, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Delete) } if err != util.ErrorSuccess { os.Exit(err) } if cmd.Flags().Changed("set-allowed-qos-list") { - err = ModifyUser(protos.ModifyField_Qos, strings.Join(FlagUserQosList, ","), FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Overwrite) + err = ModifyUser(protos.ModifyField_Qos, strings.Join(FlagUserQosList, ","), FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Overwrite) } else if cmd.Flags().Changed("add-allowed-qos-list") { - err = ModifyUser(protos.ModifyField_Qos, FlagQos.Name, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Add) + err = ModifyUser(protos.ModifyField_Qos, FlagQos.Name, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Add) } else if cmd.Flags().Changed("delete-allowed-qos-list") { - err = ModifyUser(protos.ModifyField_Qos, FlagQos.Name, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Delete) + err = ModifyUser(protos.ModifyField_Qos, FlagQos.Name, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Delete) } if err != util.ErrorSuccess { os.Exit(err) } if cmd.Flags().Changed("default-qos") { - err = ModifyUser(protos.ModifyField_DefaultQos, FlagUserDefaultQos, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperatorType_Overwrite) + err = ModifyUser(protos.ModifyField_DefaultQos, FlagUserDefaultQos, FlagUser.Name, FlagUser.Account, FlagPartition, protos.OperationType_Overwrite) } if err != util.ErrorSuccess { os.Exit(err) diff --git a/internal/cacctmgr/cacctmgr.go b/internal/cacctmgr/cacctmgr.go index 13be9d91..64409829 100644 --- a/internal/cacctmgr/cacctmgr.go +++ b/internal/cacctmgr/cacctmgr.go @@ -557,7 +557,7 @@ func DeleteQos(name string) util.CraneCmdError { } } -func ModifyAccount(modify_field protos.ModifyField, new_value string, name string, requestType protos.OperatorType) util.CraneCmdError { +func ModifyAccount(modify_field protos.ModifyField, new_value string, name string, requestType protos.OperationType) util.CraneCmdError { req := protos.ModifyAccountRequest{ Uid: userUid, ModifyField: modify_field, @@ -590,7 +590,7 @@ func ModifyAccount(modify_field protos.ModifyField, new_value string, name strin } } -func ModifyUser(modify_field protos.ModifyField, new_value string, name string, account string, partition string, requestType protos.OperatorType) util.CraneCmdError { +func ModifyUser(modify_field protos.ModifyField, new_value string, name string, account string, partition string, requestType protos.OperationType) util.CraneCmdError { if modify_field == protos.ModifyField_AdminLevel { if new_value != "none" && new_value != "operator" && new_value != "admin" { log.Errorf("Unknown admin level, valid values: none, operator, admin.") diff --git a/internal/clogin/clogin.go b/internal/clogin/clogin.go index 43952561..dee7a0cf 100644 --- a/internal/clogin/clogin.go +++ b/internal/clogin/clogin.go @@ -26,7 +26,7 @@ func Login(password string) util.CraneCmdError { } if !reply.GetOk() { - fmt.Printf("Login failed: %s.\n", reply.GetReason()) + fmt.Printf("Login failed: %s.\n", util.ErrMsg(reply.GetReason())) return util.ErrorBackend } diff --git a/internal/util/err.go b/internal/util/err.go index fbb3c554..32e81caa 100644 --- a/internal/util/err.go +++ b/internal/util/err.go @@ -57,6 +57,8 @@ func ErrMsg(err_code protos.ErrCode) string { return "The user does not belong to this account" case protos.ErrCode_ERR_NO_ACCOUNT_SPECIFIED: return "No account is specified for the user" + case protos.ErrCode_ERR_PASSWORD_MISMATCH: + return "The entered password is incorrect." default: break } diff --git a/protos/Crane.proto b/protos/Crane.proto index b2fe161d..2c8b300e 100644 --- a/protos/Crane.proto +++ b/protos/Crane.proto @@ -301,7 +301,7 @@ message ModifyAccountRequest { ModifyField modify_field = 2; //modify item field string value = 3; //new value string name = 4; - OperatorType type = 5; + OperationType type = 5; bool force = 6; } @@ -316,7 +316,7 @@ message ModifyUserRequest { string value = 3; //new value string name = 4; string partition = 5; - OperatorType type = 6; + OperationType type = 6; string account = 8; bool force = 9; } @@ -754,7 +754,7 @@ message LoginRequest { message LoginReply { bool ok = 1; string token = 2; - string reason = 3; + ErrCode reason = 3; } // Todo: Divide service into two parts: one for Craned and one for Crun diff --git a/protos/PublicDefs.proto b/protos/PublicDefs.proto index 349a77e3..fed33683 100644 --- a/protos/PublicDefs.proto +++ b/protos/PublicDefs.proto @@ -318,46 +318,47 @@ message TrimmedPartitionInfo { enum ErrCode { SUCCESS = 0; // Success - - ERR_INVALID_UID = 10001; // Invalid UID passed - ERR_INVALID_OP_USER = 10002; // Invalid operation user - ERR_INVALID_USER = 10003; // Invalid user - ERR_PERMISSION_USER = 10004; // User permissions too low, no permission to operate - ERR_USER_DUPLICATE_ACCOUNT= 10005; // User duplicate account insertion - ERR_USER_ALLOWED_ACCOUNT = 10006; // User does not have permission for the account - ERR_INVALID_ADMIN_LEVEL = 10007; // Invalid permission level - ERR_USER_ACCOUNT_MISMATCH = 10008; // User does not belong to the account + + ERR_INVALID_UID = 10001; + ERR_INVALID_OP_USER = 10002; + ERR_INVALID_USER = 10003; + ERR_PERMISSION_USER = 10004; + ERR_USER_DUPLICATE_ACCOUNT = 10005; + ERR_USER_ALLOWED_ACCOUNT = 10006; + ERR_INVALID_ADMIN_LEVEL = 10007; + ERR_USER_ACCOUNT_MISMATCH = 10008; ERR_NO_ACCOUNT_SPECIFIED = 10009; - - ERR_INVALID_ACCOUNT = 10010; // Invalid account - ERR_DUPLICATE_ACCOUNT = 10011; // Duplicate account insertion - ERR_INVALID_PARENTACCOUNT = 10012; // Invalid parent account - ERR_DELETE_ACCOUNT = 10013; // Account has child nodes - - ERR_INVALID_PARTITION = 10014; // Invalid partition, partition does not exist - ERR_ALLOWED_PARTITION = 10015; // Account/user does not include this partition - ERR_DUPLICATE_PARTITION = 10016; // Account/user duplicate insertion - ERR_PARENT_ALLOWED_PARTITION = 10017; // Parent account does not include this partition - ERR_USER_EMPTY_PARTITION = 10018; // Cannot add QoS when user has no partition - ERR_CHILD_HAS_PARTITION = 10019; // Partition '{}' is used by some descendant node of the account '{}'. Ignoring this constraint with forced operation. - - ERR_INVALID_QOS = 10020; // Invalid QoS, QoS does not exist - ERR_DB_DUPLICATE_QOS = 10021; // Duplicate QoS insertion in the database. - ERR_DELETE_QOS = 10022; // QoS reference count is not zero. - ERR_CONVERT_TO_INTERGER = 10023; // String to integer conversion failed - ERR_TIME_LIMIT = 10024; // Invalid time value - ERR_ALLOWED_QOS = 10025; // Account/user does not include this QoS. - ERR_DUPLICATE_QOS = 10026; // Account/user duplicate insertion. - ERR_PARENT_ALLOWED_QOS = 10027; // Parent account does not include this QoS. - ERR_SET_ALLOWED_QOS = 10028; // QoS '{}' is the default QoS of partition '{}', but not found in the new QoS list. - ERR_ALLOWED_DEFAULT_QOS = 10029; // Default QoS is not in the allowed QoS list - ERR_DUPLICATE_DEFAULT_QOS = 10030; // Duplicate default QoS setting - ERR_CHILD_HAS_DEFAULT_QOS = 10031; // Someone is using QoS '{}' as default QoS. Ignoring this constraint with forced deletion, the deleted default QoS is randomly replaced with one of the remaining items in the QoS list. - ERR_SET_ACCOUNT_QOS = 10032; // QoS '{}' is used by some descendant node or itself of the account '{}'. Ignoring this constraint with forced operation. - ERR_SET_DEFAULT_QOS = 10033; // Qos '{}' not in allowed qos list or is already the default qos - ERR_IS_DEFAULT_QOS = 10034; - - ERR_UPDATE_DATABASE = 10035; // Database update failed + ERR_PASSWORD_MISMATCH = 100010; + + ERR_INVALID_ACCOUNT = 10011; + ERR_DUPLICATE_ACCOUNT = 10012; + ERR_INVALID_PARENTACCOUNT = 10013; + ERR_DELETE_ACCOUNT = 10014; + + ERR_INVALID_PARTITION = 10015; + ERR_ALLOWED_PARTITION = 10016; + ERR_DUPLICATE_PARTITION = 10017; + ERR_PARENT_ALLOWED_PARTITION = 10018; + ERR_USER_EMPTY_PARTITION = 10019; + ERR_CHILD_HAS_PARTITION = 10020; + + ERR_INVALID_QOS = 10021; + ERR_DB_DUPLICATE_QOS = 10022; + ERR_DELETE_QOS = 10023; + ERR_CONVERT_TO_INTERGER = 10024; + ERR_TIME_LIMIT = 10025; + ERR_ALLOWED_QOS = 10026; + ERR_DUPLICATE_QOS = 10027; + ERR_PARENT_ALLOWED_QOS = 10028; + ERR_SET_ALLOWED_QOS = 10029; + ERR_ALLOWED_DEFAULT_QOS = 10030; + ERR_DUPLICATE_DEFAULT_QOS = 10031; + ERR_CHILD_HAS_DEFAULT_QOS = 10032; + ERR_SET_ACCOUNT_QOS = 10033; + ERR_SET_DEFAULT_QOS = 10034; + ERR_IS_DEFAULT_QOS = 10035; + + ERR_UPDATE_DATABASE = 10036; ERR_GENERIC_FAILURE = 10100; ERR_NO_RESOURCE = 10101; @@ -386,7 +387,7 @@ enum EntityType { User = 1; } -enum OperatorType { +enum OperationType { Overwrite = 0; Add = 1; Delete = 2; From bf678c59321001c9e9ef9f25fdc05ef134a3aaf7 Mon Sep 17 00:00:00 2001 From: huerni <47264950+huerni@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:38:15 +0800 Subject: [PATCH 11/11] refactor --- go.mod | 2 -- go.sum | 4 ---- internal/cacctmgr/CmdArgParser.go | 3 --- internal/clogin/CmdArgParser.go | 16 +--------------- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 96d678af..2b862662 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/tidwall/gjson v1.17.3 github.com/tidwall/sjson v1.2.5 github.com/xlab/treeprint v1.2.0 - golang.org/x/crypto v0.26.0 golang.org/x/sys v0.24.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 @@ -34,7 +33,6 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect golang.org/x/net v0.28.0 // indirect - golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index e0245ca8..359cd7ef 100644 --- a/go.sum +++ b/go.sum @@ -70,16 +70,12 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= diff --git a/internal/cacctmgr/CmdArgParser.go b/internal/cacctmgr/CmdArgParser.go index 08ca3d12..ce96cc8f 100644 --- a/internal/cacctmgr/CmdArgParser.go +++ b/internal/cacctmgr/CmdArgParser.go @@ -476,9 +476,6 @@ func init() { if err := addUserCmd.MarkFlagRequired("name"); err != nil { log.Fatalln("Can't mark 'name' flag required") } - if err := addUserCmd.MarkFlagRequired("password"); err != nil { - log.Fatalln("Can't mark 'password' flag required") - } if err := addUserCmd.MarkFlagRequired("account"); err != nil { log.Fatalln("Can't mark 'account' flag required") } diff --git a/internal/clogin/CmdArgParser.go b/internal/clogin/CmdArgParser.go index 19b324bc..331bbd20 100644 --- a/internal/clogin/CmdArgParser.go +++ b/internal/clogin/CmdArgParser.go @@ -2,11 +2,8 @@ package clogin import ( "CraneFrontEnd/internal/util" - "fmt" "os" - "golang.org/x/crypto/ssh/terminal" - "github.com/spf13/cobra" ) @@ -19,18 +16,6 @@ var ( Short: "Login with your password", Long: "", Version: util.Version(), - Args: func(cmd *cobra.Command, args []string) error { - fmt.Print("Enter Password: ") - bytePassword, err := terminal.ReadPassword(int(os.Stdin.Fd())) - if err != nil { - fmt.Println("\nError reading password:", err) - os.Exit(1) - } - FlagPassword = string(bytePassword) - fmt.Println() - - return nil - }, PersistentPreRun: func(cmd *cobra.Command, args []string) { util.DetectNetworkProxy() config := util.ParseConfig(FlagConfigFilePath) @@ -55,4 +40,5 @@ func init() { RootCmd.SetVersionTemplate(util.VersionTemplate()) RootCmd.PersistentFlags().StringVarP(&FlagConfigFilePath, "config", "C", util.DefaultConfigPath, "Path to configuration file") + RootCmd.Flags().StringVarP(&FlagPassword, "password", "P", "", "Input the password of the user") }