Skip to content

Commit

Permalink
g3-tls-ticket: add redis source and config
Browse files Browse the repository at this point in the history
  • Loading branch information
zh-jq-b committed Oct 14, 2024
1 parent ee12a69 commit b2eeeb9
Show file tree
Hide file tree
Showing 22 changed files with 618 additions and 78 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion g3proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ g3-ip-locate.workspace = true
g3-json = { workspace = true, features = ["acl-rule", "resolve", "http", "rustls", "openssl", "histogram"] }
g3-msgpack.workspace = true
g3-openssl.workspace = true
g3-redis-client.workspace = true
g3-redis-client = { workspace = true, features = ["yaml"] }
g3-resolver.workspace = true
g3-slog-types = { workspace = true, features = ["http"] }
g3-smtp-proto.workspace = true
Expand Down
55 changes: 5 additions & 50 deletions g3proxy/src/config/escaper/proxy_float/source/redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,60 +99,15 @@ impl ProxyFloatRedisSource {
fn set(&mut self, k: &str, v: &Yaml, position: Option<&YamlDocPosition>) -> anyhow::Result<()> {
match g3_yaml::key::normalize(k).as_str() {
super::CONFIG_KEY_SOURCE_TYPE => Ok(()),
"addr" | "address" => {
let addr = g3_yaml::value::as_upstream_addr(v, g3_redis_client::REDIS_DEFAULT_PORT)
.context(format!("invalid upstream address value for key {k}"))?;
self.client_builder.set_addr(addr);
Ok(())
}
"tls" | "tls_client" => {
let lookup_dir = g3_daemon::config::get_lookup_dir(position)?;
let tls = g3_yaml::value::as_rustls_client_config_builder(v, Some(lookup_dir))
.context(format!(
"invalid rustls tls client config value for key {k}"
))?;
self.client_builder.set_tls_client(tls);
Ok(())
}
"tls_name" => {
let name = g3_yaml::value::as_rustls_server_name(v)
.context(format!("invalid rustls server name value for key {k}"))?;
self.client_builder.set_tls_name(name);
Ok(())
}
"db" => {
let db =
g3_yaml::value::as_i64(v).context(format!("invalid int value for key {k}"))?;
self.client_builder.set_db(db);
Ok(())
}
"username" => {
let username = g3_yaml::value::as_string(v)?;
self.client_builder.set_username(username);
Ok(())
}
"password" => {
let password = g3_yaml::value::as_string(v)?;
self.client_builder.set_password(password);
Ok(())
}
"connect_timeout" => {
let timeout = g3_yaml::humanize::as_duration(v)
.context(format!("invalid humanize duration value for key {k}"))?;
self.client_builder.set_connect_timeout(timeout);
Ok(())
}
"response_timeout" | "read_timeout" => {
let timeout = g3_yaml::humanize::as_duration(v)
.context(format!("invalid humanize duration value for key {k}"))?;
self.client_builder.set_response_timeout(timeout);
Ok(())
}
"sets_key" => {
self.sets_key = g3_yaml::value::as_string(v)?;
Ok(())
}
_ => Err(anyhow!("invalid key {}", k)),
normalized_key => {
let lookup_dir = g3_daemon::config::get_lookup_dir(position)?;
self.client_builder
.set_yaml_kv(normalized_key, v, Some(lookup_dir))
}
}
}
}
1 change: 1 addition & 0 deletions lib/g3-json/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ humanize-rs.workspace = true
idna.workspace = true
ascii.workspace = true
rand.workspace = true
hex.workspace = true
ip_network = { workspace = true, optional = true }
regex = { workspace = true, optional = true }
rustls-pki-types = { workspace = true, optional = true, features = ["std"] }
Expand Down
4 changes: 2 additions & 2 deletions lib/g3-json/src/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ pub use datetime::as_rfc3339_datetime;
pub use metrics::{as_metrics_name, as_weighted_metrics_name};
pub use net::*;
pub use primary::{
as_ascii, as_bool, as_f64, as_hashmap, as_i32, as_list, as_nonzero_u32, as_string, as_u16,
as_u32, as_u8, as_usize,
as_ascii, as_bool, as_bytes, as_f64, as_hashmap, as_i32, as_list, as_nonzero_u32, as_string,
as_u16, as_u32, as_u8, as_usize,
};
pub use random::as_random_ratio;
pub use rate_limit::as_rate_limit_quota;
Expand Down
8 changes: 8 additions & 0 deletions lib/g3-json/src/value/primary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ pub fn as_bool(v: &Value) -> anyhow::Result<bool> {
}
}

pub fn as_bytes(v: &Value, out: &mut [u8]) -> anyhow::Result<()> {
if let Value::String(s) = v {
hex::decode_to_slice(s, out).map_err(|e| anyhow!("invalid hex string: {e}"))
} else {
Err(anyhow!("json value type for bytes should be 'hex string'"))
}
}

