InkApplications / Shade

šŸ’” Unofficial SDK for the Philips Hue API written for Kotlin Multiplatform.
https://shade.lighting
MIT License
65 stars 4 forks source link

SSL error running CLI #100

Closed joreilly closed 1 year ago

joreilly commented 1 year ago

Shade Info:

Getting following error when using authorize (discover request is working)

āžœ  bin ./shade authorize --host=<my host ip> --verbose        
Press button on hue bridge to complete
[DEBUG]: Request Json encoded as: {"devicetype":"ShadeCli#default","generateclientkey":true}
[DEBUG]: --> POST https://<my ip address>/api
[DEBUG]: {"devicetype":"ShadeCli#default","generateclientkey":true}
Error: Unknown Error making API Request
inkapplications.shade.structures.NetworkException: Unknown Error making API Request
    at inkapplications.shade.internals.ConfigurableHttpClient.hueRequest(ConfigurableHttpClient.kt:144)
    at inkapplications.shade.internals.ConfigurableHttpClient.access$hueRequest(ConfigurableHttpClient.kt:19)
    at inkapplications.shade.internals.ConfigurableHttpClient$hueRequest$1.invokeSuspend(ConfigurableHttpClient.kt)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
    at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
    at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
    at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
    at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
    at inkapplications.shade.cli.ShadeCommand.run(ShadeCommand.kt:70)
    at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:198)
    at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:211)
    at com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:18)
    at com.github.ajalt.clikt.core.CliktCommand.parse(CliktCommand.kt:395)
    at com.github.ajalt.clikt.core.CliktCommand.parse$default(CliktCommand.kt:392)
    at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:410)
    at com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:435)
    at inkapplications.shade.cli.MainKt.main(Main.kt:46)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1510)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1425)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
    at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
    at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
    at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
    at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
    at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)
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 java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
    at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
    at java.base/sun.security.validator.Validator.validate(Validator.java:264)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:638)
    ... 31 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
    at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
    ... 36 more
ReneeVandervelde commented 1 year ago

So this is a change in the V2 API for Hue Bridges. The devices now use HTTPS certificates for encrypting local traffic. However, since this is a local IP, there is no certificate authority to verify the certificate. By default, Shade defers the validation of the certificate to your system. However, if you have not or cannot manually trust a certificate for the connection on a system level you have other options:


Option 1: Manually trust the hue certificate for just Shade's connection.

This requires a properties file (default location is ~/.shade-cli.properties). For this you will need both the hostname id and IP of the hue bridge. Set the security type to hue:

security=hue
hostname=01234xxabcdef
ip=192.168.1.5

Option 2: Ignore the certificate:

This is similar to how the V1 API operated. For this you can simply use the --insecure flag. Or alternatively, set the security type to insecure in the properties file. This is, as the name suggests, less secure since it ignores the validity of the http certificate.


For the SDK, there are similar details in the Advanced Initialization section. The properties file is documented in [KDocs](http://shade.lighting/reference/latest/structures/inkapplications.shade.structures/-properties-file-configuration/index.html?query=class%20PropertiesFileConfiguration(file:%20File%20=%20File(%20%20%20%20%20%20%20%20System.getProperty(%22user.home%22)%20%20%20%20%20%20%20%20%20%20%20%20.takeIf%20{%20it.isNullOrEmpty()%20==%20false%20},%20%20%20%20%20%20%20%20%22.shade-cli.properties%22%20%20%20%20))%20:%20HueConfigurationContainer)

I'll keep this ticket open to improve the CLI docs a bit with all of these links. In the CLI docs, It's briefly mentioned here