get-hc-secrets 1.5.9__tar.gz → 1.5.20__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.
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: get_hc_secrets
3
- Version: 1.5.9
4
- Summary: A package to read secrets from Hashicorp vault
3
+ Version: 1.5.20
4
+ Summary: A package to read secrets from Hashicorp vault or from a local file
5
5
  Author-email: Xavier Mayeur <xavier@mayeur.be>
6
6
  Project-URL: Homepage, https://github.com/xmayeur/getSecrets
7
7
  Project-URL: Bug Tracker, https://github.com/xmayeur/getSecrets/issues
@@ -13,19 +13,23 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: pyyaml
15
15
  Requires-Dist: requests
16
+ Dynamic: license-file
16
17
 
17
18
  # getSecrets package
18
19
 
19
20
  getSecrets is a simple package that reads from the given engine ('secret' by default) of a Hashicorp vault
21
+ It can also read data from the local vault.yml file
20
22
 
21
23
  usage:
22
24
 
23
25
  ```
24
26
  from getSecrets import *
25
27
 
26
- data = get_secret(<id>, [<secret>])
28
+ data = get_secret(<id>, [repo:<secret>])
27
29
 
28
- usr_pwd = get_user_pwd(<id>, <new k_v_dict> , [<secret>])
30
+ usr, pwd = get_user_pwd(<id> , [repo:<secret>])
31
+
32
+ updater = update_secret(<id>, <new_object>, [repo:<secret>])
29
33
 
30
34
  list = list_secret([<secret>]
31
35
 
@@ -38,4 +42,17 @@ vault:
38
42
  token: "<access token>"
39
43
  vault_addr: "https://vault:8200"
40
44
  certs: "<path>/bundle.pem"
45
+
46
+ id:
47
+ item1: 1
48
+ item2: 2
49
+ username: user
50
+ password: !@•?
41
51
  ```
52
+
53
+ for reminder:
54
+ bundle.pem, for own certificates, is made of, in this order:
55
+
56
+ - vault certificate
57
+ - intermediate certificate
58
+ - root certificate
@@ -0,0 +1,41 @@
1
+ # getSecrets package
2
+
3
+ getSecrets is a simple package that reads from the given engine ('secret' by default) of a Hashicorp vault
4
+ It can also read data from the local vault.yml file
5
+
6
+ usage:
7
+
8
+ ```
9
+ from getSecrets import *
10
+
11
+ data = get_secret(<id>, [repo:<secret>])
12
+
13
+ usr, pwd = get_user_pwd(<id> , [repo:<secret>])
14
+
15
+ updater = update_secret(<id>, <new_object>, [repo:<secret>])
16
+
17
+ list = list_secret([<secret>]
18
+
19
+ ```
20
+
21
+ Vault parameters are stored in a config file ~/.config/.vault/.vault.yml
22
+
23
+ ```
24
+ vault:
25
+ token: "<access token>"
26
+ vault_addr: "https://vault:8200"
27
+ certs: "<path>/bundle.pem"
28
+
29
+ id:
30
+ item1: 1
31
+ item2: 2
32
+ username: user
33
+ password: !@•?
34
+ ```
35
+
36
+ for reminder:
37
+ bundle.pem, for own certificates, is made of, in this order:
38
+
39
+ - vault certificate
40
+ - intermediate certificate
41
+ - root certificate
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "get_hc_secrets"
3
- version = '1.5.9'
3
+ version = '1.5.20'
4
4
  authors = [
5
5
  { name = "Xavier Mayeur", email = "xavier@mayeur.be" }
6
6
  ]
