In an effort to improve my understanding of the Go programming language, I’ve start working the problems described on the Project Euler website. Over the past weekend I was able to complete problems 1 through 4.
Solving these kind of problems programmatically has been good challenge for me. It has been a long time since I exercised that part of my brain that makes me a good programmer.
So far I have solved these problems:
The first 100 problems are considered easy and there are over 700 in total. I won’t be running out of coding problems any time soon.
I have been wanting a new Apple laptop for some time now. My current machine is a 15" Retina MacBook Pro–the Late 2013 model. Apple classifies their hardware as vintage once it has not been sold for 5 years and less than 7 years. Beyond 7 years since sales were discontinued and the product is considered obsolete. This Apple support page explains about Vintage and Obsolete Products.
My MacBook Pro was bought in June 2014, so I’ve had it for 6 years. I don’t know when sales of the Late 2013 model ended. I expect my computer to be considered obsolete sometime in the next 12 months. It’s still a very capable computer. With a 2.3 GHz Quad Core i7 processor, 16 GB of RAM, and a 1 TB SSD, it is still respectable. My biggest complaint is the size of the hard drive. The combination of photos, movies, music, and audio books, along with all my other data, overwhelmed the storage capacity several years ago. I’ve offloaded all my movies, music, and audio books to my previous laptop, a 2009 MacBook Pro, and a 1 TB external drive.
When Apple announced that they were making their own CPUs for Mac computers, I couldn’t wait to get one. All summer and fall I’ve been anxiously awaiting the announcement of new Apple Silicone powered laptops. However…
My iPhone is 5 years old. It’s an iPhone 6s Plus bought in November 2015. I want a new phone too. I’ve only got so many dollars to spend on Apple, and getting both a $1000 phone AND what would likely be a $2200-2400 computer in the same year, isn’t fiscally responsible.
After thinking about it for quite a while I decided that I would wait and see how the new Apple laptops performed, how they held up mechanically, and to see if there were any major issues, before getting one for myself.
What I dreamed of getting was a 14" MacBook Pro in the same form-factor as the 13"—much like what happened with the new 16" replacing the 15". Today’s announcement, while very exciting, doesn’t include that dream machine. They did announce a new M1 powered versions of the MacBook Air, the Mac Mini, and the 13" MacBook Pro.
Both the MacBook Air and the 13" MacBook Pro have up to 16 GB of “integrated memory”. Previously you could get up to 32 GB of RAM. I am curious to see how 16 GB of integrated memory performs compared to 32 GB of plain RAM. Of the three, I think I’d get the Mini first, the Air second, and the MacBook third. The idea of a Mac Mini desktop, with the largest internal SSD possible (2 TB) and a couple always attached external drives, combined with a MacBook Air is very intriguing.
The desktop computer would hold all my media, all my data, everything in one place. The ultra portable MacBook Air would be for times when I was away from my desk. Hmmm…
This year, by delaying the acquisition of a new MacBook Pro, I was able to order an iPhone 12 Pro, which will arrive here on Friday. Not getting a shiny new computer this year, and only getting a shiny new iPhone, is a first world problem that I can live with.
For some time I’ve been interested in Ansible, which is Red Hat’s lightweight, infrastructure automation tool. I found an Ansible tutorial on YouTube from LearnLinuxTV. Jay, the host, uses several VirtualBox VMs as his test lab for Ansible. I decided to go a slightly different route.
I used Vagrant to create and minimally provision a lab environment that I could use for the tutorial. After some trial and error, the Vagrantfile below is my result.
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagranyfile API/syntax version
VAGRANTFILE_API_VERSION = "2"
Vagrant.require_version ">= 2.2.0"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
servers=[
{
:hostname => "lab01",
:box => "generic/ubuntu1804",
:boxurl => "generic/ubuntu1804",
:ip => "10.1.1.11"
},
{
:hostname => "lab02",
:box => "generic/ubuntu1804",
:boxurl => "generic/ubuntu1804",
:ip => "10.1.1.12"
},
{
:hostname => "lab03",
:box => "generic/ubuntu1804",
:boxurl => "generic/ubuntu1804",
:ip => "10.1.1.13"
},
{
:hostname => "lab04",
:box => "generic/centos7",
:boxurl => "generic/centos7",
:ip => "10.1.1.14"
}
]
servers.each do |machine|
config.vm.define machine[:hostname] do |node|
node.vm.hostname = machine[:hostname]
node.vm.box = machine[:box]
node.vm.box_url = machine[:boxurl]
node.vm.network :private_network, ip: machine[:ip]
node.vm.provider :libvirt do |libvirt|
libvirt.memory = 512
libvirt.cpus = 1
end
end
end
ansible_pub = File.read(File.join(Dir.home, ".ssh", "ansible.pub"))
config.vm.provision :shell,
:inline => "echo 'appending SSH public key to ~vagrant/.ssh/authorized_keys' && echo '#{ansible_pub }' >> /home/vagrant/.ssh/authorized_keys && chmod 600 /home/vagrant/.ssh/authorized_keys"
config.ssh.insert_key = false
end
The servers array has entries for each lab machine to be created. Each machine has its own
hostname, its own IP address, and a Vagrant box image and URL. I’m using a private network for the
IP addresses, and I matched the IP address with the host name. lab01 has IP address 10.1.1.11,
lab02 is .12, and so on.
The servers.each loop creates each VM, giving it 512MB of RAM and a single CPU. I’m using QEMU/KVM
as my virtualization layer, so I added the vagrant-libvirt plugin.
After the VMs are created, I’m using an inline shell provisioner to add an ssh key to the VM. I
generated a new key pair just for Ansible, and this inline script puts the public half of that key
pair on the VM.
In Ansible, I added a line to the ansible.cfg to specify vagrant as the ssh user.
With this setup I can quickly and painlessly create 4 VMs, using two different operating systems, ready for use in my tutorial. I’m enjoying learning about Ansible, but I had fun creating this lab environment using Vagrant too.
The GitHub repository for my lab environment is called lab is has an MIT license. Help yourself.
In my day job I use a VPN, specifically GlobalProtect from Palo Alto. In our installation it is setup to be “full duplex” — all the traffic from your local machine is routed through the VPN. Previous we had a half duplex setup, where only the private network traffic was routed through the VPN.
GlobalProtect has a client, which was setup by our security staff. It’s dead simple to use and annoying to work with. Between the DNS jiggery-pokey that GP does, and my own DNS settings, I’ve had problems with some non-work sites not working.
The alternative to using the official client is to use OpenConnect. This requires installing it and using it on the command line, but doesn’t mess with IP traffic as badly as GP wants to. The problem is that OpenConnect doesn’t setup routes for the private network, and therefore some work-related sites don’t work.
My choices, then, are: (1) Use the official GP client and live with all my traffic being routed through the VPN, and have some sites not work, or (B) use OpenConnect and have some other things not work.
There is a third choice. Write a script to figure out the routing rules that need to be added to the routing table, and use that, along with OpenConnect, to establish your VPN connection. One of my co-workers created a script and shared it with me. His was able to work on either Linux or macOS. I only use macOS for work, so I didn’t need the Linux specific stuff. Therefore my script is a bit more compact and straight-forward than his.
As will all scripts you find on the Internet, use caution before blindly putting them to use. This script works for me, in my situation, with my edge cases. Your mileage will almost certainly vary.
#!/bin/bash
set -e
set -o pipefail
# Dependencies
# brew install iproute2mac - gets ip command for macOS
if ! [[ -x $(command -v ip) ]] ; then
echo "ip command not found"
echo "Run brew install iproute2mac to install it"
echo "Then run $0 again"
exit
fi
# Colors
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
# This script works on macOS. It futzes with the routing table
# to only route 10.* and 129.130.* traffic over the Global Protect
# VPN, if that VPN is active.
# Detemine what gateway traffic is flowing through
GATEWAY=$(netstat -nr | grep -v "::" | grep default | awk '{print $2}')
echo -e "Gateway: ${BLUE}$GATEWAY${NC}"
# Determine which network interface the host is using
LOCAL_IFACE=$(ip route show | grep default | awk '{print $5}')
echo -e "Local interface in use: ${BLUE}$LOCAL_IFACE${NC}"
# GP VPN IP range and prefix - macOS strips the `.0` in the netmask
GPVPN_RANGE="10.130.48.0/20"
GPVPN_PREFIX="^10.130.48"
echo -e "Global Protect range: ${BLUE}$GPVPN_RANGE${NC}"
echo -e "Global Protect prefix: ${BLUE}$GPVPN_PREFIX${NC}"
# Protect local IP from being routed
if [[ "$(netstat -nr | grep -E "192\.168\.4\.1")" ]] ; then
VERB="replace"
else
VERB="add"
fi
echo
echo "Setting a route for the local network"
echo -e " ${RED}ip route $VERB 192.168.0.0/2 dev $LOCAL_IFACE ${NC}"
sudo ip route "$VERB" 192.168.0.0/16 dev "$LOCAL_IFACE"
if [[ "$(netstat -nr | grep -E $GPVPN_PREFIX)" ]] ; then
VERB="change"
else
VERB="add"
fi
echo
echo "Setting a route for the GP VPN"
echo -e " ${RED}route $VERB $GPVPN_RANGE $GATEWAY ${NC}"
sudo route "$VERB" "$GPVPN_RANGE" "$GATEWAY"
# Start the VPN...
sudo openconnect --user=mhn --protocol=gp --script "$HOME/src/openconnect/vpnc-script" gpvpn.ksu.edu
exit 0
The subtitle of this posting ought to be “1,726 Day Activity Streaked Ended by Syncing Failure.”
I bought an Apple Watch the day ordering opened, and received my watch in mid-May 2015. Initially I didn’t do much with the Activity tracking. That changed in late 2015, when I started closing all three activity rings every day.
The three rings are Move, Exercise, and Stand.
Move: You set a calorie goal, the default is 400, and the ring is closed when you burn that many calories above what you would burn if you were not active. You can adjust the goal number up or down. For me a normal day, with 20 or minutes of active exercise, will easily reach the 400 calorie number.
Exercise: This ring is closed when you have 30 or more minutes of exercise. Apple doesn’t say what parameters have to be met to count as exercise. For myself it seems like any minute where my heart rate is elevated to about 100 beats per minutes does the trick. You cannot adjust this number, it’s 30 minutes or bust.
Stand: In order to close the stand ring, you need to stand and move around at least one minute per hour, at least 12 hours in a day. This ring is by far the easiest to close. The watch helpfully will remind you to stand at :50 minutes past the hour, if you haven’t already done so. Like Exercise, you cannot adjust this goal.
Starting in August 2015 I have closed all three rings, every day, one thousand, seven hundred, and nineteen times, according to the activity record kept on my iPhone. I had minor knee surgery midway through this streak, and, by taking my daily walk at 12:01 am the day of the surgery, and then breaking my walk into three ten minute walks the day or two following, I was able to sustain my streak. I walk in the rain, the cold, the heat, you name it. Day in and day out for four and a half years.
Last Wednesday, May 6th, my phone restarted itself and the watch somehow was never able to reconnect after that. My watch continued to capture and record calories, stand minutes, and exercise, but it was no longer syncing to my iPhone.
I didn’t discover this fact until Friday, May 9th. To say I was dismayed would be a massive understatement. To see partially filled rings for Wednesday, and nothing at all on Thursday or Friday gave me a horrible sinking feeling.
Why didn’t I notice the issue sooner? Exhaustion from a combination of from being quarantined, from caring for an elderly cat, from worry about potential work furloughs—all combined to make checking my ring progress every night something that didn’t happen. Had I discovered the break in syncing last Wednesday, and early enough in the day, I might have been able to reset my watch and keep the streak going. The window to (a) notice and recognize there was a problem, and (2) figure out the solution, was only 5 hours long.
When I discovered that synchronizing between the watch and phone wasn’t working I immediately called Apple Support. This was the first of what would eventually be six support sessions, that were ultimately unsuccessful in recovering my data.
Over the course of about two hours on the phone with two different tech support people, a level-1 rep and then a senior rep, we only managed to capture some screen shots of the phone, and capture and upload some log files for Apple Engineering to examine. The level-2 rep promised a call back on Monday at 11 am. She assured me that she was determined to resolve my issue.
Over the weekend I tried several times to reconnect my watch by powering down either the phone or the watch, or both, and then powering them on in different orders. I realized while doing this that the phone could locate (Find My) watch, but that the watch could not find my phone.
The promised 11 am call never happened. About 11:30 am I contacted Apple Support and ended up talking to a new support rep. He said that there was no response from engineering yet, and that it could take several days. With people working from home, old iPhones and iPads were getting pressed into service, which had increased call volumes. He said he would call me back at 6 pm on Tuesday. The later time to hopefully allow a response from engineer.
Once again, the promised return call never happened. Once again I contacted Apple and introduced myself and my issue to yet another support rep. He said there was an update from engineering. The response was, “reset the watch.” This would wipe out any data that resided on the watch that hadn’t been synced to the phone. He wanted to tell me that the data on the phone would be fine as it was backed up to my computer. I had to explain to him that I needed the data from the watch. He got it, and said he’d resubmit my case to engineering, and said he’d call Wednesday at 6 pm.
Guess what happened at 6 pm? Not a call back from Apple Support. I ignored the whole issue until about 8pm, when I contacted Apple Support. This call started with a level-2 rep, who also wanted to tell me that, as long as my phone was backed up, I wouldn’t lose any data. Once she understood my reason for not wanting to reset my watch, she said there wasn’t any other way to fix things.
I asked what would happen if I backed up my phone, reset it, and then restored it: would the watch have to be re-paired with the phone, or would the previous pairing work? She assured me it would not need to be re-paired. I told her I’d try that course of action, and she said she’d call back in 60 minutes to see what my status was.
I initiated a “Reset all Settings” activity on my phone at about 8:27 pm. Shortly after 10 pm the phone had reset, and the synchronizing of the Apple Watch was done. Yay? It was the wrong watch.
In an effort to gather more information, first thing Wednesday morning, I dug out my original Apple Watch (now know as a Series 0) and had paired with my iPhone. I was trying to see if pairing still worked at all or not. It did work. And then I forgot to remove that watch from my phone before backing it up and restoring it. So it synced up with the Series 0 and ignored my Series 4 watch altogether.
I unpaired the Series 0, reset the watch again, and waited. Shortly after midnight the reset and synchronization completed. It had found the Series 0 in the backup I restored from, and set it up again.
This morning I realized that I had a back up from last Friday, May 8th, that did not have the Series 0 attached to my phone. Since that backup had all the activity I’d ever collected it was a good place to restore from.
Unsyncing the Series 0 from my iPhone again, I did a “Erase all Content and Setting” reset, and then restored the iPhone from Friday’s backup. This took about 100 minutes, from 8:27 am until 10:11 am. The watch still would not sync to the phone. In fact, when I opened the Apple Watch app on my iPhone and selected the watch, it would show the detail screen for the watch and sit there with a spinner. I had to force quit the app to regain control of the phone.
Clearly the reset and the erase had not accomplished anything.
At about 10:30 am I contacted Apple Support for the sixth time. Engineering was still saying that reseting the watch was the only solution. Support says there is no other way to get data from the watch to the phone. The only option is to reset the watch.
At 10:49 am I reset my Apple Watch Series 4 and lost the stored activity data it had for Wednesday May 6th through today. After the reset the watch and phone were syncing again.
Having an entire week to prepare myself for the possibility that, through no fault of my own, I might lose my activity data and therefore my 1700+ day streak helped. I’m not happy at all about losing the data, or about no longer being able to see an ever increasing number in the Activity app awards section. In my head I’ll know to add what ever number my new streak is at to the one that should be there today (1,727), but it’ll be four and a half years, before I set a new daily streak as far as the Activity app is concerned.
I am disappointed in Apple Support for making promises to recontact me and then not following through. I understand the realities of working in a call center—their time is not theirs to budget and schedule—but they should know that and either not promise to call, or tell the customer to use the link in the “Your upcoming call with Apple Support” email to initiate contact themselves.
I am also disappointed that there is no way to capture data on a watch that is no longer syncing properly with its iPhone. I get that there are privacy concerns, especially around health or health related data, but surely there is some way to allow for recovering data.
Some of the shine of Apple is lost now. I don’t know when or if it will return to its former level. I have spent probably close to $10,000 on Apple products and services in the past 20 years. I’m a huge fan. I still want new shiny things from Apple, even today. But I won’t invest so much of my heart into them now. I can’t deal with the potential emotional cost down the road. Especially in these utterly unique times.
It is possible to edit some Activity data through the Health app.
To add a missing stand minute, for example:
You can also edit Exercise data, using the same steps, substituting the actual type of workout, and a calorie count. Unfortunately you can only do this for today and the previous day. I had read several years ago about the stand hours trick, but didn’t know you could also edit exercise data.
It is a testament to how much cognitive drain trying to work from home during a pandemic, that I didn’t remembered this until today. Had I remember last Wednesday or Thursday, I could have replaced the missing data from Wednesday and Thursday, reset my watch and been fat, dumb, and happy.
As it stands now, I can (one minute at a time, twelve times per day for eight missing days) poke in some zero kilo calorie minutes to fill out my stand rings for the missing eight days, which will keep at least that streak going.
Pay attention to odd or out of place things that happen with your computers, which includes phones, tablets, watches, in addition to laptops and desktops. When something out of the ordinary happens try to step back from whatever “are you kidding me!?” emotion might have been stirred up, and check for a ripple effect.
Or maybe not get trapped in a 1,727 day streak.
I ordered my first Apple Watch the day they went on sale, April 24, 2015. I was slow enough completing the process that it didn’t ship for a couple of weeks, so I didn’t get the watch until early May.
I’ve worn it, and later the Apple Watch 4 I bought to replace it, every day since. Initially I closed some of the rings some days, but rarely all three rings in a day. Beginning in August 2015 I started closing all three rings every day.
I’ve closed all three rings every day for 1,722 days. One thousand, seven hundred and twenty-two days.
That streak is not at an end, but the “official” record of it on my iPhone is in jeopardy. On Wednesday, three days ago as I write this, my iPhone, a now five-year old iPhone 6S Plus, freaked out and started asking me for my iCloud password repeatedly. After entering that password, I discovered I had to re-enter my mail password, re-setup Authy, and sign back into other apps that sit behind passwords.
At the time I found this annoying, but didn’t really think too much about it. Yesterday afternoon I realized my Apple Watch was no longer syncing with my phone. Looking at the Activity app on th phone I could see a partial day recorded for Wednesday, and nothing at all for Thursday or Friday. It felt like I’d been punched in the stomach.
I immediately rebooted my phone and then my watch. Still no connection. I called Apple Support. Within minutes I was talking to a very helpful woman who gathered some data and had me try restarting my devices again. When that didn’t work she escalated the case to a higher level of support. The next woman and I spent more than 90 minutes on the phone together. By the end of the call she had opened a ticket with engineering, and had captured some log files from my phone. I also sent her several screen shots from the phone and the watch. We also did a full back up of the phone to my computer, using a password so that the health and activity data would be backed up too.
I’m now waiting for a return call on Monday, hopefully to set up a call with the engineering folks. Since the end of yesterday’s phone call, I’ve discovered what I think is the problem: the iPhone’s Bluetooth is not fully functional.
It is only paired with my Airpods. It shows an entry called “Apple Watch”, but there’s no “I” icon to allow seeing more information about that connection. When I try to pair the iPhone and my iPad, the iPad sees the phone, but cannot connect to it. The phone doesn’t see any nearby Bluetooth devices.
From the phone I can “find my watch”, but the reverse is not true. From the watch I cannot ping the phone to locate it.
Whatever happened Wednesday morning about 11 am has damage/crippled/borked the Bluetooth interface on the phone. My hope is that engineering can somehow reset that interface in a way that doesn’t lose my activity data.
I asked during the call how long the watch will store data without syncing to the phone. The answer is: until it runs out of storage, usually about 7-10 days. My watch has 5 GB of used space and 7 GB of free space. There is about 3 GB of music on the watch that I would instantly remove, however, that requires that it be synced with my phone.
It is not possible to pair the watch to a new phone with out wipingg it clean—losing all the data it has. If that were possible I’d go buy a new iPhone today, and restore the backup to the new phone and then pair the watch.
On my iPhone the activity history shows 1,719 days with all three rings completed. The watch has data showing 3 more days (Wednesday, Thursday, and Friday), bringing the (potential) total up to 1,722 days. By Monday that potential number will be 1,724 plus Monday.
I am on tenterhooks waiting for Monday’s call. Both tech people were impressed with the length of my streak, and the second one in particular is determined to keep it if at all possible. I fervently hope she can pull that off.
Gmail, or Google Mail, was famously announced on April 1, 2004. April Fool’s Day. Free email with unlimited storage. Initially you had to be invited to get an account. I desperately wanted to have a Gmail account and finally managed to cage an invitation through Matt Haughey, whom I knew of through his web site A Whole Lotta Nothing. I got my first Gmail address in June 2004, and I’ve been using it to one degree or another ever since.
There are email standards. One of those standards is that, while the local part of your address - the bit
preceding the at sign - can contain a dot (.), the dot cannot be the first or last character, and
it cannot be repeated, e.g, joe..user@example.com. The local part of the address needs to be
unique with in the domain. You can’t have two bob@example.com email addresses that go to two
different people.
Google breaks this rule in a subtle way. They allow any and all variations, involving dots, of your
local part to resolve as your account. An example will make this clearer. Joe User signs up with
Gmail. He picks joe.user@gmail.com as his address. He will get mail addressed to
joe.user@gmail.com. He will also get the email addressed to any of these variations:
joeuser@gmail.com
j.o.e.user@gmail.com
joe.u.s.e.r@gmail.com
j.o.e.u.s.e.r@gmail.com
And so on. Google says “dots don’t matter in Gmail addresses”.
If someone accidentally adds dots to your address when emailing you, you’ll still get that email.
On the surface, this is a nice idea, but in implementation it proves to be massively annoying.
By not following the email standard for unique local parts to email addresses, Google has set a trap for every other Internet business who allows email addresses to be used as user account names. Unless the developers at Example Incorporated code their user on-boarding process to prevent any variation of an established account, using Gmail as the username, where the variation involves adding or subtracting dots within the local part of the address, then they will end up allowing what appear to be two (or more) distinct accounts to be created on their site, the resolve to only one Gmail address.
For example: Joe User signs up at PayPal using his joe.user@gmail.com email address for the
username. He adds his phone number and sets a password and he is good to go. Then one day he gets
an email stating, “You added your phone number to your account”, which lists a phone number poor Joe
has never seen before.
PayPal allowed another person named Joseph User to create an account using joeuser@gmail.com as the
username. To PayPal the two accounts are unique. joe.user is different than joeuser.
Unfortunately, Google sees joe.user and joeuser as variations on the same email account. Joe User will now get emails from PayPal that are meant for Joseph User. Joseph won’t understand why
he isn’t getting his PayPal emails.
Because additional information is needed to reset the password for the other account, and the prompts for that information obscure the alternate contact information for the other user (which is good), there is no way to reach out to the other user to let them know that their email address isn’t what they think it is - unless that other email address is Googlable enough to find out enough information to try to contact the other user via other means.
My name is not that uncommon. There are several other people in my town of 53,000 who share my first
and last name. I have no idea how many people nationwide are named Mark Nichols. I do know that
there are enough that I get a continuous stream of emails using the dot-less variation of my Gmail
address. I get hotel reservation confirmations and bill folios. I get reminders of dental
appointments, and car service appointments. I get emailed copies of Lowe’s purchase receipts. I get
access to shared Google Docs, and invitations to weddings and other events. All because someone at
Google 16 years ago though it would be cool to “save people from typos” and decided to allow email
address local parts to be non-unique within the gmail.com domain.
Since there is no way every other business, organization, what have you, on the Internet is going to carefully vet email addresses used as usernames to ensure that two seemingly unique Gmail addresses aren’t in fact merely dot variations, then you should not use your Gmail address as a username. You’ll still get emails sent to dot variations of your address, but if you know your account username is NOT your Gmail address, then you won’t have momentary panic when you get an email confirming your week long hotel stay in Miami.
I’m starting the tedious process of visiting each online account that uses my Gmail address for the user name, and changing that user name (if possible) and changing the associated email address. Fortunately I have all of my accounts stored in a password manager, so I should be able to identify 99% of them.
I’m retiring my Gmail account as the email I use to sign up for things. I’ll create a new account on my personal domain for that. Hopefully this will prevent 30 minutes of late night panic about an email from PayPal announcing that I’ve added a phone number to my account that I’ve never seen before.
I’ve been using Let’s Encrypt to provide SSL certificates for all my domains and subdomains for a couple of years now. Let’s Encrypt certificates are only good for 90 day, and with 17 certificates to manage, renewing them all manually was a pain. So I put the commands into a cron job (actually several cron jobs) that renewed each certificate once a month. The cron job mailed me when it was done so I knew which certificates had been renewed.
Recently my web host, WebFaction, started offering built-in Let’s Encrypt certificates - ones that I would not have to renew myself. At 40 days to go they automatically generate a new certificate to replace the old one. This is great, but I’ve lost some visibility into the process.
I wanted a way to list all my SSL certificates, and their current date ranges. Each SSL certificate
has a date and time they become active, and a date and time when they expire. This command will
return those two pieces of information for the domain example.com.
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
For example:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null |
openssl x509 -noout -dates
notBefore=Nov 28 00:00:00 2018 GMT
notAfter=Dec 2 12:00:00 2020 GMT
You could create a bash shell script that was just 17 instances of that command and call it a day.
Inelegant, but functional. A better solution would be to have a file of domains to check, and a
script to do the checking.
Here’s part of my file.
zanshin zanshin.net
books books.zanshin.net
geek geek.zanshin.net
health health.zanshin.net
music music.zanshin.net
And here’s the script.
#!/bin/bash
set -e
set -o pipefail
###
# certcheck displays the good from and good until dates for SSL certificates.
# It expects a file (.certs) that contains a list of domains to query. Each
# entry in the file has two parts, the name to display, and the domain to
# query. The two entries are separated by a space.
#
# .certs file example:
# example example.com
# www www.example.com
###
echo -e "certcheck\n"
filename=".certs"
while read -r line; do
# Parse input into an array, using space as delimiter
certarray=($line)
# Get the name and the domain
name=${certarray[0]}
domain=${certarray[1]}
# Get the certificate start and end dates
result=$(echo | openssl s_client -servername $domain -connect $domain:443 2>/dev/null | openssl x509 -noout -dates)
# Muck with internal field separator (IFS) to split $result on new line
oldIFS=$IFS
IFS=$'\n'
datearray=($result)
IFS=$oldIFS
startdate=${datearray[0]}
enddate=${datearray[1]}
# Print the results in columns
printf "%-15s %-30s %-30s\n" "$name" "$startdate" "$enddate"
done < "$filename"
echo -e "\nfinished"
The script is a simple loop. For each line in the file it does the following steps:
$name contains the label to use, and
$domain has the domain to query.$domain the open_ssl command is run. The two lines of output are captured
in $resutl. The key part here is that it is two lines of output.\n. So that IFS can be returned to it’s original
value it is saved in oldIFS first.$startdate and $enddate respectively, a printf command
can be used to create the output. printf is used as it provides better control over formatting
than echo would.That’s it. Loop through the file, use the domain to run the open_ssl command and capture the
result. Split the result on the new line character. Print the results, one per line, neatly
formatted into columns.
Here is an example of the script’s output.
certcheck
zanshin notBefore=Feb 2 19:30:06 2020 GMT notAfter=May 2 19:30:06 2020 GMT
books notBefore=Jan 24 11:13:48 2020 GMT notAfter=Apr 23 11:13:48 2020 GMT
geek notBefore=Jan 23 07:36:14 2020 GMT notAfter=Apr 22 07:36:14 2020 GMT
health notBefore=Jan 31 14:24:25 2020 GMT notAfter=Apr 30 14:24:25 2020 GMT
music notBefore=Mar 18 12:09:18 2020 GMT notAfter=Jun 16 12:09:18 2020 GMT
finished
Any time I’m curious about the state of my SSL certificates I can run this script.
WFH. Work From Home. Or, as I think of it at times, What’s fucking happening?
10 days ago, as I write this, was the last day I worked at my office. The university where I am employed scheduled a test work remote day on Thursday, March 12th. By the end of the day it had been extended to include Friday. By the end of Friday we were all told to work remotely for the foreseeable future, at least through the end of the semester.
As an IT professional my job is well suited to remote work. There are entire IT companies that are 100% distributed. Last autumn, due to some HACV work in my building, that uncovered asbestos, we all worked from home for a week. That was fun actually. Going from a work-in-the-office with other people setting, to working-at-home by yourself, as been an adjustment. Knowing that this is reality for the next two, three, or more, months, puts an entirely different spin on it.
I’m an introvert, and I like things to be just so. Working from home appeals to those aspects of my personality. I also appreciate some amount of what I call “social friction.” The act of interacting with other people, in person, feeds some part of me. I miss that part of being “at” work. I don’t miss the noise and interruptions, the smells, and wonky temperature from the HAVC system.
I am incredibly fortunate that my wife, Sibylle, has a very similar temperament. She is also an introvert, and is someone content within herself. She is fortunate enough to have found a way to make her piano studio work remotely. We have found a rhythm that works for us, here in our home.
I get up at my normal work day time. I shower and get dressed as if I were going to the office, and then have breakfast. Then I come into my home office and start my day. At lunch time I leave work and go out in the rest of the house for lunch. I have eaten lunch at home most days for over a decade, so that part of my daily routine hasn’t changed. After lunch I return to work until the end of the day when I come home. My wife has her morning routine and then goes to her piano studio on the lower level of our house, and works on lessons and video critiques for her students. During the day we exchange emails and texts, exactly like we did before COVID-19. Keeping as much normalcy as possible has made this transition easier for us. It has helped to ground us at a time when everything seems ungrounded and out of control.
The coming weeks and months will be interesting and challenging. I think Sibylle and I will be able to navigate those challenges and find ways to care for ourselves. I hope the world at large can do the same thing. I fear for many that the sudden upending of regular life, will prove devastating and difficult to adjust to. Our society, the world’s society, will forever be different following this pandemic.
For now, I’m, we are, working from home, wondering what’s fucking happening.
The dig command is useful but can overwhelm with its output. This utility website simplifies the
process and the results.