github.com/letsencrypt/boulder@v0.20251208.0/test/challtestsrv.py (about) 1 import json 2 import requests 3 4 class ChallTestServer: 5 """ 6 ChallTestServer is a wrapper around chall-test-srv's HTTP management 7 API. If the chall-test-srv process you want to interact with is using 8 a -management argument other than the default ('http://10.77.77.77:8055') you 9 can instantiate the ChallTestServer using the -management address in use. If 10 no custom address is provided the default is assumed. 11 """ 12 _baseURL = "http://10.77.77.77:8055" 13 14 _paths = { 15 "set-ipv4": "/set-default-ipv4", 16 "set-ipv6": "/set-default-ipv6", 17 "del-history": "/clear-request-history", 18 "get-http-history": "/http-request-history", 19 "get-dns-history": "/dns-request-history", 20 "get-alpn-history": "/tlsalpn01-request-history", 21 "add-a": "/add-a", 22 "del-a": "/clear-a", 23 "add-aaaa": "/add-aaaa", 24 "del-aaaa": "/clear-aaaa", 25 "add-caa": "/add-caa", 26 "del-caa": "/clear-caa", 27 "add-redirect": "/add-redirect", 28 "del-redirect": "/del-redirect", 29 "add-http": "/add-http01", 30 "del-http": "/del-http01", 31 "add-txt": "/set-txt", 32 "del-txt": "/clear-txt", 33 "add-alpn": "/add-tlsalpn01", 34 "del-alpn": "/del-tlsalpn01", 35 "add-servfail": "/set-servfail", 36 "del-servfail": "/clear-servfail", 37 } 38 39 def __init__(self, url=None): 40 if url is not None: 41 self._baseURL = url 42 43 def _postURL(self, url, body): 44 response = requests.post( 45 url, 46 data=json.dumps(body)) 47 return response.text 48 49 def _URL(self, path): 50 urlPath = self._paths.get(path, None) 51 if urlPath is None: 52 raise Exception("No challenge test server URL path known for {0}".format(path)) 53 return self._baseURL + urlPath 54 55 def _clear_request_history(self, host, typ): 56 return self._postURL( 57 self._URL("del-history"), 58 { "host": host, "type": typ }) 59 60 def set_default_ipv4(self, address): 61 """ 62 set_default_ipv4 sets the challenge server's default IPv4 address used 63 to respond to A queries when there are no specific mock A addresses for 64 the hostname being queried. Provide an empty string as the default 65 address to disable answering A queries except for hosts that have mock 66 A addresses added. 67 """ 68 return self._postURL( 69 self._URL("set-ipv4"), 70 { "ip": address }) 71 72 def set_default_ipv6(self, address): 73 """ 74 set_default_ipv6 sets the challenge server's default IPv6 address used 75 to respond to AAAA queries when there are no specific mock AAAA 76 addresses for the hostname being queried. Provide an empty string as the 77 default address to disable answering AAAA queries except for hosts that 78 have mock AAAA addresses added. 79 """ 80 return self._postURL( 81 self._URL("set-ipv6"), 82 { "ip": address }) 83 84 def add_a_record(self, host, addresses): 85 """ 86 add_a_record adds a mock A response to the challenge server's DNS 87 interface for the given host and IPv4 addresses. 88 """ 89 return self._postURL( 90 self._URL("add-a"), 91 { "host": host, "addresses": addresses }) 92 93 def remove_a_record(self, host): 94 """ 95 remove_a_record removes a mock A response from the challenge server's DNS 96 interface for the given host. 97 """ 98 return self._postURL( 99 self._URL("del-a"), 100 { "host": host }) 101 102 def add_aaaa_record(self, host, addresses): 103 """ 104 add_aaaa_record adds a mock AAAA response to the challenge server's DNS 105 interface for the given host and IPv6 addresses. 106 """ 107 return self._postURL( 108 self._URL("add-aaaa"), 109 { "host": host, "addresses": addresses }) 110 111 def remove_aaaa_record(self, host): 112 """ 113 remove_aaaa_record removes mock AAAA response from the challenge server's DNS 114 interface for the given host. 115 """ 116 return self._postURL( 117 self._URL("del-aaaa"), 118 { "host": host }) 119 120 def add_caa_issue(self, host, value): 121 """ 122 add_caa_issue adds a mock CAA response to the challenge server's DNS 123 interface. The mock CAA response will contain one policy with an "issue" 124 tag specifying the provided value. 125 """ 126 return self._postURL( 127 self._URL("add-caa"), 128 { 129 "host": host, 130 "policies": [{ "tag": "issue", "value": value}], 131 }) 132 133 def remove_caa_issue(self, host): 134 """ 135 remove_caa_issue removes a mock CAA response from the challenge server's 136 DNS interface for the given host. 137 """ 138 return self._postURL( 139 self._URL("del-caa"), 140 { "host": host }) 141 142 def http_request_history(self, host): 143 """ 144 http_request_history fetches the challenge server's HTTP request history for the given host. 145 """ 146 return json.loads(self._postURL( 147 self._URL("get-http-history"), 148 { "host": host })) 149 150 def clear_http_request_history(self, host): 151 """ 152 clear_http_request_history clears the challenge server's HTTP request history for the given host. 153 """ 154 return self._clear_request_history(host, "http") 155 156 def add_http_redirect(self, path, targetURL): 157 """ 158 add_http_redirect adds a redirect to the challenge server's HTTP 159 interfaces for HTTP requests to the given path directing the client to 160 the targetURL. Redirects are not served for HTTPS requests. 161 """ 162 return self._postURL( 163 self._URL("add-redirect"), 164 { "path": path, "targetURL": targetURL }) 165 166 def remove_http_redirect(self, path): 167 """ 168 remove_http_redirect removes a redirect from the challenge server's HTTP 169 interfaces for the given path. 170 """ 171 return self._postURL( 172 self._URL("del-redirect"), 173 { "path": path }) 174 175 def add_http01_response(self, token, keyauth): 176 """ 177 add_http01_response adds an ACME HTTP-01 challenge response for the 178 provided token under the /.well-known/acme-challenge/ path of the 179 challenge test server's HTTP interfaces. The given keyauth will be 180 returned as the HTTP response body for requests to the challenge token. 181 """ 182 return self._postURL( 183 self._URL("add-http"), 184 { "token": token, "content": keyauth }) 185 186 def remove_http01_response(self, token): 187 """ 188 remove_http01_response removes an ACME HTTP-01 challenge response for 189 the provided token from the challenge test server. 190 """ 191 return self._postURL( 192 self._URL("del-http"), 193 { "token": token }) 194 195 def add_servfail_response(self, host): 196 """ 197 add_servfail_response configures the challenge test server to return 198 SERVFAIL for all queries made for the provided host. This will override 199 any other mocks for the host until removed with remove_servfail_response. 200 """ 201 return self._postURL( 202 self._URL("add-servfail"), 203 { "host": host}) 204 205 def remove_servfail_response(self, host): 206 """ 207 remove_servfail_response undoes the work of add_servfail_response, 208 removing the SERVFAIL configuration for the given host. 209 """ 210 return self._postURL( 211 self._URL("del-servfail"), 212 { "host": host}) 213 214 def add_dns01_response(self, host, value): 215 """ 216 add_dns01_response adds an ACME DNS-01 challenge response for the 217 provided host to the challenge test server's DNS interfaces. The 218 provided value will be served for TXT queries for 219 _acme-challenge.<host>. 220 """ 221 if host.endswith(".") is False: 222 host = host + "." 223 return self._postURL( 224 self._URL("add-txt"), 225 { "host": host, "value": value}) 226 227 def remove_dns01_response(self, host): 228 """ 229 remove_dns01_response removes an ACME DNS-01 challenge response for the 230 provided host from the challenge test server's DNS interfaces. 231 """ 232 return self._postURL( 233 self._URL("del-txt"), 234 { "host": host }) 235 236 def dns_request_history(self, host): 237 """ 238 dns_request_history returns the history of DNS requests made to the 239 challenge test server's DNS interfaces for the given host. 240 """ 241 return json.loads(self._postURL( 242 self._URL("get-dns-history"), 243 { "host": host })) 244 245 def clear_dns_request_history(self, host): 246 """ 247 clear_dns_request_history clears the history of DNS requests made to the 248 challenge test server's DNS interfaces for the given host. 249 """ 250 return self._clear_request_history(host, "dns") 251 252 def add_tlsalpn01_response(self, host, value): 253 """ 254 add_tlsalpn01_response adds an ACME TLS-ALPN-01 challenge response 255 certificate to the challenge test server's TLS-ALPN-01 interface for the 256 given host. The provided key authorization value will be embedded in the 257 response certificate served to clients that initiate a TLS-ALPN-01 258 challenge validation with the challenge test server for the provided 259 host. 260 """ 261 return self._postURL( 262 self._URL("add-alpn"), 263 { "host": host, "content": value}) 264 265 def remove_tlsalpn01_response(self, host): 266 """ 267 remove_tlsalpn01_response removes an ACME TLS-ALPN-01 challenge response 268 certificate from the challenge test server's TLS-ALPN-01 interface for 269 the given host. 270 """ 271 return self._postURL( 272 self._URL("del-alpn"), 273 { "host": host }) 274 275 def tlsalpn01_request_history(self, host): 276 """ 277 tls_alpn01_request_history returns the history of TLS-ALPN-01 requests 278 made to the challenge test server's TLS-ALPN-01 interface for the given 279 host. 280 """ 281 return json.loads(self._postURL( 282 self._URL("get-alpn-history"), 283 { "host": host })) 284 285 def clear_tlsalpn01_request_history(self, host): 286 """ 287 clear_tlsalpn01_request_history clears the history of TLS-ALPN-01 288 requests made to the challenge test server's TLS-ALPN-01 interface for 289 the given host. 290 """ 291 return self._clear_request_history(host, "tlsalpn")