Skip to Content
Technical Articles
Author's profile photo Sanu Sugathan

Update table field data to remove sensitive information from test systems

Summary

In this blog you will learn about a program that can be used to remove sensitive information from your test systems.  You can schedule this program as a background job after system refresh from production.  This program can  replace data at table field level with a masking text of your choice.

How does it work?

This program  replaces table field data with a text to mask the data in test systems after production refresh. The clients may need to remove the customer/vendor address information and contact details for security purposes.

This program has a selection screen where you can enter the table fields that needs to be replaced with a dummy text or masking text.  Code snippets provided.

Selection screen

 

Source code

*&---------------------------------------------------------------------*
*& Report  ZMASK_TABLE_FIELD_DATA
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zmask_table_field_data.

DATA:lv_field(47) TYPE c.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME .
SELECT-OPTIONS:s_fields FOR lv_field OBLIGATORY NO INTERVALS.
SELECTION-SCREEN SKIP .
SELECTION-SCREEN COMMENT /1(79) text-001.
SELECTION-SCREEN COMMENT /1(79) text-002.
SKIP 1.
PARAMETERS p_mask(50) TYPE c OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1  .

CLA$$ cl_tab_field DEFINITION.

PUBLIC SECTION.

  TYPES:BEGIN OF ty_tab_field,
          table TYPE tabname16,
          field TYPE name_feld,
        END OF ty_tab_field,

        tt_tab_field TYPE TABLE OF ty_tab_field.

*  DATA: it_tab_field TYPE STANDARD TABLE OF ty_tab_field.

  METHODS:  scramble_table_data IMPORTING it_table_field TYPE tt_tab_field ,
            process_each_table  IMPORTING it_tab TYPE tt_tab_field.

ENDCLA$$.

CLA$$ cl_report DEFINITION.

  PUBLIC SECTION.

    TYPE-POOLS  sscr.


    DATA: lw_restrict TYPE sscr_restrict,
          lw_opt_list TYPE sscr_opt_list,
          lw_as       TYPE sscras,
          gv_clA$$    TYPE klA$$e_d.

      DATA: it_tab_field TYPE STANDARD TABLE OF cl_tab_field=>ty_tab_field.

    METHODS: initialize,
             collect_table_field_names.

ENDCLA$$.



INITIALIZATION.
  DATA go_report TYPE REF TO  cl_report.
  CREATE OBJECT go_report .

  go_report->initialize( ).

START-OF-SELECTION.

  CHECK NOT s_fields[] IS INITIAL.
  DATA: go_tab_field TYPE REF TO cl_tab_field.
  CREATE OBJECT go_tab_field.

  go_report->collect_table_field_names( ).
  IF NOT go_report->it_tab_field[] IS INITIAL.
    go_tab_field->mask_table_data( EXPORTING it_table_field = go_report->it_tab_field[] ).
  ELSE.
    MESSAGE 'No valid table fields found for data masking' TYPE 'S' DISPLAY LIKE 'I'.
  ENDIF.



**********************************************************************
********ClA$$ Implementations*****************************************
**********************************************************************

CLA$$ cl_report IMPLEMENTATION.
  METHOD initialize.

    CLEAR: lw_restrict,
    lw_opt_list,
    lw_as.

    lw_opt_list-name       = 'EQUAL'.
    lw_opt_list-options-eq = 'X'.   " Restrict to equal
    APPEND lw_opt_list TO lw_restrict-opt_list_tab.

    lw_as-kind            = 'S'.
    lw_as-name            = 'S_FIELDS'. " select option which you want
    "to restrict
    lw_as-sg_main         = 'I'.
    lw_as-sg_addy         = ''.
    lw_as-op_main         = 'EQUAL'.
    APPEND lw_as TO lw_restrict-A$$_tab.
*** To apply restrictions to select option
    CALL FUNCTION 'SELECT_OPTIONS_RESTRICT'
      EXPORTING
        restriction            = lw_restrict
      EXCEPTIONS
        too_late               = 1
        repeated               = 2
        selopt_without_options = 3
        selopt_without_signs   = 4
        invalid_sign           = 5
        empty_option_list      = 6
        invalid_kind           = 7
        repeated_kind_a        = 8
        OTHERS                 = 9.

  ENDMETHOD.
  METHOD  collect_table_field_names.
    DATA: lw_tab_field TYPE cl_tab_field=>ty_tab_field.
    LOOP AT s_fields INTO s_fields.

      SPLIT s_fields-low AT '-' INTO lw_tab_field-table lw_tab_field-field .
      APPEND lw_tab_field TO it_tab_field.
      CLEAR lw_tab_field.

    ENDLOOP.

    IF NOT it_tab_field[] IS INITIAL.
      SORT it_tab_field.
      DELETE ADJACENT DUPLICATES FROM it_tab_field COMPARING ALL FIELDS.
    ENDIF.

  ENDMETHOD.

