add sftp_share role
This commit is contained in:
39
roles/sftp_share/molecule/default/converge.yml
Normal file
39
roles/sftp_share/molecule/default/converge.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
|
||||
pre_tasks:
|
||||
- name: Create test group
|
||||
ansible.builtin.group:
|
||||
name: testgrp
|
||||
state: present
|
||||
|
||||
- name: Ensure OpenSSH server is installed
|
||||
ansible.builtin.apt:
|
||||
name: openssh-server
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure the `/root/.ssh` directory exists
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: "/root/.ssh"
|
||||
mode: "0700"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Provide an SSH private key for testing purposes
|
||||
ansible.builtin.copy:
|
||||
src: "ssh/id_ed25519"
|
||||
dest: "/root/.ssh/id_ed25519"
|
||||
mode: "0600"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
roles:
|
||||
- role: genlab.sftp_share
|
||||
sftp_username: "testusr"
|
||||
sftp_pubkey: "{{ lookup('file', 'ssh/id_ed25519.pub') }}"
|
||||
sftp_root: "/primary/data"
|
||||
sftp_transfers_groupname: "testgrp"
|
||||
sftp_permissions: "open,close,read,lstat,fstat,opendir,readdir,realpath,stat" # read-only
|
||||
27
roles/sftp_share/molecule/default/molecule.yml
Normal file
27
roles/sftp_share/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
|
||||
driver:
|
||||
name: docker
|
||||
|
||||
platforms:
|
||||
- name: ubuntu
|
||||
image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2404}-ansible:latest
|
||||
pre_build_image: true
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
|
||||
provisioner:
|
||||
name: ansible
|
||||
|
||||
verifier:
|
||||
name: ansible
|
||||
|
||||
lint: |
|
||||
set -e
|
||||
yamllint .
|
||||
ansible-lint .
|
||||
7
roles/sftp_share/molecule/default/ssh/id_ed25519
Normal file
7
roles/sftp_share/molecule/default/ssh/id_ed25519
Normal file
@@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBSSKh3Oc0GgnvSzCmvloaoBVpa3/ZcEUhimzih81XMUAAAAJCpucRAqbnE
|
||||
QAAAAAtzc2gtZWQyNTUxOQAAACBSSKh3Oc0GgnvSzCmvloaoBVpa3/ZcEUhimzih81XMUA
|
||||
AAAEDKy8xJ6QdOj+DG1oromiQ0TmwnTWFcMwjUMdqIZFd8blJIqHc5zQaCe9LMKa+WhqgF
|
||||
Wlrf9lwRSGKbOKHzVcxQAAAAC3Jvb3RAdWJ1bnR1AQI=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
1
roles/sftp_share/molecule/default/ssh/id_ed25519.pub
Normal file
1
roles/sftp_share/molecule/default/ssh/id_ed25519.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFJIqHc5zQaCe9LMKa+WhqgFWlrf9lwRSGKbOKHzVcxQ root@ubuntu
|
||||
91
roles/sftp_share/molecule/default/verify.yml
Normal file
91
roles/sftp_share/molecule/default/verify.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
any_errors_fatal: true
|
||||
vars:
|
||||
sftp_username: "testusr"
|
||||
sftp_pubkey: "{{ lookup('file', 'ssh/id_ed25519.pub') }}"
|
||||
sftp_root: "/primary/data"
|
||||
sftp_transfers_groupname: "testgrp"
|
||||
|
||||
tasks:
|
||||
- name: Gather user SFTP directory info
|
||||
ansible.builtin.stat:
|
||||
path: "{{ sftp_root }}/{{ sftp_username }}-uploads"
|
||||
register: sftp_root_stat
|
||||
|
||||
- name: Assert that user SFTP directory has correct owner
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- sftp_root_stat.stat.pw_name == "root"
|
||||
- sftp_root_stat.stat.gr_name == "root"
|
||||
success_msg: "SFTP directory {{ sftp_root }}/{{ sftp_username }}-uploads has correct owner root:root"
|
||||
fail_msg: |
|
||||
"SFTP directory {{ sftp_root }}/{{ sftp_username }}-uploads does not have correct owner root:root,
|
||||
actual owner is {{ sftp_root_stat.stat.pw_name }}:{{ sftp_root_stat.stat.gr_name }}"
|
||||
|
||||
- name: Gather transfers directory info
|
||||
ansible.builtin.stat:
|
||||
path: "{{ sftp_root }}/{{ sftp_username }}-uploads/transfers"
|
||||
register: transfers_stat
|
||||
|
||||
- name: Assert that transfers directory has correct owner
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- transfers_stat.stat.pw_name == sftp_username
|
||||
- transfers_stat.stat.gr_name == sftp_transfers_groupname
|
||||
success_msg: "Directory {{ sftp_root }}/{{ sftp_username }}-uploads/transfers has correct owner {{ sftp_username }}:{{ sftp_transfers_groupname }}"
|
||||
fail_msg: |
|
||||
"Directory {{ sftp_root }}/{{ sftp_username }}-uploads/transfers does not have correct owner {{ sftp_username }}:{{ sftp_transfers_groupname }},
|
||||
actual owner is {{ transfers_stat.stat.pw_name }}:{{ transfers_stat.stat.gr_name }}"
|
||||
|
||||
- name: Assert that transfers directory has correct permissions
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- transfers_stat.stat.mode == "2770"
|
||||
success_msg: "Directory {{ sftp_root }}/{{ sftp_username }}-uploads/transfers has correct permissions 2770"
|
||||
fail_msg: |
|
||||
"Directory {{ sftp_root }}/{{ sftp_username }}-uploads/transfers does not have correct permissions 2770,
|
||||
actual permissions are {{ sftp_root_stat.stat.mode }}"
|
||||
|
||||
- name: Get user info
|
||||
ansible.builtin.getent:
|
||||
database: passwd
|
||||
key: "{{ sftp_username }}"
|
||||
register: user_info
|
||||
|
||||
- name: Check user exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- user_info is defined
|
||||
success_msg: "User {{ sftp_username }} exists"
|
||||
fail_msg: "User {{ sftp_username }} does not exist"
|
||||
|
||||
- name: Check that sshd refuses non-SFTP connection attempts
|
||||
changed_when: false
|
||||
failed_when: ssh.stdout != expected
|
||||
register: ssh
|
||||
vars:
|
||||
expected: "This service allows sftp connections only."
|
||||
ansible.builtin.command: "ssh -l {{ sftp_username }} 127.0.0.1 -o StrictHostKeyChecking=no exit"
|
||||
|
||||
- name: Check that sFTP chroots into /transfers
|
||||
changed_when: false
|
||||
register: sftp
|
||||
failed_when: sftp.stdout != expected
|
||||
vars:
|
||||
expected: "sftp> pwd\nRemote working directory: /transfers"
|
||||
ansible.builtin.shell:
|
||||
executable: /bin/bash
|
||||
cmd: 'set -o pipefail; echo "pwd" | sftp -b - -o StrictHostKeyChecking=no {{ sftp_username | quote }}@127.0.0.1'
|
||||
|
||||
- name: Check that non-whitelisted sFTP permissions are denied
|
||||
changed_when: false
|
||||
register: sftp_mkdir
|
||||
failed_when: sftp_mkdir.stderr != expected
|
||||
vars:
|
||||
expected: 'remote mkdir "/transfers/foo": Permission denied'
|
||||
ansible.builtin.shell:
|
||||
executable: /bin/bash
|
||||
cmd: 'set -o pipefail; echo "mkdir foo" | sftp -b - -o StrictHostKeyChecking=no {{ sftp_username | quote }}@127.0.0.1'
|
||||
Reference in New Issue
Block a user