Thanksgiving 2019

December 21, 2019 11:15 am

We drove out to Utah to spend Thanksgiving with Erin’s family this year. We arrived on Sunday night and stayed until Saturday morning.

On Tuesday we went to the Thanksgiving Point Natural History Museum.

Thursday was a busy day of baking 131 rolls, both baguette-style and soft-dinner-style, making cream puffs, eating food, and the girls playing in the snow.

I needed to make a lot of rolls, but the standard mixer bowl wasn’t big enough. Turns out it works just fine to use another bowl of similar height and hold it yourself (and spin it around to help the mixing).

A whole gaggle of girls who had a ton of fun running around all week. Heather looks twice their size. I think it’s mostly because she’s all stretched out, but she’s also tall.

On Friday we visited some friends that live in Lehi. Then we had to shovel 4 inches of snow off Erin’s driveway to park the van. I don’t miss shoveling snow!

We packed up Friday night planning for an early departure, but had to shovel more snow off the driveway in the morning in order to safely get to the street, which was not plowed.

We eventually got moving though had to head South due to the storm system coming through which also made I-80 across Donner Pass really dangerous with dozens of accidents and disabled vehicles. Shortly after we left, apparently a propane tanker overturned on I-15 around Lehi and had I-15 closed in both directions all day, but we avoided that.

The unicorn headband is also headphones!

Once we got out the bottom of Utah we had gotten ahead of the storm and the weather at least cleared up even if traffic didn’t. We had hoped to get home in one day, which should have been possible with ~15 hours of traveling. Any dream of that happening though was shattered by the CA agricultural checkpoint which had traffic completely stopped for 27 miles.

We, and much of the rest of the highway, tried to stop for some food at the only town in existence for that stretch of road, Primm, just inside the Nevada border. We headed for a Taco Bell that Google thought existed, but did not. So we ended up at the busiest McDonald’s I’ve ever seen. We grabbed some food to go and got back in the traffic jam. By the time we got up to the checkpoint they were closed for the day and you could just drive through, but it takes a long time for 27 miles of stopped traffic to start moving again.

We made it to Barstow and stayed the night there. When we got up in the morning, the checkpoint still had 5 miles of stopped traffic (according to Google Maps). We got moving again and made it back home after another 7 hours of driving. Patches of driving rain and poor visibility, heavy traffic, and incredibly unsafe drivers (gee, it’s pouring rain, I can’t see more than 2 cars in front of me, but this guy left 20 feet of space in front of him, I’m going to take it!). It was not a lot of fun.

At least a Raspberry Pi loaded with TV shows and Movies kept the girls entertained.

First Purchase

10:07 am

At Halloween Grandma sent Heather and Corinne each a $1.10 to buy something from the dollar store. Back in November we went over to the “99¢ Only Store” which is really the “99¢ and up store”, but still has lots of 99¢ stuff. Heather and Corinne perused the aisles and then got to line up for their first store purchase.

Their understanding of how cash works is pretty weak since they never see it used. But with some prompting they each got through their transaction and are now the proud owners of these balls.

The Weather Station Lives Again

9:56 am

Over Thanksgiving a big storm blew through. We were out of town but I noted that my weather station reported a bunch of rain and then stopped transmitting. When we got home, I climbed up on the roof to investigate. I replaced the batteries (which hadn’t been changed in 2.5 years) and the station started reporting again.

This guy hung out with me for a bit while I was replacing batteries and cleaning sensors:

However, next time it rained it stopped again. Then it dried up and started again. Then rained again, etc. So it was dying when wet. And the humidity reading was stuck at 99%. I tried all the troubleshooting procedures I could find but was unable to restore functionality.

So, I bought a new sensor array and installed it today. The new array is an upgraded design. It’s easier to take apart and clean. They reduced the power requirements so it runs on 2 AA batteries instead of 3. And they added a super capacitor to the solar array so it can run off sunlight without pushing any current through the batteries (the previous version pushed the solar current through the batteries to both stabilize the power and trickle-charge the batteries).

