Skip to content
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

Feature/add sensitive metadata #414

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

gmorales96
Copy link
Contributor

@gmorales96 gmorales96 commented Jan 28, 2025

Description

Added LogConfig to mark sensitive fields in logs, and introduced the JwtToken response model for /token

Changes

  • Dependency Update: Upgraded to the latest version of cuenca-validations, which now includes the LogConfig class for marking sensitive fields in logs.
  • Sensitive Data Annotation: Sensitive fields across the project have been updated to use the LogConfig class, ensuring that they are properly masked in logs.
  • New Response Model: Added the JwtToken class, a response model for the /token endpoint, where sensitive fields are explicitly marked using LogConfig.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced JwtToken resource for generating authentication tokens.
    • Added new id field to the UserLogin class for enhanced security.
  • Improvements

    • Enhanced sensitive data logging for various resources, including ApiKey, Otp, Session, and Card.
    • Updated handling of sensitive attributes with metadata across multiple classes.
  • Dependency Updates

    • Updated cuenca-validations package to development version 2.0.5.dev5.
  • Version

    • Bumped library version to 2.0.2.

Copy link

coderabbitai bot commented Jan 28, 2025

Walkthrough

This pull request introduces the JwtToken resource to the Cuenca library, adding the JwtToken class in cuenca/resources/jwt_tokens.py. The JwtToken is included in the __all__ lists of both cuenca/__init__.py and cuenca/resources/__init__.py, making it part of the public API and accessible for import. Modifications to existing classes, such as ApiKey, LoginToken, Otp, and Session, involve updating sensitive attributes to use the Annotated type with masking configurations. The version number is updated to 2.0.2, and the cuenca-validations package version is changed to 2.0.5.dev5. Additionally, a new test file tests/resources/test_jwt_tokens.py is created to validate the functionality of JWT token creation and handling.

Possibly related PRs

  • proper type annotation #409: The changes in this PR involve the addition of the JwtToken entity to the __all__ list in cuenca/__init__.py, which is directly related to the changes made in the main PR that also adds JwtToken to the public API of the module.
  • Update/pydantic v2 #411: This PR updates the cuenca-validations package, which may indirectly relate to the changes in the main PR as it involves the introduction of the JwtToken entity, potentially requiring compatibility with the updated validation framework.

Suggested reviewers

  • rogelioLpz
  • pachCode
  • felipao-mx
  • alexviquez

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e01cab2 and abfc35b.

📒 Files selected for processing (1)
  • cuenca/resources/cards.py (2 hunks)
🔇 Additional comments (2)
cuenca/resources/cards.py (2)

2-2: LGTM! Import changes are well-organized.

The new imports for Annotated and LogConfig are correctly placed and necessary for implementing the sensitive field masking feature.

Also applies to: 10-10


26-26: LGTM! Card number masking is properly configured.

The LogConfig annotation for the card number field is correctly implemented with industry-standard masking (showing only the last 4 digits).

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented Jan 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (f338ff4) to head (abfc35b).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #414   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           49        50    +1     
  Lines         1095      1118   +23     
=========================================
+ Hits          1095      1118   +23     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cuenca/__init__.py 100.00% <ø> (ø)
cuenca/resources/__init__.py 100.00% <100.00%> (ø)
cuenca/resources/api_keys.py 100.00% <100.00%> (ø)
cuenca/resources/cards.py 100.00% <100.00%> (ø)
cuenca/resources/jwt_tokens.py 100.00% <100.00%> (ø)
cuenca/resources/login_tokens.py 100.00% <100.00%> (ø)
cuenca/resources/otps.py 100.00% <100.00%> (ø)
cuenca/resources/sessions.py 100.00% <100.00%> (ø)
cuenca/resources/user_logins.py 100.00% <100.00%> (ø)
cuenca/version.py 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f338ff4...abfc35b. Read the comment docs.

@gmorales96 gmorales96 marked this pull request as ready for review January 28, 2025 17:36
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
cuenca/resources/otps.py (1)

Line range hint 15-19: Security: Remove sensitive data from example.

The example configuration shows a full secret value. Even though it's a dummy value, it's recommended to use a placeholder or masked value in examples to reinforce security best practices.

         'example': {
             'id': 'OTNEUInh69SuKXXmK95sROwQ',
-            'secret': 'somesecret',
+            'secret': '****',
         }
🧹 Nitpick comments (4)
tests/resources/test_jwt_tokens.py (1)

20-28: Enhance token security validation.

The test should include additional assertions to verify token security properties:

  1. Token format validation
  2. Token expiration
  3. Token length requirements
     jwt_token = JwtToken.create(session=session)
     assert jwt_token
     assert isinstance(jwt_token.token, str)
+    # Verify token format (e.g., JWT has three parts)
+    assert len(jwt_token.token.split('.')) == 3
+    # Verify token meets minimum length requirement
+    assert len(jwt_token.token) >= 100
+    # Verify token expiration exists and is in future
+    assert jwt_token.expires_at > datetime.datetime.now(datetime.timezone.utc)

Also consider using parameterized testing for different user scenarios.

cuenca/__init__.py (1)

45-45: Maintain alphabetical ordering in exports and imports.

The JwtToken additions should maintain the alphabetical ordering convention.

Move the entries to their correct alphabetical positions:

-    'JwtToken',
+    'JwtToken',  # Move after 'IdentityEvent' in both lists

Also applies to: 69-69

cuenca/resources/__init__.py (1)

41-41: Maintain alphabetical ordering in resource declarations.

The JwtToken additions should maintain the alphabetical ordering convention.

Move the entries to their correct alphabetical positions:

# In __all__
-    'JwtToken',
+    'JwtToken',  # Move after 'IdentityEvent'

# In imports
-from .jwt_tokens import JwtToken
+from .jwt_tokens import JwtToken  # Move after .identity_events

# In resource_classes
-    JwtToken,
+    JwtToken,  # Move after IdentityEvent

Also applies to: 63-63, 128-128

tests/resources/cassettes/test_jwt_tokens.yaml (1)

3-3: Enhance security of test credentials.

Using weak, hardcoded passwords in test fixtures can lead to security issues if accidentally used in production. Consider:

  1. Using environment variables for test credentials
  2. Using a stronger password pattern even in test environments
-    body: '{"password": "111111"}'
+    body: '{"password": "${TEST_USER_PASSWORD}"}'
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f338ff4 and b286db3.

📒 Files selected for processing (11)
  • cuenca/__init__.py (2 hunks)
  • cuenca/resources/__init__.py (3 hunks)
  • cuenca/resources/api_keys.py (2 hunks)
  • cuenca/resources/jwt_tokens.py (1 hunks)
  • cuenca/resources/login_tokens.py (2 hunks)
  • cuenca/resources/otps.py (2 hunks)
  • cuenca/resources/sessions.py (2 hunks)
  • cuenca/version.py (1 hunks)
  • requirements.txt (1 hunks)
  • tests/resources/cassettes/test_jwt_tokens.yaml (1 hunks)
  • tests/resources/test_jwt_tokens.py (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • cuenca/version.py
  • requirements.txt
🔇 Additional comments (8)
cuenca/resources/otps.py (1)

12-12: LGTM! Proper implementation of sensitive data handling.

The secret field is correctly marked as sensitive with appropriate logging restrictions.

cuenca/resources/login_tokens.py (2)

13-13: LGTM! Proper implementation of sensitive data handling.

The id field is correctly marked as sensitive with appropriate logging restrictions.


Line range hint 21-27: Verify token expiration handling.

The documentation mentions a 7-day expiration period, but there's no validation in the code to ensure this constraint.

✅ Verification successful

Token expiration is properly handled through JWT validation

The 7-day expiration mentioned in the documentation is enforced through the JWT layer, which includes proper expiration validation via is_expired property and get_expiration_date method. The actual expiration period is set by the backend during token creation, while the client-side JWT implementation ensures tokens are validated against their expiration before use.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for token expiration validation in the codebase
rg -A 5 "expires_at|expiration|valid_for" --type py

Length of output: 4772


Script:

#!/bin/bash
# Search for token creation implementation
ast-grep --pattern 'def _create($$$)' 

# Search for token creation with expiration or duration settings
rg -A 5 "token.*days|days.*token" --type py

Length of output: 488


Script:

#!/bin/bash
# View complete implementation of login_tokens.py
cat cuenca/resources/login_tokens.py

Length of output: 826


Script:

#!/bin/bash
# View Creatable base class implementation
cat cuenca/resources/base.py

Length of output: 5772

cuenca/resources/sessions.py (1)

15-15: LGTM! Proper implementation of sensitive data handling.

The id field is correctly marked as sensitive with appropriate logging restrictions.

cuenca/resources/jwt_tokens.py (1)

14-15: LGTM! Proper handling of sensitive data.

The sensitive fields id and token are correctly marked with Metadata(sensitive=True, log_chars=4), ensuring only the first 4 characters are logged.

cuenca/resources/api_keys.py (1)

15-15: LGTM! Proper handling of API key secret.

The secret field is correctly marked as sensitive with appropriate logging restrictions.

tests/resources/cassettes/test_jwt_tokens.yaml (2)

46-91: LGTM! Proper authentication flow implementation.

The login token generation follows security best practices:

  • Includes necessary authentication headers
  • Uses proper session context (X-Cuenca-LoginId)
  • Returns minimal required information

111-111: Protect sensitive JWT token data in test fixtures.

The response contains sensitive JWT token data that should be handled carefully:

  1. Consider masking or truncating the JWT token in test fixtures
  2. The token contains sensitive claims (sub, uid) that should be marked as sensitive metadata
  3. Consider using shorter expiration times in test environments

Run this script to check for other instances of exposed JWT tokens in test fixtures:

tests/resources/test_jwt_tokens.py Outdated Show resolved Hide resolved
cuenca/resources/sessions.py Show resolved Hide resolved
cuenca/resources/jwt_tokens.py Show resolved Hide resolved
cuenca/resources/jwt_tokens.py Outdated Show resolved Hide resolved
Copy link
Member

@felipao-mx felipao-mx left a comment

Choose a reason for hiding this comment

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

falta aplicar la configuración para los requests de login, sessions, cambio de contraseña y tarjetas,

cuenca/resources/otps.py Outdated Show resolved Hide resolved
tests/resources/test_jwt_tokens.py Outdated Show resolved Hide resolved
cuenca/resources/login_tokens.py Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
cuenca/resources/user_logins.py (1)

15-15: Consider adding field-level documentation.

While the field is documented in the model's example, consider adding a docstring or field description to explicitly document the masking behavior and purpose of the ID field.

-    id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
+    id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]  # Unique login identifier, masked except last 4 chars
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58bab31 and e01cab2.

