In the world of penetration testing, as I’m often involved in with ROS, those taking on the role of attackers are referred to as the “red team”, and those defending as the “blue team”. Red team people are often regarded as the rock stars of INFOSEC, but one key difference is that red-teamers only have to succeed in their efforts once, whereas blue-teamers have to succeed every time. Unfortunately, when the blue team succeeds, nothing notable happens, so they don’t get much of the glory.
This song is a tribute to the unsung heroes of the blue team; Gotta keep out the bad guys, baby!
Unsurprisingly, the “gotta keep out the bad guys” line was about the first thing I thought of, and everything stemmed from that. There were lots of blue-teamy things I could have written about, but I preferred to keep it short. The string-bend bass riff was the first bit of music, then the funky guitar parts, though I ended up dialling them back a bit in favour of some chuggy rhythm guitar. As in my other tracks, I was keen to use Synthesizer V for vocals, and the backing vocals came out really well. I wrote the lead guitar solo, then thought a higher vocal part alongside it might work, and it was also a chance to have a dig at the red team; it’s my favourite bit of the song.
There are a lot of guitar parts overall (all played by me), and only some small pad and organ keyboards for backing. I was especially happy that I managed to pull off the more aggressive bass parts and the lead solo. As usual, the drums were all done with Logic’s Drummer instrument, which does a great job without getting drunk and falling asleep during rehearsals, and its excellent “follow” mode meant that the drums could match what I’d played on the bass, rather than being some disconnected pattern.
As usual, I’m not too happy with my vocals (PRs welcome!), but Logic’s Flex Pitch editor works enough magic to get the job done. This track could really do with someone that can get a bit more grungy in the verses, with a hint of Elvis for the chorus.
[Intro]
Don’t break a sweat
from a constant threat.
We’ve got the tools to meet them
and firewall rules to defeat them.
[Verse]
We’ll take our time
to build our defences.
No need to be concerned,
we know the consequences.
They’re going to attack
our networking stack,
but we can keep them guessing as
their port scans come to nothing.
[Chorus]
Because, I’m on the blue team, baby,
we’ve got to always win.
Gotta keep out the bad guys,
can’t ever let them in.
Come join the blue team, baby,
we need your awesome skills.
Come watch that bad actor
try to guess my second factor.
[Solo]
Oooh red team stays outside,
don’t want you here.
Just go away
and don’t come back.
You’ve gotta find another way.
[Verse]
Alarm bells ring
from a tripwire’s string.
Logs tell a sad, sad story
of a search for a way in.
SOC screens flash
for a matching hash
We’ve seen this one before
and there’ll be many more
[Chorus]
That’s why I’m on the blue team, baby, (ooh yeah)
we’ve got to always win. (blue team, blue team)
Gotta keep out the bad guys, (ooh yeah, gotta keep out the bad guys baby)
can’t ever let them in.
Come join the blue team, baby,
we need your awesome skills.
Show your strength, let it shine,
help take those APTs offline
We’re on the blue team, (ooh yeah)
got to always win. (blue team, blue team)
Gotta keep out the bad guys, (ooh yeah, gotta keep out the bad guys baby)
can’t ever let them in.
We’re on the blue team, baby,
we’ve got to always win.
We’re the unsung heroes.
(gotta keep out the bad guys, baby)
If you like this song, please consider supporting me by buying my album, “Developer Music” on Bandcamp, and sharing links to my song posts on here. If you can sing (or play something) and would like to be involved in musical projects like this, please get in touch, as I could really use your help!
There’s a problem here though – that unique validation on the email field is subject to a race condition. If two requests are received very close together, both can pass validation, but then the second one will fail with a duplicate key error on the User::create call. While that sounds unlikely, it happens for real sometimes, and you’ll see something like this in your web logs when it does:
The 201 response is a successful creation, but it’s followed a second later by a 500 failure for the duplicate request. The Laravel log will then contain one of these:
To deal with that we can trap the creation error, and return an error response that looks the same as the validation error:
try {
$user = User::create(
$request->only(
[
'email',
'name',
]
)
);
} catch (QueryException $e) {
//1062 is the MySQL code for duplicate keyif ($e->errorInfo[1] !== 1062) {
//Rethrow anything except a duplicate key errorthrow $e;
}
return response()->json(
[
'error' => true,
'message' => 'That email address already has an account.',
],
Response::HTTP_UNPROCESSABLE_ENTITY
);
}Code language:PHP(php)
This way, as far as the client is concerned, it was a straightforward validation failure with an appropriate 422 error code, and we don’t get spurious 500s clogging up our error logs.
I post skiing videos fairly often, and people keep asking me how I make them, since by most normal understanding of shooting video, they seem like magic.
Skiing fast in Combloux, France on a nice sunny day, filmed by my talented, invisible friend
Is there a drone that follows me? Do I have a friend that can ski backwards very fast while filming, staying out of shot, and not casting a shadow (a vampire?)? Nothing quite so exotic, but it’s still pretty clever.
The Camera
I use an Insta360 One X camera. As you might guess from its name, it shoots 360° video, that is, it captures a complete sphere, looking in all directions at once instead of just a rectangle pointing in one direction. It achieves this by using two cameras and two fisheye lenses, mounted back-to-back, each capturing slightly over a 180° field of view as two square images. These are then mapped into a 2:1 rectangular representation (which conveniently works with common image and video formats like JPEG and MPEG-4) where the poles are the top and bottom edges, which implies a lot of distortion, a bit like a Mercator map projection. This is a full spherical frame image in this format – the distortion is clear (my skis are not the size of surfboards), but the pixels on the left and right sides will match when wrapped around:
A spherical image mapped to a 2:1 rectangle
The combined resolution of these two sensors is 5.7k (i.e. more than 4k), however, you need to bear in mind that all those megapixels have to cover a complete sphere, so you really need it to be this high if you’re going to render out videos that only look in one direction, and thus only use a small portion of the original view.
The “slightly over 180°” field of view is important as it means that when the two video streams are combined, there is a discus-shaped region centred around the camera that is hidden from view, and this is used to make the camera itself (and the selfie stick it’s mounted on) effectively invisible, without having a visible discontinuity (join) between the two image sources.
It’s possible to see the join sometimes, especially when only one lens is exposed to the sun – modern optics are good, but there’s only so much they can do! In this weird perspective, the join is running roughly vertically a bit to the left of me, roughly perpendicular to the lens flare ray from the sun, which stops at the join. The sky is slightly lighter on the left side of the join, probably due to lens flare:
You might have noticed that using spherical images requires a new perspective (ha!) on taking pictures and planning shots; Since you can rotate the view in all directions and zoom in and out, you can produce some very unusual perspectives that are not possible any other way. In the image above, the camera is effectively looking straight up and is zoomed out a long way, so the horizon around it appears as a circle.
One advantage of fisheye lenses is that they have effectively infinite depth of field, so everything is always in focus, and it doesn’t need autofocus. On the other hand, you’re not going to get any subtle bokeh effects!
Stills
You can extract still images from the video stream as either rectangular frames, or full 360° images (as I did above). The camera has a higher-resolution stills mode, however, that’s not really possible to use at speed. The stills quality from video streams is remarkably good.
I’d be delighted if someone had taken this picture of me (no doubt after much setup) – that it’s a selfie is borderline miraculous!
I’m particularly pleased with this shot – the spray of snow was caused by the camera hitting the ground at speed, and the camera itself made a gap in the spray, which happened to line up with me!
Stabilisation
The camera has “FlowState” stabilisation, which uses accelerometers and gyroscopes to keep track of where the horizon is and keeps it flat and steady, regardless of what angle the camera is held at – when you’re filming in all directions at once, it doesn’t really matter which way the camera is “pointing”, in fact the whole concept of pointing it at something doesn’t really apply. This stabilisation is extremely good, keeping things nice and smooth even during really quite violent movement and vibration, but it’s also partly responsible for the viewpoint feeling disconnected from the subject.
Mounting
The traditional place to mount an action camera like your average GoPro for skiing is on top of your head, attached to a helmet. That’s fine as it points forwards, but it means you never star in your own movies, and the resulting footage tends to be pretty monotonous. Mounting a 360° camera there is going to be a bit dull too – it means you lose the view of the ground because your helmet will get in the way, but your friends might be nicely captured. To get a nice perspective on yourself, you need to shoot from a bit further away – selfie stick to the rescue!
The camera isn’t that heavy, but when it’s waggling about at the end of a 1.2m carbon fibre telescopic selfie stick in a fast moving situation, it can be hard to control. When skiing you use your hands for holding your poles and partly for balance, and it’s actually painful to hold stick and pole at the same time. To counter this, I designed and 3D-printed a mount that clamps the stick to my ski pole fairly rigidly, and also offsets the angle a bit – otherwise there would be a risk that the “invisible selfie stick” feature would also make my ski pole disappear, but it also gives you a bit of creative control as you can easily move it between front and side viewpoints with a twist of the wrist.
The camera mounted on my bracket – finger space is a bit tight with fat gloves on
This mount is a great improvement, and makes for much steadier shots and safer precarious camera positioning (like 2cm from the ground at 100km/h!). You still lose a bit of motion in that arm (watch how little my left arm moves compared to my right in the video above), and the balance of your poles changes a lot, but it’s quite workable.
My ski pole mounting bracket, top view
Snowboarding is a bit easier because you have your hands free, and the results can look straight out of a video game:
I also printed a bracket to mount it on my mountain bike’s down tube, and this taught me a couple of things: Vibration on bikes is much more violent than on skis, so the selfie stick rattles (the telescopic parts rattle inside each other) and wobbles a lot more; you go a lot closer to things on a bike, and it’s easier to hit the camera.
A new take on jousting
The end result still looks quite cool though.
Editing
Insta360 have an iPad & iOS app called… Insta360. The iPad version is great, but the phone one is quite usable too. You have a choice of aspect ratios, trimming and editing, adding soundtracks, colour enhancements, filters, and more. As well as nicely smoothed view angle and zoom factor manual edits, it has some very clever features for auto-tracking a subject. Remember that if you’re rendering out a normal-looking video, as I’ve done here, it’s not just that you can choose your view angles – you have to; clips of the ground whooshing by or the tops of some trees and a bunch of clouds are not that interesting!
The software has some enhancement filters, though they are not very controllable – you can’t for example just “make it brighter”, you have to pick a filter preset that happens to look like what you want, then twiddle an amount slider. The dynamic range is really good – notice that in all these clips you can still see the snow texture in direct sunlight, the highlights are not blown out, yet there is still detail in dark areas.
Extras
Insta360 have some other mounts that could be interesting for skiing including a back mount that puts the camera above and slightly behind you for a 3rd-person perspective – just don’t ski under any low branches, and be careful on chairlifts!
They also have a GPS Action Remote gadget, which in addition to controlling the camera remotely, injects a GPS data stream into the video recording. In the editor this data can be used to drive on-screen speedometers and maps. I’ve not tried that, but I’d love to given that I’ve long had a thing about going quite fast. Here’s a clip of me doing that on the Mont Fort World Cup speed skiing track in Verbier, now sadly defunct due to the glacier’s retreat, which also shows how much video quality has improved since 2013 (it was shot on a Contour 1080p camera):
At the start you can see just how steep this is! I managed 147km/h (92mph) on this run.
Posting online
For the most part I share videos via Mastodon, Twitter, and Strava. All of these have similar restrictions/requirements for videos regarding size, video format, bit rate, duration, etc. I usually render full-resolution output from the Insta360 app at 100Mbit/sec, do any simple edits using LosslessCut, and then compress for final output using ffmpeg. The ffmpeg command I use is:
This compresses to just under 5Mbit/sec using the H.264 codec (sadly, vastly superior H.265 video is not accepted by these sites yet), scales the video down to 1280px wide (720p), sets the pixel format that most of these sites want, and also includes a 90% audio volume reduction, as it’s just really noisy otherwise.
Youtube has support for 360° videos, however, I find that these are actually mainly annoying to watch; rendering out a conventional rectangular clip just works better for me, and I’m the director around here…
Gripes
There are a few annoyances with this camera:
The tiny OLED screen is completely unreadable in bright sunlight.
There are only two buttons to navigate through all its menus and options, but I never know which one to press.
It’s very picky about the SD cards it will work with, though that’s understandable.
The battery life is reasonable, even in the cold, and while I printed a lens cover, the lenses seem to be surprisingly resistant. It doesn’t mind getting covered in snow. For some unknown reason, the 3 threaded sections of the selfie stick use a left-hand thread, which is annoying as it means that the action of tightening the camera undoes the selfie stick.
The One X is a few years old now, and Insta360 have since released newer One X2 and X3 models which solve the screen and controls problem by adding a small touch screen that’s more readable. It also makes the standard case a bit more robust and waterproof, has a bigger battery, better image sensor, and improved audio. Should Insta360 like to give me one to test, I wouldn’t say no!
Tailwind is a CSS framework created by Adam Wathan, and beloved by many. I’ve found it’s really helped me understand CSS grid in particular, and has made building responsive layouts really easy. It sometimes comes in for criticism because it is based on utility classes, meaning you mostly skip the ability to attach styles to elements via CSS selectors (a fundamental feature of CSS). However, when it’s used with a content framework that provides components (like Laravel’s Blade), they can effectively take on that role and prevent repetition. One of the consequences of using Tailwind is that you often end up with lots of classes in HTML class attributes.
Anyway, Tailwind is cool and I like it, so I decided to write a song about it, in the same vein as my previous effort for The Good Ship Laravel.
The arrangement in Logic Pro
It’s all about a hapless, design-challenged developer (could that possibly be me??) having trouble with their styling and layout, and thinking they should give this Tailwind thing a go as a way to help them solve it. They give Tailwind a try, it takes them a while to get to grips with it, but they finally figure it out and all is rosy.
The “I ain’t got no style; I got Tailwind” line was the first line that came to me, followed by “I got classes…”, giving me most of the chorus, but the verses took a while longer. I wrote the music for the chorus first, then worked backwards to make a verse that led into it nicely. There’s a break in the middle that seemed really obvious (“When my mode is getting dark…”), straight out of many other songs – there’s nothing revolutionary going on here!
I played the guitar parts for the chorus (which is a simple C, Am, G), and eventually found a sequence for the verse that worked well (C, F, Dm, G, then Csus2, G at the end). I wrote a very melodic bassline on keyboard. Logic Pro’s Drummer took care of the brush-style drums – I didn’t spend too much time on them. Unfortunately I then found I simply couldn’t play the chord changes in the verse smoothly enough, so I enlisted the help of musicalduo on Fiverr, who did a great job of it. He also played a really smooth version of the bass part, which I hadn’t asked him to do. So my guitar playing only appears in the chorus, and I need to practice more!
I don’t rate my singing (I would love to work with someone that can sing!), but Logic’s Flex Pitch editing works wonders. I also really like using it for vocal harmonies – figuring them out using Flex Pitch, then re-singing them, just as I did for The Good Ship Laravel. I had a cold for a couple of weeks and early versions sounded like I was holding my nose, so I re-recorded them when I was feeling less bunged up! I’ve discovered that you can get away with really bad backing vocals, so long as they are in tune!
I have some other, older songs I’ve not released, one about npm, one about being an open source maintainer, and a half-finished Whitney Houston-style belter about composer… PRs welcome!
Lyrics
[Verse]
I’m trying to build an app that looks good
It’s all taking much more time than it should
Classes and styles going ‘round in my head
turns out it’s not as easy as I originally said.
I’m finding my breakpoints, feeling defeated
and all this old stuff will have to be deleted
One thing is clear from all this confusion
I’ve had to come to an unfortunate conclusion
[Chorus]
No, I ain’t got no style;
I need tailwind
I got problems, maybe more than a few
I need tailwind
Oooooh, I ain’t got style;
I need tailwind
Not sure what I’m gonna do
I need tailwind
[Verse]
You might think I’m crazy, but I’m gonna read some docs
I’ve gotta figure out how to arrange all these blocks
It looks great on my Mac, but explodes on my phone
and judging by Stack Overflow, I’m not alone
I ask, “hey Adam, you got any ideas?”
He says, “yeah, get Tailwind to mop up those tears”
So I’m going with the flow, flexing my grid
trying to figure out what those tutorials did, but still,
[Chorus]
I ain’t got no style;
I’ll try tailwind
I got problems, maybe more than a few
I’ll try tailwind
Oooooh, I ain’t got style;
I’ll try tailwind
Not sure what I’m gonna do
I’ll try tailwind
[Middle]
When my mode is getting dark
and my layouts fall to bits
I keep trying all kinds of things
until suddenly everything clicks
[Verse]
My grid’s all cool unlike my previous wreck
I don’t have to keep my units in check
I love my pretty colours, my text is so clean
I hate to think of what it might have been, but now
I’m slicing up my blade into little tiny pieces
It’s the moment for components, it’s all utility
I’m loving how it works everywhere, especially on my phone
Tailwind’s really in several classes of its own
[Chorus]
No, I ain’t got no style;
I got tailwind
I got classes, maybe more than a few
I got tailwind
Oooooh, I ain’t got style;
I got tailwind
Maybe you’d like to try it too
We got tailwind
[Outro]
Oooooh, I ain’t got style;
I got tailwind
Oooooh, I ain’t got style;
I got tailwind