Skip to content

feat(security): add AES-256-GCM encryption for sensitive data storage with backward compatibility#547

Open
hawk9821 wants to merge 1 commit into
spring-ai-alibaba:mainfrom
hawk9821:dev1
Open

feat(security): add AES-256-GCM encryption for sensitive data storage with backward compatibility#547
hawk9821 wants to merge 1 commit into
spring-ai-alibaba:mainfrom
hawk9821:dev1

Conversation

@hawk9821

@hawk9821 hawk9821 commented Jun 15, 2026

Copy link
Copy Markdown

Describe what this PR does / why we need it

This PR adds AES-256-GCM encryption for sensitive data storage (datasource passwords, API keys, proxy passwords) to eliminate plaintext credential storage security risk.

The system currently stores sensitive information in plaintext in the database, which poses a security risk if the database is compromised. This PR introduces a transparent encryption layer that:

  • Encrypts sensitive fields before database writes
  • Decrypts sensitive fields after database reads
  • Maintains full backward compatibility with existing unencrypted data

Does this pull request fix one issue?

NONE

Describe how you did it

  1. CryptoUtil: New utility class implementing AES-256-GCM encryption with:

    • encrypt() / decrypt() for standard operations
    • decryptOrReturn() for transparent backward compatibility (auto-detects encrypted vs plaintext)
    • isEncrypted() heuristic check using Base64 + GCM structure validation
    • main() method for CLI key generation
  2. EncryptionProperties: Spring @ConfigurationProperties class binding spring.ai.alibaba.data-agent.encrypt-key from environment variable DATA_AGENT_ENCRYPT_KEY

  3. Service Layer Integration:

    • DatasourceServiceImpl: encrypts password/connectionUrl on create/update, decrypts on read
    • ModelConfigDataServiceImpl: encrypts apiKey/proxyPassword on add/update, decrypts on read
  4. Backward Compatibility: Uses decryptOrReturn() which:

    • Returns decrypted value if data is encrypted
    • Returns original value if data is plaintext (legacy)
    • Skips entirely if encryption key is not configured

Describe how to verify it

  1. Unit Tests:

    mvn -B -pl data-agent-management -Dtest="CryptoUtilTest,DatasourceServiceImplTest,ModelConfigDataServiceImplTest" test

    All 70 tests pass, including 27 CryptoUtil tests covering encryption, decryption, backward compatibility, and edge cases.

  2. Manual Verification:

    • Start application without DATA_AGENT_ENCRYPT_KEY → system works as before (plaintext)
    • Set DATA_AGENT_ENCRYPT_KEY and create datasource → verify password is encrypted in database
    • Edit datasource → verify password is decrypted correctly in UI
    • Restart application → verify existing data still works
  3. Key Generation:

    openssl rand -base64 32

Special notes for reviews

  • No data migration required: Existing plaintext data remains readable. New data is encrypted when key is configured. Historical data is gradually encrypted as it gets updated.
  • Zero-impact upgrade: If encrypt-key is not configured, encryption is completely disabled and behavior is identical to before.
  • Key management: Once configured, the encryption key should not be changed. Lost key = lost data. Document key backup procedures for production.
  • Protected fields: datasource.password, datasource.connection_url, model_config.api_key, model_config.proxy_password

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.

1 participant