7
- description = "A package to read secrets from Hashicorp vault"
7
+ description = "A package to read secrets from Hashicorp vault or from a local file"
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.7"
10
10
  classifiers = [
@@ -0,0 +1,179 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ from os import getenv
5
+ from os.path import join
6
+
7
+ import requests
8
+ import urllib3
9
+ import yaml
10
+
11
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s',
12
+ datefmt='%m/%d/%Y %I:%M:%S %p')
13
+
14
+ _config_file = ".config/.vault/vault.yml"
15
+ _home = getenv("HOME")
16
+
17
+ try:
18
+ _config = yaml.safe_load(open(join(_home, _config_file)))
19
+ except (FileNotFoundError, TypeError):
20
+ if not os.path.exists("/etc/vault"):
21
+ os.makedirs("/etc/vault")
22
+ _home = "/etc/vault"
23
+ _config_file = "vault.yml"
24
+ try:
25
+ _config = yaml.safe_load(open(join(_home, _config_file)))
26
+ except FileNotFoundError:
27
+ logging.error(f"No vault configuration found in {_home}")
28
+ sys.exit(1)
29
+
30
+
31
+ def get_secret(id: str, repo: str = 'secret') -> dict:
32
+ """
33
+ :param id: The ID of the secret to retrieve
34
+ :param repo: The name of the secrets repository to retrieve the secret from - defaults to 'secret'
35
+ :return: a json object with key/value pairs
36
+ or an empty object if the secret retrieval fails
37
+
38
+ This method retrieves a secret from a Vault server using the provided ID.
39
+ If the request is successful (status code 200), the method extracts the key-value pairs JSON object.
40
+ If the request fails, the method logs an HTTP error message and returns a n empty json {}.
41
+ """
42
+
43
+ # check if data is available in config file
44
+ if id in _config:
45
+ return _config[id]
46
+ else:
47
+ base_url = _config['vault']['vault_addr']
48
+ if _home == '/etc/vault':
49
+ certs = '/etc/vault/bundle.pem'
50
+ else:
51
+ certs = join(_home, _config['vault']['certs'].replace("~/", ''))
52
+ # check if file exist, else make insecure
53
+ if not (os.path.exists(certs)):
54
+ certs = False
55
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
56
+ logging.warning(f"No vault bundle.pem found at {certs} - working insecure !!")
57
+
58
+ token = _config['vault']['token']
59
+ headers = {"X-Vault-Token": token}
60
+ uri = f"/v1/{repo}/data/"
61
+ url = f"{base_url}{uri}{id}"
62
+ resp = requests.get(url, headers=headers, verify=certs)
63
+ if resp.status_code == 200:
64
+ secret = resp.json()["data"]["data"]
65
+ return secret
66
+
67
+ else:
68
+ print(f"http error {resp.status_code}")
69
+ logging.error(f"Vault api error {resp}")
70
+ return {}
71
+
72
+
73
+ def get_user_pwd(id: str, repo: str = 'secret') -> tuple:
74
+ """
75
+ :param id: The ID of the secret to retrieve
76
+ :param repo: The name of the secret repository to retrieve the seret from - defaults to 'secret'
77
+ :return: a tuple username, password values if the secrets has such keys, else None, None
78
+
79
+ This method retrieves a secret from a Vault server using the provided ID.
80
+ If the request is successful (status code 200), the method extracts the username and password key value
81
+ if such keys exist.
82
+ If the request fails, the method prints an HTTP error message and returns (None, None).
83
+ """
84
+
85
+ # check if data is available in config file
86
+ if id in _config:
87
+ return _config[id]['username'], _config[id]['password']
88
+ else:
89
+ base_url = _config['vault']['vault_addr']
90
+ certs = join(_home, _config['vault']['certs'].replace("~/", ''))
91
+ token = _config['vault']['token']
92
+
93
+ headers = {"X-Vault-Token": token}
94
+ uri = f"/v1/{repo}/data/"
95
+ url = f"{base_url}{uri}{id}"
96
+ resp = requests.get(url, headers=headers, verify=certs)
97
+ if resp.status_code == 200:
98
+ secret = resp.json()["data"]["data"]
99
+ if 'username' in secret and 'password' in secret:
100
+ return secret['username'], secret['password']
101
+ else:
102
+ return None, None
103
+
104
+ else:
105
+ print(f"http error {resp.status_code}")
106
+ logging.error(f"Vault api error {resp}")
107
+ return None, None
108
+
109
+
110
+ def list_secret(repo: str = 'secret'):
111
+ """
112
+ :param repo: The name of a secret repository to retrieve the secret from - defaults to 'secret'
113
+ :return: A list containing all items keys from the repository
114
+
115
+ """
116
+
117
+ base_url = _config['vault']['vault_addr']
118
+ certs = join(_home, _config['vault']['certs'].replace("~/", ''))
119
+ token = _config['vault']['token']
120
+
121
+ headers = {"X-Vault-Token": token}
122
+ uri = f"/v1/{repo}/metadata"
123
+ url = f"{base_url}{uri}"
124
+ resp = requests.request('LIST', url, headers=headers, verify=certs)
125
+ if resp.status_code == 200:
126
+ return resp.json()["data"]["keys"]
127
+
128
+ else:
129
+ print(f"http error {resp.status_code}")
130
+ logging.error(f"Vault api error {resp}")
131
+ return None, None
132
+
133
+
134
+ def upd_secret(id: str, data, repo: str = 'secret'):
135
+ """
136
+ :param id: The ID of the secret to retrieve
137
+ :param data: The data to be uploaded in place of the exitisting one
138
+ :param repo: The name of the repository to retrieve the secret from - defaults to 'secret'
139
+ :return: the response status code from the vault - 200 if successful.
140
+
141
+ """
142
+
143
+ # check if data is available in config file
144
+ if id in _config:
145
+ _config[id] = data
146
+ yaml.safe_dump(data, open(join(_home, _config_file)))
147
+ return 200
148
+
149
+ else:
150
+ base_url = _config['vault']['vault_addr']
151
+ certs = join(_home, _config['vault']['certs'].replace("~/", ''))
152
+ token = _config['vault']['token']
153
+
154
+ headers = {"X-Vault-Token": token}
155
+ uri = f"/v1/{repo}/data/"
156
+ url = f"{base_url}{uri}{id}"
157
+ resp = requests.request('GET', url, headers=headers, verify=certs)
158
+ if resp.status_code == 200:
159
+ version = resp.json()["data"]['metadata']['version']
160
+ obj = {
161
+ "options": {
162
+ "cas": version
163
+ },
164
+ "data": data
165
+ }
166
+
167
+ resp2 = requests.request('POST', url, headers=headers, json=obj, verify=certs)
168
+ if resp2.status_code != 200:
169
+ logging.warning(f"Vault update error for {id} with new {data}")
170
+ return resp2.status_code
171
+
172
+ else:
173
+ print(f"http error {resp.status_code}")
174
+ logging.error(f"Vault api error {resp}")
175
+ return None, None
176
+
177
+
178
+ if __name__ == "__main__":
179
+ secret = get_secret('test')
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: get_hc_secrets
3
- Version: 1.5.9
4
- Summary: A package to read secrets from Hashicorp vault
3
+ Version: 1.5.20
4
+ Summary: A package to read secrets from Hashicorp vault or from a local file
5
5
  Author-email: Xavier Mayeur <xavier@mayeur.be>
