~yrke/ssh-import/ssh-import-createFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/bin/sh
#
#    ssh-import-lp-id - authorize a user by fetching their key
#                       from Launchpad.net
#
#    Copyright (C) 2010 Canonical Ltd.
#
#    Author: Dustin Kirkland <kirkland@canonical.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, version 3 of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Abort on any unhandled error
set -e

error() {
	printf "ERROR: %s\n" "$@" 1>&2
	exit 1
}

warn() {
	printf "WARNING: %s\n" "$@" 1>&2
}

info() {
	printf "INFO: %s\n" "$@"
}

url_encode() {
	# from http://andy.wordpress.com/2008/09/17/urlencode-in-bash-with-perl/
	printf "%s" "$1" | perl -pe's/([^-_.~A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg'
}

validate_keys() {
	# Prune invalid characters and blank lines
	sed -i -e 's/[^a-zA-Z0-9@: .\/=+-]//g' -e '/^$/d' "$1"
	# Count lines
	lines=$(cat "$1" | wc -l)
	# Count valid keys
	keys=$(grep -c "^ssh-[dr]sa [a-zA-Z0-9: .\/=+-]\+= " "$1")
	# Validate counts match, and >0
	[ $lines -gt 0 ] && [ $keys -eq $lines ]
}

# The following URL *must* be an https address with a valid, signed certificate!!!
URL="https://launchpad.net/~%s/+sshkeys"

# Only support writing to this user's authorized_keys file
DIR="$HOME/.ssh"
FILE="$DIR"/authorized_keys

mkdir -m 0700 "$DIR" 2>/dev/null || true
[ -d "$DIR" ] || error "Cannot create directory [$DIR]"

rc=0
tmp=$(mktemp)
trap "rm -f $tmp" EXIT HUP INT QUIT TERM
for i in "$@"; do
	i=$(url_encode "$i") || error "Failed encoding [$i]"
	url=$(printf "$URL" "$i")
	if env -i wget --quiet -O- "$url" > "$tmp"; then
		echo >> "$tmp" # needed for wc
		if ! validate_keys "$tmp"; then
			warn "Invalid keys at [$url]"
			continue
		fi
		cat "$FILE" >> "$tmp" || error "Could not write to [$tmp]"
		# Prune duplicate entries
		sort -u "$tmp" > "$FILE" || error "Could not sort [$FILE]"
		info "Successfully authorized [$i]"
	else
		rc=$?
		warn "Failed to retrieve key for [$i] from [$url]"
	fi
done
exit $rc