Skip to Content
Technical Articles
Author's profile photo Ajit Kumar Panda

CAP: Handling of Media Data with Malware Scanning

Media%20Data%20with%20Malware%20Scanning

Media Data with Malware Scanning

Introduction

During digital transformation, every business uses a diverse set of technologies to build application to digitize non-digital processes and operations. The “Cloud Application Programming Model” (CAP) offered by SAP can be used to develop enterprise-grade cloud services or applications and deploy on the SAP Business Technology Platform (BTP). You can learn more about CAP by visiting this page.

In almost every application, one or more business documents are uploaded. These documents or files need to be check for virus or other malware. SAP provides a service called ‘SAP Malware Scanning Service’ on BTP to scan business documents for malware.

In this blog post, we’ll look at how to create a cap application that allows users to upload files and check them for malware using the SAP Malware Scanning Service.

Develop and Deploy application

Often project templates are used to generate the skeleton of a CAP application. But this time we shall see how we can create an application using command line. If you don’t want to follow step by step, you can find the complete project here.

  • If you are using local set up instead of SAP Business Application Studio (BAS), then install cap development kit:  npm install -g @sap/cds-dk
    use cds –help command to verify installation is successful. Also install rimraf package which is used later using npm install -g rimraf
  • Create a project using cds init cap-media-malware command where cap-media-malware is the project name. It creates the project layout with a project descriptor package.json, folder app for UI content, folder db for database related artifacts and folder srv for service related content. You can modify your project description in package.json descriptor file.
  • Install the dependencies using npm install command
  • Make sure you are on cap-media-malware folder in terminal. Then create a file using command touch db/schema.cds and fill with following content:
    namespace cap.media.db;
    using {cuid} from '@sap/cds/common';
    
    entity MediaFiles : cuid {
        @Core.MediaType   : type
        content : LargeBinary;
        @Core.IsMediaType : true
        type    : String;
        filename: String;    }​

    Note-1, cuid aspect is used to add universally unique primary key to the entity.
    Note-2, MediaFiles entity needs to be annotated with following annotations to indicate that a field contains media data.
          @Core.MediaType: Indicates that the element contains media data
          @Core.IsMediaType: Indicates that the element contains a MIME type

  • Create service definition file using touch srv/service.cds command and add following content
    using { cap.media.db as db } from '../db/schema';
    
    service MediaService {
        entity MediaFiles as projection on db.MediaFiles;
    }​
  • SAP Malware Scanning Service provides REST based apis to scan document for malware and api definition is described in OpenAPI Hence, we will use OpenAPI client generator feature of SAP Cloud SDK for Javascript to consume service apis. You can find more information about SAP Cloud SDK here.
  • Go to SAP Malware Scanning Service on API Business Hub, download OpenAPI specification from here and save as MalwareScanAPI.json.
  • Create folders to keep api specifications and api clients using following command
    mkdir srv/resources
    mkdir srv/resources/api-specs
    mkdir srv/resources/api-clients
    Copy MalwareScanAPI.json file downloaded in previous step into api-specs folder.
  • Install SAP Cloud SDK OpenAPI code generator dependencies using following commands:
    npm install @sap-cloud-sdk/openapi-generator –save –D
    npm install @sap-cloud-sdk/openapi –save
  • Generate api client for Malware Scanning Service based on the imported specification using below command:
    npx openapi-generator -t -i srv/resources/api-specs/MalwareScanAPI.json -o srv/resources/api-clients
  • Now let’s add logic in service implementation to scan documents before it is updated in db.
    Create service implementation using touch srv/service.js and copy following code:

    const cds = require("@sap/cds");
    const apiMalwareScan = require("./resources/api-clients/MalwareScanAPI/default-api")
    const { PassThrough } = require('stream')
    
    module.exports = cds.service.impl(async function (srv) {
      const { MediaFiles } = this.entities;
    
      srv.on('PUT', MediaFiles, async (req, next) => {
        const url = req._.req.path, chunks = [];
        if (url.includes('content')) {
    
          let mediaMalwareScanner = function (req) {
            let malwarescan = new Promise(function (resolve, reject) {
              req.data.content.on('data', chunk => chunks.push(chunk));
              req.data.content.on('end', async (req) => {
                let body = Buffer.concat(chunks).toString('binary');
                let requestBuilder = await apiMalwareScan.DefaultApi.createScan(body);
                requestBuilder.addCustomHeaders({ 'Content-Type': 'application/octet-stream' });
                requestBuilder.addCustomHeaders({ 'Accept': 'application/json' });
                let response = await requestBuilder.skipCsrfTokenFetching().execute({ destinationName: 'cap-media-malwarescanner-dest' });
                resolve(response.malwareDetected);
              });
            });
            return malwarescan;
          }
    
          let isMalwareDetected = await mediaMalwareScanner(req);
          if (isMalwareDetected) {
            req.error(500, 'Malware Detected');
          } else {
            req.data.content = new PassThrough();
            req.data.content.push(Buffer.concat(chunks));
            req.data.content.push(null);
            next()
          }
    
        } else {
          return next();
        }
    
      });
    })​

    Note-1, mediaMalwareScanner function is used to call malware scanning service api and determine whether the document contains malware or not.

    Note-2, SAP Cloud SDK requires destination service and xsuaa (SAP Authorization and Trust Management Service) service instance to execute api.

    Note-3, cap-media-malwarescanner-dest destination is used for api call which can be created manually on SAP BTP cockpit or programmatically during deployment which is explained in later part of the blog.

  • Now Let’s prepare the application to deploy it on SAP BTP using MTA (Multi-Target Application) deployment approach.
    add mta deployment descriptor using command: cds add mta
  • Add Hana Cloud and XSUAA configuration to the project using following command:
    cds add hana
    cds add xsuaa
    Install dependencies using npm install
  • Add destination service as a resource in deployment descriptor mta.yaml as shown below:
      - name: cap-media-malware-destination
        type: org.cloudfoundry.managed-service
        parameters:
          service: destination
          service-name: cap-media-malware-destination
          service-plan: lite​
  • Also add destination service resource as a dependency in requires section of cap service module cap-media-malware-srv
    - name: cap-media-malware-destination​
  • Add Malware Scanner Service as a resource to the deployment descriptor mta.yaml
      - name: cap-media-malwarescanner
        type: org.cloudfoundry.managed-service
        parameters:
          service: malware-scanner
          service-name: cap-media-malwarescanner
          service-plan: clamav​
  • Add following module of type com.sap.application.content [Generic Application Content Deployment protocol (GACD)] to create the destination cap-media-malwarescanner-dest required to execute malware scanner api.
    More information regarding GACD can be found at this page.

      - name: cap-media-destinations
        type: com.sap.application.content
        requires:
          - name: cap-media-malware-destination
            parameters:
              content-target: true
          - name: cap-media-malwarescanner
            parameters:
              service-key:
                name: malwarescanner-key
        parameters:
          content:
            subaccount:
              existing_destinations_policy: update
              destinations:
                - Name: cap-media-malwarescanner-dest
                  ServiceInstanceName: cap-media-malwarescanner
                  ServiceKeyName: malwarescanner-key
        build-parameters:
          no-source: true​
  • Add following scripts to project descriptor package.json:
    undeploy“: “cf undeploy cap-media-malware –delete-services –delete-service-keys“,
    build“: “rimraf resources mta_archives && mbt build –mtar archive“,
    deploy“: “cf deploy mta_archives/archive.mtar –retries 1
  • Before deployment of the application, make sure you have a multi-environment subaccount, hana cloud service is running and have entitlement of SAP Malware Scanning service
    To verify these pre-requisites, you can follow below pages:
    Getting Started with an Enterprise Account in the Cloud Foundry Environment
    Managing Entitlements and Quotas Using the Cockpit
  • Build your project using command: npm run build
  • Login to your multi-environment subaccount using following commands:
    cf api <Cloud Foundry API Endpoint>
    cf login
  • Deploy your project using command: npm run deploy
    Note down the cap service url from terminal as shown below:

Test the Application

  • Create 2 files test.txt and malware.test.txt under srv folder out of which malware.test.txt contains malware. You can also download these sample files from here.
  • Copy the test file from here: test.http
  • Read environment variables and update test.http file with with xsuaa information:copy environment variables: cf env cap-media-malware-srv > default-env.jsonupdate test.http file
    @xsuaaHostname = <<credentials.url – field from xsuaa section of default-env.json>>
    @xsuaaClient = <<credentials.clientid – field from xsuaa section of default-env.json>>
    @xsuaaSecret = <<credentials.clientsecret – field from xsuaa section of default-env.json>>
    @host = <<cap service url after deployment>>

  • Now send requests sequentially from test.http file
  • Upon sending Request-3 Update filw with Malware, service return error with message ‘Malware Detected’
  • Note that, to upload document in cap application, 2 api calls are required. First a POST call to create an entry in Media Data entity and Second a PUT call to upload the actual document content.

Reference Blog:Stay Secure with SAP Malware Scanning on SAP BTP

Conclusion 

Using CAP, you can develop business applications to upload documents and integrate SAP Malware Scanning Service to scan those documents for malware.

More information about cloud application programming model can be found here. You can follow my profile to get notification of the next blog post on CAP. Please feel free to provide any feedback you have in the comments section below and ask your questions about the topic in sap community using this link.

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Yogananda Muthaiah
      Yogananda Muthaiah

      Ajit Kumar Panda

      Nice blog ! Many of them may like to know or difficult to find the steps for Malware Scanning Services, so if you can add few screenshots from SAP BTP on how to create steps for service instance and service key for malware scanning.

      Author's profile photo Ajit Kumar Panda
      Ajit Kumar Panda
      Blog Post Author

      Hi Yoga,
      Thanks for reading the blog. In this use case, malware scanning service will be created on deployment of application automatically.
      If you want to create malware scanning service instance manually using SAP BTP cockpit, the steps remain same as other service.  🙂
      Thanks, Ajit

      Author's profile photo Yogananda Muthaiah
      Yogananda Muthaiah

      Ajit Kumar Panda

      I am been using malware scanning for other use cases but many others like partners/customers would be finding on how to enable the service as independently. As suggestion, it would be better to add it up.

      Author's profile photo Matthias Buehl
      Matthias Buehl

      There is a separate blog for the  malware scanner here. perhaps this helps.

      Author's profile photo Ajit Kumar Panda
      Ajit Kumar Panda
      Blog Post Author

      Thanks Matthias Buehl. I have added the blog as reference blog 🙂

      Author's profile photo Martin Frick
      Martin Frick

      Great content! Thanks for sharing Ajit!

      Author's profile photo Anirban Majumdar
      Anirban Majumdar

      Great article! Thank you, Ajit!