← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1845552] [NEW] ssh_util: fails to parse sshd_config when config contains an entry missing a value

 

Public bug reported:

# Overview

If the sshd_config contains keys with no values, cloud-init fails to
parse the config. This results in a system that is inaccessible over ssh
using pubkey authentication.

# Steps to reproduce:

1. Append the following content to /etc/ssh/sshd_config in a pristine
Ubuntu cloud image:

    AllowUsers ubuntu
    AllowGroups ubuntu
    DenyUsers
    DenyGroups

2. Boot the image with a cloud-config that injects an ssh key for the
ubuntu user.

3. Note the following error in the boot output:

    util.py[WARNING]: Applying ssh credentials failed!

4. Attempt to login over ssh, note the pubkey authentication failure.

# Cause of the issue

In cloudinit/ssh_util.py, in parse_ssh_config_lines(), we attempt to
parse each line of sshd_config. This function expects each line to be
one of the following forms:

    # comment
    key value
    key=value

If the line does not match one of these forms, we throw a ValueError.

Instead, we could ignore the offending line:

diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py
index 3f99b58c..ec5ef9fb 100644
--- a/cloudinit/ssh_util.py
+++ b/cloudinit/ssh_util.py
@@ -304,7 +304,10 @@ def parse_ssh_config_lines(lines):
         try:
             key, val = line.split(None, 1)
         except ValueError:
-            key, val = line.split('=', 1)
+            try:
+                key, val = line.split('=', 1)
+            except ValueError:
+                continue
         ret.append(SshdConfigLine(line, key, val))
     return ret
 
# Notes about debugging

This issue was somewhat difficult to debug because the error message
produced by cloud-init was not very useful. To dig in and find the
actual issue, I modified cloudinit/config/cc_ssh.py to print the
traceback:

diff --git a/cloudinit/config/cc_ssh.py b/cloudinit/config/cc_ssh.py
index fdd8f4d3..2b356a4c 100755
--- a/cloudinit/config/cc_ssh.py
+++ b/cloudinit/config/cc_ssh.py
@@ -99,6 +99,7 @@ public keys.
 import glob
 import os
 import sys
+import traceback
 
 from cloudinit.distros import ug_util
 from cloudinit import ssh_util
@@ -213,8 +214,9 @@ def handle(_name, cfg, cloud, log, _args):
             keys.extend(cfgkeys)
 
         apply_credentials(keys, user, disable_root, disable_root_opts)
-    except Exception:
-        util.logexc(log, "Applying ssh credentials failed!")
+    except Exception as err:
+        util.logexc(log, "Applying ssh credentials failed: {}".format(err))
+        traceback.print_exc()
 
 
 def apply_credentials(keys, user, disable_root, disable_root_opts):

** Affects: cloud-init
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to cloud-init.
https://bugs.launchpad.net/bugs/1845552

Title:
  ssh_util: fails to parse sshd_config when config contains an entry
  missing a value

Status in cloud-init:
  New

Bug description:
  # Overview

  If the sshd_config contains keys with no values, cloud-init fails to
  parse the config. This results in a system that is inaccessible over
  ssh using pubkey authentication.

  # Steps to reproduce:

  1. Append the following content to /etc/ssh/sshd_config in a pristine
  Ubuntu cloud image:

      AllowUsers ubuntu
      AllowGroups ubuntu
      DenyUsers
      DenyGroups

  2. Boot the image with a cloud-config that injects an ssh key for the
  ubuntu user.

  3. Note the following error in the boot output:

      util.py[WARNING]: Applying ssh credentials failed!

  4. Attempt to login over ssh, note the pubkey authentication failure.

  # Cause of the issue

  In cloudinit/ssh_util.py, in parse_ssh_config_lines(), we attempt to
  parse each line of sshd_config. This function expects each line to be
  one of the following forms:

      # comment
      key value
      key=value

  If the line does not match one of these forms, we throw a ValueError.

  Instead, we could ignore the offending line:

  diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py
  index 3f99b58c..ec5ef9fb 100644
  --- a/cloudinit/ssh_util.py
  +++ b/cloudinit/ssh_util.py
  @@ -304,7 +304,10 @@ def parse_ssh_config_lines(lines):
           try:
               key, val = line.split(None, 1)
           except ValueError:
  -            key, val = line.split('=', 1)
  +            try:
  +                key, val = line.split('=', 1)
  +            except ValueError:
  +                continue
           ret.append(SshdConfigLine(line, key, val))
       return ret
   
  # Notes about debugging

  This issue was somewhat difficult to debug because the error message
  produced by cloud-init was not very useful. To dig in and find the
  actual issue, I modified cloudinit/config/cc_ssh.py to print the
  traceback:

  diff --git a/cloudinit/config/cc_ssh.py b/cloudinit/config/cc_ssh.py
  index fdd8f4d3..2b356a4c 100755
  --- a/cloudinit/config/cc_ssh.py
  +++ b/cloudinit/config/cc_ssh.py
  @@ -99,6 +99,7 @@ public keys.
   import glob
   import os
   import sys
  +import traceback
   
   from cloudinit.distros import ug_util
   from cloudinit import ssh_util
  @@ -213,8 +214,9 @@ def handle(_name, cfg, cloud, log, _args):
               keys.extend(cfgkeys)
   
           apply_credentials(keys, user, disable_root, disable_root_opts)
  -    except Exception:
  -        util.logexc(log, "Applying ssh credentials failed!")
  +    except Exception as err:
  +        util.logexc(log, "Applying ssh credentials failed: {}".format(err))
  +        traceback.print_exc()
   
   
   def apply_credentials(keys, user, disable_root, disable_root_opts):

To manage notifications about this bug go to:
https://bugs.launchpad.net/cloud-init/+bug/1845552/+subscriptions


Follow ups