Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/msal/region.py: 27%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

37 statements  

1import json 

2import os 

3import logging 

4import re 

5 

6logger = logging.getLogger(__name__) 

7 

8_VALID_REGION_RE = re.compile(r"^[a-z][a-z0-9-]*$") 

9 

10# IMDS compute metadata API version used for region auto-discovery. 

11# Bump this single constant when moving to a newer IMDS API version. 

12_IMDS_API_VERSION = "2021-02-01" 

13 

14 

15def _validate_region(region, source="unknown"): 

16 """Return *region* unchanged if it looks like a valid Azure region name, 

17 otherwise log a warning and return ``None``.""" 

18 if region and _VALID_REGION_RE.match(region): 

19 return region 

20 if region: 

21 logger.warning( 

22 "Region from %s was discarded because it contains " 

23 "invalid characters: %r", source, region) 

24 return None 

25 

26 

27def _detect_region(http_client=None): 

28 region = os.environ.get("REGION_NAME", "").replace(" ", "").lower() # e.g. westus2 

29 if region: 

30 return _validate_region(region, source="REGION_NAME env variable") 

31 if http_client: 

32 return _detect_region_of_azure_vm(http_client) # It could hang for minutes 

33 return None 

34 

35 

36def _detect_region_of_azure_vm(http_client): 

37 url = ( 

38 "http://169.254.169.254/metadata/instance/compute" 

39 

40 # The region is read from the "location" field of the compute metadata. 

41 # https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=linux#response-1 

42 "?api-version=" + _IMDS_API_VERSION 

43 ) 

44 logger.info( 

45 "Connecting to IMDS {}. " 

46 "It may take a while if you are running outside of Azure. " 

47 "You should consider opting in/out region behavior on-demand, " 

48 'by loading a boolean flag "is_deployed_in_azure" ' 

49 'from your per-deployment config and then do ' 

50 '"app = ConfidentialClientApplication(..., ' 

51 'azure_region=is_deployed_in_azure)"'.format(url)) 

52 try: 

53 # https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux#instance-metadata 

54 resp = http_client.get(url, headers={"Metadata": "true"}) 

55 except: 

56 logger.info( 

57 "IMDS {} unavailable. Perhaps not running in Azure VM?".format(url)) 

58 return None 

59 else: 

60 try: 

61 location = json.loads(resp.text).get("location") 

62 except (ValueError, AttributeError, TypeError): 

63 # ValueError: body is not valid JSON; 

64 # AttributeError: body is valid JSON but not a JSON object; 

65 # TypeError: resp.text is not a string (e.g. a custom http_client). 

66 logger.info("IMDS {} returned a malformed response.".format(url)) 

67 return None 

68 if location is not None and not isinstance(location, str): 

69 logger.info("IMDS {} returned a non-string location.".format(url)) 

70 return None 

71 return _validate_region(location, source="IMDS endpoint") 

72