pub fn as_ascii(v: &Value) -> anyhow::Result<AsciiString> {
let s = as_string(v).context("the base type for AsciiString should be String")?;
AsciiString::from_str(&s).map_err(|e| anyhow!("invalid ascii string: {e}"))
Expand Down
6 changes: 6 additions & 0 deletions lib/g3-redis-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ redis = { workspace = true, features = ["aio", "tokio-comp"] }
tokio = { workspace = true, features = ["net"] }
tokio-rustls.workspace = true
rustls-pki-types.workspace = true
yaml-rust = { workspace = true, optional = true }
g3-types = { workspace = true, features = ["rustls"] }
g3-socket.workspace = true
g3-yaml = { workspace = true, optional = true, features = ["rustls"] }

[features]
default = []
yaml = ["dep:g3-yaml", "dep:yaml-rust"]
3 changes: 3 additions & 0 deletions lib/g3-redis-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ use tokio_rustls::TlsConnector;

use g3_types::net::{Host, RustlsClientConfig, RustlsClientConfigBuilder, UpstreamAddr};

#[cfg(feature = "yaml")]
mod yaml;

pub const REDIS_DEFAULT_PORT: u16 = 6379;

#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down
82 changes: 82 additions & 0 deletions lib/g3-redis-client/src/yaml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2024 ByteDance and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use std::path::Path;

use anyhow::{anyhow, Context};
use yaml_rust::Yaml;

use super::RedisClientConfigBuilder;

impl RedisClientConfigBuilder {
pub fn set_yaml_kv(
&mut self,
k: &str,
v: &Yaml,
lookup_dir: Option<&Path>,
) -> anyhow::Result<()> {
match k {
"addr" | "address" => {
let addr = g3_yaml::value::as_upstream_addr(v, crate::REDIS_DEFAULT_PORT)
.context(format!("invalid upstream address value for key {k}"))?;
self.set_addr(addr);
Ok(())
}
"tls" | "tls_client" => {
let tls = g3_yaml::value::as_rustls_client_config_builder(v, lookup_dir).context(
format!("invalid rustls tls client config value for key {k}"),
)?;
self.set_tls_client(tls);
Ok(())
}
"tls_name" => {
let name = g3_yaml::value::as_rustls_server_name(v)
.context(format!("invalid rustls server name value for key {k}"))?;
self.set_tls_name(name);
Ok(())
}
"db" => {
let db =
g3_yaml::value::as_i64(v).context(format!("invalid int value for key {k}"))?;
self.set_db(db);
Ok(())
}
"username" => {
let username = g3_yaml::value::as_string(v)?;
self.set_username(username);
Ok(())
}
"password" => {
let password = g3_yaml::value::as_string(v)?;
self.set_password(password);
Ok(())
}
"connect_timeout" => {
let timeout = g3_yaml::humanize::as_duration(v)
.context(format!("invalid humanize duration value for key {k}"))?;
self.set_connect_timeout(timeout);
Ok(())
}
"response_timeout" | "read_timeout" => {
let timeout = g3_yaml::humanize::as_duration(v)
.context(format!("invalid humanize duration value for key {k}"))?;
self.set_response_timeout(timeout);
Ok(())
}
_ => Err(anyhow!("invalid key {}", k)),
}
}
}
12 changes: 11 additions & 1 deletion lib/g3-tls-ticket/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,17 @@ edition.workspace = true
anyhow.workspace = true
log.workspace = true
rustc-hash.workspace = true
chrono.workspace = true
chrono = { workspace = true, features = ["now"] }
tokio = { workspace = true, features = ["rt", "time", "macros"] }
tokio-util = { workspace = true, features = ["time"] }
serde_json.workspace = true
yaml-rust = { workspace = true, optional = true }
redis = { workspace = true, features = ["aio", "tokio-comp"] }
g3-types = { workspace = true, features = ["openssl"] }
g3-json.workspace = true
g3-redis-client.workspace = true
g3-yaml = { workspace = true, optional = true }

[features]
default = []
yaml = ["g3-redis-client/yaml", "dep:g3-yaml", "dep:yaml-rust"]
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ use g3_types::net::{OpensslTicketKey, RollingTicketKey, RollingTicketer};

use super::{TicketKeyUpdate, TicketSourceConfig};

#[cfg(feature = "yaml")]
mod yaml;

#[derive(Clone)]
pub struct TlsTicketConfig {
pub(crate) check_interval: Duration,
Expand Down
55 changes: 55 additions & 0 deletions lib/g3-tls-ticket/src/config/yaml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2024 ByteDance and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use std::path::Path;

use anyhow::{anyhow, Context};
use yaml_rust::Yaml;

use super::TlsTicketConfig;
use crate::source::TicketSourceConfig;

impl TlsTicketConfig {
pub fn parse_yaml(value: &Yaml, lookup_dir: Option<&Path>) -> anyhow::Result<Self> {
if let Yaml::Hash(map) = value {
let mut config = TlsTicketConfig::default();
g3_yaml::foreach_kv(map, |k, v| match g3_yaml::key::normalize(k).as_str() {
"check_interval" => {
config.check_interval = g3_yaml::humanize::as_duration(v)
.context(format!("invalid humanize duration value for key {k}"))?;
Ok(())
}
"local_lifetime" => {
config.local_lifetime = g3_yaml::value::as_u32(v)?;
Ok(())
}
"source" => {
let source = TicketSourceConfig::parse_yaml(v, lookup_dir).context(format!(
"invalid remote tls ticket source config for key {k}"
))?;
config.remote_source = Some(source);
Ok(())
}
_ => Err(anyhow!("invalid key {k}")),
})?;
Ok(config)
} else {
Err(anyhow!(
"yaml value type for 'tls ticket config' should be 'map'"
))
}
}
}
Loading

0 comments on commit b2eeeb9

Please sign in to comment.