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 
<[email protected]> Folgendes geschrieben:  
 
 
Am 04.12.19 um 11:33 schrieb [email protected]:
> 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: [email protected]
For additional commands, e-mail: [email protected]

  

Reply via email to