How to access files from /tmp folder in google cloud? - google-app-engine

I followed the guide here:
http://gunargessner.com/gcloud-env-vars/
After reading the comment http://gunargessner.com/gcloud-env-vars/#comment-4061927247, I also placed the .env file in /tmp.
I would like to know how to set the contents of file /tmp/.env to environment so that my app can access it from process.env.<varname>
const { Storage } = require('#google-cloud/storage')
const storage = new Storage()
const bucketName = 'env-var'
await storage
.bucket(bucketName)
.file('.env')
.download({ destination: '/tmp/.env' })
.then(() => {
console.log('env downloaded')
afterEnvProcess()
})
How do I now set the .env file to dotenv?

Well it depends on your app language but you can search for a dotenv lib on github.
For example:
https://github.com/motdotla/dotenv#readme (JS)
https://github.com/joho/godotenv (GO)
https://github.com/symfony/dotenv (PHP)
So when the app is started, you retrieve the .env file from the fileStorage service (i.e Google Cloud Storage) to /tmp (for AppEngine case). Then you can use the dotenv lib to parse the .env file en set the env vars.

Related

Deploying Environment Variables to Vercel with nextjs

I am new to next.js and experiencing issues while trying to deploy environment variables to Vercel.
We are trying to deploy Stripe Payment Gateway to Vercel
Downloaded the Stripe Payment Gateway Sample code from
https://github.com/tmarek-stripe/demo-react-stripe-js
This is a nextjs application with a .env file that has a public and secret key pair.
Everything works fine while running on localhost , also the projects work fine on Vercel when I include the .env file in the git repository
As soon as I include the .env file in gitignore and push the updates to the repository , the .env file would not be shown and I get 500 Server error while trying to make test payments
Error while making payments
Below is the code for payment intent.js
import Stripe from "stripe";
const stripe = new Stripe(process.env.SECRET_KEY);
export default async (req, res) => {
if (req.method === "POST") {
try {
const { amount } = req.body;
const paymentIntent = await stripe.paymentIntents.create({
amount,
currency: "usd"
});
res.status(200).send(paymentIntent.client_secret);
} catch (err) {
res.status(500).json({ statusCode: 500, message: err.message });
}
} else {
res.setHeader("Allow", "POST");
res.status(405).end("Method Not Allowed");
}
};
The .Env File looks like below
PUBLISHABLE_KEY=pk_test_key
SECRET_KEY=sk_test_Secret Key
Read all the available articles online with no luck.
No changes were made to the code apart from Public and Secret Key in .env file
Please let me know how to hide the Environment Variables(as it contains the secret key) and at the same time use it in the production environment
Any help would be appreciated
Thanks in Advance
You can go to vercel.com, log-in to your account, open the project, go to settings, and then environment variables. There you can set variables for production, preview, and development.
According to their documentation that's the only way to achieve different Environment Variables based on the Environment (Development, Preview, or Production).
https://vercel.com/docs/build-step#environment-variables
Someone came up with a bash script to upload an .env file
while IFS== read -r name value
do
echo "$value" | vercel env add "$name" "$2"
done < "$1"
command:
<script name> <file> <production | preview | development>
and I also think it'd be better to have something like vercel env push [environment] [file]
SOURCE

what is the proper way to do config lookups in react?

My React app currently uses my local API when making an axios.get() call with the following url:
http://localhost:3000/users
Instead of hard-coding the url, I need my component to do a lookup against the config file that is currently configured for the current environment. For example, when my API is running on Azure the axios get call should use the following url:
https://my-api.azurewebsites.net/users
What is the proper way to lookup this config value in a React app? For example, should I create some type of config.js file? What is the proper import/code for my component to hook into the config file for lookup?
Don't use dotenv, because this package was designed for server-side app - it injects config variables in the process.env dictionary, but the process global variable only exists in Node apps and is not available in the browser.
There are many other ways to do what you want, perhaps the simplest I can think of is to have a config file that exports values, and the values it exports depends on the environment the scripts runs in:
// config.js
const isProd = location.host === 'my-app.azurewebsites.net'; // or any other check
const devConfig = {
axiosBaseUrl = 'http://localhost:3000'
}
const prodConfig = {
axiosBaseUrl = 'https://my-app.azurewebsites.net'
}
export default isProd ? prodConfig : devConfig
// upon starting your app, before making any axios call
import config from './config';
const http = axios.create({
baseUrl: config.axiosBaseUrl
});
// use as such
http.get('/hello-world');
// locally: makes a call to http://localhost:3000/hello-world
// in production: makes a call to https://my-app.azurewebsites.net/hello-world
You can also have a config file which contents depends on the build environment, but that would be more complex to setup and is highly dependent on your build pipeline and there's no details about it in your question.
You can create a config file or can use environment variables.
For environment variables:
Create .env file in the root directory of your project.
Save your URL as REACT_APP_BASE_URL=http://localhost:3000/
Now you can access your base URL when you are making axios requests like this:
process.env.REACT_APP_BASE_URL

How to inject API server URL when deploying react frontend?

