Skip to content
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
3 changes: 2 additions & 1 deletion src/azure-cli-testsdk/azure/cli/testsdk/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
patch_progress_controller, patch_get_current_system_username)
from .exceptions import CliExecutionError
from .utilities import (find_recording_dir, StorageAccountKeyReplacer, GraphClientPasswordReplacer,
MSGraphClientPasswordReplacer, AADAuthRequestFilter)
MSGraphClientPasswordReplacer, AADAuthRequestFilter, EmailAddressReplacer)
from .reverse_dependency import get_dummy_cli

logger = logging.getLogger('azure.cli.testsdk')
Expand Down Expand Up @@ -93,6 +93,7 @@ def __init__(self, method_name, config_file=None, recording_name=None,
default_recording_processors = [
SubscriptionRecordingProcessor(MOCKED_SUBSCRIPTION_ID),
AADAuthRequestFilter(),
EmailAddressReplacer(),
LargeRequestBodyProcessor(),
LargeResponseBodyProcessor(),
DeploymentNameReplacer(),
Expand Down
24 changes: 24 additions & 0 deletions src/azure-cli-testsdk/azure/cli/testsdk/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# --------------------------------------------------------------------------------------------

import os
import re
from contextlib import contextmanager

from .scenario_tests import (create_random_name as create_random_name_base, RecordingProcessor)
Expand Down Expand Up @@ -210,6 +211,29 @@ def process_response(self, response):
return response


class EmailAddressReplacer(RecordingProcessor):
"""Replace email address like xxx@microsoft.com with test@example.com"""

EMAIL_REPLACEMENT = 'test@example.com'

def _replace_email_address(self, text):
pattern = r'[\w.%#+-]+[%40|@|_]microsoft.com'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any source for this regex?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source is me😂 Any issue with this pattern?

Copy link
Copy Markdown
Member

@jiasli jiasli Apr 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious how %#+- are chosen. Could you provide some examples? I understand there are email addresses like Isaac.Newton@microsoft.com which contain [\w.].

Copy link
Copy Markdown
Member Author

@evelyn-ys evelyn-ys Apr 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for example, v-zhangsan@microsoft.com contains -. But for %#+, I don't have any sample on top of my mind

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For test_microsoft.com#EXT#@AzureSDKTeam.onmicrosoft.com, this regex only replaces the test_microsoft.com part. Should we consider replacing the full string test_microsoft.com#EXT#@AzureSDKTeam.onmicrosoft.com to avoid showing the tenant domain too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I loose the regex to recognize all string in the format of xxx@xxx.xx, then test_microsoft.com#EXT#@AzureSDKTeam.onmicrosoft can be replaced, but there will be many mismatch for example ssh@10.172 and the recording file can't work.

I'm thinking that as long as the microsoft part is replaced, then the full string will be invalid so I restricted the pattern to recognize [@|%40|_]microsoft.com only

return re.sub(pattern, self.EMAIL_REPLACEMENT, text)

def process_request(self, request):
request.uri = self._replace_email_address(request.uri)
if request.body:
body = _byte_to_str(request.body)
request.body = self._replace_email_address(body)
return request

def process_response(self, response):
if response['body']['string']:
body = _byte_to_str(response['body']['string'])
response['body']['string'] = self._replace_email_address(body)
return response


class AADAuthRequestFilter(RecordingProcessor):
"""Remove oauth authentication requests and responses from recording.
This is derived from OAuthRequestResponsesFilter.
Expand Down
Loading