Support TLS. (#49)
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 4ddd2a3..bf88d86 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -30,7 +30,7 @@
RUSTFLAGS: "-D warnings"
LLVM_CONFIG_PATH: llvm-config-10
RUST_STABLE_TOOLCHAIN: "1.65"
- RUST_NIGHTLY_TOOLCHAIN: "nightly-2023-01-11"
+ RUST_NIGHTLY_TOOLCHAIN: "nightly-2023-01-28"
jobs:
required:
diff --git a/.rustfmt.toml b/.rustfmt.toml
index 40ab383..7a6424a 100644
--- a/.rustfmt.toml
+++ b/.rustfmt.toml
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-fn_args_layout = "Compressed"
+fn_params_layout = "Compressed"
format_code_in_doc_comments = true
format_macro_bodies = true
format_macro_matchers = true
diff --git a/Cargo.lock b/Cargo.lock
index b5345e2..266bf66 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -154,6 +154,12 @@
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
+[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1711,7 +1717,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
dependencies = [
- "base64",
+ "base64 0.13.1",
"bytes",
"encoding_rs",
"futures-core",
@@ -1755,6 +1761,21 @@
]
[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1790,6 +1811,27 @@
]
[[package]]
+name = "rustls"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+dependencies = [
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+dependencies = [
+ "base64 0.21.0",
+]
+
+[[package]]
name = "rustversion"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1845,6 +1887,16 @@
]
[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
name = "security-framework"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1974,7 +2026,7 @@
checksum = "3af4420143e6b6baef0efad28e7997ea956d25e65e198ac118b18b976ca2cd12"
dependencies = [
"async-stream",
- "base64",
+ "base64 0.13.1",
"bytes",
"cfg-if",
"futures-core",
@@ -2059,6 +2111,12 @@
]
[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2274,6 +2332,17 @@
]
[[package]]
+name = "tokio-rustls"
+version = "0.23.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
name = "tokio-stream"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2307,7 +2376,7 @@
"async-stream",
"async-trait",
"axum",
- "base64",
+ "base64 0.13.1",
"bytes",
"futures-core",
"futures-util",
@@ -2320,7 +2389,9 @@
"pin-project",
"prost",
"prost-derive",
+ "rustls-pemfile",
"tokio",
+ "tokio-rustls",
"tokio-stream",
"tokio-util",
"tower",
@@ -2624,6 +2695,12 @@
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2772,6 +2849,16 @@
]
[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
name = "which"
version = "4.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 36d9a18..f614978 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -52,7 +52,7 @@
thiserror = "1.0.38"
tokio = { version = "1.24.1", features = ["full"] }
tokio-stream = "0.1.11"
-tonic = "0.8.3"
+tonic = { version = "0.8.3", features = ["tls"] }
tracing = { version = "0.1.37", features = ["attributes"] }
tracing-appender = "0.2.2"
tracing-subscriber = "0.3.16"
diff --git a/docs/en/setup/service-agent/php-agent/README.md b/docs/en/setup/service-agent/php-agent/README.md
index 9393239..896d4c1 100644
--- a/docs/en/setup/service-agent/php-agent/README.md
+++ b/docs/en/setup/service-agent/php-agent/README.md
@@ -68,7 +68,7 @@
skywalking_agent.log_level = INFO
; Address of skywalking oap server.
-skywalking_agent.server_addr = http://0.0.0.0:11800
+skywalking_agent.server_addr = 127.0.0.1:11800
; Application service name.
skywalking_agent.service_name = hello-skywalking
@@ -84,4 +84,16 @@
; Skywalking agent runtime directory, default is /tmp/skywalking-agent.
; skywalking_agent.runtime_dir = /tmp/skywalking-agent
+
+; Wether to enable tls for gPRC, default is false.
+; skywalking_agent.enable_tls = Off
+
+; The gRPC SSL trusted ca file.
+; skywalking_agent.ssl_trusted_ca_path =
+
+; The private key file. Enable mTLS when ssl_key_path and ssl_cert_chain_path exist.
+; skywalking_agent.ssl_key_path =
+
+; The certificate file. Enable mTLS when ssl_key_path and ssl_cert_chain_path exist.
+; skywalking_agent.ssl_cert_chain_path =
```
diff --git a/src/lib.rs b/src/lib.rs
index 0b6cf29..5237d62 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -60,6 +60,20 @@
/// Skywalking agent authentication token.
const SKYWALKING_AGENT_AUTHENTICATION: &str = "skywalking_agent.authentication";
+/// Wether to enable tls for gPRC.
+const SKYWALKING_AGENT_ENABLE_TLS: &str = "skywalking_agent.enable_tls";
+
+/// The gRPC SSL trusted ca file.
+const SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH: &str = "skywalking_agent.ssl_trusted_ca_path";
+
+/// The private key file. Enable mTLS when ssl_key_path and ssl_cert_chain_path
+/// exist.
+const SKYWALKING_AGENT_SSL_KEY_PATH: &str = "skywalking_agent.ssl_key_path";
+
+/// The certificate file. Enable mTLS when ssl_key_path and ssl_cert_chain_path
+/// exist.
+const SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH: &str = "skywalking_agent.ssl_cert_chain_path";
+
#[php_get_module]
pub fn get_module() -> Module {
let mut module = Module::new(
@@ -73,7 +87,7 @@
module.add_ini(SKYWALKING_AGENT_SKYWALKING_VERSION, 8i64, Policy::System);
module.add_ini(
SKYWALKING_AGENT_SERVER_ADDR,
- "http://127.0.0.1:11800".to_string(),
+ "127.0.0.1:11800".to_string(),
Policy::System,
);
module.add_ini(
@@ -102,6 +116,22 @@
"".to_string(),
Policy::System,
);
+ module.add_ini(SKYWALKING_AGENT_ENABLE_TLS, false, Policy::System);
+ module.add_ini(
+ SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH,
+ "".to_string(),
+ Policy::System,
+ );
+ module.add_ini(
+ SKYWALKING_AGENT_SSL_KEY_PATH,
+ "".to_string(),
+ Policy::System,
+ );
+ module.add_ini(
+ SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH,
+ "".to_string(),
+ Policy::System,
+ );
// Hooks.
module.on_module_init(module::init);
diff --git a/src/module.rs b/src/module.rs
index 6af3fe5..9cbb52c 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -18,9 +18,11 @@
execute::register_execute_functions,
util::{get_sapi_module_name, IPS},
worker::init_worker,
- SKYWALKING_AGENT_AUTHENTICATION, SKYWALKING_AGENT_ENABLE, SKYWALKING_AGENT_LOG_FILE,
- SKYWALKING_AGENT_LOG_LEVEL, SKYWALKING_AGENT_RUNTIME_DIR, SKYWALKING_AGENT_SERVICE_NAME,
- SKYWALKING_AGENT_SKYWALKING_VERSION,
+ SKYWALKING_AGENT_AUTHENTICATION, SKYWALKING_AGENT_ENABLE, SKYWALKING_AGENT_ENABLE_TLS,
+ SKYWALKING_AGENT_LOG_FILE, SKYWALKING_AGENT_LOG_LEVEL, SKYWALKING_AGENT_RUNTIME_DIR,
+ SKYWALKING_AGENT_SERVICE_NAME, SKYWALKING_AGENT_SKYWALKING_VERSION,
+ SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH, SKYWALKING_AGENT_SSL_KEY_PATH,
+ SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH,
};
use once_cell::sync::Lazy;
use phper::{arrays::ZArr, ini::ini_get, sys};
@@ -37,7 +39,7 @@
str::FromStr,
time::SystemTime,
};
-use tracing::{error, info, metadata::LevelFilter};
+use tracing::{debug, error, info, metadata::LevelFilter};
use tracing_subscriber::FmtSubscriber;
pub static SERVICE_NAME: Lazy<String> = Lazy::new(|| {
@@ -84,6 +86,29 @@
.unwrap_or_default()
});
+pub static ENABLE_TLS: Lazy<bool> = Lazy::new(|| ini_get::<bool>(SKYWALKING_AGENT_ENABLE_TLS));
+
+pub static SSL_TRUSTED_CA_PATH: Lazy<String> = Lazy::new(|| {
+ ini_get::<Option<&CStr>>(SKYWALKING_AGENT_SSL_TRUSTED_CA_PATH)
+ .and_then(|s| s.to_str().ok())
+ .map(ToOwned::to_owned)
+ .unwrap_or_default()
+});
+
+pub static SSL_KEY_PATH: Lazy<String> = Lazy::new(|| {
+ ini_get::<Option<&CStr>>(SKYWALKING_AGENT_SSL_KEY_PATH)
+ .and_then(|s| s.to_str().ok())
+ .map(ToOwned::to_owned)
+ .unwrap_or_default()
+});
+
+pub static SSL_CERT_CHAIN_PATH: Lazy<String> = Lazy::new(|| {
+ ini_get::<Option<&CStr>>(SKYWALKING_AGENT_SSL_CERT_CHAIN_PATH)
+ .and_then(|s| s.to_str().ok())
+ .map(ToOwned::to_owned)
+ .unwrap_or_default()
+});
+
pub fn init() {
if !is_enable() {
return;
@@ -91,6 +116,7 @@
init_logger();
+ // Skywalking agent info.
let service_name = Lazy::force(&SERVICE_NAME);
let service_instance = Lazy::force(&SERVICE_INSTANCE);
let skywalking_version = Lazy::force(&SKYWALKING_VERSION);
@@ -100,7 +126,7 @@
service_instance, skywalking_version, authentication, "Starting skywalking agent"
);
- // Skywalking version check
+ // Skywalking version check.
if *skywalking_version < 8 {
error!(
skywalking_version,
@@ -109,6 +135,17 @@
return;
}
+ // Initialize TLS if enabled.
+ let enable_tls = Lazy::force(&ENABLE_TLS);
+ let ssl_trusted_ca_path = Lazy::force(&SSL_TRUSTED_CA_PATH);
+ let ssl_key_path = Lazy::force(&SSL_KEY_PATH);
+ let ssl_cert_chain_path = Lazy::force(&SSL_CERT_CHAIN_PATH);
+ debug!(
+ enable_tls,
+ ssl_trusted_ca_path, ssl_key_path, ssl_cert_chain_path, "Skywalking TLS info"
+ );
+
+ // Initialize runtime directory.
if RUNTIME_DIR.as_os_str().is_empty() {
error!("The skywalking agent runtime directory must not be empty");
return;
@@ -118,6 +155,7 @@
return;
}
+ // Initialize Agent worker.
Lazy::force(&SOCKET_FILE_PATH);
init_worker();
@@ -127,6 +165,7 @@
Reporter::new(&*SOCKET_FILE_PATH),
));
+ // Hook functions.
register_execute_functions();
}
diff --git a/src/worker.rs b/src/worker.rs
index 1e4fd41..75912af 100644
--- a/src/worker.rs
+++ b/src/worker.rs
@@ -15,7 +15,10 @@
use crate::{
channel::{self, TxReporter},
- module::{AUTHENTICATION, SERVICE_INSTANCE, SERVICE_NAME, SOCKET_FILE_PATH},
+ module::{
+ AUTHENTICATION, ENABLE_TLS, SERVICE_INSTANCE, SERVICE_NAME, SOCKET_FILE_PATH,
+ SSL_CERT_CHAIN_PATH, SSL_KEY_PATH, SSL_TRUSTED_CA_PATH,
+ },
util::change_permission,
SKYWALKING_AGENT_SERVER_ADDR, SKYWALKING_AGENT_WORKER_THREADS,
};
@@ -43,7 +46,7 @@
};
use tonic::{
async_trait,
- transport::{Channel, Endpoint},
+ transport::{Certificate, Channel, ClientTlsConfig, Endpoint, Identity},
};
use tracing::{debug, error, info, warn};
@@ -166,7 +169,7 @@
}
});
- let endpoint = Endpoint::from_shared(server_addr)?;
+ let endpoint = create_endpoint(&server_addr).await?;
let channel = connect(endpoint).await;
report_properties_and_keep_alive(TxReporter(tx_));
@@ -208,6 +211,42 @@
Ok(())
}
+async fn create_endpoint(server_addr: &str) -> anyhow::Result<Endpoint> {
+ let scheme = if *ENABLE_TLS { "https" } else { "http" };
+
+ let url = format!("{}://{}", scheme, server_addr);
+ debug!(url, "Create Endpoint");
+ let mut endpoint = Endpoint::from_shared(url)?;
+
+ if *ENABLE_TLS {
+ let domain_name = server_addr.split(':').next().unwrap_or_default();
+ debug!(domain_name, "Configure TLS domain");
+ let mut tls = ClientTlsConfig::new().domain_name(domain_name);
+
+ let ssl_trusted_ca_path = SSL_TRUSTED_CA_PATH.as_str();
+ if !ssl_trusted_ca_path.is_empty() {
+ debug!(ssl_trusted_ca_path, "Configure TLS CA");
+ let ca_cert = tokio::fs::read(&*SSL_TRUSTED_CA_PATH).await?;
+ let ca_cert = Certificate::from_pem(ca_cert);
+ tls = tls.ca_certificate(ca_cert);
+ }
+
+ let ssl_key_path = SSL_KEY_PATH.as_str();
+ let ssl_cert_chain_path = SSL_CERT_CHAIN_PATH.as_str();
+ if !ssl_key_path.is_empty() && !ssl_cert_chain_path.is_empty() {
+ debug!(ssl_trusted_ca_path, "Configure mTLS");
+ let client_cert = tokio::fs::read(&*SSL_CERT_CHAIN_PATH).await?;
+ let client_key = tokio::fs::read(&*SSL_KEY_PATH).await?;
+ let client_identity = Identity::from_pem(client_cert, client_key);
+ tls = tls.identity(client_identity);
+ }
+
+ endpoint = endpoint.tls_config(tls)?;
+ }
+
+ Ok(endpoint)
+}
+
#[tracing::instrument(skip_all)]
async fn connect(endpoint: Endpoint) -> Channel {
let channel = loop {
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 7e9fe85..4c40fd7 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -271,10 +271,7 @@
index
),
"-d",
- &format!(
- "skywalking_agent.server_addr=http://{}",
- COLLECTOR_GRPC_ADDRESS
- ),
+ &format!("skywalking_agent.server_addr={}", COLLECTOR_GRPC_ADDRESS),
"-d",
&format!("skywalking_agent.log_level={}", PROCESS_LOG_LEVEL),
"-d",
@@ -313,10 +310,7 @@
index
),
"-d",
- &format!(
- "skywalking_agent.server_addr=http://{}",
- COLLECTOR_GRPC_ADDRESS
- ),
+ &format!("skywalking_agent.server_addr={}", COLLECTOR_GRPC_ADDRESS),
"-d",
&format!("skywalking_agent.log_level={}", PROCESS_LOG_LEVEL),
"-d",