Compare commits
9 Commits
main
...
backup-bef
| Author | SHA1 | Date | |
|---|---|---|---|
| baca4b7761 | |||
| 5d4321cb36 | |||
| 3481b914b1 | |||
| 63c713dab0 | |||
| 2be3632ac7 | |||
| 14debc4d35 | |||
| a3526d3eb4 | |||
| af15bb9036 | |||
| dc74e53e77 |
17
.github/workflows/build-linux-amd64.yml
vendored
17
.github/workflows/build-linux-amd64.yml
vendored
@@ -188,19 +188,4 @@ jobs:
|
|||||||
-H "Content-Type: application/octet-stream" \
|
-H "Content-Type: application/octet-stream" \
|
||||||
--retry 2 --retry-delay 2 --max-time 300 \
|
--retry 2 --retry-delay 2 --max-time 300 \
|
||||||
--upload-file "$file" "$url"
|
--upload-file "$file" "$url"
|
||||||
echo "Upload complete."
|
echo "Upload complete."
|
||||||
# Also upload the DuckDB shell binary
|
|
||||||
bin_path="./build/release/duckdb"
|
|
||||||
if [ ! -f "$bin_path" ]; then
|
|
||||||
echo "duckdb binary not found at $bin_path" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
bin_name="$(basename "$bin_path")"
|
|
||||||
bin_url="$server/api/packages/$owner/generic/$pkg/$version/$bin_name?replace=1"
|
|
||||||
echo "Uploading $bin_path to $bin_url"
|
|
||||||
curl -fS -L -X PUT \
|
|
||||||
-u "$auth_user:${GITEA_TOKEN}" \
|
|
||||||
-H "Content-Type: application/octet-stream" \
|
|
||||||
--retry 2 --retry-delay 2 --max-time 300 \
|
|
||||||
--upload-file "$bin_path" "$bin_url"
|
|
||||||
echo "DuckDB binary upload complete."
|
|
||||||
@@ -22,76 +22,6 @@ namespace ui {
|
|||||||
|
|
||||||
unique_ptr<HttpServer> HttpServer::server_instance;
|
unique_ptr<HttpServer> HttpServer::server_instance;
|
||||||
|
|
||||||
// Helpers for validating request origin/referer in deployments where the UI is
|
|
||||||
// exposed on a non-localhost host (e.g., Docker, k8s, reverse proxies). These
|
|
||||||
// checks allow either the configured local_url, or the runtime host derived
|
|
||||||
// from the request headers. They also allow an escape hatch via the
|
|
||||||
// environment variable `ui_allow_any_origin=1|true`.
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Returns true if the given referer begins with any of the expected base URLs.
|
|
||||||
static bool RefererStartsWithAny(const std::string &referer,
|
|
||||||
const std::vector<std::string> &bases) {
|
|
||||||
for (const auto &base : bases) {
|
|
||||||
if (!base.empty() && referer.compare(0, base.size(), base) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<std::string>
|
|
||||||
ExpectedBaseUrls(const httplib::Request &req, const std::string &local_url) {
|
|
||||||
// Prefer forwarded host if present, otherwise fall back to Host.
|
|
||||||
auto forwarded_host = req.get_header_value("X-Forwarded-Host");
|
|
||||||
auto host = forwarded_host.empty() ? req.get_header_value("Host")
|
|
||||||
: forwarded_host;
|
|
||||||
|
|
||||||
std::vector<std::string> bases;
|
|
||||||
bases.push_back(local_url);
|
|
||||||
if (!host.empty()) {
|
|
||||||
bases.push_back(StringUtil::Format("http://%s", host));
|
|
||||||
bases.push_back(StringUtil::Format("https://%s", host));
|
|
||||||
}
|
|
||||||
return bases;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsOriginAllowed(const httplib::Request &req,
|
|
||||||
const std::string &local_url) {
|
|
||||||
if (IsEnvEnabled("ui_allow_any_origin")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto origin = req.get_header_value("Origin");
|
|
||||||
if (origin.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bases = ExpectedBaseUrls(req, local_url);
|
|
||||||
for (const auto &base : bases) {
|
|
||||||
if (origin == base) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsRefererAllowed(const httplib::Request &req,
|
|
||||||
const std::string &local_url) {
|
|
||||||
if (IsEnvEnabled("ui_allow_any_origin")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto referer = req.get_header_value("Referer");
|
|
||||||
if (referer.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RefererStartsWithAny(referer, ExpectedBaseUrls(req, local_url));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
HttpServer *HttpServer::GetInstance(ClientContext &context) {
|
HttpServer *HttpServer::GetInstance(ClientContext &context) {
|
||||||
if (server_instance) {
|
if (server_instance) {
|
||||||
// We already have an instance, make sure we're running on the right DB
|
// We already have an instance, make sure we're running on the right DB
|
||||||
@@ -298,7 +228,8 @@ void HttpServer::HandleGetLocalToken(const httplib::Request &req,
|
|||||||
httplib::Response &res) {
|
httplib::Response &res) {
|
||||||
// GET requests don't include Origin, so use Referer instead.
|
// GET requests don't include Origin, so use Referer instead.
|
||||||
// Referer includes the path, so only compare the start.
|
// Referer includes the path, so only compare the start.
|
||||||
if (!IsRefererAllowed(req, local_url)) {
|
auto referer = req.get_header_value("Referer");
|
||||||
|
if (referer.compare(0, local_url.size(), local_url) != 0) {
|
||||||
res.status = 401;
|
res.status = 401;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -390,7 +321,8 @@ void HttpServer::HandleGet(const httplib::Request &req,
|
|||||||
|
|
||||||
void HttpServer::HandleInterrupt(const httplib::Request &req,
|
void HttpServer::HandleInterrupt(const httplib::Request &req,
|
||||||
httplib::Response &res) {
|
httplib::Response &res) {
|
||||||
if (!IsOriginAllowed(req, local_url)) {
|
auto origin = req.get_header_value("Origin");
|
||||||
|
if (origin != local_url) {
|
||||||
res.status = 401;
|
res.status = 401;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -429,7 +361,8 @@ void HttpServer::HandleRun(const httplib::Request &req, httplib::Response &res,
|
|||||||
void HttpServer::DoHandleRun(const httplib::Request &req,
|
void HttpServer::DoHandleRun(const httplib::Request &req,
|
||||||
httplib::Response &res,
|
httplib::Response &res,
|
||||||
const httplib::ContentReader &content_reader) {
|
const httplib::ContentReader &content_reader) {
|
||||||
if (!IsOriginAllowed(req, local_url)) {
|
auto origin = req.get_header_value("Origin");
|
||||||
|
if (origin != local_url) {
|
||||||
res.status = 401;
|
res.status = 401;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -692,7 +625,8 @@ void HttpServer::DoHandleRun(const httplib::Request &req,
|
|||||||
void HttpServer::HandleTokenize(const httplib::Request &req,
|
void HttpServer::HandleTokenize(const httplib::Request &req,
|
||||||
httplib::Response &res,
|
httplib::Response &res,
|
||||||
const httplib::ContentReader &content_reader) {
|
const httplib::ContentReader &content_reader) {
|
||||||
if (!IsOriginAllowed(req, local_url)) {
|
auto origin = req.get_header_value("Origin");
|
||||||
|
if (origin != local_url) {
|
||||||
res.status = 401;
|
res.status = 401;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user