6
6
  Project-URL: Homepage, https://github.com/xmayeur/getSecrets
7
7
  Project-URL: Bug Tracker, https://github.com/xmayeur/getSecrets/issues
@@ -13,19 +13,23 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: pyyaml
15
15
  Requires-Dist: requests
16
+ Dynamic: license-file
16
17
 
17
18
  # getSecrets package
18
19
 
19
20
  getSecrets is a simple package that reads from the given engine ('secret' by default) of a Hashicorp vault
21
+ It can also read data from the local vault.yml file
20
22
 
21
23
  usage:
22
24
 
23
25
  ```
24
26
  from getSecrets import *
25
27
 
26
- data = get_secret(<id>, [<secret>])
28
+ data = get_secret(<id>, [repo:<secret>])
27
29
 
28
- usr_pwd = get_user_pwd(<id>, <new k_v_dict> , [<secret>])
30
+ usr, pwd = get_user_pwd(<id> , [repo:<secret>])
31
+
32
+ updater = update_secret(<id>, <new_object>, [repo:<secret>])
29
33
 
30
34
  list = list_secret([<secret>]
31
35
 
@@ -38,4 +42,17 @@ vault:
38
42
  token: "<access token>"
39
43
  vault_addr: "https://vault:8200"
40
44
  certs: "<path>/bundle.pem"
45
+
46
+ id:
47
+ item1: 1
48
+ item2: 2
49
+ username: user
50
+ password: !@•?
41
51
  ```
