This is Cloak Swift - a tool and Tuist plugin to encrypt secrets and then pass them in an obfuscated form into applications.
Features • Install • Usage • Contributing
Features
☑️
Keep your secrets out of Git
Set up secrets locally outside of the Git repository to avoid them being embedded into the code.
☑️
Encrypt secrets
Create encryption key and encrypt secrets ready for use.
☑️
Access secrets from your app
Generate a Swift file to access the secrets from your app's code.
☑️
Obfuscation
The generated Swift uses obfuscation of the values rather than as raw strings.
Install
The primary intention was to use Cloak Swift as a Tuist plugin, however, it can also be used as a standard CLI tool as well.
🖥
As a Tuist Plugin
▶︎ To set up as a Tuist plugin in your project simply follow the Tuist plugin install instructions using the latest version.
Add the plugin to Config.swift
.
import ProjectDescription
let config = Config(
plugins: [
.git(url: "https://github.com/lordcodes/cloak-swift.git", tag: "v0.1.0")
]
)
🖥
Standalone via Swift Package Manager
▶︎ Cloak Swift can be easily installed globally using Swift Package Manager.
git clone https://github.com/lordcodes/cloak-swift
cd cloak-swift
make install
This will install cloakswift into /usr/local/bin
. If you get a permission error it may be that you don't have permission to write there in which case you just need to adjust permissions using sudo chown -R $(whoami) /usr/local/bin
.
You can uninstall it again using make uninstall
which simply deletes it from /usr/local/bin
.
🍺
Homebrew
▶︎ Support for Homebrew may be planned in the future.
📦
As a Swift package
▶︎ To install Cloak Swift for use in your own Swift code, add it is a Swift Package Manager dependency within your Package.swift
file. For help in doing this, please check out the Swift Package Manager documentation.
.package(url: "https://github.com/lordcodes/cloak-swift", exact: "0.1.0")
Usage
Set up configuration
Create a configuration file within your project: .cloak/config
, this file should be kept in Git and shared between contributors. Enter key-value pairs into the file EnvironmentKey.
- CLOAK_SECRETS_CLASS_NAME -> Name to give the generated Swift enum that contains the secrets in-app.
- CLOAK_SECRETS_OUTPUT_FILEPATH -> File path to put the generated Swift file.
- CLOAK_SECRETS_ACCESS_LEVEL -> Swift access level to give to the enum and each secret static property. E.g. public.
Each of these settings can be provided as an environment variable instead of listed in the configuration file. The config file will take precedance.
For example:
CLOAK_SECRETS_CLASS_NAME=AppSecrets
CLOAK_SECRETS_OUTPUT_FILEPATH=Sources/Generated/AppSecrets.swift
CLOAK_SECRETS_ACCESS_LEVEL=public
Configure required secret keys
You can list the required secret keys for your project in a .cloak/secret-keys
file, which can be kept in Git. This ensures each contributor has provided all required secrets locally. Secret keys should be listed one on each line.
For example:
ANALYTICS_WRITE_KEY
API_CLIENT_ID
API_CLIENT_SECRET
Configure secrets
Each contributor on a project will need to create a file at .cloak/secrets
that uses the same format as the config
file but that lists secret key names and values. This file should be added to your project's .gitignore
to keep them out of Git.
You should also add your encryption key to this file using the key name CLOAK_ENCRYPTION_KEY
. This will allow the encrypt/decrypt commands to function and will also allow it to be included into the generated Swift file so that your app can decrypt the secrets at runtime in order to use them.
If the secret keys are specified in the required keys file secret-keys
, then they will be read as environment variables as well, where the environment variables take precendence. This is useful in a CI environment where you can specify them as environment variables and avoid having to write them to a file as you would locally.
IMPORTANT NOTE: The secrets aren't read as environment variables correctly when using Cloak as a Tuist plugin, due to the environment Tuist plugins are executed in. Therefore, it is best to write the secrets to a file in a setup step of your CI workflow.
The best practice is that the values should be encrypted first.
🖥
Via the Tuist Plugin
Run Cloak's tasks via Tuist. The tool will check paths relative to the working directory for the .cloak
directory configured above.
USAGE: tuist cloak [-q|--quiet]
SUBCOMMANDS:
createkey Create encryption key.
decrypt Decrypt a value encrypted using cloak.
encrypt Encrypt a value.
generate Read in secrets, obfuscate them and then generate a Swift file to access them within an app.
version Print version.
OPTIONS:
-q, --quiet Silence any output except errors
You can obtain help using tuist cloak --help
and also obtain help for each subcommand using tuist cloak
.
Create encryption key
Generates an encryption key, that can then be used within your project to encrypt secrets. This key is then passed into your app so that you can decrypt them at runtime.
tuist cloak createkey
Encrypt a value
Provide a value and the encrypted version will be returned. Your encryption key should be provided as described above.
tuist cloak encrypt
Decrypt an encrypted value
Provide an encrypted value and the decrypted version will be returned. Your encryption key should be provided as described above.
tuist cloak decrypt
Generate a secrets file in-app
Generate a Swift file that can be used to access your secrets within your app at runtime. Certain aspects of the generated file can be customised using the config
file as described above. The secrets will be obfuscated and included as [UInt8]
, but with Swift properties to return them as String
in their usable form.
tuist cloak generate
🖥
Via the Standalone CLI
Run Cloak's tasks via a standalone executable. The tool will check paths relative to the working directory for the .cloak
directory configured above.
USAGE: cloakswift [-q|--quiet]
Same usage as the Tuist plugin, except tuist cloak
is replaced with cloakswift
.
📦
As a Swift Package
To use Cloak Swift within your own Swift code, import and use the public API of CloakKit
.
import CloakKit
// Configure printing
Cloak.shared.printer = ConsolePrinter(quiet: false)
EncryptionService().createKey()
Contributing or Help
If you notice any bugs or have a new feature to suggest, please check out the contributing guide. If you want to make changes, please make sure to discuss anything big before putting in the effort of creating the PR.
To reach out, please contact @lordcodes on Twitter.