Scott's Weblog The weblog of an IT pro focusing on cloud computing, Kubernetes, Linux, containers, and networking

Revisiting X.509 Certificates in Kubeconfig Files

In 2018, I wrote an article on examining X.509 certificates embedded in Kubeconfig files. In that article, I showed one way of extracting client certificate data from a Kubeconfig file and looking at the properties of the client certificate data. While there’s nothing technically wrong with that article, since then I’ve found another tool that makes the process a tad easier. In this post, I’ll revisit the topic of examining embedded X.509v3 certificates in Kubeconfig files.

The tool that I’ve found is yq, which is an incredibly useful tool when it comes to parsing YAML (much in the same way that jq is an incredibly useful tool when it comes to parsing JSON). I should probably write some sort of introductory post on yq.

In any case, you can use yq to replace the grep plus awk combo outlined in my earlier article on examining certificate data in Kubeconfig files. Instead, to pull out only the client certificate data, just use this yq command (you did know that Kubeconfig files are YAML, right?):

yq '.users[0].user.client-certificate-data' < ~./kube/config

(Of course, this command assumes your Kubeconfig file is named config in the ~/.kube directory; adjust the command as necessary based on your specific environment.)

The .users[0] portion of the yq command refers to the first user in the list of users in the referenced Kubeconfig file. If there’s more than one and you’re interested in seeing client certificate data for a different user, you’ll need to adjust that index.

From there, you can decode the Base64-encoded content and then pipe it to OpenSSL, just as described in the other post, to get a look at the actual certificate encoded within the Kubeconfig file. Here’s the full command:

yq '.users[0].user.client-certificate-data' < ~/.kube/config | base64 -D | openssl x509 -text

(Note that this command is for macOS; I believe you’ll need to use a base64 -d on GNU/Linux systems.)

I hope this is helpful to someone. Feel free to reach out to me on Twitter if you have any questions or any feedback. You can also find me in a number of different Slack communities, and you’re welcome to contact me there as well.

Posts from the Past, August 2022

I thought I might start highlighting some older posts here on the site through a semi-regular “Posts from the Past” series. I’ll start with posts published in the month of August through the years. Here’s hoping you find something that is useful (or perhaps entertaining, at least)!

August 2021

Last year, I had a couple of posts that I think are still relevant today. First, I talked about using Pulumi with Go to create a VPC Peering relationship on AWS. Second, I showed readers how to have Wireguard interfaces start automatically (using launchd) on macOS.

August 2020

I didn’t write too much in August 2020; my wife and I took a big road trip around the US to visit family and such. However, I did publish a post on some behavior changes in version 0.5.5 of the Cluster API tool clusterawsadm.

August 2019

This was a busy month for the blog! In addition to two Technology Short Takes, I also published posts on converting Kubernetes to an HA control plane, reconstructing the kubeadm join command (in the event you didn’t write down the output of kubeadm init), and one introducing Cluster API.

August 2018

In August 2018 I showed how to use (abuse?) Heptio Ark (now called Velero) to quickly populate new namespaces.

August 2017

How about a quick reference to some common AWS CLI commands?

August 2015

August 2016 was a slow month (or I was busy with VMworld, probably the latter), so looking back at 2015 I find a post on using Docker Machine with Vagrant. I still insist that Docker Machine was a hugely overlooked utility, but that’s water under the bridge now.

August 2014

This month I was exploring this new thing called CoreOS, and had three posts published on the topic (one on CoreOS itself, one on etcd, and one on Fleet and Docker).

August 2013

In August 2013 I mused, “Would it be possible to build your own network virtualization solution?”

August 2011

Skipping back to August 2011, I contemplated (ranted about?) logical-link multiplexing. You know, I kind of enjoyed those “Thinking Out Loud” posts…maybe I should start doing those again.

August 2009

This was the month that my very first book, Mastering VMware vSphere 4, was finally released. Here’s my blog post on the release of the book.

I’m not sure that going back any farther makes much sense; before that it’s all technologies that have long since sailed into oblivion. There is one small post of note: it was in August 2005 that the very first public version of this site went live on Wordpress. Read about it here.

Here’s hoping you enjoyed this little trip back into the archives. Maybe you found something useful you can still put to use! (Probably not, but it’s possible!) In the event you’d like to browse older articles, you can find a complete list of every post ever published in the Site Archives.

Site Category Changes

This weekend I made a couple of small changes to the categories on the site, in an effort to make navigation a bit more intuitive. In the past, readers had expressed some confusion over the “Education” and “Explanation” categories, and—to be frank—their confusion was warranted. I also wasn’t clear on the distinction between those categories, so this post explains the changes I’ve made.

