def find_account(context): opt_hostname_keyword = r'(?:hostname|host|username|id|user|userid|user-id|user-name|' \ 'name|user_id|user_name|uname|account)' account = r'(\w[\w\-]*)' opt_basic_auth = r'(?:[\w\-:%]*\@)?' regexes = ( RegexBasedDetector.assign_regex_generator( prefix_regex=CloudantDetector.cl, secret_keyword_regex=opt_hostname_keyword, secret_regex=account, ), re.compile( r'{http}{opt_basic_auth}{cl_account}{dot}{cloudant_api_url}'.format( http=CloudantDetector.http, opt_basic_auth=opt_basic_auth, cl_account=account, dot=CloudantDetector.dot, cloudant_api_url=CloudantDetector.cloudant_api_url, ), flags=re.IGNORECASE, ), ) return [ match for line in context.splitlines() for regex in regexes for match in regex.findall(line) ]
class SoftlayerDetector(RegexBasedDetector): """Scans for Softlayer credentials.""" secret_type = 'SoftLayer Credentials' # opt means optional sl = r'(?:softlayer|sl)(?:_|-|)(?:api|)' key_or_pass = r'(?:key|pwd|password|pass|token)' secret = r'([a-z0-9]{64})' denylist = [ RegexBasedDetector.assign_regex_generator( prefix_regex=sl, secret_keyword_regex=key_or_pass, secret_regex=secret, ), re.compile( r'(?:http|https)://api.softlayer.com/soap/(?:v3|v3.1)/([a-z0-9]{64})', flags=re.IGNORECASE, ), ] def verify(self, token, content): usernames = find_username(content) if not usernames: return VerifiedResult.UNVERIFIED for username in usernames: return verify_softlayer_key(username, token) return VerifiedResult.VERIFIED_FALSE
class IbmCloudIamDetector(RegexBasedDetector): """Scans for IBM Cloud IAM Key.""" secret_type = 'IBM Cloud IAM Key' # opt means optional opt_ibm_cloud_iam = r'(?:ibm(?:_|-|)cloud(?:_|-|)iam|cloud(?:_|-|)iam|' + \ r'ibm(?:_|-|)cloud|ibm(?:_|-|)iam|ibm|iam|cloud|)' opt_dash_undrscr = r'(?:_|-|)' opt_api = r'(?:api|)' key_or_pass = r'(?:key|pwd|password|pass|token)' secret = r'([a-zA-Z0-9_\-]{44}(?![a-zA-Z0-9_\-]))' denylist = [ RegexBasedDetector.assign_regex_generator( prefix_regex=opt_ibm_cloud_iam + opt_dash_undrscr + opt_api, secret_keyword_regex=key_or_pass, secret_regex=secret, ), ] def verify(self, token, **kwargs): response = verify_cloud_iam_api_key(token) return VerifiedResult.VERIFIED_TRUE if response.status_code == 200 \ else VerifiedResult.VERIFIED_FALSE
def find_access_key_id(content): key_id_keyword_regex = r'(?:access[-_]?(?:key)?[-_]?(?:id)?|key[-_]?id)' key_id_regex = r'([a-f0-9]{32})' regex = RegexBasedDetector.assign_regex_generator( prefix_regex=IbmCosHmacDetector.token_prefix, secret_keyword_regex=key_id_keyword_regex, secret_regex=key_id_regex, ) return [ match for line in content.splitlines() for match in regex.findall(line) ]
def find_username(content): # opt means optional username_keyword = ( r'(?:' r'username|id|user|userid|user-id|user-name|' r'name|user_id|user_name|uname' r')' ) username = r'(\w(?:\w|_|@|\.|-)+)' regex = re.compile( RegexBasedDetector.assign_regex_generator( prefix_regex=SoftlayerDetector.sl, secret_keyword_regex=username_keyword, secret_regex=username, ), ) return [ match for line in content.splitlines() for match in regex.findall(line) ]
class IbmCosHmacDetector(RegexBasedDetector): """Scans for IBM Cloud Object Storage HMAC credentials.""" # requires 3 factors # # access_key: access_key_id # secret_key: secret_access_key # host, defaults to 's3.us.cloud-object-storage.appdomain.cloud' secret_type = 'IBM COS HMAC Credentials' token_prefix = r'(?:(?:ibm)?[-_]?cos[-_]?(?:hmac)?|)' password_keyword = r'(?:secret[-_]?(?:access)?[-_]?key)' password = r'([a-f0-9]{48}(?![a-f0-9]))' denylist = (RegexBasedDetector.assign_regex_generator( prefix_regex=token_prefix, secret_keyword_regex=password_keyword, secret_regex=password, ), ) def verify(self, token, content): key_id_matches = find_access_key_id(content) if not key_id_matches: return VerifiedResult.UNVERIFIED try: for key_id in key_id_matches: verify_result = verify_ibm_cos_hmac_credentials( key_id, token, ) if verify_result: return VerifiedResult.VERIFIED_TRUE except requests.exceptions.RequestException: return VerifiedResult.UNVERIFIED return VerifiedResult.VERIFIED_FALSE
class CloudantDetector(RegexBasedDetector): """Scans for Cloudant credentials.""" secret_type = 'Cloudant Credentials' # opt means optional dot = r'\.' cl_account = r'[\w\-]+' cl = r'(?:cloudant|cl|clou)' opt_api = r'(?:api|)' cl_key_or_pass = opt_api + r'(?:key|pwd|pw|password|pass|token)' cl_pw = r'([0-9a-f]{64})' cl_api_key = r'([a-z]{24})' colon = r'\:' at = r'\@' http = r'(?:https?\:\/\/)' cloudant_api_url = r'cloudant\.com' denylist = [ RegexBasedDetector.assign_regex_generator( prefix_regex=cl, secret_keyword_regex=cl_key_or_pass, secret_regex=cl_pw, ), RegexBasedDetector.assign_regex_generator( prefix_regex=cl, secret_keyword_regex=cl_key_or_pass, secret_regex=cl_api_key, ), re.compile( r'{http}{cl_account}{colon}{cl_pw}{at}{cl_account}{dot}{cloudant_api_url}'.format( http=http, colon=colon, cl_account=cl_account, cl_pw=cl_pw, at=at, dot=dot, cloudant_api_url=cloudant_api_url, ), flags=re.IGNORECASE, ), re.compile( r'{http}{cl_account}{colon}{cl_api_key}{at}{cl_account}{dot}{cloudant_api_url}'.format( http=http, colon=colon, cl_account=cl_account, cl_api_key=cl_api_key, at=at, dot=dot, cloudant_api_url=cloudant_api_url, ), flags=re.IGNORECASE, ), ] def verify(self, token, context): hosts = find_account(context) if not hosts: return VerifiedResult.UNVERIFIED for host in hosts: return verify_cloudant_key(host, token) return VerifiedResult.VERIFIED_FALSE