First Purchase

December 21, 2019 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.

Mercury Transits the Sun 2019

November 11, 2019 8:22 am

The transit started before sunrise in California, but I thought I’d try to get a picture before heading to work.

My first shot overexposed the sun, but is kind of neat anyway. It’s wisteria below and our tree off to the right.

Pentax K-7, 200mm, f/32, 2s. (ND filters)

I took a few other shots and realized my lens has a number of spots that need to be cleaned. I thought they were mercury, but across several shots determined they were moving with the lens and not across the sun.

Looking closer I believe I did manage to get Mercury, smaller than my dirt spots. I believe the spot just above dead-center of the sun is Mercury:

Pentax K-7, 200mm, f/32, 1/25s. (ND filters)