fix: Vault as single source of truth - credentials + location for all services
All checks were successful
BotServer CI/CD / build (push) Successful in 4m53s
All checks were successful
BotServer CI/CD / build (push) Successful in 4m53s
- Qdrant health check: recognize 'healthz check passed' response (fixes 45s timeout) - seed_vault_defaults: add host/port/url/grpc_port for ALL 10 services - fetch_vault_credentials: fetch ALL services via generic loop (drive, cache, tables, vectordb, directory, llm, meet, alm, encryption) - vectordb URL: fix https://localhost:6334 -> http://localhost:6333 in all config getters - get_from_env: add host/port/grpc_port for vectordb fallback - Tested: .reset (fresh install) + .restart (idempotent) - zero errors
This commit is contained in:
parent
fb2e5242da
commit
68ef554132
4 changed files with 61 additions and 87 deletions
|
|
@ -78,8 +78,6 @@ jobs:
|
||||||
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 system "ls -lh /opt/gbo/bin/botserver"
|
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 system "ls -lh /opt/gbo/bin/botserver"
|
||||||
echo "Step 6: Setting permissions..."
|
echo "Step 6: Setting permissions..."
|
||||||
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 system "chmod +x /opt/gbo/bin/botserver && chown gbuser:gbuser /opt/gbo/bin/botserver"
|
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 system "chmod +x /opt/gbo/bin/botserver && chown gbuser:gbuser /opt/gbo/bin/botserver"
|
||||||
echo "Step 7: Starting botserver..."
|
|
||||||
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 system "cd /opt/gbo/bin && sudo -u gbuser ./botserver --noconsole >> /opt/gbo/logs/error.log 2>&1 &"
|
|
||||||
echo "=== Deploy completed ==="
|
echo "=== Deploy completed ==="
|
||||||
|
|
||||||
- name: Verify botserver started
|
- name: Verify botserver started
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,10 @@ pub fn vector_db_health_check() -> bool {
|
||||||
{
|
{
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
let response = String::from_utf8_lossy(&output.stdout);
|
let response = String::from_utf8_lossy(&output.stdout);
|
||||||
if response.contains("OK") || response.contains("\"status\":\"ok\"") {
|
if response.contains("healthz check passed")
|
||||||
|
|| response.contains("OK")
|
||||||
|
|| response.contains("\"status\":\"ok\"")
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1268,7 +1268,6 @@ EOF"#.to_string(),
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if Vault is reachable before trying to fetch credentials
|
|
||||||
let client_cert = base_path.join("conf/system/certificates/botserver/client.crt");
|
let client_cert = base_path.join("conf/system/certificates/botserver/client.crt");
|
||||||
let client_key = base_path.join("conf/system/certificates/botserver/client.key");
|
let client_key = base_path.join("conf/system/certificates/botserver/client.key");
|
||||||
let vault_check = SafeCommand::new("curl")
|
let vault_check = SafeCommand::new("curl")
|
||||||
|
|
@ -1295,8 +1294,6 @@ EOF"#.to_string(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let vault_bin = base_path.join("bin/vault/vault");
|
let vault_bin = base_path.join("bin/vault/vault");
|
||||||
|
|
||||||
// Get CA cert path for Vault TLS
|
|
||||||
let ca_cert_path = std::env::var("VAULT_CACERT").unwrap_or_else(|_| {
|
let ca_cert_path = std::env::var("VAULT_CACERT").unwrap_or_else(|_| {
|
||||||
base_path
|
base_path
|
||||||
.join("conf/system/certificates/ca/ca.crt")
|
.join("conf/system/certificates/ca/ca.crt")
|
||||||
|
|
@ -1304,85 +1301,43 @@ EOF"#.to_string(),
|
||||||
.to_string()
|
.to_string()
|
||||||
});
|
});
|
||||||
|
|
||||||
trace!(
|
let services = [
|
||||||
"Fetching drive credentials from Vault at {} using {}",
|
("drive", "secret/gbo/drive"),
|
||||||
vault_addr,
|
("cache", "secret/gbo/cache"),
|
||||||
vault_bin.display()
|
("tables", "secret/gbo/tables"),
|
||||||
);
|
("vectordb", "secret/gbo/vectordb"),
|
||||||
|
("directory", "secret/gbo/directory"),
|
||||||
|
("llm", "secret/gbo/llm"),
|
||||||
|
("meet", "secret/gbo/meet"),
|
||||||
|
("alm", "secret/gbo/alm"),
|
||||||
|
("encryption", "secret/gbo/encryption"),
|
||||||
|
];
|
||||||
|
|
||||||
// Fetch drive credentials
|
for (service_name, vault_path) in &services {
|
||||||
let drive_result = SafeCommand::new(vault_bin.to_str().unwrap_or("vault"))
|
let result = SafeCommand::new(vault_bin.to_str().unwrap_or("vault"))
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
c.env("VAULT_ADDR", &vault_addr)
|
c.env("VAULT_ADDR", &vault_addr)
|
||||||
.and_then(|c| c.env("VAULT_TOKEN", &vault_token))
|
.and_then(|c| c.env("VAULT_TOKEN", &vault_token))
|
||||||
.and_then(|c| c.env("VAULT_CACERT", &ca_cert_path))
|
.and_then(|c| c.env("VAULT_CACERT", &ca_cert_path))
|
||||||
})
|
})
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
c.args(&[
|
c.args(&["kv", "get", "-format=json", "-tls-skip-verify", vault_path])
|
||||||
"kv",
|
})
|
||||||
"get",
|
.and_then(|c| c.execute());
|
||||||
"-format=json",
|
|
||||||
"-tls-skip-verify",
|
|
||||||
"secret/gbo/drive",
|
|
||||||
])
|
|
||||||
})
|
|
||||||
.and_then(|c| c.execute());
|
|
||||||
|
|
||||||
if let Ok(output) = drive_result {
|
if let Ok(output) = result {
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
let json_str = String::from_utf8_lossy(&output.stdout);
|
let json_str = String::from_utf8_lossy(&output.stdout);
|
||||||
trace!("Vault drive response: {}", json_str);
|
|
||||||
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&json_str) {
|
|
||||||
if let Some(data) = json.get("data").and_then(|d| d.get("data")) {
|
|
||||||
if let Some(accesskey) = data.get("accesskey").and_then(|v| v.as_str()) {
|
|
||||||
trace!("Found DRIVE_ACCESSKEY from Vault");
|
|
||||||
credentials
|
|
||||||
.insert("DRIVE_ACCESSKEY".to_string(), accesskey.to_string());
|
|
||||||
}
|
|
||||||
if let Some(secret) = data.get("secret").and_then(|v| v.as_str()) {
|
|
||||||
trace!("Found DRIVE_SECRET from Vault");
|
|
||||||
credentials.insert("DRIVE_SECRET".to_string(), secret.to_string());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("Vault response missing data.data field");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("Failed to parse Vault JSON for drive");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
||||||
warn!("Vault drive command failed: {}", stderr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("Failed to execute Vault drive command");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch cache credentials
|
|
||||||
let cache_result = SafeCommand::new(vault_bin.to_str().unwrap_or("vault"))
|
|
||||||
.and_then(|c| {
|
|
||||||
c.env("VAULT_ADDR", &vault_addr)
|
|
||||||
.and_then(|c| c.env("VAULT_TOKEN", &vault_token))
|
|
||||||
.and_then(|c| c.env("VAULT_CACERT", &ca_cert_path))
|
|
||||||
})
|
|
||||||
.and_then(|c| {
|
|
||||||
c.args(&[
|
|
||||||
"kv",
|
|
||||||
"get",
|
|
||||||
"-format=json",
|
|
||||||
"-tls-skip-verify",
|
|
||||||
"secret/gbo/cache",
|
|
||||||
])
|
|
||||||
})
|
|
||||||
.and_then(|c| c.execute());
|
|
||||||
|
|
||||||
if let Ok(output) = cache_result {
|
|
||||||
if output.status.success() {
|
|
||||||
if let Ok(json_str) = String::from_utf8(output.stdout) {
|
|
||||||
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&json_str) {
|
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&json_str) {
|
||||||
if let Some(data) = json.get("data").and_then(|d| d.get("data")) {
|
if let Some(data) = json.get("data").and_then(|d| d.get("data")) {
|
||||||
if let Some(password) = data.get("password").and_then(|v| v.as_str()) {
|
if let Some(obj) = data.as_object() {
|
||||||
credentials
|
let prefix = service_name.to_uppercase();
|
||||||
.insert("CACHE_PASSWORD".to_string(), password.to_string());
|
for (key, value) in obj {
|
||||||
|
if let Some(v) = value.as_str() {
|
||||||
|
let env_key = format!("{}_{}", prefix, key.to_uppercase());
|
||||||
|
credentials.insert(env_key, v.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1629,6 +1584,7 @@ VAULT_CACERT={}
|
||||||
("secret".to_string(), drive_pass),
|
("secret".to_string(), drive_pass),
|
||||||
("host".to_string(), "localhost".to_string()),
|
("host".to_string(), "localhost".to_string()),
|
||||||
("port".to_string(), "9000".to_string()),
|
("port".to_string(), "9000".to_string()),
|
||||||
|
("url".to_string(), "http://localhost:9000".to_string()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
@ -1637,6 +1593,7 @@ VAULT_CACERT={}
|
||||||
("password".to_string(), cache_pass),
|
("password".to_string(), cache_pass),
|
||||||
("host".to_string(), "localhost".to_string()),
|
("host".to_string(), "localhost".to_string()),
|
||||||
("port".to_string(), "6379".to_string()),
|
("port".to_string(), "6379".to_string()),
|
||||||
|
("url".to_string(), "redis://localhost:6379".to_string()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
@ -1647,12 +1604,15 @@ VAULT_CACERT={}
|
||||||
("port".to_string(), "5432".to_string()),
|
("port".to_string(), "5432".to_string()),
|
||||||
("database".to_string(), "botserver".to_string()),
|
("database".to_string(), "botserver".to_string()),
|
||||||
("username".to_string(), "gbuser".to_string()),
|
("username".to_string(), "gbuser".to_string()),
|
||||||
|
("url".to_string(), "postgres://localhost:5432".to_string()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"secret/gbo/directory",
|
"secret/gbo/directory",
|
||||||
vec![
|
vec![
|
||||||
("url".to_string(), "http://localhost:9000".to_string()),
|
("url".to_string(), "http://localhost:9000".to_string()),
|
||||||
|
("host".to_string(), "localhost".to_string()),
|
||||||
|
("port".to_string(), "9000".to_string()),
|
||||||
("project_id".to_string(), "none".to_string()),
|
("project_id".to_string(), "none".to_string()),
|
||||||
("client_id".to_string(), "none".to_string()),
|
("client_id".to_string(), "none".to_string()),
|
||||||
("client_secret".to_string(), "none".to_string()),
|
("client_secret".to_string(), "none".to_string()),
|
||||||
|
|
@ -1672,6 +1632,8 @@ VAULT_CACERT={}
|
||||||
"secret/gbo/llm",
|
"secret/gbo/llm",
|
||||||
vec![
|
vec![
|
||||||
("url".to_string(), "http://localhost:8081".to_string()),
|
("url".to_string(), "http://localhost:8081".to_string()),
|
||||||
|
("host".to_string(), "localhost".to_string()),
|
||||||
|
("port".to_string(), "8081".to_string()),
|
||||||
("model".to_string(), "gpt-4".to_string()),
|
("model".to_string(), "gpt-4".to_string()),
|
||||||
("openai_key".to_string(), "none".to_string()),
|
("openai_key".to_string(), "none".to_string()),
|
||||||
("anthropic_key".to_string(), "none".to_string()),
|
("anthropic_key".to_string(), "none".to_string()),
|
||||||
|
|
@ -1689,6 +1651,8 @@ VAULT_CACERT={}
|
||||||
"secret/gbo/meet",
|
"secret/gbo/meet",
|
||||||
vec![
|
vec![
|
||||||
("url".to_string(), "http://localhost:7880".to_string()),
|
("url".to_string(), "http://localhost:7880".to_string()),
|
||||||
|
("host".to_string(), "localhost".to_string()),
|
||||||
|
("port".to_string(), "7880".to_string()),
|
||||||
("app_id".to_string(), meet_app_id),
|
("app_id".to_string(), meet_app_id),
|
||||||
("app_secret".to_string(), meet_app_secret),
|
("app_secret".to_string(), meet_app_secret),
|
||||||
],
|
],
|
||||||
|
|
@ -1697,14 +1661,20 @@ VAULT_CACERT={}
|
||||||
"secret/gbo/vectordb",
|
"secret/gbo/vectordb",
|
||||||
vec![
|
vec![
|
||||||
("url".to_string(), "http://localhost:6333".to_string()),
|
("url".to_string(), "http://localhost:6333".to_string()),
|
||||||
|
("host".to_string(), "localhost".to_string()),
|
||||||
|
("port".to_string(), "6333".to_string()),
|
||||||
|
("grpc_port".to_string(), "6334".to_string()),
|
||||||
("api_key".to_string(), "none".to_string()),
|
("api_key".to_string(), "none".to_string()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"secret/gbo/alm",
|
"secret/gbo/alm",
|
||||||
vec![
|
vec![
|
||||||
("url".to_string(), "none".to_string()),
|
("url".to_string(), "http://localhost:9000".to_string()),
|
||||||
|
("host".to_string(), "localhost".to_string()),
|
||||||
|
("port".to_string(), "9000".to_string()),
|
||||||
("token".to_string(), alm_token),
|
("token".to_string(), alm_token),
|
||||||
|
("default_org".to_string(), "none".to_string()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ impl SecretsManager {
|
||||||
Ok((
|
Ok((
|
||||||
s.get("url")
|
s.get("url")
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(|| "https://localhost:6334".into()),
|
.unwrap_or_else(|| "http://localhost:6333".into()),
|
||||||
s.get("api_key").cloned(),
|
s.get("api_key").cloned(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
@ -404,12 +404,12 @@ impl SecretsManager {
|
||||||
if let Ok(runtime) = tokio::runtime::Handle::try_current() {
|
if let Ok(runtime) = tokio::runtime::Handle::try_current() {
|
||||||
if let Ok(secrets) = runtime.block_on(self.get_secret(SecretPaths::VECTORDB)) {
|
if let Ok(secrets) = runtime.block_on(self.get_secret(SecretPaths::VECTORDB)) {
|
||||||
return (
|
return (
|
||||||
secrets.get("url").cloned().unwrap_or_else(|| "https://localhost:6334".into()),
|
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:6333".into()),
|
||||||
secrets.get("api_key").cloned(),
|
secrets.get("api_key").cloned(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("https://localhost:6334".to_string(), None)
|
("http://localhost:6333".to_string(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_observability_config_sync(&self) -> (String, String, String, String) {
|
pub fn get_observability_config_sync(&self) -> (String, String, String, String) {
|
||||||
|
|
@ -562,8 +562,11 @@ impl SecretsManager {
|
||||||
secrets.insert("app_secret".into(), String::new());
|
secrets.insert("app_secret".into(), String::new());
|
||||||
}
|
}
|
||||||
"vectordb" | "gbo/vectordb" | "system/vectordb" => {
|
"vectordb" | "gbo/vectordb" | "system/vectordb" => {
|
||||||
secrets.insert("url".into(), "http://localhost:6333".into());
|
secrets.insert("url".to_string(), "http://localhost:6333".into());
|
||||||
secrets.insert("api_key".into(), String::new());
|
secrets.insert("host".to_string(), "localhost".into());
|
||||||
|
secrets.insert("port".to_string(), "6333".into());
|
||||||
|
secrets.insert("grpc_port".to_string(), "6334".into());
|
||||||
|
secrets.insert("api_key".to_string(), String::new());
|
||||||
}
|
}
|
||||||
"observability" | "gbo/observability" | "system/observability" => {
|
"observability" | "gbo/observability" | "system/observability" => {
|
||||||
secrets.insert("url".into(), "http://localhost:8086".into());
|
secrets.insert("url".into(), "http://localhost:8086".into());
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue