1

I'm new to Locust and I'm trying to get a barebones https GET to run requesting a servers index page.

locustfile.py

import time
from locust import HttpUser, task

class QuickstartUser(HttpUser):
    @task
    def index(self):
        self.client.get("/")

my.conf

locustfile = locustfile.py
headless = true
expect-workers = 5
host = https://localhost:8001/
users = 100
spawn-rate = 10
run-time = 10m
csv = out

To start the process, I use: locust --conf my.conf

I expected it to work, but it seems to have authentication problems. Loss rate is 100%

Out:

 Name                                                          # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
 GET //                                                           806 806(100.00%)  |     318      15     729     290  |   94.26   94.26
--------------------------------------------------------------------------------------------------------------------------------------------
 Aggregated                                                       806 806(100.00%)  |     318      15     729     290  |   94.26   94.26

Response time percentiles (approximated)
 Type     Name                                                              50%    66%    75%    80%    90%    95%    98%    99%  99.9% 99.99%   100% # reqs
--------|------------------------------------------------------------|---------|------|------|------|------|------|------|------|------|------|------|------|
 GET      //                                                                290    390    450    510    570    630    680    710    730    730    730    806
--------|------------------------------------------------------------|---------|------|------|------|------|------|------|------|------|------|------|------|
 None     Aggregated                                                        290    390    450    510    570    630    680    710    730    730    730    806


Error report
 # occurrences      Error
--------------------------------------------------------------------------------------------------------------------------------------------
 806                GET //: SSLError(MaxRetryError("HTTPSConnectionPool(host='localhost', port=8001): Max retries exceeded with url: // (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1123)')))"))
--------------------------------------------------------------------------------------------------------------------------------------------
blkpingu
  • 1,556
  • 1
  • 18
  • 41
  • I posted an answer regarding https. That shouldn't make Locust not work, though. And you don't give a lot of information about what you're actually trying to do and what you're seeing happen. Does your locustfile.py work if you run it directly? Are you running distributed? If so, how are you running the workers? – Solowalker Jan 13 '21 at 22:14

2 Answers2

2

Locust works with https URLs just fine without having to do any kind of configuration if all you want to do is just hit an endpoint using https, which is why the docs don't say anything about how to do it; for basic operation, there's nothing to configure. You don't even have to use those tls-cert and tls-key options as those would be for forcing a specific cert and key to be used. If that's what you want, great. It should work.

If you want to do something more advanced, check out this FAQ: https://github.com/locustio/locust/wiki/FAQ#control-headers-or-other-things-about-my-http-requests

Which means you need to know more exactly what you're looking to do. For something like cert verification, this may be helpful:

https://2.python-requests.org/en/latest/user/advanced/#ssl-cert-verification

EDIT:

In the case of the error you get when you don't specify the cert, that's working as expected. A self-signed cert is not good to have in production so most proper clients will throw an error about that. In this case since you're just trying to get a proof of concept up, you may want to either include verify=False in your .get() call (see Python Requests throwing SSLError for more details and warnings about keeping that around), or you can specify your self-signed cert for the client to verify with. In that case, you may use the tls-cert option in the config like you had before. Make sure you include the path to it. And you probably want the .pem and not .crt.

Solowalker
  • 2,431
  • 8
  • 13
  • so I should just scratch the config options for tls and it should work? I did that but it has a 100% loss rate quoting ssl problems. I updated the question accordingly – blkpingu Jan 13 '21 at 22:17
  • Updated my answer to address your updates. – Solowalker Jan 13 '21 at 22:36
  • so in order to reduce failures, i'd have to go with `self.client.get("/", verify="my.crt")` and leave the rest as it is? – blkpingu Jan 13 '21 at 23:14
  • Tested this, and it's not working as expected. I expected it would start to accept my http requests, but the test isn't getting traction and seems to ignore the`get()` – blkpingu Jan 14 '21 at 10:15
  • 1
    Did you try `self.client.get("/", verify=False)`? You can do that first to make sure everything else is working and then figure out how to get the cert to be verified. Make sure the cert you're using is a public key (usually `.pem`); `.crt` usually has much more than the public key so I'm not positive it would work here. – Solowalker Jan 14 '21 at 14:07
  • It worked in the end because our C server had an untested edge case where "/" is producing a valid http GET, but the path get's handled as "GET // ...", so yea, it worked with verify. Thanks. Also reading [locusts request method](https://github.com/locustio/locust/blob/7ff1baac697a735205ae05dd4596fd59a6b00d92/locust/clients.py#L75) i saw it needs a `cert` arg, in case of `verify=True`. `self.client.get(''', verify=True, cert=('my.crt', 'my.key'))` – blkpingu Jan 14 '21 at 18:14
  • For those using **self-signed certificates**: You have to add your custom `.crt` to your system's trusted certificates, specify the [REQUESTS_CA_BUNDLE](https://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification) environment variable **and** re-enable `requests.Session.trust_env` (`self.client.trust_env = True`) which [locust disables by default](https://github.com/locustio/locust/blob/cce0d29b90e5e9f9dad7a7b96b25a393923c4a16/locust/user/users.py#L234). – Panos Argyrakis Jan 04 '22 at 13:06
1

Adding to Solowalkers answer:

In case somebody wants to reproduce my findings.

Locusts request method demands a cert tuple in case of verify=True. So if you don't have a .pem, use this.

locustfile.py (actually name it that or use locust -f yourname.py)

import time
from locust import HttpUser, task
import urllib3

# surpress verify warnings from urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class QuickstartUser(HttpUser):
    @task(10)
    def index(self):
        self.client.get('', verify=True, cert=('my.crt', 'my.key'))

client.conf (not important to name it that. There is however a cascading load order for the .confs. Read the docs for more info.

locustfile = locustfile.py
headless = true
expect-workers = 5
host = https://localhost:8001/ # change for server
users = 1                      # one user for proof of concept
spawn-rate = 1
run-time = 10m
csv = out

start in the dir with these files with: locust --conf client.conf Locust finds the locustfile.py itself if it's named that.

blkpingu
  • 1,556
  • 1
  • 18
  • 41