mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2025-12-22 22:20:02 +00:00
feat(metasrv): support tls for etcd client (#6818)
* add TLS support for etcd client connections~ Signed-off-by: codephage2020 <tingwangyan2020@163.com> * locate correct certs Signed-off-by: codephage2020 <tingwangyan2020@163.com> * Updated certs Signed-off-by: codephage2020 <tingwangyan2020@163.com> * Updated CI Signed-off-by: codephage2020 <tingwangyan2020@163.com> * Updated CI Signed-off-by: codephage2020 <tingwangyan2020@163.com> * Update docker-compose.yml * tests for TLS client creation Signed-off-by: codephage2020 <tingwangyan2020@163.com> * modify tests Signed-off-by: codephage2020 <tingwangyan2020@163.com> --------- Signed-off-by: codephage2020 <tingwangyan2020@163.com>
This commit is contained in:
2
.github/workflows/develop.yml
vendored
2
.github/workflows/develop.yml
vendored
@@ -763,6 +763,7 @@ jobs:
|
||||
GT_MINIO_ACCESS_KEY: superpower_password
|
||||
GT_MINIO_REGION: us-west-2
|
||||
GT_MINIO_ENDPOINT_URL: http://127.0.0.1:9000
|
||||
GT_ETCD_TLS_ENDPOINTS: https://127.0.0.1:2378
|
||||
GT_ETCD_ENDPOINTS: http://127.0.0.1:2379
|
||||
GT_POSTGRES_ENDPOINTS: postgres://greptimedb:admin@127.0.0.1:5432/postgres
|
||||
GT_MYSQL_ENDPOINTS: mysql://greptimedb:admin@127.0.0.1:3306/mysql
|
||||
@@ -815,6 +816,7 @@ jobs:
|
||||
GT_MINIO_ACCESS_KEY: superpower_password
|
||||
GT_MINIO_REGION: us-west-2
|
||||
GT_MINIO_ENDPOINT_URL: http://127.0.0.1:9000
|
||||
GT_ETCD_TLS_ENDPOINTS: https://127.0.0.1:2378
|
||||
GT_ETCD_ENDPOINTS: http://127.0.0.1:2379
|
||||
GT_POSTGRES_ENDPOINTS: postgres://greptimedb:admin@127.0.0.1:5432/postgres
|
||||
GT_MYSQL_ENDPOINTS: mysql://greptimedb:admin@127.0.0.1:3306/mysql
|
||||
|
||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -13486,6 +13486,7 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"prost 0.13.5",
|
||||
"rustls-native-certs 0.8.1",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
|
||||
@@ -138,7 +138,10 @@ deadpool-postgres = "0.14"
|
||||
derive_builder = "0.20"
|
||||
dotenv = "0.15"
|
||||
either = "1.15"
|
||||
etcd-client = { git = "https://github.com/GreptimeTeam/etcd-client", rev = "f62df834f0cffda355eba96691fe1a9a332b75a7" }
|
||||
etcd-client = { git = "https://github.com/GreptimeTeam/etcd-client", rev = "f62df834f0cffda355eba96691fe1a9a332b75a7", features = [
|
||||
"tls",
|
||||
"tls-roots",
|
||||
] }
|
||||
fst = "0.4.7"
|
||||
futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
| `runtime` | -- | -- | The runtime options. |
|
||||
| `runtime.global_rt_size` | Integer | `8` | The number of threads to execute the runtime for global read operations. |
|
||||
| `runtime.compact_rt_size` | Integer | `4` | The number of threads to execute the runtime for global write operations. |
|
||||
| `backend_tls` | -- | -- | TLS configuration for kv store backend (only applicable for PostgreSQL/MySQL backends)<br/>When using PostgreSQL or MySQL as metadata store, you can configure TLS here |
|
||||
| `backend_tls` | -- | -- | TLS configuration for kv store backend (applicable for etcd, PostgreSQL, and MySQL backends)<br/>When using etcd, PostgreSQL, or MySQL as metadata store, you can configure TLS here |
|
||||
| `backend_tls.mode` | String | `prefer` | TLS mode, refer to https://www.postgresql.org/docs/current/libpq-ssl.html<br/>- "disable" - No TLS<br/>- "prefer" (default) - Try TLS, fallback to plain<br/>- "require" - Require TLS<br/>- "verify_ca" - Require TLS and verify CA<br/>- "verify_full" - Require TLS and verify hostname |
|
||||
| `backend_tls.cert_path` | String | `""` | Path to client certificate file (for client authentication)<br/>Like "/path/to/client.crt" |
|
||||
| `backend_tls.key_path` | String | `""` | Path to client private key file (for client authentication)<br/>Like "/path/to/client.key" |
|
||||
|
||||
@@ -65,8 +65,8 @@ node_max_idle_time = "24hours"
|
||||
## The number of threads to execute the runtime for global write operations.
|
||||
#+ compact_rt_size = 4
|
||||
|
||||
## TLS configuration for kv store backend (only applicable for PostgreSQL/MySQL backends)
|
||||
## When using PostgreSQL or MySQL as metadata store, you can configure TLS here
|
||||
## TLS configuration for kv store backend (applicable for etcd, PostgreSQL, and MySQL backends)
|
||||
## When using etcd, PostgreSQL, or MySQL as metadata store, you can configure TLS here
|
||||
[backend_tls]
|
||||
## TLS mode, refer to https://www.postgresql.org/docs/current/libpq-ssl.html
|
||||
## - "disable" - No TLS
|
||||
|
||||
@@ -34,6 +34,48 @@ services:
|
||||
networks:
|
||||
- greptimedb
|
||||
|
||||
etcd-tls:
|
||||
<<: *etcd_common_settings
|
||||
container_name: etcd-tls
|
||||
ports:
|
||||
- 2378:2378
|
||||
- 2381:2381
|
||||
command:
|
||||
- --name=etcd-tls
|
||||
- --data-dir=/var/lib/etcd
|
||||
- --initial-advertise-peer-urls=https://etcd-tls:2381
|
||||
- --listen-peer-urls=https://0.0.0.0:2381
|
||||
- --listen-client-urls=https://0.0.0.0:2378
|
||||
- --advertise-client-urls=https://etcd-tls:2378
|
||||
- --heartbeat-interval=250
|
||||
- --election-timeout=1250
|
||||
- --initial-cluster=etcd-tls=https://etcd-tls:2381
|
||||
- --initial-cluster-state=new
|
||||
- --initial-cluster-token=etcd-tls-cluster
|
||||
- --cert-file=/certs/server.crt
|
||||
- --key-file=/certs/server-key.pem
|
||||
- --peer-cert-file=/certs/server.crt
|
||||
- --peer-key-file=/certs/server-key.pem
|
||||
- --trusted-ca-file=/certs/ca.crt
|
||||
- --peer-trusted-ca-file=/certs/ca.crt
|
||||
- --client-cert-auth
|
||||
- --peer-client-cert-auth
|
||||
volumes:
|
||||
- ./greptimedb-cluster-docker-compose/etcd-tls:/var/lib/etcd
|
||||
- ./greptimedb-cluster-docker-compose/certs:/certs:ro
|
||||
environment:
|
||||
- ETCDCTL_API=3
|
||||
- ETCDCTL_CACERT=/certs/ca.crt
|
||||
- ETCDCTL_CERT=/certs/server.crt
|
||||
- ETCDCTL_KEY=/certs/server-key.pem
|
||||
healthcheck:
|
||||
test: [ "CMD", "etcdctl", "--endpoints=https://etcd-tls:2378", "--cacert=/certs/ca.crt", "--cert=/certs/server.crt", "--key=/certs/server-key.pem", "endpoint", "health" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- greptimedb
|
||||
|
||||
metasrv:
|
||||
image: *greptimedb_image
|
||||
container_name: metasrv
|
||||
|
||||
71
scripts/generate-etcd-tls-certs.sh
Executable file
71
scripts/generate-etcd-tls-certs.sh
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Generate TLS certificates for etcd testing
|
||||
# This script creates certificates for TLS-enabled etcd in testing environments
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CERT_DIR="${1:-$(dirname "$0")/../tests-integration/fixtures/etcd-tls-certs}"
|
||||
DAYS="${2:-365}"
|
||||
|
||||
echo "Generating TLS certificates for etcd in ${CERT_DIR}..."
|
||||
|
||||
mkdir -p "${CERT_DIR}"
|
||||
cd "${CERT_DIR}"
|
||||
|
||||
echo "Generating CA private key..."
|
||||
openssl genrsa -out ca-key.pem 2048
|
||||
|
||||
echo "Generating CA certificate..."
|
||||
openssl req -new -x509 -key ca-key.pem -out ca.crt -days "${DAYS}" \
|
||||
-subj "/C=US/ST=CA/L=SF/O=Greptime/CN=etcd-ca"
|
||||
|
||||
# Create server certificate config with Subject Alternative Names
|
||||
echo "Creating server certificate configuration..."
|
||||
cat > server.conf << 'EOF'
|
||||
[req]
|
||||
distinguished_name = req
|
||||
[v3_req]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = etcd-tls
|
||||
DNS.3 = 127.0.0.1
|
||||
IP.1 = 127.0.0.1
|
||||
IP.2 = ::1
|
||||
EOF
|
||||
|
||||
echo "Generating server private key..."
|
||||
openssl genrsa -out server-key.pem 2048
|
||||
|
||||
echo "Generating server certificate signing request..."
|
||||
openssl req -new -key server-key.pem -out server.csr \
|
||||
-subj "/CN=etcd-tls"
|
||||
|
||||
echo "Generating server certificate..."
|
||||
openssl x509 -req -in server.csr -CA ca.crt \
|
||||
-CAkey ca-key.pem -CAcreateserial -out server.crt \
|
||||
-days "${DAYS}" -extensions v3_req -extfile server.conf
|
||||
|
||||
echo "Generating client private key..."
|
||||
openssl genrsa -out client-key.pem 2048
|
||||
|
||||
echo "Generating client certificate signing request..."
|
||||
openssl req -new -key client-key.pem -out client.csr \
|
||||
-subj "/CN=etcd-client"
|
||||
|
||||
echo "Generating client certificate..."
|
||||
openssl x509 -req -in client.csr -CA ca.crt \
|
||||
-CAkey ca-key.pem -CAcreateserial -out client.crt \
|
||||
-days "${DAYS}"
|
||||
|
||||
echo "Setting proper file permissions..."
|
||||
chmod 644 ca.crt server.crt client.crt
|
||||
chmod 600 ca-key.pem server-key.pem client-key.pem
|
||||
|
||||
# Clean up intermediate files
|
||||
rm -f server.csr client.csr server.conf
|
||||
|
||||
echo "TLS certificates generated successfully in ${CERT_DIR}"
|
||||
@@ -19,8 +19,9 @@ use common_error::ext::BoxedError;
|
||||
use common_meta::kv_backend::chroot::ChrootKvBackend;
|
||||
use common_meta::kv_backend::etcd::EtcdStore;
|
||||
use common_meta::kv_backend::KvBackendRef;
|
||||
use meta_srv::bootstrap::create_etcd_client;
|
||||
use meta_srv::bootstrap::create_etcd_client_with_tls;
|
||||
use meta_srv::metasrv::BackendImpl;
|
||||
use servers::tls::{TlsMode, TlsOption};
|
||||
|
||||
use crate::error::{EmptyStoreAddrsSnafu, UnsupportedMemoryBackendSnafu};
|
||||
|
||||
@@ -55,6 +56,26 @@ pub(crate) struct StoreConfig {
|
||||
#[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
|
||||
#[clap(long, default_value = common_meta::kv_backend::DEFAULT_META_TABLE_NAME)]
|
||||
meta_table_name: String,
|
||||
|
||||
/// TLS mode for backend store connections (etcd, PostgreSQL, MySQL)
|
||||
#[clap(long = "backend-tls-mode", value_enum, default_value = "disable")]
|
||||
backend_tls_mode: TlsMode,
|
||||
|
||||
/// Path to TLS certificate file for backend store connections
|
||||
#[clap(long = "backend-tls-cert-path", default_value = "")]
|
||||
backend_tls_cert_path: String,
|
||||
|
||||
/// Path to TLS private key file for backend store connections
|
||||
#[clap(long = "backend-tls-key-path", default_value = "")]
|
||||
backend_tls_key_path: String,
|
||||
|
||||
/// Path to TLS CA certificate file for backend store connections
|
||||
#[clap(long = "backend-tls-ca-cert-path", default_value = "")]
|
||||
backend_tls_ca_cert_path: String,
|
||||
|
||||
/// Enable watching TLS certificate files for changes
|
||||
#[clap(long = "backend-tls-watch")]
|
||||
backend_tls_watch: bool,
|
||||
}
|
||||
|
||||
impl StoreConfig {
|
||||
@@ -67,7 +88,18 @@ impl StoreConfig {
|
||||
} else {
|
||||
let kvbackend = match self.backend {
|
||||
BackendImpl::EtcdStore => {
|
||||
let etcd_client = create_etcd_client(store_addrs)
|
||||
let tls_config = if self.backend_tls_mode != TlsMode::Disable {
|
||||
Some(TlsOption {
|
||||
mode: self.backend_tls_mode.clone(),
|
||||
cert_path: self.backend_tls_cert_path.clone(),
|
||||
key_path: self.backend_tls_key_path.clone(),
|
||||
ca_cert_path: self.backend_tls_ca_cert_path.clone(),
|
||||
watch: self.backend_tls_watch,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let etcd_client = create_etcd_client_with_tls(store_addrs, tls_config.as_ref())
|
||||
.await
|
||||
.map_err(BoxedError::new)?;
|
||||
Ok(EtcdStore::with_etcd_client(etcd_client, max_txn_ops))
|
||||
|
||||
@@ -21,6 +21,7 @@ use api::v1::meta::procedure_service_server::ProcedureServiceServer;
|
||||
use api::v1::meta::store_server::StoreServer;
|
||||
use common_base::Plugins;
|
||||
use common_config::Configurable;
|
||||
#[cfg(feature = "pg_kvbackend")]
|
||||
use common_error::ext::BoxedError;
|
||||
#[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
|
||||
use common_meta::distributed_time_constants::META_LEASE_SECS;
|
||||
@@ -40,7 +41,7 @@ use common_telemetry::info;
|
||||
#[cfg(feature = "pg_kvbackend")]
|
||||
use deadpool_postgres::{Config, Runtime};
|
||||
use either::Either;
|
||||
use etcd_client::Client;
|
||||
use etcd_client::{Client, ConnectOptions};
|
||||
use servers::configurator::ConfiguratorRef;
|
||||
use servers::export_metrics::ExportMetricsTask;
|
||||
use servers::http::{HttpServer, HttpServerBuilder};
|
||||
@@ -286,7 +287,8 @@ pub async fn metasrv_builder(
|
||||
(Some(kv_backend), _) => (kv_backend, None),
|
||||
(None, BackendImpl::MemoryStore) => (Arc::new(MemoryKvBackend::new()) as _, None),
|
||||
(None, BackendImpl::EtcdStore) => {
|
||||
let etcd_client = create_etcd_client(&opts.store_addrs).await?;
|
||||
let etcd_client =
|
||||
create_etcd_client_with_tls(&opts.store_addrs, opts.backend_tls.as_ref()).await?;
|
||||
let kv_backend = EtcdStore::with_etcd_client(etcd_client.clone(), opts.max_txn_ops);
|
||||
let election = EtcdElection::with_etcd_client(
|
||||
&opts.grpc.server_addr,
|
||||
@@ -435,12 +437,67 @@ pub async fn metasrv_builder(
|
||||
}
|
||||
|
||||
pub async fn create_etcd_client(store_addrs: &[String]) -> Result<Client> {
|
||||
create_etcd_client_with_tls(store_addrs, None).await
|
||||
}
|
||||
|
||||
fn build_connection_options(tls_config: Option<&TlsOption>) -> Result<Option<ConnectOptions>> {
|
||||
use std::fs;
|
||||
|
||||
use common_telemetry::debug;
|
||||
use etcd_client::{Certificate, ConnectOptions, Identity, TlsOptions};
|
||||
use servers::tls::TlsMode;
|
||||
|
||||
// If TLS options are not provided, return None
|
||||
let Some(tls_config) = tls_config else {
|
||||
return Ok(None);
|
||||
};
|
||||
// If TLS is disabled, return None
|
||||
if matches!(tls_config.mode, TlsMode::Disable) {
|
||||
return Ok(None);
|
||||
}
|
||||
let mut etcd_tls_opts = TlsOptions::new();
|
||||
// Set CA certificate if provided
|
||||
if !tls_config.ca_cert_path.is_empty() {
|
||||
debug!("Using CA certificate from {}", tls_config.ca_cert_path);
|
||||
let ca_cert_pem = fs::read(&tls_config.ca_cert_path).context(error::FileIoSnafu {
|
||||
path: &tls_config.ca_cert_path,
|
||||
})?;
|
||||
let ca_cert = Certificate::from_pem(ca_cert_pem);
|
||||
etcd_tls_opts = etcd_tls_opts.ca_certificate(ca_cert);
|
||||
}
|
||||
// Set client identity (cert + key) if both are provided
|
||||
if !tls_config.cert_path.is_empty() && !tls_config.key_path.is_empty() {
|
||||
debug!(
|
||||
"Using client certificate from {} and key from {}",
|
||||
tls_config.cert_path, tls_config.key_path
|
||||
);
|
||||
let cert_pem = fs::read(&tls_config.cert_path).context(error::FileIoSnafu {
|
||||
path: &tls_config.cert_path,
|
||||
})?;
|
||||
let key_pem = fs::read(&tls_config.key_path).context(error::FileIoSnafu {
|
||||
path: &tls_config.key_path,
|
||||
})?;
|
||||
let identity = Identity::from_pem(cert_pem, key_pem);
|
||||
etcd_tls_opts = etcd_tls_opts.identity(identity);
|
||||
}
|
||||
// Enable native TLS roots for additional trust anchors
|
||||
etcd_tls_opts = etcd_tls_opts.with_native_roots();
|
||||
Ok(Some(ConnectOptions::new().with_tls(etcd_tls_opts)))
|
||||
}
|
||||
|
||||
pub async fn create_etcd_client_with_tls(
|
||||
store_addrs: &[String],
|
||||
tls_config: Option<&TlsOption>,
|
||||
) -> Result<Client> {
|
||||
let etcd_endpoints = store_addrs
|
||||
.iter()
|
||||
.map(|x| x.trim())
|
||||
.filter(|x| !x.is_empty())
|
||||
.collect::<Vec<_>>();
|
||||
Client::connect(&etcd_endpoints, None)
|
||||
|
||||
let connect_options = build_connection_options(tls_config)?;
|
||||
|
||||
Client::connect(&etcd_endpoints, connect_options)
|
||||
.await
|
||||
.context(error::ConnectEtcdSnafu)
|
||||
}
|
||||
@@ -533,3 +590,104 @@ pub async fn create_mysql_pool(store_addrs: &[String]) -> Result<MySqlPool> {
|
||||
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use servers::tls::TlsMode;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_etcd_client_tls_without_certs() {
|
||||
let endpoints: Vec<String> = match std::env::var("GT_ETCD_TLS_ENDPOINTS") {
|
||||
Ok(endpoints_str) => endpoints_str
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect(),
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let tls_config = TlsOption {
|
||||
mode: TlsMode::Require,
|
||||
ca_cert_path: String::new(),
|
||||
cert_path: String::new(),
|
||||
key_path: String::new(),
|
||||
watch: false,
|
||||
};
|
||||
|
||||
let _client = create_etcd_client_with_tls(&endpoints, Some(&tls_config))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_etcd_client_tls_with_client_certs() {
|
||||
let endpoints: Vec<String> = match std::env::var("GT_ETCD_TLS_ENDPOINTS") {
|
||||
Ok(endpoints_str) => endpoints_str
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect(),
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let cert_dir = std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("tests-integration")
|
||||
.join("fixtures")
|
||||
.join("etcd-tls-certs");
|
||||
|
||||
if cert_dir.join("client.crt").exists() && cert_dir.join("client-key.pem").exists() {
|
||||
let tls_config = TlsOption {
|
||||
mode: TlsMode::Require,
|
||||
ca_cert_path: String::new(),
|
||||
cert_path: cert_dir.join("client.crt").to_string_lossy().to_string(),
|
||||
key_path: cert_dir
|
||||
.join("client-key.pem")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
watch: false,
|
||||
};
|
||||
|
||||
let _client = create_etcd_client_with_tls(&endpoints, Some(&tls_config))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_etcd_client_tls_with_full_certs() {
|
||||
let endpoints: Vec<String> = match std::env::var("GT_ETCD_TLS_ENDPOINTS") {
|
||||
Ok(endpoints_str) => endpoints_str
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect(),
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let cert_dir = std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("tests-integration")
|
||||
.join("fixtures")
|
||||
.join("etcd-tls-certs");
|
||||
|
||||
if cert_dir.join("ca.crt").exists()
|
||||
&& cert_dir.join("client.crt").exists()
|
||||
&& cert_dir.join("client-key.pem").exists()
|
||||
{
|
||||
let tls_config = TlsOption {
|
||||
mode: TlsMode::Require,
|
||||
ca_cert_path: cert_dir.join("ca.crt").to_string_lossy().to_string(),
|
||||
cert_path: cert_dir.join("client.crt").to_string_lossy().to_string(),
|
||||
key_path: cert_dir
|
||||
.join("client-key.pem")
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
watch: false,
|
||||
};
|
||||
|
||||
let _client = create_etcd_client_with_tls(&endpoints, Some(&tls_config))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +257,15 @@ pub enum Error {
|
||||
location: Location,
|
||||
},
|
||||
|
||||
#[snafu(display("Failed to read file: {}", path))]
|
||||
FileIo {
|
||||
#[snafu(source)]
|
||||
error: std::io::Error,
|
||||
#[snafu(implicit)]
|
||||
location: Location,
|
||||
path: String,
|
||||
},
|
||||
|
||||
#[snafu(display("Failed to bind address {}", addr))]
|
||||
TcpBind {
|
||||
addr: String,
|
||||
@@ -970,6 +979,7 @@ impl ErrorExt for Error {
|
||||
match self {
|
||||
Error::EtcdFailed { .. }
|
||||
| Error::ConnectEtcd { .. }
|
||||
| Error::FileIo { .. }
|
||||
| Error::TcpBind { .. }
|
||||
| Error::SerializeToJson { .. }
|
||||
| Error::DeserializeFromJson { .. }
|
||||
|
||||
@@ -54,3 +54,45 @@ cd tests-integration/fixtures
|
||||
|
||||
docker compose -f docker-compose.yml up kafka
|
||||
```
|
||||
|
||||
## Setup tests with etcd TLS
|
||||
|
||||
This guide explains how to set up and test TLS-enabled etcd connections in GreptimeDB integration tests.
|
||||
|
||||
### Quick Start
|
||||
|
||||
TLS certificates are already at `tests-integration/fixtures/etcd-tls-certs/`.
|
||||
|
||||
1. **Start TLS-enabled etcd**:
|
||||
```bash
|
||||
cd tests-integration/fixtures
|
||||
docker compose up etcd-tls -d
|
||||
```
|
||||
|
||||
2. **Start all services (including etcd-tls)**:
|
||||
```bash
|
||||
cd tests-integration/fixtures
|
||||
docker compose up -d --wait
|
||||
```
|
||||
|
||||
### Certificate Details
|
||||
|
||||
The checked-in certificates include:
|
||||
- `ca.crt` - Certificate Authority certificate
|
||||
- `server.crt` / `server-key.pem` - Server certificate for etcd-tls service
|
||||
- `client.crt` / `client-key.pem` - Client certificate for connecting to etcd-tls
|
||||
|
||||
The server certificate includes SANs for `localhost`, `etcd-tls`, `127.0.0.1`, and `::1`.
|
||||
|
||||
### Regenerating Certificates (Optional)
|
||||
|
||||
If you need to regenerate the certificates:
|
||||
```bash
|
||||
# Regenerate certificates (overwrites existing ones)
|
||||
./scripts/generate-etcd-tls-certs.sh
|
||||
|
||||
# Or generate in custom location
|
||||
./scripts/generate-etcd-tls-certs.sh /path/to/cert/directory
|
||||
```
|
||||
|
||||
**Note**: The checked-in certificates are for testing purposes only and should never be used in production.
|
||||
@@ -43,6 +43,33 @@ services:
|
||||
ETCD_ADVERTISE_CLIENT_URLS: http://etcd:2379
|
||||
ETCD_MAX_REQUEST_BYTES: 10485760
|
||||
|
||||
etcd-tls:
|
||||
image: docker.io/bitnami/etcd:3.5
|
||||
ports:
|
||||
- "2378:2378"
|
||||
- "2381:2381"
|
||||
environment:
|
||||
ALLOW_NONE_AUTHENTICATION: "yes"
|
||||
ETCD_NAME: etcd-tls
|
||||
ETCD_LISTEN_CLIENT_URLS: https://0.0.0.0:2378
|
||||
ETCD_ADVERTISE_CLIENT_URLS: https://etcd-tls:2378
|
||||
ETCD_LISTEN_PEER_URLS: https://0.0.0.0:2381
|
||||
ETCD_INITIAL_ADVERTISE_PEER_URLS: https://etcd-tls:2381
|
||||
ETCD_INITIAL_CLUSTER: etcd-tls=https://etcd-tls:2381
|
||||
ETCD_INITIAL_CLUSTER_TOKEN: etcd-tls-cluster
|
||||
ETCD_INITIAL_CLUSTER_STATE: new
|
||||
ETCD_CERT_FILE: /certs/server.crt
|
||||
ETCD_KEY_FILE: /certs/server-key.pem
|
||||
ETCD_TRUSTED_CA_FILE: /certs/ca.crt
|
||||
ETCD_PEER_CERT_FILE: /certs/server.crt
|
||||
ETCD_PEER_KEY_FILE: /certs/server-key.pem
|
||||
ETCD_PEER_TRUSTED_CA_FILE: /certs/ca.crt
|
||||
ETCD_CLIENT_CERT_AUTH: "true"
|
||||
ETCD_PEER_CLIENT_CERT_AUTH: "true"
|
||||
ETCD_MAX_REQUEST_BYTES: 10485760
|
||||
volumes:
|
||||
- ./etcd-tls-certs:/certs:ro
|
||||
|
||||
minio:
|
||||
image: docker.io/bitnami/minio:2024
|
||||
ports:
|
||||
|
||||
28
tests-integration/fixtures/etcd-tls-certs/ca-key.pem
Normal file
28
tests-integration/fixtures/etcd-tls-certs/ca-key.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCfIi0iTllUQyNY
|
||||
ka+d9Zt30ILA0QBzLKHwez9QJj8bQLpfKR26d794CQn/OO6XO7MWsJ6nvqwRNYM0
|
||||
WX+UwUtuT9MrttYWpS5yEAVO79dMtF67gCNafXKjQyK8L1vz6Avq4XJN4VqZEifT
|
||||
Fdk3s2MmS0twv4sgrK//jh7aZzBQJtw+ROe9RN1dqlKoa3TtpB7iwNTDxGiR0EYj
|
||||
wHj+GdiNHtDMWvrnTNNX/IKeEwLP/Mjirzr7GnaOjR25ruqcLuwWrufu+EMhqFTU
|
||||
r+LIQpZD0TFuPX6DPlQZOs/4UpjteoC84m5AnQXNlh0vzjbW1efEYWYQoKDesx9e
|
||||
oE5jcABpAgMBAAECggEAA3Rw/r6CYaTG1tdBilA47LF/XTihu15mh6Y4BNadESDn
|
||||
IEYav0p2mDW4sgH7lWyg4ecPaBHo124jfUFM1p8Zsvk9sERwbR5vSIpWKyq5hbtM
|
||||
Fo2yIXakGgJM9ev19vDR7WqxRMVAkR6GnyZpcwmh0e+ENvGZpNR1n7qSAJOJRibW
|
||||
Ye8qMF/zMLF9VekBRPFJFIZBvKgHxSGCLbXRzsi5LKMbwfBoJmxEZSOC9zODl43o
|
||||
Z2i+LvlS0R/Rsf2KG+Hwgj1P7HH1znJeA5bVJFDewljjSwu1mk0JpQL7Jgp2xpqs
|
||||
F/mRZmtoQSH3EsTm2Kjz1sLGXwUb9JaQ274aV4t7pwKBgQDXYF+qFYip7k+b9FTF
|
||||
sFbfp3CjOqxXiAxnoE5hlfV/h0w4V1Su42AdejnbIVYFX8bvmezkNWPXhB6P5oHU
|
||||
4nO+oAuhsRT4317mfRM5NWO6mv2eglSBnS04GLsX142A7jMPr9e+Cqh4dYfw/A1L
|
||||
bSdsdILemTFQrak27pC11mHZOwKBgQC9JhDhQf5uRh6k8GvgKGu9ZEZmkYCVu2sr
|
||||
7kpD60UhklnyQo6DKYsa6OcChRQMv9ss3Hqu3Y1G0/sTe1Tjz5zwrWWAZoLlbdOt
|
||||
vipesvwNTxvJoUWPtrjOoFZtmyg0Q0TqxaxfEWAssDU9IfnIy+zx7sAg4zZIPUyy
|
||||
6kudaY1SqwKBgQCAQ/71Fjn7qddzc4GA8lHqhJeKPokg3/8zP78uUtaQCo2UCD6A
|
||||
oR0+sOn/3MyUCsQ5MZxpFHrPgPmKjabIl8yCvGHw+7sXtD+aWOa37VnlaiSc39Vg
|
||||
E7E4dVIHEvJM1I9ISlrb7REEHErHc/Se9PTDnGfMFcPO3n2mH1HDWVeQvQKBgGGn
|
||||
BHH3a08tXmbTRS5uT+lwmrQbjKJBJ3x/wtG75m4Fq/BaEk9/JDUZZyKy5/4JEzPf
|
||||
BGvBME4P5QFS3CndJu5O5ydaRVwDzpRVqHRJvb11SShY3Zvrvw/WUai2wRPyYuM+
|
||||
eNaAFwIbWvEb2GSle8gP9htEkuLK2w1HzxAOzYqPAoGAKl5l/WsoLfQP5UIUjSQe
|
||||
JtVTDVmoz8m8Mg2nn56UdUetG246EVhDx5ngj84kZDM0GDXhfVWV6MWnIZr5NQsr
|
||||
bORIDNP7Czat8FnlXeAQ+R6A/87o5g5p6ydH9jYqrrLxYjaZyXJptE+ja4zW7Lbl
|
||||
ogWAc76iZvXLXqKRfepG0zQ=
|
||||
-----END PRIVATE KEY-----
|
||||
21
tests-integration/fixtures/etcd-tls-certs/ca.crt
Normal file
21
tests-integration/fixtures/etcd-tls-certs/ca.crt
Normal file
@@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDeTCCAmGgAwIBAgIUeRD4bMVd0XEzS3UHo2ptnknsWzEwDQYJKoZIhvcNAQEL
|
||||
BQAwTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjERMA8G
|
||||
A1UECgwIR3JlcHRpbWUxEDAOBgNVBAMMB2V0Y2QtY2EwHhcNMjUwODI1MTgwNjU1
|
||||
WhcNMjYwODI1MTgwNjU1WjBMMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ
|
||||
BgNVBAcMAlNGMREwDwYDVQQKDAhHcmVwdGltZTEQMA4GA1UEAwwHZXRjZC1jYTCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ8iLSJOWVRDI1iRr531m3fQ
|
||||
gsDRAHMsofB7P1AmPxtAul8pHbp3v3gJCf847pc7sxawnqe+rBE1gzRZf5TBS25P
|
||||
0yu21halLnIQBU7v10y0XruAI1p9cqNDIrwvW/PoC+rhck3hWpkSJ9MV2TezYyZL
|
||||
S3C/iyCsr/+OHtpnMFAm3D5E571E3V2qUqhrdO2kHuLA1MPEaJHQRiPAeP4Z2I0e
|
||||
0Mxa+udM01f8gp4TAs/8yOKvOvsado6NHbmu6pwu7Bau5+74QyGoVNSv4shClkPR
|
||||
MW49foM+VBk6z/hSmO16gLzibkCdBc2WHS/ONtbV58RhZhCgoN6zH16gTmNwAGkC
|
||||
AwEAAaNTMFEwHQYDVR0OBBYEFOCkI3Uyx7F38LtXtSlg3ORE9ur6MB8GA1UdIwQY
|
||||
MBaAFOCkI3Uyx7F38LtXtSlg3ORE9ur6MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
|
||||
hvcNAQELBQADggEBAJXbWJJ9b+5nXjRiFXOg+wQnzn7kzMf6sWKIFk+AuKJWWt78
|
||||
O00t6vyAz6zel5Cj3ho9yAaMFNy8vYEnJCYngy5pT/2hOncnz/w7IKTeoEhzqAnf
|
||||
MCEmCgHbTKDoFfMfrrRwtyoePVfx4xbiGVWMQFTPG+WNlE/ivFMRvFwsgPJ+7SUK
|
||||
mR2FscH6DVo4sqF6s729lTmr6/U7bOD5l2HYGpKJ2cjCI8+HDv55aAT43tsTwBoJ
|
||||
BgX+RT4w8ryGhYV+hrRTjPlMHWiHsNbzJeAi5bNA0f6vUP6k6zHn/Ur3MNb1avcf
|
||||
cSsdYU2dhs7PeB6IpoJ0QCeJw9MIFK3XTnmbeVY=
|
||||
-----END CERTIFICATE-----
|
||||
1
tests-integration/fixtures/etcd-tls-certs/ca.srl
Normal file
1
tests-integration/fixtures/etcd-tls-certs/ca.srl
Normal file
@@ -0,0 +1 @@
|
||||
4484A9BBD4F25F32994F3C03D80D294105B119E6
|
||||
28
tests-integration/fixtures/etcd-tls-certs/client-key.pem
Normal file
28
tests-integration/fixtures/etcd-tls-certs/client-key.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCOcrzRmE3sEGYo
|
||||
pazDrpkkzbiaBhHClfmBiZAAGV2cvSXY8e9pc21GOgrGBNeyPPieS305rAE02EZl
|
||||
oIAt97XRFxkZniUy8C5+PT3eicAKPRcrgGhIrYxUs39rdRocqVVpZsiZGzhHhboB
|
||||
bXNW1l37SDQpuxAQJuhHu2wu9J7c5/TBXWN9ZOxzWTlrIdEQOA46VclE/N1TlaKs
|
||||
CSWw8qH87YLwkLEXcFLOJfmWNZxOOhdL5MSzKKNcQKbpmkd65B/PHNwBIBZHpI+K
|
||||
xphK1SybA+ESkN09qZaa1Kj3e0I62UjHNXUCuAod6RhRRmpiFDFgggXhD9T9Ttuf
|
||||
1Lq38XxDAgMBAAECggEAANNhqQldwHzi9WCxXObLoufBe9lM73+1Df1IQaDHkZR3
|
||||
jHliixxF18XQW7qZ5tAJqjsDWLPm4BxSKXozsjsvBdgIUjbqkyx1dsGlO9TjeGu5
|
||||
H2/8jlH14boIMWJ9Y0JBWwvU7EnVU5IkUOEiwsxvFlzM5Q0H+841CrSD+Xd7iSZE
|
||||
ZrpyZgpHNmvc/u7AmseZVccjX21dxwWtcd7cGUmFWC9o2a/hkgG6+baA8zH2ze3J
|
||||
Smeowa/oOyOVkTM1EHLCBvddE+/W+BeMGPY7A6SztVw0gLqlSOL3cr/g2llUTmFg
|
||||
T6MOS6FZZ7MD5c2HBL0V3OXIhxNABzD+c0O3CaRbSQKBgQC/+QuhMpDCzxBPaL/K
|
||||
sqRp4sQgURDCXPA1nAfI+NoHos/CbjwcMGp6LUSiBW0tLTJ+LZoVgZXj6j/uxji9
|
||||
DWxQfULvQ7oanm/q/D+40NnupQQTzmMT04z/mV3XjFtzEhbO30YZfqwXy+tqB8vR
|
||||
g1KajXVqLmCxKDtsFedAlIVxRQKBgQC99TKGcBwsKlYJJThU2eIIy8G0GkjjXleK
|
||||
ROMO5i0keJtLac1oRvXo4JN5UBLJM6ZpSy0TEa2bxfzy6Uea+41aZmdCpPg0Kcsq
|
||||
Pb1S3rsPpVdsfxSxsdKvwZmHXOzAdF+fom1+ZRAdo/8ALIPaNQSSaw+KkmmpHPEV
|
||||
qdzzWJ4b5wKBgFubEtKcF3nuZwENoh+ueUhRvncRV+b3hGSAjTJ4lUn5hhxoj+R/
|
||||
sf+VJGAQKNXa8HJHfnRuvsDgYhulmSOViS8rZspXzjGvkwZV0m51stjvA3AUFzE5
|
||||
zNmXLLGTt3vEkP+siX3W9XXxh+ezyq2ydbNsdy/w65D9+sUL+qrVdIvlAoGAOOQy
|
||||
2ajCB0g2tE59bIxE8jV0MiidI9uhhDvVdSTi6EVm3VM2vcBi7fg0suSUe8YIVQi6
|
||||
2zc0M688btQHKhek4ipBSuh1ncnWmzQae7NRewIeCNSWshF79D+bZ7sg/RLdgMX4
|
||||
3R4PkZEIUlkCtFuknuWJpgrrskaEveQ91HP6BokCgYAX42nKPANIMrTXuJ2vACWu
|
||||
qKQ9atAC1ngVzYe2PI8rHjA4gCDraGfCaILewrd89rK9ukBeSDIm5Mn448q3ystw
|
||||
p/QMxmMdHADCD6UwCjlt9N0Xigv+IKbDzDzhartRVIPpZdTViQXW3cSHt9id8zvO
|
||||
HTu5C6W+N9Vb7j8Ak/mvzw==
|
||||
-----END PRIVATE KEY-----
|
||||
20
tests-integration/fixtures/etcd-tls-certs/client.crt
Normal file
20
tests-integration/fixtures/etcd-tls-certs/client.crt
Normal file
@@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMjCCAhqgAwIBAgIURISpu9TyXzKZTzwD2A0pQQWxGeYwDQYJKoZIhvcNAQEL
|
||||
BQAwTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjERMA8G
|
||||
A1UECgwIR3JlcHRpbWUxEDAOBgNVBAMMB2V0Y2QtY2EwHhcNMjUwODI1MTgwNjU1
|
||||
WhcNMjYwODI1MTgwNjU1WjAWMRQwEgYDVQQDDAtldGNkLWNsaWVudDCCASIwDQYJ
|
||||
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAI5yvNGYTewQZiilrMOumSTNuJoGEcKV
|
||||
+YGJkAAZXZy9Jdjx72lzbUY6CsYE17I8+J5LfTmsATTYRmWggC33tdEXGRmeJTLw
|
||||
Ln49Pd6JwAo9FyuAaEitjFSzf2t1GhypVWlmyJkbOEeFugFtc1bWXftINCm7EBAm
|
||||
6Ee7bC70ntzn9MFdY31k7HNZOWsh0RA4DjpVyUT83VOVoqwJJbDyofztgvCQsRdw
|
||||
Us4l+ZY1nE46F0vkxLMoo1xApumaR3rkH88c3AEgFkekj4rGmErVLJsD4RKQ3T2p
|
||||
lprUqPd7QjrZSMc1dQK4Ch3pGFFGamIUMWCCBeEP1P1O25/UurfxfEMCAwEAAaNC
|
||||
MEAwHQYDVR0OBBYEFINcPBk3iqCw1B2sZzcDpSF6ZNGnMB8GA1UdIwQYMBaAFOCk
|
||||
I3Uyx7F38LtXtSlg3ORE9ur6MA0GCSqGSIb3DQEBCwUAA4IBAQBgyF1XSpAyiQNA
|
||||
sFCqXrBfwPnv6V+R5jhO6Glmn+Nhj0gbzNBlU8EKsK/WZllDrJjmxubPBqb563Zt
|
||||
J+QcNLqugZdioXPbxmmi9xj3oK25pUCRBj03nlHpGqIwuCJyn/ZxlfXMpNYE1KjM
|
||||
nprFNUKgnYPk2AGffAngQdm0yrnmSpxXhNTuhQE8avgRhd5nEUEDyPIvHWwo4iU6
|
||||
pw2aP2FpWorESv9LVna+JortThYDQrIFgCtPM6BP1N7Aeqn0H846+JsXlq2ch1Iy
|
||||
aBRqKNQRc1Q2Qb9/QCDEJ3dEixgFjxztIaqrIcr18ZJ797MhTFS3aVEwE8clSRR5
|
||||
9ow9jK8B
|
||||
-----END CERTIFICATE-----
|
||||
28
tests-integration/fixtures/etcd-tls-certs/server-key.pem
Normal file
28
tests-integration/fixtures/etcd-tls-certs/server-key.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtYFxH+oet6jTD
|
||||
0eF55ISO+bwm1NPTluP9zLJrQFNDkqlddyiIasK5q7qN1pPXOw9mJF/EN8Hf1lWj
|
||||
42an6tr7PgE0NHLcOrqDv4dRjegRi87IWiPkfep8peUE3glI4IOMXfZmAUNp+nRO
|
||||
JP/ymmR0pzHYJlx+D082OYmeBny7uFQxo+vxgVNo2MVVwy6oTv+jtjLgZ4iOrIvh
|
||||
iILoXtXcdg/tjB1rS2hSABGPJMNHwKswcrt6xXv+7Llsxroq0cx0E2PrAbc5qB40
|
||||
v1Qp7PjFTJ0drgf0g51LkOb7znpB1viPD2BLMxpELTZqa4OruarcDNxShrK8WWMP
|
||||
1mygLHLxAgMBAAECggEAC4TgtLaQP62VImKGLs1QQliU1+ahiUgX70Ojog0UyyNK
|
||||
JefWFVQ0ilX+z9AvI+hsYj6t7zE+LBNHPtuLtUHdGT66IUAP1pJ/VGQMB07cmZfW
|
||||
ngihJFv6UZxLDkr7RnCGRPP0PDw+wKKPiiaaq8F2xapbHS+VSxnUyzdA7bMkI+uj
|
||||
+gLAFj+kEU0FNbIp/mBzz8sksDzcB29oy3VnZkR1211KkL1BJDvr9oKiUg8NFKaN
|
||||
NF2WXRYI/m0CQMlX6zlTyv7+h/Ay7y8oNG7cfHavmCrWvYIMfaDggYxbIpNdGxb5
|
||||
MAdbrtXJ6daUBa2sezxgQUyJX8+8GGF2zpGvCfhkfQKBgQDiAwA8rlxrBnXclwRK
|
||||
9s/apILKCxPEGwU6XZi/8na3ugIO14y2WD0zZTjUK/3xwoKN6j6+ObLkUBX2RRYZ
|
||||
ewwxpqos2cyxi5EBKPhsydqbJQlat68I5+NOG4KOZQkqO92tBtgY3gGFWVntaqtE
|
||||
UVE/Clh2gFcc/5nR/5C5Mil8LQKBgQDEYXtrl2kl4qcyXuuXKDA/bLSnDuIEMhLO
|
||||
4oIiqmywXQgjPjGAWy0eztjMq2a353pqTFCqto/cfOif+rjkB7oFfi9gMm0plIKI
|
||||
+F8QsBB7HpGqWos3zb1yt8X9hbxKuFFwZS/un3Li4lwPlk8EZ1YIvhC44BHAvNkD
|
||||
VzxzBwoYVQKBgArRe/RroC7bS074x5LTB5X+o+gJ6bNMW860Zjhh4b7fn3OYa7ra
|
||||
tGs+YB7/0BL/bYJfgQtX9bEqCDMWkX08v5Os1553+m1RMeqtTF7gtp8Qgcce3bj+
|
||||
aIn3lSM9wNeNsAm1NyjRj58TbNOJdJM7lTkARMW/VOwla/Z6VjIXLZctAoGBAJKf
|
||||
xira7eMfi36MaJJ/qyZv36Ir9ozzZh+Z91gyrtwvWfgWY5dWfCXYgv6tqw/8gOYE
|
||||
/OW5UUhq6rUn2gxHyJh5Up4ciGzXOW9TIoevLV7/v/rVh8SulJimpelYhPG1FPk6
|
||||
U8NywbCtGdd5fp3nGdGFN68Rfa/OUKmx5KxtwRfRAoGAWpfzmoI8EmCBZNXYk03k
|
||||
hnDKmICsKi9seDclcQq2PbyNvE7LDEd8O4pDnwV6RwKVEDTer9Y4IGcjkEBZcJVm
|
||||
za3l4En9+M27Xlf1I8XeB8o8RYbFjoDQyScFFIgQpvTDsOezXeDR55FGPZN7V6Si
|
||||
lKmd+8BuzJ7d31KJtRjoS1U=
|
||||
-----END PRIVATE KEY-----
|
||||
21
tests-integration/fixtures/etcd-tls-certs/server.crt
Normal file
21
tests-integration/fixtures/etcd-tls-certs/server.crt
Normal file
@@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDjDCCAnSgAwIBAgIURISpu9TyXzKZTzwD2A0pQQWxGeUwDQYJKoZIhvcNAQEL
|
||||
BQAwTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjERMA8G
|
||||
A1UECgwIR3JlcHRpbWUxEDAOBgNVBAMMB2V0Y2QtY2EwHhcNMjUwODI1MTgwNjU1
|
||||
WhcNMjYwODI1MTgwNjU1WjATMREwDwYDVQQDDAhldGNkLXRsczCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAK1gXEf6h63qNMPR4XnkhI75vCbU09OW4/3M
|
||||
smtAU0OSqV13KIhqwrmruo3Wk9c7D2YkX8Q3wd/WVaPjZqfq2vs+ATQ0ctw6uoO/
|
||||
h1GN6BGLzshaI+R96nyl5QTeCUjgg4xd9mYBQ2n6dE4k//KaZHSnMdgmXH4PTzY5
|
||||
iZ4GfLu4VDGj6/GBU2jYxVXDLqhO/6O2MuBniI6si+GIguhe1dx2D+2MHWtLaFIA
|
||||
EY8kw0fAqzByu3rFe/7suWzGuirRzHQTY+sBtzmoHjS/VCns+MVMnR2uB/SDnUuQ
|
||||
5vvOekHW+I8PYEszGkQtNmprg6u5qtwM3FKGsrxZYw/WbKAscvECAwEAAaOBnjCB
|
||||
mzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEMDBBBgNVHREEOjA4gglsb2NhbGhvc3SC
|
||||
CGV0Y2QtdGxzggkxMjcuMC4wLjGHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwHQYD
|
||||
VR0OBBYEFK8y9gWv8Si9AusP280BrgDF6y3jMB8GA1UdIwQYMBaAFOCkI3Uyx7F3
|
||||
8LtXtSlg3ORE9ur6MA0GCSqGSIb3DQEBCwUAA4IBAQBMBsAPIlk17I2ioN9xwxwl
|
||||
yYbSjZlTs+18wSZAoCNLfxwWIYAQ08dPoEUdALfMUPEEe1Ol2IAp/qx2JoDrZWje
|
||||
maA43hppBUpFFCkTKWUMYxsetN7d7BVxWL43GDoMwoD/k36nhoUKBUjlbF0+nkem
|
||||
dOMr8SA4GZbEg7qk2cL93g0UHv/Z/dZgKf3epZkR9hEN4/R2jSP6OPmY9XIvQCoZ
|
||||
8D9jgbQKavAAXmUcP5a81alQMRroGaBCzI1f5OlS3EuVE7ZTEBgxKK1idbouSrPt
|
||||
4UHEbOGz9zXDjmfut6CTm247+lJm9jzYe2Xx+XGw29l0pzd/8tGFN9zIvW8mCv7a
|
||||
-----END CERTIFICATE-----
|
||||
Reference in New Issue
Block a user