Giter Club home page Giter Club logo

ansible-ssh-hardening's Introduction

ssh-hardening (Ansible Role)

Attention: This role has been migrated to our hardening-collection:

Please open any issues and pull requests there!

Requirements

  • Ansible > 2.5

Role Variables

  • network_ipv6_enable
    • Default: false
    • Description: true if IPv6 is needed. ssh_listen_to must also be set to listen to IPv6 addresses (for example [::]).
  • ssh_server_ports
    • Default: ['22']
    • Description: ports on which ssh-server should listen
  • ssh_client_port
    • Default: '22'
    • Description: port to which ssh-client should connect
  • ssh_listen_to
    • Default: ['0.0.0.0']
    • Description: one or more ip addresses, to which ssh-server should listen to. Default is all IPv4 adresses, but should be configured to specific addresses for security reasons!
  • ssh_host_key_files
    • Default: []
    • Description: Host keys for sshd. If empty ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key'] will be used, as far as supported by the installed sshd version
  • ssh_host_key_algorithms
    • Default: []
    • Description: Host key algorithms that the server offers. If empty the default list will be used, otherwise overrides the setting with specified list of algorithms
  • ssh_client_alive_interval
    • Default: 600
    • Description: specifies an interval for sending keepalive messages
  • ssh_client_alive_count
    • Default: 3
    • Description: defines how often keep-alive messages are sent
  • ssh_permit_tunnel
    • Default: false
    • Description: true if SSH Port Tunneling is required
  • ssh_remote_hosts
    • Default: []
    • Description: one or more hosts and their custom options for the ssh-client. Default is empty. See examples in defaults/main.yml.
  • ssh_permit_root_login
    • Default: no
    • Description: Disable root-login. Set to without-password or yes to enable root-login
  • ssh_allow_tcp_forwarding
    • Default: no
    • Description: 'no' to disable TCP Forwarding. Set to 'yes' to allow TCP Forwarding. If you are using OpenSSH >= 6.2 version, you can specify 'yes', 'no', 'all' or 'local'.
      Note: values passed to this variable must be strings, thus values 'yes' and 'no' should be passed with quotes.
  • ssh_gateway_ports
    • Default: false
    • Description: false to disable binding forwarded ports to non-loopback addresses. Set to true to force binding on wildcard address. Set to clientspecified to allow the client to specify which address to bind to.
  • ssh_allow_agent_forwarding
    • Default: false
    • Description: false to disable Agent Forwarding. Set to true to allow Agent Forwarding.
  • ssh_x11_forwarding
    • Default: false
    • Description: false to disable X11 Forwarding. Set to true to allow X11 Forwarding.
  • ssh_pam_support
    • Default: true
    • Description: true if SSH has PAM support.
  • ssh_use_pam
    • Default: true
    • Description: false to disable pam authentication.
  • ssh_gssapi_support
    • Default: false
    • Description: true if SSH has GSSAPI support.
  • ssh_kerberos_support
    • Default: true
    • Description: true if SSH has Kerberos support.
  • ssh_deny_users
    • Default: ''
    • Description: if specified, login is disallowed for user names that match one of the patterns.
  • ssh_allow_users
    • Default: ''
    • Description: if specified, login is allowed only for user names that match one of the patterns.
  • ssh_deny_groups
    • Default: ''
    • Description: if specified, login is disallowed for users whose primary group or supplementary group list matches one of the patterns.
  • ssh_allow_groups
    • Default: ''
    • Description: if specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns.
  • ssh_authorized_keys_file
    • Default: ''
    • Description: change default file that contains the public keys that can be used for user authentication.
  • ssh_trusted_user_ca_keys_file
    • Default: ''
    • Description: specifies the file containing trusted certificate authorities public keys used to sign user certificates.
  • ssh_trusted_user_ca_keys
    • Default: []
    • Description: set the trusted certificate authorities public keys used to sign user certificates. Only used if ssh_trusted_user_ca_keys_file is set.
  • ssh_authorized_principals_file
    • Default: ''
    • Description: specifies the file containing principals that are allowed. Only used if ssh_trusted_user_ca_keys_file is set.
  • ssh_authorized_principals
    • Default: []
    • Description: list of hashes containing file paths and authorized principals, see default_custom.yml for all options. Only used if ssh_authorized_principals_file is set.
  • ssh_print_motd
    • Default: false
    • Description: false to disable printing of the MOTD
  • ssh_print_pam_motd
    • Default: false
    • Description: false to disable printing of the MOTD via pam (Debian and Ubuntu)
  • ssh_print_last_log
    • Default: false
    • Description: false to disable display of last login information
  • sftp_enabled
    • Default: false
    • Description: true to enable sftp configuration
  • sftp_umask
    • Default: '0027'
    • Description: Specifies the umask for sftp
  • sftp_chroot
    • Default: true
    • Description: false to disable chroot for sftp
  • sftp_chroot_dir
    • Default: /home/%u
    • Description: change default sftp chroot location
  • ssh_client_roaming
    • Default: false
    • Description: enable experimental client roaming
  • sshd_moduli_file
    • Default: '/etc/ssh/moduli'
    • Description: path to the SSH moduli file
  • sshd_moduli_minimum
    • Default: 2048
    • Description: remove Diffie-Hellman parameters smaller than the defined size to mitigate logjam
  • ssh_challengeresponseauthentication
    • Default: false
    • Description: Specifies whether challenge-response authentication is allowed (e.g. via PAM)
  • ssh_client_password_login
    • Default: false
    • Description: true to allow password-based authentication with the ssh client
  • ssh_server_password_login
    • Default: false
    • Description: true to allow password-based authentication with the ssh server
  • ssh_banner
    • Default: false
    • Description: true to print a banner on login
  • ssh_banner_path
    • Default: '/etc/sshd/banner.txt'
    • Description: path to the SSH banner file
  • ssh_client_hardening
    • Default: true
    • Description: false to stop harden the client
  • ssh_client_port
    • Default: '22'
    • Description: Specifies the port number to connect on the remote host.
  • ssh_client_compression
    • Default: false
    • Description: Specifies whether the client requests compression.
  • ssh_compression
    • Default: false
    • Description: Specifies whether server-side compression is enabled after the user has authenticated successfully.
  • ssh_login_grace_time
    • Default: 30s
    • Description: specifies the time allowed for successful authentication to the SSH server
  • ssh_max_auth_retries
    • Default: 2
    • Description: Specifies the maximum number of authentication attempts permitted per connection.
  • ssh_max_sessions
    • Default: 10
    • Description: Specifies the maximum number of open sessions permitted from a given connection.
  • ssh_print_debian_banner
    • Default: false
    • Description: true to print debian specific banner
  • ssh_server_enabled
    • Default: true
    • Description: false to disable the opensshd server
  • ssh_server_hardening
    • Default: true
    • Description: false to stop harden the server
  • ssh_server_match_address
    • Default: ''
    • Description: Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file.
  • ssh_server_match_group
    • Default: ''
    • Description: Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file.
  • ssh_server_match_user
    • Default: ''
    • Description: Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file.
  • ssh_server_match_local_port
    • Default: ''
    • Description: Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file.
  • ssh_server_permit_environment_vars
    • Default: no
    • Description: yes to specify that ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd. With openssh version 7.8 it is possible to specify a whitelist of environment variable names in addition to global "yes" or "no" settings
  • ssh_server_accept_env_vars
    • Default: ''
    • Description: Specifies what environment variables sent by the client will be copied into the session's environment, multiple environment variables may be separated by whitespace
  • ssh_use_dns
    • Default: false
    • Description: Specifies whether sshd should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address.
  • ssh_server_revoked_keys
    • Default: []
    • Description: a list of revoked public keys that the ssh server will always reject, useful to revoke known weak or compromised keys.
  • ssh_max_startups
    • Default: '10:30:100'
    • Description: Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon.
  • ssh_macs
    • Default: []
    • Description: Change this list to overwrite macs. Defaults found in defaults/main.yml
  • ssh_kex
    • Default: []
    • Description: Change this list to overwrite kexs. Defaults found in defaults/main.yml
  • ssh_ciphers
    • Default: []
    • Description: Change this list to overwrite ciphers. Defaults found in defaults/main.yml
  • ssh_custom_options
    • Default: []
    • Description: Custom lines for SSH client configuration
  • sshd_custom_options
    • Default: []
    • Description: Custom lines for SSH daemon configuration
  • sshd_syslog_facility
    • Default: 'AUTH'
    • Description: The facility code that is used when logging messages from sshd
  • sshd_log_level
    • Default: 'VERBOSE'
    • Description: the verbosity level that is used when logging messages from sshd
  • sshd_strict_modes
    • Default: true
    • Description: Check file modes and ownership of the user's files and home directory before accepting login
  • sshd_authenticationmethods
    • Default: publickey
    • Description: Specifies the authentication methods that must be successfully completed for a user to be granted access. Make sure to set all required variables for your selected authentication method. Defaults found in defaults/main.yml

Configuring settings not listed in role-variables

If you want to configure ssh options that are not listed above, you can use ssh_custom_options (for /etc/ssh/ssh_config) or sshd_custom_options (for /etc/ssh/sshd_config) to set them. These options will be set on the beginning of the file so you can override options further down in the file.

Example playbook:

- hosts: localhost
  roles:
    - dev-sec.ssh-hardening
  vars:
    ssh_custom_options:
      - "Include /etc/ssh/ssh_config.d/*"
    sshd_custom_options:
      - "AcceptEnv LANG"

Changing the default port and idempotency

This role uses the default port 22 or the port configured in the inventory to connect to the server. If the default ssh port is changed via ssh_server_ports, once the ssh server is restarted, it will still try to connect using the previous port. In order to run this role again on the same server the inventory will have to be updated to use the new ssh port.

If idempotency is important, please consider using role ssh-hardening-fallback, which is a wrapper around this role that falls back to port 22 if the configured port is unreachable.

Example Playbook

- hosts: localhost
  roles:
    - dev-sec.ssh-hardening

Local Testing

The preferred way of locally testing the role is to use Docker. You will have to install Docker on your system. See Get started for a Docker package suitable to for your system.

You can also use vagrant and Virtualbox or VMWare to run tests locally. You will have to install Virtualbox and Vagrant on your system. See Vagrant Downloads for a vagrant package suitable for your system. For all our tests we use test-kitchen. If you are not familiar with test-kitchen please have a look at their guide.

