Working with Kentico Kontent and Gatsby has been a nice learning curve for me, as I pick up and build upon my front-end developer skillset. You can end up taking quite a lot for granted when you're working with .NET. Securing your calls to an API can be one of these things, as you add things like API keys to your .config
files and make sure that you don't push those files into your git repo.
When I started on my journey with Gatsbyjs and Kentico Kontent, I wasn't clear on a method that I could use to hide my API keys. 😕 As with most things though, a little digging on Google goes a long way and I managed to find two solutions:
- Using environment variables
- Create a settings object
Let's look at these in a little more detail.
Environment Variables
Creating and using environment variables
Environment variables are settings that are usually stored as key-value pairs that you can use in your application. To store your application settings in environment variables, you can create a .env
file in your project folder.
The .env
file format is just a simple flat file, no hierarchy. As an example, my .env
file looks as follows (obviously the values in brackets are replaced):
KONTENT_PROJECT_ID=<Kontent Project ID>
KONTENT_PREVIEW_KEY=<Kontent API Key>
KONTENT_PREVIEW_ENABLED=<true of false>
Reading that file requires you to have the dotenv
module in your project. You can install this using the following:
npm install dotenv
The using it is as simple as setting it up (in my case at the top of my gatsby.config
file):
require('dotenv').config();
As it happens, in my Gatsby project, I have two .env
files, one for running gatsby develop
and one for gatsby build
(one uses the preview mode of Kentico Kontent while the other does not). In order to do this, I pass a little more info to dotnet to tell the configuration which file to look for, bypassing in the node environment:
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
This means that when I look at my gatsby.config
file, I have a much cleaner file that I can commit to my repo that does not contain my various keys as follows:
{
resolve: `@kentico/gatsby-source-kontent`,
options: {
deliveryClientConfig: {
projectId: process.env.KONTENT_PROJECT_ID,
previewApiKey: process.env.KONTENT_PREVIEW_KEY,
globalQueryConfig: {
usePreviewMode: (process.env.KONTENT_PREVIEW_ENABLED == 'true'),
},
},
languageCodenames: [
`default`
]
}
}
What you may notice is that I'm not simply using the value from the .env
file for the value of usePreviewMode
. There is a good reason for this and very simple reason for this and that is that dotenv
does not support boolean values. If you want to debug out your environment variables you can use the following:
console.log(process.env);
which means you'll see something like this:
{
KONTENT_PREVIEW_ENABLED: 'true',
KONTENT_PREVIEW_KEY: 'Swiper, no swiping!',
KONTENT_PROJECT_ID: 'Swiper, no swiping!',
NODE_ENV: 'development',
}
(I actually have a load more in there from my Windows environment variables like PATH
, but we don't need to worry about those here)
That's it. When you run npm run build
or npm run develop
everything should now be picking up your new settings!
Ignore the .env
file!
A key point here is, add your .env
files to the .gitignore
file. The whole point here for me is to not commit your keys and other sensitive data to the git repository.
To achieve this, just add the following to your .gitignore
file:
# dotenv environment variable files
.env*
Using environment variables with Netlify
I'm my scenario, I'm using Netlify to build and host my solution. If you are too, then you may have already come across the environment variables in your projects build & deploy settings:
Netlify has no concept of build or develop environment variables in my setup (hot I think it can support them), so when we run npm run build
, it simply picks up the available variables and gets on with business.
Using environment variables with Azure DevOps
At Ridgeway, we use Azure DevOps for our build pipelines. Typically, we set up the pipelines using yaml
files, but the screenshot here uses the classic designer (it's quite an old one):
If you're editing a yaml
pipeline, then the option is still there if you click Variables in the top right while editing the pipeline.
Then you can just set the values you want. The options here to make things secret are quite a nice touch, as are the tips on how to use them.
Settings object
Creating and using a settings object
Another option I've seen in use is the creation of a settings object in a separate file. So for example, on one project we have a file called gatsby.keys
as follows:
module.exports = {
enablePreviewMode: false,
enableSecuredMode: true,
securedApiKey: 'Swiper, no swiping!',
previewApiKey: 'Swiper, no swiping!'
};
This is then used in the gatsby.config
file as follows:
const keys = require('./gatsby-keys');
The variables are then used to set up the plugins as before.
This method supports boolean values, so we don't need to do any additional work with those. Again, this file needs to be excluded from the repository using the .gitignore
file to make sure that we don't push the keys into the wrong place.
Settings objects in build pipelines
I've only tried this with Azure DevOps, and it required me to add a custom pipeline component to create the key's file. So I have a step in my yaml
that looks like this:
- task: eliostruyf.build-task.custom-build-task.file-creator@5
displayName: 'Create settings keys'
inputs:
fileoverwrite: true
filepath: 'gatsby-keys.js'
filecontent: |
module.exports = {
enablePreviewMode: true,
enableSecuredMode: false,
securedApiKey: 'Swiper, no swiping!',
previewApiKey: 'Swiper, no swiping!'
};
You can probably spot the flaw in this implementation, right? I'm not using variables so actually, this is a massive fail as those keys are directly in my yaml
file and so also in source control.
(on the upside, it's a private repo)
Summary
These are to the two methods that I came across while working on both work and personal projects. The first exposure I had was the settings object. While it solves the issue of booleans, it's note really my favourite. The environment variables appears to be a much more robust approach to things and it's the one I'm going to be using (and asking my team to use) going forward.
If you can find the time, I recommend testing both out and seeing which works best in your case.
Cover photo by Chunlea Ju on Unsplash
Top comments (0)