Swagger-codegen: Make SSL checks lenient for faulty HTTPS certificates

Created on 7 Oct 2014  路  31Comments  路  Source: swagger-api/swagger-codegen

Testing swagger codegen against a service provided by one of our partners, I fail because the HTTPS certificate used in their testbed environment obviously doesn't really match their DNS hostname:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at scala_maven_executions.MainHelper.runMain(MainHelper.java:164)
    at scala_maven_executions.MainWithArgsInFile.main(MainWithArgsInFile.java:26)
Caused by: java.lang.Exception: unable to read from https://lab.xx.yyy.com/api/core
    at com.wordnik.swagger.codegen.BasicGenerator.generateClientWithoutExit(BasicGenerator.scala:62)
    at com.wordnik.swagger.codegen.BasicGenerator.generateClient(BasicGenerator.scala:47)
    at com.wordnik.swagger.codegen.BasicJavaGenerator$.main(BasicJavaGenerator.scala:22)
    at com.wordnik.swagger.codegen.BasicJavaGenerator.main(BasicJavaGenerator.scala)
    ... 6 more
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching lab.xx.yyy.com found.
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:295)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1369)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:156)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:925)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:860)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1511)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at com.wordnik.swagger.codegen.util.RemoteUrl$class.urlToString(RemoteUrl.scala:30)
    at com.wordnik.swagger.codegen.util.ResourceExtractor$.urlToString(ResourceExtractor.scala:27)
    at com.wordnik.swagger.codegen.util.ResourceExtractor$.fetchListing(ResourceExtractor.scala:30)
    at com.wordnik.swagger.codegen.BasicGenerator.generateClientWithoutExit(BasicGenerator.scala:60)
    ... 9 more
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching lab.xx.yyy.com found.
    at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:191)
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1351)
    ... 25 more

This seems an issue not too uncommon (see [1] in example), but the solutions in here aren't applicable to me as I can't do anything about the certificate used here and I don't right now want to hack into the code generator to apply any of the Java based solutions (like the one outlined in [1]).

Would it be possible to introduce a parameter to codegen to ignore SSL errors like this?

[1] https://stackoverflow.com/questions/19540289/how-to-fix-the-java-security-cert-certificateexception-no-subject-alternative

Bug

Most helpful comment

Use -Dio.swagger.parser.util.RemoteUrl.trustAll=true to disable certificate verification.

All 31 comments

Can you please see here:

https://github.com/swagger-api/swagger-codegen/blob/master/src/main/scala/com/wordnik/swagger/codegen/util/RemoteUrl.scala#L36

println("**** you may want to run with -Djsse.enableSNIExtension=false\n\n")

@fehguy The link you posted is dead. Is there an official way to use codegen against swagger specs hosted on servers with invalid certificates (self-signed, for instance)?

The parser now should support invalid certs, and therefore support codegen reading invalid certs as well. Are you seeing otherwise?

Yes, I have built codegen from master and am using the following to build an API client:

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-a "Authorization: Basic redacted" \
-l ruby \
-o /tmp/ruby-api-sample/ \
-i https://some.host/api/v1/api-docs \
-v

The server is using a self-signed certificate... I get errors like the following:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

A basic question I have is whether there is a specific option I have to pass to disable certificate validation?

Same issue here...

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

@fehguy Could you please tell how to disable certificate verification in swagger codegen?

I'll look into this later today.

I could repeat the issue with the following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1904)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:279)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:273)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1446)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:901)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:837)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1023)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
    at io.swagger.parser.util.RemoteUrl.urlToString(RemoteUrl.java:135)
    at io.swagger.parser.Swagger20Parser.read(Swagger20Parser.java:82)
    at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:64)
    at io.swagger.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:394)
    at io.swagger.codegen.cmd.Generate.run(Generate.java:228)
    at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:36)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1428)
    ... 16 more

I'll take a look at the swagger parser to see how that can be handled in a better way.

For the time being, please download the file to your local drive as a workaround.

@lgustafson @panih2o @DenisBiondic do you have an URL to swagger spec with invalid cert that I can test?

@wing328 Can you rather google how to invalidate a certificate and don't tell me you guys don't have a testbed to test things on? And which file is that we should download?

Please use https://tv.eurosport.com/ as an example of an expired certificate. Point any swagger java client to it and it should throw an ssl exception. Normally it should throw a 404, since it won't have the swagger endpoints implemented.

Is there any ability for swagger java clients to connect to invalid ssl certificates?

I have the same issue, could I disable certificate verification now?

Use -Dio.swagger.parser.util.RemoteUrl.trustAll=true to disable certificate verification.

Thanks @SteffenE this was very helpful :)

C# variant of this solution?

@philipbohannon please open a new issue for C# API client instead as this issue referring to the generator itself (not the auto-generated API clients)

Thanks, @wing328 , I missed that distinction on first read. Will do.

I have this error with https://esi.tech.ccp.is/ server (https://esi.tech.ccp.is/latest/alliances/?datasource=tranquility&user_agent=userAgent_example). Certificate is valid and good quality. And I have this issue only on one computer. On the other it works fine...

Given that it works in one machine but not another, it's more likely the issue is with the machine setting rather than Swagger Codegen.

I reinstall my JDK with latest version and it solve my problem. Thank you to fast response.

Latest and all snapshot versions complaining: swagger-codegen: error: unrecognized arguments: '-Dio.swagger.parser.util.RemoteUrl.trustAll=true'

Here is entry point from docker file:

ENTRYPOINT ["java", "-jar", "swagger-codegen-cli.jar", "generate", "-l", "typescript-angular", "-Dio.swagger.parser.util.RemoteUrl.trustAll=true", "-o", "/code", "-i"]

-Dio.swagger.parser.util.RemoteUrl.trustAll=true allows me get the work done but is's just dirty workaround not a solution. I have the same:

SunCertPathBuilderException: unable to find valid certification path to requested target

while the certificate is perfectly valid. Codegen version used is 2.3.1.

@Gladskih please open a ticket with your feedback in the Swagger Parser repo: https://github.com/swagger-api/swagger-parser

Can someone suggest on how to add -Dio.swagger.parser.util.RemoteUrl.trustAll=true in pom.xml for swagger code gen.

have the same problem as @arpitkh12 . Is there a way to add trustAll as a plugin config property for maven ? @wing328

@PeteGashek thanks for tagging me but I'm no longer involved in this project. I hope others will be able to help you out. Good luck.

@PeteGashek @arpitkh12 Did any of you found a solution to add the property in pom.xml?

in powershell using -Dio.swagger.parser.util.RemoteUrl.trustAll=true results in "Found unexpected parameters". In that case, putting a space after -D

-D io.swagger.parser.util.RemoteUrl.trustAll=true

solves the problem

edit: format powershell code for better readability

Had to slightly change it to
-Dio.swagger.v3.parser.util.RemoteUrl.trustAll=true
And that did the trick for me

-Dio.swagger.v3.parser.util.RemoteUrl.trustAll=true

[DEPRECATED] -D arguments after 'generate' are application arguments and not Java System Properties, please consider changing to -p, or apply your options to JAVA_OPTS, or move the -D arguments before the jar option.

Can someone suggest on how to add -Dio.swagger.parser.util.RemoteUrl.trustAll=true in pom.xml for swagger code gen.

This worked for me.

<plugin>
  ...
  <executions>
    <execution>
      ...
      <configuration>
      ...
      <environmentVariables>
        <io.swagger.parser.util.RemoteUrl.trustAll>
        true
        </io.swagger.parser.util.RemoteUrl.trustAll>
      </environmentVariables>
      ...
     </configuration>
   </execution>
  </executions>
</plugin>
Was this page helpful?
0 / 5 - 0 ratings