Skip to content

Commit 56d5452

Browse files
committed
Rename provider to key_file. Pass in KeyValueSecret, get back token string.
1 parent 9e41652 commit 56d5452

File tree

6 files changed

+34
-48
lines changed

6 files changed

+34
-48
lines changed

docs/pages/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ CREATE SECRET (
4545
-- (see "Getting a Google API Access Private Key" below)
4646
CREATE SECRET (
4747
TYPE gsheet,
48-
PROVIDER private_key,
48+
PROVIDER key_file,
4949
FILENAME '<path_to_JSON_file_with_private_key>'
5050
);
5151
```
@@ -119,7 +119,7 @@ Follow steps 1-9 above to get a JSON file with your private key inside.
119119
Include the path to the file as the `FILENAME` parameter when creating a secret.
120120
The recommendation is to use an absolute path, not a relative one, and to store it in the `~/.duckdb` folder.
121121
You will need to be able to access this file while querying GSheets (its content are not persisted. Later versions of this extension may enable that.)
122-
Ex: `CREATE SECRET (TYPE gsheet, PROVIDER private_key, FILENAME '<path_to_JSON_file_with_private_key>');`
122+
Ex: `CREATE SECRET (TYPE gsheet, PROVIDER key_file, FILENAME '<path_to_JSON_file_with_private_key>');`
123123

124124
You can skip steps 10, 11, and 12 since this extension will convert from your JSON file to a token on your behalf!
125125

src/gsheets_auth.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ namespace duckdb
8383
}
8484

8585
// TODO: Maybe this should be a KeyValueSecret
86-
static unique_ptr<BaseSecret> CreateGsheetSecretFromPrivateKey(ClientContext &context, CreateSecretInput &input) {
86+
static unique_ptr<BaseSecret> CreateGsheetSecretFromKeyFile(ClientContext &context, CreateSecretInput &input) {
8787
auto scope = input.scope;
8888

8989
auto result = make_uniq<KeyValueSecret>(scope, input.type, input.provider, input.name);
@@ -95,16 +95,16 @@ namespace duckdb
9595
std::ifstream ifs(filename);
9696
json credentials_file = json::parse(ifs);
9797
std::string email = credentials_file["client_email"].get<std::string>();
98-
std::string private_key_string = credentials_file["private_key"].get<std::string>();
98+
std::string secret = credentials_file["private_key"].get<std::string>();
9999

100100
// Manage specific secret option
101-
(*result).secret_map["client_email"] = Value(email);
102-
(*result).secret_map["sheets_private_key"] = Value(private_key_string);
101+
(*result).secret_map["email"] = Value(email);
102+
(*result).secret_map["secret"] = Value(secret);
103103
CopySecret("filename", input, *result); // Store the filename anyway
104104

105105
// Redact sensible keys
106106
RedactCommonKeys(*result);
107-
result->redact_keys.insert("sheets_private_key");
107+
result->redact_keys.insert("secret");
108108
result->redact_keys.insert("filename");
109109

110110
return std::move(result);
@@ -134,10 +134,10 @@ namespace duckdb
134134
ExtensionUtil::RegisterFunction(instance, oauth_function);
135135

136136
// Register the private key secret provider
137-
CreateSecretFunction private_key_function = {type, "private_key", CreateGsheetSecretFromPrivateKey};
138-
private_key_function.named_parameters["filename"] = LogicalType::VARCHAR;
139-
RegisterCommonSecretParameters(private_key_function);
140-
ExtensionUtil::RegisterFunction(instance, private_key_function);
137+
CreateSecretFunction key_file_function = {type, "key_file", CreateGsheetSecretFromKeyFile};
138+
key_file_function.named_parameters["filename"] = LogicalType::VARCHAR;
139+
RegisterCommonSecretParameters(key_file_function);
140+
ExtensionUtil::RegisterFunction(instance, key_file_function);
141141
}
142142

143143
std::string InitiateOAuthFlow()

src/gsheets_copy.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,11 @@ namespace duckdb
5454

5555
std::string token;
5656

57-
if (secret.GetProvider() == "private_key") {
57+
if (secret.GetProvider() == "key_file") {
5858
// If using a private key, retrieve the private key from the secret, but convert it
5959
// into a token before use. This is an extra request per Google Sheet read or copy.
6060
// The secret is the JSON file that is extracted from Google as per the README
61-
62-
63-
Value client_email_value;
64-
if (!kv_secret->TryGetValue("client_email", client_email_value)) {
65-
throw InvalidInputException("'client_email' not found in 'gsheet' secret");
66-
}
67-
std::string client_email_string = client_email_value.ToString();
68-
69-
Value sheets_private_key_value;
70-
if (!kv_secret->TryGetValue("sheets_private_key", sheets_private_key_value)) {
71-
throw InvalidInputException("'sheets_private_key' not found in 'gsheet' secret");
72-
}
73-
std::string sheets_private_key_string = sheets_private_key_value.ToString();
74-
75-
token = get_token(client_email_string, sheets_private_key_string);
61+
token = get_token(kv_secret);
7662
} else {
7763
Value token_value;
7864
if (!kv_secret->TryGetValue("token", token_value)) {

src/gsheets_get_token.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "gsheets_requests.hpp"
77
#include "gsheets_utils.hpp"
88
#include "duckdb/common/exception.hpp"
9+
#include "duckdb/main/secret/secret_manager.hpp"
910

1011
#include <openssl/ssl.h>
1112
#include <openssl/err.h>
@@ -67,14 +68,26 @@ namespace duckdb
6768
output[output_index] = '\0';
6869
}
6970

70-
std::string get_token(const std::string& email, const std::string& private_key_string) {
71+
std::string get_token(const KeyValueSecret* kv_secret) {
7172
const char *header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
7273

7374
/* Create jwt claim set */
7475
json jwt_claim_set;
7576
std::time_t t = std::time(NULL);
7677

77-
jwt_claim_set["iss"] = email; /* service account email address */
78+
Value email_value;
79+
if (!kv_secret->TryGetValue("email", email_value)) {
80+
throw InvalidInputException("'email' not found in 'gsheet' secret");
81+
}
82+
std::string email_string = email_value.ToString();
83+
84+
Value secret_value;
85+
if (!kv_secret->TryGetValue("secret", secret_value)) {
86+
throw InvalidInputException("'secret' (private_key) not found in 'gsheet' secret");
87+
}
88+
std::string secret_string = secret_value.ToString();
89+
90+
jwt_claim_set["iss"] = email_string; /* service account email address */
7891
jwt_claim_set["scope"] = "https://www.googleapis.com/auth/spreadsheets" /* scope of requested access token */;
7992
jwt_claim_set["aud"] = "https://accounts.google.com/o/oauth2/token"; /* intended target of the assertion for an access token */
8093
jwt_claim_set["iat"] = std::to_string(t); /* issued time */
@@ -100,8 +113,8 @@ namespace duckdb
100113
digest_str[SHA256_DIGEST_LENGTH * 2] = '\0';
101114

102115
BIO* bio = BIO_new(BIO_s_mem());
103-
const void * private_key_pointer = private_key_string.c_str();
104-
int private_key_length = std::strlen(private_key_string.c_str());
116+
const void * private_key_pointer = secret_string.c_str();
117+
int private_key_length = std::strlen(secret_string.c_str());
105118
BIO_write(bio, private_key_pointer, private_key_length);
106119
EVP_PKEY* evp_key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
107120
RSA* rsa = EVP_PKEY_get1_RSA(evp_key);

src/gsheets_read.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,25 +134,11 @@ unique_ptr<FunctionData> ReadSheetBind(ClientContext &context, TableFunctionBind
134134

135135
std::string token;
136136

137-
if (secret.GetProvider() == "private_key") {
137+
if (secret.GetProvider() == "key_file") {
138138
// If using a private key, retrieve the private key from the secret, but convert it
139139
// into a token before use. This is an extra request per Google Sheet read or copy.
140140
// The secret is the JSON file that is extracted from Google as per the README
141-
142-
143-
Value client_email_value;
144-
if (!kv_secret->TryGetValue("client_email", client_email_value)) {
145-
throw InvalidInputException("'client_email' not found in 'gsheet' secret");
146-
}
147-
std::string client_email_string = client_email_value.ToString();
148-
149-
Value sheets_private_key_value;
150-
if (!kv_secret->TryGetValue("sheets_private_key", sheets_private_key_value)) {
151-
throw InvalidInputException("'sheets_private_key' not found in 'gsheet' secret");
152-
}
153-
std::string sheets_private_key_string = sheets_private_key_value.ToString();
154-
155-
token = get_token(client_email_string, sheets_private_key_string);
141+
token = get_token(kv_secret);
156142

157143
} else {
158144
Value token_value;

src/include/gsheets_get_token.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
#include <string>
44
#include <stdlib.h>
5+
#include "duckdb/main/secret/secret_manager.hpp"
56

67
namespace duckdb {
78

89
char get_base64_char(char byte);
910

1011
void base64encode(char *output, const char *input, size_t input_length) ;
1112

12-
std::string get_token(const std::string& email, const std::string& private_key_string ) ;
13+
std::string get_token(const KeyValueSecret* kv_secret) ;
1314

1415
}

0 commit comments

Comments
 (0)