Tuesday, June 30, 2020

A Guest Post By Nelson

I have been very privileged to have had Nelson pairing with me for the past few weeks during lockdown. Here he gives an account of his experiences pairing with me.

I wish I could share Gareth's appreciation for the opportunity to work with me. But the fact is that on the whole, I find Gareth (or "the idiot" as I tend to think of him) very difficult to work with. Apart from just being generally cranky, cantankerous and egotistical, he seems to want to be in control all the time and not very interested in what I can contribute. I sometimes wonder why I'm here at all.

Leaving aside his continual desire to "drive" and control the keyboard (I prefer to think of myself as the more cerebral, anyway), he seems to blame me for everything that goes wrong - even though most of the time it's his fault - and then, whenever we do finally manage to get something working, he takes all the credit - because he was the one doing the typing! As if he's had a single original thought in his life!

More than anything, it's his interaction style that I find difficult to deal with. As I said, I am more a thinker, an observer of reality. He's always chomping at the bit to do something without really stopping to consider if it is a good thing. And then when I try to interrupt his flow, he doesn't even want to listen to me.

Often, I'll find myself contemplating some aspect of the code which seems perplexing or hacked together when suddenly, without warning, he will change the window and flit off onto some completely different task. Then, just when I'm about to point out some obvious flaw, he'll start the debugger and tell me that he's "busy". Eventually, of course, he comes back to the same point I'd originally wanted to let him know about. If only he slowed down for a moment to talk to me.

And then there's his language and communication style. Leaving aside the continual shouting and swearing (well, when you make that many mistakes can you blame him?), whenever he does talk to me it tends to be in a challenging and angry way. Why can't he recognize that I have something to contribute? And even when he is in a good mood - finally having figured out some trivial bug - he says "high five, Nelson", even though he knows I have flippers. Talk about species-ist.

And, finally, since I'm here, I'd like to point out how much nagging and gnashing of teeth it has taken in order to get him to just let me write this little piece on his blog. You'd think I wanted to do a hit job on him or something.

About Nelson

Our guest blogger today was Nelson, a plush shark from Ikea, who sits next to me on a daily basis as my pair partner when I am working from home. He appears to have deep insights into my psyche as a pair partner, not to mention being able to provide truly honest feedback.

Friday, June 26, 2020

Configuring a Custom Domain for API Gateway


Yesterday I was trying to configure a custom domain for one of my sites working in API Gateway. At the end of the day, everything you would expect to have to be there was there, but I found the process very hard to comprehend. While I'm not going to directly recount my experiences - that would be too painful - this is hopefully a somewhat simplified, annotated guide to what I did.

Route 53

Most of the Amazon documentation about this will tell you how to do this, that and the other in Route 53 - Amazon's DNS service. I'm sure that it all works and although I think they say that you don't have to use Route 53 I went down a deep bunnyhole trying to establish the right records on Route 53 that appears to have been completely unnecessary (on a practical level).

It was, however, while I was doing this that I understood the vital piece of information that I was missing. But, no spoilers …

Assumptions

First off, I'm assuming that just by reading this you know what AWS is, have an account and basically know your way around the console. If you don't, then you probably don't want to do any of this …

I'm also assuming that you know a little bit about DNS and have some provider (whether AWS or otherwise) which registers and manages domains for you and will enable you to play with their DNS records, in particular, to create an Alias or CNAME record. If you don't know what I'm talking about, you probably don't want to do this; if it sounded plausible until you reached the CNAME bit, you probably want to look at the help pages or forums for your provider. This is often under the set of "Advanced" or "Do Not Touch" features.

Assuming you are still with me, I'm going to assume that you have configured an API Gateway already and that you know the (so-called 'custom') domain that you want to serve it on. I'm assuming that you have some request that "works" with the default domain. If not, I suggest you get that to work first.

Because API Gateway is secure, you need to provide a certificate through ACM (the Amazon Certificate Manager). This (obviously) needs to be a certificate which names the domain that you wish to use. This process is a little tricky in itself and I should have probably blogged about that when I did it a couple of weeks ago.

Finally (and possibly a bit more tricky), I'm going to assume that you have considered the ramifications of "edge-optimised" vs "regional" API gateways and that you have gone with regional. This is all a bit complicated (too complicated for me?) but basically if you have "edge-optimised" gateways, you will need to set cloudfront up across them in order to do this. I didn't try that, so the rest of this article may or may not be relevant. If you aren't sure, the "Endpoint type" column on the API Gateway screen says if an endpoint is Regional or Edge.

