Loading credentials from Env variables

Good morning,

I’ve been developing a small server-side Swift project that requires the use of an API, and so access to an API Token on the server-side. I was wondering if there’s a way to retrieve this token as a string from a bash environmental variable, this would mean I can make the source code public and still save the credential in an env variable for CI or deployment.

I’m open to any alternatives. I basically just wanted a semi-automated way that would let me use an API token (String) in my code without having it hardcoded.

Thank you,
Tiago

import Foundation
let v = ProcessInfo.processInfo.environment["MYVAR"]
2 Likes

Take a look at https://github.com/IBM-Swift/Configuration. I use it in my server-side projects to load settings from various sources (incl. environment variables).

1 Like

I came across this on StackOverflow but it didn’t work. I believe this is for Xcode env variables? I’m trying to do this with a SwiftPM only project. No Xcode in Linux :)

Thanks I’ve been trying to use it with env variables, although I’m not sure I understand the syntax for env variables. What exactly do they mean by PATH__TO__CONFIGURATION=value? Say, how would I read an env variable called API_KEY?

Thanks a lot for your time.

No, ProcessInfo.processInfo.environment does return environment variables from the inherited shell.

$ export DEMO=-1
$ echo "import Foundation; print(ProcessInfo.processInfo.environment[\"DEMO\"])" > env.swift
$ swift env.swift 
Optional("-1")

Take in account that in the Swift REPL the environment variables will be clean.

1 Like

Oh interesting, I don’t know why but when I tried it it didn’t work. Thank you!

Configuration uses a double underscore to separate paths. This can be used to group settings in a hierarchy.

If your variable is called API_KEY, it doesn’t contain any path separators, so you should be able to read it with:

let settings = ConfigurationManager().load(.environmentVariables)
let apiKey = settings["API_KEY"] as? String

If your variable was named MYAPP__API_KEY, you would load it as:

let apiKey = settings["MYAPP:API_KEY"] as? String

I find hierarchies very useful as I load default settings (excluding secrets) from a JSON file and then overwrite (and add secrets) where needed via environment variables. For example:

Part of settings.json file:

{
  "DATABASE": {
    "URI": "something"
 }
}

I can then load this as follows:

let settings = ConfigurationManager()
        .load(file: "Configuration/settings.json", relativeFrom: .project)
        .load(.environmentVariables)
let uri = settings["DATABASE:URI"] as? String

And if needed, I can overwrite this by setting a DATABASE__URI environment variable.

I am using this technique in a project I hope to open source soon.

1 Like

Thanks a lot for everyone’s help.
I was able to get everything working with the Foundation ProcessInfo.
IBM’s Configuration seems amazing, especially for config files, but in my case, I just need to read this one env variable and as my code doesn’t run on REPL, Foundation suffices. I might use it on another bigger project though, have been looking for something like this for quite a while.

Thanks again,
Tiago

Any tricks for getting this to work? I have tried starting xcode from my shell, running my build from command line with xcodebuild, and nothing seems to pick up the environment variable.

Any tricks for getting this to work?

Are you building an app? Or a command-line tool?

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

Terms of Service

Privacy Policy

Cookie Policy