keysloth 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Appraisals +9 -0
- data/CHANGELOG.md +30 -1
- data/LICENSE +21 -0
- data/README.md +37 -8
- data/gemfiles/thor_1.0.gemfile +18 -0
- data/gemfiles/thor_1.3.gemfile +18 -0
- data/keysloth.gemspec +5 -5
- data/keysloth.png +0 -0
- data/lib/keysloth/cli.rb +58 -53
- data/lib/keysloth/file_manager.rb +34 -12
- data/lib/keysloth/git_manager.rb +31 -5
- data/lib/keysloth/version.rb +1 -1
- data/lib/keysloth.rb +17 -4
- data/promts/main/rules.md +16 -0
- data/promts/outdated/feature_wildcard_extensions.md +62 -0
- data/promts/outdated/fix_backups.md +49 -0
- data/promts/outdated/fix_config_file.md +47 -0
- data/promts/outdated/fix_ssh.md +77 -0
- data/promts/outdated/thor-updates.md +38 -0
- data/promts/task_lists_for_human/release_task_list.md +60 -0
- data/{task → promts/task_lists_for_human}/test_plan.md +8 -89
- metadata +33 -16
- data/task/cr.md +0 -59
- /data/{task → promts/main}/task.md +0 -0
- /data/{task/ragged_removing.md → promts/outdated/feature_ragged_removing.md} +0 -0
- /data/{task → promts/outdated}/plan.md +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83e6473845f54b9be85c0e72e3c07cd8f9230ae11c2e8c1fe13284eebcc70c68
|
|
4
|
+
data.tar.gz: b6aac32a358a3fd948fa24234211197fac62173d9b8e4e5120c6db6731082488
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cdeaadbacf945fab4594cd19c1692c1ee35333f99bd71a678def06411a91252eda8292a2ceac8495fa0bd1b7b3e55013fceac558ec241f4db8110e6980610faa
|
|
7
|
+
data.tar.gz: 7855a1388754df2d9db3732470aabbc3ac933ed0b01b917f1110f34769e1ac1cf8475fd0e51c1dbe98483c15e932206b622609f719a9ec1b681a9f94e7ce4bc5
|
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,36 @@
|
|
|
5
5
|
Формат основан на [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
и этот проект придерживается [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [Released]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2025-09-04
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Поддержка произвольных типов файлов для шифрования/дешифрования (wildcard extensions)
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Сбор входных файлов: рекурсивно все обычные файлы, исключая `*.enc`, `.git/**`, `.DS_Store`, `Thumbs.db`, локальный `README.md`
|
|
17
|
+
- Перевод всех I/O операций на бинарные методы `File.binread`/`File.binwrite`
|
|
18
|
+
- Обновлены проверки целостности: работают с бинарными данными
|
|
19
|
+
- Обновлены CLI help и README для отражения поддержки любых типов
|
|
20
|
+
- Улучшены сообщения об ошибках SSH: подсказки для `Permission denied (publickey)`, `Host key verification failed`, `Repository not found`
|
|
21
|
+
- Улучшена читаемость логов CLI: добавлены явные маркеры начала/конца выполнения команд, эмодзи ✅ для успешных действий и ⛔ для ошибок
|
|
22
|
+
- Расширен диапазон совместимости с Thor: теперь `'>= 1.0.1', '< 1.4.0'`
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- Исправлено: параметр `backup_count` из `.keyslothrc` ранее игнорировался (всегда хранилось 3 бэкапа). Теперь значение конфигурации применяется, а `backup_count: 0` корректно отключает создание и ротацию бэкапов.
|
|
26
|
+
- Исправлено: значения `branch` и `local_path` из `.keyslothrc` игнорировались при использовании CLI из-за дефолтов в опциях. Дефолты в CLI убраны; приоритет теперь корректный: CLI > конфиг > дефолты. Документация обновлена (автопоиск и дефолты).
|
|
27
|
+
- Исправлено: `keysloth status` падал при форматировании времени backup'ов на некоторых окружениях (`Time.strptime` недоступен). Добавлено `require 'time'` и безопасный парсинг с `rescue`.
|
|
28
|
+
- Исправлено: команды `status`, `validate`, `restore` игнорировали `local_path` из `.keyslothrc`. Теперь при отсутствии `--path` путь берётся из конфигурации (или дефолта), а при наличии флага — имеет приоритет.
|
|
29
|
+
|
|
30
|
+
### Tests
|
|
31
|
+
- Обновлены и расширены тесты `file_manager_spec` и `git_manager_spec` под wildcard и бинарный I/O
|
|
32
|
+
- Добавлены тесты на подсказки SSH-ошибок в `git_manager_spec`
|
|
33
|
+
|
|
34
|
+
### Docs
|
|
35
|
+
- README: заменён раздел «Поддерживаемые типы» на «Типы файлов (любые)» и добавлены исключения
|
|
36
|
+
- Обновлён test_plan с учётом новых сценариев
|
|
37
|
+
- README: добавлены примеры с `ed25519` и переменной `KEYSLOTH_SSH_KEY_PATH`
|
|
9
38
|
|
|
10
39
|
## [0.1.1] - 2025-09-02
|
|
11
40
|
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Surf
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# KeySloth
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
3
5
|
Ruby gem для безопасного управления зашифрованными секретами в Git репозиториях.
|
|
4
6
|
|
|
5
7
|
## Описание
|
|
@@ -15,12 +17,15 @@ KeySloth решает проблему безопасного хранения
|
|
|
15
17
|
- 📦 **Backup'ы**: Автоматическое создание резервных копий
|
|
16
18
|
- 🎯 **CI/CD готовность**: Поддержка переменных окружения для автоматизации
|
|
17
19
|
|
|
18
|
-
###
|
|
20
|
+
### Типы файлов
|
|
21
|
+
|
|
22
|
+
Поддерживаются любые типы файлов (сертификаты, конфиги, изображения, бинарные и т.д.).
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
- `.
|
|
23
|
-
- `.
|
|
24
|
+
По умолчанию игнорируются при сборе и шифровании:
|
|
25
|
+
- `*.enc` (зашифрованные артефакты в репозитории)
|
|
26
|
+
- содержимое `.git/`
|
|
27
|
+
- `.DS_Store`, `Thumbs.db`
|
|
28
|
+
- локальный `README.md` в директории секретов
|
|
24
29
|
|
|
25
30
|
## Зависимости
|
|
26
31
|
|
|
@@ -107,6 +112,7 @@ keysloth push --repo git@github.com:company/secrets.git \
|
|
|
107
112
|
|
|
108
113
|
```bash
|
|
109
114
|
keysloth status --path ./secrets
|
|
115
|
+
# без --path возьмёт путь из .keyslothrc (или дефолт)
|
|
110
116
|
```
|
|
111
117
|
|
|
112
118
|
#### restore - Восстановление из backup'а
|
|
@@ -115,6 +121,7 @@ keysloth status --path ./secrets
|
|
|
115
121
|
|
|
116
122
|
```bash
|
|
117
123
|
keysloth restore secrets_backup_20231215_143022 --path ./secrets
|
|
124
|
+
# без --path возьмёт путь из .keyslothrc (или дефолт)
|
|
118
125
|
```
|
|
119
126
|
|
|
120
127
|
### Конфигурационный файл
|
|
@@ -131,6 +138,16 @@ backup_count: 3
|
|
|
131
138
|
|
|
132
139
|
Параметры командной строки имеют приоритет над конфигурационным файлом.
|
|
133
140
|
|
|
141
|
+
Дополнительно: файл конфигурации ищется автоматически, если путь не указан флагом `--config`:
|
|
142
|
+
- сначала в текущей директории (`./.keyslothrc`)
|
|
143
|
+
- затем в домашней директории (`~/.keyslothrc`)
|
|
144
|
+
|
|
145
|
+
Дефолтные значения при отсутствии флагов CLI и отсутствующих полях в конфиге:
|
|
146
|
+
- `branch`: `main`
|
|
147
|
+
- `local_path`: `./secrets`
|
|
148
|
+
- `backup_count`: `3`
|
|
149
|
+
- `repo_url`: отсутствует (должен быть указан явно через CLI или в конфиге)
|
|
150
|
+
|
|
134
151
|
### Логирование
|
|
135
152
|
|
|
136
153
|
KeySloth поддерживает три уровня логирования:
|
|
@@ -165,10 +182,14 @@ KeySloth обеспечивает многоуровневую защиту:
|
|
|
165
182
|
|
|
166
183
|
```bash
|
|
167
184
|
# Генерируем SSH ключ если нет
|
|
168
|
-
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
|
185
|
+
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" # RSA
|
|
186
|
+
# или современный вариант:
|
|
187
|
+
ssh-keygen -t ed25519 -C "your_email@example.com" # Ed25519
|
|
169
188
|
|
|
170
189
|
# Добавляем публичный ключ в GitHub/GitLab
|
|
171
190
|
cat ~/.ssh/id_rsa.pub
|
|
191
|
+
# или
|
|
192
|
+
cat ~/.ssh/id_ed25519.pub
|
|
172
193
|
```
|
|
173
194
|
|
|
174
195
|
#### CI/CD настройка
|
|
@@ -177,8 +198,8 @@ cat ~/.ssh/id_rsa.pub
|
|
|
177
198
|
|
|
178
199
|
```bash
|
|
179
200
|
# Экспортируем SSH ключ в переменную окружения
|
|
180
|
-
export SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)"
|
|
181
|
-
export SSH_PUBLIC_KEY="$(cat ~/.ssh/id_rsa.pub)"
|
|
201
|
+
export SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" # может быть RSA или Ed25519
|
|
202
|
+
export SSH_PUBLIC_KEY="$(cat ~/.ssh/id_rsa.pub)" # опционально
|
|
182
203
|
|
|
183
204
|
# Используем в CI/CD
|
|
184
205
|
keysloth pull -r git@github.com:company/secrets.git -p $SECRET_PASSWORD
|
|
@@ -194,6 +215,12 @@ export GIT_SSH_COMMAND='ssh -i /tmp/keysloth_ssh/id_rsa -o IdentitiesOnly=yes -o
|
|
|
194
215
|
|
|
195
216
|
Для локальной разработки отключать проверку хостов не рекомендуется.
|
|
196
217
|
|
|
218
|
+
Также можно явно указать путь к ключу через переменную окружения `KEYSLOTH_SSH_KEY_PATH` (поддерживаются как RSA, так и Ed25519):
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
export KEYSLOTH_SSH_KEY_PATH="~/.ssh/id_ed25519"
|
|
222
|
+
```
|
|
223
|
+
|
|
197
224
|
#### Требования к автору коммита
|
|
198
225
|
|
|
199
226
|
Перед отправкой изменений должны быть настроены глобальные параметры Git:
|
|
@@ -342,6 +369,8 @@ ssh-add -l
|
|
|
342
369
|
|
|
343
370
|
# Добавьте SSH ключ если необходимо
|
|
344
371
|
ssh-add ~/.ssh/id_rsa
|
|
372
|
+
# или
|
|
373
|
+
ssh-add ~/.ssh/id_ed25519
|
|
345
374
|
|
|
346
375
|
# Проверьте соединение с GitHub/GitLab
|
|
347
376
|
ssh -T git@github.com
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "thor", "1.0.1"
|
|
6
|
+
|
|
7
|
+
group :development, :test do
|
|
8
|
+
gem "pry", "~> 0.14"
|
|
9
|
+
gem "rake", "~> 13.0"
|
|
10
|
+
gem "appraisal", "~> 2.5"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
group :test do
|
|
14
|
+
gem "timecop", "~> 0.9"
|
|
15
|
+
gem "webmock", "~> 3.18"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "thor", "~> 1.3.2"
|
|
6
|
+
|
|
7
|
+
group :development, :test do
|
|
8
|
+
gem "pry", "~> 0.14"
|
|
9
|
+
gem "rake", "~> 13.0"
|
|
10
|
+
gem "appraisal", "~> 2.5"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
group :test do
|
|
14
|
+
gem "timecop", "~> 0.9"
|
|
15
|
+
gem "webmock", "~> 3.18"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
gemspec path: "../"
|
data/keysloth.gemspec
CHANGED
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
|
|
|
6
6
|
spec.name = 'keysloth'
|
|
7
7
|
spec.version = KeySloth::VERSION
|
|
8
8
|
spec.authors = ['KeySloth Team']
|
|
9
|
-
spec.email = ['
|
|
9
|
+
spec.email = ['chausov@surf.dev']
|
|
10
10
|
|
|
11
11
|
spec.summary = 'Ruby gem для управления зашифрованными секретами в Git репозиториях'
|
|
12
12
|
spec.description = <<~DESC
|
|
@@ -15,14 +15,14 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
Обеспечивает простое получение, изменение и отправку секретов с использованием#{' '}
|
|
16
16
|
AES-256-GCM шифрования.
|
|
17
17
|
DESC
|
|
18
|
-
spec.homepage = 'https://github.com/
|
|
18
|
+
spec.homepage = 'https://github.com/chausovSurfStudio/keysloth'
|
|
19
19
|
spec.license = 'MIT'
|
|
20
20
|
spec.required_ruby_version = '>= 2.7.0'
|
|
21
21
|
|
|
22
22
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
23
23
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
24
|
-
spec.metadata['source_code_uri'] = 'https://github.com/
|
|
25
|
-
spec.metadata['changelog_uri'] = 'https://github.com/
|
|
24
|
+
spec.metadata['source_code_uri'] = 'https://github.com/chausovSurfStudio/keysloth'
|
|
25
|
+
spec.metadata['changelog_uri'] = 'https://github.com/chausovSurfStudio/keysloth/blob/main/CHANGELOG.md'
|
|
26
26
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
27
27
|
|
|
28
28
|
# Определяем, какие файлы включить в gem
|
|
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
|
|
|
37
37
|
spec.require_paths = ['lib']
|
|
38
38
|
|
|
39
39
|
# Основные зависимости
|
|
40
|
-
spec.add_dependency 'thor', '
|
|
40
|
+
spec.add_dependency 'thor', '>= 1.0.1', '< 1.4.0' # CLI интерфейс
|
|
41
41
|
# Используем системные git команды вместо rugged для упрощения установки
|
|
42
42
|
# Используем встроенный openssl, доступный в Ruby по умолчанию
|
|
43
43
|
|
data/keysloth.png
ADDED
|
Binary file
|
data/lib/keysloth/cli.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'thor'
|
|
4
|
+
require 'time'
|
|
4
5
|
|
|
5
6
|
module KeySloth
|
|
6
7
|
# Интерфейс командной строки для KeySloth
|
|
@@ -34,27 +35,21 @@ module KeySloth
|
|
|
34
35
|
из указанной ветки, расшифровывает их с использованием предоставленного пароля
|
|
35
36
|
и сохраняет в локальную директорию.
|
|
36
37
|
|
|
37
|
-
Поддерживаемые типы файлов секретов:
|
|
38
|
-
- .cer (сертификаты)
|
|
39
|
-
- .p12 (PKCS#12 сертификаты)
|
|
40
|
-
- .mobileprovisioning (профили подготовки iOS)
|
|
41
|
-
- .json (конфигурационные файлы)
|
|
42
|
-
|
|
43
38
|
Перед выполнением операции автоматически создается резервная копия
|
|
44
39
|
существующей локальной директории с секретами.
|
|
45
40
|
DESC
|
|
46
41
|
option :repo, type: :string, aliases: '-r',
|
|
47
42
|
desc: 'URL Git репозитория (SSH: git@github.com:user/repo.git)'
|
|
48
|
-
option :branch, type: :string,
|
|
43
|
+
option :branch, type: :string, aliases: '-b',
|
|
49
44
|
desc: 'Ветка репозитория для получения секретов'
|
|
50
45
|
option :password, type: :string, required: true, aliases: '-p',
|
|
51
46
|
desc: 'Пароль для расшифровки секретов'
|
|
52
|
-
option :path, type: :string,
|
|
47
|
+
option :path, type: :string, aliases: '-d',
|
|
53
48
|
desc: 'Локальный путь для сохранения расшифрованных секретов'
|
|
54
49
|
def pull
|
|
55
50
|
setup_logger
|
|
56
51
|
|
|
57
|
-
logger.info(
|
|
52
|
+
logger.info("\n=== Начинаем операцию получения секретов ===")
|
|
58
53
|
|
|
59
54
|
begin
|
|
60
55
|
KeySloth.pull(
|
|
@@ -65,9 +60,9 @@ module KeySloth
|
|
|
65
60
|
config_file: options[:config]
|
|
66
61
|
)
|
|
67
62
|
|
|
68
|
-
logger.info(
|
|
63
|
+
logger.info("✅ Операция получения секретов завершена успешно\n")
|
|
69
64
|
rescue KeySloth::KeySlothError => e
|
|
70
|
-
logger.error("Ошибка выполнения операции: #{e.message}")
|
|
65
|
+
logger.error("⛔ Ошибка выполнения операции: #{e.message}")
|
|
71
66
|
exit 1
|
|
72
67
|
end
|
|
73
68
|
end
|
|
@@ -82,26 +77,21 @@ module KeySloth
|
|
|
82
77
|
При обнаружении конфликтов операция прекращается с детальным сообщением
|
|
83
78
|
об ошибке.
|
|
84
79
|
|
|
85
|
-
Поддерживаемые типы файлов секретов:
|
|
86
|
-
- .cer (сертификаты)
|
|
87
|
-
- .p12 (PKCS#12 сертификаты)#{' '}
|
|
88
|
-
- .mobileprovisioning (профили подготовки iOS)
|
|
89
|
-
- .json (конфигурационные файлы)
|
|
90
80
|
DESC
|
|
91
81
|
option :repo, type: :string, aliases: '-r',
|
|
92
82
|
desc: 'URL Git репозитория (SSH: git@github.com:user/repo.git)'
|
|
93
|
-
option :branch, type: :string,
|
|
83
|
+
option :branch, type: :string, aliases: '-b',
|
|
94
84
|
desc: 'Ветка репозитория для отправки секретов'
|
|
95
85
|
option :password, type: :string, required: true, aliases: '-p',
|
|
96
86
|
desc: 'Пароль для шифрования секретов'
|
|
97
|
-
option :path, type: :string,
|
|
87
|
+
option :path, type: :string, aliases: '-d',
|
|
98
88
|
desc: 'Локальный путь с секретами для шифрования'
|
|
99
89
|
option :message, type: :string, aliases: '-m',
|
|
100
90
|
desc: 'Сообщение коммита (опционально)'
|
|
101
91
|
def push
|
|
102
92
|
setup_logger
|
|
103
93
|
|
|
104
|
-
logger.info(
|
|
94
|
+
logger.info("\n=== Начинаем операцию отправки секретов ===")
|
|
105
95
|
|
|
106
96
|
begin
|
|
107
97
|
KeySloth.push(
|
|
@@ -113,9 +103,9 @@ module KeySloth
|
|
|
113
103
|
commit_message: options[:message]
|
|
114
104
|
)
|
|
115
105
|
|
|
116
|
-
logger.info(
|
|
106
|
+
logger.info("✅ Операция отправки секретов завершена успешно\n")
|
|
117
107
|
rescue KeySloth::KeySlothError => e
|
|
118
|
-
logger.error("Ошибка выполнения операции: #{e.message}")
|
|
108
|
+
logger.error("⛔ Ошибка выполнения операции: #{e.message}")
|
|
119
109
|
exit 1
|
|
120
110
|
end
|
|
121
111
|
end
|
|
@@ -128,7 +118,7 @@ module KeySloth
|
|
|
128
118
|
- Информацию о доступных резервных копиях
|
|
129
119
|
- Проверку целостности файлов
|
|
130
120
|
DESC
|
|
131
|
-
option :path, type: :string,
|
|
121
|
+
option :path, type: :string, aliases: '-d',
|
|
132
122
|
desc: 'Локальный путь с секретами для проверки'
|
|
133
123
|
def status
|
|
134
124
|
setup_logger
|
|
@@ -137,14 +127,17 @@ module KeySloth
|
|
|
137
127
|
|
|
138
128
|
begin
|
|
139
129
|
file_manager = FileManager.new(logger)
|
|
130
|
+
# Выбор пути: CLI -> конфиг -> дефолт
|
|
131
|
+
config = Config.load(options[:config])
|
|
132
|
+
resolved_path = options[:path] || config[:local_path] || Config::DEFAULT_CONFIG[:local_path]
|
|
140
133
|
|
|
141
|
-
unless file_manager.directory_exists?(
|
|
142
|
-
logger.warn("Директория секретов не существует: #{
|
|
134
|
+
unless file_manager.directory_exists?(resolved_path)
|
|
135
|
+
logger.warn("Директория секретов не существует: #{resolved_path}")
|
|
143
136
|
return
|
|
144
137
|
end
|
|
145
138
|
|
|
146
139
|
# Собираем файлы секретов
|
|
147
|
-
secret_files = file_manager.collect_secret_files(
|
|
140
|
+
secret_files = file_manager.collect_secret_files(resolved_path)
|
|
148
141
|
|
|
149
142
|
if secret_files.empty?
|
|
150
143
|
logger.info('Файлы секретов не найдены')
|
|
@@ -155,21 +148,27 @@ module KeySloth
|
|
|
155
148
|
|
|
156
149
|
secret_files.each do |file_path|
|
|
157
150
|
size = File.size(file_path)
|
|
158
|
-
relative_path = file_manager.get_relative_path(file_path,
|
|
151
|
+
relative_path = file_manager.get_relative_path(file_path, resolved_path)
|
|
159
152
|
integrity = file_manager.verify_file_integrity(file_path) ? '✓' : '✗'
|
|
160
153
|
|
|
161
154
|
logger.info(" #{integrity} #{relative_path} (#{size} байт)")
|
|
162
155
|
end
|
|
163
156
|
|
|
164
157
|
# Показываем информацию о backup'ах
|
|
165
|
-
backups = file_manager.list_backups(
|
|
158
|
+
backups = file_manager.list_backups(resolved_path)
|
|
166
159
|
if backups.any?
|
|
167
160
|
logger.info("\nДоступные резервные копии:")
|
|
168
161
|
backups.each do |backup_path|
|
|
169
162
|
backup_time = File.basename(backup_path).match(/_(\d{8}_\d{6})$/)&.captures&.first
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
163
|
+
formatted_time = begin
|
|
164
|
+
if backup_time
|
|
165
|
+
Time.strptime(backup_time, '%Y%m%d_%H%M%S').strftime('%Y-%m-%d %H:%M:%S')
|
|
166
|
+
end
|
|
167
|
+
rescue StandardError
|
|
168
|
+
nil
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
if formatted_time
|
|
173
172
|
logger.info(" #{File.basename(backup_path)} (#{formatted_time})")
|
|
174
173
|
else
|
|
175
174
|
logger.info(" #{File.basename(backup_path)}")
|
|
@@ -179,7 +178,7 @@ module KeySloth
|
|
|
179
178
|
logger.info("\nРезервные копии не найдены")
|
|
180
179
|
end
|
|
181
180
|
rescue KeySloth::KeySlothError => e
|
|
182
|
-
logger.error("Ошибка проверки состояния: #{e.message}")
|
|
181
|
+
logger.error("⛔ Ошибка проверки состояния: #{e.message}")
|
|
183
182
|
exit 1
|
|
184
183
|
end
|
|
185
184
|
end
|
|
@@ -190,20 +189,22 @@ module KeySloth
|
|
|
190
189
|
резервной копии. Используйте команду 'status' для просмотра
|
|
191
190
|
доступных резервных копий.
|
|
192
191
|
DESC
|
|
193
|
-
option :path, type: :string,
|
|
192
|
+
option :path, type: :string, aliases: '-d',
|
|
194
193
|
desc: 'Локальный путь для восстановления секретов'
|
|
195
194
|
def restore(backup_path)
|
|
196
195
|
setup_logger
|
|
197
196
|
|
|
198
|
-
logger.info(
|
|
197
|
+
logger.info("\n=== Восстанавливаем секреты из резервной копии ===")
|
|
199
198
|
|
|
200
199
|
begin
|
|
201
200
|
file_manager = FileManager.new(logger)
|
|
202
|
-
|
|
201
|
+
config = Config.load(options[:config])
|
|
202
|
+
resolved_path = options[:path] || config[:local_path] || Config::DEFAULT_CONFIG[:local_path]
|
|
203
|
+
file_manager.restore_from_backup(backup_path, resolved_path)
|
|
203
204
|
|
|
204
|
-
logger.info(
|
|
205
|
+
logger.info("✅ Восстановление завершено успешно\n")
|
|
205
206
|
rescue KeySloth::KeySlothError => e
|
|
206
|
-
logger.error("Ошибка восстановления: #{e.message}")
|
|
207
|
+
logger.error("⛔ Ошибка восстановления: #{e.message}")
|
|
207
208
|
exit 1
|
|
208
209
|
end
|
|
209
210
|
end
|
|
@@ -217,23 +218,25 @@ module KeySloth
|
|
|
217
218
|
- Валидирует структуру файлов секретов
|
|
218
219
|
- Выводит детальный отчет о состоянии каждого файла
|
|
219
220
|
DESC
|
|
220
|
-
option :path, type: :string,
|
|
221
|
+
option :path, type: :string, aliases: '-d',
|
|
221
222
|
desc: 'Локальный путь с секретами для проверки'
|
|
222
223
|
def validate
|
|
223
224
|
setup_logger
|
|
224
225
|
|
|
225
|
-
logger.info(
|
|
226
|
+
logger.info("\n=== Проверяем целостность файлов секретов ===")
|
|
226
227
|
|
|
227
228
|
begin
|
|
228
229
|
file_manager = FileManager.new(logger)
|
|
230
|
+
config = Config.load(options[:config])
|
|
231
|
+
resolved_path = options[:path] || config[:local_path] || Config::DEFAULT_CONFIG[:local_path]
|
|
229
232
|
|
|
230
|
-
unless file_manager.directory_exists?(
|
|
231
|
-
logger.error("Директория секретов не существует: #{
|
|
233
|
+
unless file_manager.directory_exists?(resolved_path)
|
|
234
|
+
logger.error("Директория секретов не существует: #{resolved_path}")
|
|
232
235
|
exit 1
|
|
233
236
|
end
|
|
234
237
|
|
|
235
238
|
# Собираем файлы секретов
|
|
236
|
-
secret_files = file_manager.collect_secret_files(
|
|
239
|
+
secret_files = file_manager.collect_secret_files(resolved_path)
|
|
237
240
|
|
|
238
241
|
if secret_files.empty?
|
|
239
242
|
logger.warn('Файлы секретов не найдены')
|
|
@@ -246,7 +249,7 @@ module KeySloth
|
|
|
246
249
|
invalid_files = 0
|
|
247
250
|
|
|
248
251
|
secret_files.each do |file_path|
|
|
249
|
-
relative_path = file_manager.get_relative_path(file_path,
|
|
252
|
+
relative_path = file_manager.get_relative_path(file_path, resolved_path)
|
|
250
253
|
|
|
251
254
|
if file_manager.verify_file_integrity(file_path)
|
|
252
255
|
logger.info(" ✓ #{relative_path} - файл корректен")
|
|
@@ -263,13 +266,14 @@ module KeySloth
|
|
|
263
266
|
logger.info("Поврежденных файлов: #{invalid_files}")
|
|
264
267
|
|
|
265
268
|
if invalid_files.positive?
|
|
266
|
-
logger.error("Обнаружены поврежденные файлы! Рекомендуется восстановление из backup'а.")
|
|
269
|
+
logger.error("⛔ Обнаружены поврежденные файлы! Рекомендуется восстановление из backup'а.")
|
|
267
270
|
exit 1
|
|
268
271
|
else
|
|
269
272
|
logger.info('Все файлы секретов прошли проверку целостности.')
|
|
273
|
+
logger.info("✅ Проверка целостности завершена успешно\n")
|
|
270
274
|
end
|
|
271
275
|
rescue KeySloth::KeySlothError => e
|
|
272
|
-
logger.error("Ошибка проверки целостности: #{e.message}")
|
|
276
|
+
logger.error("⛔ Ошибка проверки целостности: #{e.message}")
|
|
273
277
|
exit 1
|
|
274
278
|
end
|
|
275
279
|
end
|
|
@@ -295,7 +299,7 @@ module KeySloth
|
|
|
295
299
|
def init
|
|
296
300
|
setup_logger
|
|
297
301
|
|
|
298
|
-
logger.info(
|
|
302
|
+
logger.info("\n=== Инициализируем KeySloth проект ===")
|
|
299
303
|
|
|
300
304
|
begin
|
|
301
305
|
file_manager = FileManager.new(logger)
|
|
@@ -366,11 +370,12 @@ module KeySloth
|
|
|
366
370
|
keysloth status
|
|
367
371
|
```
|
|
368
372
|
|
|
369
|
-
##
|
|
370
|
-
|
|
371
|
-
-
|
|
372
|
-
- `.
|
|
373
|
-
- `.
|
|
373
|
+
## Типы файлов
|
|
374
|
+
Поддерживаются любые типы файлов. По умолчанию игнорируются:
|
|
375
|
+
- `*.enc` (артефакты шифрования)
|
|
376
|
+
- содержимое `.git/`
|
|
377
|
+
- `.DS_Store`, `Thumbs.db`
|
|
378
|
+
- локальный `README.md` в этой директории
|
|
374
379
|
|
|
375
380
|
**ВНИМАНИЕ:** Никогда не коммитьте эту директорию в Git!
|
|
376
381
|
MARKDOWN
|
|
@@ -378,16 +383,16 @@ module KeySloth
|
|
|
378
383
|
File.write(readme_path, readme_content)
|
|
379
384
|
logger.info("Создан файл справки: #{readme_path}")
|
|
380
385
|
|
|
381
|
-
logger.info("\n
|
|
386
|
+
logger.info("\n✅ Инициализация завершена успешно\n")
|
|
382
387
|
logger.info('Следующие шаги:')
|
|
383
388
|
logger.info("1. Поместите ваши файлы секретов в #{secrets_path}/")
|
|
384
389
|
logger.info("2. Используйте 'keysloth push' для первой отправки секретов")
|
|
385
390
|
logger.info('3. Поделитесь паролем шифрования с командой')
|
|
386
391
|
rescue KeySloth::KeySlothError => e
|
|
387
|
-
logger.error("Ошибка инициализации: #{e.message}")
|
|
392
|
+
logger.error("⛔ Ошибка инициализации: #{e.message}")
|
|
388
393
|
exit 1
|
|
389
394
|
rescue StandardError => e
|
|
390
|
-
logger.error("Неожиданная ошибка: #{e.message}")
|
|
395
|
+
logger.error("⛔ Неожиданная ошибка: #{e.message}")
|
|
391
396
|
exit 1
|
|
392
397
|
end
|
|
393
398
|
end
|