So the my weather station is up and running again!

http://weather.serindu.com

First LED bulb failure

December 1, 2019 4:38 pm

We had an LED bulb fail for the first time. We put 5 Philips bulbs in our over-the-table chandelier when we moved into our house. A week or two ago one of the bulbs began shutting off after being on for ~30 minutes and it would then cycle on and off. That suggests to me an overheating problem. Now the bulb doesn’t light at all.

It lasted almost exactly 7 years and the other 4 bulbs in the fixture are still going just fine. I expected it to last longer and maybe it was flawed (we’ll see what happens with the other 4 bulbs). But 7 years is pretty good since it paid for itself in reduced electrical usage after about 1.5 years.

Django in FIPS mode

November 12, 2019 11:28 am

Django today (2.2+) still uses the MD5 hash function to generate cache keys and database object names. They’re not security related, so that’s fine. But if you’re running on a FIPS-compliant system then MD5 is disabled and Django blows up.

Red Hat Enterprise Linux provides a patched version of Python which allows you to pass a keyword argument to md5, “usedforsecurity”. If you set that to False the system will allow your call to MD5 to go through.

This extension is being merged upstream so everyone will have it, it’s targeted for Python 3.9: https://github.com/python/cpython/pull/16044. Once that work is complete, Django will update their code to pass the parameter natively and none of this will be necessary: https://code.djangoproject.com/ticket/28401. But until then….

So, RHEL has a supported method to tell the system that you’re using MD5 for non-security purposes; now we need to make Django pass that parameter without forking Django. We can do this with monkey patching.

I would prefer not to use a global monkey patch. It would work, but then anything using MD5 would be allowed instead of only the things I’ve verified are non-security related. This could be a compliance issue.

Implementing a localized monkey patch isn’t too much harder once you know a little Python voodoo. We load a copy of the hashlib module and then monkey-patch the copy to pass the “usedforsecurity” parameter. Then we inject the monkey-patched version into any modules we need to replace their normal hashlib object with our copy.

import hashlib
import importlib

def _non_security_md5(*args, **kwargs):
    kwargs['usedforsecurity'] = False
    return hashlib.md5(*args, **kwargs)

def monkey_patch_md5(modules_to_patch):
    """Monkey-patch calls to MD5 that aren't used for security purposes.

    Sets RHEL's custom flag `usedforsecurity` to False allowing MD5 in FIPS mode.
    `modules_to_patch` must be an iterable of module names (strings).
    Modules must use `import hashlib` and not `from hashlib import md5`.
    """
    # Manually load a module as a unique instance
    # https://stackoverflow.com/questions/11170949/how-to-make-a-copy-of-a-python-module-at-runtime
    HASHLIB_SPEC = importlib.util.find_spec('hashlib')
    patched_hashlib = importlib.util.module_from_spec(HASHLIB_SPEC)
    HASHLIB_SPEC.loader.exec_module(patched_hashlib)

    patched_hashlib.md5 = _non_security_md5  # Monkey patch MD5

    # Inject our patched_hashlib for all requested modules
    for module_name in modules_to_patch:
        module = importlib.import_module(module_name)
        module.hashlib = patched_hashlib

When our application starts up it detects FIPS mode and runs the monkey patch:

modules_to_patch = [
    'django.contrib.staticfiles.storage',
    'django.core.cache.backends.filebased',
    'django.core.cache.utils',
    'django.db.backends.utils',
    # 'django.db.backends.sqlite3.base',  -- Only if system has sqlite installed
    'django.utils.cache',
]
try:
    import hashlib
    hashlib.md5()
except ValueError:
    monkey_patch_md5(modules_to_patch)

This lists the specific modules in Django that use MD5 for non-security purposes (determined by searching through the codebase and reading the code). Each module has its version of hashlib replaced with the monkey-patched version and Django is none the wiser.