pax_global_header 0000666 0000000 0000000 00000000064 12366007143 0014514 g ustar 00root root 0000000 0000000 52 comment=cd23df6b7de6e0f01a2697cc1b6725ada05fb349 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/ 0000775 0000000 0000000 00000000000 12366007143 0027342 5 ustar 00root root 0000000 0000000 .gitignore 0000664 0000000 0000000 00000000067 12366007143 0031256 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 *.py[coa] /django_sshkey.egg-info /testproject/test.db LICENSE 0000664 0000000 0000000 00000002726 12366007143 0030277 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 Copyright (c) 2014, Clemson University All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the {organization} nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MANIFEST.in 0000664 0000000 0000000 00000000533 12366007143 0031022 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 include LICENSE include README.rst include README.upgrading.rst include lookup.py include lookup.sh include django-sshkey-lookup include django-sshkey-lookup-all include django-sshkey-lookup-by-username include django-sshkey-lookup-by-fingerprint recursive-include django_sshkey/migrations *.py recursive-include django_sshkey/templates.example * README 0000777 0000000 0000000 00000000000 12366007143 0031625 2README.rst ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 README.rst 0000664 0000000 0000000 00000021253 12366007143 0030755 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 ============= django-sshkey ============= django-sshkey allows you to associate multiple SSH public keys with Django user accounts. It provides views to list, add, edit, and delete keys, each of which is intended for end-user consumption. It also provides a lookup view and corresponding lookup commands that are suitable for use with the ``AuthorizedKeysCommand`` feature in OpenSSH_ 6.2 and above. The Django app ============== To use django-sshkey in your Django project, simply add ``django_sshkey`` to ``INSTALLED_APPS`` in ``settings.py``, map the URLs into your project, and provide templates for the views (example templates are provided in the source). In order to associate an incoming public key with a user you must define ``SSHKEY_AUTHORIZED_KEYS_OPTIONS`` in your project's ``settings.py``. This should be a string containing options accepted by sshd, with ``{username}`` being replaced with the username of the user associated with the incoming public key. django-sshkey can also help you keep track of when a key was last used. ``SSHKEY_AUTHORIZED_KEYS_OPTIONS`` also replaces ``{key_id}`` with the key's id. The command that is run can then notify django-sshkey that the key was used by issuing a HTTP POST to the lookup URL, placing the key_id in the request body. For instance:: SSHKEY_AUTHORIZED_KEYS_OPTIONS = 'command="my-command {username} {key_id}",no-pty' in settings.py will cause keys produced by the below commands to look similar to:: command="my-command fred 15",no-pty ssh-rsa AAAAB3NzaC1yc2E... sshd would then verify the key is correct and run ``my-command``. ``my-command`` would then know that this is fred and that he is using key 15, and could tell django-sshkey to update the last_used field of that key by running the equivalent of this command:: curl -d 15 http://localhost:8000/sshkey/lookup Your URL may vary depending upon your configuration. URL Configuration ----------------- This text assumes that your project's ``urls.py`` maps ``django_sshkey.urls`` into the URL namespace as follows:: import django_sshkey.urls urlpatterns = patterns('', ... url('^sshkey/', include(django_sshkey.urls)), ... ) You will need to adjust your URLs in the examples below if you use a different mapping. .. WARNING:: The ``/sshkey/lookup`` URL can expose all public keys that have been uploaded to your site. Although they are public keys, it is probably a good idea to limit what systems can access this URL via your web server's configuration. Most of the lookup methods below require access to this URL, and only the systems that need to run the lookup commands should have access to it. Settings -------- ``SSHKEY_AUTHORIZED_KEYS_OPTIONS`` String, optional. Defines the SSH options that will be prepended to each public key. ``{username}`` will be replaced by the username; ``{key_id}`` will be replaced by the key's id. New in version 2.3. ``SSHKEY_ALLOW_EDIT`` Boolean, defaults to ``False``. Whether or not editing keys is allowed. Note that no email will be sent in any case when a key is edited, hence the reason that editing keys is disabled by default. New in version 2.3. ``SSHKEY_EMAIL_ADD_KEY`` Boolean, defaults to ``True``. Whether or not an email should be sent to the user when a new key is added to their account. New in version 2.3. ``SSHKEY_EMAIL_ADD_KEY_SUBJECT`` String, defaults to ``"A new key was added to your account"``. The subject of the email that gets sent out when a new key is added. New in version 2.3. ``SSHKEY_FROM_EMAIL`` String, defaults to ``DEFAULT_FROM_EMAIL``. New in version 2.3. ``SSHKEY_SEND_HTML_EMAIL`` Boolean, defaults to ``False``. Whether or not multipart HTML emails should be sent. New in version 2.3. Templates --------- Example templates are available in the ``templates.example`` directory. ``sshkey/userkey_list.html`` Used when listing a user's keys. ``sshkey/userkey_detail.html`` Used when adding or editing a user's keys. ``sshkey/add_key.txt`` The plain text body of the email sent when a new key is added. New in version 2.3. ``sshkey/add_key.html`` The HTML body of the email sent when a new key is added. New in version 2.3. Tying OpenSSH to django-sshkey ============================== There are multiple methods of connecting OpenSSH to django-sshkey. All of the methods listed here require the use of the ``AuthorizedKeysCommand`` directive in ``sshd_config`` present in OpenSSH 6.2 and above. Please note that the command that is referenced by this directive and its ancestor directories must be owned by root and writable only by owner. Unless otherwise stated, all of the methods below use the ``SSHKEY_LOOKUP_URL`` environment variable to determine the URL of the ``/sshkey/lookup`` URL. If this environment variable is not defined then it will default to ``http://localhost:8000/sshkey/lookup``. If this environment variable is defined in the sshd process then it will be inherited by the ``AuthorizedKeysCommand``. Additionally, all of the methods below use either ``curl`` (preferred) or ``wget``. Some commands also use ``ssh-keygen``. These commands must be present in ``PATH``. If you would prefer not to use these external commands then there are variants of the lookup commands implemented purely in Python. However, they are *much* slower. To use the variants, replace ``lookup`` with ``pylookup``. For example, use ``django-sshkey-pylookup-all`` instead of ``django-sshkey-lookup-all``. Using ``django-sshkey-lookup`` ------------------------------ :: Usage: django-sshkey-lookup -a URL django-sshkey-lookup -u URL USERNAME django-sshkey-lookup -f URL FINGERPRINT django-sshkey-lookup URL [USERNAME] This program has different modes of operation: ``-a`` Print all public keys. ``-u`` Print all public keys owned by the specified user. ``-f`` Print all public keys matching the specified fingerprint. Default Compatibility mode. If the username parameter is given then print all public keys owned by the specified user; otherwise perform the same functionality as ``django-sshkey-lookup-by-fingerprint`` (see below). All modes expect that the lookup URL be specified as the first non-option parameter. This command is compatible with the old script ``lookup.sh`` but was renamed to have a less ambiguous name when installed system-wide. A symlink is left in its place for backwards compatibility. Using ``django-sshkey-lookup-all`` ---------------------------------- ``Usage: django-sshkey-lookup-all`` This program prints all SSH public keys that are defined on your site. sshd will have to scan through all of them to find the first match, so with many keys this method will be slow. However, it does not require a patched OpenSSH server. This program: * can be used directly with ``AuthorizedKeysCommand`` (the username parameter is ignored). * does not require a patched OpenSSH server. * does not scale well to a large number of user keys. Using ``django-sshkey-lookup-by-username`` ------------------------------------------ ``Usage: django-sshkey-lookup-by-username USERNAME`` This program prints all SSH public keys that are associated with the specified user. This program: * can be used directly with ``AuthorizedKeysCommand``. * does not require a patched OpenSSH server. * is ideal if each Django user corresponds to a system user account. Using ``django-sshkey-lookup-by-fingerprint`` --------------------------------------------- ``Usage: django-sshkey-lookup-by-fingerprint`` This program prints all SSH public keys that match the given fingerprint. The fingerprint is determined by the first of the following that is found: 1. The ``SSH_KEY_FINGERPRINT`` environment variable, which should contain the MD5 fingerprint of the key (this is the second field generated by ``ssh-keygen -l``). 2. The ``SSH_KEY`` environment variable, which should contain the key in standard openssh format (the same format as ``~/.ssh/id_rsa.pub``), is sent to ``ssh-keygen -l`` to determine the fingerprint. 3. The key in standard openssh format is read from standard input and is sent to ``ssh-keygen -l`` to determine the fingerprint. This program: * can be used directly with ``AuthorizedKeysCommand`` (the username parameter is ignored). * requires a patched OpenSSH server; compatible patches can be found at one of the following locations: - openssh-akcenv_ (this is the preferred patch) - openssh-stdinkey_ * is ideal if you want all Django users to access SSH via a shared system user account and be identified by their SSH public key. .. _OpenSSH: http://www.openssh.com/ .. _openssh-akcenv: https://github.com/ScottDuckworth/openssh-akcenv .. _openssh-stdinkey: https://github.com/ScottDuckworth/openssh-stdinkey README.upgrading.rst 0000664 0000000 0000000 00000005126 12366007143 0032735 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 Upgrading and Downgrading ========================= django-sshkey is equipped with South_ migrations. This makes changes to the database schema in upgrades or downgrades a simple process. Migrations will only be present on minor version changes. To use South migrations, you must have the south app in your project's ``INSTALLED_APPS``. The following table maps django-sshkey version to migration labels: +---------+---------------+-------+------------------------------------------+ | Version | App Name | Label | Notes | +=========+===============+=======+==========================================+ | 1.0 | sshkey | 0001 | Migrations were not present in 1.0.x | +---------+---------------+-------+------------------------------------------+ | 1.1 | sshkey | 0002 | | +---------+---------------+-------+------------------------------------------+ | 2.0-2.2 | django_sshkey | 0001 | See Upgrading from 1.1.x to 2.x below | +---------+---------------+-------+------------------------------------------+ | 2.3 | django_sshkey | 0002 | | +---------+---------------+-------+------------------------------------------+ To upgrade, install the new version of django-sshkey and then migrate your project to its corresponding label from the table above using the following command:: python manage.py migrate APP_NAME LABEL To downgrade, perform the migration down to the label of the desired version before installing the older django-sshkey. Upgrading from 1.1.x to 2.x --------------------------- django-sshkey 2.x renames the sshkey app to django_sshkey. However, the database table names are not changed. To upgrade, all references to the sshkey module must be changed to django_sshkey. This includes all instances of ``import sshkey`` or ``from sshkey import ...`` and all references to sshkey in URL patterns, views, or templates, as well as updating ``INSTALLED_APPS`` in ``settings.py``. Once you have made those changes you will need to fake the initial migration for django_sshkey:: python manage.py migrate --fake django_sshkey 0001_initial This completes the upgrade process. The only thing that remains is the two existing migration records in the ``south_migrationhistory`` table from the now nonexistent sshkey app. These records do not cause any problems, but they can be removed at your discrection using the following SQL statement on your database:: DELETE FROM south_migrationhistory WHERE app_name="sshkey"; .. _South: http://south.aeracode.org/ RELEASE-NOTES.rst 0000664 0000000 0000000 00000003761 12366007143 0031772 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 =============================== Release Notes for django-sshkey =============================== 2.3.1 (2014-07-29) ------------------ * Add support for Django 1.6 * Add missing dependency for pyasn1 (introduced in 2.3.0) * Add release notes (this file) 2.3.0 (2014-07-07) ------------------ * Schema change (label 0002): add last_used timestamp * Provide {key_id} in template for SSHKEY_AUTHORIZED_KEYS_OPTIONS so that last_used timestamp may be updated * Add support for RFC4716 and PEM public keys for import and export * django-sshkey-lookup can now use any method to lookup keys: all, by username, by fingerprint, or compatibility mode * Add ability to send email to user when a key is added to their account * Add the following settings * SSHKEY_ALLOW_EDIT * SSHKEY_EMAIL_ADD_KEY * SSHKEY_EMAIL_ADD_KEY_SUBJECT * SSHKEY_FROM_EMAIL * SSHKEY_SEND_HTML_EMAIL * Remove setting SSHKEY_AUTHORIZED_KEYS_COMMAND (deprecated since 1.0.0) * Fix up example templates 2.2.0 (2014-03-26) ------------------ * Change license to BSD 3-clause * Basic compatability with Django > 1.3 * OpenSSH patch removed, refer to their separate projects * Remove deprecated sshkey_authorized_keys_command management command * Add the following lookup commands * django-sshkey-lookup-all * django-sshkey-lookup-by-fingerprint * django-sshkey-lookup-by-username 2.1.0 (2014-01-22) ------------------ * lookup.sh and lookup.py deprecated in favor of django-sshkey-lookup and django-sshkey-pylookup, respectively * Install scripts using setuptools 2.0.1 (2013-09-30) ------------------ * Add missing __init__.py 2.0.0 (2013-09-30) ------------------ * Rename sshkey to django_sshkey 1.1.1 (2013-09-03) ------------------ * Include management and migrations directories in setuptools 1.1.0 (2013-08-28) ------------------ * Schema change (label 0001): add created and last_modified timestamps 1.0.1 (2013-08-28) ------------------ * Add copyright info 1.0.0 (2013-08-28) ------------------ First release django-sshkey-lookup 0000775 0000000 0000000 00000005051 12366007143 0033267 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 #!/bin/sh # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. usage() { echo "Usage: $0 -a URL" echo " $0 -u URL USERNAME" echo " $0 -f URL FINGERPRINT" echo " $0 URL [USERNAME]" } mode=x while getopts ':hafu' opt; do case $opt in h) usage exit 0 ;; a) mode=a ;; f) mode=f ;; u) mode=u ;; [?]) exec 1>&2 echo "Invalid option: -$OPTARG" usage exit 1 ;; esac done shift $(($OPTIND-1)) if [ $# -eq 0 ]; then usage >&2 exit 1 fi url="$1" case $mode in a) query= ;; f) if [ $# -lt 2 ]; then usage >&2 exit 1 fi query="fingerprint=$2" ;; u) if [ $# -lt 2 ]; then usage >&2 exit 1 fi query="username=$2" ;; x) if [ $# -eq 1 ]; then SSHKEY_LOOKUP_URL="${url}" export SSHKEY_LOOKUP_URL exec `dirname $0`/django-sshkey-lookup-by-fingerprint else query="username=$2" fi ;; esac if type curl >/dev/null 2>&1; then exec curl -s -G "${url}" --data-urlencode "${query}" else exec wget -q -O - "${url}?${query}" fi django-sshkey-lookup-all 0000775 0000000 0000000 00000003256 12366007143 0034042 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 #!/bin/sh # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. url="${SSHKEY_LOOKUP_URL:-http://localhost:8000/sshkey/lookup}" if type curl >/dev/null 2>&1; then exec curl -s "$url" else exec wget -q -O - "$url" fi django-sshkey-lookup-by-fingerprint 0000775 0000000 0000000 00000004141 12366007143 0036223 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 #!/bin/bash # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. url="${SSHKEY_LOOKUP_URL:-http://localhost:8000/sshkey/lookup}" if [ "x$SSH_KEY_FINGERPRINT" != "x" ]; then fingerprint="$SSH_KEY_FINGERPRINT" else if [ "x$SSH_KEY" == "x" ] && ! read SSH_KEY; then echo "Error: cannot retrieve fingerprint from environment or stdin" >&2 exit 1 fi info="$(ssh-keygen -lf /dev/stdin <<< "$SSH_KEY")" if [ $? -ne 0 ]; then echo "Error: $info" >&2 exit 1 fi info=($info) fingerprint="${info[1]}" fi if type curl >/dev/null 2>&1; then exec curl -s -G "$url" --data-urlencode "fingerprint=${fingerprint}" else exec wget -q -O - "${url}?fingerprint=${fingerprint}" fi django-sshkey-lookup-by-username 0000775 0000000 0000000 00000003336 12366007143 0035520 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 #!/bin/sh # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. url="${SSHKEY_LOOKUP_URL:-http://localhost:8000/sshkey/lookup}" if type curl >/dev/null 2>&1; then exec curl -s -G "$url" --data-urlencode "username=$1" else exec wget -q -O - "${url}?username=$1" fi django_sshkey/ 0000775 0000000 0000000 00000000000 12366007143 0032113 5 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349 __init__.py 0000664 0000000 0000000 00000003036 12366007143 0034226 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. __version__ = '2.3.1' admin.py 0000664 0000000 0000000 00000003677 12366007143 0033572 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from django.contrib import admin from django_sshkey.models import UserKey class UserKeyAdmin(admin.ModelAdmin): list_display = [ '__unicode__', 'user', 'name', 'fingerprint', 'created', 'last_modified', 'last_used', ] search_fields = [ 'user__username', ] readonly_fields = [ 'fingerprint', 'created', 'last_modified', 'last_used', ] admin.site.register(UserKey, UserKeyAdmin) forms.py 0000664 0000000 0000000 00000003772 12366007143 0033624 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from django import forms from django_sshkey.models import UserKey class UserKeyForm(forms.ModelForm): class Meta: model = UserKey fields = ['name', 'key'] widgets = { 'name': forms.TextInput(attrs={ 'size': 50, 'placeholder': "username@hostname, or leave blank to use key comment", }), 'key': forms.Textarea(attrs={ 'cols': 72, 'rows': 15, 'placeholder': "Paste in the contents of your public key file here", }), } migrations/ 0000775 0000000 0000000 00000000000 12366007143 0034267 5 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey 0001_initial.py 0000664 0000000 0000000 00000012640 12366007143 0036735 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/migrations # encoding: utf-8 import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models class Migration(SchemaMigration): def forwards(self, orm): # Adding model 'UserKey' db.create_table('sshkey_userkey', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), ('name', self.gf('django.db.models.fields.CharField')(max_length=50, blank=True)), ('key', self.gf('django.db.models.fields.TextField')(max_length=2000)), ('fingerprint', self.gf('django.db.models.fields.CharField')(db_index=True, max_length=47, blank=True)), ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, null=True, blank=True)), ('last_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, null=True, blank=True)), )) db.send_create_signal('django_sshkey', ['UserKey']) # Adding unique constraint on 'UserKey', fields ['user', 'name'] db.create_unique('sshkey_userkey', ['user_id', 'name']) def backwards(self, orm): # Removing unique constraint on 'UserKey', fields ['user', 'name'] db.delete_unique('sshkey_userkey', ['user_id', 'name']) # Deleting model 'UserKey' db.delete_table('sshkey_userkey') models = { 'auth.group': { 'Meta': {'object_name': 'Group'}, 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, 'auth.permission': { 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, 'auth.user': { 'Meta': {'object_name': 'User'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, 'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, 'django_sshkey.userkey': { 'Meta': {'unique_together': "[('user', 'name')]", 'object_name': 'UserKey', 'db_table': "'sshkey_userkey'"}, 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}), 'fingerprint': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '47', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.TextField', [], {'max_length': '2000'}), 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) } } complete_apps = ['django_sshkey'] 0002_auto__add_field_userkey_last_used.py 0000664 0000000 0000000 00000011117 12366007143 0044177 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/migrations # encoding: utf-8 import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'UserKey.last_used' db.add_column('sshkey_userkey', 'last_used', self.gf('django.db.models.fields.DateTimeField')(null=True), keep_default=False) def backwards(self, orm): # Deleting field 'UserKey.last_used' db.delete_column('sshkey_userkey', 'last_used') models = { 'auth.group': { 'Meta': {'object_name': 'Group'}, 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, 'auth.permission': { 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, 'auth.user': { 'Meta': {'object_name': 'User'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, 'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, 'django_sshkey.userkey': { 'Meta': {'unique_together': "[('user', 'name')]", 'object_name': 'UserKey', 'db_table': "'sshkey_userkey'"}, 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}), 'fingerprint': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '47', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'key': ('django.db.models.fields.TextField', [], {'max_length': '2000'}), 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), 'last_used': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) } } complete_apps = ['django_sshkey'] __init__.py 0000664 0000000 0000000 00000000000 12366007143 0036366 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/migrations models.py 0000664 0000000 0000000 00000012375 12366007143 0033760 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from django.db import models from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db.models.signals import pre_save from django.dispatch import receiver try: from django.utils.timezone import now except ImportError: import datetime now = datetime.datetime.now from django_sshkey.util import PublicKeyParseError, pubkey_parse from django_sshkey import settings class UserKey(models.Model): user = models.ForeignKey(User, db_index=True) name = models.CharField(max_length=50, blank=True) key = models.TextField(max_length=2000) fingerprint = models.CharField(max_length=47, blank=True, db_index=True) created = models.DateTimeField(auto_now_add=True, null=True) last_modified = models.DateTimeField(null=True) last_used = models.DateTimeField(null=True) class Meta: db_table = 'sshkey_userkey' unique_together = [ ('user', 'name'), ] def __unicode__(self): return unicode(self.user) + u': ' + self.name def clean_fields(self, exclude=None): if not exclude or 'key' not in exclude: self.key = self.key.strip() def clean(self): try: pubkey = pubkey_parse(self.key) except PublicKeyParseError as e: raise ValidationError(str(e)) self.key = pubkey.format_openssh() self.fingerprint = pubkey.fingerprint() if not self.name: if not pubkey.comment: raise ValidationError('Name or key comment required') self.name = pubkey.comment def validate_unique(self, exclude=None): if self.pk is None: objects = type(self).objects else: objects = type(self).objects.exclude(pk=self.pk) if exclude is None or 'name' not in exclude: if objects.filter(user=self.user, name=self.name).count(): message = 'You already have a key with that name' raise ValidationError({'name': [message]}) if exclude is None or 'key' not in exclude: try: other = objects.get(fingerprint=self.fingerprint, key=self.key) if self.user == other.user: message = 'You already have that key on file (%s)' % other.name else: message = 'Somebody else already has that key on file' raise ValidationError({'key': [message]}) except type(self).DoesNotExist: pass def export(self, format='RFC4716'): pubkey = pubkey_parse(self.key) f = format.upper() if f == 'RFC4716': return pubkey.format_rfc4716() if f == 'PEM': return pubkey.format_pem() raise ValueError("Invalid format") def save(self, *args, **kwargs): if kwargs.pop('update_last_modified', True): self.last_modified = now() super(UserKey, self).save(*args, **kwargs) def touch(self): self.last_used = now() self.save(update_last_modified=False) @receiver(pre_save, sender=UserKey) def send_email_add_key(sender, instance, **kwargs): if not settings.SSHKEY_EMAIL_ADD_KEY or instance.pk: return from django.template.loader import render_to_string from django.core.mail import EmailMultiAlternatives from django.core.urlresolvers import reverse context_dict = { 'key': instance, 'subject': settings.SSHKEY_EMAIL_ADD_KEY_SUBJECT, } request = getattr(instance, 'request', None) if request: context_dict['request'] = request context_dict['userkey_list_uri'] = request.build_absolute_uri(reverse('django_sshkey.views.userkey_list')) text_content = render_to_string('sshkey/add_key.txt', context_dict) msg = EmailMultiAlternatives( settings.SSHKEY_EMAIL_ADD_KEY_SUBJECT, text_content, settings.SSHKEY_FROM_EMAIL, [instance.user.email], ) if settings.SSHKEY_SEND_HTML_EMAIL: html_content = render_to_string('sshkey/add_key.html', context_dict) msg.attach_alternative(html_content, 'text/html') msg.send() settings.py 0000664 0000000 0000000 00000004064 12366007143 0034331 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey # Copyright (c) 2014, Clemson University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the {organization} nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from django.conf import settings SSHKEY_AUTHORIZED_KEYS_OPTIONS = getattr(settings, 'SSHKEY_AUTHORIZED_KEYS_OPTIONS', None) SSHKEY_ALLOW_EDIT = getattr(settings, 'SSHKEY_ALLOW_EDIT', False) SSHKEY_EMAIL_ADD_KEY = getattr(settings, 'SSHKEY_EMAIL_ADD_KEY', True) SSHKEY_EMAIL_ADD_KEY_SUBJECT = getattr(settings, 'SSHKEY_EMAIL_ADD_KEY_SUBJECT', "A new public key was added to your account" ) SSHKEY_FROM_EMAIL = getattr(settings, 'SSHKEY_FROM_EMAIL', settings.DEFAULT_FROM_EMAIL) SSHKEY_SEND_HTML_EMAIL = getattr(settings, 'SSHKEY_SEND_HTML_EMAIL', False) templates.example/ 0000775 0000000 0000000 00000000000 12366007143 0035543 5 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey sshkey/ 0000775 0000000 0000000 00000000000 12366007143 0037051 5 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/templates.example add_key.html 0000664 0000000 0000000 00000001103 12366007143 0041332 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/templates.example/sshkey
{{ key.user.first_name }},
The following SSH public key was added to your account {% if request.META.SERVER_NAME %} on {{ request.META.SERVER_NAME }} {% endif %} {% if request.META.REMOTE_ADDR %} from {{ request.META.REMOTE_ADDR }}{% if request.META.REMOTE_HOST %} ({{ request.META.REMOTE_HOST }}){% endif %}{% endif %}:
Name: {{ key.name }}
Fingerprint: {{ key.fingerprint }}
If you believe this key was added in error then you should click here and delete the key.
add_key.txt 0000664 0000000 0000000 00000000745 12366007143 0041220 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/templates.example/sshkey {{ key.user.first_name }}, The following SSH public key was added to your account{% if request.META.SERVER_NAME %} on {{ request.META.SERVER_NAME }}{% endif %}{% if request.META.REMOTE_ADDR %} from {{ request.META.REMOTE_ADDR }}{% if request.META.REMOTE_HOST %} ({{ request.META.REMOTE_HOST }}){% endif %}{% endif %}: Name: {{ key.name }} Fingerprint: {{ key.fingerprint }} If you believe this key was added in error then you should go to {{ userkey_list_uri }} and delete the key. userkey_detail.html 0000664 0000000 0000000 00000000445 12366007143 0042753 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/templates.example/sshkey {% if action == 'add' %}{{ error_message }}
{% endif %} userkey_list.html 0000664 0000000 0000000 00000002007 12366007143 0042460 0 ustar 00root root 0000000 0000000 django-sshkey-cd23df6b7de6e0f01a2697cc1b6725ada05fb349-cd23df6b7de6e0f01a2697cc1b6725ada05fb349/django_sshkey/templates.example/sshkeyKey | Fingerprint | Created | {% if allow_edit %}Last Modified | {% endif %}Last Used | |
---|---|---|---|---|---|
{{ userkey.name }} | {{ userkey.fingerprint }} | {{ userkey.created|default:"unknown" }} | {% if allow_edit %}{{ userkey.last_modified|default:"unknown" }} | {% endif %}{{ userkey.last_used|default:"never" }} | {% if allow_edit %} Edit {% endif %} Delete |