willshersystems / ansible-sshd

Ansible role to configure the OpenSSH server daemon
https://galaxy.ansible.com/willshersystems/sshd
GNU Lesser General Public License v3.0
244 stars 136 forks source link

Appending values to AcceptEnv while doing other changes #219

Closed skwde closed 1 year ago

skwde commented 1 year ago

How do I achieve the following 3 points in a single role run?

  1. generate the default config
  2. do some modifications, e.g. set PermitRootLogin no
  3. add a variable to AcceptEnv, e.g. add MY_VAR

The preferred solution is to get (for RHEL7)

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv MY_VAR
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
PasswordAuthentication yes
PermitRootLogin yes
Subsystem sftp /usr/libexec/openssh/sftp-server
SyslogFacility AUTHPRIV
UsePAM yes
UsePrivilegeSeparation sandbox
X11Forwarding yes

However this seems not possible within the current sshd role.

The only way I can think of is running the role twice which seems like overkill (takes twice the time), is generally not a really nice and also doesn't produce above config exactly.

The workaround looks something like

- name: Test
  hosts: localhost
  gather_facts: false
  roles:
    # - role: fedora.linux-system-roles.sshd
    - role: willshersystems.sshd
      become: true
      vars:
        sshd_skip_defaults: false
        sshd_main_config_file: '/home/user/src/tests//sshd_config_test'
        sshd_config_file: '/home/user/src/tests/sshd_config_test'
        sshd_config_owner: 'user'
        sshd_config_group: 'user'
        sshd_config_mode: '0600'
        sshd:
          PermitRootLogin: 'no'
          # AcceptEnv: 'MY_VAR'

    - role: willshersystems.sshd
      become: true
      vars:
        sshd_config_namespace: accept-env
        sshd_main_config_file: '/home/user/src/tests//sshd_config_test'
        sshd_config_file: '/home/user/src/tests/sshd_config_test'
        sshd_config_owner: 'user'
        sshd_config_group: 'user'
        sshd_config_mode: '0600'
        sshd:
          AcceptEnv: MY_VAR

Note, that I set non-default sshd_main_config_file, sshd_config_file, sshd_config_owner and sshd_config_group. for testing. Moreover I explicitly set sshd_config_mode to the default.

This generates two files(?!)

non of which contains default settings

The first one contains

# BEGIN sshd system role managed block: namespace accept-env
Match all
  AcceptEnv MY_VAR
# END sshd system role managed block: namespace accept-env

and the second one

# BEGIN sshd system role managed block: namespace accept-env
Match all
  PermitRootLogin no
# END sshd system role managed block: namespace accept-env

Am I missing something?

mattwillsher commented 1 year ago

Hi @skwde

Have you tried the approaches shown in the Example Playbooks section of the README? It should work in a single pass.

skwde commented 1 year ago

@mattwillsher thanks for your immediate response!

I updated my original post to reflect what I actually try. I am not even able to generate the workaround I mentioned which was previously based on my understanding of how it should work.

I am not quite sure what you mean. If I set sshd_config_namespace: accept-env all sshd stuff is put into a Match all block. Besides that, as mentioned in the variable description of sshd_skip_defaults "Defaults to false unless sshd_config_namespace is set".

In any case, if I run

- name: Test
  hosts: localhost
  gather_facts: false
  roles:
    # - role: fedora.linux-system-roles.sshd
    - role: willshersystems.sshd
      become: true
      vars:
        sshd_skip_defaults: false
        sshd_main_config_file: '/home/user/src/tests/sshd_config_test'
        sshd_config_file: '/home/user/src/tests/sshd_config_test'
        sshd_config_owner: 'user'
        sshd_config_group: 'user'
        sshd_config_mode: '0600'
        sshd:
          PermitRootLogin: 'no'
          AcceptEnv: 'MY_VAR'

I get

#
# Ansible managed
#
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
AcceptEnv MY_VAR
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
PasswordAuthentication yes
PermitRootLogin no
Subsystem sftp /usr/libexec/openssh/sftp-server
SyslogFacility AUTHPRIV
UsePAM yes
UsePrivilegeSeparation sandbox
X11Forwarding yes

If I just add sshd_config_namespace: accept-env I get an additional section

# BEGIN sshd system role managed block: namespace accept-env
Match all
  AcceptEnv MY_VAR
  PermitRootLogin no
# END sshd system role managed block: namespace accept-env

So what am I doing wrong?

skwde commented 1 year ago

The workaround I found is to use

- name: Test
  hosts: localhost
  gather_facts: false
  roles:
    # - role: fedora.linux-system-roles.sshd
    - role: willshersystems.sshd
      become: true
      vars:
        sshd_skip_defaults: false
        sshd_main_config_file: '/home/user/src/tests/sshd_config_test'
        sshd_config_file: '/home/user/src/tests/sshd_config_test'
        sshd_config_owner: 'user'
        sshd_config_group: 'user'
        sshd_config_mode: '0600'
        sshd:
          PermitRootLogin: 'no'
          Match:
            - Condition: "all"
              AcceptEnv: 'MY_VAR'

which gives

#
# Ansible managed
#
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
PasswordAuthentication yes
PermitRootLogin no
Subsystem sftp /usr/libexec/openssh/sftp-server
SyslogFacility AUTHPRIV
UsePAM yes
UsePrivilegeSeparation sandbox
X11Forwarding yes
Match all
  AcceptEnv MY_VAR

which still uses a Match block.

mattwillsher commented 1 year ago

Just so I'm clear your want to add

AcceptEnv MY_VAR

Along side the defaults in the main block not as a match?

As you've seen it's overriding what is there entirely - I'm not sure if there is a merge option for that list.

I'll have a closer look at the code over the weekend.

skwde commented 1 year ago

Yes, you are absolutely right.

Just like in the very first code block above.

mattwillsher commented 1 year ago

The whole value will need to be set - there is no way to add to a list. The template treats most of the elements as simple key/value pairs, for example:

...
 vars:
  sshd:
    AcceptEnv:
    - LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
    - LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
    - LC_IDENTIFICATION LC_ALL LANGUAGE
    - XMODIFIERS MYVAR
skwde commented 1 year ago

Ok, thanks.

Unfortunately, this is what I thought. Guess I'll use a match block then.