The following category changes are now in effect on the site:

  • First, the “Education” category has been completely removed. I try to make almost everything on this site educational in nature, so why have an “Education” category? This really only affects you if you’d subscribed to that category’s RSS feed. (Did you know that every category and every tag has its own RSS feed?)
  • A lot of the content from the “Education” category has been moved into the “Explanation” category. This is the category that will contain posts where I provide some level of explanation around a concept, technology, product, or project.
  • The “Tutorial” category also picked up some new articles from the now-eliminated “Education” category. The “Tutorial” category contains walkthroughs or step-by-step instructions for doing something. There’s most likely going to be explanation along the way, but the distinction between “Tutorial” and “Explanation” is that the latter won’t contain step-by-step instructions for anything.
  • I added a new “Introduction” category, where I’ll put introductory-type posts about some technology, product, or project. The amount of explanation provided will be less than a typical article in the “Explanation” category, where I’ll tend to go a bit deeper.

I hope that these organizational changes make sense to readers, and make it easier to find the content you’re seeking. If you have feedback—and all constructive feedback is more than welcome!—please feel free to contact me on Twitter or reach out to me on any one of a number of Slack communities. Thanks for reading!

Using Default AWS Resources with Pulumi

Per the AWS documentation (although I’m sure there are exceptions), when you start using AWS you are given some automatically-created resources: a default VPC that contains public subnets in each availability zone in the region along with an Internet gateway and settings to enable DNS resolution. Most of the infrastructure-as-code tutorials that I’ve seen start with creating a VPC and subnets and gateway, but what if you wanted to use these default resources instead? I wasn’t really able to find a good walkthrough on how to do this, so this post provides some sample Go code you can use with Pulumi to identify these default AWS resources and use them.

I’ll approach this from the perspective of wanting to launch an EC2 instance in the default infrastructure that AWS provides for you in a region. To launch an EC2 instance using Pulumi (and most other infrastructure-as-code tools), there are several pieces of information you need:

  1. An AMI ID
  2. The instance type
  3. The name of an SSH keypair that’s been uploaded to/created in AWS
  4. A subnet ID
  5. A security group ID

The first three are probably things you’ll want to parameterize (i.e., make it possible for you to pass values in for your code to use). You can use Pulumi to look up the remaining values, so let’s see how to do that.

The first step is to look up the VPC itself. It might be possible for you to skip this step, but I like to include it for the sake of completeness. The Pulumi Go SDK has a function called “LookupVpc” that does exactly what you need it to do:

