Zendro-dev / graphql-server

Skeleton NodeJS project for a graphQL server.
GNU General Public License v3.0
0 stars 1 forks source link

Setting of OAUTH2_SERVER environment variable. #80

Open asishallab opened 2 years ago

asishallab commented 2 years ago

Setting of environment variables

Problem

The several components of Zendro, i.e. the graphql-server, the single-page-application, the GraphiQL interface, etc. need to know the OAUTH2_SERVER environment variable URL pointing to the registered OAuth2 service. In our Docker based environment this can be tricky for the graphql-server. The OAuth2 redirect URL cannot be something like keycloak:8080 which works only from inside the graphql-server container that shares a network with the respective keycloak container. However, localhost:8080 would not work either, because from inside the graphql-server this does not provide access to the host system. If we do not want to make all services running on the host network, we could solve this issue by using context insensitive IP Addresses.

The problem here is, that the IP Address of a Docker service is not static, it can vary every time the whole docker-compose is launched and probably varies between machines.

Thus, in the respective .env file of the Graphql-Server, we would need to lookup the IP Address of the keycloak service and export this environment variable after parsing. From this stems another technical problem. We use the proven dotenv package to manage our environment variables, but it does not support "dynamic" variables, less so, if they have to be initialized asynchronously, which is the case when looking up the IP Address of a service using node's dns package.

Solution

Consider this specification and provide feedback, please. If found to be a good solution, please implement.

Set the to be async looked up vars in the environment as a JSON object, like so in the .env file:

// .env file
DNS_LOOKUP_VARS='{"OAUTH2_SERVICE":"keycloak:8080"}'

Next, write a new helper module, async_env_init.js, that looks like this:

const dns = require('dns')

module.exports.dnsLookupAndSetEnv = async function() {
  // only do something, if input has been provided:
  if (process.env.DNS_LOOKUP_VARS !== undefined) {
    // 1. get the environment variable:
    const asyncDnsLookupVarDefs = JSON.parse(process.env.DNS_LOOKUP_VARS);
    // 2. Process each of those variable definitions:  
    Object.keys(asyncDnsLookupVarDefs).forEach((var_name) => {
      const lookup_service = asyncDnsLookupVarDefs[var_name];
      dns.lookup(lookup_service, (err, res) => {
        // TODO: handle error here!
        process.env[var_name] = res;
      });
    });
  }
}

Finally, require and invoke the above dnsLookupAndSetEnv in server.js, before the server starts to listen to incoming requests.

asishallab commented 2 years ago

Question: Would this not also solve our issue we had with Minio, too?

asishallab commented 2 years ago

If this solution is implemented, please make adding respective documentation to the Zendro user manual part of the issue. Thanks