52
+
53
+ for reminder:
54
+ bundle.pem, for own certificates, is made of, in this order:
55
+
56
+ - vault certificate
57
+ - intermediate certificate
58
+ - root certificate
@@ -1,6 +1,7 @@
1
- import secrets
2
1
  import unittest
3
- import getSecrets as gs
2
+
3
+ # import getSecrets as gs
4
+ from src import getSecrets as gs
4
5
 
5
6
 
6
7
  class TestGetSecrets(unittest.TestCase):
@@ -21,4 +22,4 @@ class TestGetSecrets(unittest.TestCase):
21
22
 
22
23
 
23
24
  if __name__ == '__main__':
24
- unittest.main()
25
+ unittest.main()
@@ -1,25 +0,0 @@
1
- # getSecrets package
2
-
3
- getSecrets is a simple package that reads from the given engine ('secret' by default) of a Hashicorp vault
4
-
5
- usage:
6
-
7
- ```
8
- from getSecrets import *
9
-
10
- data = get_secret(<id>, [<secret>])
11
-
12
- usr_pwd = get_user_pwd(<id>, <new k_v_dict> , [<secret>])
13
-
14
- list = list_secret([<secret>]
15
-
16
- ```
17
-
18
- Vault parameters are stored in a config file ~/.config/.vault/.vault.yml
19
-
20
- ```
21
- vault:
22
- token: "<access token>"
23
- vault_addr: "https://vault:8200"
24
- certs: "<path>/bundle.pem"
25
- ```
@@ -1,153 +0,0 @@
1
- import logging
2
- from os import getenv
3
- from os.path import join
4
- import requests
5
- import yaml
6
- import os
7
- import sys
8
-
9
-
10
- logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s',
11
- datefmt='%m/%d/%Y %I:%M:%S %p')
12
-
13
- _config_file = "~/.config/.vault/vault.yml"
14
- _home = getenv("HOME")
15
-
16
- try:
17
- _config = yaml.safe_load(open(join(_home, _config_file.replace("~/", ''))))
18
- except FileNotFoundError:
19
- if not os.path.exists("/etc/vault"):
20
- os.makedirs("/etc/vault")
21
- _home = "/etc/vault"
22
- try:
23
- _config = yaml.safe_load(open(join(_home, 'vault.yml')))
24
- except FileNotFoundError:
25
- logging.error(f"No vault configuration found in {_home}")
26
- sys.exit(1)
27
-
28
-
29
- def get_secret(id: str, repo: str = 'secret') -> dict:
30
- """
31
- :param id: The ID of the secret to retrieve
32
- :param repo: The name of the secrets repository to retrieve the secret from - defaults to 'secret'
33
- :return: a json object with key/value pairs
34
- or an empty object if the secret retrieval fails
35
-
36
- This method retrieves a secret from a Vault server using the provided ID.
37
- If the request is successful (status code 200), the method extracts the key-value pairs JSON object.
38
- If the request fails, the method logs an HTTP error message and returns a n empty json {}.
39
- """
40
-
41
- base_url = _config['vault']['vault_addr']
42
- if _home == '/etc/vault':
43
- certs = '/etc/vault/bundle.pem'
44
- else:
45
- certs = join(_home, _config['vault']['certs'].replace("~/", ''))
46
-
47
- token = _config['vault']['token']
48
- headers = {"X-Vault-Token": token}
49
- uri = f"/v1/{repo}/data/"
50
- url = f"{base_url}{uri}{id}"
51
- resp = requests.get(url, headers=headers, verify=certs)
52
- if resp.status_code == 200:
53
- secret = resp.json()["data"]["data"]
54
- return secret
55
-
56
- else:
57
- print(f"http error {resp.status_code}")
58
- logging.error(f"Vault api error {resp}")
59
- return {}
60
-
61
-
62
- def get_user_pwd(id: str, repo: str = 'secret') -> tuple:
63
- """
64
- :param id: The ID of the secret to retrieve
65
- :param repo: The name of the secret repository to retrieve the seret from - defaults to 'secret'
66
- :return: a tuple username, password values if the secrets has such keys, else None, None
67
-
68
- This method retrieves a secret from a Vault server using the provided ID.
69
- If the request is successful (status code 200), the method extracts the username and password key value
70
- if such keys exist.
71
- If the request fails, the method prints an HTTP error message and returns (None, None).
72
- """
73
-
74
- base_url = _config['vault']['vault_addr']
75
- certs = join(_home, _config['vault']['certs'].replace("~/", ''))
76
- token = _config['vault']['token']
77
-
78
- headers = {"X-Vault-Token": token}
79
- uri = f"/v1/{repo}/data/"
80
- url = f"{base_url}{uri}{id}"
81
- resp = requests.get(url, headers=headers, verify=certs)
82
- if resp.status_code == 200:
83
- secret = resp.json()["data"]["data"]
84
- if 'username' in secret and 'password' in secret:
85
- return secret['username'], secret['password']
86
- else:
87
- return None, None
88
-
89
- else:
90
- print(f"http error {resp.status_code}")
91
- logging.error(f"Vault api error {resp}")
92
- return None, None
93
-
94
-
95
- def list_secret(repo: str = 'secret'):
96
- """
97
- :param repo: The name of a secret repository to retrieve the secret from - defaults to 'secret'
98
- :return: A list containing all items keys from the repository
99
-
100
- """
101
-
102
- base_url = _config['vault']['vault_addr']
103
- certs = join(_home, _config['vault']['certs'].replace("~/", ''))
104
- token = _config['vault']['token']
105
-
106
- headers = {"X-Vault-Token": token}
107
- uri = f"/v1/{repo}/metadata"
108
- url = f"{base_url}{uri}"
109
- resp = requests.request('LIST', url, headers=headers, verify=certs)
110
- if resp.status_code == 200:
111
- return resp.json()["data"]["keys"]
112
-
113
- else:
114
- print(f"http error {resp.status_code}")
115
- logging.error(f"Vault api error {resp}")
116
- return None, None
117
-
118
-
119
- def upd_secret(id: str, data, repo: str = 'secret'):
120
- """
121
- :param id: The ID of the secret to retrieve
122
- :param data: The data to be uploaded in place of the exitisting one
123
- :param repo: The name of the repository to retrieve the secret from - defaults to 'secret'
124
- :return: the response status code from the vault - 200 if successful.
125
-
126
- """
127
-
128
- base_url = _config['vault']['vault_addr']
129
- certs = join(_home, _config['vault']['certs'].replace("~/", ''))
130
- token = _config['vault']['token']
131
-
132
- headers = {"X-Vault-Token": token}
133
- uri = f"/v1/{repo}/data/"
134
- url = f"{base_url}{uri}{id}"
135
- resp = requests.request('GET', url, headers=headers, verify=certs)
136
- if resp.status_code == 200:
137
- version = resp.json()["data"]['metadata']['version']
138
- obj = {
139
- "options": {
140
- "cas": version
141
- },
142
- "data": data
143
- }
144
-
145
- resp2 = requests.request('POST', url, headers=headers, json=obj, verify=certs)
146
- if resp2.status_code != 200:
147
- logging.warning(f"Vault update error for {id} with new {data}")
148
- return resp2.status_code
149
-
150
- else:
151
- print(f"http error {resp.status_code}")
152
- logging.error(f"Vault api error {resp}")
153
- return None, None
File without changes