ENDCLA$$.

CLA$$ cl_tab_field IMPLEMENTATION.

  METHOD mask_table_data .
    DATA: lw_table_field LIKE LINE OF it_table_field,
          lt_indv_tab    TYPE STANDARD TABLE OF ty_tab_field.
    LOOP AT it_table_field INTO lw_table_field.
* Collect the fields of invidual tables and process table by table
      APPEND lw_table_field TO lt_indv_tab.
      AT END OF table.
        process_each_table( EXPORTING it_tab = lt_indv_tab ).
        REFRESH lt_indv_tab.
      ENDAT.


    ENDLOOP.

  ENDMETHOD.

  METHOD process_each_table.

    DATA: lw_tab        LIKE LINE OF it_tab,
          lo_tdata      TYPE REF TO data,
          lo_tline      TYPE REF TO data,
          lv_field(100) TYPE c,
          lv_text       TYPE string,
          lv_line       TYPE i,
          lv_line_c(10) TYPE c.

* Generate internal table dynamically
    FIELD-SYMBOLS:<fs_tab_data>   TYPE ANY TABLE,
                  <fs_tab_line>   TYPE any,
                  <fs_field_name> TYPE name_feld,
                  <fs_field_data> TYPE any.

    READ TABLE it_tab INTO lw_tab INDEX 1.
    CHECK lw_tab-table IS NOT INITIAL.

* Create dynamic internal table
    CREATE DATA lo_tdata TYPE TABLE OF (lw_tab-table).
    CHECK sy-subrc EQ 0.
    A$$IGN lo_tdata->* TO <fs_tab_data>.
    CHECK <fs_tab_data> IS A$$IGNED.
    SELECT * FROM (lw_tab-table)
             INTO TABLE <fs_tab_data>.
*    CREATE DATA lo_tline TYPE (lw_tab-table).
*    CHECK sy-subrc EQ 0.
*    A$$IGN lo_tline->* TO <fs_tab_line>.
*    CHECK <fs_tab_line> IS A$$IGNED.

    LOOP AT <fs_tab_data> A$$IGNING <fs_tab_line> .
      LOOP AT it_tab INTO lw_tab.
        CONCATENATE '<fs_tab_line>-' lw_tab-field INTO lv_field.
        A$$IGN (lv_field) TO <fs_field_data>.
        IF <fs_field_data> IS NOT INITIAL.
          <fs_field_data> = p_mask.
        ENDIF.
      ENDLOOP.
    ENDLOOP.

*  Update the table  with modified fields
    IF NOT <fs_tab_data> IS INITIAL.
      UPDATE (lw_tab-table) FROM TABLE <fs_tab_data>.
      IF sy-subrc EQ 0.
        ULINE.
        CONCATENATE 'The following fields are updated in table' lw_tab-table 'with masking text' p_mask  INTO lv_text SEPARATED BY space.
        WRITE:/ lv_text.
        LOOP AT it_tab INTO lw_tab.
          WRITE:/ lw_tab-field.
        ENDLOOP.
        CLEAR: lv_text,lv_line.
        DESCRIBE TABLE <fs_tab_data> LINES lv_line.
        lv_line_c = lv_line.
        CONCATENATE 'Number of records updated:' lv_line_c INTO lv_text SEPARATED BY space.
        WRITE:/ lv_text.

      ENDIF.
    ENDIF.
  ENDMETHOD.

ENDCLA$$.




 

 

Conclusion

This simple program can be a handy tool in system refresh activities. Execution of this program can be added as a post refresh activity to ensure that no sensitive information is copied to Quality systems from production.  This program is designed to work on any number of table fields and there are no restrictions based on tables.

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Peter Jaeckel
      Peter Jaeckel

      Hi Sanu,

      a question for you. Did you spent any time in research of existing solutions? Since this problem is a very common one, it is hard to believe that there aren’t any solutions out there. Personally I don’t know, but maybe you came across one or two?

      Actually I don’t like this simplistic approach much, since you might easily destroy data consistency in your test system, which in turn renders all tests as useless.

      Cheers,

      Peter

       

      Author's profile photo Sanu Sugathan
      Sanu Sugathan
      Blog Post Author

      Our client did not want to procure any new license and they are aware of the impact of such a solution. I did my research and this custom solution was the method client chose.  Thank you for your comments.

      Author's profile photo Sandra Rossi
      Sandra Rossi

      That’s called data anonymization and there are softwares to do that.