Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
SSH Posture Control enables you to audit and configure SSH Server security posture on supported Linux distros including Ubuntu, Red Hat, Azure Linux, and more. SSH Posture Control integrates seamlessly with Azure Governance services (Policy, Machine Configuration) so you can:
- Ensure compliance with sshd standards in your industry or organization
- Reduce attack surface of sshd-based remote management
- Ensure consistent sshd setup across your fleet for security and productivity
To help you demonstrate compliance to auditors (and to help you take action where needed) each compliance check includes evidence via the Reasons field indicating how compliance or non-compliance was determined.
You can customize the sshd parameters (port number, allowed groups, etc.) or use the policy default values, which are aligned to the Azure security baseline for Linux.
Documentation for getting started
- Quickstart: For a click-by-click hands-on experience, see Quickstart: Apply SSH Posture Control to a test machine.
- Overview and reference: For conceptual information, reference, and FAQs, continue with this article.
Selecting audit-only vs. audit-and-configure behavior
When assigning an SSH Posture Control policy, you can choose audit-only (aka "Audit") behavior or audit-and-configure (aka "Configure") behavior.
Policy definition | Azure Policy effect | Notes on what to expect | |
---|---|---|---|
Audit-only behavior | **Audit** SSH Posture Control on Linux machines |
auditIfNotExists | The policy includes more restrictive settings compared to many popular system images. For example, denial of root ssh access. Accordingly, expect to see Not-compliant states reported. |
Audit-and-configure behavior | **Configure** SSH Posture Control on Linux machines |
deployIfNotExists | As above, you can expect to see Not-compliant states reported initially. Subsequently, the machines will be reconfigured to match the policy, resulting in eventual Compliant states. |
For existing machines, admins typically start with audit-only behavior to determine existing state and to discover dependencies such as accounts allowed for systems automation. After comparing the existing fleet against SSH Posture Control defaults, you would decide which SSH Posture Control parameters to customize. After this analysis and planning, you would then transition to audit-and-configure behavior (with safe deployment practices such as rings).
For greenfield scenarios or disposable test machines, you might choose to skip that analysis and move directly to audit-and-configure behavior, starting fresh with strong SSH Posture Control defaults.
Caution
Before configuring any machines, take great care to validate your new configuration. You could accidentally lose access to your machines.
Examples of accidentally locking yourself out include:
- The net authorization settings applied (combination of
allowUsers
,denyGroups
,permitRootLogin
, etc.) do not allow the logins you need - The
port
you configure for sshd is blocked by other controls in your environment (SELinux policies, host firewall rules, network firewall rules, etc.)- Note that many Red Hat family distros have SELinux policies in place by default which block sshd from using ports other than 22.
- To avoid overstepping enterprise team boundaries, SSH Posture Control only configured sshd. It does not currently attempt to modify on-machine SELinux policies, firewall rules, etc. to accommodate the configured sshd port. If you would like to discuss these scenarios with us, please contact us (see Additional resources below).
SSH Posture Control scope: rules, defaults, and customization
The following table lists the items that can be audited or configured with SSH Posture Control. Each of these is known as a rule.
Each rule has a default configuration value, aligned to the Azure security baseline for Linux.
Most rules can be given custom values, via policy assignment parameters to audit against or configure and audit. For example, if the standard in your organization is to use port 1111 (rather than 22) for sshd, you would set the corresponding parameter in the policy assignment. These parameters have identifiers which are included in the table below. Typically, the short parameter name is used programmatically (for example with az policy assignment create --params ...
), while the longer parameter display name is used in Azure portal workflows.
When customizing values, take care to provide values which are compatible with sshd. For example, allowGroups
takes a space delimited list of group name patterns. For reference, see the sshd_config man page. The sshd_config reference is also useful for understanding other sshd behaviors such as how allow and deny lists intersect.
Note
To preserve table layout, some cell values have been moved to footnotes below the table.
Rule name | Default value | Parameter name | Parameter display name |
---|---|---|---|
Ensure that permissions on /etc/ssh/sshd_config are configured | 600 | <footnote 1> | Access permissions for sshd_config |
Ensure that IgnoreRhosts is set | yes | ignoreHosts |
Ignore rhosts and shosts |
Ensure that LogLevel is set | INFO | logLevel |
Log verbosity level |
Ensure that MaxAuthTries is set | 6 | maxAuthTries |
Maximum number of authentication attempts |
Ensure that allowed users for SSH access are configured | @ <see footnote 5> | allowUsers |
Allowed users for SSH |
Ensure that denied users for SSH access are configured | root | denyUsers |
Denied users for SSH |
Ensure that allowed groups for SSH access are configured | * | allowGroups |
Allowed groups for SSH |
Ensure that denied groups for SSH access are configured | root | denyGroups |
Denied groups for SSH |
Ensure that HostbasedAuthentication is set | no | hostBasedAuthentication |
Host-based authentication |
Ensure that PermitRootLogin is set | no | permitRootLogin |
Whether root can log in using ssh |
Ensure that PermitEmptyPasswords is set | no | permitEmptyPasswords |
Whether the server allows login to accounts with empty password strings |
Ensure that ClientAliveCountMax is set | 0 | clientAliveCountMax |
The number of client alive messages which may be sent without sshd receiving any messages back from the client |
Ensure that ClientAliveInterval is set | 3600 | clientAliveInterval |
Timeout interval in seconds after which if no data has been received from the client, sshd will send a message to request a response |
Ensure that MACs are configured | <footnote 2> | <footnote 3> | The list of available message authentication code (MAC) algorithms |
Ensure that a banner is configured | <footnote 4> | banner |
The contents of the banner file that is sent to the remote user before authentication is allowed |
Ensure that PermitUserEnvironment is set | no | permitUserEnvironment |
Whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd |
Ensure that Ciphers are configured | aes128-ctr,aes192-ctr,aes256-ctr | ciphers |
The list of allowed ciphers |
Ensure that the SSH port is configured | 22 | port |
The SSH port |
Ensure that the best practice protocol is used | 2 | <no parameter> | <no parameter> |
Table footnotes:
accessPermissionsForSshdConfig
messageAuthenticationCodeAlgorithms
hmac-sha2-256,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-512-etm@openssh.com
#######################################################################\n\nAuthorized access only!\n\nIf you are not authorized to access or use this system, disconnect now!\n\n#######################################################################\n
- Note: this displays to end users as:
####################################################################### Authorized access only! If you are not authorized to access or use this system, disconnect now! #######################################################################
In
allowUsers
the default value "@" represents all accounts on the machine
Additional (non-sshd) policy parameters
These additional policy parameters are available during policy assignment. These influence Azure Policy assignment behavior, as opposed to sshd settings on machines.
Name | Description | Default |
---|---|---|
Include Arc connected servers | By selecting this option, you agree to be charged monthly per Arc connected machine. | FALSE |
Effect | Enable or disable the execution of this policy | <Depends on Selecting audit-only vs. audit-and-configure behavior> |
Policy definitions? Policy assignments? Guest assignments? Machine Configuration? How does this all fit together?
To get started with SSH Posture Control, your core action is to create a policy assignment. Your policy assignment links a policy definition (e.g., "Audit SSH Posture Control for Linux machines") to a scope (e.g., "my_factory_3_resource_group").
As you use the system, you will encounter additional resource types and terminology, as summarized in the following.
Description | |
---|---|
Policy definition | Within the Policy service, the abstract data which describes a cluster of available audit and/or configuration behaviors. For example, "Audit SSH Posture Control on Linux machines". |
Policy assignment | Links an abstract policy definition to a concrete scope, such as a resource group. The policy assignment can include Parameters and other properties which are specific to that assignment. |
Machine Configuration | The Azure service and agentry which handle auditing and setting configuration at the OS level. |
Guest assignment | Resource that acts as a three-way link between the policy assignment, the machine, and the Machine Configuration service. Policy creates and monitors guest assignment resources as needed. For more information on "guest" vs. "machine" terminology, see Why do I see the terms "Guest Configuration" and "Automanage" in places? |
Machine | An Arc-enabled machine or an Azure VM. |
About compatibility (distros, SSH Server implementations, etc.)
SSH Posture Control is designed for the mainstream general-purpose Linux scenario of a single long-running SSH Server instance:
- whose lifecycle is managed by the init system sush as systemd
- whose behavior is goverened by sshd_config file, consistent with OpenSSH sshd behavior
- whose effective configuration/state is revealed by
sshd -T
output, consistent with OpenSSH sshd behavior
For all supported distros (see below), this is the default SSH Server use case.
In principle, a machine could have any number of SSH server instances running with varying lifetimes, based on any number of codebases, and taking their configuration from any number of places (config files, command line arguments, compile time parameters, etc.). Such cases are out of scope for SSH Posture Control at this time. If you are interested in such cases for the future, please contact us to discuss.
SSH Posture Control is intended for use on those Linux distros supported by Azure Policy and Machine Configuration-- excluding those which were in extended support at the time of development. Specifically, the following are in scope as of 2024-06-05:
- AlmaLinux 9
- Amazon Linux 2
- Ubuntu Server 20.04
- Ubuntu Server 22.04
- Debian 10
- Debian 11
- Debian 12
- Azure Linux (CBL Mariner) 2
- Oracle Linux 7
- Oracle Linux 8
- CentOS 7.3
- CentOS 8
- RHEL 7.4
- RHEL 8
- RHEL 9
- Rocky Linux 9
- SLES 15
To the extent feasible, SSH Posture Control is tested with specific widely used system compositions of the above distros. For example, OS image compositions published by distro maintainers in the Azure gallery. Compatibility with any specific machine at run time cannot be guaranteed as sysadmins and image builders are free to remove components from the OS, make filesystems read-only, block agent actions with SELinux, etc.
Compatibility with sshd_config Include directives
SSH Posture Control attempts to accommodate and make use of Include
directives in sshd_config, as follows:
- For audit/read actions: Rely on sshd -T to reflect the net configuration from sshd's perspective-- taking into account any Includes.
- For configure/write actions:
- If the sshd implementation on the machine supports Includes, link a new SSH Posture Control specific file to sshd_config (as an Include). Subsequently, place all writes into the linked SSH Posture Control file. This enhances system hygiene and traceability of system changes.
- If the sshd implementation on the machine does not support Include directives, write any configuration changes directly to sshd_config.
Compatibility with sshd_config Match directives
SSH Posture Control is designed to audit and configure core sshd behavior. It does not attempt to interact with conditional Match
blocks (if any) which can apply different sshd configurations to specific populations.
Compatibility with multiple sshd_config values
SSH Posture Control does not support the use of multiple values for the rule 'port' i.e, setting the rule 'port' to 22 and 33. This rule should be configured with a single value to ensure proper functionality and compliance for auditing and configuring scenarios. Other rules such as allow/deny users and ciphers can have multiple values, as long as they are added on a single line.
Example:
- An existing sshd_config file includes a line "port:22" and another line "port:33".
- The "Audit SSH" Policy is used to audit for an expected port value of 33.
- Outcome: The audit may pass or fail unpredictably.
- Recommendation: Do not use this feature with scenarios such as these.
How can I query the results programmatically?
Using Azure Resource Graph (ARG) queries you can integrate assignment and status data into your own workflows. These examples use Search-AzGraph
in PowerShell to execute the ARG query, but PowerShell is not required. You can use ARG from many entry points including the Azure Portal, Azure CLI, REST calls, etc.
At the highest altitude of summarization, you can get machine counts per compliance status bucket. For example:
$machineCountsQuery = @' // SSH machine counts by compliance status guestconfigurationresources | where name contains "LinuxSshServerSecurityBaseline" | extend complianceStatus = tostring(properties.complianceStatus) | summarize machineCount = count() by complianceStatus '@ Search-AzGraph -Query $machineCountsQuery <# Sample output from an environment with two machines: complianceStatus machineCount ---------------- ------------ Pending 1 Compliant 1 #>
To drill in such that you see overall compliance status by machine, you can use the following:
$machinePerRowQuery = @' // SSH machine level compliance guestconfigurationresources | where name contains "LinuxSshServerSecurityBaseline" | project machine = split(properties.targetResourceId,'/')[-1], complianceStatus = properties.complianceStatus, lastComplianceStatusChecked = properties.lastComplianceStatusChecked '@ Search-AzGraph -Query $machinePerRowQuery <# Sample output: machine complianceStatus lastComplianceStatusChecked ------- ---------------- --------------------------- sshdemovm01 Compliant 2/15/2024 11:07:21 PM sshdemovm02 Pending 1/1/0001 12:00:00 AM #>
To drill down to setting-by-setting details, you can use the following:
$settingPerRowQuery = @' // SSH rule level detail GuestConfigurationResources | where name contains "LinuxSshServerSecurityBaseline" | project report = properties.latestAssignmentReport, machine = split(properties.targetResourceId,'/')[-1], lastComplianceStatusChecked=properties.lastComplianceStatusChecked | mv-expand report.resources | project machine, rule = report_resources.resourceId, ruleComplianceStatus = report_resources.complianceStatus, ruleComplianceReason = report_resources.reasons[0].phrase, lastComplianceStatusChecked '@ Search-AzGraph $settingPerRowQuery <# Sample output: machine rule ruleComplianceStatus ruleComplianceReason ------- --------------- ------ ------ sshdemovm01 Ensure permissions on /etc/ssh/sshd_config are configured true Access to '/etc/ssh/sshd_config' matches required ... sshdemovm01 Ensure SSH is configured to meet best practices (protocol 2) true 'Protocol 2' is found uncommented in /etc/ssh/sshd_config sshdemovm01 Ensure SSH is configured to ignore rhosts true The sshd service reports that 'ignorerhosts' is set to 'yes' sshdemovm01 Ensure SSH LogLevel is set to INFO true The sshd service reports that 'loglevel' is set to 'INFO' sshdemovm01 Ensure SSH MaxAuthTries is configured true The sshd service reports that 'maxauthtries' is set to '6' sshdemovm01 Ensure allowed users for SSH access are configured true The sshd service reports that 'allowusers' is set to '*@*' sshdemovm01 Ensure denied users for SSH are configured true The sshd service reports that 'denyusers' is set to 'root' sshdemovm01 Ensure allowed groups for SSH are configured true The sshd service reports that 'allowgroups' is set to '*' sshdemovm01 Ensure denied groups for SSH are configured true The sshd service reports that 'denygroups' is set to 'root' sshdemovm01 Ensure SSH host-based authenticationis disabled true The sshd service reports that 'hostbasedauthentication' is ... #>
Why do I see the terms "Guest Configuration" and "Automanage" in places?
The Machine Configuration service has also been known as Guest Configuration and as Automanage Machine Configuration. You may encounter these names as you interact with services and documentation. For example:
- In the Azure Resource Graph query examples in this article, the data table is called
guestconfigurationresources
. - In the Azure portal, a useful view for observing results is called "Guest Assignments".
- In the Azure portal, when applying the relevant VM extension to enable Machine Configuration, the extension title is "Automanage Machine Configuration".
For the purposes of SSH Posture Control, there is no meaningful distinction between "guest" and "machine". Arc-enabled machines and Azure VMs are eligible.
What are the identifiers for the built-in policy definitions?
In some cases, such as creating policy assignments with Azure CLI, it may be useful or necessary to refer to a policy definition by id rather than display name.
displayName | id |
---|---|
Audit SSH Posture Control on Linux machines | /providers/Microsoft.Authorization/policyDefinitions/a8f3e6a6-dcd2-434c-b0f7-6f309ce913b4 |
Configure SSH Posture Control on Linux machines | /providers/Microsoft.Authorization/policyDefinitions/e22a2f03-0534-4d10-8ea0-aa25a6113233 |
Related resources
- Quickstart: Apply SSH Posture Control to a test machine
- Safely deploying SSH server settings with Azure Policy
- For support with problems, etc., contact Microsoft Support
- To provide feedback, discuss feature requests, etc. contact: linux_sec_config_mgmt@service.microsoft.com