Skip to content

Commit d58dcc8

Browse files
authored
Drop dependency on Flask (#240)
This commit rewrites credentials endpoint using http.server Python module Resolves #233
1 parent 6db04e5 commit d58dcc8

File tree

2 files changed

+38
-26
lines changed

2 files changed

+38
-26
lines changed

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
"colorama",
4242
"container-utils",
4343
"docker>=3.0.0",
44-
"flask",
4544
"humanfriendly",
4645
"Jinja2>=2.11.3",
4746
"packaging>=19.1",
Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
1-
import logging, multiprocessing, os, platform, secrets, time, urllib.parse
1+
import multiprocessing, secrets, time, urllib.parse
22
from .NetworkUtils import NetworkUtils
3-
from flask import Flask, request
3+
from http.server import BaseHTTPRequestHandler, HTTPServer
4+
from urllib.parse import urlparse, parse_qs
5+
from functools import partial
6+
7+
8+
class CredentialRequestHandler(BaseHTTPRequestHandler):
9+
def __init__(self, username: str, password: str, token: str, *args, **kwargs):
10+
self.username = username
11+
self.password = password
12+
self.token = token
13+
super().__init__(*args, **kwargs)
14+
15+
def log_request(self, code: str = "-", size: str = "-") -> None:
16+
# We do not want to log each and every incoming request
17+
pass
18+
19+
def do_POST(self):
20+
query_components = parse_qs(urlparse(self.path).query)
21+
22+
self.send_response(200)
23+
self.end_headers()
24+
25+
if "token" in query_components and query_components["token"][0] == self.token:
26+
content_length = int(self.headers["Content-Length"])
27+
prompt = self.rfile.read(content_length).decode("utf-8")
28+
29+
response = self.password if "Password for" in prompt else self.username
30+
self.wfile.write(response.encode("utf-8"))
431

532

633
class CredentialEndpoint(object):
7-
def __init__(self, username, password):
34+
def __init__(self, username: str, password: str):
835
"""
936
Creates an endpoint manager for the supplied credentials
1037
"""
@@ -17,7 +44,7 @@ def __init__(self, username, password):
1744
# Generate a security token to require when requesting credentials
1845
self.token = secrets.token_hex(16)
1946

20-
def args(self):
47+
def args(self) -> [str]:
2148
"""
2249
Returns the Docker build arguments for creating containers that require Git credentials
2350
"""
@@ -33,7 +60,7 @@ def args(self):
3360
"HOST_TOKEN_ARG=" + urllib.parse.quote_plus(self.token),
3461
]
3562

36-
def start(self):
63+
def start(self) -> None:
3764
"""
3865
Starts the HTTP endpoint as a child process
3966
"""
@@ -49,36 +76,22 @@ def start(self):
4976
time.sleep(2)
5077

5178
# Verify that the endpoint started correctly
52-
if self.endpoint.is_alive() == False:
79+
if not self.endpoint.is_alive():
5380
raise RuntimeError("failed to start the credential endpoint")
5481

55-
def stop(self):
82+
def stop(self) -> None:
5683
"""
5784
Stops the HTTP endpoint child process
5885
"""
5986
self.endpoint.terminate()
6087
self.endpoint.join()
6188

6289
@staticmethod
63-
def _endpoint(username, password, token):
90+
def _endpoint(username: str, password: str, token: str) -> None:
6491
"""
6592
Implements a HTTP endpoint to provide Git credentials to Docker containers
6693
"""
67-
server = Flask(__name__)
68-
69-
# Disable the first-run banner message
70-
os.environ["WERKZEUG_RUN_MAIN"] = "true"
71-
72-
# Disable Flask log output (from <https://stackoverflow.com/a/18379764>)
73-
log = logging.getLogger("werkzeug")
74-
log.setLevel(logging.ERROR)
75-
76-
@server.route("/", methods=["POST"])
77-
def credentials():
78-
if "token" in request.args and request.args["token"] == token:
79-
prompt = request.data.decode("utf-8")
80-
return password if "Password for" in prompt else username
81-
else:
82-
return "Invalid security token"
94+
handler = partial(CredentialRequestHandler, username, password, token)
8395

84-
server.run(host="0.0.0.0", port=9876)
96+
server = HTTPServer(("0.0.0.0", 9876), RequestHandlerClass=handler)
97+
server.serve_forever()

0 commit comments

Comments
 (0)