Keycloak and the art of exploring

Bryan Kroger
4 min readJan 21, 2020

It is sometimes the case that I’ll run into a software package that I’ve never even heard of and need to do something amazing with it. Up until about a week ago I had never heard of a software package called “Keycloak.”

It’s basically a canned oauth solution, like AWS::Cognito. My job was to write some automation that could bootstrap this software to our needs installing some basic clients and roles. This type of thing is actually pretty standard.

What I mean by “this type of thing” is that we’re going from a POC to something more robust. The POC for this product has been proven to some degree, now we’re going to add some automation around things to help make our processes better and more robust.

In the beginning of this product life cycle, people were just doing what they had to do to get things done. Many things were done by hand and just sort of patched together. This is a good pattern because we never want to do too much work right away and run the risk of missing our target. Being second to market is sometimes as good as being dead.

The cost of doing the fast work the beginning is always going to be a slightly longer tail of work to design and “fix” the parts that need work. For example, we often see bundles of terraform code strung together in the “best guess” form. My job is to untangle that code and get it into better shape.

Really what I’m doing is a combination of story telling and a little magic, or maybe art. The story I want to end up telling is “this infrastructure is a joy to work on” or “this infrastructure makes sense.” What I don’t want is a story that says “this was too complicated and broken.” I’m always looking for that sweet spot between complexity and simplicity.

This Keycloak work is a wonderful example of what we often face in the realm of DevOps, and quite frankly, I think this is the purest form of what DevOps really is. I took a piece of software with no previous knowledge and created some software that uses the API of that software to fulfill the requirements of the business.

Lucky for me, I work at a place where people are very good about filling out tickets and requirements. Sometimes this isn’t the case and we have to do some mind reading to figure out what’s really needed.

For Keycloak I first needed to figure out how it’s authentication to its API works. I love Keycloak for this example because the documentation is actually not that great. At least, compared to some other API’s, it’s actually not good at all. And for this article, that’s pretty great. In my opinion, most of what DevOps really is hovers around being able to take limited or bad documentation or information and turn it into something useful. The best DevOps engineers are the ones that have a mental flexibility that allows for bad things in the process. But more importantly, has the emotional fortitude and mindfulness to make those bad things work for them.

According to the documentation, the KeyCloak API uses a barer, or token authentication. That’s easy enough, I’ve dealt with that plenty of times. After some trial and error, I was able to get a simple authentication workflow figure out.

#!/usr/bin/env python
import requests
import json
import sys
import boto3
project_name = sys.argv[1]
domain = "staging.insight.renovo.cloud"
headers = {
"Content-Type": "application/json",
}
data = {
"grant_type": "password",
"scope": "openid",
"username": "admin",
"password": "super_awesome_password",
"client_id": "admin-cli"}
url = "https://authn.blah.yada.com/auth/realms/master/protocol/openid-connect/token"
response = requests.post(url, data=data)
r_json = response.json()
token = r_json["access_token"]
print(token)

This was roughly what the code looked like. It’s very different now, but we’ll get into that later. The idea of this article is more about pointing out how I got from a scratch pad of “how does this work?” to “this is now easy to read and understand.”

I was able to get a barer token and use it future request as such:

headers = {
"Content-Type": "application/json",
"Authorization": f"bearer {token}"
}

Now let’s get a list of clients:

url = "https://authn.blah.yada.com/auth/admin/realms/master/clients"
response = requests.get(url, headers=headers)
print(response.status_code)
clients = response.json()
for client in clients:
print(f"{client['id']}\t{client['clientId']}")

Okay, so, let’s checkpoint where we are here.

  1. I can now interact with an API I’ve never used before.
  2. I can use the authentication mechanism to get the token I need, then do stuff with the token in the way that the API expect.
  3. I can list clients, which is great because once I start creating the clients, I want to also verify that they’ve been created.

In the next article we’ll be showing off how we go from this scratch pad to something a little more robust.

Originally published at https://medium.com on January 21, 2020.

--

--

Bryan Kroger

Exploring the space at the intersection of technology and spirituality.