# API Endpoint Certs

**URL:** <https://forum.inductiveautomation.com/t/api-endpoint-certs/55461>\
**Category:** Ignition\
**Created:** [January 28, 2022, 12:03am UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461 "2022-01-28T00:03:44Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [January 28, 2022, 12:03am UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/1 "2022-01-28T00:03:44Z")

</div>

When calling an API (in this case graphql) if I set the following, the call and response goes through OK:

```auto
client = system.net.httpClient(bypass_cert_validation=True)

```

However without bypassing the cert validation I see the following when posting:

> caused by: sun.security.validator.validatorexception: pkix path building failed: sun.security.provider.certpath.suncertpathbuilderexception: unable to find valid certification path to requested target

As far as I have read, I need to get the cert from the endpoint and place it on the machine running Ignition. In which directory should that be placed?

Thanks,

Nick

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 28, 2022, 12:12am UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/2 "2022-01-28T00:12:30Z")

</div>

See this for a starting point:

> [@Server returned HTTP response code: 403](https://forum.inductiveautomation.com/t/server-returned-http-response-code-403/55370/4):
>
> You can use pure Java APIs. If you’re on Ignition 8 it’s gonna be something like what is detailed here: [java - JDK11 HttpClient mutual tls - Stack Overflow](https://stackoverflow.com/questions/63022464/jdk11-httpclient-mutual-tls)

There's no specific file location; you'd need to scaffold an SSLContext with the appropriate cert installed.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [January 28, 2022, 12:39am UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/3 "2022-01-28T00:39:29Z")

</div>

I think you’ve mixed it up - he just needs to get the certificate and add it to the supplemental certs folder.

[https://docs.inductiveautomation.com/display/DOC81/Adding+Security+Certificates+into+Keystores](https://docs.inductiveautomation.com/display/DOC81/Adding+Security+Certificates+into+Keystores)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 28, 2022, 4:04pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/4 "2022-01-28T16:04:40Z")

</div>

Oh, yeah, you’re right; he’s not doing mutual TLS, just wants to trust the server. Nevermind then.

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [February 21, 2022, 5:29pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/5 "2022-02-21T17:29:09Z")

</div>

@Kevin.Herron following that instruction to place in supplemental certs I have placed the root certificate of the target endpoint (Kafka Lenses) into the folder as follows and restarted the service.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/c/ac88b17897474737ea36e7b11a23cad3bd2ecc2a.png)

However, I still see the following. Is there some other action I need to do like import the cert using keytool?

> java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Thanks,

Nick

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 21, 2022, 5:44pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/6 "2022-02-21T17:44:09Z")

</div>

No, that should be it for Ignition 8.x. What scope are you testing your scripting call in? Adding it to the supplemental cert folder only brings it in for the gateway scope.

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [February 21, 2022, 5:51pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/7 "2022-02-21T17:51:11Z")

</div>

Right now I’m working in the script console to get it up to the point where I can get a response and learn how to parse through it. The end game will be on a gateway script timer or in a UDT.

This machine runs 8.1.13. Sorry if this is duplicate but its related to web sockets. What we are trying to do is have a way to get a filtered response from Kafka since the topic itself is terabyte size. The Lense SQL api allows this and I have it working in the google web socket tested.

Just working through the mechanics of making it work in the ignition environment.

Thanks,

Nick

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 21, 2022, 5:54pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/8 "2022-02-21T17:54:56Z")

</div>

Make a gateway message handler that delegates to a script module. In the designer script console, use system.util.sendRequest() to trigger your code and receive the result. The actual request to Kafka will then come from the gateway as you intend in the future, and will use its certificate store.

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [February 21, 2022, 6:42pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/9 "2022-02-21T18:42:10Z")

</div>

I am going to merge this thread into this:

> [@WebSocket Client](https://forum.inductiveautomation.com/t/websocket-client/44447/20):
>
> You are discarding the return value from .buildAsync(). Don’t do that. You need it to .get() the finished websocket object.

The summary here is that by moving this to a gateway script (as opposed to running it all from the script console) overcomes the error named:

> unable to find valid certification path to requested target

Thanks,

Nick

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [April 3, 2023, 1:47pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/10 "2023-04-03T13:47:51Z")

</div>

@paul-griffith I have a different case now that does require the use of mutual TLS. As I read above the system.net.httpClient native to Ignition cannot do mTLS, is that correct?

My eventual target is in Java but for testing it is often convenient to get things working from the python script console first.

Thanks,

Nick

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [April 3, 2023, 2:03pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/11 "2023-04-03T14:03:00Z")

</div>

Correct, it's not supported.

It's more awkward than it should be even in pure Java, as you'll gather quickly from Google/StackOverflow posts.

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [April 3, 2023, 2:17pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/12 "2023-04-03T14:17:38Z")

</div>

Yeah, that is what I am seeing. Anyways, once I do get it figured out in Java, I'll post it back up here so the next person that comes along can use it for reference.

Here the SSL cert auto-renewal API that we are starting to work with requires mTLS.

Nick

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [April 4, 2023, 1:19pm UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/13 "2023-04-04T13:19:01Z")

</div>

FWIW, this code here allows us to get through the SSL handshake successfully:

```auto
public class JavaHttpClientTest {
    public static void main(String[] args) {
        String appId = "";
        String commonName = "";
        String teamDL = "";
        String certPath = "";
        char certPass[] = "".toCharArray();
        try {
            String urlString = "";
            urlString = String.format(urlString+"?appID=%s&commonName=%s&teamDL=%s", appId, commonName, teamDL);
            System.out.println(urlString);

            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(new FileInputStream(certPath), certPass);

            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, certPass);

            SSLContext ctx = SSLContext.getInstance("TLSv1.3");
            ctx.init(keyManagerFactory.getKeyManagers(), null, null);

            HttpClient client = HttpClient.newBuilder().sslContext(ctx).build();
            HttpRequest request = HttpRequest.newBuilder().uri(URI.create(urlString)).GET().build();
            var response = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).join();
            System.out.println(response.statusCode());
            System.out.println(response.body());
        } catch (Exception e) {
            System.out.println(e.getCause());
        }
    }
}

```

And to make the entire handshake work, it was also necessary to add the server cert to the JVM cacert store with the advice listed [here](https://stackoverflow.com/questions/21076179/pkix-path-building-failed-and-unable-to-find-valid-certification-path-to-requ). You can download the server cert directly from the browser, we downloaded in PKCS7 format.

Nick

---

<div class="post-metadata">

**Author:** ![david.guerra](https://avatars.discourse-cdn.com/v4/letter/d/dfb087/32.png) [@david.guerra](https://forum.inductiveautomation.com/u/david.guerra)\
**Post date:** [January 31, 2024, 4:14am UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/14 "2024-01-31T04:14:46Z")

</div>

Hey Nick,

Just curious how exactly you are running this java script and how you were able to call it in ignition?

---

<div class="post-metadata">

**Author:** ![nicholas.robinson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nicholas.robinson/32/22188_2.png) [@nicholas.robinson](https://forum.inductiveautomation.com/u/nicholas.robinson)\
**Post date:** [January 31, 2024, 10:32am UTC](https://forum.inductiveautomation.com/t/api-endpoint-certs/55461/15 "2024-01-31T10:32:06Z")

</div>

All code written in Java is executed in Ignition via module development. This post may be of some use if you're just getting started with modules:

[How do you create your own MODL file - Module Development - Inductive Automation Forum](https://forum.inductiveautomation.com/t/how-do-you-create-your-own-modl-file/51562/8)

Ignition is also starting to add more training resources on how to build modules.

Nick
