remove noverifyssl.txt in favor of GAM_CA_FILE

completely disabling SSL hostname verification is very dangerous and
unnecessary. Instead, allow admin to set GAM_CA_FILE to point to their
own file with certificate authorities. This file would presumably
include their own certificate authority when doing "man in the middle"
SSL/TLS inspection.
This commit is contained in:
Jay Lee
2019-04-29 10:21:56 -04:00
parent 097eb07fcc
commit 49fc1c4f7e
2 changed files with 21 additions and 19 deletions

View File

@@ -86,6 +86,8 @@ def _build_ssl_context(disable_ssl_certificate_validation, ca_certs, cert_file=N
context = ssl.SSLContext(httplib2.DEFAULT_TLS_VERSION)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
if GC_Values[GC_CA_FILE]:
ca_certs = GC_Values[GC_CA_FILE]
context.load_verify_locations(ca_certs)
if cert_file:
context.load_cert_chain(cert_file, key_file)
@@ -614,6 +616,8 @@ def SetGlobalVariables():
return GC_Defaults[itemName]
def _getCfgFile(itemName):
if not GC_Defaults[itemName]:
return None
value = os.path.expanduser(GC_Defaults[itemName])
if not os.path.isabs(value):
value = os.path.expanduser(os.path.join(GC_Values[GC_CONFIG_DIR], value))
@@ -711,8 +715,8 @@ def SetGlobalVariables():
_getOldEnvVar(GC_CSV_ROW_FILTER, 'GAM_CSV_ROW_FILTER')
_getOldEnvVar(GC_TLS_MIN_VERSION, 'GAM_TLS_MIN_VERSION')
_getOldEnvVar(GC_TLS_MAX_VERSION, 'GAM_TLS_MAX_VERSION')
_getOldEnvVar(GC_CA_FILE, 'GAM_CA_FILE')
_getOldSignalFile(GC_DEBUG_LEVEL, 'debug.gam', filePresentValue=4, fileAbsentValue=0)
_getOldSignalFile(GC_NO_VERIFY_SSL, 'noverifyssl.txt')
_getOldSignalFile(GC_NO_BROWSER, 'nobrowser.txt')
# _getOldSignalFile(GC_NO_CACHE, u'nocache.txt')
# _getOldSignalFile(GC_CACHE_DISCOVERY_ONLY, u'allcache.txt', filePresentValue=False, fileAbsentValue=True)
@@ -773,7 +777,7 @@ def doGAMCheckForUpdates(forceCheck=False):
return
check_url = GAM_LATEST_RELEASE # latest full release
headers = {'Accept': 'application/vnd.github.v3.text+json'}
simplehttp = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL])
simplehttp = httplib2.Http()
try:
(_, c) = simplehttp.request(check_url, 'GET', headers=headers)
try:
@@ -897,7 +901,7 @@ def checkGAPIError(e, soft_errors=False, silent_errors=False, retryOnHttpError=F
elif (e.resp['status'] == '400') and ('UnknownError' in eContent):
error = {'error': {'code': 400, 'errors': [{'reason': GAPI_INVALID, 'message': 'UnknownError'}]}}
elif retryOnHttpError:
service._http.request.credentials.refresh(httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL]))
service._http.request.credentials.refresh(httplib2.Http())
return (-1, None, None)
elif soft_errors:
if not silent_errors:
@@ -1239,7 +1243,7 @@ def getValidOauth2TxtCredentials():
doRequestOAuth()
credentials = storage.get()
elif credentials.access_token_expired:
http = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL])
http = httplib2.Http()
try:
credentials.refresh(http)
except oauth2client.client.HttpAccessTokenRefreshError as e:
@@ -1296,8 +1300,7 @@ def buildGAPIObject(api):
GM_Globals[GM_CURRENT_API_USER] = None
credentials = getValidOauth2TxtCredentials()
credentials.user_agent = GAM_INFO
http = credentials.authorize(httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL],
cache=GM_Globals[GM_CACHE_DIR]))
http = credentials.authorize(httplib2.Http(cache=GM_Globals[GM_CACHE_DIR]))
service = getService(api, http)
if GC_Values[GC_DOMAIN]:
if not GC_Values[GC_CUSTOMER_ID]:
@@ -1376,8 +1379,7 @@ def convertEmailAddressToUID(emailAddressOrUID, cd=None, email_type='user'):
return normalizedEmailAddressOrUID
def buildGAPIServiceObject(api, act_as, showAuthError=True):
http = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL],
cache=GM_Globals[GM_CACHE_DIR])
http = httplib2.Http(cache=GM_Globals[GM_CACHE_DIR])
service = getService(api, http)
GM_Globals[GM_CURRENT_API_USER] = act_as
GM_Globals[GM_CURRENT_API_SCOPES] = API_SCOPE_MAPPING[api]
@@ -1447,7 +1449,7 @@ def doCheckServiceAccount(users):
for scope in all_scopes:
try:
credentials = getSvcAcctCredentials([scope], user)
request = google_auth_httplib2.Request(httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL]))
request = google_auth_httplib2.Request(httplib2.Http())
credentials.refresh(request)
result = 'PASS'
except httplib2.ServerNotFoundError as e:
@@ -3922,7 +3924,7 @@ def doPhoto(users):
filename = filename.replace('#username#', user[:user.find('@')])
print("Updating photo for %s with %s (%s/%s)" % (user, filename, i, count))
if re.match('^(ht|f)tps?://.*$', filename):
simplehttp = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL])
simplehttp = httplib2.Http()
try:
(_, image_data) = simplehttp.request(filename, 'GET')
except (httplib2.HttpLib2Error, httplib2.ServerNotFoundError) as e:
@@ -7373,17 +7375,17 @@ def getCRMService(login_hint):
storage_dict = {}
storage = DictionaryStorage(storage_dict, 'credentials')
flags = cmd_flags(noLocalWebserver=GC_Values[GC_NO_BROWSER])
http = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL])
http = httplib2.Http()
credentials = oauth2client.tools.run_flow(flow=flow, storage=storage, flags=flags, http=http)
credentials.user_agent = GAM_INFO
http = credentials.authorize(httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL], cache=None))
http = credentials.authorize(httplib2.Http(cache=None))
return (googleapiclient.discovery.build('cloudresourcemanager', 'v1',
http=http, cache_discovery=False,
discoveryServiceUrl=googleapiclient.discovery.V2_DISCOVERY_URI),
http)
def getGAMProjectAPIs():
httpObj = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL])
httpObj = httplib2.Http()
_, c = httpObj.request(GAM_PROJECT_APIS, 'GET')
return httpObj, c.decode(UTF8).splitlines()
@@ -12709,7 +12711,7 @@ def doDeleteOAuth():
sys.stderr.write('boom!\n')
sys.stderr.flush()
try:
credentials.revoke(httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL]))
credentials.revoke(httplib2.Http())
except oauth2client.client.TokenRevokeError as e:
stderrErrorMsg(str(e))
storage.delete()
@@ -12717,7 +12719,7 @@ def doDeleteOAuth():
def doRequestOAuth(login_hint=None):
storage, credentials = getOauth2TxtStorageCredentials()
if credentials is None or credentials.invalid:
http = httplib2.Http(disable_ssl_certificate_validation=GC_Values[GC_NO_VERIFY_SSL])
http = httplib2.Http()
flags = cmd_flags(noLocalWebserver=GC_Values[GC_NO_BROWSER])
scopes = getScopesFromUser()
if scopes is None:

