1use anyhow::Context;
2use google_cloud_auth::credentials::AccessTokenCredentials;
3use google_cloud_auth::credentials::{
4 external_account, impersonated, service_account, user_account, Credentials,
5};
6use schemars::JsonSchema;
7use serde::Deserialize;
8use serde_json::Value;
9use summer::config::Configurable;
10
11summer::submit_config_schema!("pubsub", PubSubConfig);
12
13#[derive(Debug, Configurable, Clone, JsonSchema, Deserialize)]
14#[config_prefix = "pubsub"]
15pub struct PubSubConfig {
16 #[serde(default = "default_enabled")]
18 pub enabled: bool,
19 pub project_id: String,
21 pub endpoint: Option<String>,
23 pub credentials: Option<String>,
25}
26
27fn default_enabled() -> bool {
28 true
29}
30
31pub fn credentials_from_json_value(json: Value) -> anyhow::Result<Credentials> {
32 let cred_type = json
33 .get("type")
34 .and_then(|v| v.as_str())
35 .context("credential JSON missing string field `type`")?;
36 let atc: AccessTokenCredentials = match cred_type {
37 "authorized_user" => user_account::Builder::new(json)
38 .build_access_token_credentials()
39 .map_err(|e| anyhow::anyhow!("{e}"))?,
40 "service_account" => service_account::Builder::new(json)
41 .build_access_token_credentials()
42 .map_err(|e| anyhow::anyhow!("{e}"))?,
43 "external_account" => external_account::Builder::new(json)
44 .build_access_token_credentials()
45 .map_err(|e| anyhow::anyhow!("{e}"))?,
46 "impersonated_service_account" => impersonated::Builder::new(json)
47 .build_access_token_credentials()
48 .map_err(|e| anyhow::anyhow!("{e}"))?,
49 other => anyhow::bail!("unsupported credential type: {other}"),
50 };
51 Ok(atc.into())
52}
53
54pub fn credentials_from_file(path: &str) -> anyhow::Result<Credentials> {
55 let raw = std::fs::read_to_string(path)
56 .with_context(|| format!("read pubsub credentials file {path}"))?;
57 let json: Value = serde_json::from_str(&raw).context("parse credentials JSON")?;
58 credentials_from_json_value(json)
59}