A ray of light in the middle of darkness can save your life.
In 1998 Madonna released one of her finest albums whose name was Ray of Light. That song marked the lives of many people during that year. The song was played all over the world.
In this article, we will see how the NodeJS Netfoundry.io SDK can spark the light to consume a Dark Service API. A ray of light within your code is the spark to consume your Dark Services in a highly secured manner.
In our previous article, we’ve learned how to expose a Dark Service API using Netfoundry.io, MuleSoft Anypoint Platform, and Oracle Cloud Infrastructure. In that article, we’ve explained the procedure to deploy APIs as Dark Services and access them from a terminal (laptop) that is sitting on a completely different network. That is already very valuable and powerful at the same time, but we can go even further. And if you are wondering what do we mean by going even further? Just keep reading the article.
(Property of Netfoundry.io)
What do we mean by the app is the new edge?
The API consumer (the app) is going to contain the necessary elements to connect with the Dark Service API. The invisibility of the dark service will be lighted (if you will) through the application. The application, through the strong identity, will be entitled to consume the API, not the server, nor any other application running in the same environment, just the entitled application. In fact, for the rest, the Dark Service will remain…pretty much invisible.
This goes beyond just protecting the API with any type of authentication mechanism. When we have a Dark Service API, not only that consumers need to be authenticated to use it, but the strong identity is going to allow us to make it visible, to the rest of the world the Dark Service will remain invisible…
When we incorporate classic mechanisms to authenticate/authorize consumers for our public APIs, for example, OAuth 2.0, even though we add controls to avoid non-authorized consumers to use our APIs, the truth is that our API remains visible to pretty much everyone. A non-authorized consumer may be able to try to get access, to fuzz the requests, to guess the credentials, and in the worst case scenario: to consume it.
With Netfoundry.io we can make our APIs visible just for valid consumers, and invisible to the rest of the world. The consumer application is the edge and is what will contain the right elements to reach the APIs. And that is exactly what we are going to share in this article.
Netfoundry.io offers different SDKs for both enabling Dark Services and consuming them. There are different programming languages you can use for those SDKs, for example, Java, NodeJS, Python, C, Go, etc.
My Dark Service API
This consumer endpoint: http://darskide.api.com is reachable through the internet, but invisible at the same time. Try to access it and you will not reach it. The question is: how can an application get access to it? The response is: through Netroundry.io as we explained in the previous article. But now we will share how the identity can be incorporated into your code that consumes the API, in this case, a very simple NodeJS application.
Our scenario is the following:
a) We need to consume the API from the NodeJS application running in a Digital Ocean droplet
b) As we explained in our previous article, our API is deployed in MuleSoft inside a private Oracle Cloud subnet
c) The API is not reachable from the internet. But we have turned it Dark (invisible) using Netfoundry
d) The NodeJS application running in Digital Ocean will be able to consume the API, and it will be the only piece of software within that droplet that can reach the API (darkside.api.com).
The previous diagram depicts the idea of what we want to achieve. And as you can see the only piece of light that can reach our dark service is that small NodeJS consumer application.
The steps you need to take are:
• Follow this article.
• Create a new endpoint at the Netfoundry.io console
• Download the identity of the endpoint
• Download the NodeJS dependency to incorporate the Netfoundry SDK
• Create a very simple NodeJS application
• Use the identity generated in step #3
• Test your application
Let’s create the new endpoint. Go to your Netfoundry.io console and head to the endpoint section:
Click on the blue plus button, and then give it a name and download the key (jwt file):
Then, add this endpoint to the AppWAN:
Now, using the ziti-edge-tunnel command line utility:
# enroll from a token file
./ziti-edge-tunnel enroll –jwt ./myDarkConsumer.jwt –identity ./myDarkConsumer.json
That will produce a json file by the name myDarkConsumer.json that will represent our identity.
Now is the time to create our consumer API code. But first, we need to download the NodeJS dependency. The complete documentation can be found here: https://github.com/openziti/ziti-sdk-nodejs
npm i @openziti/ziti-sdk-nodejs
Once you install the ziti SDK, create a file with the following code and name it callMyDarkService.js:
import ziti from ‘@openziti/ziti-sdk-nodejs’;
const zitiIdentityFile = process.env.ZITI_IDENTITY_FILE;
// Authenticate ourselves onto the Ziti network
await ziti.init( zitiIdentityFile ).catch(( err ) => { /* probably exit */ });
const on_resp_data = ( obj ) => {
console.log(`response is: ${obj.body.toString(‘utf8’)}`);
};
// Perform an HTTP GET request to a dark OpenZiti web service
ziti.httpRequest(
undefined,
‘http://darkside.api.com/’, // Dark Service HTTP URL
‘GET’,
‘/api/people/1’, // path part of the URL including query params
[‘Accept: application/json’ ], // headers
undefined, // optional on_req cb
undefined, // optional on_req_data cb
on_resp_data // optional on_resp_data cb
);
Set the environment variable to point to the identity file:
export ZITI_IDENTITY_FILE=/path_to_your_identity/myDarkConsumer.json
And execute your code:
node callMyDarkService.js
The result:
root@rcarrascogb2:~/nf/samples/node# node callMyDarkService.js
on_req entered: { req: 94757361460352 }
on_resp entered: {
req: 94757361548992,
code: 200,
status: ‘OK’,
headers: {
‘Transfer-Encoding’: ‘chunked’,
‘strict-transport-security’: ‘max-age=15768000’,
allow: ‘GET, HEAD, OPTIONS’,
etag: ‘»ee398610435c328f4d0a4e1b0d2f7bbc»‘,
‘x-frame-options’: ‘SAMEORIGIN’,
vary: ‘Accept, Cookie’,
‘Content-Type’: ‘application/json’,
date: ‘Wed, 21 Dec 2022 22:59:08 GMT’
}
}
response is: {«name»:»Luke Skywalker»,»height»:»172″,»mass»:»77″,»hair_color»:»blond»,»skin_color»:»fair»,»eye_color»:»blue»,»birth_year»:»19BBY»,»gender»:»male»,»homeworld»:»https://swapi.dev/api/planets/1/»,»films»:[«https://swapi.dev/api/films/1/»,»https://swapi.dev/api/films/2/»,»https://swapi.dev/api/films/3/»,»https://swapi.dev/api/films/6/»],»species»:[],»vehicles»:[«https://swapi.dev/api/vehicles/14/»,»https://swapi.dev/api/vehicles/30/»],»starships»:[«https://swapi.dev/api/starships/12/»,»https://swapi.dev/api/starships/22/»],»created»:»2014-12-09T13:50:51.644000Z»,»edited»:»2014-12-20T21:17:56.891000Z»,»url»:»https://swapi.dev/api/people/1/»}
We can call our API which is sitting privately within a private Oracle Cloud Infrastructure subnet, from a Digital Ocean server, and through the internet.
But if we do a ping to the darkside.api.com hostname from the Digital Ocean server, see what happens:
root@rcarrascogb2:~/nf/samples/node# ping darkside.api.com
ping: darkside.api.com: Temporary failure in name resolution
If we try telnet:
root@rcarrascogb2:~# telnet darkside.api.com 80
telnet: could not resolve darkside.api.com/80: Temporary failure in name resolution
From my Digital Ocean server, we can call the Dark API through the NodeJS application, but outside the application, we cannot reach the API. We cannot resolve the hostname, and most importantly we cannot even reach it. Isn’t that interesting?
The ray of light that we can use to light the darkness is Netfoundry’s SDK. And as you could see is very simple to incorporate into your code. With that, your consumers’ effort to consume your Dark APIs is very low.
In the next article, we’ll elaborate on the idea of how to automate the enrollment of your API consumers.
Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.