You want to see something really random? Infinite entropy returns

Remember a few posts ago where I talked about entropy, randomness, and how it was under-estimated as important for a high shared-user dynamic environment like public cloud? Some folks commented that the /dev/urandom was good enough. But, when there's a gadget on the line, why settle?

So I bought the "Infinite Noise TRNG". In fact, I bought two.

Interestingly, they came w/ 2 'user manuals', and one is colour, one black and white, both the same version. Interesting. Its hand-printed and folded, the devices are also hand-made. Remember when gadgets where hand-made? Pepperidge farms doesn't!

So, lets plug it in. Shows up as an '13-37' usb device (below).

This one is neat since it uses a 'whitening' algorithm. You see, in random generators, its possible that adjacent bits are correlated, so they run it through Keccak/SHA3 to smooth that out. We have a 'github repo' with the cad images and software, in case we want to build our own. Its worth checking out the link, he goes into details on the design and how it functions.

Lets try:

./infnoise | pv > /dev/random
448KiB 0:00:13 [39.0KiB/s] ==>

OK, seems to generate about 35-45KiB/s of random. Is that infinite? Well, if you run it long enough ūüôā

Now, I'm thinking of selling my random numbers to pay for this gadget. Maybe i'll set up a site you can buy my bits to use in your private keys, seems like a good idea eh? Why generate your own slow, possible not random, when you can buy it from a stranger and feel more secure?

[6388951.178077] usb 2-1.3.2.1.1.4: new full-speed USB device number 41 using ehci-pci
[6388951.403596] usb 2-1.3.2.1.1.4: New USB device found, idVendor=0403, idProduct=6015, bcdDevice=10.00
[6388951.403605] usb 2-1.3.2.1.1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[6388951.403611] usb 2-1.3.2.1.1.4: Product: Infinite Noise TRNG
[6388951.403615] usb 2-1.3.2.1.1.4: Manufacturer: 13-37.org
[6388951.403620] usb 2-1.3.2.1.1.4: SerialNumber: 1337-17C08314
[6388951.431663] usbcore: registered new interface driver ftdi_sio
[6388951.431688] usbserial: USB Serial support registered for FTDI USB Serial Device
[6388951.432016] ftdi_sio 2-1.3.2.1.1.4:1.0: FTDI USB Serial Device converter detected
[6388951.432058] usb 2-1.3.2.1.1.4: Detected FT-X
[6388951.432419] usb 2-1.3.2.1.1.4: FTDI USB Serial Device converter now attached to ttyUSB0

Using single-sign-on oauth2 across many sites in Kubernetes

You have a set of web resources (a kibana dashboard, a grafana dashboard, a few other misc ones). You are setting them all up with 'basic' auth because its simple, and secretly hoping no-one guesses "MyS3cret". You, my friend, are doing it wrong. Let me explain.

It turns out there is a protocol called 'oauth2'. You have probably seen this on many sites (e.g. 'sign in with Google'/'GitHub' etc). As a consumer, you should always do that when you can. Its much better to have one strong setup (your Google one) than many weak ones. When you 'sign in with Google' it doesn't actually share your password or profile, it just does authentication.

Now, how can we translate that into the misc set of web pages that we run in our system? This is super simple but it wasn't well documented and took me a bit to figure out how to do it well.

