Skip to Content
Product Information

Field Masking – Context based masking scenario in specific Sub-type of Personal IDs (0185) Info-type of SE16/SE16N/PA20/PA30

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.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.