Disclaimer: I am a React noob so perhaps what I am trying to do is not the React Way
I am writing a React front-end that will be deployed to be served statically by some cloud provider, e.g. S3 or Google Storage or whatever. This front-end interacts with several API servers that live somewhere in the cloud, maybe in the same provider, maybe not. Furthermore, while developing the UI or part of it, those servers' addresses might be local or testing instances.
How do I inject the API server(s) URLs into my react application in a flexible so that I can deploy in dev, staging or prod using different addresses?
SOLUTION: I finally ended up using a combination of solutions proposed:
use .env.production and .env.development files (exact names) to store the variable REACT_APP_API_URI = 'host'
this is automatically picked-up by create-react-app's build scaffolding and available in UI code as process.env.REACT_APP_API_URI
Note this somewhat goes against principles from 12 Factor Apps, e.g. storing env variables in files in version control but it does the job ATM.
You can try this:
// http.js
const getBaseUrl = () => {
let url;
switch(process.env.NODE_ENV) {
case 'production':
url = 'https://stackoverflow.com';
break;
case 'development':
default:
url = 'https://google.com';
}
return url;
}
export default axios.create({
baseURL: getBaseUrl(),
});
Using this package https://github.com/toddbluhm/env-cmd you could create an env file for your environment
for example create .env.staging and .env file with this code
// .env.staging file
API_URL=https://staging.url.com/api/
// .env file
API_URL=https://url.com/api/
How to fetch with API_URL from env variable:
fetch(process.env.API_URL)
Then you can just add some extra scripts in your package.json:
{
"scripts": {
"build:staging": "env-cmd .env.staging yarn build",
"build:prod": "env-cmd .env yarn build"
}
}
You can use .env file if the API's are constant for development or production environment. after build you can't change these parameters.
If you want to change the URL after build, add a js file lets say config.js
Include the conf.js in index.html
Add URL in conf.js like
var URL1 = 'https://www.google.com'
You can access the parameter like :
export const {URL1} = window;
You can do that making use of environment variables on the build step for example.
You can use something like .env that allows you to define environment variables and load them on your webpack file for example (assuming you use webpack). But you can really use it with any bundler.
.env file:
API=http://localhost:3000
On your webpack you could make use of the DefinePlugin
example taken from docs: add your API env
...
require('dotenv').config()
...
new webpack.DefinePlugin({
API_ENDPOINT: process.env.API,
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1',
'typeof window': JSON.stringify('object')
});
Anyway, this is just one way. I like this way because it makes my project ready for defining API keys and other useful stuff for different environments.
NOTE: You can even define different .env files for local, staging and production and load the respective one in the webpack depending on the build type.

Does google app engine support environment variables?

I've noticed that the developer console doesn't seem to expose anywhere where I can configure static environment variables.
Is the expectation on GAE that I will bundle those variables as part of the deployment from my build server? If so, is there any documentation on GAE/Google Cloud that covers why or details the philosophy?
Years have passed, and still it doesn't.
My workaround is to compile app.yaml during deployment process (locally or with CI).
For example, I have a template file app.tml.yaml file
runtime: python37
handlers:
- url: /static
static_dir: app/static/
- url: /.*
script: auto
env_variables:
DJANGO_GC_DATABASE_PASSWORD: ${DJANGO_GC_DATABASE_PASSWORD}
Then I call envsubst right before deployment
envsubst < ./app.tml.yaml > app.yaml and after that gcloud app deploy as usual. After the deployment is done app.yaml with sensitive data is deleted. Variables are read from local .env file or are set in CI system.
There also other approaches I found listed in this post: https://dev.to/mungell/google-cloud-app-engine-environment-variables-5990 but for me they are not convienient or generic enough.
Environment variables can be defined in your application's app.yaml
An example for a python/php/(maybe go?) app. Java uses a different format.
env_variables:
MY_ENV_VAR: 'some value here'
https://cloud.google.com/appengine/docs/python/config/appconfig#Python_app_yaml_Defining_environment_variables
You can set these values during your CI process as well if you need to by programmatically appending them to your app.yaml before deploying.
One solution is apparently https://cloud.google.com/secret-manager/docs, but I opted for the solution offered here:
Securely storing environment variables in GAE with app.yaml
First, put the environment variables in an env_variables.yaml, e.g.,
env_variables:
SECRET: 'my_secret'
Then, include this env_variables.yaml in the app.yaml
includes:
- env_variables.yaml
Finally, add the env_variables.yaml to .gitignore, so that the secret variables won't exist in the repository.
Further,
I commit env_variables.sample.yaml, with instructions and placeholder values which the next dev can fill in
in dev, I parse env_variables.yaml and add the vars to process.env so I have a single source of truth for those vars…
if (process.env.NODE_ENV === "development") {
try {
const fs = require("fs");
const yaml = require("js-yaml");
let fileContents = fs.readFileSync("./env_variables.yaml", "utf8");
let {env_variables} = yaml.load(fileContents);
console.log({ env_variables });
Object.keys(env_variables).forEach((v) => {
process.env[v] = env_variables[v];
});
} catch (error) {
res.status(500).end("500: Problem getting env vars");
return;
}
}
I'm adding my solution here as the quoted question specifies python, and this question is generic.
As with other PAAS solutions (eg Heroku, Netlify), if a user has access to the App Engine console, they can see the secrets (in this case by browsing the source files in the console).

How do I authenticate access to assets folder in sails.js

I am already using passport to authenticate users. I added kibana 3 to the assets folder and want users to access it only if they are authenticated. how do i do this ?
The assets folder is intended for publicly-available files, like your images and Javascripts. If you want to protect those files, you can either override the default www middleware in Sails, which activates the Express static handler to servet those files (see details on overriding default middleware in this answer), or save the files you want to protect in a different location and use a controller action to serve them (probably the more reasonable option).
So, you could save the files in protected_files, and add a route like this to config/routes.js:
'/protected/:file': 'ProtectedFileController.download'
then in controllers/ProtectedFileController:
var fs = require('fs');
var path = require('path');
module.exports = {
download: function(req, res) {
// Get the URL of the file to download
var file = req.param('file');
// Get the file path of the file on disk
var filePath = path.resolve(sails.config.appPath, "protected_files", file);
// Should check that it exists here, but for demo purposes, assume it does
// and just pipe a read stream to the response.
fs.createReadStream(filePath).pipe(res);
}
};
Then protect that controller / action using a policy like you would with any other area that needs authentication.

Resources