lifecycle {
ignore_changes = [
image_uri
]
}
Some of the interesting things I did, learned, or found in the (week before the) past week. This time it’s not very complete and comes a bit later - the reason is simple:
We’ve been witnessess of terrible aggresivity with far-reaching consequences. As many others, I’m horrified. The people of Ukraine need all the support we can give them.
We should analyze the structure of the domain. An important structural feature is alternative.
This method focuses on substance (alternative) first and style (which representation) second.
It is superior to design rules of thumb (“always/never use an interface for this or that”) or principles such as Open/Closed which focus exclusively on style.
Programming is like designing a door. We can’t say “program to interfaces” (Open/Closed principle).
Those are rules of thumb with the same problems as “make the doors symmetrical." or "design the door to require less hardware"
⇒ they follow conflicting paths: Which one is correct?
We must understand the purpose (of the door, for instance)
Some doors welcome strangers off the street (customers). Others allow easy escape but no entry (fire escapes). Yet others signal an area private to some small group of people (employees only!).
⇒ then consider the purpose and systemic context (cost, material availability, culture, etc.) to decide
Learn Reagent is a nice video course by Jacek Schae. It teaches you how to use Reagent to implement a single-page application to show gigs & orders.
While I used Reagent a couple of times, frontend programming is my weak point so I welcome this refreshing tutorial and I’m slowly going through it.
Last week, I had a lot of "fun" with CloudFront and mysterious timeouts that some people were getting when accessing our website. The issues were intermittent and I couldn’t reproduce it myself which made it hard to debug.
After a lot of pain and suffering, inspecting CloudFront logs and searching on the Internet, I finally find what was the problem. Interested in knowing more? Read CloudFront and mysterious OriginCommError
Terraform lifecycle policy - lifecycle
+ ignore_changes
can typically be used to ignore changes in some attributes.
Unfortunately, this
doesn’t work for modules
and cannot be applied conditionally/dynamically.
Wisfull thinking:
lifecycle {
ignore_changes = [
image_uri
]
}
This is worth a separate blog post so I’m leaving out the details for later
I finished chapter 5 which contains some nice refactorings - factoring out calculations out of actions.
Here’s a good example of a function with too many responsibilities (see the comment in the code). Can you spot which part has which responsibility?
// this function is doing a lot of things...
// 1. It operates on 'buy buttons'
// 2. It does cart & item operations - adding new item, checking free shipping
// 3. It manipulates the DOM: hide/show free shipping icons
function update_shipping_icons(cart, buttons) {
buttons.forEach(button => {
const {item: {price, name}} = button;
// this is the update: call make_cart_item
const new_cart = add_item(cart, make_cart_item(name, price));
if (gets_free_shipping(new_cart)) {
button.show_free_shipping_icon();
} else {
button.hide_free_shipping_icon();
}
});
}
I was plodding through the chapter 4 examples and implementing all the examples.
There’s a ton of useful stuff so it’s hard to summarize. But it’s all about session cookies and how they can be used for authentication. It touches things like SOP (Same Origin Policy), Session fixation attacks, Timing attacks, CSRF and double-submit cookies.
Double-submit cookies cookies are an interesting technique
for protecting your API (used by a JavaScript client)
leveraging cookies for authentication against CSRF.
Using this technique, there’s a anti-CSRF token derived from the session token,
preferably with a cryptographic hash function like SHA-256.
This token is then read by JavaScript and stored in a cookie on the client.
When the client (JavaScript) calls the API, it reads the cookie and passes its value
in the X-CSRF-Token
header which is then read and verified by the server.
Some sample code:
// the provided token is expected to be Base64-encoded version of SHA256 of session token
var providedToken = Base64Url.decode(request.headers("X-CSRF-Token"));
var computedToken = sha256(session.id());
if (!MessageDigest.isEqual(providedToken, computedToken)) { (1)
// somebody is trying to forge the token?
return Optional.empty();
}
// here's the code to compute sha256
String randomToken = ...
MessageDigest.getInstance("sha256").digest(randomToken.getBytes(StandardCharsets.UTF_8));
Using MessageDigest.isEqual instead of ordinary string equality we mitigate timing attacks.
I read chapter 5 (Business Metrics) and chapter 6 (Frontend Monitoring).
Both of them are tremdendously useful and focus on monitoring real business KPIs and user experience rather than traditional monitoring which focuses on servers and low-level machine metrics.
Two basic approaches:
Real User Monitoring (RUM) - preferable
Synthetic monitoring - tools like WebpageTest.org
Navigation Timing API - You can compute page load times:
total page load time = domComplete - navigationStart
user-perceived page load time = domComplete - navigationStart
I was trying to move a bunch of widgets on a Cloudwatch dashboard.
The problem was how to quickly add a fixed number to their y
coordinate.
A dashboard source is a JSON like this:
{
"widgets": [
{
"height": 2,
"width": 19,
"y": 0,
"x": 0,
...
And so it continues with many other widgets. I basically wanted to add number 10 to all those y coordinates.
For that, I found a very convenient emacs function query-replace-regex
- the sequence goes like this:
C-M-%
"y": \([0-9]+\)
RET
"y": \,(+ 10 \#1)
This searches for all lines matching "y"
followed by a number, capturing the value of the number with parentheses (a capturing group).
Then using \,
to provide arbitrary elisp expression and using \#1
to reference the first matching group
and interpreting it as a number.
See section Regexp Replacement of the Emacs Manual for more details.
I’ve been using 1Password for a long time, but I’ve never used their CLI. This week, I was trying to fetch the one-time authentication code for my AWS account to produce a session token. So I installed 1Password CLI.
Getting the code is then easy:
eval $(op signin my);
op get totp 'AWS console login'; (1)
'AWS console login' is the name/title of the login item in 1Password
A quick recap of some of the links mentioned in this post: