Is there a way to dynamically inject sensitive environment variables into a serverless React frontend application using Azure/Github Actions? - reactjs

I'm sort of restricted to Azure since that is what the client is already using.
But basically, we have this React website which is your typical react-scripts no server website, which means that there's nowhere in Azure Static Webapps to set environment variables for a frontend application.
I saw this on Azure Static Webapps Configuration, but subject to the following restrictions, won't work for my use case because there is no backend API for my frontend application - the backend associated with the frontend is published separately to Azure App services. And I need the secrets on the frontend to use some npm packages that require them, which I would prefer to do on frontend instead of backend.
Are available as environment variables to the backend API of a static web app
Can be used to store secrets used in authentication configuration
Are encrypted at rest
Are copied to staging and production environments
May only be alphanumeric characters, ., and _
I was doing some more research, and this seems to sort of be up the alley of what I'm looking for:
https://learn.microsoft.com/en-us/answers/questions/249842/inject-environment-variables-from-pipeline-to-azur.html
Essentially, I really want to avoid hardcoding secrets into the React code because that's bad practice.
I personally see a few different (potential) options:
Create an endpoint on the backend Spring Boot api that simply serves all environment variables
This is the most trivial to implement but I have concerns about security with this approach. As my frontend has no access to any kind of secrets, there's no way for it to pass a secure token to the backend or anything to authenticate the request, so someone could conceivably have chrome network inspect element tab open, see that I'm making a request to /getEnvironmentVariables, and recreate the request. The only way I can see to prevent this is to have IP restrictions enacted on the backend API, so it only accepts incoming requests from the IP address of my frontend website, but honestly that just sounds like so much overhead to worry about. Especially because we're building the product as more of a POC, so we don't have access to their production environments and can't just test it like that.
Have the Azure Static Webapps Github Actions workflow somehow inject environment variables
So I've actually done something similar with GCP before. In order to login to a GCP service account to deploy the app during continuous build, the workaround was to encode a publicly viewable file that could be freely uploaded to whatever public repo, which could only (realistically) be decrypted using secrets set on the CI/CD pipeline, which would be travis-ci, or in my case, Github Actions. And I know how to set secrets on Github Actions but I'm not sure how realistic a solution like that would be for my use case because decrypting a file is not enough, it has to be formatted or rewritten in such a way that React is able to read it, and I know React is a nightmare working with fs and whatnot, so I'm really worried about the viability of going down a path like that. Maybe a more rudimentary approach might be writing some kind of bash script that could run in the github actions, and using the github actions secrets to store the environment variables I want to inject, run a rudimentary file edit on a small React file that is responsible for just disbursing environment variabless, before packaging with npm and deploying to Azure?
TLDR: I have a window in github actions when I have access to a linux environment and any environment variables I want, in which I want to somehow inject into React during ci/cd before deployment.

Related

Adding Environment Variables to Azure Static Web App Release Task

My react frontend SPA has some environment variables I would like to pass at deploy time using the Static Web App Deploy task in Azure ADO.
If I'm doing this in a pipeline, it's simple to add directly to the YAML https://learn.microsoft.com/en-us/azure/developer/javascript/how-to/with-authentication/static-web-app-with-api/deploy-static-web-app-to-azure#add-react-client-environment-variables-to-workflow-configuration-file
However, within the "Releases", I don't see where I can add these env variables since I can't directly edit the YAML file.
My questions are:
Is this not possible? Is this limitation due to the fact the Deploy Static Web App is technically still in "Preview"?
Is it possible to write a custom Task/YAML code to run during the release? I would prefer to keep the CD in the Releases section so I can keep approvals/rollback functionality, rather than just make a multi-stage pipeline
Is there a better or more correct way to pass these environment variables? They are not secrets, just for example the API URL. Passing as env variables would allow me to break up deployment into dev/prod and pass different values for each environment.
Thank you!

Next.js monorepo: multiple apps on subdomains vs. one app?

I just started using nx.dev to migrate from a single app repo to a monorepo as I have added a very basic static documentation app to the mix which is deployed to a subdomain docs.company.com.
My main application is currently deployed to main route company.com. However, one could think of it as different apps as well where there is app1, app2 and admin for example. I do like the idea of having everything as a single application as it can be easily deployed with nx and Vercels monorepo support.
I am just not sure what the go to approach is here. Of course, I could split up the main app into multiple apps and deploy them independently to subdomains such as:
admin.company.com
app1.company.com
app2.company.com
If understood correctly, I could also use multi zones support if I do not like subdomains and use one domain instead.
This main app, that could logically be split up in multiple apps is non public and authentication is required. It is completely client side rendered while apollo client is used to interatct with the GraphQL API. This API server also sets an http-only JWT cookie for authentication. I am quite sure I could mitigate the issue with subdomains in this regard by setting the domain cookie setting, such that the cookie is also valid for subdomains.
However, as the cookie is http-only I cannot access it from the client and need to keep track of the logged in status in my global state mangement (which is overmind.js). Splitting up the app would add some extra complexity to persist global state between subdomain apps.
I am not sure whether this is worth it or if it is better sticking to the one app approach. I would love to hear your opinion and maybe I have forgotten some major issues. Some questions that come to my mind:
What are the advantages and disadvantages of using subdomains?
Is it more preferable to use multi zones and only one app?
How could the auth/global state issues be solved if switching to multiple apps?
What are your thoughts?

Is it possible to configure React application to use container's environment variables in Kubernetes?

To begin with - let us suppose we have a React application. We want to build it and deploy to 3 environments - dev, test and production. As every front-end app it needs to call some APIs. API addresses will vary between the environments. So they should be stored as environment variables.
As every modern, progressive developer we want to use containers. In particular Kubernetes.
We want to build our web application and deploy it on K8S cluster. The container image should be built and kind of sealed for changes, then before deployment to each particular environment the variables should be injected.
But it seems there's one great impossibility here. When it comes to .NET apps for example, when we have .dll compiled, it reads a config file in the runtime. It's not a case with React. After we generate build we have just static files. The variables are changed to static values in the process of building React app. It seems there's no way to update it after that point - or is it?
The way you are trying to solve your problem is not correct.
You don't need to know anything about the addresses of the backend services in your react app. Only the frontend server/gateway that is serving your react app needs to know about the backend services. Any request from the react app should be proxied via the gateway.
See API gateway pattern - https://microservices.io/patterns/apigateway.html
You can use config map to store the API endpoint address and refer it as environment variable in the pod.
If you want to change some values while the pod is running you can mount the config map and any change to it will be synced in the pod

Injecting secrets from CI with GCP AppEngine's app.yml

Thanks for your help in advance!
I'm trying to create a simple but secure way to inject secrets from a commandline call to gcloud app deploy app.yml.
I'm relying on secret information stored in environment variables in my app's runtime, which I can set using the following app.yml:
runtime: nodejs
env: flex
env_variables:
SECRET_KEY: "passed-in-value"
For example, I'd like to be able to do something like
SECRETKEY=${LOCAL_SECRET_VALUE} gcloud app deploy app.yml
or use a cli argument if there is one, but I don't see any here.
At the end of the day, I just need a simple way to inject secrets so I can deploy to my testing environment from my local machine, or to production from a github action. I could just write the app.yml dynamically from my ci script and inject local environment variables, but it seems like there must be a more canonical way.
I can set environment variables with app.yml using the following syntax.
I would like a solution which works with both standard and flex app engine if possible.
Google Cloud has silently released in Beta Secret Manager. The APIs are available but the client libraries aren't yet. The service will be announced soon and will help you to manage your secrets.
The principle is simple: In your yaml files and in your GIT, you simply save a reference to the secret, for example mySecret#2 where 2 is the version number, and mySecret the name of your secret.
Then, perform a simple call to the API to get access to the secret
https://secretmanager.googleapis.com/v1beta1/projects/<myProject>/secrets/<MySecret>/versions/<Version>:access
The call must be secured with a Bearer access token in the header. Be sure that the App Engine service account has the required roles (default service account: YOUR_PROJECT_ID#appspot.gserviceaccount.com), at least roles/
secretmanager.secretAccessor
Note: I don't know how the library will be implemented if you request the secret without giving an explicit version. Is the 1st version which will be taken? the lastest?
For now, there is a lot of manual overhead (get the token, build the URL, manage errors,...). If you can wait a couple of weeks, the life will be easier with client libraries!

React clarifications

I am trying to understand React to possibly create an app for Production purposes.
I am used to creating an Node Express app, and with Express if we want https we require https and in the https.createserver() we provide a path to our pem file from our CA and our passphrase to access it.
Do we not have this option to use a CA Certificate file for React? Or since it is just a UI does it not need it?
Say I have an Express API, I created using https that I can get information from using postman with no problems, and I want my React App to access my API. Is the only thing I will need to get info from my api the proxy line in my react package.json file pointing to https://api.to.call.com? I thought it was bad practiced to post or get to https server from http.
Plus I just read that Create-React-App should not be used for production. Then what am I supposed to use for production? Is there a Create-React-Production-App? Or is this something else I need to add to my express server? I am very confused about the entire setup.
React is a front-end library. As such, it has nothing to do with SSL certificates, since in the end it's just javascript code that runs inside the client interface (i.e. a browser).
React is also agnostic when it comes to your back-end. It can be Node/Express, Rails, Python, PHP, your front-end really doesn't care, all it will see is an API that provides data (usually in the JSON form) upon request.
You do not have to serve your API and your front-end files from the same server - you can, but it's a matter of preference. And to access your API from your front-end, you can use one of several npm packages, Axios is a great one, there are others (Fetch, ...) ; all you have to do is hookup your API calls using the same URLs you used in Postman in the components that require them.
As for Create-React-App, it's a nice helper tool, but I would recommend learning a bit about the React ecosystem rather than rely blindly on it. The trickiest part is probably the Webpack configuration, but once you get the hang of it, everything becomes a lot easier. There are also newer tools like poi that can do a lot of the grunt work for you. With Webpack, you can have a dev configuration (hot reloading dev server, etc.) and a production configuration (that will output your production build JS, HTML, CSS, can optimize with chunking, etc.).
I'm not very familiar with Create-React-App (I prefer to use my own boilerplate projects), but if I'm not mistaken, there is a possibility for you to access full customization of your project, see here. Be warned however, it's a one-way operation.

Resources