# GAN Remote Certificates - Auto Approval

**URL:** <https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385>\
**Category:** Ignition\
**Created:** [August 24, 2022, 10:55am UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385 "2022-08-24T10:55:42Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![derrickdvdsn](https://avatars.discourse-cdn.com/v4/letter/d/3d9bf3/32.png) [@derrickdvdsn](https://forum.inductiveautomation.com/u/derrickdvdsn)\
**Post date:** [August 24, 2022, 10:55am UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/1 "2022-08-24T10:55:42Z")

</div>

1. How to automatically approve certificates for Incoming GAN connections?
2. When the certificate is approved, is it saved in the internal db?
3. What Java classes are used to read the status of the certificates of the Incoming connections that are not yet approved?

Thanks in advance

---

<div class="post-metadata">

**Author:** ![apalas](https://avatars.discourse-cdn.com/v4/letter/a/e47774/32.png) [@apalas](https://forum.inductiveautomation.com/u/apalas)\
**Post date:** [August 30, 2022, 8:36pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/2 "2022-08-30T20:36:20Z")

</div>

Hi Derrick,

Could you give us more details on what you’re trying to do with this information first? And what version of Ignition are you are planning to attempt this on?

---

<div class="post-metadata">

**Author:** ![ggross](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ggross/32/12668_2.png) [@ggross](https://forum.inductiveautomation.com/u/ggross)\
**Post date:** [August 30, 2022, 11:58pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/3 "2022-08-30T23:58:21Z")

</div>

The best way to do this would be to create metro-keystore’s using your own CA. Process would be something like the following (assuming a Java JDK and openssl are installed):

1. Create a new keystore:

```auto
keytool -genkey -alias metro-key -keyalg RSA -keysize 2048 -keystore metro-keystore

```

1. Create a new Certificate Signing Request using the above keystore:

```auto
keytool -certreq -alias metro-key -file metro-keystore.csr -keystore metro-keystore

```

1. Sign the request using your CA. When doing this, I have the following in my `openssl.cnf` file for use with the `extensions` flag and adjust the `subjectAltName` part as necessary:

```auto
####################################################################
		# Metro Keystore
		[metro]
		keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign
		extendedKeyUsage = clientAuth, serverAuth
		subjectAltName = IP:127.0.0.1, DNS:gw*, URI:uri://*/metro
		subjectKeyIdentifier = hash
		authorityKeyIdentifier = keyid, issuer

```

Example signing command:

```auto
openssl ca -config ../openssl.cnf -extensions metro -out metro-keystore.pem -infiles metro-keystore.csr

```

1. Import your root public key for your CA:

```auto
keytool -import -trustcacerts -alias root -file ../root/root-ca.crt -keystore metro-keystore

```

1. Import signed certificate

```auto
keytool -import -trustcacerts -alias metro-key -file metro-keystore.pem -keystore metro-keystore

```

The above should get you a keystore that can be placed in the `{IGNITION_HOME}/webserver` directory. It would replace the file that is already there.

There are a couple of other things that are needed to make this work:

1. The default password for the metro-keystore is `metro`. The above process will not allow you to use this password because it is too short. Instead you will have to set it to something else and tell Ignition about it. This is done by:
  1. Open `{IGNITION_HOME}/data/ignition.conf`
  2. Find the `# Java Additional Parameters` header in the file
  3. Add `wrapper.java.additional.<#>=-Dmetro.keystore.password=<Your Password>` replacing the `<#>` with a number that isn’t being used and `<Your Password>` with the password you set for the keystore.

2. Ignition must trust your root certificate. You must put the public key in the following directory (as of 8.1.14) and anything signed by that cert will be automatically trusted.:  
`{IGNITION_HOME}/data/gateway-network/client/security/pki/trusted/certs`.

The certificate isn’t saved in the internal DB, but the approval of the connection is. There are different options of configuring a Gateway for allowing connections but your options boil down to:

1. Trust anything with a trusted cert
2. Manually approve everything (can be done via a WebDev API endpoint if you can build it)
3. Whitelist specific Gateways

In terms of what Java classes you can use to get Incoming connections, you would need to use a combination of the following:

```auto
com.inductiveautomation.ignition.gateway.IgnitionGateway
com.inductiveautomation.ignition.gateway.gan.IncomingConnection
simpleorm.dataset.SQuery

```

Garth

---

<div class="post-metadata">

**Author:** ![derrickdvdsn](https://avatars.discourse-cdn.com/v4/letter/d/3d9bf3/32.png) [@derrickdvdsn](https://forum.inductiveautomation.com/u/derrickdvdsn)\
**Post date:** [September 12, 2022, 11:16am UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/4 "2022-09-12T11:16:11Z")

</div>

Hey @ggross ,

Thank you for your response, I have a couple of questions

1. Are the “Extensions” mandatory for the certificate?
2. since the instance of ignition will be hosted on a kubernetes pod, I don’t know for sure what IP address will be used, how do we tackle this?
3. How do we test/know if the keystore that we have generated is correct, because I have created a keystore but my local instance of ignition went down after that.(Please refer my keystore and conf file)

keystore password = metroPassword

I used openssl x.509 command to sign the certificate as opposed to the openssl ca command, will this create any issues?

Do you have any experience with the Keystore Explorer tool? It looks like I can access the default Keystore with the ‘metro’ password and even import certificates but I am not able to create a certificate chain once it is imported.

Also can you share your copy of the openssl.cnf file? I Keep getting this error when using the openssl ca command to sign  
“Using configuration from openssl.cnf  
variable lookup failed for ca::default\_ca”

Thank you in advance  
[metro-keystore.zip](https://forum.inductiveautomation.com/uploads/short-url/8eVVyc0qsALP8sLRa0UsgxPPmJD.zip) (9.1 KB)

---

<div class="post-metadata">

**Author:** ![ggross](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ggross/32/12668_2.png) [@ggross](https://forum.inductiveautomation.com/u/ggross)\
**Post date:** [September 12, 2022, 6:04pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/5 "2022-09-12T18:04:44Z")

</div>

Hi @derrickdvdsn,

1. The extensions aspect, specifically `subjectAltName`, of the certificate extensions is required but the IP aspect of it is not. If you will be connecting everything via hostname, then the `DNS` and `URI` parts of the `subjectAltName` would be all that you would need. Keep in mind my example is using wildcards and you would need to make your trusted items a lot more narrow than what I provided.
2. See 1. If you have a fully qualified domain name for these pods, you would want to use that when creating the certificate for the Subject Alternate Name, if everything can be reached via hostname (which I doubt will occur in a production environment) using a hostname would be an option.
3. It looks like your `ignition.conf` file isn’t setup correctly as it is missing the `wrapper` key at the beginning. It is currently:

```auto
java.additional.11=-Dmetro.keystore.password=metroPassword

```

if should be:

```auto
wrapper.java.additional.11=-Dmetro.keystore.password=metroPassword

```

The certificate itself looks like it was created properly and is loading into my local Ignition instance. Once you get Ignition started by fixing the configure file, you can confirm this by logging into the Gateway and navigating to the `Config > Networking > Gateway Network > Diagnostics` screen. Under `Local Certificate Information` you will see the information you provided when creating the certificate.

Using `openssl x.509` you should be fine as long as you are able to add the `x509v3_config` options. While I have not configured a certificate this way myself, they all adhere to a specific format to be trusted. The certificate just needs to contain everything the client and server require to negotiate a connection.

While I have used Keystore Explorer to validate the contents of a keystore, I haven’t tried to replace anything. I know I have helped people do it in the past, but the details on how to do it escape me.

Here is what my `openssl.cnf` looks like. Keep in mind that while I have this working, I am by no means an expert in how certificates and their options work. You will need to confirm the options used to sign the certificates match you organization’s security policies:  
[openssl.cnf.zip](https://forum.inductiveautomation.com/uploads/short-url/1ulIDrGKNVNOMXGethwvI0D1j0.zip) (1.9 KB)

Garth

---

<div class="post-metadata">

**Author:** ![derrickdvdsn](https://avatars.discourse-cdn.com/v4/letter/d/3d9bf3/32.png) [@derrickdvdsn](https://forum.inductiveautomation.com/u/derrickdvdsn)\
**Post date:** [September 12, 2022, 6:09pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/6 "2022-09-12T18:09:13Z")

</div>

Thank you very much @ggross for your prompt response, I too am still learning about how the SSL/TLS mechanism works, will keep you posted on how things turn out

---

<div class="post-metadata">

**Author:** ![derrickdvdsn](https://avatars.discourse-cdn.com/v4/letter/d/3d9bf3/32.png) [@derrickdvdsn](https://forum.inductiveautomation.com/u/derrickdvdsn)\
**Post date:** [September 13, 2022, 2:40pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/7 "2022-09-13T14:40:13Z")

</div>

@ggross , I am able to successfully make the GAN connection automatically in the dev environment but how do I do this in the production environment? I already have an EAM gateway that is connected to about 100 other gateways. What effect will changing the keystore have on the other GAN connections? What’s the best way to go about it?

---

<div class="post-metadata">

**Author:** ![ggross](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ggross/32/12668_2.png) [@ggross](https://forum.inductiveautomation.com/u/ggross)\
**Post date:** [September 13, 2022, 4:00pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/8 "2022-09-13T16:00:09Z")

</div>

Fist thing you will need to do is make sure the public key of your signing certificate is trusted by both Gateways that are talking to each other. This is done by placing the key in the following directory (or mapping an external folder with the cert into the container location) for all Gateways that interact with each other using your self signed certificates.:

```auto
/data/gateway-network/client/security/pki/trusted/certs

```

While this will automatically trust the certs, even if the `Require Two Way Auth` option is set, it doesn’t take care of the `Connection Policy` option. You have the following options for this:

`Approved Only`: Default option and would require you to manually approve each Gateway, or you could create a resource via WebDev that would allow you to make an API call to approve untrusted Gateways.

`Unrestricted`: Still requires the certificate to be trusted to connect, but will let anything with a trusted cert connect.

`SpecifiedList`: You would need to provide a list of Gateway names that are allowed to connect.

You would need to figure out which scenario would be best for your setup but all options can automated should it be necessary.

I am attaching example WebDev resources for getting pending connections and approving them. There are called like the following and are set to use authentication by default:

- Get Connections (HTTP Get): http://\<Gateway URL\>/system/webdev/Test/getPendingConnections
- Approve Connection (HTTP Post): http://\<Gateway URL\>/system/webdev/Test/approveConnection
  - Payload Example (Both items provided by Get Connections): `{"incGwName": "gw2", "incGwUuid": "55c7edfe-98aa-41a6-88d3-5e18da1d3ed3"}`

[WebDev\_GANExamples.zip](https://forum.inductiveautomation.com/uploads/short-url/9MOiMdpFVayRC1nUiZy26Ggg3pU.zip) (6.9 KB)

Garth

---

<div class="post-metadata">

**Author:** ![derrickdvdsn](https://avatars.discourse-cdn.com/v4/letter/d/3d9bf3/32.png) [@derrickdvdsn](https://forum.inductiveautomation.com/u/derrickdvdsn)\
**Post date:** [September 13, 2022, 4:08pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/9 "2022-09-13T16:08:27Z")

</div>

@ggross what effect will changing the webserver/metro-keystore have on the existing GAN connections in the gateway?

---

<div class="post-metadata">

**Author:** ![ggross](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ggross/32/12668_2.png) [@ggross](https://forum.inductiveautomation.com/u/ggross)\
**Post date:** [September 13, 2022, 4:21pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/10 "2022-09-13T16:21:10Z")

</div>

Depends on where it is changed.

It will affect any Gateway that has a direct incoming/outgoing connection to the gateway with the changed certificate.

If you have a single Gateway that 100 other Gateways connect to and you change the cert on that 1 Gateway, then all 100 remote Gateways would need to trust the certificate prior to remote Gateway each Gateway being able to go back online.

If it is a single remote Gateway that you replace the certificate for, then you would just need to trust it on any of the Gateways it is making a connection to.

Not sure the best way to approach making the change over, but making sure that the public key of the signing cert is pushed to the `<Ignition Home>/data/gateway-network/client/security/pki/trusted/certs` directory on all Gateways would help make things go a lot smoother.

Garth

---

<div class="post-metadata">

**Author:** ![derrickdvdsn](https://avatars.discourse-cdn.com/v4/letter/d/3d9bf3/32.png) [@derrickdvdsn](https://forum.inductiveautomation.com/u/derrickdvdsn)\
**Post date:** [September 19, 2022, 1:25pm UTC](https://forum.inductiveautomation.com/t/gan-remote-certificates-auto-approval/63385/11 "2022-09-19T13:25:07Z")

</div>

@ggross and @jrosenkrans , I am finally able to implement this. All I had to do was add the metro-keystore only on the containerized instance of Ignition and create an Outgoing Connection to the EAM Gateway. And I had to approve the certificates only the 1st time of connection and all other subsequent connections from different container IDs were automatically approved.

Thank you so much.

Solution:

Create SelfSigned rootCA certificate:

1. First we would need a private key to generate the rootCA certificate:  
`openssl genrsa -out rootCAkey.pem 4096`
2. Next we will create one custom openssl configuration file required to generate the Certificate Signing request and add X.509 extensions to our RootCA certificate:  
`#cat openssl.cnf`  
`[req]  
distinguished\_name = req\_distinguished\_name  
policy = policy\_match  
x509\_extensions = v3\_ca

# For the CA policy

[policy\_match]  
countryName = optional  
stateOrProvinceName = optional  
organizationName = optional  
organizationalUnitName = optional  
commonName = supplied  
emailAddress = optional

[req\_distinguished\_name]  
countryName = Country Name (2 letter code)  
countryName\_default = US  
countryName\_min = 2  
countryName\_max = 2  
stateOrProvinceName = State or Province Name (full name) ## Print this message  
stateOrProvinceName\_default = California ## This is the default value  
localityName = Locality Name (eg, city) ## Print this message  
localityName\_default = Folsom ## This is the default value  
0.organizationName = Organization Name (eg, company) ## Print this message  
0.organizationName\_default = Inductive Automation ## This is the default value  
organizationalUnitName = Organizational Unit Name (eg, section) ## Print this message  
organizationalUnitName\_default = QA ## This is the default value  
commonName = Common Name (eg, your name or your server hostname) ## Print this message  
commonName\_max = 64

# v3\_ca

[v3\_ca]  
authorityKeyIdentifier = keyid, issuer  
basicConstraints = critical,CA:true  
extendedKeyUsage = serverAuth, clientAuth  
keyUsage = keyCertSign,cRLSign  
subjectAltName = @alt\_section  
subjectKeyIdentifier = hash

[alt\_section]  
email = your-email.com`

3.Let us go ahead and create our RootCA certificate

`openssl req -new -x509 -days 3650 -config openssl.cnf -key rootCAkey.pem -out rootCA.pem`

```python

1. Create a new keystore

   `keytool -genkey -alias metro-key -keyalg RSA -keysize 2048 -keystore metro-keystore`

2. Create a new Certificate Signing Request using the above keystore:
`keytool -certreq -alias metro-key -file metro-keystore.csr -keystore metro-keystore`

3. Sign the certificate:
`openssl x509 -req -in metro-keystore.csr -CA rootCA.pem -CAkey rootCAkey.pem -CAcreateserial -out WCNP.crt -days 500 -sha256 -extfile openssl.cnf`

   Note: This openssl.cnf file is different from the root certificate.This openssl.cnf file should have the following contents

   `keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = IP:127.0.0.1, DNS:ignition-wcnp-lab, URI:uri://*/metro
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer`

4. Import your root public key for your CA:
`keytool -import -trustcacerts -alias root -file rootCA.pem -keystore metro-keystore`

5. Import signed certificate:
`keytool -import -trustcacerts -alias metro-key -file WCNP.crt -keystore metro-keystore`

Inspect the newly created keystore using the Keystore Explorer tool to verify.

Since I am using a derived image, these were my configuration for the Dockerfile
`
COPY ./backup.gwbk /usr/local/bin/ignition/backup.gwbk
COPY ./register-module.sh /usr/local/bin/ignition/register-module.sh
COPY ./Walmart-SSO-signed.modl /usr/local/bin/ignition/user-lib/modules/Walmart-SSO-signed.modl
COPY ./Ignition-Kafka-signed.modl /usr/local/bin/ignition/user-lib/modules/Ignition-Kafka-signed.modl
# COPY ./ssl.pfx /usr/local/bin/ignition/data/local/ssl.pfx
COPY ./rootCA.pem /usr/local/bin/ignition/data/gateway-network/client/security/pki/trusted/certs/rootCA.pem
COPY ./metro-keystore /usr/local/bin/ignition/webserver/metro-keystore

RUN chmod +x register-module.sh && ./register-module.sh

ENV IGNITION_UID=999  
ENV IGNITION_GID=999

RUN chown -R ${IGNITION_UID}:${IGNITION_GID} ${IGNITION_INSTALL_LOCATION:?expected in environment}

USER 999

ENTRYPOINT ["docker-entrypoint.sh","-r","/usr/local/bin/ignition/backup.gwbk","-n","ignition-wcnp-lab", "-m","16384","--","-Dmetro.keystore.password=metroPassword","-Dmetro.keystore.alias=metro-key"]

`
Hope this helps. 

Thank you IA Team for all your support
```
