Skip to content

Commit

Permalink
fix: add ip whitelist to tunnels
Browse files Browse the repository at this point in the history
  • Loading branch information
MasterPtato committed Jun 19, 2024
1 parent dfe5f8b commit 359b4f3
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 18 deletions.
10 changes: 10 additions & 0 deletions infra/tf/k8s_infra/traefik_tunnel.tf
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ resource "helm_release" "traefik_tunnel" {
enabled = true
options = "ingress-tunnel"
}

# Created in svc/api/traefik-provider/src/route/tunnel.rs
middlewares = [
"tunnel-ip-allowlist@http"
]
}
}

Expand Down Expand Up @@ -138,6 +143,11 @@ resource "helm_release" "traefik_tunnel" {
}
} : null

additionalArguments = [
"--providers.http.endpoint=http://rivet-api-internal-monolith.rivet-service.svc.cluster.local/traefik-provider/config/tunnel?token=${module.traefik_secrets.values["rivet/api_traefik_provider/token"]}",
"--providers.http.pollInterval=2.5s",
]

logs = {
# general = {
# level = "DEBUG"
Expand Down
2 changes: 1 addition & 1 deletion infra/tf/tls/tunnel_server.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ resource "tls_locally_signed_cert" "locally_signed_tunnel_server" {
ca_key_algorithm = "RSA"
ca_private_key_pem = tls_private_key.root_ca.private_key_pem
ca_cert_pem = tls_self_signed_cert.root_ca.cert_pem

validity_period_hours = 8760 # 1 year

allowed_uses = [
Expand Down
1 change: 1 addition & 0 deletions svc/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions svc/api/traefik-provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,20 @@ util-cdn = { package = "rivet-util-cdn", path = "../../pkg/cdn/util" }
util-job = { package = "rivet-util-job", path = "../../pkg/job/util" }
uuid = { version = "1", features = ["v4"] }

cluster-server-list = { path = "../../pkg/cluster/ops/server-list" }

[dev-dependencies]
rivet-connection = { path = "../../../lib/connection" }
rivet-route = { path = "../../../lib/smithy-output/api-traefik-provider/rust" }
base64 = "0.13"
reqwest = "0.11"

cdn-namespace-domain-create = { path = "../../pkg/cdn/ops/namespace-domain-create" }
cdn-namespace-auth-user-update = { path = "../../pkg/cdn/ops/namespace-auth-user-update" }
faker-game = { path = "../../pkg/faker/ops/game" }
cdn-namespace-domain-create = { path = "../../pkg/cdn/ops/namespace-domain-create" }
faker-cdn-site = { path = "../../pkg/faker/ops/cdn-site" }
faker-game = { path = "../../pkg/faker/ops/game" }
faker-game-namespace = { path = "../../pkg/faker/ops/game-namespace" }
faker-job-run = { path = "../../pkg/faker/ops/job-run" }
faker-game-version = { path = "../../pkg/faker/ops/game-version" }
faker-job-run = { path = "../../pkg/faker/ops/job-run" }
faker-region = { path = "../../pkg/faker/ops/region" }
game-get = { path = "../../pkg/game/ops/get" }
28 changes: 16 additions & 12 deletions svc/api/traefik-provider/src/route/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ pub async fn config(
) -> GlobalResult<types::TraefikConfigResponseNullified> {
ctx.auth().token(&token).await?;

let mut config = types::TraefikConfigResponse::default();

// Fetch configs and catch any errors
let config = build_cdn(&ctx).await?;
build_cdn(&ctx, &mut config).await?;

// tracing::info!(
// http_services = ?config.http.services.len(),
Expand All @@ -47,6 +49,13 @@ pub async fn config(
// "traefik config"
// );

tracing::info!(
services = ?config.http.services.len(),
routers = config.http.routers.len(),
middlewares = ?config.http.middlewares.len(),
"cdn traefik config"
);

Ok(types::TraefikConfigResponseNullified {
http: config.http.nullified(),
tcp: config.tcp.nullified(),
Expand All @@ -56,16 +65,18 @@ pub async fn config(

/// Builds configuration for CDN routes.
#[tracing::instrument(skip(ctx))]
pub async fn build_cdn(ctx: &Ctx<Auth>) -> GlobalResult<types::TraefikConfigResponse> {
let mut config = types::TraefikConfigResponse::default();
pub async fn build_cdn(
ctx: &Ctx<Auth>,
config: &mut types::TraefikConfigResponse,
) -> GlobalResult<()> {
let s3_client = s3_util::Client::from_env("bucket-cdn").await?;

let redis_cdn = ctx.op_ctx().redis_cdn().await?;
let cdn_fetch = fetch_cdn(redis_cdn).await?;

// Process namespaces
for ns in &cdn_fetch {
let register_res = register_namespace(ns, &mut config, &s3_client);
let register_res = register_namespace(ns, config, &s3_client);
match register_res {
Ok(_) => {}
Err(err) => tracing::error!(?err, ?ns, "failed to register namespace route"),
Expand Down Expand Up @@ -149,14 +160,7 @@ pub async fn build_cdn(ctx: &Ctx<Auth>) -> GlobalResult<types::TraefikConfigResp
},
);

tracing::info!(
services = ?config.http.services.len(),
routers = config.http.routers.len(),
middlewares = ?config.http.middlewares.len(),
"cdn traefik config"
);

Ok(config)
Ok(())
}

#[tracing::instrument(skip(redis_cdn))]
Expand Down
8 changes: 8 additions & 0 deletions svc/api/traefik-provider/src/route/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use hyper::{Body, Request, Response};

pub mod core;
pub mod game_guard;
pub mod tunnel;

pub async fn handle(
shared_client: chirp_client::SharedClientHandle,
Expand All @@ -26,6 +27,13 @@ define_router! {
opt_auth: true,
),
},
"config" / "tunnel": {
GET: tunnel::config(
query: tunnel::ConfigQuery,
internal_endpoint: true,
opt_auth: true,
),
},
"config" / "game-guard": {
GET: game_guard::config(
query: game_guard::ConfigQuery,
Expand Down
70 changes: 70 additions & 0 deletions svc/api/traefik-provider/src/route/tunnel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use api_helper::{anchor::WatchIndexQuery, ctx::Ctx};
use proto::backend;
use rivet_operation::prelude::*;
use serde::{Deserialize, Serialize};

use crate::{auth::Auth, types};

#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigQuery {
token: String,
}

#[tracing::instrument(skip(ctx))]
pub async fn config(
ctx: Ctx<Auth>,
_watch_index: WatchIndexQuery,
ConfigQuery { token }: ConfigQuery,
) -> GlobalResult<types::TraefikConfigResponseNullified> {
ctx.auth().token(&token).await?;

let mut config = types::TraefikConfigResponse::default();

build_ip_allowlist(&ctx, &mut config).await?;

tracing::info!(
services = ?config.tcp.services.len(),
routers = config.tcp.routers.len(),
middlewares = ?config.tcp.middlewares.len(),
"tunnel traefik config"
);

Ok(types::TraefikConfigResponseNullified {
http: config.http.nullified(),
tcp: config.tcp.nullified(),
udp: config.udp.nullified(),
})
}

/// Builds configuration for GG edge node routes.
#[tracing::instrument(skip(ctx))]
pub async fn build_ip_allowlist(
ctx: &Ctx<Auth>,
config: &mut types::TraefikConfigResponse,
) -> GlobalResult<()> {
let servers_res = op!([ctx] cluster_server_list {
filter: Some(backend::cluster::ServerFilter {
pool_types: vec![backend::cluster::PoolType::Gg as i32],
..Default::default()
}),
include_destroyed: false,
})
.await?;

let public_ips = servers_res
.servers
.iter()
.filter_map(|server| server.public_ip.clone())
.collect::<Vec<_>>();

config.tcp.middlewares.insert(
"tunnel-ip-allowlist".to_owned(),
types::TraefikMiddlewareHttp::IpAllowList {
source_range: public_ips,
ip_strategy: None,
},
);

Ok(())
}
4 changes: 2 additions & 2 deletions svc/api/traefik-provider/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ pub struct TraefikTlsDomain {
pub enum TraefikMiddlewareHttp {
#[serde(rename = "chain", rename_all = "camelCase")]
Chain { middlewares: Vec<String> },
#[serde(rename = "ipWhiteList", rename_all = "camelCase")]
IpWhiteList {
#[serde(rename = "ipAllowList", rename_all = "camelCase")]
IpAllowList {
source_range: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
ip_strategy: Option<IpStrategy>,
Expand Down

0 comments on commit 359b4f3

Please sign in to comment.