目录

DLP Service Development (ArkTS)

The Data Loss Prevention (DLP) service is a system solution provided to prevent leakage of sensitive data. It provides a file format called DLP. A DLP file consists of the original file in ciphertext and the authorization credential, and ".dlp" is added to the end of the original file name (including the file name extension), for example, test.docx.dlp.

A DLP file can be accessed only after successful device-cloud authentication (network connection required). The permissions for a DLP file include the following:

When an application accesses a DLP file, the system automatically installs a dual application, a copy based on the current application. Both can run at the same time without affecting each other. The dual application is running in a sandbox, which restricts external access to prevent data leakage. For simplicity, the dual application running in a sandbox is referred to as sandbox application. Each time a DLP file is opened, a sandbox application is generated. The sandbox applications are also isolated from each other. When an application is closed, its sandbox application will be automatically uninstalled and the temporary data generated in the sandbox directory will be cleared.

Normally, the application is unaware of the sandbox and accesses the file in plaintext, like accessing a common file. However, the DLP sandbox restricts the application from accessing external resources (such as the network, clipboard, screenshot capturing, screen recording, and Bluetooth). For better user experience, you need to adapt your application to service requirements. For example, for a read-only file, you'd better hide the Save button and disable automatic Internet access.

Sandbox Restrictions

The sandbox also restricts the permissions granted to the application based on the permission on the DLP file.

Application Permission Description Read-Only Edit/Full Control
ohos.permission.USE_BLUETOOTH Allows an application to use Bluetooth. Forbidden Forbidden
ohos.permission.INTERNET Allows an application to access the Internet. Forbidden Forbidden
ohos.permission.DISTRIBUTED_DATASYNC Allows an application to exchange user data (such as images, music, videos, and application data) with another device. Forbidden Forbidden
ohos.permission.WRITE_MEDIA Allows an application to read and write media files, such as videos, audio clips, and images. Forbidden Allowed
ohos.permission.NFC_TAG Allows an application to use NFC. Forbidden Allowed

Available APIs

API Description

isDLPFile(fd: number): Promise<boolean>

isDLPFile(fd: number, callback: AsyncCallback<boolean>): void

Checks whether a file is a DLP file.

getDLPPermissionInfo(): Promise<DLPPermissionInfo>

getDLPPermissionInfo(callback: AsyncCallback<DLPPermissionInfo>): void

Obtains the DLP permission information of this sandbox application.
getOriginalFileName(fileName: string): string Obtains the original name of a DLP file.
getDLPSuffix(): string Obtains the file name extension of this DLP file.
on(type: 'openDLPFile', listener: Callback<AccessedDLPFileInfo>): void Subscribes to the DLP file open event.
off(type: 'openDLPFile', listener?: Callback<AccessedDLPFileInfo>): void Unsubscribes from the DLP file open event.

isInSandbox(): Promise<boolean>

isInSandbox(callback: AsyncCallback<boolean>): void

Checks whether this application is a sandbox application.

getDLPSupportedFileTypes(): Promise<Array<string>>

getDLPSupportedFileTypes(callback: AsyncCallback<Array<string>>): void

Obtains the file name extension types that can be appended with .dlp.

setRetentionState(docUris: Array<string>): Promise<void>

setRetentionState(docUris: Array<string>, callback: AsyncCallback<void>): void

Sets the sandbox application retention state. If the retention state is set, the sandbox application will not be automatically uninstalled after being closed.

cancelRetentionState(docUris: Array<string>): Promise<void>

cancelRetentionState(docUris: Array<string>, callback: AsyncCallback<void>): void

Cancels the sandbox application retention state.

getRetentionSandboxList(bundleName?: string): Promise<Array<RetentionSandboxInfo>>

getRetentionSandboxList(bundleName: string, callback: AsyncCallback<Array<RetentionSandboxInfo>>): void

getRetentionSandboxList(callback: AsyncCallback<Array<RetentionSandboxInfo>>): void

Obtains the sandbox applications in the retention state.

getDLPFileAccessRecords(): Promise<Array<AccessedDLPFileInfo>>

getDLPFileAccessRecords(callback: AsyncCallback<Array<AccessedDLPFileInfo>>): void

Obtains the recently accessed DLP files.
setSandboxAppConfig(configInfo: string): Promise<void> Sets sandbox application configuration.
getSandboxAppConfig(): Promise<string> Obtains the sandbox application configuration.
cleanSandboxAppConfig(): Promise<void> Clears the sandbox application configuration.
startDLPManagerForResult(context: common.UIAbilityContext, want: Want): Promise<DLPManagerResult> Starts the DLP manager application on the current UIAbility page in borderless mode (available only for the stage model).

How to Develop

DLP is a system-level data protection solution that can be integrated into your application with minor adaptation or without adaptation.

When a DLP file is opened using the default application or a specified application, the DLP framework:

  1. Installs a sandbox application for your application.

  2. Binds a Filesystem in Userspace (FUSE) file to the DLP file.

  3. Shares the FUSE file with the DLP sandbox application.

This allows the sandbox application to seamlessly access the decrypted content of the DLP file, without aware of the encryption and decryption process.

To incorporate the DLP feature (support opening of DLP files) to a third-party application, perform the following adaptation.

[h2]Prerequisites

Before you start, ensure that the following conditions are met:

[h2]Importing Modules

Import the dlpPermission module.

import { dlpPermission } from '@kit.DataProtectionKit';

[h2]Opening the FUSE File

Generally, an application can open the FUSE file without adaptation if it can open the files mentioned in Prerequisites and there is no restriction on the Want parameter.

When a DLP file is opened, a sandbox application will be installed for the application. The sandbox application receives a Want request and parses the fields in the request.

 import Want from '@ohos.app.ability.Want';

 interface DLPUriObj {
   name: string
 };

 interface DLPWriteable {
   name:boolean
 };

 interface DLPNameObj {
   dateModified: string,
   displayName: string,
   relativePath: string,
 };

 interface DLPLinkNameObj {
   name: string
 };

 function getParams(want: Want) {
   // Receive the parameters passed after the DLP file is opened.
   let dlpFuseUri: string = want.uri? want.uri : '';  // URI of the FUSE file, which stores the decrypted plaintext.
   let dlpFuseWriteable: boolean = (want.parameters?.linkFileWriteable as DLPWriteable).name; // Whether the FUSE file is writeable.
   let dlpUri: string = (want.parameters?.dlpUri as DLPUriObj).name; // URI of the DLP file.
   let dlpName: string = (want.parameters?.fileAsset as DLPNameObj).displayName; // DLP file name.
   let dlpFuseName: string = (want.parameters?.linkFileName as DLPLinkNameObj).name; // FUSE file name.
 }

The sandbox application opens the FUSE file based on want.uri, obtains the FD, and then obtains the content of the FUSE file based on the FD.

 import fileIo from '@ohos.fileio';
 import fs from '@ohos.file.fs';
 import util from '@ohos.util';

 function readFileContent(dlpFuseUri:string): string {
   let content: string = '';
   let file: fs.File;
   try {
     file = fs.openSync(dlpFuseUri, fs.OpenMode.READ_ONLY); // Open the FUSE file and obtain the FD.
     this.commonFd = file.fd;
   } catch (err) {
     console.error('openSync failed. ' + err);
     return content;
   }

   try {
     let buffer = new ArrayBuffer(4096);
     let readOut = fs.readSync(this.commonFd, buffer, { // Read the file content.
       offset: 0
     });
     content = bufferToString(buffer); // Convert the file content to a string.
   } catch (err) {
     console.error('readSync failed. ' + err);
   }
   fileIo.closeSync(this.commonFd); // Close the file.
   return content;
 }

 function bufferToString(buffer: ArrayBuffer): string {
   let textDecoder = new util.TextDecoder('utf-8', {
     ignoreBOM: true
   });
   let resultPut = textDecoder.decodeWithStream(new Uint8Array(buffer), {
     stream: true
   });
   return resultPut;
 }

If the FUSE file is readable and writeable, you can also update the FUSE file content.

import fs from '@ohos.file.fs';

function writeFileContent(dlpFuseUri: string, content: string): void {
  let file: fs.File = fs.openSync(dlpFuseUri, fs.OpenMode.READ_WRITE); // Open the FUSE file in read/write mode.
  let writeLen: number = fs.writeSync(file.fd, content);  // Write data to the FUSE file.
  fs.closeSync(file); // Close the file.
}

[h2]Setting the UI Based on the DLP File Permission

Use getDLPPermissionInfo to obtain the user permission and operations allowed for the login domain account on the DLP file. The operations allowed vary with the user permission.

 import { dlpPermission } from '@kit.DataProtectionKit';
 import { BusinessError } from '@kit.BasicServicesKit';

 dlpPermission.getDLPPermissionInfo().then((data: dlpPermission.DLPPermissionInfo)=> {
   let userAccess: dlpPermission.DLPPermissionInfo.DLPFileAccess = data.dlpFileAccess; // User permission on the DLP file, which can be read-only, edit, or full control.
   let isEditable: number = data.flags & dlpPermission.DLPPermissionInfo.ACTION_EDIT; // Operations allowed on the DLP file.
 }).catch((err: BusinessError) => {
   console.error('getDLPPermissionInfo: ' + JSON.stringify(err));
 });

In DLPPermissionInfo returned by getDLPPermissionInfo, dlpFileAccess indicates the user permission and flags is the bitwise combination of the operations allowed. You can determine the allowed operations based on ActionFlagType and disable the related buttons on the UI.

[h2]Sharing Data Between an Application and Its Sandbox Application

Since the sandbox application is isolated from the application, its data is different from that of the application. To share data between them, you can use the data sharing mechanism provided by the DLP framework. For example, the application and its sandbox application can share the configuration for determining whether the privacy statement window has been displayed.

Generally, the configuration can be written and read in any of the following sequences:

Constraints

Procedure

  1. Set the configuration information.

    Convert the configuration information to the string type and call setSandboxAppConfig to set the configuration information for the sandbox application.

    Both an application and its sandbox application can call this API. However, the DLP sandbox application can call this API only before reading the DLP file content.

     import { dlpPermission } from '@kit.DataProtectionKit';
     import { BusinessError } from '@kit.BasicServicesKit';
    
     async function setSandboxAppConfig() {
       try {
         await dlpPermission.setSandboxAppConfig('configInfo'); // Set configuration information.
       } catch (err) {
         console.error('setSandboxAppConfig error, ', (err as BusinessError).code, (err as BusinessError).message); // Throw an error if the operation fails.
       }
     }
  2. Clear the configuration information.

    Call cleanSandboxAppConfig to clear all configuration of the sandbox application.

    This API can be called only by a common application.

     import { dlpPermission } from '@kit.DataProtectionKit';
     import { BusinessError } from '@kit.BasicServicesKit';
    
     async function cleanSandboxAppConfig() {
       try {
         await dlpPermission.cleanSandboxAppConfig(); // Clear configuration information.
       } catch (err) {
         console.error('cleanSandboxAppConfig error, ', (err as BusinessError).code, (err as BusinessError).message); // Throw an error if the operation fails.
       }
     }
  3. Obtain configuration information.

    Call getSandboxAppConfig to obtain configuration of the sandbox application.

    Both an application and its sandbox application can call this API.

     import { dlpPermission } from '@kit.DataProtectionKit';
     import { BusinessError } from '@kit.BasicServicesKit';
    
     async function getSandboxAppConfig() {
       try {
         let res:string = await dlpPermission.getSandboxAppConfig(); // Obtain configuration information.
       } catch (err) {
         console.error('getSandboxAppConfig error, ', (err as BusinessError).code, (err as BusinessError).message); // Throw an error if the operation fails.
       }
     }

[h2]Updating the DLP File Access Record

You can use the APIs provided by the DLP framework to obtain information about the recently accessed DLP files. Scenarios include the following:

[h2]Opening a DLP File in an Application

You can select a DLP file in the list of recently accessed files or using a file Picker and open it as follows:

  1. Set Want as follows:

    Set action to ohos.want.action.viewData.

    Set bundleName and abilityName to the bundle name and ability name of the application that attempts to open the DLP file, respectively.

    Set uri to the URI of the DLP file to open.

    Set fileName in Parameters to the name of the DLP file.

  2. Obtain UIAbilityContext.

  3. Call startAbility of the context to pass in the Want parameter and open the DLP file.

 import { Want } from '@kit.AbilityKit';
 import { BusinessError } from '@kit.BasicServicesKit';
 import common from '@ohos.app.ability.common';

 function openDlpFile(dlpUri: string, fileName: string) {
   let want: Want = {
     "action": "ohos.want.action.viewData",
     "bundleName": "com.example.example_bundle_name",
     "abilityName": "exampleAbility",
     "uri": dlpUri,
     "parameters": {
       "fileName": {
         "name": fileName
       }
     }
   }
   let context = getContext() as common.UIAbilityContext; // Obtain UIAbilityContext.
   try {
     console.log('openDLPFile:' + JSON.stringify(want));
     console.log('openDLPFile: delegator:' + JSON.stringify(context));
     context.startAbility(want);
   } catch (err) {
     console.error('openDLPFile startAbility failed', (err as BusinessError).code, (err as BusinessError).message);
     return;
   }
 }

[h2]Setting the DLP File Permission in an Application

You can integrate the permission settings button into an application. When opening a common file, you can click the button to open the modal permission settings page of the DLPManager application and generate a DLP file. You can also view the allowed operations for the opened DLP file via the sandbox application.

[h2]Other DLP Capabilities

FAQs

[h2]What should I do if the application can open a common file but cannot open the FUSE file?