... |
... |
@@ -72,6 +72,56 @@ def create_server(repo, *, enable_push): |
72
|
72
|
return server
|
73
|
73
|
|
74
|
74
|
|
|
75
|
+class _SSLServerCredentialsCallable:
|
|
76
|
+
|
|
77
|
+ def __init__(self, server_key, server_cert, client_certs):
|
|
78
|
+ self.server_key = server_key
|
|
79
|
+ self.server_cert = server_cert
|
|
80
|
+ self.client_certs = client_certs
|
|
81
|
+ self.client_certs_stat = None
|
|
82
|
+ self.load_server_key()
|
|
83
|
+ self.load_server_cert()
|
|
84
|
+ self.load_client_certs()
|
|
85
|
+
|
|
86
|
+ def load_server_key(self):
|
|
87
|
+ with open(self.server_key, 'rb') as f:
|
|
88
|
+ self.server_key_bytes = f.read()
|
|
89
|
+
|
|
90
|
+ def load_server_cert(self):
|
|
91
|
+ with open(self.server_cert, 'rb') as f:
|
|
92
|
+ self.server_cert_bytes = f.read()
|
|
93
|
+
|
|
94
|
+ def load_client_certs(self):
|
|
95
|
+ if self.client_certs:
|
|
96
|
+ with open(self.client_certs, 'rb') as f:
|
|
97
|
+ stat = os.fstat(f.fileno())
|
|
98
|
+ if stat != self.client_certs_stat:
|
|
99
|
+ # The stat is different. We need to reload the client certs
|
|
100
|
+ self.client_certs_bytes = f.read()
|
|
101
|
+ self.client_certs_stat = stat
|
|
102
|
+ return True
|
|
103
|
+ return False
|
|
104
|
+ else:
|
|
105
|
+ self.client_certs_stat = None
|
|
106
|
+ self.client_certs_bytes = None
|
|
107
|
+ # Nothing has been loaded
|
|
108
|
+ return False
|
|
109
|
+
|
|
110
|
+ def get_ssl_server_credentials(self):
|
|
111
|
+ return grpc.ssl_server_certificate_configuration(
|
|
112
|
+ private_key_certificate_chain_pairs=[(self.server_key_bytes, self.server_cert_bytes)],
|
|
113
|
+ root_certificates=self.client_certs_bytes,
|
|
114
|
+ )
|
|
115
|
+
|
|
116
|
+ def __call__(self):
|
|
117
|
+ if self.load_client_certs():
|
|
118
|
+ # We performed a reload
|
|
119
|
+ return self.get_ssl_server_credentials()
|
|
120
|
+ else:
|
|
121
|
+ # Nothing changed
|
|
122
|
+ return None
|
|
123
|
+
|
|
124
|
+
|
75
|
125
|
@click.command(short_help="CAS Artifact Server")
|
76
|
126
|
@click.option('--port', '-p', type=click.INT, required=True, help="Port number")
|
77
|
127
|
@click.option('--server-key', help="Private server key for TLS (PEM-encoded)")
|
... |
... |
@@ -94,22 +144,13 @@ def server_main(repo, port, server_key, server_cert, client_certs, enable_push): |
94
|
144
|
sys.exit(-1)
|
95
|
145
|
|
96
|
146
|
if use_tls:
|
97
|
|
- # Read public/private key pair
|
98
|
|
- with open(server_key, 'rb') as f:
|
99
|
|
- server_key_bytes = f.read()
|
100
|
|
- with open(server_cert, 'rb') as f:
|
101
|
|
- server_cert_bytes = f.read()
|
102
|
|
-
|
103
|
|
- if client_certs:
|
104
|
|
- with open(client_certs, 'rb') as f:
|
105
|
|
- client_certs_bytes = f.read()
|
106
|
|
- else:
|
107
|
|
- client_certs_bytes = None
|
108
|
|
-
|
109
|
|
- credentials = grpc.ssl_server_credentials([(server_key_bytes, server_cert_bytes)],
|
110
|
|
- root_certificates=client_certs_bytes,
|
111
|
|
- require_client_auth=bool(client_certs))
|
112
|
|
- server.add_secure_port('[::]:{}'.format(port), credentials)
|
|
147
|
+ credentials_gen = _SSLServerCredentialsCallable(server_key, server_cert, client_certs)
|
|
148
|
+ initial_credentials = credentials_gen.get_ssl_server_credentials()
|
|
149
|
+ dynamic_credentials = grpc.dynamic_ssl_server_credentials(
|
|
150
|
+ initial_certificate_configuration=initial_credentials,
|
|
151
|
+ certificate_configuration_fetcher=credentials_gen,
|
|
152
|
+ require_client_authentication=bool(client_certs))
|
|
153
|
+ server.add_secure_port('[::]:{}'.format(port), dynamic_credentials)
|
113
|
154
|
else:
|
114
|
155
|
server.add_insecure_port('[::]:{}'.format(port))
|
115
|
156
|
|