Skip to content

Commit 2d8201a

Browse files
committed
feat(protocol): implement kwargs updater to handle acme posts
Also handle acme post_as_get requests. Refs: #141
1 parent cafc7dd commit 2d8201a

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

automatoes/crypto.py

+22
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,27 @@ def generate_ari_data(cert):
9191
return f"{aki_b64}.{serial_b64}"
9292

9393

94+
# TODO: accept new kinds of encryption
95+
def generate_protected_header(account_key):
96+
"""
97+
Creates a new request header for the specified account key.
98+
"""
99+
numbers = account_key.public_key().public_numbers()
100+
e = numbers.e.to_bytes((numbers.e.bit_length() // 8 + 1), byteorder='big')
101+
n = numbers.n.to_bytes((numbers.n.bit_length() // 8 + 1), byteorder='big')
102+
if n[0] == 0: # for strict JWK
103+
n = n[1:]
104+
return {
105+
'alg': 'RS256',
106+
'jwk': {
107+
'kty': 'RSA',
108+
'e': jose_b64(e),
109+
'n': jose_b64(n),
110+
},
111+
}
112+
113+
114+
# TODO: Remove this function after acme to peasant migration
94115
def generate_header(account_key):
95116
"""
96117
Creates a new request header for the specified account key.
@@ -141,6 +162,7 @@ def sign_request(key, header, protected_header, payload):
141162
})
142163

143164

165+
# TODO: we need to accept other forms of encryption over here!!!
144166
def sign_request_v2(key, protected_header, payload):
145167
"""
146168
Creates a JSON Web Signature for the request header and payload using the

automatoes/protocol.py

+48-3
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,58 @@ def __init__(self, bastion_address):
6666
self.basic_headers = {
6767
'User-Agent': self.user_agent
6868
}
69-
self.kwargs_updater = self.update_kwargs
70-
71-
def update_kwargs(self, method, **kwargs):
69+
self.kwargs_updater = self.__kwargs_updater
70+
71+
def __kwargs_updater(self, method, **kwargs):
72+
if method == METHOD_POST:
73+
kid = None
74+
if "kid" in kwargs:
75+
kid = kwargs.pop("kid")
76+
key = None
77+
if "key" in kwargs:
78+
key = kwargs.pop("key")
79+
uri = None
80+
if "uri" in kwargs:
81+
uri = kwargs.pop("uri")
82+
protected = self.get_protected_headers(key, uri=uri)
83+
if kid:
84+
protected['kid'] = kid
85+
protected.pop("jwk")
86+
data = kwargs.get("data")
87+
if data:
88+
kwargs['data'] = sign_request_v2(key, protected, data)
7289
if self.peasant.verify:
7390
kwargs['verify'] = self.peasant.verify
7491
return kwargs
7592

93+
def get_protected_headers(self, key, uri=None):
94+
"""
95+
Builds a new pair of headers for signed requests.
96+
"""
97+
header = generate_protected_header(key)
98+
protected_header = copy.deepcopy(header)
99+
protected_header['nonce'] = self.new_nonce()
100+
if uri is not None:
101+
protected_header['url'] = uri
102+
return protected_header
103+
104+
def post_as_get(self, path, **kwargs):
105+
"""Send a POST request.
106+
107+
:param path: absolute or relative URL for the new
108+
:class:`requests.Request` object.
109+
:param **kwargs: Optional arguments that ``request`` takes.
110+
:return: :class:`requests.Response <Response>` object
111+
:rtype: requests.Response
112+
"""
113+
url = self.get_url(path, **kwargs)
114+
headers = self.get_headers(**kwargs)
115+
kwargs['headers'] = headers
116+
kwargs = self.update_kwargs(METHOD_POST, **kwargs)
117+
with requests.post(url, **kwargs) as result:
118+
result.raise_for_status()
119+
return result
120+
76121
def set_directory(self):
77122
response = self.get("/%s" % self.peasant.directory_path)
78123
if response.status_code == 200:

0 commit comments

Comments
 (0)