Skip to content

Commit

Permalink
add Password-Store
Browse files Browse the repository at this point in the history
Signed-off-by: Laurent Vallar <[email protected]>
  • Loading branch information
Val committed Feb 5, 2019
1 parent 9ba41e4 commit 11f1c52
Show file tree
Hide file tree
Showing 36 changed files with 422 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*~
*.retry
/.*build
/.bundle
/.kitchen
Expand Down
47 changes: 39 additions & 8 deletions .kitchen.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
<%
require_relative 'spec/spec_helper'
ANSIBLE_CHECK_MODE = \
ENV['ANSIBLE_CHECK_MODE']&.match? /^(1|[Yy](es)?|[Tt](rue)?)$/
Expand All @@ -15,15 +17,17 @@
-o PidFile=/tmp/sshd.pid
]
kitchen_provider = ENV['KITCHEN_PROVIDER'] || 'docker'
dockerized = kitchen_provider == 'docker'
if ENV['container'] == 'docker' || dockerized
if ENV['container'] == 'docker' || DOCKERIZED
require_relative 'spec/kitchen/docker/monkey_patches'
kitchen_docker_id_rsa = ROOT / '.kitchen/docker_id_rsa'
if File.exists?(kitchen_docker_id_rsa)
FileUtils.chmod(0o600, kitchen_docker_id_rsa)
end
end
%>
driver:
name: <%= kitchen_provider %>
name: <%= KITCHEN_PROVIDER %>
require_chef_omnibus: false
platform: debian
image: debian:stretch
Expand All @@ -32,7 +36,7 @@ driver:
http_proxy: <%= ENV['HTTP_PROXY'] %>
https_proxy: <%= ENV['HTTP_PROXY'] %>
<% end %>
<% if dockerized %>
<% if DOCKERIZED %>
run_options:
env: container=docker
stop-signal: SIGRTMIN+3
Expand All @@ -56,7 +60,7 @@ driver:
systemd
&& apt-get clean
&& apt-get -y autoremove
&& curl -q -o /tmp/systemctl <%= SYSTEMCTL_REPLACEMENT_URL %>
&& curl -q -o /tmp/systemctl https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py
&& install -o root -g root -m 0755 /tmp/systemctl /bin/systemctl
&& rm -rf /tmp/* /var/tmp/*
&& find /etc/systemd/system /lib/systemd/system
Expand Down Expand Up @@ -92,9 +96,23 @@ provisioner:
idempotency_test: <%= ! ANSIBLE_CHECK_MODE %>
fail_non_idempotent: true
chef_bootstrap_url: nil
# verbose level v, vv, vvv, vvvv
verbose:
raw_arguments: --timeout=10 --diff

platforms:
- name: debian-stretch
lifecycle:
pre_converge: >
if [ -d /tmp/.<%= NAME %>_password-store ]; then
rm -rf /tmp/.<%= NAME %>_password-store ;
fi ;
if [ -d /tmp/.<%= NAME %>_gnupg ]; then
rm -rf /tmp/.<%= NAME %>_gnupg ;
fi ;
cp -a <%= PASSWORD_STORE %> /tmp/.<%= NAME %>_password-store ;
cp -a <%= GNUPG %> /tmp/.<%= NAME %>_gnupg ;
printf "\n\033[36;1m####### pre_converge_command done ########\033[0m\n\n"
driver:
box: debian/stretch64
box_url: https://vagrantcloud.com/debian/stretch64
Expand All @@ -112,11 +130,24 @@ suites:
provisioner:
custom_instance_name: default-sandbox.local
extra_vars:
ansible_fqdn: default-sandbox.local
ansible_check_mode: <%= ANSIBLE_CHECK_MODE %>
ansible_fqdn: default-sandbox.local
verifier:
inspec_tests:
- spec/roles/common/sshd_spec.rb
- name: password-store
provisioner:
playbook: spec/kitchen/playbooks/password-store.yml
mygroup: password_store
custom_instance_name: password-store-sandbox.local
extra_vars:
ansible_check_mode: <%= ANSIBLE_CHECK_MODE %>
ansible_fqdn: password-store-sandbox.local
verifier:
inspec_tests:
- spec/roles/password_store/push_spec.rb
attributes:
host_vars_path: password-store-sandbox.local

transport:
username: <%= ENV['KITCHEN_USERNAME'] %>
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ man-db \
ncurses-base \
ncurses-term \
openssh-client \
pass \
procps \
rsync \
ruby \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Sharing a common [Ansible](https://github.com/ansible/ansible) Provisioning with
for a remote Linux/OsX team and keep most of test & CI code in repository:

* [x] Ansible based provisioning
* [ ] [Password-Store](https://github.com/test-kitchen/test-kitchen) for credentials management
* [x] [Password-Store](https://github.com/test-kitchen/test-kitchen) for credentials management
* [x] Testable provisioning with **Test-Kitchen**
* [x] Bundler friendly (mounted `.bundle` with proper rights)
* [x] custom Ruby version via `.ruby-version` file
Expand Down
11 changes: 11 additions & 0 deletions ansible.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[defaults]
remote_tmp = $HOME/.ansible/tmp
retry_files_save_path = $HOME/.ansible/retry_files
nocows = True
deprecation_warnings = True
command_warnings = True
gathering = explicit
roles_path = roles

[ssh_connection]
pipelining = True
6 changes: 6 additions & 0 deletions group_vars/all
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
# file: all, group variables

ansible_managed: >-
***** /!\ Ansible managed file, do not edit: all changes will be lost *****
...
7 changes: 7 additions & 0 deletions roles/password_store/tasks/decrypt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: Decrypt password store entries
set_fact:
password_store_decrypted: "{{ ( password_store_decrypted | default([]) ) + [ { item.name: ( lookup('passwordstore', item.src + ' returnall=true') ) } ] }}"
with_items: "{{ password_store.decrypt }}"
register: password_store_decrypted
...
15 changes: 15 additions & 0 deletions roles/password_store/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
- name: Password store configured fact set
set_fact:
password_store_configured: "{{ password_store_dir is defined }}"

- debug:
var: password_store_configured
when: password_store_configured

- include_tasks: decrypt.yml
when: password_store_configured and password_store.decrypt is defined

- include_tasks: push.yml
when: password_store_configured and password_store.push is defined
...
54 changes: 54 additions & 0 deletions roles/password_store/tasks/pull.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
- name: Stat remote password store files
stat:
path: "{{ item.path }}"
with_items: "{{ password_store.pull }}"
register: password_store_pulled_stat_raw

- name: Set remote password store files to be pulled fact
set_fact:
password_store_pulled_stat_dict: "{{ ( password_store_pulled_stat_dict | default({}) | combine({ item.item.dest: ( item.stat | combine({ 'dest': item.item.dest, 'force': (item.item.force | default(false)) }) ) }) ) }}"
with_items: "{{ password_store_pulled_stat_raw.results }}"

- name: Set password store file to be pulled stat list fact
set_fact:
password_store_pulled_stat: "{{ password_store_pulled_stat_dict.values() | selectattr('exists', 'equalto', true) | list }}"

- name: Retrieve remote password store files content to be pulled
command: "cat {{ item.path }}"
register: password_store_pulled_content
with_items: "{{ password_store_pulled_stat }}"
changed_when: false

- name: Set remote password store files content to be pulled fact
set_fact:
password_store_pulled_content_dict: "{{ ( password_store_pulled_content_dict | default({}) | combine({ item.item.dest: { 'content': item.stdout, 'dest': item.item.dest, 'force': item.item.force } }) ) }}"
with_items: "{{ password_store_pulled_content.results }}"

- name: Set remote password store files to be pulled fact as list
set_fact:
password_store_pulled: "{{ password_store_pulled_content_dict.values() }}"

- name: Decrypt password store files to be pulled
set_fact:
password_store_pulled_with_original_content: "{{ ( password_store_pulled_with_original_content | default([]) ) + [ ( item | combine( { 'original_content': ( lookup('passwordstore', item.dest + ' returnall=true create=true') | string ) } ) ) ] }}"
with_items: "{{ password_store_pulled }}"
register: password_store_pulled_with_original_content
ignore_errors: Yes

- debug:
var: password_store_pulled_with_original_content

- name: Store remote password store files to be pull in password-store
local_action:
module: command
# module: shell
# stdin: "{{ item.content | string }}"
_raw_params: >-
sh -c '/bin/echo -en "{{ item.content }}" | pass insert {% if item.force %} -f{% endif %} -m {{ item.dest }}'
with_items: "{{ password_store_pulled_with_original_content }}"
when: item.original_content is not defined or item.content != item.original_content
vars:
display_args_to_stdout: true
become: false
...
16 changes: 16 additions & 0 deletions roles/password_store/tasks/push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
- name: Decrypt password store files to be pushed
set_fact:
password_store_pushed: "{{ ( password_store_pushed | default([]) ) + [ ( item | combine( { 'content': ( lookup('passwordstore', item.src + ' returnall=true') ) } ) ) ] }}"
with_items: "{{ password_store.push }}"
register: password_store_pushed

- name: Push password store files
copy:
content: "{{ item.content | string }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner | default('root') }}"
group: "{{ item.group | default('root') }}"
mode: "{{ item.mode | default('0600') }}"
with_items: "{{ password_store_pushed }}"
...
6 changes: 5 additions & 1 deletion site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

gather_facts: No

vars:
password_store_dir: "{{ lookup('env', 'PASSWORD_STORE_DIR') }}"

tasks:
- debug:
msg:
ansible_ssh_user: "{{ ansible_ssh_user }}"
ansible_fqdn: "{{ ansible_fqdn }}"
hostvars__inventory_hostname: "{{ hostvars[inventory_hostname] }}"
PASSWORD_STORE_DIR: "{{ password_store_dir }}"
...
2 changes: 2 additions & 0 deletions spec/fixtures/gnupg/gpg-agent.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
max-cache-ttl 60480000
default-cache-ttl 60480000
90 changes: 90 additions & 0 deletions spec/fixtures/gnupg/gpg.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# correct character displaying
utf8-strings
charset utf-8
display-charset utf-8

# when outputting certificates, view user IDs distinctly from keys:
fixed-list-mode

# Don’t rely on the Key ID: short-keyids are trivially spoofed;
# it's easy to create a long-keyid collision; if you care about strong key
# identifiers, you always want to see the fingerprint:
keyid-format 0xlong
#fingerprint

# when multiple digests are supported by all recipients, choose
# the strongest one:
personal-cipher-preferences AES256 AES192 AES CAST5
personal-digest-preferences SHA512 SHA384 SHA256 SHA224

# preferences chosen for new keys should prioritize stronger
# algorithms:
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed

# digest algorithm used to mangle the passphrases for symmetric encryption.
s2k-digest-algo SHA512

# cipher algorithm for symmetric encryption with a passphrase if
# --personal-cipher-preferences and --cipher-algo are not given
s2k-cipher-algo AES256

# Do not use string as a comment string in cleartext signatures and ASCII
# armored messages or keys (see --armor).
no-comments

# Do not include the version string in ASCII armored output.
no-emit-version

# If you use a graphical environment (and even if you don't)
# you should be using an agent: (similar arguments as
# https://www.debian-administration.org/users/dkg/weblog/64)
use-agent

# You should always know at a glance which User IDs gpg thinks
# are legitimately bound to the keys in your keyring:
verify-options show-uid-validity
list-options show-uid-validity

# Use the sks keyserver pool, instead of one specific server, with secure
# connections.
#keyserver hkps://hkps.pool.sks-keyservers.net
#keyserver x-hkp://pool.sks-keyservers.net
keyserver x-hkp://ha.pool.sks-keyservers.net

# Ensure that all keys are refreshed through the keyserver you have selected.
keyserver-options no-honor-keyserver-url

# Locate the keys given as arguments
auto-key-locate keyserver

# include an unambiguous indicator of which key made a
# signature: (see
# http://thread.gmane.org/gmane.mail.notmuch.general/3721/focus=7234)
sig-notation [email protected]=%g

# when making an OpenPGP certification, use a stronger digest
# than the default SHA1:
cert-digest-algo SHA512

# The environment variable http_proxy is only used when the this option is set.
keyserver-options http-proxy

# My default key
default-key 0x841906A275A7FA23

# Add cross-certification signatures to signing subkeys that may not currently have them.
require-cross-certification

# command te see photo in keys
#photo-viewer "<your image software here> %i"

# see photo in keys when listed (warning, can be annoying)
#list-options show-photos

# see photo in keys when verifying the keys (warning can be annoying)
#verify-options show-photos

# Fix mutt "Could not copy message" ?
#pinentry-mode loopback
#keyserver-options auto-key-retrieve
with-fingerprint
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
This is a revocation certificate for the OpenPGP key:

pub rsa4096/0x841906A275A7FA23 2019-02-04 [S]
Key fingerprint = F068 6BA4 FE02 B6EC FF7B EEE0 8419 06A2 75A7 FA23
uid tap4ci <[email protected]>

A revocation certificate is a kind of "kill switch" to publicly
declare that a key shall not anymore be used. It is not possible
to retract such a revocation certificate once it has been published.

Use it to revoke this key in case of a compromise or loss of
the secret key. However, if the secret key is still accessible,
it is better to generate a new revocation certificate and give
a reason for the revocation. For details see the description of
of the gpg command "--generate-revocation" in the GnuPG manual.

To avoid an accidental use of this file, a colon has been inserted
before the 5 dashes below. Remove this colon with a text editor
before importing and publishing this revocation certificate.

:-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: This is a revocation certificate

iQI2BCABCgAgFiEE8GhrpP4Ctuz/e+7ghBkGonWn+iMFAlxYqB8CHQAACgkQhBkG
onWn+iOGLg/+KaWnXD9cgC25IR4l2WwsV9Q0oN6qkBPFvbsYWbJlMCvmziwhUfJN
VpOe+r4qfzl//tHlBv5djgtYZWKbvf6SV+x+2BX5mQzkgjaIFGikf46itlIELc2C
3cP/PF85L8N1g9yzRx60pVrIa5m9Flri9hOAUcqMQyKWl0/1RRJaEWTtGjNXwGLX
/PA9IevXumEkj7NeDDTZ/3VB9Xl7e3NcwGaXnyQOyqAR2NKGtWxkHyvWtNcWixM9
XTAccQW7Qn4UDFImo5VZHpttRLbdpSdkYPAxoZcoLHxzhjo2y5D3Ak+zy6AlH+XK
JrB77t4gDrl4J5q1mj/3jCATYqa/E6FWqvNH6qrXrflyHTYKGgNwho2Xv0mKYiXo
LV2I3rz+WfU5tD2JtF1a9PAtwYTvjlhX9rRDXitliEBNv2MP8n5PA8c0WWkIHXtv
jzNuK8hcyOQ5hZjhBQYwE3d7lwPur1Kuc4Ylohg6IuqQ2ntGO3/QEL6JH5YFLOs9
3TKxO9G4HMVNkEIOVxUuCihzgkWkL5TBHlCgj9N3p1TgH9VS1mA6P4vZoKWpSAER
SnVOe3cTTMJ6UNsAzZqfGGL2pLohedcUS+NkbqSCY8yZg7ZyLrNjNurTnnuoY9bR
fitu38hsyFaeqInPQFZu2Ht8jnuy2KyN1NW5Vipqf3nGUt1Tt+C5Fdg=
=YA+N
-----END PGP PUBLIC KEY BLOCK-----
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added spec/fixtures/gnupg/pubring.kbx
Binary file not shown.
Binary file added spec/fixtures/gnupg/random_seed
Binary file not shown.
Binary file added spec/fixtures/gnupg/tofu.db
Binary file not shown.
Binary file added spec/fixtures/gnupg/trustdb.gpg
Binary file not shown.
1 change: 1 addition & 0 deletions spec/fixtures/password-store/.gpg-id
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x841906A275A7FA23
Binary file added spec/fixtures/password-store/foo/bar.gpg
Binary file not shown.
Binary file added spec/fixtures/password-store/foo/baz.gpg
Binary file not shown.
2 changes: 2 additions & 0 deletions spec/fixtures/password-store/foo/quux.gpg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
� �k� ˳8�Y�AD��{T�L�'������Z���@���� !��p�4Q9ԋLK-j Plx""��(�d���m��k���v&���%^�6����o:��p*�՛"��
���$��Ez��GiN^��֌�AE'N;oM�6&��ƍ�x:޽��~<� �Yb�q�2�A<b��W!�����L� �h)-����n^.l��x�e??Aڈw�:�y�ΥL�P�� �8��]�n݋Q����t�tM�M@�, "�M��Z�Q�h�L'���@���T�o�V��(���:�M�_/�X�oQ�e�Rw0�k��<�ho4+g�/���/HA>����jaH��<�+�gV� �h���HW$f�}h���H�\�1�� �S�gd.�I��r���ѷ���DoGߨ�+�b^P�l��[���Q$�I3�xD$�61�y^�{�9}�CgP]F��x]p�(�>w}�;��a�%�A��&N����v��\�L3��w�Q8��j����K&���T���?^}�]��SPA����hL'W�]�.���r�9���F�U����?����DU���t����2e���/�uѧ8��?w#��3�O�(A5��p
Expand Down
Binary file added spec/fixtures/password-store/foo/qux.gpg
Binary file not shown.
1 change: 1 addition & 0 deletions spec/kitchen/playbooks/ansible.cfg
6 changes: 6 additions & 0 deletions spec/kitchen/playbooks/group_vars/all
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
# file: all, group variables

ansible_managed: >-
***** /!\ Ansible managed file, do not edit: all changes will be lost *****
...
Loading

0 comments on commit 11f1c52

Please sign in to comment.