Merge remote-tracking branch 'steven/issue/365'

This commit is contained in:
Nico Schottelius 2014-09-29 20:48:45 +02:00
commit 7fab50a82b
14 changed files with 300 additions and 38 deletions

View File

@ -46,13 +46,13 @@ tmpfile=\$(mktemp ${file}.cdist.XXXXXXXXXX)
if [ -f "$file" ]; then
cp -p "$file" "\$tmpfile"
fi
awk -v prefix="^$prefix\\\$" -v suffix="^$suffix\\\$" '
awk -v prefix="^$prefix\$" -v suffix="^$suffix\$" '
{
if (index(\$0,prefix)) {
if (match(\$0,prefix)) {
triggered=1
}
if (triggered) {
if (index(\$0,suffix)) {
if (match(\$0,suffix)) {
triggered=0
}
} else {

View File

@ -0,0 +1,26 @@
#!/bin/sh
#
# 2014 Steven Armstrong (steven-cdist at armstrong.cc)
#
# This file is part of cdist.
#
# cdist 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, either version 3 of the License, or
# (at your option) any later version.
#
# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
#
# extract the keytype and base64 encoded key ignoring any options and comment
type_and_key="$(cat "$__object/parameter/key" | tr ' ' '\n' | awk '/^(ssh|ecdsa)-[^ ]+/ { printf $1" "; getline; printf $1 }')"
file="$(cat $__object/parameter/file)"
# get any entries that match the type and key
grep ".*$type_and_key[ \n]" "$file" || true

View File

@ -0,0 +1,109 @@
#!/bin/sh
#
# 2014 Steven Armstrong (steven-cdist at armstrong.cc)
#
# This file is part of cdist.
#
# cdist 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, either version 3 of the License, or
# (at your option) any later version.
#
# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
#
set -u
remove_line() {
file="$1"
line="$2"
cat << DONE
tmpfile=\$(mktemp ${file}.cdist.XXXXXXXXXX)
# preserve ownership and permissions of existing file
if [ -f "$file" ]; then
cp -p "$file" "\$tmpfile"
fi
grep -v -F -x '$line' '$file' > \$tmpfile || true
mv -f "\$tmpfile" "$file"
DONE
}
add_line() {
file="$1"
line="$2"
# escape single quotes
line_sanitised=$(echo "$line" | sed -e "s/'/'\"'\"'/g")
printf '%s' "printf '%s\n' '$line_sanitised' >> $file"
}
file="$(cat "$__object/parameter/file")"
mkdir "$__object/files"
# Generate the entry as it should be
(
if [ -f "$__object/parameter/option" ]; then
# comma seperated list of options
options="$(cat "$__object/parameter/option" | tr '\n' ',')"
printf '%s ' "${options%*,}"
fi
if [ -f "$__object/parameter/comment" ]; then
# extract the keytype and base64 encoded key ignoring any options and comment
printf '%s ' "$(cat "$__object/parameter/key" | tr ' ' '\n' | awk '/^(ssh|ecdsa)-[^ ]+/ { printf $1" "; getline; printf $1 }')"
# override the comment with the one explicitly given
printf '%s' "$(cat "$__object/parameter/comment")"
else
printf '%s' "$(cat "$__object/parameter/key")"
fi
printf '\n'
) > "$__object/files/should"
# Remove conflicting entries if any
if [ -s "$__object/explorer/entry" ]; then
# Note that the files have to be sorted for comparison with `comm`.
sort "$__object/explorer/entry" > "$__object/files/is"
comm -13 "$__object/files/should" "$__object/files/is" | {
while read entry; do
remove_line "$file" "$entry"
done
}
fi
# Determine the current state
entry="$(cat "$__object/files/should")"
state_should="$(cat "$__object/parameter/state")"
num_existing_entries=$(grep -c -F -x "$entry" "$__object/explorer/entry")
if [ $num_existing_entries -eq 1 ]; then
state_is="present"
else
# Posix grep does not define the -m option, so we can not remove a single
# occurence of a string from a file in the `remove_line` function. Instead
# _all_ occurences are removed.
# By using `comm` to detect conflicting entries this could lead to the
# situation that the key we want to add is actually removed.
# To workaround this we must treat 0 or more then 1 existing entries to
# mean current state is 'absent'. By doing this, the key is readded
# again after cleaning up conflicting entries.
state_is="absent"
fi
# Manage the actual entry as it should be
if [ "$state_should" = "$state_is" ]; then
# Nothing to do
exit 0
fi
case "$state_should" in
present)
add_line "$file" "$entry"
;;
absent)
remove_line "$file" "$entry"
;;
esac

View File

@ -0,0 +1,67 @@
cdist-type__ssh_authorized_key(7)
=================================
Steven Armstrong <steven-cdist--@--armstrong.cc>
NAME
----
cdist-type__ssh_authorized_key - manage a single ssh authorized key entry
DESCRIPTION
-----------
Manage a single authorized key entry in an authorized_key file.
This type was created to be used by the __ssh_authorized_keys type.
REQUIRED PARAMETERS
-------------------
file::
the authorized_keys file to which the given key should be added
key::
a string containing the ssh keytype, base 64 encoded key and optional
trailing comment which shall be added to the given authorized_keys file.
OPTIONAL PARAMETERS
-------------------
comment::
explicit comment instead of the one which may be trailing the given key
option::
an option to set for this authorized_key entry.
Can be specified multiple times.
See sshd(8) for available options.
state::
if the given keys should be 'present' or 'absent', defaults to 'present'.
EXAMPLES
--------
--------------------------------------------------------------------------------
__ssh_authorized_key some-id \
--file "/home/user/.ssh/autorized_keys" \
--key "$(cat ~/.ssh/id_rsa.pub)"
__ssh_authorized_key some-id \
--file "/home/user/.ssh/autorized_keys" \
--key "$(cat ~/.ssh/id_rsa.pub)" \
--option 'command="/path/to/script"' \
--option 'environment="FOO=bar"' \
--comment 'one to rule them all'
--------------------------------------------------------------------------------
SEE ALSO
--------
- cdist-type(7)
- cdist__ssh_authorized_keys(7)
- sshd(8)
COPYING
-------
Copyright \(C) 2014 Steven Armstrong. Free use of this software is
granted under the terms of the GNU General Public License version 3 (GPLv3).

View File

@ -0,0 +1 @@
present

View File

@ -0,0 +1,2 @@
comment
state

View File

@ -0,0 +1 @@
option

View File

@ -0,0 +1,2 @@
file
key

View File

@ -0,0 +1,32 @@
#!/bin/sh
#
# 2014 Steven Armstrong (steven-cdist at armstrong.cc)
#
# This file is part of cdist.
#
# cdist 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, either version 3 of the License, or
# (at your option) any later version.
#
# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
#
# Find and sort any entries in the authorized_keys file that we care about
file="$($__type_explorer/file)"
(
while read key; do
# extract the keytype and base64 encoded key ignoring any options and comment
type_and_key="$(echo "$key" | tr ' ' '\n' | awk '/^(ssh|ecdsa)-[^ ]+/ { printf $1" "; getline; printf $1 }')"
# emit any entries that match the type and key
grep ".*$type_and_key[ \n]" "$file"
done < "$__object/parameter/key"
) | sort

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
# 2014 Steven Armstrong (steven-cdist at armstrong.cc)
#
# This file is part of cdist.
#
@ -18,6 +18,10 @@
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
#
owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
getent passwd "$owner" || true
if [ -f "$__object/parameter/file" ]; then
cat "$__object/parameter/file"
else
owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
home=$(getent passwd "$owner" | cut -d':' -f 6)
echo "$home/.ssh/authorized_keys"
fi

View File

@ -18,5 +18,6 @@
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
#
gid="$("$__type_explorer/passwd" | cut -d':' -f 4)"
owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
gid="$(getent passwd "$owner" | cut -d':' -f 4)"
getent group "$gid" || true

View File

@ -12,13 +12,13 @@ DESCRIPTION
-----------
Adds or removes ssh keys from a authorized_keys file.
This type uses the __ssh_dot_ssh type to the directory containing
the authorized_keys file.
You can disable this feature with the --noparent boolean parameter.
This type uses the __ssh_dot_ssh type to manage the directory containing
the authorized_keys file. You can disable this feature with the --noparent
boolean parameter.
The existence, ownership and permissions of the authorized_keys file itself are
also managed. This can be disabled with the --nofile boolean parameter. It is
then left to the user to ensure that the file exists and that ownership and
then left to the user to ensure that the file exists and that ownership and
permissions work with ssh.
@ -31,15 +31,23 @@ key::
OPTIONAL PARAMETERS
-------------------
comment::
explicit comment instead of the one which may be trailing the given key
file::
an alternative destination file, defaults to ~$owner/.ssh/authorized_keys
option::
an option to set for all created authorized_key entries.
Can be specified multiple times.
See sshd(8) for available options.
owner::
the user owning the authorized_keys file, defaults to object_id.
state::
if the given keys should be 'present' or 'absent', defaults to 'present'.
file::
an alternative destination file, defaults to ~$owner/.ssh/authorized_keys
BOOLEAN PARAMETERS
------------------
@ -64,13 +72,24 @@ __ssh_authorized_keys root \
__ssh_authorized_keys user-name \
--key "ssh-rsa AXYZAAB3NzaC1yc2..."
# allow key to login as user-name with options and expicit comment
__ssh_authorized_keys user-name \
--key "ssh-rsa AXYZAAB3NzaC1yc2..." \
--option no-agent-forwarding \
--option 'from="*.example.com"' \
--comment 'backup server'
# same as above, but with explicit owner and two keys
# note that the options are set for all given keys
__ssh_authorized_keys some-fancy-id \
--owner user-name \
--key "ssh-rsa AXYZAAB3NzaC1yc2..." \
--key "ssh-rsa AZXYAAB3NzaC1yc2..."
--key "ssh-rsa AZXYAAB3NzaC1yc2..." \
--option no-agent-forwarding \
--option 'from="*.example.com"' \
--comment 'backup server'
# same as above, but authorized_keys file in non standard location
# authorized_keys file in non standard location
__ssh_authorized_keys some-fancy-id \
--file /etc/ssh/keys/user-name/authorized_keys \
--owner user-name \
@ -89,6 +108,7 @@ __ssh_authorized_keys some-fancy-id \
SEE ALSO
--------
- cdist-type(7)
- sshd(8)
COPYING

View File

@ -21,16 +21,7 @@
owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
state="$(cat "$__object/parameter/state" 2>/dev/null)"
if [ -f "$__object/parameter/file" ]; then
file="$(cat "$__object/parameter/file")"
else
home="$(cut -d':' -f 6 "$__object/explorer/passwd")"
if [ -z "$home" ]; then
echo "Failed to get home directory from explorer." >&2
exit 1
fi
file="$home/.ssh/authorized_keys"
fi
file="$(cat "$__object/explorer/file")"
if [ ! -f "$__object/parameter/noparent" -o ! -f "$__object/parameter/nofile" ]; then
group="$(cut -d':' -f 1 "$__object/explorer/group")"
@ -50,6 +41,7 @@ if [ ! -f "$__object/parameter/noparent" -o ! -f "$__object/parameter/nofile" ];
--group "$group" \
--mode 0600 \
--state exists
export require="__file/$file"
fi
fi
@ -63,22 +55,25 @@ __block "$__object_name" \
--text - << DONE
remove legacy block
DONE
export require="__block/$__object_name"
_cksum() {
echo "$1" | cksum | cut -d' ' -f 1
}
while read key; do
cksum_key="$(_cksum "$key")"
line_id="${owner}-${cksum_key}"
set -- "$line_id"
type_and_key="$(echo "$key" | tr ' ' '\n' | awk '/^(ssh|ecdsa)-[^ ]+/ { printf $1" "; getline; printf $1 }')"
object_id="$(_cksum "$file")-$(_cksum "$type_and_key")"
set -- "$object_id"
set -- "$@" --file "$file"
set -- "$@" --regex ".*$key.*"
if [ "$state" = 'present' ]; then
set -- "$@" --line "$key"
fi
set -- "$@" --key "$key"
set -- "$@" --state "$state"
# Ensure __line does not read stdin
require="__block/$__object_name" __line "$@" < /dev/null
if [ -f "$__object/parameter/option" ]; then
set -- "$@" --option "$(cat "$__object/parameter/option")"
fi
if [ -f "$__object/parameter/comment" ]; then
set -- "$@" --comment "$(cat "$__object/parameter/comment")"
fi
# Ensure __ssh_authorized_key does not read stdin
__ssh_authorized_key "$@" < /dev/null
done < "$__object/parameter/key"

View File

@ -1,3 +1,5 @@
comment
file
option
owner
state
file