Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Crans Passwords
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
5
Issues
5
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nounous
Crans Passwords
Commits
57ff2413
Commit
57ff2413
authored
Mar 07, 2013
by
Vincent Le gallic
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
ssh://git.crans.org/git/cranspasswords
parents
aade16b2
0c127bdf
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
215 additions
and
16 deletions
+215
-16
.gitignore
.gitignore
+3
-0
README
README
+2
-1
clientconfig.example.py
clientconfig.example.py
+6
-0
cranspasswords.py
cranspasswords.py
+101
-15
cranspasswords_bash_completion
cranspasswords_bash_completion
+101
-0
server
server
+2
-0
No files found.
.gitignore
View file @
57ff2413
clientconfig.py
serverconfig.py
*.pyc
# Dossier contenant les mots de passe
db
README
View file @
57ff2413
...
...
@@ -3,9 +3,10 @@ Ce dépôt git contient à la fois le programme client (à utiliser sur votre
ordinateur) et le serveur.
== Installation et configuration du client ==
* Copier le dépôt git sur votre ordinateur:
* Copier le dépôt git sur votre ordinateur
:
$ git clone git://git.crans.org/git/cranspasswords.git
* Copier clientconfig.example.py en clientconfig.py et adapter
à vos besoins
* Si ce n'est déjà fait, indiquer votre clé publique sur gest_crans
* ???
clientconfig.example.py
View file @
57ff2413
...
...
@@ -9,6 +9,12 @@ servers = {
'/root/cranspasswords/server'
],
'user'
:
os
.
getenv
(
'USER'
)
# À définir à la main pour les personnes
# n'ayant pas le même login sur leur pc
},
'ovh'
:
{
'server_cmd'
:
[
'/usr/bin/ssh'
,
'ovh.crans.org'
,
\
'/root/cranspasswords/server'
],
'user'
:
os
.
getenv
(
'USER'
)
# À définir à la main pour les personnes
# n'ayant pas le même login sur leur pc
}
}
cranspasswords.py
View file @
57ff2413
...
...
@@ -10,7 +10,14 @@ import os
import
atexit
import
argparse
import
re
import
clientconfig
as
config
import
random
import
string
import
datetime
try
:
import
clientconfig
as
config
except
ImportError
:
print
"Read the README"
sys
.
exit
(
1
)
## Password pattern in files:
PASS
=
re
.
compile
(
'[
\t
]*pass(?:word)?[
\t
]*:[
\t
]*(.*)
\r
?
\n
?$'
,
\
...
...
@@ -29,7 +36,8 @@ GPG_ARGS = {
DEBUG
=
False
VERB
=
False
CLIPBOARD
=
bool
(
os
.
getenv
(
'DISPLAY'
))
# Par défaut, place-t-on le mdp dans le presse-papier ?
# Par défaut, place-t-on le mdp dans le presse-papier ?
CLIPBOARD
=
bool
(
os
.
getenv
(
'DISPLAY'
))
and
os
.
path
.
exists
(
'/usr/bin/xclip'
)
FORCED
=
False
#Mode interactif qui demande confirmation
NROLES
=
None
# Droits à définir sur le fichier en édition
SERVER
=
None
...
...
@@ -56,6 +64,18 @@ def gpg(command, args = None):
proc
.
stderr
.
close
()
return
proc
.
stdin
,
proc
.
stdout
class
simple_memoize
(
object
):
""" Memoization/Lazy """
def
__init__
(
self
,
f
):
self
.
f
=
f
self
.
val
=
None
def
__call__
(
self
):
if
self
.
val
==
None
:
self
.
val
=
self
.
f
()
return
self
.
val
######
## Remote commands
...
...
@@ -84,14 +104,17 @@ def remote_command(command, arg = None, stdin_contents = None):
sshin
.
close
()
return
json
.
loads
(
sshout
.
read
())
@
simple_memoize
def
all_keys
():
"""Récupère les clés du serveur distant"""
return
remote_command
(
"listkeys"
)
@
simple_memoize
def
all_roles
():
"""Récupère les roles du serveur distant"""
return
remote_command
(
"listroles"
)
@
simple_memoize
def
all_files
():
"""Récupère les fichiers du serveur distant"""
return
remote_command
(
"listfiles"
)
...
...
@@ -108,11 +131,19 @@ def rm_file(filename):
"""Supprime le fichier sur le serveur distant"""
return
remote_command
(
"rmfile"
,
filename
)
@
simple_memoize
def
get_my_roles
():
"""Retoure la liste des rôles perso"""
allr
=
all_roles
()
return
filter
(
lambda
role
:
SERVER
[
'user'
]
in
allr
[
role
],
allr
.
keys
())
def
gen_password
():
"""Generate random password"""
random
.
seed
(
datetime
.
datetime
.
now
().
microsecond
)
chars
=
string
.
letters
+
string
.
digits
+
'/=+*'
length
=
15
return
''
.
join
([
random
.
choice
(
chars
)
for
_
in
xrange
(
length
)])
######
## Local commands
...
...
@@ -140,17 +171,38 @@ def check_keys():
return
True
return
False
def
get_recipients_of_roles
(
roles
):
"""Renvoie les destinataires d'un rôle"""
recipients
=
set
()
allroles
=
all_roles
()
for
role
in
roles
:
for
recipient
in
allroles
[
role
]:
recipients
.
add
(
recipient
)
return
recipients
def
get_dest_of_roles
(
roles
):
""" Summarize recipients of a role """
allkeys
=
all_keys
()
def
additionnal_info
(
rec
):
""" Gives additionnal information for a given recipient """
if
len
(
allkeys
[
rec
])
==
0
:
return
""
out
=
allkeys
[
rec
][
0
]
if
len
(
allkeys
[
rec
])
>
1
:
out
+=
" -> "
+
allkeys
[
rec
][
1
]
return
"(%s)"
%
out
return
[
"%s %s"
%
(
rec
,
additionnal_info
(
rec
))
for
rec
in
\
get_recipients_of_roles
(
roles
)
]
def
encrypt
(
roles
,
contents
):
"""Chiffre le contenu pour les roles donnés"""
recipients
=
set
()
allroles
=
all_roles
()
allkeys
=
all_keys
()
recipients
=
get_recipients_of_roles
(
roles
)
email_recipients
=
[]
for
role
in
roles
:
for
recipient
in
allroles
[
role
]:
recipients
.
add
(
recipient
)
for
recipient
in
recipients
:
email
,
key
=
allkeys
[
recipient
]
if
key
:
...
...
@@ -194,25 +246,39 @@ def get_password(name):
## Interface
def
editor
(
texte
):
""" Lance $EDITOR sur texte"""
f
=
tempfile
.
NamedTemporaryFile
()
def
editor
(
texte
,
annotations
=
""
):
""" Lance $EDITOR sur texte.
Renvoie le nouveau texte si des modifications ont été apportées, ou None
"""
# Avoid syntax hilight with ".txt". Would be nice to have some colorscheme
# for annotations ...
f
=
tempfile
.
NamedTemporaryFile
(
suffix
=
'.txt'
)
atexit
.
register
(
f
.
close
)
f
.
write
(
texte
)
for
l
in
annotations
.
split
(
'
\n
'
):
f
.
write
(
"# %s
\n
"
%
l
.
encode
(
'utf-8'
))
f
.
flush
()
proc
=
subprocess
.
Popen
(
os
.
getenv
(
'EDITOR'
)
+
' '
+
f
.
name
,
shell
=
True
)
os
.
waitpid
(
proc
.
pid
,
0
)
f
.
seek
(
0
)
ntexte
=
f
.
read
()
f
.
close
()
return
texte
<>
ntexte
and
ntexte
or
None
ntexte
=
'
\n
'
.
join
(
filter
(
lambda
l
:
not
l
.
startswith
(
'#'
),
ntexte
.
split
(
'
\n
'
)))
if
texte
!=
ntexte
:
return
ntexte
return
None
def
show_files
():
proc
=
subprocess
.
Popen
(
"cat"
,
stdin
=
subprocess
.
PIPE
,
shell
=
True
)
out
=
proc
.
stdin
out
.
write
(
"""Liste des fichiers disponibles
\n
"""
)
my_roles
=
get_my_roles
()
for
(
fname
,
froles
)
in
all_files
().
iteritems
():
files
=
all_files
()
keys
=
files
.
keys
()
keys
.
sort
()
for
fname
in
keys
:
froles
=
files
[
fname
]
access
=
set
(
my_roles
).
intersection
(
froles
)
!=
set
([])
out
.
write
(
" %s %s (%s)
\n
"
%
((
access
and
'+'
or
'-'
),
fname
,
", "
.
join
(
froles
)))
out
.
write
(
"""--Mes roles: %s
\n
"""
%
\
...
...
@@ -227,6 +293,11 @@ def show_roles():
if
role
.
endswith
(
'-w'
):
continue
print
" * "
+
role
def
show_servers
():
print
"""Liste des serveurs disponibles"""
for
server
in
config
.
servers
.
keys
():
print
" * "
+
server
old_clipboard
=
None
def
saveclipboard
(
restore
=
False
):
global
old_clipboard
...
...
@@ -284,12 +355,15 @@ def show_file(fname):
def
edit_file
(
fname
):
value
=
get_file
(
fname
)
nfile
=
False
annotations
=
u
""
if
value
==
False
:
nfile
=
True
print
"Fichier introuvable"
if
not
confirm
(
"Créer fichier ?"
):
return
texte
=
""
annotations
+=
u
"""Ceci est un fichier initial contenant un mot de passe
aléatoire, pensez à rajouter une ligne "login: ${login}" """
texte
=
"pass: %s
\n
"
%
gen_password
()
roles
=
get_my_roles
()
# Par défaut les roles d'un fichier sont ceux en écriture de son
# créateur
...
...
@@ -303,7 +377,16 @@ def edit_file(fname):
sin
.
write
(
value
[
'contents'
])
sin
.
close
()
texte
=
sout
.
read
()
ntexte
=
editor
(
texte
)
value
[
'roles'
]
=
NROLES
or
value
[
'roles'
]
annotations
+=
u
"Ce fichier sera chiffré pour les rôles suivants :
\n
%s
\n\
C'est-à-dire pour les utilisateurs suivants :
\n
%s"
%
(
', '
.
join
(
value
[
'roles'
]),
'
\n
'
.
join
(
' %s'
%
rec
for
rec
in
get_dest_of_roles
(
value
[
'roles'
]))
)
ntexte
=
editor
(
texte
,
annotations
)
if
ntexte
==
None
and
not
nfile
and
NROLES
==
None
:
print
"Pas de modifications effectuées"
else
:
...
...
@@ -388,7 +471,7 @@ if __name__ == "__main__":
help
=
"Mode verbeux"
)
parser
.
add_argument
(
'-c'
,
'--clipboard'
,
action
=
'store_true'
,
default
=
None
,
help
=
"Stocker le mot de passe dans le presse papier"
)
parser
.
add_argument
(
'--noclipboard'
,
action
=
'store_false'
,
default
=
None
,
parser
.
add_argument
(
'--no
-clip'
,
'--noclip'
,
'--no
clipboard'
,
action
=
'store_false'
,
default
=
None
,
dest
=
'clipboard'
,
help
=
"Ne PAS stocker le mot de passe dans le presse papier"
)
parser
.
add_argument
(
'-f'
,
'--force'
,
action
=
'store_true'
,
default
=
False
,
...
...
@@ -417,6 +500,9 @@ if __name__ == "__main__":
action_grp
.
add_argument
(
'--list-roles'
,
action
=
'store_const'
,
dest
=
'action'
,
default
=
show_file
,
const
=
show_roles
,
help
=
"Lister les rôles des gens"
)
action_grp
.
add_argument
(
'--list-servers'
,
action
=
'store_const'
,
dest
=
'action'
,
default
=
show_file
,
const
=
show_servers
,
help
=
"Lister les rôles serveurs"
)
action_grp
.
add_argument
(
'--recrypt-role'
,
action
=
'store_const'
,
dest
=
'action'
,
default
=
show_file
,
const
=
update_role
,
help
=
"Met à jour (reencode les roles)"
)
...
...
cranspasswords_bash_completion
0 → 100644
View file @
57ff2413
# Fonction de notre auto completion
contain(){
local i
for i in $2; do
if [[ "$i" = "$1" ]]; then
return 0
fi
done
return 1
}
if [[ "$EDITOR" = "" ]]; then
export EDITOR="nano";
fi
_cranspasswords(){
# declaration des variables locales
local argc first last prev cur cur_first_char opts_short opts role_dir pass_dir server server_list role_list pass_list timeout
role_dir="/tmp/cranspasswords-$USER-role/"
pass_dir="/tmp/cranspasswords-$USER-passwords/"
# Combien de temps on garde les réponses du serveur en cache (en minutes)
timeout=5
#COMPREPLY désigne la réponse à renvoyer pour la complétion actuelle
COMPREPLY=()
# argc : vaut le nombre d'argument actuel sur la ligne de commande
argc=${COMP_CWORD};
# cur : désigne la chaine de caractère actuelle pour le dernier mot de la ligne de commande
first="${COMP_WORDS[1]}"
last="${COMP_WORDS[$(($argc - 1 ))]}"
prev="${COMP_WORDS[$(($argc - 2 ))]}"
cur="${COMP_WORDS[argc]}"
cur_first_char=${cur:0:1}
opts_short="-h -v -c -f -l"
opts="--help --server --verbose --clipboard --noclipboard --force --edit --view --remove --list --check-keys --update-keys --list-roles --recrypt-roles --roles --list-servers"
mkdir -p -m 700 "$role_dir"
mkdir -p -m 700 "$pass_dir"
find "$role_dir" -type f -mmin +$timeout -exec rm -f {} \;
find "$pass_dir" -type f -mmin +$timeout -exec rm -f {} \;
# On détermine si on utilsie un serveur alternatif
if contain "--server" "${COMP_WORDS[*]}"; then
if [[ "$prev" = "--server" ]]; then
_cranspasswords_server=$last;
fi
else
_cranspasswords_server="default";
fi
server=$_cranspasswords_server
# les options possibles pour notre auto-complétion
if [[ $cur_first_char = "-" ]]; then
COMPREPLY=( $(compgen -W "$opts" -- $cur ) )
return 0
fi
if [[ "$last" = "--server" ]]; then
server_list="`cranspasswords --list-servers | grep -- "*" | awk '{print $2}'`"
COMPREPLY=( $(compgen -W "$server_list" -- $cur ) )
return 0
fi
if [[ "$last" = "--roles" ]]; then
if [ ! -f "${role_dir}$server" ]; then
echo "`cranspasswords --server $server --list-roles | grep -- "*" | awk '{print $2}'`" > "${role_dir}$server"
fi
role_list="`cat "${role_dir}$server"`"
COMPREPLY=( $(compgen -W "$role_list" -- $cur ) )
return 0
fi
if [[ "$last" = "--edit" ]]; then
if [ ! -f "${pass_dir}${server}-w" ]; then
echo "`cranspasswords --server $server -l | grep "+" | awk '{print $2}'`" > "${pass_dir}${server}-w"
fi
pass_list="`cat "${pass_dir}${server}-w"`"
COMPREPLY=( $(compgen -W "$pass_list" -- $cur ) )
return 0
fi
if true; then
if [ ! -f "${pass_dir}$server" ]; then
echo "`cranspasswords --server $server -l | grep "\( +\| -\)" | awk '{print $2}'`" > "${pass_dir}$server"
fi
pass_list="`cat "${pass_dir}$server"`"
COMPREPLY=( $(compgen -W "$pass_list" -- $cur ) )
return 0
fi
}
# On active l'auto-completion
complete -F _cranspasswords cranspasswords
server
0 → 100755
View file @
57ff2413
#!/bin/bash
sudo
/root/cranspasswords/server.py
$*
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment