Browse Source

First deployed version

main
Victor Roest 7 months ago
parent
commit
2611be562f
Signed by: 0x76 GPG Key ID: A3923C699D1A3BDA
  1. 21
      .drone.yml
  2. 89
      Cargo.lock
  3. 2
      Cargo.toml
  4. 22
      Dockerfile
  5. 5
      README.md
  6. 57
      k8s/deployment.yml
  7. 121
      src/main.rs

21
.drone.yml

@ -0,0 +1,21 @@
---
kind: pipeline
type: kubernetes
name: default
steps:
- name: website
depends_on: [ clone ]
image: harbor.xirion.net/finitum/drone-kaniko:0.8.2
when:
branch: [main]
settings:
cache: true
username:
from_secret: registry_username
password:
from_secret: registry_password
registry: harbor.xirion.net
repo: library/cors-no-more
tags: latest
build_args:
- SOURCE_COMMIT=${DRONE_COMMIT}

89
Cargo.lock

@ -1,5 +1,25 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -72,6 +92,8 @@ name = "cors-no-more"
version = "0.1.0"
dependencies = [
"http",
"log",
"pretty_env_logger",
"reqwest",
"tokio",
"warp",
@ -101,6 +123,19 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -319,6 +354,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "hyper"
version = "0.14.7"
@ -573,6 +617,16 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
dependencies = [
"env_logger",
"log",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
@ -699,6 +753,23 @@ dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
@ -888,6 +959,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "time"
version = "0.1.43"
@ -1283,6 +1363,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

2
Cargo.toml

@ -9,6 +9,8 @@ tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
warp = "0.3"
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] }
http = "0.2"
log = "0.4"
pretty_env_logger = "0.4"
[profile.release]
lto = true

22
Dockerfile

@ -0,0 +1,22 @@
ARG BASE_IMAGE=harbor.xirion.net/hub/library/rust
FROM ${BASE_IMAGE} AS builder
# Cache our dependencies
WORKDIR /home/rust/
RUN USER=rust cargo new app --bin
WORKDIR /home/rust/app
COPY Cargo.* ./
RUN cargo build --release && rm ./target/release/deps/cors* && rm -rf ./src/
# Add our source code.
COPY . ./
# Build our application.
RUN cargo build --release
# Runner
FROM gcr.io/distroless/cc
EXPOSE 8282
ENV RUST_LOG=info
COPY --from=builder /home/rust/app/target/release/cors-no-more /app
CMD ["/app"]

5
README.md

@ -0,0 +1,5 @@
# CORS no more!
Small rust program to circumvent (the lack of) CORS.
This program will proxy the requests it receives but will have lax CORS headers set.
This program was mainly made to work in conjunction with [fseconomy plot missions](https://github.com/NULLx76/fseconomy-plot-missions) as the fseconomy API doesn't have the correct CORS headers to work in the browser.

57
k8s/deployment.yml

@ -0,0 +1,57 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: no-cors
labels:
app: no-cors
keel.sh/policy: force
spec:
replicas: 1
selector:
matchLabels:
app: no-cors
template:
metadata:
labels:
app: no-cors
spec:
containers:
- name: no-cors
image: harbor.xirion.net/library/cors-no-more
env:
- name: RUST_LOG
value: info
- name: ALLOWED_SITES
value: server.fseconomy.net,wooloofan.club
ports:
- containerPort: 8282
---
apiVersion: v1
kind: Service
metadata:
name: no-cors
spec:
selector:
app: no-cors
ports:
- protocol: TCP
port: 8282
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: no-cors-ingress
annotations:
kubernetes.io/ingress.class: "traefik"
spec:
rules:
- host: "no-cors.xirion.net"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: no-cors
port:
number: 8282

121
src/main.rs

@ -1,33 +1,116 @@
use http::Method;
use warp::{path::FullPath, Filter, Rejection};
use std::collections::HashSet;
use std::env;
use http::{uri::InvalidUri, Method, Uri};
use log::warn;
use warp::{path::FullPath, reject::Reject, Filter, Rejection};
#[tokio::main]
async fn main() {
let cors = warp::cors().allow_any_origin();
pretty_env_logger::init_timed();
let allowed = match env::var("ALLOWED_SITES") {
Ok(s) => {
let a = s.split(",");
let mut hs = HashSet::with_capacity(a.size_hint().0);
for el in a {
let el = el.trim();
if !el.is_empty() {
hs.insert(el.to_owned());
}
}
hs
}
Err(_) => {
warn!("ALLOWED_SITES is empty, allowing everything");
HashSet::new()
}
};
let client = reqwest::Client::new();
let home_page = format!(
"Allowed websites: {:?}\n\nSource code: https://git.xirion.net/0x76/cors-no-more",
&allowed
);
let root = warp::any().map(move || home_page.clone());
let base = warp::any()
.map(move || (client.clone(), allowed.clone()))
.and(warp::path::full().and(warp::method()));
let routes = warp::path::full()
.and(warp::method())
let with_query = base
.clone()
.and(warp::query::raw())
.and_then(proxy)
.with(cors);
warp::serve(routes).run(([0, 0, 0, 0], 8282)).await;
.and_then(move |(c, w), p, m, q| proxy(c, w, p, m, Some(q)));
let without_query = base.and_then(move |(c, w), p, m| proxy(c, w, p, m, None));
let filter = with_query
.or(without_query)
.or(root)
.with(warp::cors().allow_any_origin());
warp::serve(filter).run(([0, 0, 0, 0], 8282)).await
}
async fn proxy(path: FullPath, method: Method, query: String) -> Result<String, Rejection> {
let p: String = format!("{}?{}", path.as_str().strip_prefix("/").unwrap(), query);
#[derive(Debug)]
struct ReqwestError(reqwest::Error);
impl Reject for ReqwestError {}
dbg!(&p);
impl From<reqwest::Error> for ReqwestError {
fn from(e: reqwest::Error) -> Self {
ReqwestError(e)
}
}
let client = reqwest::Client::new();
let response = client
.request(method, p)
#[derive(Debug)]
struct NotAllowed;
impl Reject for NotAllowed {}
#[derive(Debug)]
struct InvalidRequest(String);
impl Reject for InvalidRequest {}
impl From<InvalidUri> for InvalidRequest {
fn from(e: InvalidUri) -> Self {
InvalidRequest(format!("InvalidUri: {:?}", e))
}
}
async fn proxy(
client: reqwest::Client,
allowlist: HashSet<String>,
path: FullPath,
method: Method,
query: Option<String>,
) -> Result<String, Rejection> {
let path = path
.as_str()
.strip_prefix("/")
.ok_or(warp::reject::custom(InvalidRequest("Invalid Path".into())))?;
let uri: Uri = path.parse().map_err(InvalidRequest::from)?;
let host = uri
.host()
.ok_or(warp::reject::custom(InvalidRequest("Invalid URL".into())))?;
// Check uri against allowlist
if allowlist.len() > 0 && !allowlist.contains(host) {
return Err(warp::reject::custom(NotAllowed));
}
let url = query
.map(|q| format!("{}?{}", path, q))
.unwrap_or(path.into());
Ok(client
.request(method, url)
.send()
.await
.unwrap()
.map_err(ReqwestError::from)?
.text()
.await
.unwrap();
Ok(response)
.map_err(ReqwestError::from)?)
}

Loading…
Cancel
Save