1""" 2Basic functions for accessing the SDB interface 3 4For configuration options, see the docs for specific sdb 5modules. 6""" 7 8import random 9 10import salt.loader 11from salt.exceptions import SaltInvocationError 12 13 14def sdb_get(uri, opts, utils=None, strict=False): 15 """ 16 Get a value from a db, using a uri in the form of ``sdb://<profile>/<key>``. If 17 the uri provided is not valid, then it will be returned as-is, unless ``strict=True`` was passed. 18 """ 19 if not isinstance(uri, str) or not uri.startswith("sdb://"): 20 if strict: 21 raise SaltInvocationError('SDB uri must start with "sdb://"') 22 else: 23 return uri 24 25 if utils is None: 26 utils = salt.loader.utils(opts) 27 28 sdlen = len("sdb://") 29 indx = uri.find("/", sdlen) 30 31 if (indx == -1) or not uri[(indx + 1) :]: 32 if strict: 33 raise SaltInvocationError( 34 "SDB uri must have a profile name as a first part of the uri before" 35 " the /" 36 ) 37 else: 38 return uri 39 40 profile = opts.get(uri[sdlen:indx], {}) 41 if not profile: 42 profile = opts.get("pillar", {}).get(uri[sdlen:indx], {}) 43 if "driver" not in profile: 44 if strict: 45 raise SaltInvocationError( 46 'SDB profile "{}" wasnt found in the minion configuration'.format( 47 uri[sdlen:indx] 48 ) 49 ) 50 else: 51 return uri 52 53 fun = "{}.get".format(profile["driver"]) 54 query = uri[indx + 1 :] 55 56 loaded_db = salt.loader.sdb(opts, fun, utils=utils) 57 return loaded_db[fun](query, profile=profile) 58 59 60def sdb_set(uri, value, opts, utils=None): 61 """ 62 Set a value in a db, using a uri in the form of ``sdb://<profile>/<key>``. 63 If the uri provided does not start with ``sdb://`` or the value is not 64 successfully set, return ``False``. 65 """ 66 if not isinstance(uri, str) or not uri.startswith("sdb://"): 67 return False 68 69 if utils is None: 70 utils = salt.loader.utils(opts) 71 72 sdlen = len("sdb://") 73 indx = uri.find("/", sdlen) 74 75 if (indx == -1) or not uri[(indx + 1) :]: 76 return False 77 78 profile = opts.get(uri[sdlen:indx], {}) 79 if not profile: 80 profile = opts.get("pillar", {}).get(uri[sdlen:indx], {}) 81 if "driver" not in profile: 82 return False 83 84 fun = "{}.set".format(profile["driver"]) 85 query = uri[indx + 1 :] 86 87 loaded_db = salt.loader.sdb(opts, fun, utils=utils) 88 return loaded_db[fun](query, value, profile=profile) 89 90 91def sdb_delete(uri, opts, utils=None): 92 """ 93 Delete a value from a db, using a uri in the form of ``sdb://<profile>/<key>``. If 94 the uri provided does not start with ``sdb://`` or the value is not successfully 95 deleted, return ``False``. 96 """ 97 if not isinstance(uri, str) or not uri.startswith("sdb://"): 98 return False 99 100 if utils is None: 101 utils = salt.loader.utils(opts) 102 103 sdlen = len("sdb://") 104 indx = uri.find("/", sdlen) 105 106 if (indx == -1) or not uri[(indx + 1) :]: 107 return False 108 109 profile = opts.get(uri[sdlen:indx], {}) 110 if not profile: 111 profile = opts.get("pillar", {}).get(uri[sdlen:indx], {}) 112 if "driver" not in profile: 113 return False 114 115 fun = "{}.delete".format(profile["driver"]) 116 query = uri[indx + 1 :] 117 118 loaded_db = salt.loader.sdb(opts, fun, utils=utils) 119 return loaded_db[fun](query, profile=profile) 120 121 122def sdb_get_or_set_hash( 123 uri, 124 opts, 125 length=8, 126 chars="abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)", 127 utils=None, 128): 129 """ 130 Check if value exists in sdb. If it does, return, otherwise generate a 131 random string and store it. This can be used for storing secrets in a 132 centralized place. 133 """ 134 if not isinstance(uri, str) or not uri.startswith("sdb://"): 135 return False 136 137 if utils is None: 138 utils = salt.loader.utils(opts) 139 140 ret = sdb_get(uri, opts, utils=utils) 141 142 if ret is None: 143 val = "".join([random.SystemRandom().choice(chars) for _ in range(length)]) 144 sdb_set(uri, val, opts, utils) 145 146 return ret or val 147