16
16
import re
17
17
import shlex
18
18
import struct
19
+ import os
19
20
20
21
import requests
21
22
import requests .exceptions
22
23
import six
23
24
24
25
from .auth import auth
25
26
from .unixconn import unixconn
27
+ from .ssladapter import ssladapter
26
28
from .utils import utils
29
+ from .exceptions import exceptions
27
30
28
31
if not six .PY3 :
29
32
import websocket
@@ -75,12 +78,14 @@ def __init__(self,
75
78
timeout = DEFAULT_TIMEOUT_SECONDS ,
76
79
tls = False ,
77
80
tls_cert = None ,
78
- tls_key = None ):
81
+ tls_key = None ,
82
+ tls_verify = False ,
83
+ tls_ca_cert = None ,
84
+ ssl_version = None ):
79
85
super (Client , self ).__init__ ()
80
- if tls and not (tls_cert and tls_key ):
81
- raise RuntimeError ('tls_key and tls_cert are required.' )
82
- if tls and not base_url .startswith ('https' ):
83
- raise RuntimeError ('TLS: base_url has to start with https://' )
86
+
87
+ if (tls or tls_verify ) and not base_url .startswith ('https://' ):
88
+ raise exceptions .TLSParameterError ('If using TLS, the base_url argument must begin with "https://".' )
84
89
if base_url is None :
85
90
base_url = "http+unix://var/run/docker.sock"
86
91
if 'unix:///' in base_url :
@@ -96,10 +101,44 @@ def __init__(self,
96
101
self ._timeout = timeout
97
102
self ._auth_configs = auth .load_config ()
98
103
99
- if tls :
100
- self .cert = (tls_cert , tls_key )
101
- self .verify = False # We assume the server.crt will we self signed
102
- self .mount ('https://' , requests .adapters .HTTPAdapter ())
104
+ """ Argument compatibility/mapping with http://docs.docker.io/examples/https/
105
+
106
+ This diverges from the Docker CLI in that users can specify 'tls' here, but also
107
+ disable any public/default CA pool verification by leaving tls_verify=False
108
+ """
109
+ """ urllib3 sets a default ssl_version if ssl_version is None
110
+ https://github.com/shazow/urllib3/blob/62ecd1523ec383802cb13b09bd7084d2da997420/urllib3/util/ssl_.py#L83
111
+ """
112
+ self .ssl_version = ssl_version
113
+
114
+ """ "tls" and "tls_verify" must have both or neither cert/key files
115
+ In either case, Alert the user when both are expected, but any are missing."""
116
+ if (tls or tls_verify ) and (tls_cert or tls_key ):
117
+ if not (tls_cert and tls_key ) or (not os .path .isfile (tls_cert ) or not os .path .isfile (tls_key )):
118
+ raise exceptions .TLSParameterError (
119
+ 'You must provide either both "tls_cert"/"tls_key" files, or neither, in order to use TLS.' )
120
+ else :
121
+ self .cert = (tls_cert , tls_key )
122
+
123
+ """
124
+ Either set tls_verify to True (public/default CA checks) or to the path of a CA Cert file.
125
+ ref: https://github.com/kennethreitz/requests/blob/739d153ef77765392fa109bebead4260c05f3193/requests/adapters.py#L135-L137
126
+ ref: https://github.com/kennethreitz/requests/blob/master/requests/sessions.py#L433-L439
127
+ """
128
+ if tls_verify :
129
+ if not tls_ca_cert :
130
+ self .verify = True
131
+ elif os .path .isfile (tls_ca_cert ):
132
+ self .verify = tls_ca_cert
133
+ else :
134
+ raise exceptions .TLSParameterError (
135
+ 'If "tls_verify" is set, then "tls_ca_cert" must be blank (to check default/public CA list) OR a path to a CA Cert File.' )
136
+ else :
137
+ self .verify = False
138
+
139
+ """ Use SSLAdapter for the ability to specify SSL version """
140
+ if tls or tls_verify :
141
+ self .mount ('https://' , ssladapter .SSLAdapter (self .ssl_version ))
103
142
else :
104
143
self .mount ('http+unix://' , unixconn .UnixAdapter (base_url , timeout ))
105
144
0 commit comments