initial commit
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Robert Kaussow 2019-11-02 19:10:39 +01:00
commit 1366f1473a
21 changed files with 886 additions and 0 deletions

148
.drone.jsonnet Normal file
View File

@ -0,0 +1,148 @@
local PipelineLinting = {
kind: "pipeline",
name: "linting",
platform: {
os: "linux",
arch: "amd64",
},
steps: [
{
name: "ansible-later",
image: "xoxys/ansible-later:latest",
environment: {
PY_COLORS: 1
},
commands: [
"git clone https://gitea.rknet.org/ansible/ansible-later-policy.git ~/policy",
"ansible-later -c ~/policy/config.yml"
],
},
],
trigger: {
ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"],
},
};
local PipelineDeployment = {
kind: "pipeline",
name: "deployment",
platform: {
os: "linux",
arch: "amd64",
},
concurrency: {
limit: 1
},
workspace: {
base: "/drone/src",
path: "xoxys.sshd"
},
steps: [
{
name: "ansible-molecule",
image: "xoxys/molecule:do-linux-amd64",
environment: {
DO_API_KEY: { "from_secret": "do_api_key" },
USER: "root",
MOLECULE_CUSTOM_MODULES_REPO: "https://gitea.rknet.org/ansible/custom_modules",
MOLECULE_CUSTOM_FILTERS_REPO: "https://gitea.rknet.org/ansible/custom_filters",
PY_COLORS: 1
},
commands: [
"/bin/bash /docker-entrypoint.sh",
"molecule test -s default",
],
},
],
depends_on: [
"linting",
],
trigger: {
ref: ["refs/heads/master", "refs/tags/**"],
},
};
local PipelineDocumentation = {
kind: "pipeline",
name: "documentation",
platform: {
os: "linux",
arch: "amd64",
},
steps: [
{
name: "ansible-doctor",
image: "xoxys/ansible-doctor:latest",
environment: {
ANSIBLE_DOCTOR_LOG_LEVEL: "INFO",
ANSIBLE_DOCTOR_FORCE_OVERWRITE: true,
ANSIBLE_DOCTOR_EXCLUDE_FILES: "molecule/",
ANSIBLE_DOCTOR_CUSTOM_HEADER: "HEADER.md",
PY_COLORS: 1
},
},
{
name: "push-to-repo",
image: "plugins/git-action:latest",
settings: {
actions: ["commit", "push"],
author_email: "shipper@rknet.org",
author_name: "DroneShipper",
branch: "master",
message: "[SKIP CI] update readme",
remote: "https://gitea.rknet.org/ansible/xoxys.sshd",
netrc_machine: "gitea.rknet.org",
netrc_username: {"from_secret": "gitea_username"},
netrc_password: {"from_secret": "gitea_token"},
},
when: {
ref: ["refs/heads/master"],
},
},
],
depends_on: [
"deployment",
],
trigger: {
ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"],
},
};
local PipelineNotification= {
kind: "pipeline",
name: "notification",
platform: {
os: "linux",
arch: "amd64",
},
clone: {
disable: true,
},
steps: [
{
name: "matrix",
image: "plugins/matrix",
settings: {
homeserver: { "from_secret": "matrix_homeserver" },
roomid: { "from_secret": "matrix_roomid" },
template: "Status: **{{ build.status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}<br/> Message: {{ build.message }}",
username: { "from_secret": "matrix_username" },
password: { "from_secret": "matrix_password" },
},
},
],
depends_on: [
"documentation",
],
trigger: {
status: [ "success", "failure" ],
ref: ["refs/heads/master", "refs/tags/**"],
},
};
[
PipelineLinting,
PipelineDeployment,
PipelineDocumentation,
PipelineNotification,
]

148
.drone.yml Normal file
View File

