How Do I encode a List of Passwords for Using in LRE/TruClient?

Hi Guys,

I have a problem.I need to know how I can encode/mask a hundred thousands of values. Here's the context:

I use VTS extensiviley to configure my REST and TruClient Scripts for getting the environent parameters, users, passwords and so on. I use Basic authentication for GUI, without authentication via API (historical reasons). When I activate authentication via NTLM I don't get the TC-script to connect to VTS.

Now I have to use an not anonymised test environment for loadtesting via TrueClient. Because of our security concerns and possible data leaks I would like to mask all Login data beside the passwords. I'm talking about <500k values.

The password Encoder for LRE has no known parameters to use it over CLI and I don't want to start to develop a UFT-Script to "manually" insert, generate & copy the values. Why does UFT has this feature, but LRE/VuGen not?

I tried the DevWebUtils.exe with the csv-file, but TC doesn't recognize the result as an decodable value.

Does Anybody have an idea  or a proper Solution?

Thanks

Pascal

  • Verified Answer

    +1  

    I think that there is no standard solution. You might use one of the standard JS libraries and use a symmetric en/decryption. E.g. CryptoJS, see this discussion.

    Put the CrytoJS code in a TC library so you can use it in multiple projects.

    [EDIT]

    There are two functions load.unmask() and load.decrypt(). For both, according documentation, devwebutils.exe should be used to generate masked or encrypted data.

    The issue I've with all these is that it is hard to impossible to protect user/passwords for other (non-authorized testers). Any one that can lay it hands on the script can reconstruct the data. In our lab we have been thinking about solutions where we might generate a library. The hash of that lib-file and the domain/project/test name might be used to retrieve a special key from a service. That service is only accessible from the Load Generators (LGs are only accessible by LRE). This will limit the access to encrypt data and is needs authorized access to LRE to use.

    Still special care has to be taken not to use parameters to handle decrypted data, due to possible logging setting. But I agree that this is still not optimal and might need tight integration with LRE as well.

    How to ask questions

    Reward contributions via likes or 'verified answers'

  • 0 in reply to 

    YES exactly that was my topic - never then PasswordEncoderConsole.exe in my VuGen-installation folder.

    Thanks a lot.

  • 0 in reply to 

    Hi There,

    here are my sources for my final solution. Because of runtime around 1.2 Sec per iteration in VuGen I did it as Loadtest on 60 loadgens,

    I have my data stored in one VTS and the configuration to connect in Runtime Settings / additional Attributes

    #include "globals.h"
    #include "mic_socket.h"
    vuser_init()
    {
    	lr_load_dll("micsocket.dll");
    	
    	
    	//Aufbau Verbindung zu Daten Virtual Table Server für Testdaten
    	VTServer = lr_get_attrib_string("VTServer");
    	
    	lr_save_string(lr_get_attrib_string("VTServer"),"VTServer");
    	
    	
    	VTSPort = lr_get_attrib_long("VTSPort"); 
    	
    	lr_save_int(lr_get_attrib_long("VTSPort"),"VTSPort");
    	
    	
    	lrvtc_connect_ex("Server={VTServer}","Port={VTSPort}",LAST);
    	
    	lr_save_string("SecretPassword","Password");
    	
        return 0;
    }
    

    Action()
    {
        // Installationspfad des PasswordEncoderConsole.exe
    // e.g.   const char *executablePath = "\"C:\\VuGen\\bin\\PasswordEncoderConsole.exe\"";
        const char *executablePath = lr_get_attrib_string("executablePath");
        
        // Buffer für Befehlszeile und Rückgabewert 
        char command[400], buf[1024];
     
        // Function Pointer enthält die Adresse des Rückgabewertes des Streams aus der Befehlszeile um die Pipe auszulesen
        long fp = 0;
        
        // Lies die erste Zeile aus der VTS-Tabelle aus
        lrvtc_retrieve_row();
        
        if (strlen(lr_eval_string("{enc_PersID}")) > 0 )
    	{
    		lr_message("Alle PersIDs & OKNs encodiert!");
    		lrvtc_send_row1("PersID;OKN;enc_PersID;enc_OKN", "{PersID};{OKN};{enc_PersID};{enc_OKN}",";",VTSEND_SAME_ROW);
    		lr_exit(LR_EXIT_VUSER,LR_PASS);
    	}
     
        // Zusammenbau der Befehlszeile über String-Verkettung und Variablenersetzung
        snprintf(command, sizeof(command), "%s %s", executablePath , lr_eval_string("{PersID}"));
        
        // initiate pipe streams to or from a process siehe https://pubs.opengroup.org/onlinepubs/009696799/functions/popen.html
        // r := Pipe auslesen
        fp = popen(command, "r");
        
        // Auslesen der Pipe und schreiben in den Buffer und speichern in einen Parameter
        while (fgets(buf, sizeof(buf), fp) != 0)
        {
            lr_save_string(buf, "enc_PersID");
        }
        
        // pclose - close a pipe stream to or from a process https://pubs.opengroup.org/onlinepubs/009696799/functions/pclose.html
        pclose(fp);
        
        // Function Pointer initialisieren / zurücksetzen
        fp = 0;
        
        snprintf(command, sizeof(command), "%s %s", executablePath , lr_eval_string("{OKN}"));
     
        fp = popen(command, "r");
        
        while (fgets(buf, sizeof(buf), fp) != 0)
        {
            lr_save_string(buf, "enc_OKN");
        }
        
        pclose(fp);
        
        fp = 0;
        
        lrvtc_send_row1("PersID;OKN;enc_PersID;enc_OKN", "{PersID};{OKN};{enc_PersID};{enc_OKN}",";",VTSEND_SAME_ROW);
        
        return 0;
    }
     
    Action()
    {
        // Installationspfad des PasswordEncoderConsole.exe
    // e.g.   const char *executablePath = "\"C:\\VuGen\\bin\\PasswordEncoderConsole.exe\"";
        const char *executablePath = lr_get_attrib_string("executablePath");
        
        // Buffer für Befehlszeile und Rückgabewert 
        char command[400], buf[1024];
     
        // Function Pointer enthält die Adresse des Rückgabewertes des Streams aus der Befehlszeile um die Pipe auszulesen
        long fp = 0;
        
        // Lies die erste Zeile aus der VTS-Tabelle aus
        lrvtc_retrieve_row();
        
        if (strlen(lr_eval_string("{enc_PersID}")) > 0 )
    	{
    		lr_message("Alle PersIDs & OKNs encodiert!");
    		lrvtc_send_row1("PersID;OKN;enc_PersID;enc_OKN", "{PersID};{OKN};{enc_PersID};{enc_OKN}",";",VTSEND_SAME_ROW);
    		lr_exit(LR_EXIT_VUSER,LR_PASS);
    	}
     
        // Zusammenbau der Befehlszeile über String-Verkettung und Variablenersetzung
        snprintf(command, sizeof(command), "%s %s", executablePath , lr_eval_string("{PersID}"));
        
        // initiate pipe streams to or from a process siehe https://pubs.opengroup.org/onlinepubs/009696799/functions/popen.html
        // r := Pipe auslesen
        fp = popen(command, "r");
        
        // Auslesen der Pipe und schreiben in den Buffer und speichern in einen Parameter
        while (fgets(buf, sizeof(buf), fp) != 0)
        {
            lr_save_string(buf, "enc_PersID");
        }
        
        // pclose - close a pipe stream to or from a process https://pubs.opengroup.org/onlinepubs/009696799/functions/pclose.html
        pclose(fp);
        
        // Function Pointer initialisieren / zurücksetzen
        fp = 0;
        
        snprintf(command, sizeof(command), "%s %s", executablePath , lr_eval_string("{OKN}"));
     
        fp = popen(command, "r");
        
        while (fgets(buf, sizeof(buf), fp) != 0)
        {
            lr_save_string(buf, "enc_OKN");
        }
        
        pclose(fp);
        
        fp = 0;
        
        lrvtc_send_row1("PersID;OKN;enc_PersID;enc_OKN", "{PersID};{OKN};{enc_PersID};{enc_OKN}",";",VTSEND_SAME_ROW);
        
        return 0;
    }
     

    Passwort()
    {
    	const char *executablePath = lr_get_attrib_string("executablePath");
        
        // Buffer für Befehlszeile und Rückgabewert 
        char command[400], buf[1024];
        
        int OKN_size, PW_size = 0;
            
        // Function Pointer enthält die Adresse des Rückgabewertes des Streams aus der Befehlszeile um die Pipe auszulesen
        long fp = 0;
        
        OKN_size = lrvtc_column_size("OKN");
        PW_size = lrvtc_column_size("enc_PW");
        
        if (PW_size >= OKN_size) 
        {
            lr_exit(LR_EXIT_VUSER,LR_PASS);
        }
     
        // Zusammenbau der Befehlszeile über Sting-Verkettung und Variablenersetzung
        snprintf(command, sizeof(command), "%s %s", executablePath , lr_eval_string("{Passwort}"));
        
        // initiate pipe streams to or from a process siehe https://pubs.opengroup.org/onlinepubs/009696799/functions/popen.html
        // r := Pipe auslesen
        fp = popen(command, "r");
        
        // Auslesen der Pipe und schreiben in den Buffer und speichern in einen Parameter
        while (fgets(buf, sizeof(buf), fp) != 0)
        {
            lr_save_string(buf, "enc_PW");
        }
        
        // pclose - close a pipe stream to or from a process https://pubs.opengroup.org/onlinepubs/009696799/functions/pclose.html
        pclose(fp);
        
        lr_output_message("Password %s ; Encoded Password %s ; Decoded Password %s", lr_eval_string("{Password}"),lr_eval_string("{enc_PW}"), lr_unmask(lr_eval_string("{enc_PW}")));
        
        lrvtc_send_row1("Password","{enc_PW}",";",VTSEND_SAME_ROW);
        
        return 0;
    }
    

    Hope that helps somebody in the future