|
1 | 1 | import asyncio |
| 2 | +import platform |
| 3 | +import subprocess |
2 | 4 | import time |
3 | 5 | import enum |
4 | 6 | import random |
@@ -60,15 +62,57 @@ def build_dict_from_map(m): |
60 | 62 | return d |
61 | 63 |
|
62 | 64 |
|
| 65 | +def _fetch_root_certificates_darwin(): |
| 66 | + try: |
| 67 | + p = subprocess.run( |
| 68 | + ["security", "find-certificate", "-a", "-p"], |
| 69 | + capture_output=True, |
| 70 | + timeout=10, |
| 71 | + ) |
| 72 | + if p.returncode != 0 or not p.stdout: |
| 73 | + return None |
| 74 | + return p.stdout |
| 75 | + except Exception: |
| 76 | + logging.exception("unexpected error when fetching certificates from macOS Keychain") |
| 77 | + |
| 78 | + return None |
| 79 | + |
| 80 | + |
| 81 | +def _fetch_root_certificates_linux(): |
| 82 | + ca_bundle_path = "/etc/ssl/certs/ca-certificates.crt" |
| 83 | + try: |
| 84 | + # TODO: Current supports Debian/Ubuntu. Extend to support other distributions. |
| 85 | + with open(ca_bundle_path, "rb") as f: |
| 86 | + certs = f.read() |
| 87 | + if certs: |
| 88 | + return certs |
| 89 | + except OSError as e: |
| 90 | + logging.warning("failed to read CA bundle at %s: %s", ca_bundle_path, e) |
| 91 | + except Exception: |
| 92 | + logging.exception("unexpected error while reading ca certificates") |
| 93 | + |
| 94 | + return None |
| 95 | + |
| 96 | + |
| 97 | +def _fetch_root_certificates(): |
| 98 | + if platform.system() == "Darwin": |
| 99 | + return _fetch_root_certificates_darwin() |
| 100 | + |
| 101 | + if platform.system() == "Linux": |
| 102 | + return _fetch_root_certificates_linux() |
| 103 | + |
| 104 | + return None |
| 105 | + |
| 106 | + |
63 | 107 | def get_client_credentials(args: Namespace) -> Optional[grpc.ChannelCredentials]: |
64 | 108 | if not args.secure: |
65 | 109 | return None |
66 | 110 |
|
67 | 111 | if not args.cert: |
68 | | - return grpc.ssl_channel_credentials() |
| 112 | + return grpc.ssl_channel_credentials(root_certificates=_fetch_root_certificates()) |
69 | 113 |
|
70 | 114 | with open(args.cert, "rb") as fc: |
71 | | - return grpc.ssl_channel_credentials(fc.read()) |
| 115 | + return grpc.ssl_channel_credentials(root_certificates=fc.read()) |
72 | 116 |
|
73 | 117 |
|
74 | 118 | @attr.s(eq=False) |
|
0 commit comments