1+ // Copyright (c) 2025 Calvin Min
2+ // SPDX-License-Identifier: MIT
3+ #pragma once
4+
5+ #include " databricks/core/config.h"
6+ #include " databricks/secrets/secrets_types.h"
7+
8+ #include < optional>
9+ #include < vector>
10+
11+ namespace databricks {
12+ namespace internal {
13+ class IHttpClient ;
14+ }
15+
16+ /* *
17+ * @brief Client for interacting with the Databricks Secrets API
18+ *
19+ * The Secrets API allows you to securely store and manage credentials, tokens, and other
20+ * sensitive information in your Databricks workspace. Rather than entering credentials
21+ * directly into notebooks, you can store them as secrets and reference them securely.
22+ * This implementation uses Secrets API 2.0.
23+ *
24+ * Example usage:
25+ * @code
26+ * databricks::AuthConfig auth = databricks::AuthConfig::from_environment();
27+ * databricks::Secrets secrets(auth);
28+ *
29+ * // List all secret scopes
30+ * auto scopes = secrets.list_scopes();
31+ *
32+ * // Create a new secret scope
33+ * secrets.create_scope("my_scope", databricks::SecretScopeBackendType::DATABRICKS);
34+ *
35+ * // Store a secret
36+ * secrets.put_secret("my_scope", "api_key", "my_secret_value");
37+ *
38+ * // List secrets in a scope
39+ * auto secret_list = secrets.list_secrets("my_scope");
40+ *
41+ * // Delete a secret
42+ * secrets.delete_secret("my_scope", "api_key");
43+ * @endcode
44+ */
45+ class Secrets {
46+ public:
47+ /* *
48+ * @brief Construct a Secrets API client
49+ * @param auth Authentication configuration with host and token
50+ * @param api_version Secrets API version to use (default: "2.0")
51+ */
52+ explicit Secrets (const AuthConfig& auth, const std::string& api_version = " 2.0" );
53+
54+ /* *
55+ * @brief Construct a Secrets API client with dependency injection (for testing)
56+ * @param http_client Injected HTTP client (use MockHttpClient for unit tests)
57+ * @note This constructor is primarily for testing with mock HTTP clients
58+ */
59+ explicit Secrets (std::shared_ptr<internal::IHttpClient> http_client);
60+
61+ /* *
62+ * @brief Destructor
63+ */
64+ ~Secrets ();
65+
66+ Secrets (const Secrets&) = delete ;
67+ Secrets& operator =(const Secrets&) = delete ;
68+
69+ // Scope operations
70+ /* *
71+ * @brief List all secret scopes in the workspace
72+ *
73+ * @return Vector of SecretScope objects
74+ * @throws std::runtime_error if the API request fails
75+ */
76+ std::vector<SecretScope> list_scopes ();
77+
78+ /* *
79+ * @brief Create a new secret scope
80+ *
81+ * @param scope The name of the secret scope to create
82+ * @param initial_manage_principal The principal (user or group) that will be granted MANAGE
83+ * permission on the new scope. Common values:
84+ * - "users": grants MANAGE access to all workspace users (default)
85+ * - "admins": grants MANAGE access to workspace admins only
86+ * - A specific user or group name
87+ * @param backend_type The type of backend (DATABRICKS or AZURE_KEYVAULT)
88+ * @param azure_resource_id Azure Key Vault resource ID (required for AZURE_KEYVAULT backend)
89+ * @param azure_tenant_id Azure tenant ID (required for AZURE_KEYVAULT backend)
90+ * @param dns_name Azure Key Vault DNS name (required for AZURE_KEYVAULT backend)
91+ * @throws std::runtime_error if the scope already exists or the API request fails
92+ * @throws std::invalid_argument if Azure parameters are missing for AZURE_KEYVAULT backend
93+ *
94+ * @note Databricks-backed scopes are stored in the control plane. Azure Key Vault-backed
95+ * scopes are stored in your Azure Key Vault instance.
96+ */
97+ void create_scope (const std::string& scope, const std::string& initial_manage_principal,
98+ SecretScopeBackendType backend_type,
99+ const std::optional<std::string>& azure_resource_id = std::nullopt ,
100+ const std::optional<std::string>& azure_tenant_id = std::nullopt ,
101+ const std::optional<std::string>& dns_name = std::nullopt );
102+
103+ /* *
104+ * @brief Delete a secret scope
105+ *
106+ * @param scope The name of the secret scope to delete
107+ * @throws std::runtime_error if the scope is not found or the API request fails
108+ *
109+ * @note Deleting a scope also deletes all secrets stored in that scope.
110+ * This operation cannot be undone.
111+ */
112+ void delete_scope (const std::string& scope);
113+
114+ // Secret operations
115+ /* *
116+ * @brief Store a secret as a string value
117+ *
118+ * @param scope The name of the secret scope
119+ * @param key The name of the secret to store
120+ * @param value The secret value as a string
121+ * @throws std::runtime_error if the API request fails
122+ *
123+ * @note The value parameter is passed by const reference to avoid unnecessary copies.
124+ * For enhanced security, users should securely clear the value from memory
125+ * after calling this function.
126+ */
127+ void put_secret (const std::string& scope, const std::string& key, const std::string& value);
128+
129+ /* *
130+ * @brief Delete a secret from a scope
131+ *
132+ * @param scope The name of the secret scope
133+ * @param key The name of the secret to delete
134+ * @throws std::runtime_error if the secret is not found or the API request fails
135+ */
136+ void delete_secret (const std::string& scope, const std::string& key);
137+
138+ /* *
139+ * @brief List all secrets in a scope
140+ *
141+ * @param scope The name of the secret scope
142+ * @return Vector of Secret objects containing metadata (not the secret values)
143+ * @throws std::runtime_error if the API request fails
144+ *
145+ * @note This method returns secret metadata only. Secret values cannot be retrieved
146+ * via the API for security reasons.
147+ */
148+ std::vector<Secret> list_secrets (const std::string& scope);
149+
150+ private:
151+ class Impl ;
152+ std::unique_ptr<Impl> pimpl_;
153+
154+ std::string backend_type_to_string (SecretScopeBackendType backend_type) const ;
155+
156+ // Helper methods for parsing API responses
157+ static std::vector<SecretScope> parse_scopes_list (const std::string& json_str);
158+ static std::vector<Secret> parse_secrets_list (const std::string& json_str);
159+ };
160+
161+ } // namespace databricks
0 commit comments