Skip to content

Commit ea926d5

Browse files
authored
fix: more descriptive error messages (#49)
1 parent ced64a9 commit ea926d5

File tree

4 files changed

+125
-7
lines changed

4 files changed

+125
-7
lines changed

questdb-rs/src/ingress/mod.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,7 @@ impl SenderBuilder {
17591759

17601760
fn b64_decode(descr: &'static str, buf: &str) -> Result<Vec<u8>> {
17611761
Base64UrlUnpadded::decode_vec(buf)
1762-
.map_err(|b64_err| error::fmt!(AuthError, "Could not decode {}: {}", descr, b64_err))
1762+
.map_err(|b64_err| error::fmt!(AuthError, "Misconfigured ILP authentication keys. Could not decode {}: {}. Hint: Check the keys for a possible typo.", descr, b64_err))
17631763
}
17641764

17651765
fn parse_public_key(pub_key_x: &str, pub_key_y: &str) -> Result<Vec<u8>> {
@@ -1769,9 +1769,23 @@ fn parse_public_key(pub_key_x: &str, pub_key_y: &str) -> Result<Vec<u8>> {
17691769
// SEC 1 Uncompressed Octet-String-to-Elliptic-Curve-Point Encoding
17701770
let mut encoded = Vec::new();
17711771
encoded.push(4u8); // 0x04 magic byte that identifies this as uncompressed.
1772-
encoded.resize((32 - pub_key_x.len()) + 1, 0u8);
1772+
let pub_key_x_ken = pub_key_x.len();
1773+
if pub_key_x_ken > 32 {
1774+
return Err(error::fmt!(
1775+
AuthError,
1776+
"Misconfigured ILP authentication keys. Public key x is too long. Hint: Check the keys for a possible typo."
1777+
));
1778+
}
1779+
let pub_key_y_len = pub_key_y.len();
1780+
if pub_key_y_len > 32 {
1781+
return Err(error::fmt!(
1782+
AuthError,
1783+
"Misconfigured ILP authentication keys. Public key y is too long. Hint: Check the keys for a possible typo."
1784+
));
1785+
}
1786+
encoded.resize((32 - pub_key_x_ken) + 1, 0u8);
17731787
encoded.append(&mut pub_key_x);
1774-
encoded.resize((32 - pub_key_y.len()) + 1 + 32, 0u8);
1788+
encoded.resize((32 - pub_key_y_len) + 1 + 32, 0u8);
17751789
encoded.append(&mut pub_key_y);
17761790
Ok(encoded)
17771791
}
@@ -1786,7 +1800,13 @@ fn parse_key_pair(auth: &AuthParams) -> Result<EcdsaKeyPair> {
17861800
&public_key[..],
17871801
&system_random,
17881802
)
1789-
.map_err(|key_rejected| error::fmt!(AuthError, "Bad private key: {}", key_rejected))
1803+
.map_err(|key_rejected| {
1804+
error::fmt!(
1805+
AuthError,
1806+
"Misconfigured ILP authentication keys: {}. Hint: Check the keys for a possible typo.",
1807+
key_rejected
1808+
)
1809+
})
17901810
}
17911811

17921812
pub(crate) struct F64Serializer {

questdb-rs/src/tests/sender.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,105 @@ fn test_table_name_too_long() -> TestResult {
9999
Ok(())
100100
}
101101

102+
#[test]
103+
fn test_auth_inconsistent_keys() -> TestResult {
104+
test_bad_key("fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d
105+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x
106+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac",
107+
"Misconfigured ILP authentication keys: InconsistentComponents. Hint: Check the keys for a possible typo."
108+
)
109+
}
110+
111+
#[test]
112+
fn test_auth_bad_base64_private_key() -> TestResult {
113+
test_bad_key(
114+
"bad key", // d
115+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x
116+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
117+
"Misconfigured ILP authentication keys. Could not decode private authentication key: invalid Base64 encoding. Hint: Check the keys for a possible typo."
118+
)
119+
}
120+
121+
#[test]
122+
fn test_auth_private_key_too_long() -> TestResult {
123+
test_bad_key(
124+
"ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU",
125+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x
126+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
127+
"Misconfigured ILP authentication keys: InvalidComponent. Hint: Check the keys for a possible typo."
128+
)
129+
}
130+
131+
#[test]
132+
fn test_auth_public_key_x_too_long() -> TestResult {
133+
test_bad_key(
134+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU",
135+
"ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", // x
136+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
137+
"Misconfigured ILP authentication keys. Public key x is too long. Hint: Check the keys for a possible typo."
138+
)
139+
}
140+
141+
#[test]
142+
fn test_auth_public_key_y_too_long() -> TestResult {
143+
test_bad_key(
144+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU",
145+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // x
146+
"ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", // y
147+
"Misconfigured ILP authentication keys. Public key y is too long. Hint: Check the keys for a possible typo."
148+
)
149+
}
150+
151+
#[test]
152+
fn test_auth_bad_base64_public_key_x() -> TestResult {
153+
test_bad_key(
154+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d
155+
"bad base64 encoding", // x
156+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
157+
"Misconfigured ILP authentication keys. Could not decode public key x: invalid Base64 encoding. Hint: Check the keys for a possible typo."
158+
)
159+
}
160+
161+
#[test]
162+
fn test_auth_bad_base64_public_key_y() -> TestResult {
163+
test_bad_key(
164+
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d
165+
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // x
166+
"bad base64 encoding", // y
167+
"Misconfigured ILP authentication keys. Could not decode public key y: invalid Base64 encoding. Hint: Check the keys for a possible typo."
168+
)
169+
}
170+
171+
fn test_bad_key(
172+
priv_key: &str,
173+
pub_key_x: &str,
174+
pub_key_y: &str,
175+
expected_error_msg: &str,
176+
) -> TestResult {
177+
let server = MockServer::new()?;
178+
let lsb = server
179+
.lsb()
180+
.auth("testUser1", priv_key, pub_key_x, pub_key_y);
181+
let sender = lsb.connect();
182+
183+
match sender {
184+
Ok(_) => panic!("Expected an error due to bad key, but connect succeeded."),
185+
Err(err) => {
186+
assert_eq!(
187+
err.code(),
188+
ErrorCode::AuthError,
189+
"Expected an ErrorCode::AuthError"
190+
);
191+
assert_eq!(
192+
err.msg(),
193+
expected_error_msg,
194+
"Error message did not match expected message."
195+
);
196+
}
197+
}
198+
Ok(())
199+
}
200+
102201
#[test]
103202
fn test_timestamp_overloads() -> TestResult {
104203
let tbl_name = TableName::new("tbl_name")?;

system_test/fixture.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ def start(self):
262262
'-Debug',
263263
'-XX:+UnlockExperimentalVMOptions',
264264
'-XX:+AlwaysPreTouch',
265-
'-XX:+UseParallelOldGC',
266265
'-p', str(self._root_dir / 'bin' / 'questdb.jar'),
267266
'-m', 'io.questdb/io.questdb.ServerMain',
268267
'-d', str(self._data_dir)]

system_test/test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def ns_to_qdb_date(at_ts_ns):
5959
# We first need to match QuestDB's internal microsecond resolution.
6060
at_ts_us = int(at_ts_ns / 1000.0)
6161
at_ts_sec = at_ts_us / 1000000.0
62-
at_td = datetime.datetime.fromtimestamp(at_ts_sec)
62+
at_td = datetime.datetime.utcfromtimestamp(at_ts_sec)
6363
return at_td.isoformat() + 'Z'
6464

6565

@@ -568,7 +568,7 @@ def test_malformed_auth1(self):
568568

569569
with self.assertRaisesRegex(
570570
qls.SenderError,
571-
r'.*Bad private key.*'):
571+
r'Misconfigured ILP authentication keys: InconsistentComponents. Hint: Check the keys for a possible typo.'):
572572
sender.connect()
573573

574574
def test_malformed_auth2(self):

0 commit comments

Comments
 (0)