@ -0,0 +1,148 @@
---
kind: pipeline
name: linting
platform:
os: linux
arch: amd64
steps:
- name: ansible-later
image: xoxys/ansible-later:latest
commands:
- git clone https://gitea.rknet.org/ansible/ansible-later-policy.git ~/policy
- ansible-later -c ~/policy/config.yml
environment:
PY_COLORS: 1
trigger:
ref:
- refs/heads/master
- refs/tags/**
- refs/pull/**
---
kind: pipeline
name: deployment
platform:
os: linux
arch: amd64
concurrency:
limit: 1
workspace:
base: /drone/src
path: xoxys.sshd
steps:
- name: ansible-molecule
image: xoxys/molecule:do-linux-amd64
commands:
- /bin/bash /docker-entrypoint.sh
- molecule test -s default
environment:
DO_API_KEY:
from_secret: do_api_key
MOLECULE_CUSTOM_FILTERS_REPO: https://gitea.rknet.org/ansible/custom_filters
MOLECULE_CUSTOM_MODULES_REPO: https://gitea.rknet.org/ansible/custom_modules
PY_COLORS: 1
USER: root
trigger:
ref:
- refs/heads/master
- refs/tags/**
depends_on:
- linting
---
kind: pipeline
name: documentation
platform:
os: linux
arch: amd64
steps:
- name: ansible-doctor
image: xoxys/ansible-doctor:latest
environment:
ANSIBLE_DOCTOR_CUSTOM_HEADER: HEADER.md
ANSIBLE_DOCTOR_EXCLUDE_FILES: molecule/
ANSIBLE_DOCTOR_FORCE_OVERWRITE: true
ANSIBLE_DOCTOR_LOG_LEVEL: INFO
PY_COLORS: 1
- name: push-to-repo
image: plugins/git-action:latest
settings:
actions:
- commit
- push
author_email: shipper@rknet.org
author_name: DroneShipper
branch: master
message: "[SKIP CI] update readme"
netrc_machine: gitea.rknet.org
netrc_password:
from_secret: gitea_token
netrc_username:
from_secret: gitea_username
remote: https://gitea.rknet.org/ansible/xoxys.sshd
when:
ref:
- refs/heads/master
trigger:
ref:
- refs/heads/master
- refs/tags/**
- refs/pull/**
depends_on:
- deployment
---
kind: pipeline
name: notification
platform:
os: linux
arch: amd64
clone:
disable: true
steps:
- name: matrix
image: plugins/matrix
settings:
homeserver:
from_secret: matrix_homeserver
password:
from_secret: matrix_password
roomid:
from_secret: matrix_roomid
template: "Status: **{{ build.status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}<br/> Message: {{ build.message }}"
username:
from_secret: matrix_username
trigger:
ref:
- refs/heads/master
- refs/tags/**
status:
- success
- failure
depends_on:
- documentation
---
kind: signature
hmac: 2bfb1fd991fecdc2875b843a6e9fadb7e42a3920c1a2884c69d7b9ddf8ac52eb
...

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# ---> Ansible
*.retry
plugins
library
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

4
HEADER.md Normal file
View File

@ -0,0 +1,4 @@
# xoxys.sshd
[![Build Status](https://drone.rknet.org/api/badges/ansible/xoxys.sshd/status.svg)](https://drone.rknet.org/ansible/xoxys.sshd)

8
LICENSE Normal file
View File

@ -0,0 +1,8 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# xoxys.sshd

53
defaults/main.yml Normal file
View File

@ -0,0 +1,53 @@
---
sshd_protocol: 2
sshd_permit_root_login: 'yes'
sshd_permit_empty_passwords: 'no'
sshd_password_authentication: 'no'
sshd_gssapi_authentication: 'yes'
sshd_strict_modes: 'yes'
sshd_allow_groups: []
sshd_ignore_rhosts: 'yes'
sshd_hostbased_authentication: 'no'
sshd_client_alive_interval: 900
sshd_client_alive_count_max: 0
sshd_ciphers:
- chacha20-poly1305@openssh.com
- aes256-gcm@openssh.com
- aes128-gcm@openssh.com
- aes256-ctr
- aes192-ctr
- aes128-ctr
sshd_kex:
- curve25519-sha256@libssh.org
- diffie-hellman-group-exchange-sha256
sshd_moduli_minimum: 2048
sshd_macs:
- hmac-sha2-512-etm@openssh.com
- hmac-sha2-256-etm@openssh.com
- hmac-ripemd160-etm@openssh.com
- umac-128-etm@openssh.com
- hmac-sha2-512
- hmac-sha2-256
- hmac-ripemd160
sshd_allow_agent_forwarding: 'no'
sshd_allow_tcp_forwarding: 'yes'
sshd_compression: delayed
sshd_log_level: INFO
sshd_max_auth_tries: 6
sshd_max_sessions: 10
sshd_tcp_keep_alive: 'yes'
sshd_use_dns: 'yes'
# @var sshd_challenge_response_authentication:description: >
# If you disable password auth you should only disable
# ChallengeResponseAuth.
# @end
sshd_challenge_response_authentication: 'no'
# @var sshd_google_auth_enabled:description: >
# Google Authenticator required ChallengeResponseAuth!
# @end
sshd_google_auth_enabled: False
# @var sshd_google_auth_exclude_group:description: Exclude a group from 2FA auth
# @var sshd_google_auth_exclude_group:example: $ "my_group"
# @var sshd_google_auth_exclude_group: $ "_unset_"

8
handlers/main.yml Normal file
View File

@ -0,0 +1,8 @@
---
- name: Restart ssh server
service:
name: sshd
state: restarted
listen: __sshd_restart
become: True
become_user: root

13
meta/main.yml Normal file
View File

@ -0,0 +1,13 @@
# Standards: 0.1
---
galaxy_info:
author: xoxys
description:
license: MIT
min_ansible_version: 2.4
platforms:
- name: EL
versions:
- 7
galaxy_tags:
dependencies:

View File

@ -0,0 +1,87 @@
---
- name: Create
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
vars:
ssh_user: root
ssh_port: 22
keypair_name: molecule_key
keypair_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key"
tasks:
- name: Create local keypair
user:
name: "{{ lookup('env', 'USER') }}"
generate_ssh_key: true
ssh_key_file: "{{ keypair_path }}"
register: local_keypair
- name: Create remote keypair
digital_ocean_sshkey:
name: "{{ keypair_name }}"
ssh_pub_key: "{{ local_keypair.ssh_public_key }}"
state: present
register: remote_keypair
- name: Create molecule instance(s)
digital_ocean_droplet:
name: "{{ item.name }}"
unique_name: true
region: "{{ item.region_id }}"
image: "{{ item.image_id }}"
size: "{{ item.size_id }}"
ssh_keys: "{{ remote_keypair.data.ssh_key.id }}"
wait: true
wait_timeout: 300
state: present
register: server
loop: "{{ molecule_yml.platforms }}"
async: 7200
poll: 0
- name: Wait for instance(s) creation to complete
async_status:
jid: "{{ item.ansible_job_id }}"
register: digitalocean_jobs
until: digitalocean_jobs.finished
retries: 300
loop: "{{ server.results }}"
# Mandatory configuration for Molecule to function.
- name: Populate instance config dict
set_fact:
instance_conf_dict: {
'instance': "{{ item.data.droplet.name }}",
'address': "{{ item.data.ip_address }}",
'user': "{{ ssh_user }}",
'port': "{{ ssh_port }}",
'identity_file': "{{ keypair_path }}",
'droplet_id': "{{ item.data.droplet.id }}",
'ssh_key_id': "{{ remote_keypair.data.ssh_key.id }}",
}
loop: "{{ digitalocean_jobs.results }}"
register: instance_config_dict
when: server.changed | bool
- name: Convert instance config dict to a list
set_fact:
instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
when: server.changed | bool
- name: Dump instance config
copy:
content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool
- name: Wait for SSH
wait_for:
port: "{{ ssh_port }}"
host: "{{ item.address }}"
search_regex: SSH
delay: 10
timeout: 320
loop: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"

View File

@ -0,0 +1,54 @@
---
- name: Destroy
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
tasks:
- block:
- name: Populate instance config
set_fact:
instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"
skip_instances: false
rescue:
- name: Populate instance config when file missing
set_fact:
instance_conf: {}
skip_instances: true
- name: Destroy molecule instance(s)
digital_ocean_droplet:
name: "{{ item.instance }}"
id: "{{ item.droplet_id }}"
state: absent
register: server
loop: "{{ instance_conf | flatten(levels=1) }}"
when: not skip_instances
async: 7200
poll: 0
- name: Wait for instance(s) deletion to complete
async_status:
jid: "{{ item.ansible_job_id }}"
register: digitalocean_jobs
until: digitalocean_jobs.finished
retries: 300
loop: "{{ server.results }}"
- name: Delete remote keypair
digital_ocean_sshkey:
fingerprint: "{{ item.ssh_key_id }}"
state: absent
loop: "{{ instance_conf | flatten(levels=1) }}"
# Mandatory configuration for Molecule to function.
- name: Populate instance config
set_fact:
instance_conf: {}
- name: Dump instance config
copy:
content: "{{ instance_conf | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool

View File

@ -0,0 +1,24 @@
---
dependency:
name: galaxy
driver:
name: digitalocean
platforms:
- name: centos7-sshd
region_id: fra1
image_id: centos-7-x64
size_id: s-1vcpu-1gb
lint:
name: yamllint
enabled: False
provisioner:
name: ansible
lint:
name: ansible-lint
enabled: False
verifier:
name: testinfra
lint:
name: flake8
options:
max-line-length: 120

View File

@ -0,0 +1,5 @@
---
- name: Converge
hosts: all
roles:
- role: xoxys.sshd

View File

@ -0,0 +1,9 @@
---
- name: Prepare
hosts: all
gather_facts: false
tasks:
- name: Install python for Ansible
raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
become: true
changed_when: false

View File

@ -0,0 +1,18 @@
import os
import testinfra.utils.ansible_runner
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_sshd_config_file(host):
sshd = host.file("/etc/ssh/sshd_config")
assert sshd.exists
assert sshd.user == "root"
assert sshd.group == "root"
assert oct(sshd.mode) == "0600"

3
molecule/pytest.ini Normal file
View File

@ -0,0 +1,3 @@
[pytest]
filterwarnings =
ignore::DeprecationWarning

13
tasks/main.yml Normal file
View File

@ -0,0 +1,13 @@
---
- include_tasks: "{{ lookup('first_found', params) }}"
vars:
params:
files:
- "ssh_{{ ansible_lsb.id | default('') | lower }}.yml"
- "ssh_{{ ansible_os_family | lower }}.yml"
- "ssh_default.yml"
paths:
- "tasks"
- include_tasks: ssh_2fa.yml
when: sshd_google_auth_enabled | bool

42
tasks/ssh_2fa.yml Normal file
View File

@ -0,0 +1,42 @@
---
- block:
- name: Install google authenticator PAM module
yum:
name: google-authenticator
state: present
- name: Add google auth module to PAM
pamd:
name: sshd
type: account
control: required
module_path: pam_nologin.so
new_type: auth
new_control: required
new_module_path: pam_google_authenticator.so
state: before
- name: Skip google auth for specific group
pamd:
name: sshd
type: auth
control: required
module_path: pam_google_authenticator.so
new_type: auth
new_control: "[success=done default=ignore]"
new_module_path: pam_succeed_if.so
module_arguments:
- user
- ingroup
- "{{ sshd_google_auth_exclude_group }}"
state: "{{ 'before' if sshd_google_auth_exclude_group is defined else 'absent' }}"
- name: Remove password auth from PAM
pamd:
name: sshd
type: auth
control: substack
module_path: password-auth
state: absent
become: True
become_user: root

30
tasks/ssh_default.yml Normal file
View File

@ -0,0 +1,30 @@
---
- block:
- name: Hardening sshd config
template:
src: etc/ssh/sshd_config.j2
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: 0600
notify: __sshd_restart
- name: Check if /etc/ssh/moduli contains weak DH parameters
shell: awk '$5 < {{ sshd_moduli_minimum }}' /etc/ssh/moduli
register: __sshd_register_moduli
changed_when: False
check_mode: no
- name: Remove all small primes
shell: awk '$5 >= {{ sshd_moduli_minimum }}' /etc/ssh/moduli > /etc/ssh/moduli.new ;
[ -r /etc/ssh/moduli.new -a -s /etc/ssh/moduli.new ] && mv /etc/ssh/moduli.new /etc/ssh/moduli || true
notify: __sshd_restart
when: __sshd_register_moduli.stdout
- name: Create SSH Usergroup
group:
name: "{{ item }}"
state: present
loop: "{{ sshd_allow_groups }}"
become: True
become_user: root

37
tasks/ssh_univention.yml Normal file
View File

@ -0,0 +1,37 @@
---
- block:
- name: Hardening sshd config
ucr:
path: "{{ item.path }}"
value: "{{ item.value }}"
loop:
- { path: sshd/permitroot, value: "{{ sshd_permit_root_login | default('') }}" }
- { path: sshd/PermitEmptyPasswords, value: "{{ sshd_permit_empty_passwords | default('') }}" }
- { path: sshd/permitroot, value: "{{ sshd_permit_root_login | default('') }}" }
- { path: sshd/passwordauthentication, value: "{{ sshd_password_authentication | default('') }}" }
- { path: sshd/challengeresponse, value: "{{ sshd_password_authentication | default('') }}" }
- { path: sshd/IgnoreRhosts, value: "{{ sshd_ignore_rhosts | default('') }}" }
- { path: sshd/HostbasedAuthentication, value: "{{ sshd_hostbased_authentication | default('') }}" }
- { path: sshd/ClientAliveInterval, value: "{{ sshd_client_alive_interval | default('') }}" }
- { path: sshd/ClientAliveCountMax, value: "{{ sshd_client_alive_count_max | default('') }}" }
- { path: sshd/Ciphers, value: "{{ sshd_ciphers | default('[]') | join(',') }}" }
- { path: sshd/KexAlgorithms, value: "{{ sshd_kex | default('[]') | join(',') }}" }
- { path: sshd/MACs, value: "{{ sshd_macs | default('[]') | join(',') }}" }
loop_control:
label: "variable: {{ item.path }}={{ item.value }}"
notify: __sshd_restart
- name: Set allowed ssh groups
ucr:
path: "auth/sshd/group/{{ item }}"
value: "yes"
loop: "{{ sshd_allow_groups }}"
- name: Create SSH Usergroup
group:
name: "{{ item }}"
system: 'yes'
state: present
loop: "{{ sshd_allow_groups }}"
become: True
become_user: root

View File

@ -0,0 +1,169 @@
#jinja2: lstrip_blocks: True
{{ ansible_managed | comment }}
# $OpenBSD: sshd_config,v 1.93 2014/01/10 05:59:19 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/local/bin:/usr/bin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# The default requires explicit activation of protocol 1
Protocol {{ sshd_protocol }}
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024
# Ciphers and keying
#RekeyLimit default none
Ciphers {{ sshd_ciphers | join(',') }}
KexAlgorithms {{ sshd_kex | join(',') }}
MACs {{ sshd_macs | join(',') }}
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
SyslogFacility AUTHPRIV
LogLevel {{ sshd_log_level }}
# Authentication:
#LoginGraceTime 2m
PermitRootLogin {{ sshd_permit_root_login }}
StrictModes {{ sshd_strict_modes }}
{% if sshd_allow_groups %}
AllowGroups {{ sshd_allow_groups|join(',') }}
{% endif %}
MaxAuthTries {{ sshd_max_auth_tries }}
MaxSessions {{ sshd_max_sessions }}
#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication {{ sshd_hostbased_authentication }}
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts {{ sshd_ignore_rhosts }}
{% if sshd_google_auth_enabled %}
# Force public key auth then ask for google auth code
AuthenticationMethods publickey,keyboard-interactive
{% endif %}
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication {{ sshd_password_authentication }}
PermitEmptyPasswords {{ sshd_permit_empty_passwords }}
# Change to no to disable s/key passwords
ChallengeResponseAuthentication {{ sshd_challenge_response_authentication }}
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
#KerberosUseKuserok yes
# GSSAPI options
GSSAPIAuthentication {{ sshd_gssapi_authentication }}
GSSAPICleanupCredentials no
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
#GSSAPIEnablek5users no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
# problems.
UsePAM yes
AllowAgentForwarding {{ sshd_allow_agent_forwarding }}
AllowTcpForwarding {{ sshd_allow_tcp_forwarding }}
#GatewayPorts no
X11Forwarding {{ sshd_x11_forwarding }}
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog no
TCPKeepAlive {{ sshd_tcp_keep_alive }}
#UseLogin no
UsePrivilegeSeparation sandbox
#PermitUserEnvironment no
Compression {{ sshd_compression }}
ClientAliveInterval {{ sshd_client_alive_interval }}
ClientAliveCountMax {{ sshd_client_alive_count_max }}
#ShowPatchLevel no
UseDNS {{ sshd_use_dns }}
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# Accept locale-related environment variables
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
# override default of no subsystems
Subsystem sftp /usr/libexec/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
{% if sshd_google_auth_exclude_group is defined %}
Match User {{ sshd_google_auth_exclude_group }}
AuthenticationMethods publickey
{% endif %}