View File

@@ -701,8 +701,6 @@ GC_NO_BROWSER = 'no_browser'
GC_NO_CACHE = 'no_cache'
# Disable GAM update check
GC_NO_UPDATE_CHECK = 'no_update_check'
# Disable SSL certificate validation
GC_NO_VERIFY_SSL = 'no_verify_ssl'
# Number of threads for gam batch
GC_NUM_THREADS = 'num_threads'
# Path to oauth2.txt
@@ -727,6 +725,8 @@ GC_CSV_ROW_FILTER = 'csv_row_filter'
GC_TLS_MIN_VERSION = 'tls_min_ver'
# Maximum TLS Version used for HTTPS connections
GC_TLS_MAX_VERSION = 'tls_max_ver'
# Path to certificate authority file for validating TLS hosts
GC_CA_FILE = 'ca_file'
GC_Defaults = {
GC_ACTIVITY_MAX_RESULTS: 100,
@@ -747,7 +747,6 @@ GC_Defaults = {
GC_NO_BROWSER: False,
GC_NO_CACHE: False,
GC_NO_UPDATE_CHECK: False,
GC_NO_VERIFY_SSL: False,
GC_NUM_THREADS: 25,
GC_OAUTH2_TXT: _FN_OAUTH2_TXT,
GC_OAUTH2SERVICE_JSON: _FN_OAUTH2SERVICE_JSON,
@@ -760,6 +759,7 @@ GC_Defaults = {
GC_CSV_ROW_FILTER: '',
GC_TLS_MIN_VERSION: 'TLSv1_2',
GC_TLS_MAX_VERSION: None,
GC_CA_FILE: None,
}
GC_Values = {}
@@ -797,7 +797,6 @@ GC_VAR_INFO = {
GC_NO_BROWSER: {GC_VAR_TYPE: GC_TYPE_BOOLEAN},
GC_NO_CACHE: {GC_VAR_TYPE: GC_TYPE_BOOLEAN},
GC_NO_UPDATE_CHECK: {GC_VAR_TYPE: GC_TYPE_BOOLEAN},
GC_NO_VERIFY_SSL: {GC_VAR_TYPE: GC_TYPE_BOOLEAN},
GC_NUM_THREADS: {GC_VAR_TYPE: GC_TYPE_INTEGER, GC_VAR_LIMITS: (1, None)},
GC_OAUTH2_TXT: {GC_VAR_TYPE: GC_TYPE_FILE},
GC_OAUTH2SERVICE_JSON: {GC_VAR_TYPE: GC_TYPE_FILE},
@@ -810,6 +809,7 @@ GC_VAR_INFO = {
GC_CSV_ROW_FILTER: {GC_VAR_TYPE: GC_TYPE_ROWFILTER},
GC_TLS_MIN_VERSION: {GC_VAR_TYPE: GC_TYPE_STRING},
GC_TLS_MAX_VERSION: {GC_VAR_TYPE: GC_TYPE_STRING},
GC_CA_FILE: {GC_VAR_TYPE: GC_TYPE_FILE},
}
# Google API constants