test(sms): harden S3 adapter secret-redaction + coverage (review follow-up)
This commit is contained in:
+11
-5
@@ -117,6 +117,12 @@ public sealed class SmsNotificationDeliveryAdapter : INotificationDeliveryAdapte
|
||||
}
|
||||
|
||||
var authToken = smsConfig.AuthToken!;
|
||||
// Defense-in-depth: build the full Basic-auth credential string so that BOTH
|
||||
// the bare AuthToken AND the "AccountSid:AuthToken" composite are guaranteed
|
||||
// scrubbed from any returned / logged error. CredentialRedactor.Scrub redacts
|
||||
// the whole string it is given AND its last colon-separated component (when
|
||||
// >= MinSecretLength), so one call with the composite covers both shapes.
|
||||
var redactSecret = $"{smsConfig.AccountSid}:{authToken}";
|
||||
var body = ComposeBody(notification.Subject, notification.Body);
|
||||
|
||||
var baseUrl = string.IsNullOrWhiteSpace(smsConfig.ApiBaseUrl)
|
||||
@@ -147,7 +153,7 @@ public sealed class SmsNotificationDeliveryAdapter : INotificationDeliveryAdapte
|
||||
|
||||
var attempt = await SendOneAsync(
|
||||
httpClient, requestUri, authHeader, smsConfig, hasMessagingService,
|
||||
phone, body, timeoutSeconds, authToken, cancellationToken);
|
||||
phone, body, timeoutSeconds, redactSecret, cancellationToken);
|
||||
|
||||
switch (attempt.Class)
|
||||
{
|
||||
@@ -180,7 +186,7 @@ public sealed class SmsNotificationDeliveryAdapter : INotificationDeliveryAdapte
|
||||
string toNumber,
|
||||
string body,
|
||||
int timeoutSeconds,
|
||||
string authToken,
|
||||
string redactSecret,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// Per-request timeout layered over the caller's token via a linked CTS, so a
|
||||
@@ -224,7 +230,7 @@ public sealed class SmsNotificationDeliveryAdapter : INotificationDeliveryAdapte
|
||||
var cls = SmsErrorClassifier.Classify(response.StatusCode);
|
||||
var detail = CredentialRedactor.Scrub(
|
||||
$"Twilio returned HTTP {(int)response.StatusCode} ({response.StatusCode}) for {toNumber}",
|
||||
authToken);
|
||||
redactSecret);
|
||||
|
||||
if (cls == SmsErrorClass.Transient)
|
||||
{
|
||||
@@ -250,7 +256,7 @@ public sealed class SmsNotificationDeliveryAdapter : INotificationDeliveryAdapte
|
||||
{
|
||||
var detail = CredentialRedactor.Scrub(
|
||||
$"SMS transport failure for {toNumber} ({ex.GetType().Name}): {ex.Message}",
|
||||
authToken);
|
||||
redactSecret);
|
||||
_logger.LogWarning(
|
||||
"Transient SMS failure delivering to {Recipient} ({ExceptionType}): {Detail}",
|
||||
toNumber, ex.GetType().Name, detail);
|
||||
@@ -263,7 +269,7 @@ public sealed class SmsNotificationDeliveryAdapter : INotificationDeliveryAdapte
|
||||
// stance for unclassified failures).
|
||||
var detail = CredentialRedactor.Scrub(
|
||||
$"SMS delivery failed for {toNumber} ({ex.GetType().Name}): {ex.Message}",
|
||||
authToken);
|
||||
redactSecret);
|
||||
_logger.LogError(
|
||||
"Unclassified SMS failure delivering to {Recipient} ({ExceptionType}): {Detail}",
|
||||
toNumber, ex.GetType().Name, detail);
|
||||
|
||||
Reference in New Issue
Block a user