20
20
import errno
21
21
from functools import partial
22
22
import hashlib
23
+ import json
23
24
import logging
24
25
import os
25
26
import re
28
29
import gnupg
29
30
import yaml
30
31
32
+ from kapitan .utils import PrettyDumper
33
+
31
34
logger = logging .getLogger (__name__ )
32
35
33
36
SECRET_TOKEN_TAG_PATTERN = r"(\?{([\w\:\.\-\/]+)})" # e.g. ?{gpg:my/secret/token}
@@ -196,20 +199,23 @@ def reveal_gpg_replace(gpg_obj, secrets_path, match_obj, verify=True, **kwargs):
196
199
logger .debug ("Revealing %s" , token_tag )
197
200
return secret_gpg_read (gpg_obj , secrets_path , token , ** kwargs )
198
201
199
- def secret_gpg_reveal (gpg_obj , secrets_path , filename , verify = True , output = None , ** kwargs ):
202
+ def secret_gpg_reveal_raw (gpg_obj , secrets_path , filename , verify = True , output = None , ** kwargs ):
200
203
"""
201
- read filename and reveal content with secrets to stdout
204
+ read filename and reveal content (per line search and replace) with secrets to stdout
202
205
set filename=None to read stdin
203
206
set verify=False to skip secret hash verification
204
207
set output to filename to write to file object, default is stdout
208
+ returns string with revealed content when output is not stdout
205
209
"""
206
210
_reveal_gpg_replace = partial (reveal_gpg_replace , gpg_obj , secrets_path ,
207
211
verify = verify , ** kwargs )
212
+ out_raw = ''
208
213
if filename is None :
209
214
for line in sys .stdin :
210
215
revealed = re .sub (SECRET_TOKEN_TAG_PATTERN , _reveal_gpg_replace , line )
211
216
if output :
212
217
output .write (revealed )
218
+ out_raw += revealed
213
219
else :
214
220
sys .stdout .write (revealed )
215
221
else :
@@ -218,5 +224,76 @@ def secret_gpg_reveal(gpg_obj, secrets_path, filename, verify=True, output=None,
218
224
revealed = re .sub (SECRET_TOKEN_TAG_PATTERN , _reveal_gpg_replace , line )
219
225
if output :
220
226
output .write (revealed )
227
+ out_raw += revealed
221
228
else :
222
229
sys .stdout .write (revealed )
230
+
231
+ return out_raw
232
+
233
+ def secret_gpg_reveal_obj (gpg_obj , secrets_path , obj , verify = True , ** kwargs ):
234
+ "recursively updates obj with revealed secrets"
235
+ def sub_reveal_data (data ):
236
+ _reveal_gpg_replace = partial (reveal_gpg_replace , gpg_obj , secrets_path ,
237
+ verify = verify , ** kwargs )
238
+ return re .sub (SECRET_TOKEN_TAG_PATTERN , _reveal_gpg_replace , data )
239
+
240
+ if isinstance (obj , dict ):
241
+ for k , v in obj .iteritems ():
242
+ obj [k ] = secret_gpg_reveal_obj (gpg_obj , secrets_path , v , verify , ** kwargs )
243
+ elif isinstance (obj , list ):
244
+ obj = [secret_gpg_reveal_obj (gpg_obj , secrets_path , item , verify , ** kwargs ) for item in obj ]
245
+ elif isinstance (obj , basestring ): # XXX this is python 2 specific
246
+ obj = sub_reveal_data (obj )
247
+
248
+ return obj
249
+
250
+ def secret_gpg_reveal_dir (gpg_obj , secrets_path , dirname , verify = True , ** kwargs ):
251
+ "prints grouped output for revealed file types"
252
+ out_json = ''
253
+ out_yaml = ''
254
+ out_raw = ''
255
+ # find yaml/json/raw files and group their outputs
256
+ for f in os .listdir (dirname ):
257
+ full_path = os .path .join (dirname , f )
258
+ if not os .path .isfile (full_path ):
259
+ pass
260
+ if f .endswith ('.json' ):
261
+ out_json += secret_gpg_reveal_file (gpg_obj , secrets_path , full_path ,
262
+ verify = verify , ** kwargs )
263
+ elif f .endswith ('.yml' ):
264
+ out_yaml += secret_gpg_reveal_file (gpg_obj , secrets_path , full_path ,
265
+ verify = verify , ** kwargs )
266
+ else :
267
+ out_raw += secret_gpg_reveal_file (gpg_obj , secrets_path , full_path ,
268
+ verify = verify , ** kwargs )
269
+ if out_json :
270
+ sys .stdout .write (out_json )
271
+ if out_yaml :
272
+ sys .stdout .write (out_yaml )
273
+ if out_raw :
274
+ sys .stdout .write (out_raw )
275
+
276
+ def secret_gpg_reveal_file (gpg_obj , secrets_path , filename , verify = True , ** kwargs ):
277
+ "detects type and reveals file, returns revealed output string"
278
+ out = None
279
+ if filename .endswith ('.json' ):
280
+ logger .debug ("secret_gpg_reveal_file: revealing json file: %s" , filename )
281
+ with open (filename ) as fp :
282
+ obj = json .load (fp )
283
+ rev_obj = secret_gpg_reveal_obj (gpg_obj , secrets_path , obj ,
284
+ verify = verify , ** kwargs )
285
+ out = json .dumps (rev_obj , indent = 4 , sort_keys = True )
286
+ elif filename .endswith ('.yml' ):
287
+ logger .debug ("secret_gpg_reveal_file: revealing yml file: %s" , filename )
288
+ with open (filename ) as fp :
289
+ obj = yaml .safe_load (fp )
290
+ rev_obj = secret_gpg_reveal_obj (gpg_obj , secrets_path , obj ,
291
+ verify = verify , ** kwargs )
292
+ out = yaml .dump (rev_obj , Dumper = PrettyDumper ,
293
+ default_flow_style = False , explicit_start = True )
294
+ else :
295
+ logger .debug ("secret_gpg_reveal_file: revealing raw file: %s" , filename )
296
+ devnull = open (os .devnull , 'w' )
297
+ out = secret_gpg_reveal_raw (gpg_obj , secrets_path , filename , output = devnull ,
298
+ verify = verify , ** kwargs )
299
+ return out
0 commit comments