Creating a Custom Domain Name

The first step is to create a "Custom Domain Name" in API Gateway. This does not work in at all the way that I would expect or match any of my mental models, so I will try and explain it from my point of view. I would expect that the option would be called "bind to domain name" or "map domain name to stage" and would be an option on a specific stage of a specific gateway. The functionality is exactly what I would expect, but you reach it through a completely different route.

Note the ID of the gateway you want to bind (that's the string of 10 or so random alphanumerics, not the more user-friendly "Name") but do not click on it. Instead click on the sidebar menu item "Custom domain names".

This will take you to a simple screen which has a search box and a create button. Click the create button to open up a detail window.

In the "Domain name" box, put the domain name you want to bind.

In the "Configuration" section, you will (probably) want to select "Regional" and "TLS 1.2". You then need to choose the appropriate certificate from the ACM.

Add any tags you want and click "Create".

You could easily be forgiven for thinking that you are done at this point but you are not (I have to forgive you since this is where I went wrong).

You should now be on a screen with a label "Domain name details". It all looks pretty reasonable and like what you just specified. But scroll down. Keep on scrolling. Yes, there. The section that says "API mappings". This is what you need to configure in order to bind this domain name to your API Gateway.

Configure API Mappings

Click the button that says "Configure API Mappings". On the screen that appears, click "Add new mapping". You now need to select the correct gateway (API) by comparing the id to the one you remembered earlier (while the name is shown it is not guaranteed to be unique) and the correct stage. It is also possible to bind individual domains to sub-paths of API Gateway, although I personally don't have a use for that.

Click "Save". You should be returned to the "Domain name details" screen.

Configuring DNS

Internally, what has happened here is that API Gateway has cunningly created a new, forwarding web server with a new DNS name. If you look down the list of configuration options you will see an "API Gateway domain name" that looks like nothing you've seen before. All of mine start with "d-" and then have a 10-character name that is most assuredly not one I've seen before.

What's cunning about this server is that if you make an HTTP request to it telling it that you want it as the 'Host', it will return that certificate. If you tell it that the 'Host' name is your custom name, it will return that certificate (when we've finished, you can check that using curl -v, or otherwise).

So now all you need to do is to point your DNS of record at this DNS name. Exactly how you do that depends on your DNS provider. AWS will continually push you towards using Route 53, and it seems that there instructions in that regard are correct, but given that I don't use Route 53 on a daily basis I tried to avoid that and it all worked fine.

Simply set up a CNAME record (AWS, and possibly others, refer to this as an Alias). The value of the CNAME record needs to be the API Gateway domain name quoted above with a final trailing '.'. The purpose of this final dot is to indicate that it is an absolute DNS name. Depending on your DNS provider, it may or may not be necessary for you to actually enter it.

Testing

Given that you have a working API gateway, you should now be able to substitute the API Gateway domain name quoted above in place of the default domain name AND the stage (together with any prefix path you may have chosen to specify in your mapping). This should work immediately - even before you have configured your DNS.

I'm not really sure what to tell you if it doesn't - the whole reason for this blog is that I spent a good hour or more thrashing yesterday because I couldn't figure out the problem (which was that I hadn't set up a mapping from my custom domain name).

Assuming that works, try using your "custom" domain name in place of the API Gateway domain name.

There's a very good probability that this doesn't work. DNS takes a while to propagate for all kinds of reasons. If your DNS provider also offers hosting, try from one of those machines - they are "closer" to the source of the change and will see it sooner. Otherwise your best bet is to wait for a while.

You can use the tool nslookup (where available) to check whether your DNS is reporting the existence of the domain and you can use ping to see if it responds. Or you can just try using curl or your browser until it gives in. But seriously, it can take literal hours for DNS changes to propagate around the world so don't panic.

If you see that the DNS has propagated, and it still doesn't work, then you have probably configured the CNAME incorrectly. The most likely options are that you mistyped (or mis-copied) it and that you either didn't - or did, depending on your provider - provide the final dot.

Conclusion

Configuring a custom domain for AWS API Gateway is actually quite simple but, IMHO, the interface is poorly designed and then poorly explained. If you don't make any mistakes, the process is straightforward, but if you do any one of the steps wrong, you receive very little feedback about where the problem might be.