Skip to content

egov-malware-detection: add Azure Blob Storage support - #1376

Open
LataNaik wants to merge 1 commit into
egovernments:masterfrom
LataNaik:malware-detection-azure-blob-support
Open

egov-malware-detection: add Azure Blob Storage support#1376
LataNaik wants to merge 1 commit into
egovernments:masterfrom
LataNaik:malware-detection-azure-blob-support

Conversation

@LataNaik

@LataNaik LataNaik commented Jul 15, 2026

Copy link
Copy Markdown

Summary

  • egov-malware-detection currently only supports MinIO/S3 (io.minio.MinioClient) and explicitly rejects AzureBlobStorage as a file source (FileRetrievalService.validateFileSource), unlike egov-filestore which already supports both backends. This leaves Azure-based DIGIT deployments unable to run malware scanning at all - the app fails at scan time (or, if MINIO_URL is malformed, at Spring context startup).
  • Adds a StorageClient abstraction (mirroring egov-filestore's CloudFilesManager pattern) with two implementations selected via config flags:
    • MinioStorageClient - existing MinIO/S3 behavior, unchanged
    • AzureBlobStorageClient - new, using com.microsoft.azure:azure-storage (same SDK/version as egov-filestore), driven by isAzureStorageEnabled + azure.accountName/azure.accountKey (same property names as filestore, so the same secret can be reused)
  • FileRetrievalService and QuarantineService now depend on StorageClient instead of MinioClient directly.
  • Fixes a latent bug in MinioClientConfig: its @ConditionalOnProperty(value = "isS3Enabled", havingValue = "true", matchIfMissing = true) meant the Minio bean was built even when isS3Enabled was unset, with no way to actually disable it in favor of another backend. It's now @ConditionalOnExpression("${isS3Enabled:true} and !${isAzureStorageEnabled:false}"), ensuring exactly one storage client is ever active.

Config additions

isAzureStorageEnabled=false
azure.defaultEndpointsProtocol=https
azure.accountName=${AZURE_ACCOUNTNAME:}
azure.accountKey=${AZURE_ACCOUNTKEY:}

Container names reuse the existing fixed.bucketname / quarantine.bucketname properties for both backends.

Test plan

  • mvn compile passes (verified locally)
  • Deploy with isAzureStorageEnabled=true against a real Azure Storage account and confirm scan requests with fileSource=AzureBlobStorage are retrieved, scanned, and quarantined correctly
  • Confirm existing MinIO/S3 environments are unaffected (isS3Enabled=true, isAzureStorageEnabled unset)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Azure Blob Storage support for malware detection file retrieval, quarantine, uploads, and deletions.
    • Added configuration options to enable Azure storage and provide account credentials.
    • Added automatic selection between Azure Blob Storage and MinIO based on configuration.
  • Bug Fixes

    • Improved storage source handling so Azure-backed files are accepted and processed correctly.

The service only supported MinIO/S3 (io.minio.MinioClient) and explicitly
rejected AzureBlobStorage as a file source, unlike egov-filestore which
already supports both backends. This left Azure-based deployments unable
to run malware scanning at all.

Introduces a StorageClient abstraction (mirroring egov-filestore's
CloudFilesManager pattern) with MinioStorageClient and AzureBlobStorageClient
implementations, selected via isS3Enabled/isAzureStorageEnabled -
FileRetrievalService and QuarantineService now depend on the interface
instead of MinioClient directly.

Also fixes MinioClientConfig's bean condition, which previously defaulted
to enabled (matchIfMissing=true) regardless of the Azure flag, so both
clients could never be selected correctly at once.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 611be715-f4d9-46ee-b4d5-1bd0cc5bc1b8

📥 Commits

Reviewing files that changed from the base of the PR and between e22c7c5 and ea21907.

📒 Files selected for processing (11)
  • core-services/egov-malware-detection/pom.xml
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/config/AzureBlobConfig.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/config/MalwareDetectionConfig.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/config/MinioClientConfig.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/service/QuarantineService.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/AzureBlobStorageClient.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/MinioStorageClient.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/StorageClient.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/StorageObjectMetadata.java
  • core-services/egov-malware-detection/src/main/resources/application.properties
 _______________________________
< When in doubt, review it out. >
 -------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The malware detection service adds Azure Blob Storage support, introduces a shared StorageClient abstraction, provides Azure and MinIO implementations, and updates file retrieval and quarantine workflows to use the abstraction.

Changes

Storage backend abstraction

Layer / File(s) Summary
Storage contract and Azure configuration
core-services/egov-malware-detection/pom.xml, core-services/egov-malware-detection/src/main/java/org/egov/malware/{config,storage}/*, core-services/egov-malware-detection/src/main/resources/application.properties
Azure Storage configuration, Maven dependency declarations, Azure client initialization, StorageClient, and StorageObjectMetadata are added.
Selectable storage implementations
core-services/egov-malware-detection/src/main/java/org/egov/malware/config/MinioClientConfig.java, core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/*
Azure Blob and MinIO services implement shared storage operations, with MinIO disabled when Azure storage is enabled.
Malware service storage integration
core-services/egov-malware-detection/src/main/java/org/egov/malware/service/{FileRetrievalService,QuarantineService}.java
File retrieval and quarantine operations use StorageClient for object metadata, streams, uploads, deletions, bucket management, and existence checks.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FileRetrievalService
  participant StorageClient
  participant AzureBlobStorageClient
  participant AzureBlobStorage
  FileRetrievalService->>StorageClient: request file metadata or content
  StorageClient->>AzureBlobStorageClient: delegate storage operation
  AzureBlobStorageClient->>AzureBlobStorage: access Azure blob
  AzureBlobStorage-->>FileRetrievalService: return metadata or stream
Loading

Suggested reviewers: ghanshyamrawat-egov, talele08

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding Azure Blob Storage support to egov-malware-detection.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java (1)

67-71: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Resource leak: Unclosed InputStream on exception.

The InputStream is manually closed after IOUtils.toByteArray(). If an exception occurs while reading the stream (e.g., a network error), the .close() method is bypassed, which leaks the underlying network connection to the storage backend. Please use a try-with-resources block to ensure the stream is always safely closed.

  • core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java#L67-L71: Wrap the storageClient.getObject call in a try-with-resources block.
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java#L191-L194: Wrap the storageClient.getObject call in a try-with-resources block.
💻 Proposed fixes

For fetchFile (Lines 67-71):

-            InputStream inputStream = storageClient.getObject(bucketName, objectPath);
-
-            // Read content into byte array for scanning
-            byte[] content = IOUtils.toByteArray(inputStream);
-            inputStream.close();
+            byte[] content;
+            try (InputStream inputStream = storageClient.getObject(bucketName, objectPath)) {
+                // Read content into byte array for scanning
+                content = IOUtils.toByteArray(inputStream);
+            }

For getFileContent (Lines 191-194):

-            InputStream inputStream = storageClient.getObject(config.getMinioBucketName(), filePath);
-            byte[] content = IOUtils.toByteArray(inputStream);
-            inputStream.close();
-            return content;
+            try (InputStream inputStream = storageClient.getObject(config.getMinioBucketName(), filePath)) {
+                return IOUtils.toByteArray(inputStream);
+            }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java`
around lines 67 - 71, Prevent stream leaks in both fetchFile and getFileContent
by wrapping each storageClient.getObject result in a try-with-resources block,
including the IOUtils.toByteArray processing inside the block, and remove the
manual close calls. Apply this at FileRetrievalService.java lines 67-71 and
191-194.
🧹 Nitpick comments (3)
core-services/egov-malware-detection/pom.xml (1)

93-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Plan a migration to the modern Azure SDK
This module still depends on the legacy com.microsoft.azure:azure-storage SDK. If it can diverge from egov-filestore, migrating to com.azure:azure-storage-blob would improve long-term support and maintainability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-services/egov-malware-detection/pom.xml` around lines 93 - 99, Plan and
implement migration of the Azure Blob Storage dependency in the module’s pom
configuration from legacy com.microsoft.azure:azure-storage to modern
com.azure:azure-storage-blob, updating the version property and all dependent
code or configuration as needed. Verify behavior remains aligned with
egov-filestore, and remove the legacy dependency once migration is complete.
core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/AzureBlobStorageClient.java (1)

46-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Remove redundant container creation check to improve upload performance.

Calling container.createIfNotExists(...) on every putObject invocation introduces unnecessary network overhead (I/O latency) for each upload. The StorageClient contract already manages bucket creation explicitly via makeBucket() (which callers like QuarantineService use beforehand). Removing this check improves performance and aligns the Azure implementation with the MinIO client, which assumes the bucket already exists.

⚡ Proposed performance optimization
     `@Override`
     public void putObject(String bucket, String objectPath, InputStream content, long contentLength, String contentType) throws Exception {
         CloudBlobContainer container = getContainer(bucket);
-        container.createIfNotExists(BlobContainerPublicAccessType.OFF, new BlobRequestOptions(), new OperationContext());
         CloudBlockBlob blob = container.getBlockBlobReference(objectPath);
         if (contentType != null) {
             blob.getProperties().setContentType(contentType);
         }
         blob.upload(content, contentLength);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/AzureBlobStorageClient.java`
around lines 46 - 55, Remove the container.createIfNotExists call from
AzureBlobStorageClient.putObject, leaving bucket/container provisioning to
makeBucket() and preserving the existing blob reference, content type, and
upload flow.
core-services/egov-malware-detection/src/main/java/org/egov/malware/service/QuarantineService.java (1)

112-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider renaming minioBucketName for clarity.

Since the service is now storage-agnostic and supports Azure Blob Storage, relying on config.getMinioBucketName() (which maps to ${fixed.bucketname}) is slightly misleading. Consider renaming this configuration property field in MalwareDetectionConfig (and its usages) to something like getStorageBucketName() or getFixedBucketName() as an optional cleanup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@core-services/egov-malware-detection/src/main/java/org/egov/malware/service/QuarantineService.java`
around lines 112 - 114, Rename the storage bucket configuration accessor from
getMinioBucketName to a storage-agnostic name such as getStorageBucketName,
updating its field definition in MalwareDetectionConfig and every usage
including deleteOriginalFile. Preserve the existing ${fixed.bucketname}
configuration mapping and bucket-selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java`:
- Around line 67-71: Prevent stream leaks in both fetchFile and getFileContent
by wrapping each storageClient.getObject result in a try-with-resources block,
including the IOUtils.toByteArray processing inside the block, and remove the
manual close calls. Apply this at FileRetrievalService.java lines 67-71 and
191-194.

---

Nitpick comments:
In `@core-services/egov-malware-detection/pom.xml`:
- Around line 93-99: Plan and implement migration of the Azure Blob Storage
dependency in the module’s pom configuration from legacy
com.microsoft.azure:azure-storage to modern com.azure:azure-storage-blob,
updating the version property and all dependent code or configuration as needed.
Verify behavior remains aligned with egov-filestore, and remove the legacy
dependency once migration is complete.

In
`@core-services/egov-malware-detection/src/main/java/org/egov/malware/service/QuarantineService.java`:
- Around line 112-114: Rename the storage bucket configuration accessor from
getMinioBucketName to a storage-agnostic name such as getStorageBucketName,
updating its field definition in MalwareDetectionConfig and every usage
including deleteOriginalFile. Preserve the existing ${fixed.bucketname}
configuration mapping and bucket-selection behavior.

In
`@core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/AzureBlobStorageClient.java`:
- Around line 46-55: Remove the container.createIfNotExists call from
AzureBlobStorageClient.putObject, leaving bucket/container provisioning to
makeBucket() and preserving the existing blob reference, content type, and
upload flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 611be715-f4d9-46ee-b4d5-1bd0cc5bc1b8

📥 Commits

Reviewing files that changed from the base of the PR and between e22c7c5 and ea21907.

📒 Files selected for processing (11)
  • core-services/egov-malware-detection/pom.xml
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/config/AzureBlobConfig.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/config/MalwareDetectionConfig.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/config/MinioClientConfig.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/service/FileRetrievalService.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/service/QuarantineService.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/AzureBlobStorageClient.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/MinioStorageClient.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/StorageClient.java
  • core-services/egov-malware-detection/src/main/java/org/egov/malware/storage/StorageObjectMetadata.java
  • core-services/egov-malware-detection/src/main/resources/application.properties

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