📒 Files selected for processing (4)
  • cuenca/resources/jwt_tokens.py (1 hunks)
  • cuenca/resources/otps.py (2 hunks)
  • cuenca/resources/user_logins.py (2 hunks)
  • tests/resources/test_jwt_tokens.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/resources/test_jwt_tokens.py
  • cuenca/resources/otps.py
  • cuenca/resources/jwt_tokens.py
🔇 Additional comments (3)
cuenca/resources/user_logins.py (3)

2-2: LGTM! Necessary imports added for sensitive data handling.

The addition of Annotated and LogConfig imports supports the new sensitive field masking functionality.

Also applies to: 4-4


15-15: Verify consistent masking configuration across related models.

The masking configuration for the id field looks good, showing only the last 4 characters for security while maintaining usability.

Let's verify that similar ID fields across related models use consistent masking configurations:

✅ Verification successful

ID field masking configuration is consistent across related models ✓

All authentication-related resources (user_logins, sessions, login_tokens, jwt_tokens) use identical masking configuration showing only the last 4 characters of IDs.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other ID field declarations with LogConfig
ast-grep --pattern 'id: Annotated[$_, LogConfig($$$)]'

Length of output: 481


Line range hint 34-37: Review security implications of ID in headers.

The id field is used in the X-Cuenca-LoginId header. While the field itself is properly masked in logs, verify that:

  1. The header is used over HTTPS only
  2. The header is not exposed in any logging middleware

Let's check for any security-related configurations and header logging:

Also applies to: 45-48

✅ Verification successful

Security review completed: Implementation is secure

The X-Cuenca-LoginId header is properly protected:

  • HTTPS is strictly enforced in client.py
  • Headers are managed securely within the requests session
  • No logging middleware exposes the headers
  • Proper cleanup during logout
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for HTTPS enforcement
rg -l "https|ssl|tls" --type python

# Check for header logging in middleware
rg -l "middleware|logging.*header" --type python

Length of output: 150


Script:

#!/bin/bash
# Check for HTTPS/TLS enforcement and configurations
rg -l "https|ssl|tls|verify" --type py

# Check for middleware and header logging
rg -l "middleware|logging.*header|header.*log" --type py

# Search for specific header usage
rg "X-Cuenca-LoginId" --type py

Length of output: 1081


Script:

#!/bin/bash
# Check HTTP client implementation for security configurations
cat cuenca/http/client.py

# Look for any logging configurations related to headers
rg -A 5 "log.*header|header.*log" --type py

Length of output: 5314

@gmorales96 gmorales96 requested a review from felipao-mx January 31, 2025 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants