# How are you hiding your API keys?

**URL:** <https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689>\
**Category:** Ignition\
**Created:** [October 2, 2024, 1:50am UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689 "2024-10-02T01:50:50Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![drewdin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/drewdin/32/3363_2.png) [@drewdin](https://forum.inductiveautomation.com/u/drewdin)\
**Post date:** [October 2, 2024, 1:50am UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/1 "2024-10-02T01:50:50Z")

</div>

I'm just curios how you guys are hiding you api key in the scripting module, are you hashing it in a database or something similar? Just looking for suggestions.

Thanks!

---

<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:** [October 2, 2024, 11:50am UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/2 "2024-10-02T11:50:55Z")

</div>

I recommend placing secrets in a json file outside the Ignition install folder (so it won't be caught in backups or GIT) and loading the whole file into a script module top level variable (outside any function, so it caches). This conveniently also makes it easy to have testing secrets in DEV.

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [October 2, 2024, 2:59pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/3 "2024-10-02T14:59:46Z")

</div>

We use OS environment variables, but how you set them is OS dependent.

On Ubuntu, we tweaked the Ignition-Gateway systemd service to load extra variables from a file that we keep outside of the Ignition folder (like pturmel suggested).

---

<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:** [October 2, 2024, 3:20pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/4 "2024-10-02T15:20:25Z")

</div>

> [@justin.brzozoski](#):
>
> We use OS environment variables

I know this is popular in the devops world, but prevents hiding secrets from privilege escalation attacks. Linux's SELinux framework (and others) can prevent access to file-based secrets and regular process memory even by the `root` user, but cannot prevent access to a process' environment exposed in `/proc/`.

I strongly recommend using file-based secrets storage even if you aren't yet using SELinux, so you **can** migrate to that level of security when you need to. This is particularly important when delegating secrets storage to a external vault, as you must somehow secure the local credentials you use to _authenticate to the vault itself_.

It's one of the things that makes me unhappy with common practices in Docker. ☹

Some background:

> <https://security.stackexchange.com/questions/7801/keeping-secrets-from-root-on-linux>

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [October 2, 2024, 3:47pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/5 "2024-10-02T15:47:10Z")

</div>

I'm so used to the idea that "if they have root they have everything" that the concept of "hardening against a compromised root" felt _alien_ at first. But I see your point.

In our case we're halfway there since the secret variables all in a `.env` file that systemd imports to the environment. We could just turn off the systemd import and make it a scripted import of the same file inside Ignition.

---

<div class="post-metadata">

**Author:** ![drewdin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/drewdin/32/3363_2.png) [@drewdin](https://forum.inductiveautomation.com/u/drewdin)\
**Post date:** [October 6, 2024, 2:50am UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/6 "2024-10-06T02:50:05Z")

</div>

Any suggestions on how to hide a file in a docker container? would hashing it in a database be a bad idea?

---

<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:** [October 6, 2024, 12:27pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/7 "2024-10-06T12:27:07Z")

</div>

> [@drewdin](#):
>
> hide a file in a docker container?

Use docker's standard secrets management, which places the secrets file in the container's `/run/` memdisk hierarchy. Which is naturally outside Ignition's folders.

---

<div class="post-metadata">

**Author:** ![drewdin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/drewdin/32/3363_2.png) [@drewdin](https://forum.inductiveautomation.com/u/drewdin)\
**Post date:** [October 7, 2024, 2:50am UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/8 "2024-10-07T02:50:13Z")

</div>

Thanks, I'll check it out. I have a question about importing the file too. If you are in the gateway, what is to prevent you from printing out the variable to get the apikey, is it worth the effort to keep it in an external file to import? Thanks again!

---

<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:** [October 7, 2024, 11:28am UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/9 "2024-10-07T11:28:07Z")

</div>

> [@drewdin](#):
>
> prevent you from printing out the variable to get the apikey

Nothing. There is no way to stop that. It's one of the reasons designer access is effectively full access to a gateway.

> [@drewdin](#):
>
> is it worth the effort to keep it in an external file to import?

Yes, as it protects against hacks that gain access to the OS, but not from within Ignition.

---

<div class="post-metadata">

**Author:** ![drewdin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/drewdin/32/3363_2.png) [@drewdin](https://forum.inductiveautomation.com/u/drewdin)\
**Post date:** [October 7, 2024, 4:12pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/10 "2024-10-07T16:12:57Z")

</div>

Thanks for the clarification!

---

<div class="post-metadata">

**Author:** ![justin.brzozoski](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justin.brzozoski/32/13452_2.png) [@justin.brzozoski](https://forum.inductiveautomation.com/u/justin.brzozoski)\
**Post date:** [October 8, 2024, 9:04pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/11 "2024-10-08T21:04:30Z")

</div>

Somewhat related question, once i have a config setting or token or whatever that I've pulled into Ignition this way in a script, is there any way to get at it using a simple expression if I haven't pushed it into a tag?

Like if I've saved it into a dictionary in a script library named `shared.config` then I can obviously get to it as `shared.config.whatever` from another script. Or I stored it in the globals area I could use `system.util.getGlobals()`. But neither of those are reachable via expressions, right?

---

<div class="post-metadata">

**Author:** ![ryan.white](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan.white/32/73193_2.png) [@ryan.white](https://forum.inductiveautomation.com/u/ryan.white)\
**Post date:** [October 8, 2024, 9:09pm UTC](https://forum.inductiveautomation.com/t/how-are-you-hiding-your-api-keys/96689/12 "2024-10-08T21:09:03Z")

</div>

> [@justin.brzozoski](#):
>
> But neither of those are reachable via expressions, right?

Correct.

> [@justin.brzozoski](#):
>
> Or I stored it in the globals area I could use `system.util.getGlobals()`

You would probably have to use pturmel's Integration Toolkit's `globalVarMap` method to retrieve it via an expression, and you would also need to use the associated `system.util.globalVarMap()` method instead of `system.util.getGlobals()`

[https://www.automation-pros.com/toolkit/doc/scripting.html#globalvarmap](https://www.automation-pros.com/toolkit/doc/scripting.html#globalvarmap)
