Everything you need to do to simulate the environment of a trusted profile compute resource.
Does this sound scary? Trusted profile, compute resource, access token, token conversion? I recently had to deal with these for an app deployed to Kubernetes. In this blog post, I discuss how I managed to develop and test the app on my local machine.
As a developer, I prefer to develop (including testing) and code locally. Sometimes, the code needs to interact with functionality that is only available in a certain environment. So how do we deal with this situation? Is there a workaround that allows for local tests?
Recently, I worked with trusted profiles and compute resources on IBM Cloud. Through this work, a special access token is made available in a designated compute environment. That token is then exchanged for an IBM Cloud IAM (Identity and Access Management) access token that allows you to work as a trusted profile (a special IAM identity.)
In this blog post, I share the lessons learned and tricks that I applied in order to develop the app code locally. What is needed to simulate an environment of a trusted profile compute resource?
Cloud-based security vs. local development
One of the security features of IBM Cloud is the concept of a trusted profile. There are different options available on how to assume the identity of a trusted profile. Without going into details, one of them is by operating on an identified (configured) compute resource, obtaining a special access token and then turning it into an IAM (Identity and Access Management) access token. One of the supported scenarios for compute resources is a service within a namespace of a Kubernetes cluster. For more details, read my recent blog post: “Turn Your Container Into a Trusted Cloud Identity.”
Because the above compute resource is a feature of IBM Cloud security, it is only available there. So, how can I develop an app locally that uses that feature? An option that I looked into (but did not follow further) is to use extensions for my code editor, such as the Kubernetes and Remote Development extensions. I wanted to have something working really on my machine. After looking into the entire authentication and authorization flow, I decided to simulate the compute resource and injecting a real access token—a JSON web token (JWT)—into my local test environment.
Simulate the compute resource
The approach to simulate a compute resource and to provide a valid access token is independent of the coding style. When working with any of the IBM Cloud SDKs (software development kits), the Container Authenticator is used with Kubernetes compute resources. The documentation on Authentication and the Container Authentication (e.g., the Node.js and Python SDKs) details how the token is obtained by the Container Authenticator and what needs to be configured. It is the name of the file from which a valid compute resource token can be read. On Kubernetes, the file is made available in the pod to the running app.
When working solely with the IBM Cloud API functions, your code will utilize the function to turn a valid compute resource token into an IAM access token using the available API function. But, first, you need to read that compute resource token from a file. So it is similar to the SDK—a local token file needs to be read instead of the one made available in the Kubernetes pod. In Python, it may be something like this to read the file name from an environment variable TEST_TOKEN_FNAME, and, when not set, use the default location:
You may wonder how a valid token can be easily retrieved from the valid compute resource token and kept current. I resorted to deploying a skeleton app to the Kubernetes environment and setting up the trusted profile with my Kubernetes environment as the compute resource. Next, I connected to the Kubernetes pod and copied over the token to my local file. On the command line, with access to the Kubernetes cluster set up, you can connect to a pod named “tp-demo” like this:
Then, in the shell in the running container, show the token (and manually copy it over to your local file):
Another option is to use kubectl to copy over the token file from the pod to your machine:
The above uses the
tar command on the pod to package up the directory with the compute resource token. Thereafter, that archive is extracted on my local machine and strips away the first four levels in the directory hierarchy (“/var/run/secrets/tokens”). The token file (which is actually two symbolic links and an file with content) ends up in the current directory.
When developing your app, you have to repeat the copy process whenever the token expires. Typically, the token is valid for 60 minutes and is refreshed after some 45 minutes. If you are curious, check on the token itself on when it expires.
Decode and pretty print the compute resource token—a regular JSON web token (JWT)—that is stored in the file “sa-token”:
The above breaks up (
tr) the JWT components, decodes (
base64) and pretty prints them (
jq)—see the screenshot above. The attribute
exp holds the expiration timestamp as integer. Simply decode such an integer like this:
The command prints “Mon May 8 15:01:51 CEST 2023” on my machine. Another refresh is coming up pretty soon.
It is great to have more enhanced options for cloud security. As developer, I prefer local to remote development, so it is ideal if I can continue to develop and test apps locally. This is also the case for apps utilizing trusted profiles with Kubernetes-based compute resources. It does not require much, only some technical insights to simulate cloud security for local development—copy over the file with the access token and make the app use it.
If you have feedback, suggestions, or questions about this post, please reach out to me on Twitter (@data_henrik), Mastodon (@firstname.lastname@example.org) or LinkedIn.