First, lets create a small yaml file, 'oauth2-values.yaml'. Fill it in like so. You will need to get the clientID and clientSecret. I am using Google (so https://console.cloud.google.com/apis/credentials), but there are other sites like GitHub, GitLab, etc you can use, and ample instructions online for this. In the Google case, allow redirect URI of 'oauth2.MYDOMAIN/oauth2/callback'

config:
  clientID: "xxxxx.apps.googleusercontent.com"
  clientSecret: "yyyyyyy"
  # Create a new cookieSecret with the following command
  # python -c 'import os,base64; print base64.b64encode(os.urandom(16))'
  cookieSecret: "zzzzz=="
  configFile: |-
    pass_basic_auth = false
    pass_access_token = true
    set_authorization_header = true
    pass_authorization_header = true

image:
  repository: "quay.io/pusher/oauth2_proxy"
  tag: "v3.1.0"
  pullPolicy: "IfNotPresent"

extraArgs:
  provider: "google"
  email-domain: "MYDOMAIN"
  cookie-domain: "MYDOMAIN"
  upstream: "file:///dev/null"
  http-address: "0.0.0.0:4180"

ingress:
  enabled: true
  annotations:
    ingress.kubernetes.io/ssl-redirect: 'true'
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    certmanager.k8s.io/cluster-issuer: letsencrypt
    nginx.ingress.kubernetes.io/proxy-body-size: 100m
    path: /
  hosts:
    - oauth2.MYDOMAIN
    - oauth2.MYDOMAIN
  tls:
    - secretName: oauth2-noc-tls
      hosts:
        - oauth2.MYDOMAIN
        - oauth2.MYDOMAIN

Now we are going to install an 'oauth2 proxy'. We will run *1* for our entire domain, and it will allow anyone with our domain to access.

helm install -f oauth2-values.yaml --name oauth2 --namespace oauth2 stable/oauth2-proxy

OK, now we just need to add 2 annotation lines to every ingress:

 nginx.ingress.kubernetes.io/auth-signin: https://oauth2.MYDOMAIN/oauth2/start?rd=$http_host$request_uri
 nginx.ingress.kubernetes.io/auth-url: https://oauth2.MYDOMAIN/oauth2/auth

And boom we are done. I'm assuming you are already using the excellent cert-manager so your site is TLS protected. Now you have strong sign-on, and, more usefuly, single-sign-on.

The key is that 'cookie-domain' above. It means we are using a single oauth2-proxy protecting the entire domain, and, once one site is signed in, all sites are signed in. So great!

Even better, if you use Multi-Factor-Authenticaation it fits in with it. Rarely type a password again, prevent needing passwords for new sites, and be more secure. What's not to love!

Project Block Heater: an update

The other day I wrote about adding a 'block heater' to the e-bike charging system. I'm please to report its working great!

If we look at it with a thermal imaging camera, we can see that the 'hot spot' is about 6C, outside the insulation. So it shouldn't be *colder* than that inside I guess.

This is with an outdoor temperature of about -10C.

The 'cold' spot is about 0C.

So I think its achieving the goal. The efficiency is not that great (charging off the built-in battery instead of an external pack), but I'm not concerned about long-distance driving, and I only have to charge about 1/week in the winter, so its not additional inconvenience.

IoT (h)army: hacking the smart switch

I purchased a pair of Teckin SP10 smartplugs. They were on sale for $8 each, they fluctuate up and down, are available in round, square, 1-pack,2-pack,4-pack, lots of options. I did this on the thesis that:

  1. They would be a disaster for security
  2. They would probably have an esp8266 in them for simple hacking

I'm pleased to report that both turned out to be true! Look @ the attached packet capture and you will see for yourself (dump.pcap). In a nutshell, they run a public MQTT server, all these devices contact it. You can use that bus to upgrade them (imagine me pushing new firmware to a widget in your house, and that widget can be a WiFi AP and Client for great man-in-the-middle attacks against your other devices). Its got a bit of control on it (there is some password which is defined by the mac of the device... can't imagine that number being guessable!). Hmm.

So let's dremel it open (side note: it seems you can just apply some heat and wiggling to break the ultra-sonic weld, but who has time for that!).

OK, we're in. That little module standing vertically is indeed an ESP8266-01. The serial ports is indeed exposed underneath, so programming it is simple.

But, turns out there is an even simpler way. Install this git repo and plug in the device, boom, running Tasmota. And now I can setup the device from a simple web interface, assign it to my private MQTT server, and from there my HomeAssistant. And now we are good to go, no Internet needed, security is much stronger.

This is actually quite a good device for the price. Since it has the esp8266 its both more and less hackable than the KanKun I did earlier. I kind of wish I had got the rectangular ones, but they were 'much more expensive' at ~$15/each. They also have a power-bar one with 4 outlets. Hmm, so many choices!

So, tl;dr: this device has decent hardware. The software and app worked very well (surprisingly, they are usually terrible). The security was a 2/5, I mean, its unlikely your house will be burned down, but, well, a moderately skilled hacker could use it to get access to traffic from other devices in your home. THe hackability is high, its now running secure on my TLS-based MQTT, on my private network, with my own HomeAssistant (meaning I don't worry about it being bricked if they give up like Lowes did).

So, I do recommend. Get your hack on.

Cloud anti-pattern dilemma: shared ‘state’

So i've been working with fluent-bit for cloud log processing. Got it working with Druid.io for some ludicrous scale etc.

Now the way fluent-bit works, it mounts the host '/var/log' inside itself, and does a 'tail -f' on all the files (it runs as a DaemonSet). To handle the case where you restart fluent-bit (perhaps for an upgrade, perhaps to change config) it can squirrel the state away into a database (sqllite), effectively remembering the offsets in each of the files. Sounds great right? Means that when fluent-bit is restarted you don't get duplicated messages.

Now, let's assume I place a 'readiness' check on it. I make a config change, and let the 'rollingUpdate' strategy do its work. Let's assume I also use the 'hash of file' strategy I mentioned earlier so that the config is 'hermetic'.

So what happens is the 'old' fluent-bit is running. A new one is started. Until its 'ready' Kubernetes doesn't kill the old one. They both process the same files for a bit, writing to this shared file. If the new one doesn't come online (e.g. it has an error in config) this is fine I guess. But when it does come online, they are both processing for some period of time. Hmm. Double logs? Corrupt sqllite? Hmm.

 

Top