git-secret-protector 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/PKG-INFO +22 -14
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/README.md +21 -13
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/pyproject.toml +1 -1
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/aes_key_manager.py +1 -2
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/git_attributes_parser.py +9 -1
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/main.py +80 -7
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/settings.py +26 -9
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/__init__.py +0 -0
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/encryption_manager.py +0 -0
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/key_rotator.py +0 -0
- {git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/logging.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: git-secret-protector
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A tool for managing secrets in Git with AWS Parameter Store integration.
|
|
5
5
|
Author: Duc Duong
|
|
6
6
|
Author-email: duc.duong@c0x12c.com
|
|
@@ -30,7 +30,6 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
### Requirements
|
|
31
31
|
|
|
32
32
|
- pipx ([Download](https://pipx.pypa.io/stable/installation/))
|
|
33
|
-
- Poetry ([Download](https://python-poetry.org/docs/#installation))
|
|
34
33
|
|
|
35
34
|
You can install the `git-secret-protector` module via pipx:
|
|
36
35
|
|
|
@@ -42,25 +41,35 @@ pipx install git-secret-protector
|
|
|
42
41
|
|
|
43
42
|
### 1. Initial Setup
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
#### Set up AES key
|
|
45
|
+
|
|
46
|
+
Before using the tool, ensure you have the necessary AWS permissions to manage AWS MKS & SSM.
|
|
46
47
|
|
|
47
48
|
```sh
|
|
48
|
-
git-secret-protector
|
|
49
|
+
git-secret-protector init <filter_name>
|
|
49
50
|
```
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
**NOTE: Perform this setup once per repository during initial configuration.**
|
|
53
|
+
|
|
54
|
+
### 2. Configure Git Filters
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
onfigure the Git clean and smudge filters for the specified filter name
|
|
54
57
|
|
|
55
58
|
```sh
|
|
56
|
-
git-secret-protector
|
|
59
|
+
git-secret-protector init <filter_name>
|
|
57
60
|
```
|
|
58
61
|
|
|
59
|
-
|
|
62
|
+
### 3. Pull AES Key and IV
|
|
63
|
+
|
|
64
|
+
Before encrypting or decrypting files, it's necessary to retrieve the relevant AES keys from the AWS Parameter Store for specific filters:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
git-secret-protector pull-aes-key <filter_name>
|
|
68
|
+
```
|
|
60
69
|
|
|
61
|
-
This command
|
|
70
|
+
This command fetches the latest AES data key and IV from AWS Parameter Store for the designated filter and caches them locally for subsequent operations. This step ensures that you have the correct keys for encryption or decryption tasks related to the specified filter.
|
|
62
71
|
|
|
63
|
-
###
|
|
72
|
+
### 4. Key Rotation
|
|
64
73
|
|
|
65
74
|
#### Command to Rotate Keys
|
|
66
75
|
|
|
@@ -81,7 +90,7 @@ git rm --cached -r .
|
|
|
81
90
|
git reset --hard
|
|
82
91
|
```
|
|
83
92
|
|
|
84
|
-
###
|
|
93
|
+
### 5. View Encryption Status
|
|
85
94
|
|
|
86
95
|
Command to obtain a comprehensive overview of the encryption status of files within the repository:
|
|
87
96
|
|
|
@@ -93,7 +102,6 @@ git-secret-protector status
|
|
|
93
102
|
|
|
94
103
|
All configurations are managed through a `config.ini` file located in the `.git-secret-protector` directory. You can customize the following settings:
|
|
95
104
|
|
|
96
|
-
- **AWS Configuration**: Set your AWS region, profile, and other credentials.
|
|
97
105
|
- **Logging**: Configure the log file path and rotation settings.
|
|
98
106
|
- **Module Name**: Specify a custom module name for organizing keys in AWS Parameter Store.
|
|
99
107
|
|
|
@@ -102,8 +110,8 @@ All configurations are managed through a `config.ini` file located in the `.git-
|
|
|
102
110
|
Define which files to encrypt in your `.gitattributes` file:
|
|
103
111
|
|
|
104
112
|
```
|
|
105
|
-
secrets/*.tfstate filter=
|
|
106
|
-
config/**/credentials/* filter=
|
|
113
|
+
secrets/*.tfstate filter=sample-app diff=sample-app
|
|
114
|
+
config/**/credentials/* filter=sample-shared diff=sample-shared
|
|
107
115
|
```
|
|
108
116
|
|
|
109
117
|
### Logging
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
### Requirements
|
|
16
16
|
|
|
17
17
|
- pipx ([Download](https://pipx.pypa.io/stable/installation/))
|
|
18
|
-
- Poetry ([Download](https://python-poetry.org/docs/#installation))
|
|
19
18
|
|
|
20
19
|
You can install the `git-secret-protector` module via pipx:
|
|
21
20
|
|
|
@@ -27,25 +26,35 @@ pipx install git-secret-protector
|
|
|
27
26
|
|
|
28
27
|
### 1. Initial Setup
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
#### Set up AES key
|
|
30
|
+
|
|
31
|
+
Before using the tool, ensure you have the necessary AWS permissions to manage AWS MKS & SSM.
|
|
31
32
|
|
|
32
33
|
```sh
|
|
33
|
-
git-secret-protector
|
|
34
|
+
git-secret-protector init <filter_name>
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
**NOTE: Perform this setup once per repository during initial configuration.**
|
|
38
|
+
|
|
39
|
+
### 2. Configure Git Filters
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
onfigure the Git clean and smudge filters for the specified filter name
|
|
39
42
|
|
|
40
43
|
```sh
|
|
41
|
-
git-secret-protector
|
|
44
|
+
git-secret-protector init <filter_name>
|
|
42
45
|
```
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
### 3. Pull AES Key and IV
|
|
48
|
+
|
|
49
|
+
Before encrypting or decrypting files, it's necessary to retrieve the relevant AES keys from the AWS Parameter Store for specific filters:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
git-secret-protector pull-aes-key <filter_name>
|
|
53
|
+
```
|
|
45
54
|
|
|
46
|
-
This command
|
|
55
|
+
This command fetches the latest AES data key and IV from AWS Parameter Store for the designated filter and caches them locally for subsequent operations. This step ensures that you have the correct keys for encryption or decryption tasks related to the specified filter.
|
|
47
56
|
|
|
48
|
-
###
|
|
57
|
+
### 4. Key Rotation
|
|
49
58
|
|
|
50
59
|
#### Command to Rotate Keys
|
|
51
60
|
|
|
@@ -66,7 +75,7 @@ git rm --cached -r .
|
|
|
66
75
|
git reset --hard
|
|
67
76
|
```
|
|
68
77
|
|
|
69
|
-
###
|
|
78
|
+
### 5. View Encryption Status
|
|
70
79
|
|
|
71
80
|
Command to obtain a comprehensive overview of the encryption status of files within the repository:
|
|
72
81
|
|
|
@@ -78,7 +87,6 @@ git-secret-protector status
|
|
|
78
87
|
|
|
79
88
|
All configurations are managed through a `config.ini` file located in the `.git-secret-protector` directory. You can customize the following settings:
|
|
80
89
|
|
|
81
|
-
- **AWS Configuration**: Set your AWS region, profile, and other credentials.
|
|
82
90
|
- **Logging**: Configure the log file path and rotation settings.
|
|
83
91
|
- **Module Name**: Specify a custom module name for organizing keys in AWS Parameter Store.
|
|
84
92
|
|
|
@@ -87,8 +95,8 @@ All configurations are managed through a `config.ini` file located in the `.git-
|
|
|
87
95
|
Define which files to encrypt in your `.gitattributes` file:
|
|
88
96
|
|
|
89
97
|
```
|
|
90
|
-
secrets/*.tfstate filter=
|
|
91
|
-
config/**/credentials/* filter=
|
|
98
|
+
secrets/*.tfstate filter=sample-app diff=sample-app
|
|
99
|
+
config/**/credentials/* filter=sample-shared diff=sample-shared
|
|
92
100
|
```
|
|
93
101
|
|
|
94
102
|
### Logging
|
|
@@ -113,8 +113,7 @@ class AesKeyManager:
|
|
|
113
113
|
try:
|
|
114
114
|
self.ssm_client.get_parameter(Name=parameter_name, WithDecryption=True)
|
|
115
115
|
return True
|
|
116
|
-
except ClientError
|
|
117
|
-
logging.error("Failed to check if parameter '%s': {%s}", parameter_name, str(e))
|
|
116
|
+
except ClientError:
|
|
118
117
|
return False
|
|
119
118
|
|
|
120
119
|
def _ssm_parameter_name(self, filter_name):
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import fnmatch
|
|
2
2
|
import glob
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
import re
|
|
5
6
|
|
|
7
|
+
from git_secret_protector.settings import get_settings
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
6
11
|
|
|
7
12
|
class GitAttributesParser:
|
|
8
|
-
def __init__(self
|
|
13
|
+
def __init__(self):
|
|
14
|
+
settings = get_settings()
|
|
15
|
+
git_attributes_file = os.path.join(settings.base_dir, '.gitattributes')
|
|
16
|
+
|
|
9
17
|
self.git_attributes_file = git_attributes_file
|
|
10
18
|
self.patterns = self._parse_patterns()
|
|
11
19
|
|
|
@@ -1,21 +1,61 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import configparser
|
|
2
3
|
import logging
|
|
3
4
|
import subprocess
|
|
4
5
|
import sys
|
|
6
|
+
from pathlib import Path
|
|
5
7
|
|
|
6
8
|
from git_secret_protector.aes_key_manager import AesKeyManager
|
|
7
9
|
from git_secret_protector.encryption_manager import EncryptionManager
|
|
8
10
|
from git_secret_protector.git_attributes_parser import GitAttributesParser
|
|
9
11
|
from git_secret_protector.key_rotator import KeyRotator
|
|
10
12
|
from git_secret_protector.logging import configure_logging
|
|
13
|
+
from git_secret_protector.settings import get_settings
|
|
11
14
|
|
|
12
15
|
logger = logging.getLogger(__name__)
|
|
13
16
|
|
|
17
|
+
MODULE_FOLDER = '.git_secret_protector'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def init_module_folder():
|
|
21
|
+
module_path = Path(get_settings().module_dir)
|
|
22
|
+
|
|
23
|
+
if not module_path.exists():
|
|
24
|
+
module_path.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
(module_path / 'cache').mkdir(exist_ok=True)
|
|
26
|
+
(module_path / 'logs').mkdir(exist_ok=True)
|
|
27
|
+
|
|
28
|
+
# Check if config.ini exists, if not, create it with default settings
|
|
29
|
+
config_file = module_path / 'config.ini'
|
|
30
|
+
if not config_file.exists():
|
|
31
|
+
config = configparser.ConfigParser()
|
|
32
|
+
config['DEFAULT'] = {
|
|
33
|
+
'module_name': 'git-secret-protector',
|
|
34
|
+
'log_level': 'WARN',
|
|
35
|
+
'log_max_size': '10485760' # 10MB
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
with open(config_file, 'w') as configfile:
|
|
39
|
+
config.write(configfile)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def setup_aes_key(args):
|
|
43
|
+
filter_name = args.filter_name
|
|
44
|
+
logger.info("Set up AES key for filter: %s", filter_name)
|
|
45
|
+
|
|
46
|
+
init_module_folder()
|
|
47
|
+
|
|
48
|
+
key_manager = AesKeyManager()
|
|
49
|
+
key_manager.setup_aes_key_and_iv(args.filter_name)
|
|
50
|
+
logger.info(f"Filters for '{filter_name}' have been set up successfully.")
|
|
51
|
+
|
|
14
52
|
|
|
15
53
|
def init_filter(args):
|
|
16
54
|
filter_name = args.filter_name
|
|
17
55
|
logger.info("Initializing filter: %s", filter_name)
|
|
18
56
|
|
|
57
|
+
init_module_folder()
|
|
58
|
+
|
|
19
59
|
# Check for existing Git filters
|
|
20
60
|
check_clean = subprocess.getoutput(f'git config --get filter.{filter_name}.clean')
|
|
21
61
|
check_smudge = subprocess.getoutput(f'git config --get filter.{filter_name}.smudge')
|
|
@@ -32,10 +72,6 @@ def init_filter(args):
|
|
|
32
72
|
subprocess.run(['git', 'config', f'filter.{filter_name}.required', 'true'], check=True)
|
|
33
73
|
logger.debug("Git clean & smudge filters for '%s' have been set up successfully.", filter_name)
|
|
34
74
|
|
|
35
|
-
key_manager = AesKeyManager()
|
|
36
|
-
key_manager.setup_aes_key_and_iv(args.filter_name)
|
|
37
|
-
logger.info(f"Filters for '{filter_name}' have been set up successfully.")
|
|
38
|
-
|
|
39
75
|
|
|
40
76
|
def pull_aes_key(args):
|
|
41
77
|
key_manager = AesKeyManager()
|
|
@@ -106,6 +142,33 @@ def encrypt_stdin(args):
|
|
|
106
142
|
sys.stdout.buffer.flush()
|
|
107
143
|
|
|
108
144
|
|
|
145
|
+
def decrypt_files_by_filter(args):
|
|
146
|
+
filter_name = args.filter_name
|
|
147
|
+
logger.info("Decrypting files for filter: %s", filter_name)
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
git_attributes_parser = GitAttributesParser()
|
|
151
|
+
files = git_attributes_parser.get_files_for_filter(filter_name)
|
|
152
|
+
|
|
153
|
+
if not files:
|
|
154
|
+
logger.info("No files to decrypt for filter: %s", filter_name)
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
key_manager = AesKeyManager()
|
|
158
|
+
aes_key, iv = key_manager.retrieve_key_and_iv(filter_name)
|
|
159
|
+
encryption_manager = EncryptionManager(aes_key, iv, git_attributes_parser)
|
|
160
|
+
|
|
161
|
+
for file in files:
|
|
162
|
+
logger.debug("Decrypting file: %s", file)
|
|
163
|
+
encryption_manager.decrypt_file(file)
|
|
164
|
+
logger.debug("Successfully decrypted: %s", file)
|
|
165
|
+
|
|
166
|
+
logger.info("All files decrypted for filter: %s", filter_name)
|
|
167
|
+
except Exception as e:
|
|
168
|
+
logger.error("Failed to decrypt files for filter %s: %s", filter_name, e)
|
|
169
|
+
raise
|
|
170
|
+
|
|
171
|
+
|
|
109
172
|
def status_command(args):
|
|
110
173
|
logger.info("Gathering status of all filters and their files...")
|
|
111
174
|
git_attributes_parser = GitAttributesParser()
|
|
@@ -132,9 +195,14 @@ def main():
|
|
|
132
195
|
subparsers = parser.add_subparsers(help="Available commands")
|
|
133
196
|
|
|
134
197
|
# Command to init filter
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
198
|
+
parser_init = subparsers.add_parser('init', help="Init filter actions in git config")
|
|
199
|
+
parser_init.add_argument('filter_name', type=str, help="The filter name")
|
|
200
|
+
parser_init.set_defaults(func=init_filter)
|
|
201
|
+
|
|
202
|
+
# Command to set up AES key
|
|
203
|
+
parser_setup_aes_key = subparsers.add_parser('setup-aes-key', help="Set up AES key for a filter")
|
|
204
|
+
parser_setup_aes_key.add_argument('filter_name', type=str, help="The filter name for the AES key")
|
|
205
|
+
parser_setup_aes_key.set_defaults(func=setup_aes_key)
|
|
138
206
|
|
|
139
207
|
# Command to pull AES key
|
|
140
208
|
parser_pull_aes_key = subparsers.add_parser('pull-aes-key', help="Pull AES key for a filter")
|
|
@@ -156,6 +224,11 @@ def main():
|
|
|
156
224
|
parser_encrypt_stdin.add_argument('file_name', type=str, help="Filename for encryption")
|
|
157
225
|
parser_encrypt_stdin.set_defaults(func=encrypt_stdin)
|
|
158
226
|
|
|
227
|
+
# Command to decrypt files for a specific filter
|
|
228
|
+
parser_decrypt_files = subparsers.add_parser('decrypt-files', help="Decrypt files for a specific filter")
|
|
229
|
+
parser_decrypt_files.add_argument('filter_name', type=str, help="The filter name whose files to decrypt")
|
|
230
|
+
parser_decrypt_files.set_defaults(func=decrypt_files_by_filter)
|
|
231
|
+
|
|
159
232
|
# Status command
|
|
160
233
|
parser_status = subparsers.add_parser('status', help="List all filters and file statuses")
|
|
161
234
|
parser_status.set_defaults(func=status_command)
|
{git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/settings.py
RENAMED
|
@@ -2,28 +2,45 @@ import configparser
|
|
|
2
2
|
import os
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
|
|
5
|
-
BASE_DIR = '.git_secret_protector'
|
|
6
|
-
|
|
7
5
|
|
|
8
6
|
@dataclass
|
|
9
7
|
class Settings:
|
|
10
|
-
|
|
8
|
+
BASE_DIR_LOOKUP_FOLDER = ".git"
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
_instance: 'Settings' = field(default=None, init=False, repr=False, compare=False)
|
|
11
|
+
module_folder: str = '.git_secret_protector'
|
|
12
|
+
base_dir: str = field(init=False)
|
|
13
|
+
module_dir: str = field(init=False)
|
|
14
|
+
config_file: str = field(init=False)
|
|
15
|
+
cache_dir: str = field(init=False)
|
|
16
|
+
log_dir: str = field(init=False)
|
|
15
17
|
module_name: str = 'git-secret-protector'
|
|
16
|
-
log_file: str = field(init=False
|
|
18
|
+
log_file: str = field(init=False)
|
|
17
19
|
log_level: str = 'INFO'
|
|
18
20
|
log_max_size: int = 10485760 # 10MB
|
|
19
21
|
log_backup_count: int = 3
|
|
20
|
-
config: configparser.ConfigParser = field(init=False
|
|
22
|
+
config: configparser.ConfigParser = field(init=False)
|
|
21
23
|
|
|
22
24
|
def __post_init__(self):
|
|
23
|
-
self.
|
|
25
|
+
self.base_dir = self.find_base_dir()
|
|
26
|
+
self.module_dir = os.path.join(self.base_dir, self.module_folder)
|
|
27
|
+
self.config_file = os.path.join(self.module_dir, 'config.ini')
|
|
28
|
+
self.cache_dir = os.path.join(self.module_dir, 'cache')
|
|
29
|
+
self.log_dir = os.path.join(self.module_dir, 'logs')
|
|
24
30
|
self.log_file = os.path.join(self.log_dir, 'git_secret_protector.log')
|
|
31
|
+
self.config = configparser.ConfigParser()
|
|
25
32
|
self._load_config()
|
|
26
33
|
|
|
34
|
+
def find_base_dir(self):
|
|
35
|
+
current_dir = os.getcwd()
|
|
36
|
+
while current_dir != os.path.dirname(current_dir): # Traverse up to the root directory
|
|
37
|
+
possible_dir = os.path.join(current_dir, Settings.BASE_DIR_LOOKUP_FOLDER)
|
|
38
|
+
if os.path.exists(possible_dir):
|
|
39
|
+
return current_dir
|
|
40
|
+
current_dir = os.path.dirname(current_dir)
|
|
41
|
+
raise FileNotFoundError(
|
|
42
|
+
"The git-secret-protector module folder was not found in any ascendant directories. Please ensure the module is set up correctly.")
|
|
43
|
+
|
|
27
44
|
def _load_config(self):
|
|
28
45
|
if os.path.exists(self.config_file):
|
|
29
46
|
self.config.read(self.config_file)
|
{git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/key_rotator.py
RENAMED
|
File without changes
|
{git_secret_protector-0.2.0 → git_secret_protector-0.3.0}/src/git_secret_protector/logging.py
RENAMED
|
File without changes
|