// Look up the default VPC
isDefault := true
desiredState := "available"
vpc, err := ec2.LookupVpc(ctx, &ec2.LookupVpcArgs{
	Default: &isDefault,
	State:   &desiredState,

Perfect; now you have the default VPC for your account in whatever region you’re using. Next, you need to look up the availability zones (AZs) in your selected region, because you’ll need that information when you go to find the subnets. This is a bit more complicated than just using the “GetAvailabilityZones” function; because the number of AZs may vary from region to region, some additional code is needed:

// Look up availability zones in the desired region
rawAzInfo, err := aws.GetAvailabilityZones(ctx, &aws.GetAvailabilityZonesArgs{
	State: &desiredState,
// Determine how many AZs are present
numOfAZs := len(rawAzInfo.Names)
ctx.Export("numOfAZs", pulumi.Int(numOfAZs))
// Build a list of AZ names
azNames := make([]string, numOfAZs)
for i := 0; i < numOfAZs; i++ {
	azNames[i] = rawAzInfo.Names[i]

Now you have the VPC and information about the AZs (including the number of AZs and the names of each AZ). Next, you can use the “LookupSubnet” function to look up the subnets in each AZ:

// Iterate through the AZs to discover subnets
pubSubnetIds := make([]pulumi.StringInput, numOfAZs)
for i := 0; i < numOfAZs; i++ {
	selectedAz := azNames[i]
	azDefault := true
	subnet, err := ec2.LookupSubnet(ctx, &ec2.LookupSubnetArgs{
		AvailabilityZone: &selectedAz,
		DefaultForAz:     &azDefault,
		VpcId:            &vpc.Id,
	pubSubnetIds[i] = pulumi.String(subnet.Id)

This code iterates over the list of AZs, and for each AZ looks up the subnet that is in the default VPC and is considered the “default” subnet for that AZ. It stores this list of subnets in the array named “pubSubnetIds”, which you’ll use later.

Only the security group remains before you have all the information you need to launch an EC2 instance:

// Identify default SG
defaultSgName := "default"
sg, err := ec2.LookupSecurityGroup(ctx, &ec2.LookupSecurityGroupArgs{
	Name: &defaultSgName,

And with all the information in hand, you’re now ready to launch your EC2 instance:

// Launch an instance
instance, err := ec2.NewInstance(ctx, "instance", &ec2.InstanceArgs{
	Ami:                      pulumi.String("ami-123456789"),
	InstanceType:             pulumi.String("t3.large"),
	KeyName:                  pulumi.String("my-keypair-name"),
	SubnetId:                 pubSubnetIds[0],
	VpcSecurityGroupIds:      pulumi.StringArray{sg.ID()},
	Tags: pulumi.StringMap{
		"Name":       pulumi.String("my-instance-name"),

Obviously, this code doesn’t show parameterizing the AMI ID, instance type, or key pair name; I’ll leave that as an exercise for the reader. (Or, if you really want to see that information, let me know and I’ll add it in another blog post.) The code snippets above also don’t show any error handling or such, which would be necessary (the Go compiler will complain if you don’t reference the err variable populated in these code snippets). However, you should be able to assemble this into a working Pulumi program without too much difficulty.

For those that would like a bit more assistance in putting all this together in a working example, have a look in the pulumi/default-aws-infra folder of my GitHub “learning-tools” repository. There you’ll find a complete, working Pulumi program incorporating all the code shown above.

I hope this is helpful to folks out there. If you find an error in this post, please let me know so that I can fix it! You can reach me on Twitter, and I also lurk in the Pulumi community Slack instance. Alternately, if you just feel like reaching out and saying hi, I’d love that, too!

Technology Short Take 157

Welcome to Technology Short Take 157! I hope that this collection of links I’ve gathered is useful to someone out there. In particular, the “Career/Soft Skills” section is a bit bigger than usual this time around, as is the “Security” section.


  • Interested in understanding how NAT Traversal works? David Anderson’s post on how NAT Traversal works should help.
  • This happened a couple of months ago, but I don’t think I’ve linked to it in a Technology Short Take: the Envoy Proxy open source project announced Envoy Gateway, a “new member of the Envoy Proxy family aimed at significantly decreasing the barrier to entry when using Envoy for API Gateway (sometimes known as ’north-south’) use cases”.
  • This is a slightly older article from Ivan Pepelnjak on using netsim-tools to build Vagrant boxes, but let’s be real—his stuff is kind of timeless anyway, right?


Cloud Computing/Cloud Management

Operating Systems/Applications

  • I believe I shared this a short while ago on Twitter: this article talks about gmailctl, a command-line utility for managing Gmail filters using a configuration file. This looks handy enough that I almost wish I liked Gmail.
  • Julia Evans has a post discussing some “new-ish” command-line tools; it might be worth checking out. I use a fair number of these (and referenced a few of them in my 2018 “Supercharging My CLI” blog post).
  • This is useful to know.
  • Rob Harrop has a series on using Cue to generate Envoy configurations; part 1 of the series—along with links to the other posts in the series—is available here.
  • Mark Dominus has a two part series (part 1, part 2) on “things I wish everyone knew about Git.”
  • Here are some notes on macOS zsh configuration.


  • Paul Johnston explains why he believes serverless systems aren’t software systems. I must admit I initially took umbrage with the title, but Paul does admit that the title of the article is a little click-baity (is that a word?). Regardless, Paul does effectively point out some of the differences in building “traditional” software systems versus serverless systems.


Career/Soft Skills

  • Constantin Gonzalez shares some thoughts on how to find good opportunities in your career or life.
  • I’m a big fan of Cal Newport’s books, but for some reason never really read a lot of the stuff on his blog. However, this article on the Einstein principle recently popped up for me, and even though it’s a much older article I still enjoyed it and found some useful advice in it.
  • I really enjoyed this article by Jan Schaumann on learning by lurking. There’s some good stuff in this article, like a link to this article on asking the duck.

That’s it for this Technology Short Take. Your feedback is always welcome; feel free to contact me via Twitter, or on any one of a number of different Slack communities. I’d be happy to chat with you.

Recent Posts

Network Programmability and Automation, Second Edition

In late 2015, I was lucky enough to be part of a small crew of authors who launched a new book project targeting “next-generation network engineering skills.” That book, Network Programmability and Automation, was published by O’Reilly and has garnered praise and accolades for tackling head-on the topics that network engineers should consider mastering as the field of network engineering continues to grow and evolve. I was excited about that announcement, and I’m even more excited to announce that the early release of the second edition of Network Programmability and Automation is now available!


Technology Short Take 156

Welcome to Technology Short Take #156! It’s been about a month since the last Technology Short Take, and in that time I’ve been gathering links that I wanted to share with my readers. (I still have quite the backlog of links to read!) Hopefully something I share here will prove useful to someone. Enjoy the links below, and enjoy your weekend!


Making Flatpak Firefox use Private Browsing by Default

In April 2021 I wrote a post on making Firefox use Private Browsing by default, in which I showed how to modify the GNOME desktop file so that Firefox would open private windows by default without restricting access to normal browsing windows and functionality. I’ve used that technique on all my Fedora-based systems since that time, until just recently. What happened recently, you ask? I switched to the Flatpak version of Firefox. Fortunately, with some minor tweaks, this technique works with the Flatpak version of Firefox as well. In this post, I’ll share with you the changes needed to make the Flatpak version of Firefox also use private browsing by default.


Git Difftool and Meld as a Flatpak

I’ve recently started migrating many of the applications on my Fedora 36 laptop to their Flatpak versions. For the most part, this has been pretty straightforward, although there isn’t really any method for migrating configuration and data. Today I ran into a problem with Meld, a graphical diff utility, and using it with the git difftool command. Below I’ll share how I worked around this problem.


Technology Short Take 155

Welcome to Technology Short Take #155, just in time for the 2022 Memorial Day holiday weekend! (Here in the US, at least.) I mean, don’t you want to spend this weekend catching up on some technology-related articles instead of cooking on the grill and gathering with friends and family? I certainly hope not! Still, for those who need a little technology fix over the weekend, hopefully I’ve included something useful in the list of articles below. Enjoy!


Fine-Tuning Control Plane Access with Cluster API

When Cluster API creates a workload cluster, it also creates a load balancing solution to handle traffic to the workload cluster’s control plane. This is necessary so that the control plane endpoint is decoupled from the underlying control plane nodes (which facilitates scaling the control plane, among other things). On AWS, this mean creating an ELB and a set of security groups. For flexibility, Cluster API provides a limited ability to customize this control plane load balancer. In this post, I’ll show you how to use this functionality to fine-tune access to a workload cluster’s control plane when using Cluster API with AWS.


Technology Short Take 154

Welcome to Technology Short Take #154! My link of links and articles from around the Internet is a bit light on networking and virtualization this time around, but heftier in the security, cloud, and OS/application sections. I hope that I’ve managed to include something that you’ll find useful. Enjoy the content!


Technology Short Take 153

Welcome to Technology Short Take #153! My personal and professional life has kept me busy over the last couple of months, so things have been quiet here on the blog. I’ve still been collecting links to share with you, though, and here’s the latest collection. I hope you’re able to find something useful here!


Technology Short Take 152

Welcome to Technology Short Take #152! Normally I’d publish a Technology Short Take in the morning on a Friday, but I really wanted to get this one out so I’m making it live late in the day on a Monday. Here’s hoping I’ve included some content below that you find useful!


Using cert-manager with Kuma for mTLS

When configuring mutual TLS (mTLS) on the open source Kuma service mesh, users have a couple of different options. They can use a “builtin” certificate authority (CA), in which Kuma itself will generate a CA certificate and key for use in creating service-specific mTLS certificates. Users also have the option of using a “provided” CA, in which they must supply a CA certificate and key for Kuma to use when creating service-specific mTLS certificates. Both of these options are described on this page in the Kuma documentation. In this post, I’d like to explore the use of cert-manager as a “provided” CA for mTLS on Kuma.


Follow Up: Bootstrapping Servers into Ansible

Seven years ago, I wrote a quick post on bootstrapping servers into Ansible. The basic gist of the post was that you can use variables on the Ansible command-line to specify hosts that aren’t part of your inventory or log in via a different user (useful if the host doesn’t yet have a dedicated Ansible user account because you want to use Ansible to create that account). Recently, though, I encountered a situation where this approach doesn’t work, and in this post I’ll describe the workaround.


Technology Short Take 151

Welcome to Technology Short Take #151, the first Technology Short Take of 2022. I hope everyone had a great holiday season and that 2022 is off to a wonderful start! I have a few more links than normal this time around, although I didn’t find articles in a couple categories. Don’t worry—I’ll keep my eyes peeled and my RSS reader ready to pull in new articles in those categories for next time. And now for the content!


Getting Certificate Details from HashiCorp Vault

It seems there are lots of tutorials on setting up a PKI (public key infrastructure) using HashiCorp Vault. What I’ve found missing from most of these tutorials, however, is how to get details on certificates issued by a Vault-driven PKI after the initial creation. For example, someone other than you issued a certificate, but now you need to get the details for said certificate. How is that done? In this post, I’ll show you a couple ways to get details on certificates issued and stored in HashiCorp Vault.


Using Test-Driven Development for Kustomize Overlays

I am by no means a developer (not by a long shot!), but I have been learning lots of development-related things over the last several years and trying to incorporate those into my workflows. One of these is the idea of test-driven development (see Wikipedia for a definition and some additional information), in which one writes tests to validate functionality before writing the code to implement said functionality (pardon the paraphrasing). In this post, I’ll discuss how to use conftest to (loosely) implement test-driven development for Kustomize overlays.


Technology Short Take 150

Welcome to Technology Short Take #150! This is the last Technology Short Take of 2021, so hopefully I’ll close the year out “with a bang” with this collection of links and articles on various technology areas. Bring on the content!


Older Posts

Find more posts by browsing the post categories, content tags, or site archives pages. Thanks for visiting!