├── .gitignore ├── .travis.yml ├── .yamllint ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── molecule └── default │ ├── converge.yml │ ├── files │ ├── functional-tests.sh │ └── samba.bats │ ├── molecule.yml │ ├── templates │ ├── global-include.conf │ └── protectedshare-include.conf │ └── verify.yml ├── tasks └── main.yml ├── templates ├── smb.conf.j2 └── smbusers.j2 └── vars ├── os_Archlinux.yml ├── os_Debian.yml └── os_RedHat.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | 3 | # Hidden Vagrant-directory 4 | .vagrant 5 | 6 | # Backup files (e.g. Vim, Gedit, etc.) 7 | *~ 8 | 9 | # Vagrant base boxes (you never know when someone puts one in the repository) 10 | *.box 11 | 12 | # Compiled Python 13 | *.pyc 14 | 15 | # Test directories. These are Git worktrees to separate test branches 16 | *-tests/ 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: python 3 | 4 | # Use the new container infrastructure 5 | sudo: required 6 | 7 | env: 8 | global: 9 | - ROLE_NAME: samba 10 | matrix: 11 | - MOLECULE_DISTRO: centos7 12 | - MOLECULE_DISTRO: debian9 13 | - MOLECULE_DISTRO: fedora29 14 | - MOLECULE_DISTRO: ubuntu1804 15 | 16 | #Enable docker support 17 | services: 18 | - docker 19 | 20 | install: 21 | - sudo apt-get update 22 | - sudo apt-get install bats curl smbclient samba-testsuite 23 | # Install dependencies for Molecule test 24 | - python3 -m pip install molecule yamllint ansible-lint docker 25 | # Check ansible, molecule and nmblookup version 26 | - ansible --version 27 | - molecule --version 28 | - nmblookup --version 29 | # Create ansible.cfg with correct roles_path 30 | - printf '[defaults]\nroles_path=../' >ansible.cfg 31 | 32 | before_script: 33 | #Renames ansible-role-bind to bertvv.bind to make it match with Ansible Galaxy 34 | - cd ../ 35 | - mv ansible-role-$ROLE_NAME bertvv.$ROLE_NAME 36 | - cd bertvv.$ROLE_NAME 37 | 38 | script: 39 | #Run molecule test 40 | - molecule test 41 | 42 | notifications: 43 | webhooks: https://galaxy.ansible.com/api/v1/notifications/ -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | # Based on ansible-lint config 3 | extends: default 4 | 5 | rules: 6 | braces: 7 | max-spaces-inside: 1 8 | level: error 9 | brackets: 10 | max-spaces-inside: 1 11 | level: error 12 | colons: 13 | max-spaces-after: -1 14 | level: error 15 | commas: 16 | max-spaces-after: -1 17 | level: error 18 | comments: disable 19 | comments-indentation: disable 20 | document-start: disable 21 | empty-lines: 22 | max: 3 23 | level: error 24 | hyphens: 25 | level: error 26 | indentation: disable 27 | key-duplicates: enable 28 | line-length: disable 29 | new-line-at-end-of-file: disable 30 | new-lines: 31 | type: unix 32 | trailing-spaces: disable 33 | truthy: disable 34 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | This file contains al notable changes to the bertvv.samba Ansible role. 4 | 5 | This file adheres to the guidelines of [http://keepachangelog.com/](http://keepachangelog.com/). Versioning follows [Semantic Versioning](http://semver.org/). "GH-X" refers to the X'th issue or pull request on the Github project. 6 | 7 | ## 2.7.1 - 2019-06-22 8 | 9 | ## Changed 10 | 11 | - (GH-39) Have include_options use absolute paths (credit: [Bengt Giger](https://github.com/BenGig)) 12 | - (GH-41) Change default of "map to guest" to "never" 13 | - (GH-42) Only apply mitigation of vulnerability CVE-2017-7494 to vulnerable Samba versions 14 | - Fix deprecation warnings for Ansible 2.8.x 15 | - Removed with_items loop from package tasks 16 | 17 | ## 2.7.0 - 2018-10-04 18 | 19 | ## Added 20 | 21 | - (GH-36) Control the Samba log level (credit: [Karl Goetz](https://github.com/goetzk)) 22 | - (GH-35) Load arbitrary config files in every section (credit: [Karl Goetz](https://github.com/goetzk)) 23 | - (GH-34) Control if shares are browseable or not (credit: [Karl Goetz](https://github.com/goetzk)) 24 | - (GH-33) Support for enabling Apple SMB extensions (credit: [Karl Goetz](https://github.com/goetzk)) 25 | 26 | ## 2.6.0 - 2018-08-16 27 | 28 | ### Added 29 | 30 | - (GH-28) Enable a cups server to be used (credit: [Thiago Gomes Verissimo](https://github.com/thiagogomesverissimo)) 31 | 32 | ### Changed 33 | 34 | - (GH-30, GH-31) Improve handling of link to www_documentroot (credit: [Karl Goetz](https://github.com/goetzk)) 35 | - Update supported versions of Fedora to 27 and 28. Fedora 25 and 26 are EOL. This role will probably still work (for a while) on these platforms, but we do no effort to test them. 36 | - (GH-29) Don't print passwords out to the log (credit: [George Hartzell](https://github.com/hartzell)) 37 | 38 | ## 2.5.1 - 2018-05-20 39 | 40 | ### Added 41 | 42 | - (GH-21) Add config flag to disable CVE-2017-7494 mitigation (credit: [Tiemo Kieft](https://github.com/blubber)) 43 | - (GH-23) Added username map configuration (credit: [Tomohiko Ozawa](https://github.com/kota65535)) 44 | - (GH-24) Add samba_server_max_protocol parameter (credit: [Jonathan Underwood](https://github.com/jonathanunderwood)) 45 | - (GH-25) Add Fedora 26 and 27 support explicitly in meta (credit: [Jonathan Underwood](https://github.com/jonathanunderwood)) 46 | - (GH-26) Name the include_vars task (credit: [Tobias Wolter](https://github.com/towo)) 47 | 48 | ## 2.5.0 - 2017-11-21 49 | 50 | ## Added 51 | 52 | - (GH-20) Added variable `ansible_realm`, which adds support for Realmd. This variable is only needed when the host is joined to an already existing domain by using realmd, and you want to configure this member server as a Samba file server. (credit: [Sven Eeckeman](https://github.com/SvenEeckeman)) 53 | 54 | ## 2.4.0 - 2017-09-15 55 | 56 | ### Changed 57 | 58 | - (GH-19) Made WINS support configurable (credit: [Ben Tomasik](https://github.com/tomislacker)) 59 | 60 | 61 | ## 2.3.1 - 2017-05-29 62 | 63 | ### Changed 64 | 65 | - Fix for remote code execution vulnerability CVE-2017-7494: 66 | 67 | ## 2.3.0 - 2017-05-10 68 | 69 | ### Changed 70 | 71 | - Fix service names for Ubuntu/Debian 72 | - Start services in a single task 73 | - Fix issue with NetBIOS name resolution not working on Ubuntu and Debian 74 | - Updated list of supported platforms 75 | - Added Fedora 25 76 | - Removed Ubuntu 14.04 (the name of the `samba` service was changed to `smbd` in more recent versions, supporting both would become cumbersome) 77 | - Removed older versions of EL. The role should still be working on EL6, but the test environment doesn't work. 78 | 79 | ### Added 80 | 81 | - (GH-16) Added global option `guest_account`, share options `writable` and `guest_ok` (credit: [morbidick](https://github.com/morbidick)) 82 | - (GH-17) Added support for vfs options (credit: [Slavek Jurkowski](https://github.com/slavekjurkowski2)) 83 | 84 | ## 2.2.2 - 2017-01-20 85 | 86 | ### Changed 87 | 88 | - (GH-13) Updated documentation, added `setype:` 89 | - (GH-14) Fixed an issue with creating users (credit: [Sven Eeckeman](https://github.com/SvenEeckeman)) 90 | - (GH-15) Fixed the check for SELinux status (credit: [Tomohiko Ozawa](https://github.com/kota65535)) 91 | 92 | ## 2.2.1 - 2016-10-29 93 | 94 | ### Added 95 | 96 | - (GH-12) Add the ability to set owner to the path (credit: [Paul Montero](https://github.com/lpaulmp)) 97 | 98 | ### Changes 99 | 100 | - Added tags to all tasks 101 | 102 | ## 2.2.0 - 2016-07-29 103 | 104 | ### Added 105 | 106 | - (GH-11) Introduced variable `samba_interfaces` (credit: [Jonas Heinrich](https://github.com/onny)) 107 | - (GH-11) Added support for Arch Linux (credit: [Jonas Heinrich](https://github.com/onny)) 108 | 109 | ## 2.1.1 - 2016-05-29 110 | 111 | This is a bugfix release. 112 | 113 | ### Changed 114 | 115 | - (GH-6) Made creation of Samba users idempotent. The task "Create Samba users [...]" will now only indicate it has changed when it actually created a user. 116 | - (GH-9) Fixed forgotten `when: samba_create_varwww_symlinks` (credit: [DarkStar1973](https://github.com/DarkStar1973)) 117 | 118 | ## 2.1.0 - 2016-05-12 119 | 120 | ### Added 121 | 122 | - (GH-7) Support for Debian/Ubuntu (credit: [Ian Young](https://github.com/iangreenleaf)) and Fedora. 123 | - Vagrant test environment for all supported platforms 124 | 125 | ### Changed 126 | 127 | - Moved test code to a separate branch 128 | - (GH-8) Fixed deprecation warnings in Ansible 2.0 (partial credit: [Ian Young](https://github.com/iangreenleaf)) 129 | - Use the generic `package:` module introduced in Ansible 2.0. 130 | 131 | ### Removed 132 | 133 | - The `version:` field in `meta/main.yml` was removed because it is no longer accepted in Ansible 2.0. Unfortunately, this change breaks compatibility with `librarian-ansible`. For more info on this issue, see [ansible/ansible#](https://github.com/ansible/ansible/issues/13496). 134 | 135 | ## 2.0.2 - 2015-12-01 136 | 137 | ### Changed 138 | 139 | - The directory `samba_shares_root` is now created befor creating the directories of the shares, with sane permissions set. This fixes GH-3. Contributed by @birgitcroux. 140 | 141 | ### Removed 142 | 143 | - The role variables `create_mask` and `create_directory_mask` were removed. Samba settings `create mask` and `create directory mask` are synonyms for `create mode` and `create directory mode`, respectively. The former name is misleading, because it suggests they work like the Linux command `umask`. 144 | 145 | ## 2.0.1 - 2015-11-05 146 | 147 | ### Changed 148 | 149 | - (GH-1) The variable type of `samba_create_varwww_symlinks` is now boolean instead of string 150 | - The variable `samba_netbios_name` is no longer required and defaults to `ansible_hostname`. 151 | 152 | ## 2.0.0 - 2015-11-05 153 | 154 | Bugfix release with changes that are not backwards compatible 155 | 156 | ### Changed 157 | 158 | - (GH-1) The variable type of `samba_load_*` is now boolean instead of string, which makes more sense. However, this change is **not backwards compatible**. 159 | - (GH-2) Restart WinBind when changing the configuration 160 | - Updated the base box for the test environment to CentOS 7.1 ([bertvv/centos71](https://atlas.hashicorp.com/bertvv/boxes/centos71/)) 161 | - Cleaned up indentation and spaces in the configuration file template 162 | 163 | ### Removed 164 | 165 | - The firewall configuration is no longer set by this role. This also removes the dependency on firewalld. 166 | 167 | ## 1.0.0 - 2015-03-14 168 | 169 | First release 170 | 171 | ### Added 172 | 173 | - Installation 174 | - Create directories 175 | - SELinux settings 176 | - Configuration template with a.o. configurable print sharing, home directories, user access control 177 | - Set user passwords 178 | 179 | 180 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # BSD License 2 | 3 | Copyright (c) 2014, Bert Van Vreckem, (bert.vanvreckem@gmail.com) 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | 11 | 2. 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. 12 | 13 | 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. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible role `bertvv.samba` 2 | 3 | An Ansible role for setting up Samba as a file server. 4 | 5 | Due to lack of time and resources, I have handed over the maintenance of this role to @vladgh. I am no longer able to follow up on Issues and PRs and to make sure that new releases are of sufficiently high quality to be actually usable. 6 | 7 | - The new Github repo can be found here: 8 | - Ansible Galaxy page: 9 | - Install with `ansible-galaxy collection install vladgh.samba --upgrade` 10 | 11 | Thanks to everyone who showed their support during the years, to all contributors and especially to @vladgh for graciously volunteering to take over maintenance. 12 | 13 | --- 14 | 15 | The responsibilities of this role are to: 16 | 17 | - Install the necessary packages 18 | - Configure SELinux settings (when SELinux is active) 19 | - Create share directories 20 | - Manage Samba users and passwords 21 | - Manage access to shares 22 | 23 | The following are not considered concerns of this role, and you should configure these using another role (e.g. [bertvv.rh-base](https://galaxy.ansible.com/bertvv/rh-base/): 24 | 25 | - Managing firewall settings. 26 | - Creating system users. Samba users should already exist as system users. 27 | 28 | **If you like/use this role, please consider giving it a star! Thanks!** 29 | 30 | ## CVE-2017-7494 31 | 32 | A remote code execution vulnerability may affect your Samba server installation. Samba versions 3.5.0 and before 4.6.4 are affected. If SELinux is enabled on your system, it is **NOT** vulnerable. 33 | 34 | This role will check if the installed version of Samba is affected by the vulnerability and apply the proposed workaround: adding `nt pipe support = no` to the `[global]` section of the configuration. Remark that this disables share browsing by Windows clients. 35 | 36 | You can explicitly disable the fix if necessary, by setting the role variable `samba_mitigate_cve_2017_7494` to `false`. 37 | 38 | More info: 39 | 40 | ## Requirements 41 | 42 | No specific requirements 43 | 44 | ## Role Variables 45 | 46 | | Variable | Default | Comments | 47 | | :--- | :--- | :--- | 48 | | `samba_apple_extensions` | no | When yes, enables support for Apple specific SMB extensions. Required for Time Machine support to work (see below) | 49 | | `samba_create_varwww_symlinks` | false | When true, symlinks are created in web docroot to the shares. (`var/www/` or `/var/www/html` depending on platform) | 50 | | `samba_cups_server` | localhost:631 | Value for the global option `cups server` (only needed when `samba_printer_type` is "cups") | 51 | | `samba_domain_master` | true | When true, smbd enables WAN-wide browse list collation | 52 | | `samba_global_include` | - | Samba-compatible configuration file with options to be loaded to [global] section (see below) | 53 | | `samba_guest_account` | - | Guest account for unknown users | 54 | | `samba_homes_include` | - | Samba-compatible configuration file with options to be loaded to [homes] section (see below) | 55 | | `samba_interfaces` | [] | List of network interfaces used for browsing, name registration, etc. | 56 | | `samba_load_homes` | false | When true, user home directories are accessible. | 57 | | `samba_load_printers` | false | When true, printers attached to the host are shared | 58 | | `samba_local_master` | true | When true, nmbd will try & become local master of the subnet | 59 | | `samba_log` | - | Set the log file. If left undefined, logging is done through syslog. | 60 | | `samba_log_size` | 5000 | Set the maximum size of the log file. | 61 | | `samba_log_level` | 0 | Set Samba log level, 0 is least verbose and 10 is a flood of debug output. | 62 | | `samba_map_to_guest` | `bad user` | Behaviour when unregistered users access the shares. | 63 | | `samba_mitigate_cve_2017_7494` | true | CVE-2017-7494 mitigation breaks some clients, such as macOS High Sierra. | 64 | | `samba_netbios_name` | `{{ ansible_hostname }}` | The NetBIOS name of this server. | 65 | | `samba_passdb_backend` | `tdbsam` | Password database backend. | 66 | | `samba_preferred_master` | true | When true, indicates nmbd is a preferred master browser for workgroup | 67 | | `samba_realm` | - | Realm domain name | 68 | | `samba_printer_type` | cups | value for the global option `printing` and `printcap name` | 69 | | `samba_security` | `user` | Samba security setting | 70 | | `samba_server_max_protocol` | - | Specify a maximum protocol version offered by the server. | 71 | | `samba_server_min_protocol` | - | Specify a minimum protocol version offered by the server. | 72 | | `samba_server_string` | `fileserver %m` | Comment string for the server. | 73 | | `samba_shares_root` | `/srv/shares` | Directories for the shares are created under this directory. | 74 | | `samba_shares` | [] | List of dicts containing share definitions. See below for details. | 75 | | `samba_users` | [] | List of dicts defining users that can access shares. | 76 | | `samba_wins_support` | true | When true, Samba will act as a WINS server | 77 | | `samba_workgroup` | `WORKGROUP` | Name of the server workgroup. | 78 | 79 | ### Defining users 80 | 81 | In order to allow users to access the shares, they need to get a password specifically for Samba: 82 | 83 | ```Yaml 84 | samba_users: 85 | - name: alice 86 | password: ecila 87 | - name: bob 88 | password: bob 89 | - name: charlie 90 | password: eilrahc 91 | ``` 92 | 93 | Unfortunately, passwords have to be in plain text for now. Also, remark that this role will not change the password of an existing user. 94 | 95 | These users should already have an account on the host! Creating system users is not a concern of this role, so you should do this separately. A possibility is my role [bertvv.rh-base](https://galaxy.ansible.com/bertvv/rh-base/). An example: 96 | 97 | ```Yaml 98 | rhbase_users: 99 | - name: alice 100 | comment: 'Alice' 101 | password: !! 102 | shell: /sbin/nologin 103 | groups: 104 | [...] 105 | ``` 106 | 107 | This user is not allowed to log in on the system (e.g. with SSH) and would only get access to the Samba shares. 108 | 109 | ### Defining shares 110 | 111 | Defining Samba shares and configuring access control can be challenging, since it involves not only getting the Samba configuration right, but also user and file permissions, and SELinux settings. This role attempts to simplify the process. 112 | 113 | To specify a share, you should at least give it a name: 114 | 115 | ```Yaml 116 | samba_shares: 117 | - name: readonlyshare 118 | ``` 119 | 120 | This will create a share with only read access for registered users. Guests will not be able to see the contents of the share. 121 | 122 | A good way to configure write access for a share is to create a system user group, add users to that group, and make sure they have write access to the directory of the share. This role assumes groups are already set up and users are members of the groups that control write access. Let's assume you have two users `jack` and `teach`, members of the group `pirates`. This share definition will give both read and write access to the `pirates`: 123 | 124 | ```Yaml 125 | samba_shares: 126 | - name: piratecove 127 | comment: 'A place for pirates to hang out' 128 | group: pirates 129 | write_list: +pirates 130 | ``` 131 | 132 | Guests have no access to this share, registered users can read. You can further tweak access control. Read access can be extended to guests (add `public: yes`) or restricted to specified users or groups (add `valid_users: +pirates`). Write access can be restricted to individual pirates (e.g. `write_list: jack`). Files added to the share will be added to the specified group and group write access will be granted by default. 133 | 134 | This is an example of configuring multiple vfs object modules to share a glusterfs volume. VFS object options are optional. The necessary VFS object modules must be present/installed outside this role. In this case samba-glusterfs was installed on centos. See samba documentation for how to install or what the default VFS object modules are. 135 | 136 | ```Yaml 137 | samba_shares: 138 | - name: gluster-app_deploys 139 | comment: 'For samba share of volume app_deploys' 140 | vfs_objects: 141 | - name: audit 142 | options: 143 | - name: facility 144 | value: LOCAL1 145 | - name: priority 146 | value: NOTICE 147 | - name: glusterfs 148 | options: 149 | - name: volume 150 | value: app_deploys 151 | - name: logfile 152 | value: /var/log/samba/glusterfs-app_deploys.%M.log 153 | - name: loglevel 154 | value: 7 155 | path: / 156 | read_only: no 157 | guest_ok: yes 158 | write_list: tomcat 159 | group: tomcat 160 | ``` 161 | 162 | A complete overview of share options follows below. Only `name` is required, the rest is optional. 163 | 164 | | Option | Default | Comment | 165 | | :--- | :--- | :--- | 166 | | `browseable` | - | Controls whether this share appears in file browser. | 167 | | `comment` | - | A comment string for the share | 168 | | `create_mode` | `0664` | See the Samba documentation for details. | 169 | | `directory_mode` | `0775` | See the Samba documentation for details. | 170 | | `include_file` | - | Samba combatible configuration file with options to be included for this share (see below). | 171 | | `force_create_mode` | `0664` | See the Samba documentation for details. | 172 | | `force_directory_mode` | `0775` | See the Samba documentation for details. | 173 | | `group` | `users` | The user group files in the share will be added to. | 174 | | `guest_ok` | - | Allow guest access. | 175 | | `name` (required) | - | The name of the share. | 176 | | `owner` | `root` | Set the owner of the path | 177 | | `path` | /{{samba_shares_root}}/{{name}} | The path to the share directory. | 178 | | `public` | `no` | Controls read access for guest users | 179 | | `setype` | `samba_share_t` | The SELinux type of the share directory | 180 | | `valid_users` | - | Controls read access for registered users. Use the syntax of the corresponding Samba setting. | 181 | | `vfs_objects` | - | See the Samba documentation for details. | 182 | | `writable` | - | Writable for guests. | 183 | | `write_list` | - | Controls write access for registered users. Use the syntax of the corresponding Samba setting. | 184 | 185 | The values for `valid_users` and `write_list` should be a comma separated list of users. Names prepended with `+` or `@` are interpreted as groups. The documentation for the [Samba configuration](https://www.samba.org/samba/docs/man/manpages-3/smb.conf.5.html) has more details on these options. 186 | 187 | ## Adding arbitrary configuration files 188 | 189 | You can add settings that are not supported by this role out-of-the-box through custom configuration files that will be included from the main configuration file. There are three types of include files: for the global section, for the homes section, and for individual shares. Put your custom configuration files in a subdirectory `templates`, relative to your master playbook location. Then, specify them in the variables `samba_global_include`, `samba_homes_include`, or `include_file` in the `samba_shares` definition. 190 | 191 | Your custom configuration files are considered to be Jinja templates, so you can use Ansible variables inside them. The configuration files will be validated to ensure they are syntactically correct. 192 | 193 | For example, to include `templates/global-include.conf`, set: 194 | 195 | ```yaml 196 | samba_global_include: global-include.conf 197 | ``` 198 | 199 | Remark that is it not necessary to specify the `templates/` directory. 200 | 201 | Likewise, to include `templates/piratecove-include.conf`, specific for the `piratecove` share (see the example above); set: 202 | 203 | ```yaml 204 | samba_shares: 205 | - name: piratecove 206 | comment: 'A place for pirates to hang out' 207 | group: pirates 208 | write_list: +pirates 209 | include_file: piratecove-include.conf 210 | ``` 211 | 212 | The [test playbook](https://github.com/bertvv/ansible-role-samba/blob/docker-tests/test.yml) has some examples. The custom configuration files can be found in the [docker-tests](https://github.com/bertvv/ansible-role-samba/tree/docker-tests) branch. 213 | 214 | ## Dependencies 215 | 216 | No dependencies. 217 | 218 | ## Example Playbook 219 | 220 | See the [test playbook](https://github.com/bertvv/ansible-role-samba/blob/docker-tests/test.yml) 221 | 222 | ## Testing 223 | 224 | This role is tested using [Ansible Molecule](https://molecule.readthedocs.io/). Tests are launched automatically on [Travis CI](https://travis-ci.org/bertvv/ansible-role-samba) after each commit and PR. 225 | 226 | This Molecule configuration will: 227 | 228 | - Run Yamllint and Ansible Lint 229 | - Create a Docker container 230 | - Run a syntax check 231 | - Apply the role with a [test playbook](molecule/default/converge.yml) 232 | - Run acceptance tests with [BATS](https://github.com/bats-core/bats-core/) 233 | 234 | This process is repeated for the supported Linux distributions. 235 | 236 | ### Local test environment 237 | 238 | If you want to set up a local test environment, you can use this reproducible setup based on Vagrant+VirtualBox: . Steps to install the necessary tools manually: 239 | 240 | 1. Docker, BATS and smbclient should be installed on your machine (assumed to run Linux). No Docker containers should be running when you start the test. 241 | 2. As recommended by Molecule, create a python virtual environment 242 | 3. Install the software tools `python3 -m pip install molecule docker yamllint ansible-lint` 243 | 4. Navigate to the root of the role directory and run `molecule test` 244 | 245 | Molecule automatically deletes the containers after a test. If you would like to check out the containers yourself, run `molecule converge` followed by `molecule login --host HOSTNAME`. 246 | 247 | The Docker containers are based on images created by [Jeff Geerling](https://hub.docker.com/u/geerlingguy), specifically for Ansible testing (look for images named `geerlingguy/docker-DISTRO-ansible`). You can use any of his images, but only the distributions mentioned in [meta/main.yml](meta/main.yml) are supported. 248 | 249 | The default config will start a Centos 7 container. Choose another distro by setting the `MOLECULE_DISTRO` variable with the command, e.g.: 250 | 251 | ``` bash 252 | MOLECULE_DISTRO=debian9 molecule test 253 | ``` 254 | 255 | or 256 | 257 | ``` bash 258 | MOLECULE_DISTRO=debian9 molecule converge 259 | ``` 260 | 261 | You can run the acceptance tests on both servers with `molecule verify` or manually with 262 | 263 | ```console 264 | SUT_IP=172.17.0.2 bats molecule/default/files/samba.bats 265 | ``` 266 | 267 | You need to initialise the variable `SUT_IP`, the system under test's IP address. The server, `smb1`, should have IP address 172.17.0.2. 268 | 269 | ## Contributing 270 | 271 | Issues, feature requests, ideas are appreciated and can be posted in the Issues section. 272 | 273 | Pull requests are also very welcome. The best way to submit a PR is by first creating a fork of this Github project, then creating a topic branch for the suggested change and pushing that branch to your own fork. Github can then easily create a PR based on that branch. Don't forget to add yourself to the list of contributors below! 274 | 275 | ## License 276 | 277 | 2-clause BSD license, see [LICENSE.md](LICENSE.md) 278 | 279 | ## Contributors 280 | 281 | This role could only have been realized thanks to the contributions of the people listed below. If you have an idea to improve it even further, don't hesitate to pitch in! 282 | 283 | Issues, feature requests, ideas, suggestions, etc. can be posted in the Issues section. 284 | 285 | Pull requests are also very welcome. Please create a topic branch for your proposed changes. If you don't, this will create conflicts in your fork after the merge. Don't hesitate to add yourself to the contributor list below in your PR! 286 | 287 | [Ben Tomasik](https://github.com/tomislacker), 288 | [Bengt Giger](https://github.com/BenGig), 289 | [Bert Van Vreckem](https://github.com/bertvv/) (maintainer), 290 | [Birgit Croux](https://github.com/birgitcroux), 291 | [DarkStar1973](https://github.com/DarkStar1973), 292 | [George Hartzell](https://github.com/hartzell), 293 | [Ian Young](https://github.com/iangreenleaf), 294 | [Jonas Heinrich](https://github.com/onny), 295 | [Jonathan Underwood](https://github.com/jonathanunderwood), 296 | [Karl Goetz](https://github.com/goetzk), 297 | [morbidick](https://github.com/morbidick), 298 | [Paul Montero](https://github.com/lpaulmp), 299 | [Slavek Jurkowski](https://github.com/slavekjurkowski2), 300 | [Sven Eeckeman](https://github.com/SvenEeckeman), 301 | [Tiemo Kieft](https://github.com/blubber), 302 | [Tobias Wolter](https://github.com/towo), 303 | [Tomohiko Ozawa](https://github.com/kota65535), 304 | [Robin Ophalvens](https://github.com/RobinOphalvens). 305 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | # roles/samba/defaults/main.yml 2 | --- 3 | 4 | samba_workgroup: 'WORKGROUP' 5 | samba_server_string: 'Fileserver %m' 6 | samba_log_size: 5000 7 | samba_log_level: 0 8 | samba_interfaces: [] 9 | samba_security: 'user' 10 | samba_passdb_backend: 'tdbsam' 11 | samba_map_to_guest: 'never' 12 | samba_load_printers: false 13 | samba_printer_type: 'cups' 14 | samba_cups_server: 'localhost:631' 15 | samba_load_homes: false 16 | samba_create_varwww_symlinks: false 17 | samba_shares_root: '/srv/shares' 18 | samba_shares: [] 19 | samba_users: [] 20 | 21 | samba_wins_support: 'yes' 22 | samba_local_master: 'yes' 23 | samba_domain_master: 'yes' 24 | samba_preferred_master: 'yes' 25 | samba_mitigate_cve_2017_7494: true 26 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | # File: roles/samba/handlers/main.yml 2 | --- 3 | - name: Restart Samba services 4 | service: 5 | name: "{{ item }}" 6 | state: restarted 7 | with_items: "{{ samba_services }}" 8 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Bert Van Vreckem 4 | description: This role installs and configures Samba as a file server. Deprecated, please use vladgh.samba instead. 5 | license: BSD 6 | min_ansible_version: 2.8 7 | platforms: 8 | - name: EL 9 | versions: 10 | - 7 11 | - name: Fedora 12 | versions: 13 | - 28 14 | - name: Ubuntu 15 | versions: 16 | - xenial 17 | - bionic 18 | - name: Debian 19 | versions: 20 | - jessie 21 | - stretch 22 | - name: ArchLinux 23 | versions: 24 | - all 25 | galaxy_tags: 26 | - system 27 | - networking 28 | dependencies: [] 29 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | pre_tasks: 5 | - name: Ensure package database is up-to-date 6 | apt: 7 | update-cache: true 8 | failed_when: false 9 | changed_when: false 10 | when: ansible_os_family == 'Debian' 11 | - name: Create users 12 | user: 13 | name: "{{ item }}" 14 | groups: users 15 | append: true 16 | with_items: 17 | - usr1 18 | - usr2 19 | - timemachine 20 | vars: 21 | samba_netbios_name: SAMBA_TEST 22 | samba_server_string: 'Welcome to the test file server' 23 | samba_workgroup: TESTGROUP 24 | samba_global_include: global-include.conf 25 | samba_load_homes: true 26 | samba_load_printers: false 27 | samba_create_varwww_symlinks: true 28 | samba_log: /var/log/samba.log 29 | samba_log_size: 60000 30 | samba_log_level: '3 passdb:5 auth:10 winbind:2 ' 31 | # The smbclient version of the Travis CI environment crashes when `min 32 | # protocol' is set: 33 | # protocol negotiation failed: NT_STATUS_INVALID_NETWORK_RESPONSE 34 | # Uncomment the following lines if you want to test this setting locally. 35 | # 36 | # samba_server_min_protocol: SMB2 37 | # samba_server_max_protocol: SMB3 38 | samba_map_to_guest: Never 39 | samba_users: 40 | - name: usr1 41 | password: usr1 42 | - name: usr2 43 | password: usr2 44 | - name: timemachine 45 | password: timemachine 46 | samba_username_map: 47 | - from: 'User Two' 48 | to: usr2 49 | samba_shares_root: /srv/samba 50 | samba_shares: 51 | - name: restrictedshare 52 | - name: privateshare 53 | comment: 'Only readable/writeable by usr1' 54 | valid_users: usr1 55 | write_list: usr1 56 | group: usr1 57 | browseable: 'no' 58 | - name: protectedshare 59 | public: 'yes' 60 | comment: 'Public, but only writeable by usr2' 61 | write_list: usr2 62 | group: users 63 | browseable: 'yes' 64 | include_file: protectedshare-include.conf 65 | - name: publicshare 66 | comment: 'Public share, writeable by all members of group ‘users’' 67 | public: 'yes' 68 | write_list: +users 69 | group: users 70 | setype: public_content_t 71 | browseable: 'yes' 72 | - name: guestshare 73 | comment: 'Share accessible for guests' 74 | guest_ok: 'yes' 75 | writable: 'yes' 76 | browseable: 'yes' 77 | - name: TimeMachine 78 | comment: 'Share useable as a TimeMachine backup target on MacOS' 79 | vfs_objects: 80 | - name: fruit 81 | options: 82 | - name: time machine 83 | value: 'yes' 84 | - name: streams_xattr 85 | path: /srv/timemachine 86 | write_list: timemachine 87 | owner: timemachine 88 | group: timemachine 89 | public: 'no' 90 | guest_ok: 'no' 91 | browseable: 'no' 92 | roles: 93 | - role: bertvv.samba -------------------------------------------------------------------------------- /molecule/default/files/functional-tests.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | # 3 | # Author: Bert Van Vreckem 4 | # 5 | # Run BATS test files in the current directory, and the ones in the subdirectory 6 | # matching the host name. 7 | # 8 | # The script installs BATS if needed. It's best to put ${bats_install_dir} in 9 | # your .gitignore. 10 | 11 | set -o errexit # abort on nonzero exitstatus 12 | set -o nounset # abort on unbound variable 13 | 14 | #{{{ Variables 15 | 16 | test_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 17 | 18 | bats_archive="v1.1.0.tar.gz" 19 | bats_url="https://github.com/bats-core/bats-core/archive/${bats_archive}" 20 | bats_install_dir="/opt" 21 | bats_default_location="${bats_install_dir}/bats/libexec/bats" 22 | test_file_pattern="*.bats" 23 | 24 | # Color definitions 25 | readonly reset='\e[0m' 26 | readonly yellow='\e[0;33m' 27 | readonly cyan='\e[0;36m' 28 | #}}} 29 | 30 | main() { 31 | 32 | bats=$(find_bats_executable) 33 | 34 | if [ -z "${bats}" ]; then 35 | install_bats 36 | bats="${bats_default_location}" 37 | fi 38 | 39 | debug "Using BATS executable at: ${bats}" 40 | 41 | # List all test cases (i.e. files in the test dir matching the test file 42 | # pattern) 43 | 44 | # Tests to be run on all hosts 45 | global_tests=$(find_tests "${test_dir}" 1) 46 | 47 | # Tests for individual hosts 48 | host_tests=$(find_tests "${test_dir}/${HOSTNAME}") 49 | 50 | # Loop over test files 51 | for test_case in ${global_tests} ${host_tests}; do 52 | info "Running test ${test_case}" 53 | ${bats} "${test_case}" 54 | done 55 | } 56 | 57 | #{{{ Functions 58 | 59 | # Tries to find BATS executable in the PATH or the place where this script 60 | # installs it. 61 | find_bats_executable() { 62 | if which bats > /dev/null; then 63 | which bats 64 | elif [ -x "${bats_default_location}" ]; then 65 | echo "${bats_default_location}" 66 | else 67 | echo "" 68 | fi 69 | } 70 | 71 | # Usage: install_bats 72 | install_bats() { 73 | pushd "${bats_install_dir}" > /dev/null 2>&1 74 | curl --location --remote-name "${bats_url}" 75 | tar xzf "${bats_archive}" 76 | mv bats-* bats 77 | rm "${bats_archive}" 78 | popd > /dev/null 2>&1 79 | } 80 | 81 | # Usage: find_tests DIR [MAX_DEPTH] 82 | # 83 | # Finds BATS test suites in the specified directory 84 | find_tests() { 85 | local max_depth="" 86 | if [ "$#" -eq "2" ]; then 87 | max_depth="-maxdepth $2" 88 | fi 89 | 90 | local tests 91 | tests=$(find "$1" ${max_depth} -type f -name "${test_file_pattern}" -printf '%p\n' 2> /dev/null) 92 | 93 | echo "${tests}" 94 | } 95 | 96 | # Usage: info [ARG]... 97 | # 98 | # Prints all arguments on the standard output stream 99 | info() { 100 | printf "${yellow}### %s${reset}\n" "${*}" 101 | } 102 | 103 | # Usage: debug [ARG]... 104 | # 105 | # Prints all arguments on the standard output stream 106 | debug() { 107 | printf "${cyan}### %s${reset}\n" "${*}" 108 | } 109 | #}}} 110 | 111 | main 112 | -------------------------------------------------------------------------------- /molecule/default/files/samba.bats: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bats 2 | # 3 | # Author: Bert Van Vreckem 4 | # 5 | # Test a Samba server 6 | 7 | sut_wins_name=SAMBA_TEST # NetBIOS name 8 | workgroup=TESTGROUP # Workgroup 9 | 10 | # The name of a directory and file that will be created to test for 11 | # write access (= random string) 12 | test_dir=peghawJaup 13 | test_file=Nocideicye 14 | 15 | # {{{Helper functions 16 | 17 | # Checks if a user has shell access to the system 18 | # Usage: assert_can_login USER PASSWD 19 | assert_can_login() { 20 | echo $2 | su -c 'ls ${HOME}' - $1 21 | } 22 | 23 | # Checks that a user has NO shell access to the system 24 | # Usage: assert_cannot_login USER 25 | assert_cannot_login() { 26 | run sudo su -c 'ls' - $1 27 | [ "0" -ne "${status}" ] 28 | } 29 | 30 | # Check that the guest account has read access 31 | # Usage: assert_guest_read SHARE 32 | assert_guest_read() { 33 | local share="${1}" 34 | 35 | run smbclient "//${SUT_IP}/${share}" \ 36 | --user=% \ 37 | --command='ls' 38 | 39 | echo "${output}" 40 | 41 | [ "${status}" -eq "0" ] 42 | } 43 | 44 | # Check that a user has read acces to a share 45 | # Usage: read_access SHARE USER PASSWORD 46 | assert_read_access() { 47 | local share="${1}" 48 | local user="${2}" 49 | local password="${3}" 50 | 51 | run smbclient "//${SUT_IP}/${share}" \ 52 | --user=${user}%${password} \ 53 | --command='ls' 54 | 55 | echo "${output}" 56 | 57 | [ "${status}" -eq "0" ] 58 | } 59 | 60 | # Check that a user has NO read access to a share 61 | # Usage: no_read_access SHARE USER PASSWORD 62 | assert_no_read_access() { 63 | local share="${1}" 64 | local user="${2}" 65 | local password="${3}" 66 | 67 | run smbclient "//${SUT_IP}/${share}" \ 68 | --user=${user}%${password} \ 69 | --command='ls' 70 | 71 | echo "${output}" 72 | 73 | [ "${status}" -eq "1" ] 74 | } 75 | 76 | # Check that a user has write access to a share 77 | # Usage: write_access SHARE USER PASSWORD 78 | assert_write_access() { 79 | local share="${1}" 80 | local user="${2}" 81 | local password="${3}" 82 | 83 | run smbclient "//${SUT_IP}/${share}" \ 84 | --user=${user}%${password} \ 85 | --command="mkdir ${test_dir};rmdir ${test_dir}" 86 | 87 | echo "${output}" 88 | 89 | # Output should NOT contain any error message. Checking on exit status is 90 | # not reliable, it can be 0 when the command failed... 91 | [ -z "$(echo ${output} | grep NT_STATUS_)" ] 92 | } 93 | 94 | # Check that a user has NO write access to a share 95 | # Usage: no_write_access SHARE USER PASSWORD 96 | assert_no_write_access() { 97 | local share="${1}" 98 | local user="${2}" 99 | local password="${3}" 100 | 101 | run smbclient "//${SUT_IP}/${share}" \ 102 | --user=${user}%${password} \ 103 | --command="mkdir ${test_dir};rmdir ${test_dir}" 104 | 105 | echo "${output}" 106 | 107 | # Output should contain an error message (beginning with NT_STATUS, usually 108 | # NT_STATUS_MEDIA_WRITE_PROTECTED 109 | [ -n "$(echo ${output} | grep NT_STATUS_)" ] 110 | } 111 | 112 | # Check that users from the same group can write to each other’s files 113 | # Usage: assert_group_write_file SHARE USER1 PASSWD1 USER2 PASSWD2 114 | assert_group_write_file() { 115 | local share="${1}" 116 | local user1="${2}" 117 | local passwd1="${3}" 118 | local user2="${4}" 119 | local passwd2="${5}" 120 | 121 | echo "Hello world!" > ${test_file} 122 | 123 | smbclient "//${SUT_IP}/${share}" --user=${user1}%${passwd1} \ 124 | --command="put ${test_file}" 125 | # In order to overwrite the file, write access is needed. This will fail 126 | # if user2 doesn’t have write access. 127 | smbclient "//${SUT_IP}/${share}" --user=${user2}%${passwd2} \ 128 | --command="put ${test_file}" 129 | } 130 | 131 | # Check that users from the same group can write to each other’s directories 132 | # Usage: assert_group_write_dir SHARE USER1 PASSWD1 USER2 PASSWD2 133 | assert_group_write_dir() { 134 | local share="${1}" 135 | local user1="${2}" 136 | local passwd1="${3}" 137 | local user2="${4}" 138 | local passwd2="${5}" 139 | 140 | smbclient "//${SUT_IP}/${share}" --user=${user1}%${passwd1} \ 141 | --command="mkdir ${test_dir}; mkdir ${test_dir}/tst" 142 | run smbclient "//${SUT_IP}/${share}" --user=${user2}%${passwd2} \ 143 | --command="rmdir ${test_dir}/tst" 144 | [ -z $(echo "${output}" | grep NT_STATUS_ACCESS_DENIED) ] 145 | } 146 | 147 | #}}} 148 | 149 | @test 'NetBIOS name resolution should work' { 150 | #skip 151 | # Look up the Samba server’s NetBIOS name under the specified workgroup 152 | # The result should contain the IP followed by NetBIOS name 153 | nmblookup -U ${SUT_IP} --workgroup ${workgroup} ${sut_wins_name} | grep "^${SUT_IP} ${sut_wins_name}" 154 | } 155 | 156 | # Read / write access to shares 157 | 158 | @test 'read access for share ‘restrictedshare’' { 159 | # Share User Password 160 | assert_read_access restrictedshare usr1 usr1 161 | assert_read_access restrictedshare usr2 usr2 162 | } 163 | 164 | @test 'write access for share ‘restrictedshare’' { 165 | # Share User Password 166 | assert_no_write_access restrictedshare usr1 usr1 167 | assert_no_write_access restrictedshare usr2 usr2 168 | } 169 | 170 | @test 'read access for share ‘privateshare’' { 171 | # Share User Password 172 | assert_read_access privateshare usr1 usr1 173 | assert_no_read_access privateshare usr2 usr2 174 | } 175 | 176 | @test 'write access for share ‘privateshare’' { 177 | # Share User Password 178 | assert_write_access privateshare usr1 usr1 179 | assert_no_write_access privateshare usr2 usr2 180 | } 181 | 182 | @test 'read access for share ‘protectedshare’' { 183 | # Share User Password 184 | assert_read_access protectedshare usr1 usr1 185 | assert_read_access protectedshare usr2 usr2 186 | } 187 | 188 | @test 'write access for share ‘protectedshare’' { 189 | # Share User Password 190 | assert_no_write_access protectedshare usr1 usr1 191 | assert_write_access protectedshare usr2 usr2 192 | } 193 | 194 | @test 'read access for share ‘publicshare’' { 195 | # Share User Password 196 | assert_read_access publicshare usr1 usr1 197 | assert_read_access publicshare usr2 usr2 198 | } 199 | 200 | @test 'write access for share ‘publicshare’' { 201 | # Share User Password 202 | assert_write_access publicshare usr1 usr1 203 | assert_write_access publicshare usr2 usr2 204 | } 205 | 206 | @test 'Guest access in share ‘guestshare’' { 207 | assert_guest_read guestshare 208 | } 209 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | #Specifies the driver that should be used. Podman should also work 6 | name: docker 7 | lint: | 8 | yamllint . 9 | ansible-lint --exclude=molecule/default/verify.yml 10 | platforms: 11 | #Set name and hostname 12 | - name: smb1 13 | hostname: smb1 14 | #Specify which image should be used. Geerlingguys images are Ansible compatible and have Systemd installed 15 | image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest" 16 | #Command to execute when the container starts 17 | command: ${MOLECULE_DOCKER_COMMAND:-""} 18 | #Volumes to mount within the container. Important to enable systemd 19 | volumes: 20 | - /sys/fs/cgroup:/sys/fs/cgroup:rw 21 | #Give extended privileges to the container. Necessary for Systemd to operate within the container. 22 | # DO NOT use extended privileges in a production environment! 23 | privileged: true 24 | #Allocate pseudo-TTY 25 | tty: True 26 | environment: 27 | container: docker 28 | 29 | provisioner: 30 | name: ansible 31 | #Runs the verify.yml playbook. Testinfra is also a supported method. Check the Molecule documention for more information. 32 | verifier: 33 | name: ansible 34 | -------------------------------------------------------------------------------- /molecule/default/templates/global-include.conf: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | # These come from Debians 4.8.4 config file 4 | panic action = /usr/share/samba/panic-action %d 5 | obey pam restrictions = yes 6 | unix password sync = yes 7 | passwd program = /usr/bin/passwd %u 8 | passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . 9 | pam password change = yes 10 | 11 | # vim: ft=samba 12 | -------------------------------------------------------------------------------- /molecule/default/templates/protectedshare-include.conf: -------------------------------------------------------------------------------- 1 | # Additional Samba options for protectedshare 2 | # {{ ansible_managed }} 3 | 4 | delete readonly = yes 5 | 6 | # vim: ft=samba 7 | -------------------------------------------------------------------------------- /molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: all 4 | tasks: 5 | # We run the BATS tests from the localhost, since they are black box tests 6 | - name: "Run BATS tests for {{ ansible_hostname }}" 7 | shell: SUT_IP={{ ansible_default_ipv4.address }} bats {{ playbook_dir }}/files/samba.bats 8 | delegate_to: localhost 9 | changed_when: false -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | # File: roles/samba/tasks/main.yml 2 | --- 3 | 4 | - name: Include OS specific variables 5 | include_vars: "{{ item }}" 6 | with_first_found: 7 | - "os_{{ ansible_distribution }}.yml" 8 | - "os_{{ ansible_os_family }}.yml" 9 | tags: samba 10 | 11 | - name: Install Samba packages 12 | package: 13 | name: "{{ samba_packages }}" 14 | state: present 15 | tags: samba 16 | 17 | - name: Install Samba VFS extensions packages 18 | package: 19 | name: "{{ samba_vfs_packages }}" 20 | state: present 21 | when: samba_vfs_packages is defined 22 | tags: samba 23 | 24 | - name: Register Samba version 25 | shell: > 26 | set -o nounset -o pipefail -o errexit && 27 | smbd --version | sed 's/Version //' 28 | args: 29 | executable: /bin/bash 30 | register: samba_version 31 | changed_when: false 32 | tags: samba 33 | 34 | # - name: "Installed Samba version:" 35 | # debug: 36 | # msg: "{{ samba_version }}" 37 | # tags: samba 38 | 39 | - name: Install SELinux package 40 | package: 41 | name: "{{ samba_selinux_packages }}" 42 | state: present 43 | when: ansible_selinux is defined and ansible_selinux.status == 'enabled' 44 | tags: samba 45 | 46 | - name: Make sure SELinux boolean settings are correct 47 | seboolean: 48 | name: "{{ item }}" 49 | state: true 50 | persistent: true 51 | with_items: "{{ samba_selinux_booleans }}" 52 | when: ansible_selinux is defined and ansible_selinux.status == 'enabled' 53 | tags: samba 54 | 55 | - name: Create Samba shares root directory 56 | file: 57 | state: directory 58 | path: "{{ samba_shares_root }}" 59 | owner: root 60 | group: root 61 | mode: '0755' 62 | when: samba_shares|length > 0 63 | tags: samba 64 | 65 | - name: Create share directories 66 | with_items: "{{ samba_shares }}" 67 | file: 68 | state: directory 69 | path: "{{ item.path|default([samba_shares_root,item.name]|join('/')) }}" 70 | owner: "{{ item.owner|default('root') }}" 71 | group: "{{ item.group|default('users') }}" 72 | mode: "{{ item.directory_mode|default('0775') }}" 73 | setype: "{{ item.setype|default('samba_share_t') }}" 74 | tags: samba 75 | 76 | - name: Ensure webserver document root exists 77 | file: 78 | name: "{{ samba_www_documentroot }}" 79 | state: directory 80 | when: samba_create_varwww_symlinks|bool 81 | tags: samba 82 | 83 | - name: Create link to shares in webserver document root 84 | file: 85 | state: link 86 | path: "{{ samba_www_documentroot }}/{{ item.name }}" 87 | src: "{{ item.path|default([samba_shares_root,item.name]|join('/')) }}" 88 | with_items: "{{ samba_shares }}" 89 | when: samba_create_varwww_symlinks|bool 90 | tags: samba 91 | 92 | - name: Samba configuration 93 | template: 94 | dest: "{{ samba_configuration }}" 95 | src: smb.conf.j2 96 | validate: 'testparm -s %s' 97 | notify: 98 | - Restart Samba services 99 | tags: samba 100 | 101 | - name: Install global include file 102 | template: 103 | src: "{{ samba_global_include }}" 104 | dest: "{{ samba_configuration_dir }}" 105 | validate: 'testparm -s %s' 106 | when: samba_global_include is defined 107 | notify: 108 | - Restart Samba services 109 | tags: samba 110 | 111 | - name: Install home include file 112 | template: 113 | src: "{{ samba_homes_include }}" 114 | dest: "{{ samba_configuration_dir }}" 115 | validate: 'testparm -s %s' 116 | when: samba_homes_include is defined 117 | notify: 118 | - Restart Samba services 119 | tags: samba 120 | 121 | - name: Install share specific include files 122 | template: 123 | src: "{{ item.include_file }}" 124 | dest: "{{ samba_configuration_dir }}" 125 | validate: 'testparm -s %s' 126 | when: item.include_file is defined 127 | notify: 128 | - Restart Samba services 129 | with_items: "{{ samba_shares }}" 130 | tags: samba 131 | 132 | - name: Create username map file if needed 133 | template: 134 | dest: "{{ samba_username_map_file }}" 135 | src: smbusers.j2 136 | notify: 137 | - Restart Samba services 138 | when: samba_username_map is defined 139 | tags: samba 140 | 141 | - name: Start Samba service(s) 142 | service: 143 | name: "{{ item }}" 144 | state: started 145 | enabled: true 146 | with_items: "{{ samba_services }}" 147 | tags: samba 148 | 149 | - name: Create Samba users if they don't exist yet 150 | shell: > 151 | set -o nounset -o pipefail -o errexit && 152 | (pdbedit --user={{ item.name }} 2>&1 > /dev/null) \ 153 | || (echo {{ item.password }}; echo {{ item.password }}) \ 154 | | smbpasswd -s -a {{ item.name }} 155 | args: 156 | executable: /bin/bash 157 | with_items: "{{ samba_users }}" 158 | no_log: true 159 | register: create_user_output 160 | changed_when: "'Added user' in create_user_output.stdout" 161 | tags: samba 162 | -------------------------------------------------------------------------------- /templates/smb.conf.j2: -------------------------------------------------------------------------------- 1 | # Samba configuration -- Managed by Ansible, please don't edit manually 2 | # vim: ft=samba 3 | # 4 | # {{ ansible_managed }} 5 | 6 | [global] 7 | # Server information 8 | netbios name = {% if samba_netbios_name is defined %}{{ samba_netbios_name }}{% else %}{{ ansible_hostname }}{% endif %} 9 | 10 | workgroup = {{ samba_workgroup }} 11 | {% if samba_realm is defined %} 12 | realm = {{ samba_realm }} 13 | {% endif %} 14 | server string = {{ samba_server_string }} 15 | 16 | {% if samba_apple_extensions is defined %} 17 | fruit:aapl = yes 18 | {% endif %} 19 | 20 | # Logging 21 | {% if samba_log is defined %} 22 | log file = {{ samba_log }} 23 | max log size = {{ samba_log_size }} 24 | log level = {{ samba_log_level }} 25 | {% else %} 26 | logging = syslog 27 | {% endif %} 28 | 29 | # Authentication 30 | security = {{ samba_security }} 31 | passdb backend = {{ samba_passdb_backend }} 32 | map to guest = {{ samba_map_to_guest }} 33 | {% if samba_guest_account is defined %} 34 | guest account = {{ samba_guest_account }} 35 | {% endif %} 36 | {% if samba_username_map is defined %} 37 | username map = {{ samba_username_map_file }} 38 | {% endif %} 39 | 40 | {% if samba_server_min_protocol is defined %} 41 | # Minimum protocol version offered by the server 42 | server min protocol = {{ samba_server_min_protocol }} 43 | 44 | {% endif %} 45 | {% if samba_server_max_protocol is defined %} 46 | # Maximum protocol version offered by the server 47 | server max protocol = {{ samba_server_max_protocol }} 48 | 49 | {% endif %} 50 | {% if samba_interfaces|length > 0 %} 51 | interfaces = {{ samba_interfaces }} 52 | 53 | {% endif %} 54 | # Name resolution: make sure \\NETBIOS_NAME\ works 55 | wins support = {{ samba_wins_support | ternary('yes', 'no') }} 56 | local master = {{ samba_local_master | ternary('yes', 'no') }} 57 | domain master = {{ samba_domain_master | ternary('yes', 'no') }} 58 | preferred master = {{ samba_preferred_master | ternary('yes', 'no') }} 59 | 60 | {% if not samba_load_printers %} 61 | # Don't load printers 62 | load printers = no 63 | printing = bsd 64 | printcap name = /dev/null 65 | disable spoolss = yes 66 | {% else %} 67 | load printers = yes 68 | printing = {{ samba_printer_type }} 69 | printcap name = {{ samba_printer_type }} 70 | {% if samba_printer_type == 'cups' %} 71 | cups server = {{ samba_cups_server }} 72 | {% endif %} 73 | {% endif %} 74 | 75 | {% if samba_mitigate_cve_2017_7494 and samba_version.stdout >= "3.5.0" and samba_version.stdout < "4.6.4" %} 76 | # Fix for CVE-2017-7494 in Samba versions from 3.5.0 and before 4.6.4 77 | # https://access.redhat.com/security/cve/cve-2017-7494 78 | nt pipe support = no 79 | {% endif %} 80 | 81 | {% if samba_global_include is defined %} 82 | include = {{ samba_configuration_dir }}/{{ samba_global_include }} 83 | {% endif %} 84 | 85 | {% if samba_load_homes %} 86 | ## Make home directories accessible 87 | [homes] 88 | comment = Home Directories 89 | browseable = no 90 | writable = yes 91 | {% endif %} 92 | 93 | {% if samba_homes_include is defined %} 94 | include = {{ samba_configuration_dir }}/{{ samba_homes_include }} 95 | {% endif %} 96 | 97 | {% if samba_shares|length > 0 %} 98 | ## Shared directories 99 | {% for share in samba_shares %} 100 | [{{ share.name }}] 101 | {% if share.comment is defined %} 102 | comment = {{ share.comment }} 103 | {% endif %} 104 | {% if share.vfs_objects is defined and share.vfs_objects|length > 0 %} 105 | vfs objects = {% for obj in share.vfs_objects %}{{obj.name}} {% endfor %} 106 | 107 | {% for obj in share.vfs_objects %} 108 | {% if obj.options is defined %} 109 | {% if obj.options|length > 0 %} 110 | {% for opt in obj.options %} 111 | {{ obj.name }}:{{ opt.name }} = {{ opt.value }} 112 | {% endfor %} 113 | {% endif %} 114 | {% endif %} 115 | {% endfor %}{% endif %} 116 | path = {{ share.path|default([samba_shares_root,share.name]|join('/')) }} 117 | public = {{ share.public|default('no') }} 118 | {% if share.valid_users is defined %} 119 | valid users= {{ share.valid_users }} 120 | {% endif %} 121 | {% if share.write_list is defined %} 122 | write list = {{ share.write_list }} 123 | {% endif %} 124 | {% if share.group is defined %} 125 | force group = {{ share.group }} 126 | {% endif %} 127 | {% if share.guest_ok is defined %} 128 | guest ok = {{ share.guest_ok }} 129 | {% endif %} 130 | {% if share.browseable is defined %} 131 | browseable = {{ share.browseable }} 132 | {% endif %} 133 | {% if share.writable is defined %} 134 | writable = {{ share.writable }} 135 | {% endif %} 136 | create mode = {{ share.create_mode|default('0664') }} 137 | force create mode = {{ share.force_create_mode|default('0664') }} 138 | directory mode = {{ share.directory_mode|default('0775') }} 139 | force directory mode = {{ share.force_directory_mode|default('0775') }} 140 | {% if share.include_file is defined %} 141 | include = {{ samba_configuration_dir }}/{{ share.include_file }} 142 | {% endif %} 143 | 144 | {% endfor %} 145 | {% endif%} 146 | 147 | -------------------------------------------------------------------------------- /templates/smbusers.j2: -------------------------------------------------------------------------------- 1 | {% for entry in samba_username_map %} 2 | {{ entry.to }} = {{ entry.from }} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /vars/os_Archlinux.yml: -------------------------------------------------------------------------------- 1 | # roles/samba/vars/os_Archlinux.yml 2 | --- 3 | 4 | samba_packages: 5 | - samba 6 | - smbclient 7 | 8 | samba_vfs_packages: [] 9 | 10 | samba_selinux_packages: [] 11 | samba_selinux_booleans: [] 12 | 13 | samba_configuration_dir: /etc/samba 14 | samba_configuration: "{{ samba_configuration_dir }}/smb.conf" 15 | samba_username_map_file: "{{ samba_configuration_dir }}/smbusers" 16 | 17 | samba_services: 18 | - smbd 19 | - nmbd 20 | 21 | samba_www_documentroot: /var/www 22 | -------------------------------------------------------------------------------- /vars/os_Debian.yml: -------------------------------------------------------------------------------- 1 | # roles/samba/vars/os_Debian.yml 2 | --- 3 | 4 | samba_packages: 5 | - samba-common 6 | - samba 7 | - samba-client 8 | 9 | samba_vfs_packages: 10 | - samba-vfs-modules 11 | 12 | samba_selinux_packages: [] 13 | samba_selinux_booleans: [] 14 | 15 | samba_configuration_dir: /etc/samba 16 | samba_configuration: "{{ samba_configuration_dir }}/smb.conf" 17 | samba_username_map_file: "{{ samba_configuration_dir }}/smbusers" 18 | 19 | # The name of the Samba service in older releases (Ubuntu 14.04, 20 | # Debian <8) is "samba". 21 | samba_services: 22 | - smbd 23 | - nmbd 24 | 25 | samba_www_documentroot: /var/www 26 | -------------------------------------------------------------------------------- /vars/os_RedHat.yml: -------------------------------------------------------------------------------- 1 | # roles/samba/vars/os_RedHat.yml 2 | --- 3 | 4 | samba_packages: 5 | - samba-common 6 | - samba 7 | - samba-client 8 | 9 | samba_vfs_packages: [] 10 | 11 | samba_selinux_packages: 12 | - libsemanage-python 13 | 14 | samba_selinux_booleans: 15 | - samba_enable_home_dirs 16 | - samba_export_all_rw 17 | 18 | samba_configuration_dir: /etc/samba 19 | samba_configuration: "{{ samba_configuration_dir }}/smb.conf" 20 | samba_username_map_file: "{{ samba_configuration_dir }}/smbusers" 21 | 22 | samba_services: 23 | - smb 24 | - nmb 25 | 26 | samba_www_documentroot: /var/www/html 27 | --------------------------------------------------------------------------------