Skip to content

fix: more descriptive error messages #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions questdb-rs/src/ingress/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,7 +1759,7 @@ impl SenderBuilder {

fn b64_decode(descr: &'static str, buf: &str) -> Result<Vec<u8>> {
Base64UrlUnpadded::decode_vec(buf)
.map_err(|b64_err| error::fmt!(AuthError, "Could not decode {}: {}", descr, b64_err))
.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))
}

fn parse_public_key(pub_key_x: &str, pub_key_y: &str) -> Result<Vec<u8>> {
Expand All @@ -1769,9 +1769,23 @@ fn parse_public_key(pub_key_x: &str, pub_key_y: &str) -> Result<Vec<u8>> {
// SEC 1 Uncompressed Octet-String-to-Elliptic-Curve-Point Encoding
let mut encoded = Vec::new();
encoded.push(4u8); // 0x04 magic byte that identifies this as uncompressed.
encoded.resize((32 - pub_key_x.len()) + 1, 0u8);
let pub_key_x_ken = pub_key_x.len();
if pub_key_x_ken > 32 {
return Err(error::fmt!(
AuthError,
"Misconfigured ILP authentication keys. Public key x is too long. Hint: Check the keys for a possible typo."
));
}
let pub_key_y_len = pub_key_y.len();
if pub_key_y_len > 32 {
return Err(error::fmt!(
AuthError,
"Misconfigured ILP authentication keys. Public key y is too long. Hint: Check the keys for a possible typo."
));
}
encoded.resize((32 - pub_key_x_ken) + 1, 0u8);
encoded.append(&mut pub_key_x);
encoded.resize((32 - pub_key_y.len()) + 1 + 32, 0u8);
encoded.resize((32 - pub_key_y_len) + 1 + 32, 0u8);
encoded.append(&mut pub_key_y);
Ok(encoded)
}
Expand All @@ -1786,7 +1800,13 @@ fn parse_key_pair(auth: &AuthParams) -> Result<EcdsaKeyPair> {
&public_key[..],
&system_random,
)
.map_err(|key_rejected| error::fmt!(AuthError, "Bad private key: {}", key_rejected))
.map_err(|key_rejected| {
error::fmt!(
AuthError,
"Misconfigured ILP authentication keys: {}. Hint: Check the keys for a possible typo.",
key_rejected
)
})
}

pub(crate) struct F64Serializer {
Expand Down
99 changes: 99 additions & 0 deletions questdb-rs/src/tests/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,105 @@ fn test_table_name_too_long() -> TestResult {
Ok(())
}

#[test]
fn test_auth_inconsistent_keys() -> TestResult {
test_bad_key("fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac",
"Misconfigured ILP authentication keys: InconsistentComponents. Hint: Check the keys for a possible typo."
)
}

#[test]
fn test_auth_bad_base64_private_key() -> TestResult {
test_bad_key(
"bad key", // d
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
"Misconfigured ILP authentication keys. Could not decode private authentication key: invalid Base64 encoding. Hint: Check the keys for a possible typo."
)
}

#[test]
fn test_auth_private_key_too_long() -> TestResult {
test_bad_key(
"ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU",
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // x
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
"Misconfigured ILP authentication keys: InvalidComponent. Hint: Check the keys for a possible typo."
)
}

#[test]
fn test_auth_public_key_x_too_long() -> TestResult {
test_bad_key(
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU",
"ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", // x
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
"Misconfigured ILP authentication keys. Public key x is too long. Hint: Check the keys for a possible typo."
)
}

#[test]
fn test_auth_public_key_y_too_long() -> TestResult {
test_bad_key(
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU",
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // x
"ZkxLWUVhb0ViOWxybjNua3dMREEtTV94bnVGT2RTdDl5MFo3X3ZXU0hMVWZMS1lFYW9FYjlscm4zbmt3TERBLU1feG51Rk9kU3Q5eTBaN192V1NITFU", // y
"Misconfigured ILP authentication keys. Public key y is too long. Hint: Check the keys for a possible typo."
)
}

#[test]
fn test_auth_bad_base64_public_key_x() -> TestResult {
test_bad_key(
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d
"bad base64 encoding", // x
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // y
"Misconfigured ILP authentication keys. Could not decode public key x: invalid Base64 encoding. Hint: Check the keys for a possible typo."
)
}

#[test]
fn test_auth_bad_base64_public_key_y() -> TestResult {
test_bad_key(
"fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU", // d
"Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac", // x
"bad base64 encoding", // y
"Misconfigured ILP authentication keys. Could not decode public key y: invalid Base64 encoding. Hint: Check the keys for a possible typo."
)
}

fn test_bad_key(
priv_key: &str,
pub_key_x: &str,
pub_key_y: &str,
expected_error_msg: &str,
) -> TestResult {
let server = MockServer::new()?;
let lsb = server
.lsb()
.auth("testUser1", priv_key, pub_key_x, pub_key_y);
let sender = lsb.connect();

match sender {
Ok(_) => panic!("Expected an error due to bad key, but connect succeeded."),
Err(err) => {
assert_eq!(
err.code(),
ErrorCode::AuthError,
"Expected an ErrorCode::AuthError"
);
assert_eq!(
err.msg(),
expected_error_msg,
"Error message did not match expected message."
);
}
}
Ok(())
}

#[test]
fn test_timestamp_overloads() -> TestResult {
let tbl_name = TableName::new("tbl_name")?;
Expand Down
1 change: 0 additions & 1 deletion system_test/fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ def start(self):
'-Debug',
'-XX:+UnlockExperimentalVMOptions',
'-XX:+AlwaysPreTouch',
'-XX:+UseParallelOldGC',
'-p', str(self._root_dir / 'bin' / 'questdb.jar'),
'-m', 'io.questdb/io.questdb.ServerMain',
'-d', str(self._data_dir)]
Expand Down
4 changes: 2 additions & 2 deletions system_test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def ns_to_qdb_date(at_ts_ns):
# We first need to match QuestDB's internal microsecond resolution.
at_ts_us = int(at_ts_ns / 1000.0)
at_ts_sec = at_ts_us / 1000000.0
at_td = datetime.datetime.fromtimestamp(at_ts_sec)
at_td = datetime.datetime.utcfromtimestamp(at_ts_sec)
return at_td.isoformat() + 'Z'


Expand Down Expand Up @@ -568,7 +568,7 @@ def test_malformed_auth1(self):

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

def test_malformed_auth2(self):
Expand Down