You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@jmeter.apache.org by Markus Obermann <ma...@yahoo.de.INVALID> on 2020/01/08 16:10:06 UTC

Re: Problems Execute Linux Commands using JSR223 PrePrcessor with Groovy Engine and pipe-symbol

 Hello,
sorry for my very late reply and many thanks for your help - it really helped me a lot so i wanna share with you what i have done now and how it is working.
First some background what i needed to do:1) i have an https server where i need to connect using mutual tls which works perfect with the keystore (i only have 1 cert in the keystore)2) i do HTTPS POST request to my API running on this server where i send (text and/or xml) data. The server send me data back which then i store (using jmeters save-response-to-file)3) The tricky part is that i must sign (using S/MIME (p7 signature) the data i wanna send AND my URL using my priv. key and cert. AND THEN i need to do a base64 encoding of this signed file and paste the base64 result string as an specific HTTP-Header and sent this with my request.
Well doing this with openssl using bash works quite well - but doing this with jmeter would be either using bouncy-castle and do s/mime - or i just call my openssl commands from jmeter using groovy :)
So my solution looks like this (it's not yet fully optimized but it works quite good and stable)I use a JSR223 PreProcessor with groovy engine with this code (i also have some user-defined-variables defined thus do not wonder about the vars.get():

<start of code>

1: import org.apache.jmeter.protocol.http.sampler.HTTPSampler;
2: String path = sampler.getPath(); // this was very tricky as i do NOT have to use getURL(); but only the "Path"
3: String datapath = vars.get("datapath");4: String cert = vars.get("cert");5: String key = vars.get("key");6: String tempsave = vars.get("tempsave");

7: p="echo -en $path".execute() | "openssl smime -sign -signer $cert -inkey $key -outform der -binary -md sha384 -out $savetemp/url.p7".execute() | "openssl smime -in $datapath/data.xml -sign -signer $cert -inkey $key -outform der -binary -md sha384 -out $savetemp/file.p7".execute()8: p.text
9: f="base64 -w 0 $savetemp/file.p7".execute().text10: u="base64 -w 0 $savetemp/url.p7".execute().text
11: vars.put("filebase64", f);12: vars.put("urlbase64", u);
<end of code>
Well this works and will do the stuff i need. It was a little bit tricky about the getPath() stuff at line 2.As ive told before i need to sign the URL. Thus i thought this must be everything from beginning with https to end of the line without \r\n and without the method (POST) and without the protocol version which is HTTP/1.1So first what i did in line 2: was a "sampler.getURL()" and print it out on console. It gaves me exact what i first thought is correct namely the URL staring with https://. I also looked on the view results tree what jmeter doing with the POST and it looked quite good. 
But my server said that the URL signature is wrong. Thus i've calculated the URL sign - and send withhin the request - but it was wrong.
Then i've noticed what jmeter was really sending namely "POST /path". This means jmeter has not sent the URL starting with "https://ip:port/path" but only POST /path.Maybe this is because im using an http-request-default-config element?
Well if jmeter sends the /path then i have changed in line 2: from "sampler.getURL()" to "sampler.getPath()" and then it worked.Mostly thats it - the rest was just making some static stuff more generic.
BrMarkus

    Am Mittwoch, 4. Dezember 2019, 19:16:13 MEZ hat Felix Schumacher <fe...@internetallee.de> Folgendes geschrieben:  
 
 
Am 04.12.19 um 11:33 schrieb glinius@live.com:
> As you correctly mentioned, "it's working perfect on bash". 
>
> Groovy knows nothing about the pipe symbol so you need to execute  bash -c
> command <https://www.gnu.org/software/bash/manual/bash.html>  and pass your
> whole command as the parameter, something like:
>
>
>> "/bin/bash -c \"echo -en \\\"https://my-url.com:8888\\\" | openssl smime
>> -sing -signer cert.crt -inkey cert.key -outform der -binary -md sha384
>> -out blah.p7\"".execute().text


Alternatively you could use groovy's magic to write the url to the stdin
of the openssl process by using something like

p = "openssl smime ...".execute()
p.withWriter { writer -> writer.println("https://...") }
p.text

I find it more readable.  It is probably faster, too, as it doesn't need
to instantiate a shell.

On a side node, groovy's Process instances can be used together with a
pipe symbol inside groovy like the following

p = "date".execute() | "tr a-z A-Z".execute()
p.text

> Groovy neither knows your *$path* environment variable, if the environment
> variable exists and is available to JVM you can read its value using 
> System.getEnv()
> <https://docs.oracle.com/javase/tutorial/essential/environment/env.html>  
> function
>
> It might be easier to go for  OS Process Sampler
> <https://jmeter.apache.org/usermanual/component_reference.html#OS_Process_Sampler> 
> , check out  How to Run External Commands and Programs Locally and Remotely
> from JMeter
> <https://www.blazemeter.com/blog/how-run-external-commands-and-programs-locally-and-remotely-jmeter/>  
> article for details. 
>
> And from the performance perspective instead of calling external
> applications you should rather consider creating the CSR request using i..e 
> BouncyCastle API <https://www.bouncycastle.org/>  

+1


Felix



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@jmeter.apache.org
For additional commands, e-mail: user-help@jmeter.apache.org