From 318b916af6c699d43e9d602d5f7f3b832d8ba2c1 Mon Sep 17 00:00:00 2001 From: Egor Date: Wed, 22 May 2024 23:43:26 +0300 Subject: [PATCH] :bug: fixes --- config/config-servers.toml | 4 +- config/config.go | 6 - config/config.toml | 14 +- doc/src/other.md | 8 ++ internal/domains/transaction-logger.go | 1 + internal/service/security/security.go | 121 ++++++++++-------- internal/service/servers/servers.go | 4 +- .../service/transaction-logger/restore.go | 5 + 8 files changed, 93 insertions(+), 70 deletions(-) diff --git a/config/config-servers.toml b/config/config-servers.toml index 45642c6..308a9f3 100644 --- a/config/config-servers.toml +++ b/config/config-servers.toml @@ -1 +1,3 @@ -Servers = ["127.0.0.1:8889"] +Servers = [ + # "127.0.0.1:8889" +] diff --git a/config/config.go b/config/config.go index a410de0..6bd24bc 100644 --- a/config/config.go +++ b/config/config.go @@ -48,7 +48,6 @@ type BalancerConfig struct { type SecurityConfig struct { MandatoryAuthorization bool `toml:"MandatoryAuthorization"` - MandatoryEncryption bool `toml:"MandatoryEncryption"` } type LoggingConfig struct { @@ -58,11 +57,6 @@ type LoggingConfig struct { var _configFlag = flag.String("config", "", "Specify the path to the config file") var _configServersFlag = flag.String("config-servers", "", "Specify the path to the config file") -var _noSecurity = SecurityConfig{ - MandatoryAuthorization: false, - MandatoryEncryption: false, -} - const _defaultPathToConfig = "config/config.toml" const _defaultPathToServers = "config/config-servers.toml" diff --git a/config/config.toml b/config/config.toml index 404584d..ebc0749 100644 --- a/config/config.toml +++ b/config/config.toml @@ -27,11 +27,13 @@ BackupDirectory = "transaction-logger" # Buffer size. BufferSize = "1s" -# Encryption parameters. +# Параметры шифрования. [Encryption] -# Key that is used to encrypt data. -# Example: "jdvbe3j1hve11jhv2js1vdvuvs1yud" -Key = "CHANGE ME" +# Key used for data encryption. +# Must be an AES key, 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256. +# Example: "PLEASE CHANGE ME" = 16 bytes -> AES-128. +# DO NOT CHANGE THE NUMBER OF BYTES AFTER THE FIRST PRODUCTION RUN. +Key = "PLEASE CHANGE ME" # Web application settings. [WebApp] @@ -52,9 +54,5 @@ On = true # If false, authentication is not required for keys and objects that has Default level. MandatoryAuthorization = true -# Mandatory encryption. -# If false, encryption is not mandatory for keys and objects that has Secret level. -MandatoryEncryption = true - [Logging] Level = "debug" \ No newline at end of file diff --git a/doc/src/other.md b/doc/src/other.md index 1b3a851..b13ffdf 100644 --- a/doc/src/other.md +++ b/doc/src/other.md @@ -18,6 +18,14 @@ SERVERS <- no available servers ``` +### ADD SERVER - Add server to the list of active servers. + +Example: +```go +ADD SERVER 127.0.0.1:8080 +<- OK +``` + ### EXIT - Exit from the acount. ```go EXIT diff --git a/internal/domains/transaction-logger.go b/internal/domains/transaction-logger.go index 37d5144..df3dea1 100644 --- a/internal/domains/transaction-logger.go +++ b/internal/domains/transaction-logger.go @@ -29,6 +29,7 @@ type Restorer interface { CreateObject(name string, opts models.ObjectOptions) gost.ResultN AttachToObject(dst, src string) gost.ResultN NewUser(user models.User) (r gost.ResultN) + DeleteUser(login string) (r gost.Result[bool]) AddObjectInfo(name string, info models.ObjectInfo) DeleteObjectInfo(name string) DeleteAttr(object, key string) gost.ResultN diff --git a/internal/service/security/security.go b/internal/service/security/security.go index 48e424c..f5824d2 100644 --- a/internal/service/security/security.go +++ b/internal/service/security/security.go @@ -14,13 +14,13 @@ import ( ) type SecurityService struct { - cfg config.SecurityConfig + cfg config.SecurityConfig encryptionConfig config.EncryptionConfig } func NewSecurityService(cfg config.SecurityConfig, encryptionConfig config.EncryptionConfig) *SecurityService { return &SecurityService{ - cfg: cfg, + cfg: cfg, encryptionConfig: encryptionConfig, } } @@ -46,60 +46,73 @@ func (l *SecurityService) HasPermission(claimsOpt gost.Option[models.UserClaims] } func (l *SecurityService) Encrypt(val string) (string, error) { - // Преобразуем ключ из конфигурации шифрования в байты - key := []byte(l.encryptionConfig.Key) - // Создаем шифр на основе ключа - block, err := aes.NewCipher(key) - if err != nil { - return "", err - } - - // Преобразуем строку для шифрования в байты - plaintext := []byte(val) - // Создаем массив для шифротекста с дополнительным местом для IV - ciphertext := make([]byte, aes.BlockSize+len(plaintext)) - // Используем первый блок массива в качестве IV - iv := ciphertext[:aes.BlockSize] - // Заполняем IV случайными данными - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return "", err - } - - // Создаем потоковый шифр для шифрования - stream := cipher.NewCFBEncrypter(block, iv) - // Применяем XOR между ключом и текстом, начиная с позиции после IV - stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) - - // Возвращаем зашифрованное значение - return val, nil + // Преобразуем ключ из конфигурации шифрования в байты + key := []byte(l.encryptionConfig.Key) + // Создаем шифр на основе ключа + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + // Преобразуем строку для шифрования в байты + plaintext := []byte(val) + // Создаем массив для шифротекста с дополнительным местом для IV + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + // Используем первый блок массива в качестве IV + iv := ciphertext[:aes.BlockSize] + // Заполняем IV случайными данными + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return "", err + } + + // Создаем потоковый шифр для шифрования + stream := cipher.NewCFBEncrypter(block, iv) + // Применяем XOR между ключом и текстом, начиная с позиции после IV + stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) + + // Возвращаем зашифрованное значение + return string(ciphertext), nil } func (l *SecurityService) Decrypt(val string) (string, error) { - // Преобразуем ключ из конфигурации шифрования в байты - key := []byte(l.encryptionConfig.Key) - - // Создаем шифр на основе ключа - block, err := aes.NewCipher(key) - if err != nil { - return "", err - } - - // Проверяем, достаточно ли длинный шифротекст - if len(val) < aes.BlockSize { - return "", errors.New("ciphertext too short") - } - - // Используем первый блок шифротекста в качестве IV - iv := val[:aes.BlockSize] - val = val[aes.BlockSize:] - - // Создаем потоковый шифр для дешифрования - stream := cipher.NewCFBDecrypter(block, []byte(iv)) - // Применяем XOR между ключом и текстом - stream.XORKeyStream([]byte(val), []byte(val)) - - // Возвращаем дешифрованное значение - return string(val), nil -} + // Преобразуем ключ из конфигурации шифрования в байты + key := []byte(l.encryptionConfig.Key) + // Создаем шифр на основе ключа + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + // Проверяем, достаточно ли длинный шифротекст + if len(val) < aes.BlockSize { + return "", errors.New("ciphertext too short") + } + + // Используем первый блок шифротекста в качестве IV + iv := []byte(val[:aes.BlockSize]) + ciphertext := []byte(val[aes.BlockSize:]) + + // Создаем потоковый шифр для дешифрования + stream := cipher.NewCFBDecrypter(block, iv) + // Применяем XOR между ключом и текстом + stream.XORKeyStream(ciphertext, ciphertext) + + // Возвращаем дешифрованное значение + return string(ciphertext), nil +} +// func pad(src []byte, blockSize int) []byte { +// padding := blockSize - len(src)%blockSize +// padtext := bytes.Repeat([]byte{byte(padding)}, padding) +// return append(src, padtext...) +// } + +// func unpad(src []byte) ([]byte, error) { +// length := len(src) +// unpadding := int(src[length-1]) +// if unpadding > length { +// return nil, errors.New("unpad error. This can happen when incorrect encryption key is used") +// } +// return src[:(length - unpadding)], nil +// } diff --git a/internal/service/servers/servers.go b/internal/service/servers/servers.go index 073227f..62549ed 100644 --- a/internal/service/servers/servers.go +++ b/internal/service/servers/servers.go @@ -163,7 +163,9 @@ func (s *Servers) AddServer(ctx context.Context, address string, force bool) (in s.logger.Error("can't add server", zap.Int32("server", server), zap.Error(err)) if !force { return 0, err - } + } + + stClient.tries.Add(constants.MaxServerTries) } var addresses = make([]string, 0, len(s.servers)) diff --git a/internal/service/transaction-logger/restore.go b/internal/service/transaction-logger/restore.go index 73e4b6b..c9194bb 100644 --- a/internal/service/transaction-logger/restore.go +++ b/internal/service/transaction-logger/restore.go @@ -143,6 +143,11 @@ func (t *TransactionLogger) handleEvents(r domains.Restorer, events <-chan Event if rUser.IsErr() { return fmt.Errorf("can't create user %s, v: %s: %w", e.Name, e.Value, rUser.Error()) } + case DeleteUser: + rDelUser := r.DeleteUser(e.Name) + if rDelUser.IsErr() { + return fmt.Errorf("can't delete user %s: %w", e.Name, rDelUser.Error()) + } case CreateObject: split := strings.Split(e.Value, constants.MetadataSeparator) if len(split) < 2 {