Reputation: 1806
I'm doing REST request against an https api server, its working in soapui using the configuration below,
I've added the certificate on the SSL Settings>Keystore
the self-signed-keystore.jks has key pair that is trusted on the server and is being checked for each requests. If the certs are valid the server will return a json
tried this in python using this code, its not working I'm getting an error on SSL
requests.exceptions.SSLError: HTTPSConnectionPool(host='xlocal', port=8014): Max retries exceeded with url: //api/path/here (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))
#!/usr/bin/env python3
import sys
import requests
API_ENDPOINT = "https://xlocal:8xxx/api/test/list"
#pem keys are exported from the jks using keytool explorer or
#openssl pkcs12 -in soapui-keystore.p12 -nokeys -out soapuicert.pem
#openssl pkcs12 -in soapui-keystore.p12 -nodes -nocerts -out soapuikey.pem
NEW_CERT = r"C:\Users\myuser\self-signed-exported.cert.pem"
NEW_KEY = r"C:\Users\myuser\self-signed-exported.key.pem"
def main(argv):
get = requests.get(API_ENDPOINT, cert=(NEW_CERT, NEW_KEY))
get2 = requests.get(API_ENDPOINT, verify=NEW_CERT)
print(get)
print(get2)
if __name__ == "__main__":
main(sys.argv[1:])
Its working on Java using this code, below.
public void getforObject() {
restTemplate = new RestTemplate();
try (FileInputStream fis = new FileInputStream(Project.keystorePath)) {
KeyStore keyStore = SSL.getKeyStore(fis, Project.keystorePassword);
SSLSocketFactory sslSocketFactory = SSL.getSSLSocketFactory(keyStore, Project.keystorePassword, trustAllCerts);
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslSocketFactory, (hostname, session) -> true);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
restTemplate.setRequestFactory(httpRequestFactory);
String forObject = restTemplate.getForObject(LIST_URL, String.class);
} catch (Exception e) {
//SystemLogger.error("Error configuring ssl", e);
throw new RuntimeException("Error: unable to configure ssl.", e);
}
}
public class DummyX509TrustManager implements X509TrustManager {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString)
throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString)
throws CertificateException {
}
}
What seems to be the issue? Is there a better way to do this in python?
Upvotes: 2
Views: 3644
Reputation: 11
I was able to solve this issue by adding pem file in the request. You will need to create a pem file from p12 file with the following command.
openssl pkcs12 -in soapui-keystore.p12 -out self-signed-exported.pem
Code Snippet:
NEW_CERT = r"C:\Users\myuser\self-signed-exported.cert.pem"
NEW_KEY = r"C:\Users\myuser\self-signed-exported.key.pem"
PEM_FILE=r"C:\Users\myuser\self-signed-exported.pem"
get = requests.get(API_ENDPOINT, verify=PEM_FILE, cert=(NEW_CERT, NEW_KEY))
Upvotes: 1
Reputation: 613
I suspect the problem is not your python code, but the certificate chain that you're supplying.
It's not sufficient to make available the certificate for your private key - you must supply the certificate for your key, plus every other certificate in a chain that terminates in a trusted certificate authority.
The openssl commands you're being asked to run will dump the certificate chain (which is generally public). That you can find your key's certificate in the pem file doesn't mean the certificate chain is complete or correct.
Upvotes: 0