Next install test-kitchen:

# Install dependencies
gem install bundler
bundle install

Testing with Docker

# fast test on one machine
bundle exec kitchen test ssh-ubuntu1804-ansible-latest

# test on all machines
bundle exec kitchen test

# for development
bundle exec kitchen create ssh-ubuntu1804-ansible-latest
bundle exec kitchen converge ssh-ubuntu1804-ansible-latest
bundle exec kitchen verify ssh-ubuntu1804-ansible-latest

# cleanup
bundle exec kitchen destroy ssh-ubuntu1804-ansible-latest

Testing with Virtualbox

# fast test on one machine
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test ssh-ubuntu-1804

# test on all machines
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test

# for development
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen create ssh-ubuntu-1804
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen converge ssh-ubuntu-1804

For more information see test-kitchen

FAQ / Pitfalls

I can't log into my account. I have registered the client key, but it still doesn't let me it.

If you have exhausted all typical issues (firewall, network, key missing, wrong key, account disabled etc.), it may be that your account is locked. The quickest way to find out is to look at the password hash for your user:

sudo grep myuser /etc/shadow

If the hash includes an !, your account is locked:

myuser:!:16280:7:60:7:::

The proper way to solve this is to unlock the account (passwd -u myuser). If the user doesn't have a password, you should can unlock it via:

usermod -p "*" myuser

Alternatively, if you intend to use PAM, you enabled it via ssh_use_pam: true. PAM will allow locked users to get in with keys.

Why doesn't my application connect via SSH anymore?

Always look into log files first and if possible look at the negotiation between client and server that is completed when connecting.

We have seen some issues in applications (based on python and ruby) that are due to their use of an outdated crypto set. This collides with this hardening module, which reduced the list of ciphers, message authentication codes (MACs) and key exchange (KEX) algorithms to a more secure selection.

After using the role Ansibles template/copy/file module does not work anymore!

This role by default deactivates SFTP. Ansible uses by default SFTP to transfer files to the remote hosts. You have to set scp_if_ssh = True in your ansible.cfg. This way Ansible uses SCP to copy files. Alternatively you can enable SFTP again by setting sftp_enabled to true.

Cannot restart sshd-service due to lack of privileges

If you get the following error when running handler "restart sshd"

Unable to restart service ssh: Failed to restart ssh.service: Access denied

or

failure 1 running systemctl show for 'ssh': Failed to connect to bus: No such file or directory

either run the playbook as root (without become: yes at the playbook level), or add become: yes to the handler.

This is a bug with Ansible: see here and here for more information.

Contributing

See contributor guideline.

License and Author

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

ansible-ssh-hardening's People

Contributors

ageis avatar aisbergg avatar alexclear avatar aqw avatar atomic111 avatar bentoumitech avatar chris-rock avatar conorsch avatar dennisse avatar djesionek avatar fazlearefin avatar fitz123 avatar foonix avatar ftaeger avatar fullyint avatar jaredledvina avatar jbenden avatar jbronn avatar jcheroske avatar kljensen avatar lazzurs avatar lunarthegrey avatar matthiaslohr avatar rndmh3ro avatar schurzi avatar slamdunk avatar szevez avatar techraf avatar tsenart avatar ypid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ansible-ssh-hardening's Issues

SELinux-specific task still runs on SELinux-disabled systems

The last task in tasks/main.yml, "remove selinux-policy when Pam is used, because Allowing sshd to read the shadow file directly is considered a potential security risk (http://danwalsh.livejournal.com/12333.html)" will run on systems with SELinux disabled.

Looks like the when: test only tests the return code of getenforce. Previous tasks in this file test both the getenforce return code and stdout.

I've forked this repo and updated the when: test so that it also tests getenforce output. But I feel like the standard output of getenforce should be deciding factor for whether to run SELinux-specific tasks. If getenforce fails, that's a deeper problem and the whole role should probably fail, too. That would simplify the when: clauses of several other tasks in tasks/main.yml. Thoughts?

Fail at TASK [remove selinux-policy when Pam is used...] when ssh_use_pam: true

