-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Recorder] Central sanitizers (#29331)
### Packages impacted by this PR `@azure-tools/test-recorder` - Adding the central sanitizers ### Issues associated with this PR **References:** - Azure/azure-sdk-for-java#39700 - Azure/azure-sdk-for-python#35196 - And the patterns found ### Describe the problem that is addressed by this PR - Introducing fallback sanitizers into the test recorder to handle potential secret leaks. - The new sanitizers are designed to work in conjunction with the existing `handleEnvSetup` mechanism and the fake secrets. - The sanitizers include: - `BodyKeySanitizers` that redact sensitive information in the JSON body of the requests. - `FindReplaceSanitizers` that redact sensitive information based on provided regular expressions. - `HeaderSanitizers` that redact sensitive information in the headers of the requests. ## Tests I've ran the tests for the following and they work fine - [x] recorder - [x] template - [x] notification-hubs (needed to make a few fixes for browser tests in notification hubs which do feel like unrelated to this PR, but fixing them here anyway.) ___Currently only these three packages depend on recorder v4.___ ## Future work (future PRs) - Once this PR is merged, cherrypick the commit and release a hotfix 3.x version - Add more tests at some point
- Loading branch information
1 parent
3ca26ee
commit b047b37
Showing
7 changed files
with
171 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# Used in most samples. Retrieve these values from a Azure Notification Hub in the Azure Portal. | ||
NOTIFICATIONHUBS_CONNECTION_STRING="<connection string>" | ||
NOTIFICATION_HUB_CONNECTION_STRING="<connection string>" | ||
|
||
# Used in most samples. Provide the name of a Notification Hub within a namespace. | ||
NOTIFICATION_HUB_NAME="<hub name>" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
sdk/test-utils/recorder/src/utils/fallbackSanitizers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
import { HttpClient } from "@azure/core-rest-pipeline"; | ||
import { addSanitizers } from "../sanitizer.js"; | ||
import { BodyKeySanitizer, FindReplaceSanitizer, HeaderSanitizer } from "./utils.js"; | ||
|
||
const JSON_BODY_KEYS_TO_REDACT = [ | ||
"authHeader", | ||
"accountKey", | ||
"accessToken", | ||
"accountName", | ||
"applicationId", | ||
"apiKey", | ||
"client_secret", | ||
"connectionString", | ||
"url", | ||
"host", | ||
"password", | ||
"userName", | ||
"applicationSecret", | ||
"aliasSecondaryConnectionString", | ||
"aliasPrimaryConnectionString", | ||
"primaryKey", | ||
"secondaryKey", | ||
"adminPassword.value", | ||
"administratorLoginPassword", | ||
"runAsPassword", | ||
"adminPassword", | ||
"accessSAS", | ||
"WEBSITE_AUTH_ENCRYPTION_KEY", | ||
"decryptionKey", | ||
"primaryMasterKey", | ||
"primaryReadonlyMasterKey", | ||
"secondaryMasterKey", | ||
"secondaryReadonlyMasterKey", | ||
"certificatePassword", | ||
"clientSecret", | ||
"keyVaultClientSecret", | ||
"authHeader", | ||
"httpHeader", | ||
"encryptedCredential", | ||
"appkey", | ||
"functionKey", | ||
"atlasKafkaPrimaryEndpoint", | ||
"atlasKafkaSecondaryEndpoint", | ||
"certificatePassword", | ||
"storageAccountPrimaryKey", | ||
"privateKey", | ||
"fencingClientPassword", | ||
"acrToken", | ||
"scriptUrlSasToken", | ||
"azureBlobSource.containerUrl", | ||
"properties.DOCKER_REGISTRY_SEVER_PASSWORD", | ||
]; | ||
|
||
const BODY_REGEXES_TO_REDACT = [ | ||
"(?:(Password|User ID)=)(?<secret>.*)(?:;)", | ||
"client_secret=(?<secret>[^&]+)", | ||
"<PrimaryKey>(?<secret>.*?)</PrimaryKey>", | ||
"<SecondaryKey>(?<secret>.*?)</SecondaryKey>", | ||
"<UserDelegationKey>.*?<SignedOid>(?<secret>.*?)</SignedOid>.*?</UserDelegationKey>", | ||
"<UserDelegationKey>.*?<SignedTid>(?<secret>.*?)</SignedTid>.*?</UserDelegationKey>", | ||
"<UserDelegationKey>.*?<Value>(?<secret>.*?)</Value>.*?</UserDelegationKey>", | ||
'SharedAccessKey=(?<secret>[^;\\"]+)', | ||
'AccountKey=(?<secret>[^;\\"]+)', | ||
'accesskey=(?<secret>[^;\\"]+)', | ||
'AccessKey=(?<secret>[^;\\"]+)', | ||
'Secret=(?<secret>[^;\\"]+)', | ||
"access_token=(?<secret>.*?)(?=&|$)", | ||
"refresh_token=(?<secret>.*?)(?=&|$)", | ||
'(?:(sv|sig|se|srt|ss|sp)=)(?<secret>[^&\\"]*)', | ||
]; | ||
|
||
const URL_REGEX = "(?<=http://|https://)([^/?]+)"; | ||
|
||
const HEADER_KEYS_TO_REDACT = [ | ||
"Ocp-Apim-Subscription-Key", | ||
"api-key", | ||
"x-api-key", | ||
"subscription-key", | ||
"x-ms-encryption-key", | ||
"sshPassword", | ||
]; | ||
|
||
export async function fallbackSanitizers( | ||
httpClient: HttpClient, | ||
url: string, | ||
recordingId: string, | ||
): Promise<void> { | ||
const bodyKeySanitizers: BodyKeySanitizer[] = JSON_BODY_KEYS_TO_REDACT.map((prop) => ({ | ||
jsonPath: `$..${prop}`, // Handles the request body | ||
value: "REDACTED", | ||
})); | ||
|
||
const generalSanitizers: FindReplaceSanitizer[] = BODY_REGEXES_TO_REDACT.map((regex) => ({ | ||
value: "REDACTED", | ||
regex: true, | ||
groupForReplace: "secret", | ||
target: regex, | ||
})); | ||
|
||
const headerSanitizers: HeaderSanitizer[] = [ | ||
{ | ||
key: "Operation-location", | ||
groupForReplace: "secret", | ||
regex: true, | ||
target: URL_REGEX, | ||
value: "REDACTED", | ||
}, | ||
{ | ||
key: "ServiceBusDlqSupplementaryAuthorization", | ||
groupForReplace: "secret", | ||
regex: true, | ||
target: '(?:(sv|sig|se|srt|ss|sp)=)(?<secret>[^&\\"]+)', | ||
value: "REDACTED", | ||
}, | ||
{ | ||
key: "ServiceBusSupplementaryAuthorization", | ||
groupForReplace: "secret", | ||
regex: true, | ||
target: '(?:(sv|sig|se|srt|ss|sp)=)(?<secret>[^&\\"]+)', | ||
value: "REDACTED", | ||
}, | ||
]; | ||
|
||
const headersForRemoval: string[] = HEADER_KEYS_TO_REDACT; | ||
await addSanitizers(httpClient, url, recordingId, { | ||
bodyKeySanitizers, | ||
generalSanitizers, | ||
removeHeaderSanitizer: { headersForRemoval }, | ||
headerSanitizers, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters