Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
AmitKrSingh
Advisor
Advisor

Introduction


In this blog post, we will learn how to mask “ID Number field in Birth Certificate (BC)Driver’s License (DL), Social Insurance Number (SN), Company Security ID (CS), and Work Visa (VI) sub-types of Personal IDs (0185) Info-type of transaction SE16/SE16N/PA20/PA30. For Passport (PP) Sub-type, ID Number field will remain unmasked.

A PFCG Role will be used for the authorization check which will allow users with the specified role to view the field value. If a user does not have this role, it means the user is not authorized and data will be protected either through masking, clearing, or disabling the field.

The result for Birth Certificate (BC)Driver’s License (DL), Social Insurance Number (SN), Company Security ID (CS), Work Visa (VI), and Passport (PP) sub-types in listed transactions will look like below:

SE16 - ALV Grid Display



Masking is also supported in Display, Detail, Double-Click, Print, and Download scenario for SE16 ALV Grid Display in this scenario.

SE16 - ALV List



Masking is also supported in Display, Detail, Double-Click, and Download scenario for SE16 ALV List in this scenario.

SE16 - Standard List



Masking is also supported in Display, Detail, and Double-Click scenario for SE16 Standard List in this scenario.

SE16N



Masking is also supported in Detail, Double-Click, Views-List Output, View-Excel In-place, and Download scenario for SE16N in this scenario.

PA20/PA30









What is Context based Masking?


Attributes that deal with time, location or dynamic aspects is called Context (environment) attribute. Masking a field based on context attribute is called Context based-masking.

e.g. – Masking the salary of employees who belong to Germany.

Prerequisite


Field Masking for SAP GUI” is a solution to protect sensitive data on SAP GUI screens at field level.Product “Field Masking for SAP GUI” is delivered to customer as add-on (UIM 100). To achieve Role based masking, Add-on UIM 100 must be installed in customer system.

Requirement


Context-based masking is required for transaction SE16/SE16N/PA20/PA30, “ID Number” field need to be masked in Birth Certificate (BC)Driver’s License (DL), Social Insurance Number (SN), Company Security ID (CS), and Work Visa (VI) sub-types. Only for Passport (PP) Sub-type, ID Number field will remain unmasked.

Maintain Masking configuration


Configure Technical Information (Table Name-Field Name) of field in masking configuration.

You can get the Technical Address of a GUI field by pressing “F1” on the field.



Follow the given path:


SPRO -> SAP NetWeaver -> Field Masking for SAP GUI -> Masking Configuration->Maintain Masking Configuration
Follow below mentioned steps:


  • Click on “New Entries” button

  • Enter “Table Name” as “P0185

  • Enter “Field Name” as “ICNUM

  • Enter “PFCG Role Name” as “/UIM/PFCG_ROLE“. In this example, we have used a blank role “/UIM/PFCG_ROLE”. Customers can use any role as per their requirement.

  • Check “Masking Control” checkbox”

  • Click on “Save” button




Mass Configuration


For the above entries, “Mass Configuration” report should be executed which is required to generate technical addresses.
Follow below mentioned steps:


  • Select the entry

  • Click on “Mass Configuration” button

  • Click on “Select All” button

  • Click on “Generate Customizing” button

  • Save the information





BAdI Implementation


Context-based masking can be achieved by implementing Masking BAdI /UIM/BD_MASKING.


Create BAdI implementation for method PREPARE_MASK_DATA

Sample code is given below –


METHOD /uim/if_uisecurity~prepare_mask_data.

*/ This badi implementation is to cater the need of context based masking in different UIs like ALV Grid/List/Standard List/Pa20/Pa30/Se16n/Se16
*/ and for different functionalities like display button from toolbar/double click/download to local file/detail display

DATA: lv_context_1 TYPE string,
lv_context_2 TYPE string,
lv_context_fieldvalue_1 TYPE string,
lv_context_fieldvalue_2 TYPE string,
lv_struc TYPE string,
lv_exp TYPE string,
msg_text TYPE string,
lv_progname TYPE dbglprog,
lv_prog TYPE dbglprog,
channel TYPE string,
lv_datachar TYPE string VALUE 'DATACHAR',
lv_keychar TYPE string VALUE 'KEYCHAR',
lv_fldname TYPE string VALUE 'FIELDNAME',
lv_low TYPE string VALUE 'LOW',
op_ref TYPE REF TO cx_root.

DATA lt_callstack TYPE abap_callstack.
DATA lt_stack TYPE sys_callst.

FIELD-SYMBOLS: <fs_data> TYPE table,
<fs_subty> TYPE any,
<fs_tab> TYPE ANY TABLE,
<fs_str> TYPE any.
TRY.
lv_context_1 = 'INFTY'. "Pass the contexts for which conditional masking has to be applied
lv_context_2 = 'SUBTY'.
lv_context_fieldvalue_1 = '0185'.
lv_context_fieldvalue_2 = 'PP'.

CALL FUNCTION 'SYSTEM_CALLSTACK' "Call system stack
EXPORTING
max_level = 0
IMPORTING
callstack = lt_callstack
et_callstack = lt_stack.

*/ Read the stack to get the corresponding program name as functionality may call from list/grid/dynp channels

READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_stack_list>)
WITH KEY blockname = 'K_KKB_LIST_DISPLAY'.
IF <ls_stack_list> IS ASSIGNED.
channel = 'LIST'.
ENDIF.

READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_stack_st_list>)
WITH KEY blockname = 'THEW_LIST_MASKING2'
blocktype = 'FORM'
mainprogram = 'SAPMSSY0'.
IF <ls_stack_st_list> IS ASSIGNED.
channel = 'ST_LIST'.
ENDIF.

READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_stack_dynp>)
WITH KEY blockname = 'MSK_DYNP'
blocktype = 'METHOD'.
IF <ls_stack_dynp> IS ASSIGNED.
channel = 'DYNP'.
ENDIF.

READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_stack_grid>)
WITH KEY blockname = 'MASK_ALV_GRID'
blocktype = 'METHOD'.

IF <ls_stack_grid> IS ASSIGNED.
channel = 'GRID'.
ENDIF.

*/ in case of double click on ALV Grid, stack calls from 'mask_tree' method but functionality calls from 'Grid' channel itself

READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_stck_grid>)
WITH KEY blockname = 'MASK_TREE'
blocktype = 'METHOD'.
IF <ls_stck_grid> IS ASSIGNED.
channel = 'GRID'.
ENDIF.

*/ check case whether functionality is calling from dynpro channel/list or grid and check conditions further accordingly

CASE channel.

WHEN 'DYNP'.

DATA(lv_program) = /uim/cl_dynp_msk=>sv_in_prog. "To get program name

CONCATENATE '(' lv_program ')' cs_mask_data-tabname INTO lv_exp.
ASSIGN (lv_exp) TO FIELD-SYMBOL(<fs_val3>). "Get structure in case of dynp screen

*/ Condition check in case of Dynp screen if structure is assigned, then check on contexts if they are fulfilling the required condition

IF <fs_val3> IS ASSIGNED AND NOT <fs_val3> IS INITIAL.

ASSIGN COMPONENT lv_context_1 OF STRUCTURE <fs_val3> TO FIELD-SYMBOL(<fs_infty>). "Get value of field 'Infotype'
ASSIGN COMPONENT lv_context_2 OF STRUCTURE <fs_val3> TO <fs_subty>.
" Get value of field 'Subtype'

*/ Both conditions should be fulflled in case of PA20/PA30 as both context needs to pass in case of PA20/PA30

IF <fs_infty> IS ASSIGNED AND <fs_subty> IS ASSIGNED.

*/ check if value in structure is same as the contexts passed for conditional masking.If yes, unmask the value and authorised it.
IF lv_context_fieldvalue_1 EQ <fs_infty> AND lv_context_fieldvalue_2 EQ <fs_subty>.
cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.
ENDIF.
*/ Condition runs in case of click button display from toolbar in List/Grid/Standard List
*/ and double click on standard list as the functionality calls from dynpro class.

ELSEIF <fs_subty> IS ASSIGNED.
IF lv_context_fieldvalue_2 EQ <fs_subty>.

cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.
ENDIF.
ELSE.
RETURN.
ENDIF.

ELSE.
*/ Read the stack in case of se16n
READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_stck_dynp>)
WITH KEY blockname = 'SE16N_SHOW_GRID_LINE'
blocktype = 'FUNCTION'.
*/ Condition runs in case of double click in SE16N .
IF <ls_stck_dynp> IS ASSIGNED.
lv_program = <ls_stck_dynp>-mainprogram.
*/ Get the structure in case of SE16N.
CONCATENATE '(' lv_program ')' 'GT_DETAIL' '[]' INTO DATA(lv_ex).
ASSIGN (lv_ex) TO <fs_tab>.
IF <fs_tab> IS ASSIGNED.
*/ Loop as if the contexts in structure is same as need for conditional masking, then unmask the values and authorised it.
LOOP AT <fs_tab> ASSIGNING <fs_str> .

ASSIGN COMPONENT lv_fldname OF STRUCTURE <fs_str> TO FIELD-SYMBOL(<fs_fldname>).
ASSIGN COMPONENT lv_low OF STRUCTURE <fs_str> TO <fs_subty>. "Get value of fieldname
IF <fs_fldname> IS ASSIGNED AND <fs_subty> IS ASSIGNED.

IF <fs_fldname> EQ lv_context_2.
IF lv_context_fieldvalue_2 EQ <fs_subty>.
"if fieldname is same, check if value is same for field as of context passed
cs_mask_data-masked_val = cs_mask_data-original_val.
"If yes, unmask it and authorised it.
cs_mask_data-auth_flag = 'X'.
RETURN.
ELSE.
RETURN.
ENDIF.
ENDIF.

ENDIF.

ENDLOOP.
ENDIF.
ENDIF.
ENDIF.

WHEN 'GRID'.
*/ Get the whole entries in case of grid display
ASSIGN /uim/cl_msk_alv=>ss_data->* TO <fs_data>.
*/ Condition runs in case of ALV Grid as if structure is assigned, then check for context value if it is same as need for conditional masking
IF <fs_data> IS ASSIGNED .

IF <ls_stck_grid> IS ASSIGNED.
ASSIGN /uim/cl_tree=>ss_data_tree->* TO <fs_str>.
*/ Condition runs in case of double click on ALV Grid
IF <fs_str> IS ASSIGNED AND NOT <fs_str> IS INITIAL.
ASSIGN COMPONENT lv_context_2 OF STRUCTURE <fs_str> TO <fs_subty>.

IF <fs_subty> IS NOT ASSIGNED.
RETURN.
ELSEIF <fs_subty> IS ASSIGNED
AND lv_context_fieldvalue_2 EQ <fs_subty>.
cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.
ENDIF.

ENDIF.

ELSE.
*/ This condition runs in case of grid data display
READ TABLE <fs_data> ASSIGNING FIELD-SYMBOL(<fs_val5>) INDEX /uim/cl_msk_alv=>sv_row_id.

ASSIGN COMPONENT lv_context_2 OF STRUCTURE <fs_val5> TO <fs_subty>.

IF NOT <fs_subty> IS ASSIGNED.
RETURN.
ELSEIF <fs_subty> IS ASSIGNED
AND lv_context_fieldvalue_2 EQ <fs_subty>.
cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.
ENDIF.
ENDIF.
ENDIF.

WHEN 'LIST'
OR 'ST_LIST'.

READ TABLE lt_callstack ASSIGNING FIELD-SYMBOL(<ls_callstck>)
WITH KEY blockname = 'K_KKB_OUTTAB_DETAIL_SHOW'
blocktype = 'FUNCTION'.
DATA(lv_pro) = sy-cprog.
*/ Condition runs in case of double click on ALV List, if structure is assigned, check for context, mask/unmask it.
IF <ls_callstck> IS ASSIGNED.
CONCATENATE '(' lv_pro ')' '%_ALV_' cs_mask_data-tabname INTO lv_ex.

ASSIGN (lv_ex) TO <fs_str>.

IF <fs_str> IS ASSIGNED AND NOT <fs_str> IS INITIAL.

ASSIGN COMPONENT lv_context_2 OF STRUCTURE <fs_str> TO <fs_subty>.

IF <fs_subty> IS NOT ASSIGNED.
RETURN.
ELSEIF <fs_subty> IS ASSIGNED
AND lv_context_fieldvalue_2 EQ <fs_subty>.
cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.
ENDIF.
ENDIF.
"Condition runs in case of download in ALV Grid
ELSEIF <ls_stack_list> IS ASSIGNED.

lv_progname = <ls_stack_list>-mainprogram.
lv_struc = 'T_OUTTAB'.
CONCATENATE '(' lv_progname ')' 'T_OUTTAB' INTO DATA(lv_expr).

"Get structure to manipulate data in case of download to file in ALV Grid

ASSIGN (lv_expr) TO FIELD-SYMBOL(<fs_val2>).

IF <fs_val2> IS ASSIGNED AND NOT <fs_val2> IS INITIAL.

ASSIGN COMPONENT lv_context_2 OF STRUCTURE <fs_val2> TO <fs_subty>.

IF <fs_subty> IS NOT ASSIGNED.
RETURN.
ELSEIF <fs_subty> IS ASSIGNED
AND lv_context_fieldvalue_2 EQ <fs_subty>.
cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.
ENDIF.
ENDIF.

ELSEIF <ls_stack_st_list> IS ASSIGNED.
lv_prog = sy-cprog.
DATA(lv_stru) = /uim/cl_uimasking=>ss_tabname. "Get the table name in case of ALV Standard List

CONCATENATE '(' lv_prog ')' lv_stru INTO DATA(lv_exprs).
ASSIGN (lv_exprs) TO FIELD-SYMBOL(<fs_val6>).
"Get structure to manipualte data in case of ALV Standard List

IF <fs_val6> IS ASSIGNED AND NOT <fs_val6> IS INITIAL. "condition runs in case of Standard List display

ASSIGN COMPONENT 'SUBTY' OF STRUCTURE <fs_val6> TO <fs_subty>.

IF <fs_subty> IS ASSIGNED
AND lv_context_fieldvalue_2 EQ <fs_subty>.
cs_mask_data-masked_val = cs_mask_data-original_val.
cs_mask_data-auth_flag = 'X'.

ENDIF.
ENDIF.

ENDIF.

ENDCASE.

CATCH cx_root.

ENDTRY.
ENDMETHOD.

Conclusion


In this blog post, we have learnt how Role-based masking is achieved for “ID Number” field of Birth Certificate (BC)Driver’s License (DL), Social Insurance Number (SN), Company Security ID (CS), and Work Visa (VI) sub-types of Personal IDs (0185) Info-type of transaction SE16, SE16N, PA20, and PA30.