Python/SSL authentification - python

I am trying to connect to the Visa Direct API, but i am not passing the basic SSL certificate authetification, here is my code:
import requests
headers = { 'Content-Type' : 'Application/json' }
url = 'https://sandbox.visa.com/rsrv_vpp/v1/acnl'
payload = {"SystemsTraceAuditNumber":565690,
"RetrievalReferenceNumber":"505012455690",
"AcquiringBin":409999,
"AcquirerCountryCode":"840",
"PrimaryAccountNumber":"4895070000008881"}
r = requests.post(url, data=json.dumps(payload),
cert =('/etc/ssl/certs/sandbox_cert.pem'), headers=headers,
auth=('370df57a-a8aa-4446-a23e-44a0ef06ea09',
'6023e518-c36c-47a8-b16e-c8a5b3a941ef'))
Ass you can see i am using request and passing the cert argument along with the API user and password info but i keep getting the error:
requests.exceptions.SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

I get a SSL error when I try to open https://sandbox.visa.com/rsrv_vpp/v1/acnl in Google Chrome.
The Visa Docs say
SSL Server Authentication
The SSL server certificate installed on sandbox.visa.com servers is a
Visa issued self-signed certificate. Client applications need to add
the sandbox.visa.com SSL certificate to their local trust store to
prevent SSL Handshake errors at runtime.
Ensure that your application that connects to the Visa Direct API is
configured (or built) to use the trusted certificate store as a trust
store, and not a key store.
Verify that the application is configured to use the right password
associated with the trust store file.
It looks like you need to do do some SSL Authentication before you can connect to Visa.

Related

Certificate for Client Authentication

I need your help.
I want to generate a certificate for a client for authorization on my api.
In my use case, I have an API that is hosted with python hypercorn and fastapi. Then I have multiple clients (also python (httpx)) that should request data from this api. For authentication between the client and the server, I want to use certificates. I want to provide the client with a certificate with which it can authorize itself with the server.
For generating the certificates i used this instruction: https://www.makethenmakeinstall.com/2014/05/ssl-client-authentication-step-by-step/
What did I do wrong, or how can I implement my use case?
server:
async def main():
config = Config.from_mapping(dict(
worker_class='trio',
certfile='server.cer',
keyfile='server.key',
verify_mode=VerifyMode.CERT_REQUIRED,
bind=f"0.0.0.0:{8000}"))
async with trio.open_nursery() as nursery:
nursery.start_soon(serve, app, config)
client:
import httpx
res = httpx.get("https://localhost:8000/", verify=True, cert=("client.cer", "client.key"))
res
When I execute the request in the client I get the following error:
ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1123)
let's simplify how certificates work.
certificates used for authentication and authorization and this is what you're exactly doing in your case. your backend-server has its own certificate, and your client has his own certificate. your applications is set to recognize each other using these certificates and you're doing it in a great way.
but certificates are vulnerable and can be created locally, so I myself can create a certificate that says that I'm facebook or google. and here is the validation's role come; a well know authority that's already implemented in all browsers and OS - and we call it CA for a certification authority - signs your certificates, so when your server send its cert to a client, the client's browser would recognize the signature and tells you that the certificate is valid.
in your case here you have a self signed certificate, which means that for development purpose you've signed your cert by yourself "instead of the recognized CAs".
Overcoming such an issue would be in two ways.
you disable the validation in your code and in your client side as well. suits for development purpose or intra network.
sign your certificate and your client's certificate with a recognized authority like digicert, and add your CA in your trust-store.

Disable Client Authentication for python HTTPS requests

Currently my client side HTTPS request code looks like this:
resp = requests.post(endpoint_predict_v100, files={'image': open(file_path, 'rb')}, verify=client_auth,
cert=(client_cert_path, client_secret_path))
This is an HTTPS request, the server root CA is client_auth and the client certificate and key are client_cert_path and client_secret_path.
because my server code is deployed and I cannot change much on that side, I am wondering if I can do the following on the client side:
enable server authentication only when the server root CA is provided by the client
enable client authentication only when the client cert and key are provided by the client.
I have found out that I am able to do the first thing, "enable server authentication only when the server root CA is provided by the client", by passing verify=False if the server root CA is not presented on the client side., referring to the Python requests docs. However, when I try to remove the cert=(client_cert_path, client_secret_path), the request will fail, throwing this error:
ssl.SSLError: [SSL] tlsv13 alert certificate required (_ssl.c:2570)
It seems that this error is suggesting I must pass in the client cert and key to make the server accept my request. but is there a way to disable client authentication on the client side, when the client cert and key are not present?
ssl.SSLError: [SSL] tlsv13 alert certificate required (_ssl.c:2570)
... is there a way to disable client authentication on the client side, when the client cert and key are not present?
The alert you get is because the server is requiring the client certificate. Since it is required by the server it is not sufficient to change some client side behavior only. This is similar to a server requesting authentication by password - this cannot be simply skipped in the client too.
With many servers there is a way to have client certificates optional, i.e. request a client certificate but don't insist that one is sent. How to do this with your specific server and if it is supported by your server at all is unknown though.

Can't send GET to HTTPS service with cert, error: certificate verify failed: self signed certificate

I'm trying to send a GET request to a host with (supposedly) correct certificates.
It's a university task, and they gave me these certificates. (which are only valid for 30 seconds)
But the code below gives me the error that certificate verify failed: self signed certificate
The package I got from the host in response says that Fatal Error: Unknown CA.
What could cause the issue? Thanks!
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain('clientcert.pem', keyfile='clientkey.pem')
connection = http.client.HTTPSConnection(IP)
connection.request("GET", "/")
response = connection.getresponse()
print("response:", response)
The error message seems to be self-explanatory. Self-signed SSL certificates always cause security warnings/errors. You will either need to add your self-signed SSL as an exception or add the self-signed CA to OS trusted certificates pool.
You may also try using something identical to --insecure option in curl.

Python - SSL: CERTIFICATE_VERIFY_FAILED

I have a python script that uses the VirusTotal API. It has been working with no problems, but all of a sudden when I run the script I am getting the following error:
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>
I believe it may be our web proxy that is causing the issue. Is there a way to prevent it from verifying the cert? Here is the portion of the code that uses the API:
json_out = []
url = "https://www.virustotal.com/vtapi/v2/file/report"
parameters = {"resource": my_list,
"apikey": "<MY API KEY>"}
data = urllib.urlencode(parameters)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
json_out.append (response.read())
I believe it may be our web proxy that is causing the issue. Is there a way to prevent it from verifying the cert?
If you assume that a SSL intercepting proxy is denying the connection then you have to fix the problem at the proxy, i.e. there is no way to instruct the proxy to not check the certificate from your application.
If instead you assume that there is a SSL intercepting proxy and thus the certificate you receive is not signed by a CA you trust then you should get the CA of the proxy and trust it in your application (see cafile parameter in the documentation). Disabling validation is almost never the right way. Instead fix it so that validation works.
There are two possibilities,
You are using a self-signed certificate. Browsers don not trust on such certificate, so be sure that you are using CA-signed trusted certificate.
If you are using CA-signed trusted the certificate that you should have to check for install CA chain certificates (Root and Intermediate certificate).
You can refer this article, it may help you. - https://access.redhat.com/articles/2039753

How to connect to a SOAP service (without WSDL) using SSL and authentication in Python?

I want to connect to a SOAP API that does not have WSDL in Python. To connect I need to a add a SSL certificate and authenticate afterwards.
from pysimplesoap.client import SoapClient, SimpleXMLElement
cacert = open(path, 'rb').read() # read the certificate
header = SimpleXMLElement('<Header/>')
credentials = header.add_child('Credentials')
credentials.marshall('Password', 'password')
credentials.marshall('Username', 'username')
client = SoapClient(
location="https://mytest.com/Services/",
cacert=cacert)
client['Header'] = header
client.action = "https://mytest.com/Services/Action1"
client.Action1() # gives SSL error
The result I receive is a SSL error:
SSLHandshakeError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Can anyone, please, tell me how to solve this issue? Or can you advise any other library I can use. Most SOAP libraries I found offer connection only to WSDL.
Usually in a pfx file there is the client certificate with key, not the CA file. The libraries seems to expect the client certificate as PEM. You should extract the certificate and the key as show in https://stackoverflow.com/a/9516936/3929826.
Then hand it in to the SoapClient() initiation as cert and key_file argument:
client = SoapClient(location="https://mytest.com/Services/",
cert='mycert.pem',
key_file='mycert.key)
It should also be possible to put both into the cert file.
If that still does not work your have to add the CA certificate as the cacert parameter after you retrieved it as described in https://stackoverflow.com/a/7886248/3929826 .
For further reference see the source code of simplesoap: https://code.google.com/p/pysimplesoap/source/browse/pysimplesoap/client.py#75 .

Categories

Resources