“If you can’t contact your loved ones, or government agencies and relief organizations can’t coordinate, you can’t get anything done. […] A communications system is only useful if you can connect to every other endpoint on the network. If you have power but no one else does, you have a well powered and expensive paperweight (assuming you still have paper). To that point, if your phone has power but the switching station does not, or the cell towers in half the city are down, you still aren’t able to communicate with anyone else.” —emtcharlie on ArsTechnica
A secret process that requires neither “concrete facts” nor “irrefutable evidence” …
“Instead of a watchlist limited to actual, known terrorists, the government has built a vast system based on the unproven and flawed premise that it can predict if a person will commit a terrorist act in the future,” says Hina Shamsi, the head of the ACLU’s National Security Project. “On that dangerous theory, the government is secretly blacklisting people as suspected terrorists and giving them the impossible task of proving themselves innocent of a threat they haven’t carried out.”
Yesterday, virtualenv-burrito 2.7 was released. There are two significant changes:
- All Python packages in the
.venvburritodirectory are now inside a versioned site-packages directory. For example, if you are running Python 2.7 during the install or upgrade, all packages will now live in
pipprogram is no longer user accessible (i.e., in the PATH). You could easily figure out where it’s been moved, but that’s discouraged (and unsupported).
These changes should help reduce some confusion and incompatibilities reported on the GitHub project.
To upgrade to the latest version, run:
If you are installing for the first time, run:
curl -sL https://raw.githubusercontent.com/brainsik/virtualenv-burrito/master/virtualenv-burrito.sh | $SHELL
After 14 years, it’s time for a new GPG key adhering to modern standards. You can find my transition statement here. The full-text follows.
-----BEGIN PGP SIGNED MESSAGE-----
Wed, 02 Jul 2014 20:54:03 -0700
I am transitioning GPG keys from an old 1024-bit DSA key to a new
4096-bit RSA key. The old key will continue to be valid for some time,
but I prefer all new correspondance to be encrypted with the new key.
All future signatures will be made with the new key.
This transition document is signed with both keys to validate the
If you have signed my old key, I would appreciate signatures on my new
key as well.
The old key:
pub 1024D/C771DF0B 2000-08-24
Key fingerprint = 6846 E600 739F 3DB5 DB02 B670 FDDE 4167 C771 DF0B
The new key:
pub 4096R/4FE98E13 2014-07-03
Key fingerprint = 5D80 FC62 9CEF 8FAE 737C DDED 19A1 D142 4FE9 8E13
To fetch my new key from a public key server:
gpg --keyserver pgp.mit.edu --recv-key 4FE98E13
If you've already validated my old key, you can validate the new key is
signed by my old key:
gpg --check-sigs 4FE98E13
If you are satisfied you've got the right key, I'd appreciate your
signature and upload:
gpg --sign-key 4FE98E13
gpg --keyserver pgp.mit.edu --send-key 4FE98E13
- -- jeremy avnet .:. @brainsik
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
-----END PGP SIGNATURE-----
x.pose is a wearable data-driven sculpture that exposes a person’s skin as a real-time reflection of the data that the wearer is producing.
She decided to aggregate this data collected on her everyday, building a mobile app to do the job using Node.js and PhoneGap. X.pose is the result of those data points, which have been translated into an abstract geometric representation using 3D printing software Rhino. Under the mesh is an array of displays that can change in opacity according to which location you are in (mapped out into the design) and how much data you are giving up at any given minute, in real time. They are made from electrochromic film, which becomes transparent when a current is passed through at a specific frequency. The app doing the data calculations is driving that current, with the panels controlled by an Arduino and linked to the app by Bluetooth. Give too much away and you will be bare for the world to see.
A simple way for Python cron tasks to exit if another process is currently running. Does not use a pidfile.
Update 2011-09-27: Turns out virtualenv and virtualenvwrapper support this out of the box. Most of what’s written below is horrifically complex compared to just using the
-p switch when you make your virtualenv. You simply need to do this:
$ mkvirtualenv -p /path/to/some/python coolname
That’ll create a new virtualenv called “coolname” that uses
/path/to/some/python for it’s Python interpreter. I’ve tested this with PyPy and it worked great.
A recent comment on the original Virtualenv Burrito announcement asked whether it was possible to create virtualenvs using different Python interpreters. The answer is a cautious: yes!
When virtualenv-burrito installs virtualenv, it prevents the
virtualenv command from tying itself to a specific interpreter. I wanted to be able to switch between Python versions, creating virtualenvs for each. I haven’t publicized this feature, nor made it easy to use since there may be hidden pitfalls. That said, I’ve not run into any problems.
The way it works is
mkvirtualenv uses the same interpreter invoked by the
python command to create the virtualenv. For example, normally when I run
mkvirtualenv I get a Python 2.7 environment. Using MacPorts, I can switch from my 2.7 default to 2.6 with:
port select --set python26
mkvirtualenv creates a 2.6 environment.
Regardless of what your current default Python interpreter is, once the virtualenv is made, it stays tied to the Python used during creation.
If you don’t have a nice way to switch your default Python, you can still hack it. The key is making the
python command use the interpreter you want.
You can easily create one yourself. Since xpi files are zip files, it’s something like:
mkdir tangerine; cd tangerine
- edit install.rdf so maxVersion is
zip -r9X ../elasticfox-forever.xpi .
Or cop out and click this: elasticfox-forever.xpi
Update 2011-09-23: Using
* for the maxVersion still didn’t cut it so I’ve updated the article and
xpi file to use a maxVersion of
This is part of the mini-series OpenSSH for Devs.
SSH agent forwarding let’s you lock down remote hosts while making them easier to access and use in automated ways. One co-worker succinctly describes agent forwarding as “the shit”.
Securely connect to a remote host from a remote host without a password.
laptop:~$ ssh -A host1.example.com Linux host1 2.6.35-25-server #44-Ubuntu SMP Fri Jan 21 19:09:14 UTC 2011 x86_64 GNU/Linux host1:~$ scp host2.example.com:some.config . some.config 100% 1612 1.6KB/s 00:00 host1:~$ logout Connection to host1.example.com closed.
The SSH agent has become so integrated into our local systems many people don’t realize it’s being used. Devs use it daily to avoid having to retype their SSH key1 password every time they connect to a remote host. The typical workflow is:
- Login to laptop
- SSH to a remote host
- Type SSH key password into popup
- No more password typing
The agent serves us by holding onto our private key and transparently authenticating to remote hosts when we connect instead of making us type a password.2
What is SSH agent forwarding?
Simply put, agent forwarding allows you to access a remote machine from a remote machine.
Let’s look at the scenario above: connect to host1 and download a file from host2. Without agent forwarding, you’re lucky if you just get to type your password again. If host2 has password authentication disabled or your account has no password set, there’s two options. Option 1: download the file from host2 to your local machine and then upload it to host1. Option 2: upload your SSH private key to host1 and authenticate to host2 using your key password. Compare these to agent forwarding where you run
scp and the file is downloaded without question.
If you’ve run into this problem more than a few times, learning about agent forwarding may feel like this:
Where can it take you?
The SSH agent provides a rare pairing of increased security and better user experience.
From a per-host perspective, you can disable password authentication on all your remote machines and rely on SSH keys for superior auth. Leaked passwords are no longer a vector for unauthorized access since you can’t login with them. Forget about generating random passwords for every user on every new server. If sudo access isn’t needed, don’t set a password at all. If sudo access is required you can get away with reusing passwords, keeping your devops team lean3.
From a network perspective, you ideally want your private servers only accessible via a bastion host or other intermediary. With agent forwarding, instead of this setup being a pain to get into, it’s a single command:
$ ssh -At public.example.com ssh private1.internal Linux private1 2.6.35-25-server #44-Ubuntu SMP Fri Jan 21 19:09:14 UTC 2011 x86_64 GNU/Linux private1:~$ logout Connection to private1.internal closed. Connection to public.example.com closed.
Agent forwarding can be turned on via the command-line by passing
-A or via your SSH config by setting
I’d be negligent if I didn’t recommend setting this only for hosts you trust. While it’s not possible to steal a private key through an agent, it’s trivial for a malicious root user to login to remote hosts with your public key.
Is there another way you use SSH agent forwarding? You should post a comment or send me a message.
- This article assumes you already use an SSH key to access remote hosts. If you don’t, send me a note. If I get enough questions about SSH keys, I’ll do a writeup on them. [↩]
- Some systems aren’t setup with an askpass program and the agent running in the background. In those cases, some devs will generate their SSH private key without a password to get the effect of not needing to type in their password for every SSH connection they make. Regardless of the security implications, that setup loses a beneficial feature of SSH: agent forwarding! [↩]
- Buzzwords aside, having to search for a password randomly generated 2 months ago before getting on with your task is sure way to wipe stored state and kill a task’s momentum. [↩]
This is part of the mini-series OpenSSH for Devs.
An SSH config let’s you set options you use often (e.g., the user to login as or the port to connect to) globally or per-host. It can save a lot of typing and helps make SSH Just Work.
Instead of typing:
ssh -p734 email@example.com
You can type:
By having this in your
Host sencha HostName sencha.example.com Port 734 User teamaster
What’s a per-user SSH config?
In your home is a
.ssh directory. This is where your SSH keypair and
known_hosts1 files are. This directory is not made of unicorns. Create a file named
config and your SSH tools2 will use it’s settings.
If your laptop username is different than the one on your remote hosts, create it with:
If you use a non-standard SSH port to avoid the bots, create it with:
Have different settings for different hosts? No problem. Just keep in mind the first match wins and put specific settings before generic ones:
# ancient box we never upgraded Host host1.example.com User oldusername # still on port 22 Host *.example.com Port 22022 ForwardAgent yes # defaults for all hosts Host * User bofh
It gets better
You’re probably familiar with the dance you do when connecting to a host for the first time:
$ ssh host1.example.com The authenticity of host 'host1.example.com (192.0.2.101)' can't be established. RSA key fingerprint is 39:9b:de:ad:9e:be:ef:95:ca:fe:1b:53:b0:00:00:b5. Are you sure you want to continue connecting (yes/no)?
It looks impressive, but it’s worthless. If you’re worried about man-in-the-middle attacks, there are much better things to do. Start by disabling password authentication3 and require people to have an SSH key on the server. Expecting people to check these hashes means you’ve already failed.
To get rid of the dance add something like:
Host *.compute-1.amazonaws.com StrictHostKeyChecking no
First time connections will give you a warning, but you’ll make it in.
You can create aliases4 by using Host to match a name and HostName to say where to connect.
Host web1 HostName ec2-192-0-2-42.compute-1.amazonaws.com
The advantages over modifying
/etc/hosts are you don’t need to be root and SSH will use the same host key for web1 and ec2-192-0-2-42.compute-1.amazonaws.com. The disadvantage is that only SSH tools see this. For example, your browser has no idea web1 is an alias for that EC2 host. Because of this, I sometimes create both the SSH alias and hosts entry for the best of both worlds.
There are a lot of options, but these are the ones I’ve seen used most:
- Host — Matches the hostname argument. Accepts patterns and causes options following it to apply only to hosts matching the pattern.
- User — Username to connect with.
- Port — Port to connect to.
- ForwardAgent — Set to
yesto turn on SSH agent forwarding.
- StrictHostKeyChecking — Set to
noto skip the “authenticity of host” dance.
- HostName — Server to connect to. Used to create an alias from Host to another remote server.
Do you have a favorite option not mentioned here? You should post a comment or send me a message.
known_hostsfile contains the keys for all the remote hosts you’ve connected to. The stored key is compared to the remote key when you connect to warn of a man-in-the-middle attack. [↩]
sshfs, well-written paramiko based Python tools, and probably more. [↩]
- In the server’s
PasswordAuthentication no. Contact me if you are interested in a post on securing the SSH server. [↩]
- I made this term up. There may be a better one. [↩]