TASK [ansible-ssh-hardening : remove selinux-policy when Pam is used, because Allowing sshd to read the shadow file directly is considered a potential security risk (http://danwalsh.livejournal.com/12333.html)] ***
task path: /home/felis/ansible/roles/ansible-ssh-hardening/tasks/main.yml:50
fatal: [localhost: FAILED! => {"changed": true, "cmd": "semodule -r ssh_password", "delta": "0:00:02.974666", "end": "2016-02-27 13:19:42.302047", "failed": true, "rc": 1, "start": "2016-0

If ssh_use_pam: true, ssh_password selinux policy doesn't get installed. semodule -r ssh_password will then fail.

GlobalKnownHostsFile missing from ssh_config

It would be great if this role took in a list variable containing host keys and constructed the /etc/ssh/known_hosts file. The GlobalKnownHostsFile configuration parameter would also need to be set in ssh_config.

Thank you for an awesome tool!

ssh_ports - individual client/server config

Hi there,

first of all thank you very much for your ansible role.

May I suggest splitting the variable ssh_ports into 2 separate variables to distinguish client/server ports individually? In my use case I don't want sshd accessible on port 22, but I don't want to change ssh client-config.

cheers

Sebastian

UseLogin is deprecated on CentOS 7

On CentOS 7 the option UseLogin no produces the following depecation warning on each ssh login:

rexec line 69: Deprecated option UseLogin

Root permissions required for ssh_config and sshd_config files

Hi

To update ssh/sshd config you need to have root permissions. Previously I was using sudo: true in my playbook. According to Ansible, it will be removed in 2.6.

DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and
make sure become_method is 'sudo' (default). This feature will be removed in
version 2.6. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.

Without sudo I am getting below error:

TASK [dev-sec.ssh-hardening : create sshd_config and set permissions to root/600] ***
fatal: [gateway]: FAILED! => {"changed": false, "checksum": "60fb9f3fcee48310b83298e657fe10a1c06406f0", "failed": true, "msg": "Destination /etc/ssh not writable"}

I have created a small PR -> #144

Options not compatible with OpenSSH server 7.6

sshd[18263]: /etc/ssh/sshd_config line 73: Deprecated option UsePrivilegeSeparation

Sandboxing is now enabled by default in OpenSSH, across all platforms/distros. See the changelog.

Likewise, these two options for the client config are not understood in recent versions of OpenSSH

 HostsRSAAuthentication no                                                                                  
 RSAAuthentication yes

@chris-rock, @atomic111 @mms-segu you guys still interested in maintaining this stuff? I will join and help out.

semodule ssh_password error on AWS Centos 7

Hello - I'm seeing the error below and I'm not sure if I'm doing something wrong or if this is a bug. The server is the official Centos7 image on AWS. The error is observed when running ansible-playbook with --check.

Running the following on the server (which appears to be part of the problem) shows no output.

semodule -l | grep "ssh_password" | awk '{print $3}'

These are the module names I see with the string ssh:

semodule -l | grep "ssh"

rssh 2.3.0
ssh 2.4.2

Thanks!

Error:
fatal: [server1]: FAILED! => {"failed": true, "msg": "The conditional check 'sestatus.rc == 0 and sestatus.stdout != 'Disabled'' failed. The error was: error while evaluating conditional (sestatus.rc == 0 and sestatus.stdout != 'Disabled'): 'dict object' has no attribute 'rc'\n\nThe error appears to have been in '/Users/user1/RRS GDrive/Projects/corp1/repos/corp1-ansible/roles/hardening.ssh-hardening/tasks/main.yml': line 11, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: check the ssh_password policy state\n ^ here\n"}

UsePAM should probably default to yes on Red Hat Linux 7

From the sshd_config file on a CentOS 7 box:

# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
# problems.

As such, it's probably a good idea to default ssh_use_pam to true on RedHat 7.

This warning isn't in the CentOS 6 sshd_config file, but there is an article in the Red Hat 6 knowledgebase about not being able to SSH into a system if UsePAM is off and SELinux is on. I don't have an account and can't see the solution, though, so there might be a way to deal with that.

See also dev-sec/puppet-ssh-hardening#53 and dev-sec/chef-ssh-hardening#96.

opensshd.conf.j2 template type error

TASK [dev-sec.ssh-hardening : create sshd_config and set permissions to root/600] ************
task path: /home/snoopy/ansible/roles/dev-sec.ssh-hardening/tasks/main.yml:25
fatal: [woodstock]: FAILED! => {
    "changed": false, 
    "msg": "AnsibleError: Unexpected templating type error occurred on (
...
Content of templates/opensshd.conf.j2
...
): 'int' object is not iterable"
}

Copy module works.

CentOS 7 selinux dependencies

Hello,
When running this role on a CentOS 7 I get the following errors:

TASK [dev-sec.ssh-hardening : check and compile policy] ************************
fatal: [192.168.77.10]: FAILED! => {"changed": true, "cmd": "checkmodule -M -m -o /etc/selinux/local-policies/ssh_password.mod /etc/selinux/local-policies/ssh_password", "delta": "0:00:00.002428", "end": "2016-10-10 11:48:41.962335", "failed": true, "rc": 127, "start": "2016-10-10 11:48:41.959907", "stderr": "/bin/sh: checkmodule: command not found", "stdout": "", "stdout_lines": [], "warnings": []}

Then I've installed the checkpolicy package and had this error:

TASK [dev-sec.ssh-hardening : create selinux policy module package] ************
fatal: [192.168.77.10]: FAILED! => {"changed": true, "cmd": "semodule_package -o /etc/selinux/local-policies/ssh_password.pp -m /etc/selinux/local-policies/ssh_password.mod", "delta": "0:00:00.002294", "end": "2016-10-10 11:50:04.572800", "failed": true, "rc": 127, "start": "2016-10-10 11:50:04.570506", "stderr": "/bin/sh: semodule_package: command not found", "stdout": "", "stdout_lines": [], "warnings": []}

Resolved by installing policycoreutils-python package.
Then the role applied correctly.

Should the ansible role manage its dependencies?
Romain

`ssh_server_ports` a bit misleading in the vars section?

ssh_ports: ['22'] in the main README did not work to change the SSH port from the default 22 for me. In the end I followed the trail backwards and ended up at ssh_server_ports: ['1234'] variable.

Is this a mistake? ssh_ports vs ssh_server_ports and ssh_client_ports? I couldn't find anywhere that combined the two?

ssh_use_dns used twice in defaults/main.yml

Thanks for your great work!

I noticed a minor issue in defaults/main.yml:

[WARNING]: While constructing a mapping from /home/me/ansible-priv/provisioning/roles/dev-sec.ssh-hardening/defaults/main.yml, line 2, column 1, found a duplicate dict key (ssh_use_dns). Using last defined value only.

ssh_use_dns is indeed defined on both line 8 and 179 of defaults/main.yml

Too much of a n00b to tell if it makes sense to keep the first or the last one, sorry...

User login failed after running this module

Problem: this module stops one new user from logging in, but not the default ubuntu vagrant user.

I've set up the user/playbook like so:

  - role: dev-sec.os-hardening
  #- role: dev-sec.ssh-hardening
  #  sftp_enabled: true
  - role: sansible.users_and_groups
    users_and_groups:
      authorized_keys_dir: /etc/ssh/authorized_keys
      groups:
      - name: sftp-only
      users:
      - name: myuser
        groups:
        - sftp-only
        home: /home/myuser
        ssh_key: ./myuser.pub

If I comment in this module in the above playbook, I get this error in /var/log/auth.log:

May 23 18:05:21 ubuntu-xenial sshd[26236]: Connection from 10.0.2.2 port 59156 on 10.0.2.15 port 22
May 23 18:05:21 ubuntu-xenial sshd[26236]: User myuser not allowed because account is locked
May 23 18:05:21 ubuntu-xenial sshd[26236]: input_userauth_request: invalid user myuser [preauth]
May 23 18:05:21 ubuntu-xenial sshd[26236]: error: maximum authentication attempts exceeded for invalid user myuser from 10.0.2.2 port 59156 ssh2 [preauth]
May 23 18:05:21 ubuntu-xenial sshd[26236]: Disconnecting: Too many authentication failures [preauth]
May 23 18:05:31 ubuntu-xenial su[22231]: pam_unix(su:session): session closed for user myuser

It's running on xenial64, the 16.04 LTS of Ubuntu.

Provisioning the node without this module makes it possible access both SSH and SFTP with the newly created user.

System completely unresponsive after role execution

The role/playbook executes without any sign of error.

However after the execution the remote system behaves as follows:

  • it is not possible login via SSH (timeout).
  • ping requests produce timeouts
  • custom services (e.g. NodeJS apps behind nginx) seem to load but run into timeouts
    Overall it seems that system is not able to process any incoming requests.

I could only make the server respond to anything be rebooting it. However, after a few minutes it is unresponsive again.

At first I thought it was related to the sshd config but now I´m unsure what´s causing these issues. It might even be caused by https://github.com/dev-sec/ansible-os-hardening which was also applied.

Any ideas what is happening in this case?
Do you need any additional information?

Install from ansible galaxy missing files (tasks)

If you install with ansible-galaxy:

ansible-galaxy install hardening.ssh-hardening

You will see that the tasks folder for example is missing:

afreitas@artemis:/etc/ansible/roles/hardening.ssh-hardening
> ls -lha
total 88
drwxr-xr-x  15 afreitas  wheel   510B Jan 27 12:48 .
drwxrwxrwx   4 root      wheel   136B Jan 27 12:48 ..
-rw-rw-r--   1 afreitas  wheel   152B Apr 30  2015 .gitignore
-rw-rw-r--   1 afreitas  wheel   1.3K Apr 30  2015 .kitchen.yml
-rw-rw-r--   1 afreitas  wheel   813B Apr 30  2015 .kitchen_debian.yml
-rw-rw-r--   1 afreitas  wheel   434B Apr 30  2015 .travis.yml
-rw-rw-r--   1 afreitas  wheel   520B Apr 30  2015 CHANGELOG.md
-rw-rw-r--   1 afreitas  wheel   3.8K Apr 30  2015 CONTRIBUTING.md
-rw-rw-r--   1 afreitas  wheel   450B Apr 30  2015 Gemfile
-rw-rw-r--   1 afreitas  wheel   6.9K Apr 30  2015 README.md
-rw-rw-r--   1 afreitas  wheel   194B Apr 30  2015 Thorfile
-rw-rw-r--   1 afreitas  wheel    34B Apr 30  2015 ansible-install.sh
drwxr-xr-x   4 afreitas  wheel   136B Jan 27 12:48 meta
drwxr-xr-x   3 afreitas  wheel   102B Jan 27 12:48 roles
drwxr-xr-x   3 afreitas  wheel   102B Jan 27 12:48 spec
(.env)

Selinux issue

Hello,
When I have ssh_use_pam=true the role fails on:

TASK [dev-sec.ssh-hardening : remove selinux-policy when Pam is used, because Allowing sshd to read the shadow file directly is considered a potential security risk (http://danwalsh.livejournal.com/12333.html)] ***
fatal: [gitana-ext.magellium.com]: FAILED! => {"changed": true, "cmd": "semodule -r ssh_password", "delta": "0:00:02.809950", "end": "2016-10-10 16:42:34.105591", "failed": true, "rc": 1, "start": "2016-10-10 16:42:31.295641", "stderr": "libsemanage.get_module_file_by_name: Module ssh_password was not found.\nsemodule:  Failed on ssh_password!", "stdout": "", "stdout_lines": [], "warnings": []}

(except if I have run the playbook before withe ssh_use_pam=false).
Maybe you could check if the module is installed before trying to remove it?
Thanks.
PS: the 3.1 release is not on ansible galaxy

Question --> ssh_allow_users -- Should allow specific logins ?

Hi ,

First off , thank you for creating this project and making securing the machines that much easier.

I've one issue though. For a single specific machine I'd like to enable normal ssh login for a specific username.
I thought adding that user to the ssh_allow_users in the defaults would permit it but I'm still seeing the permission denied although I can view the /sshd_config which contains the entry.

I'm just wondering what else is required to be done to enable this behaviour ?

coreos support?

Curious whether there's any interest in supporting coreos?

sftp_enabled: false will break Ansible's template module

The Ansible's template module relies on sftp to work. I wanted to suggest to set sftp_enabled: true as default, but that would go against the point of the playbook.
Maybe add a little warning to the user?
And maybe a way to not depend on the template module if sftp is disabled. This will help if the user decides to re-enable sftp or update the sshd_config

The role fails when conditionally included

Hi,

I need to use your role only on specific environments so I'm using a when instruction in my role statement in my playbook like below to choose whether or not I want to deploy security rules :

roles: 
    - { role: security, when: deploy_security_rules }

Then in the task file of my "security" role I use the statements below to include your role

- name: OS hardening
  include_role:
    name: dev-sec.os-hardening

The problem occurs when I don't want to deploy security rules, i.e when deploy_security_rules = false

Here is the output I obtain during failure :

TASK [dev-sec.os-hardening : get all system accounts] **************************
[DEPRECATION WARNING]: always_run is deprecated. Use check_mode = no instead..

This feature will be removed in version 2.4. Deprecation warnings can be 
disabled by setting deprecation_warnings=False in ansible.cfg.
skipping: [vagrant-debian8.6] => {"changed": false, "skip_reason": "Conditional check failed", "skipped": true}

TASK [dev-sec.os-hardening : remove always ignored system accounts from list] **
skipping: [vagrant-debian8.6] => {"changed": false, "skip_reason": "Conditional check failed", "skipped": true}

TASK [dev-sec.os-hardening : change system accounts not on the user provided ignore-list] ***
fatal: [vagrant-debian8.6]: FAILED! => {"failed": true, "msg": "'sys_accs_cond' is undefined"}

Any idea why the role is failing ?

ssh_password is never installed

I tried to find info about the selinux module ssh_password (https://www.google.com/search?q="ssh_password"+selinux) and I didn't find anything unrelated to this ansible role, so I'm assuming is a custom module and the definition of it is the file: https://github.com/dev-sec/ansible-ssh-hardening/blob/master/files/ssh_password

What I don't understand is that in the role, the first mention to it is to check if it's installed. But there isn't any task to install previous to that, and also this role doesn't have any other role as a dependency.

So what I'm trying to understand is if this is an error and there should be a task installing the module first or I'm missing something.

Running test-kitchen fails

I receive the following error during test-kitchen run:

kitchen test default-ubuntu-1204
-----> Starting Kitchen (v1.3.1)
-----> Cleaning up any prior instances of <default-ubuntu-1204>
-----> Destroying <default-ubuntu-1204>...
       Finished destroying <default-ubuntu-1204> (0m0.00s).
-----> Testing <default-ubuntu-1204>
-----> Creating <default-ubuntu-1204>...
>>>>>> Create failed on instance <default-ubuntu-1204>.
>>>>>> Please see .kitchen/logs/default-ubuntu-1204.log for more details
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: Could not find Vagrantfile template /Users/chris/Development/hardening/ansible/ansible-ssh-hardening/Vagrantfile.erb
>>>>>> ----------------------

Is SFTP supported or not supported?

Hello!

First thanks for your great role, which I'm happy to use 😄

I have a setup hardened with this role where I also need to add some form of SFTP access, and I'm confused a bit and unsure if it's supported or not.

In the FAQ, one can read:

This role deactivates SFTP

But at the same time, there is an option to enable SFTP:

sftp_enabled - false - true to enable sftp configuration

Can you clarify if SFTP is supported? (I'd say yes, based on reading the tasks, but I'd rather be sure here).

Thank you!

Deprecation warning always_run

always_run is deprecated. Use check_mode = no instead..

TASK [ansible-ssh-hardening : test to see if selinux is running] ***************
[DEPRECATION WARNING]: always_run is deprecated. Use check_mode = no instead..
This feature will be removed in version 2.4. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.

Should compression be opt-in?

According to this thread, compression can be vulnerable to CRIME/BREACH attacks (if the encrypted data carries public data as well).

I am not into crypto but I guess compression should be opt-in, at least, shouldn't it?

Running the tests locally

Perhaps I'm missing something obvious, but I'm unable to run the inspec test suites locally with virtualbox hosts. Creating and converging is fine, but the inspec tests are skipped altogether:

undle exec kitchen verify debian-8
-----> Starting Kitchen (v1.5.0)
-----> Verifying <ansible-19-debian-8>...


Finished in 0.00025 seconds (files took 0.95551 seconds to load)
0 examples, 0 failures

       Finished verifying <ansible-19-debian-8> (0m0.80s).
-----> Verifying <ansible-latest-debian-8>...


Finished in 0.00019 seconds (files took 1.51 seconds to load)
0 examples, 0 failures

       Finished verifying <ansible-latest-debian-8> (0m0.55s).
-----> Kitchen is finished. (0m1.75s)
zlib(finalizer): the stream was freed prematurely.
zlib(finalizer): the stream was freed prematurely.

This is likely a regression introduced by #56, since the integration suites are no longer called "default". Changing the test dir seems to fix it:

bundle exec kitchen verify ansible-latest-debian-8         
-----> Starting Kitchen (v1.5.0)
-----> Verifying <ansible-latest-debian-8>...
.................FFF..........FFF..............................................................

Possible solutions are renaming the inspec test directory, which I don't like, or adding a verifier parameter to the suite blocks to point to the appropriate tests (since the tests are shared across all versions of ansible).

role creates duplicate parameter/values after run

Hey guys, I've just run this issue with a very basic configuration and found duplicates in /etc/ssh/sshd_config afterwards. The relevant details:

The OS:

$ lsb_release -id
Distributor ID:	Debian
Description:	Debian GNU/Linux 8.8 (jessie)

The configuration:

- name: Configure sshd and restart                                                 
  hosts: web                                                                       
  user: bob                                                                     
  become: yes                                                                      
  roles:                                                                           
    - role: dev-sec.ssh-hardening                                                  
      ssh_port: 22                                                                 
      ssh_use_pam: true                                                            
      sftp_enabled: true                                                           
      network_ipv6_enable: false                                                   

Duplicates

sudo egrep -v '^(#|$)' /etc/ssh/sshd_config | sort | uniq -d
    
AllowAgentForwarding no
AllowTcpForwarding no
PasswordAuthentication no
PermitRootLogin no
X11Forwarding no

Workaround

As I intend to use sftp early in the process, I've commented the duplicate parameters outside of the if sftp_enabled block.

egrep '(AllowAgentForwarding|AllowTcpForwarding|PasswordAuthentication|PermitRootLogin|X11Forwarding)' templates/opensshd.conf.j2
#PermitRootLogin {{ 'without-password' if ssh_allow_root_with_key else 'no' }}
#PasswordAuthentication {{ 'yes' if ssh_server_password_login else 'no' }}
#AllowTcpForwarding {{ 'yes' if ssh_allow_tcp_forwarding else 'no' }}
#AllowAgentForwarding {{ 'yes' if ssh_allow_agent_forwarding else 'no' }}
#X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PasswordAuthentication no
PermitRootLogin no
X11Forwarding no

This is gross but it does eliminate the duplicates:

The ansible run output with -v has been included: ansible-sshd.txt

As always, I reserve the right to be completely in the wrong :-)

Please let me know if I've duffed it.

Changes in selinux section to avoid confusion and some inconsistencies

It would be great to made some small changes in the selinux section of this role to avoid confusion, as discussed in this PR: #102
The two changes I think should be made are:

Besides from that, I found two inconsistencies between what the comment says and the actual code:

  1. first one here: https://github.com/dev-sec/ansible-ssh-hardening/blob/master/tasks/main.yml#L86
    It says that "only runs when selinux is in state enforcing", but the conditional is sestatus.stdout != 'Disabled', so the task could also be executed when selinux is in Permissive mode.
    Does the task can be also executed in Permissive mode or is this an error?

  2. and the second one: https://github.com/dev-sec/ansible-ssh-hardening/blob/master/tasks/main.yml#L106
    It says the same from above: "only runs when selinux is in state enforcing" but there isn't any conditional related to selinux in the when: at the end, is this an error?

Can't connect to server by SSH after applying this role

I tried to apply the role to a server and after successful applying, I can't connect to a server by SSH. I read the FAQ and tried to change different settings, but it doesn't help. Server using Ubuntu 16.04.

SSH client log:

OpenSSH_7.4p1, LibreSSL 2.5.0
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to x.x.x.x [x.x.x.x] port 22.
debug1: Connection established.
debug1: identity file /xxx/.ssh/id_rsa type 1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /xxx/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_7.4
debug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1p1
debug1: match: OpenSSH_6.6.1p1 pat OpenSSH_6.6.1* compat 0x04000000
debug1: Authenticating to x.x.x.x:22 as 'artem'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: [email protected]
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: [email protected] MAC: <implicit> compression: none
debug1: kex: client->server cipher: [email protected] MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:TY3W4ZY8ysTNV33FH5gnJUQuNWjJ2zdc0M3nMo2rHbI
debug1: Host 'x.x.x.x' is known and matches the ECDSA host key.
debug1: Found key in /xxx/.ssh/known_hosts:32
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /xxx/.ssh/id_rsa
debug1: Authentications that can continue: publickey
debug1: Trying private key: /xxx/.ssh/id_dsa
debug1: Trying private key: /xxx/.ssh/id_ecdsa
debug1: Trying private key: /xxx/.ssh/id_ed25519
debug1: No more authentication methods to try.
Permission denied (publickey).

fails in --check mode

Hi and thanks for projects.

Running playbook with --check option was failed after update from 3.2 to 4.0 on task "dev-sec.ssh-hardening : set hostkeys according to openssh-version".

Adding "check_mode: no" to this task will fix this issue.

Some tasks are always run even if they are not needed

Hello,

It's not a major problem but it's usefull to really know what is changed when we execute a playbook and those task always return a 'changed' state:

TASK [dev-sec.ssh-hardening : check and compile policy] ************************
changed: [server]

TASK [dev-sec.ssh-hardening : create selinux policy module package] ************
changed: [server]

TASK [dev-sec.ssh-hardening : install selinux policy] **************************
changed: [server]

It would be nice if they weren't executed if don't needed or don't produce a changed state if not necessary.

Romain

get openssh-version fails on FreeBSD (with ansible 2.4.0.0)

Running the get openssh-version task fails on FreeBSD

TASK [dev-sec.ssh-hardening : get openssh-version] ************************************************************************************************************
fatal: [template201709]: FAILED! => {"changed": false, "cmd": "ssh -V 2>&1 | sed -r 's/.*_([0-9]*\\.[0-9]).*/\\1/g'", "delta": "0:00:00.061695", "end": "2017-10-09 08:25:00.292831", "failed": true, "msg": "non-zero return code", "rc": 1, "start": "2017-10-09 08:25:00.231136", "stderr": "Ambiguous output redirect.", "stderr_lines": ["Ambiguous output redirect."], "stdout": "", "stdout_lines": []}
    to retry, use: --limit @./template.retry

perhaps only since the upgrade to ansible 2.4.0.0

The problem appears to be, that tcsh is used as shell.

Move cipher/kex/mac vars to defaults

The vars/main.yml lists all whitelisted ciphers, MACs, and key exchange algorithms for sshd. Although the sshd template does a decent job of inferring appropriate settings from the distro and release version, invariably some administers will want to override these settings in typical Ansible fashion. Doing so is currently impossible.

Therefore I propose:

  • Folding the contents of vars/main.yml into defaults/main.yml
  • Prefixing the moved vars with ssh_ to help prevent accidental clobbering in site-wide configs

Since these vars cannot currently be overridden, there is no breaking change in adding the prefix—now's the best time for us to get away with it. Allowing local overrides would be more consistent with Ansible best practices, as well.

I'm happy to write a PR after any discussion here. Being able to override the vars at run time would make it a heck of a lot easier to test improvements for #28, as well—which is really why I bring it up. ;)

sftp Match Group settings overriding global sshd_config settings

Match Group sftponly
ForceCommand internal-sftp -l INFO -f LOCAL6
ChrootDirectory {{ sftp_chroot_dir }}
AllowTcpForwarding no
AllowAgentForwarding no
PasswordAuthentication no
PermitRootLogin no
X11Forwarding no

Lines 241-247 should be indented in order to apply to only the Match Group. Right now they are overriding the global settings higher up in the config file.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.