givin config 'cfg' and distro 'distro'

  (users, _groups) = ug_util.normalize_users_groups(cfg, distro)
  (default_user, _user_config) = ug_util.extract_default(users)

default_user is then the use name.

I think there may be an issue though in that the cfg that the datasource gets
is only config that is present in /etc/cloud/cloud.cfg.d and /etc/cloud.cfg
the user's provided cloud-config is not yet present (it has not yet been read).

I think that can be made acceptable though, see comment inline.


Diff comments:

> diff --git a/cloudinit/sources/DataSourceGCE.py 
> b/cloudinit/sources/DataSourceGCE.py
> index ad6dae3..c1fa354 100644
> --- a/cloudinit/sources/DataSourceGCE.py
> +++ b/cloudinit/sources/DataSourceGCE.py
> @@ -92,15 +97,59 @@ class DataSourceGCE(sources.DataSource):
>          return self.availability_zone.rsplit('-', 1)[0]
>  
>  
> -def _trim_key(public_key):
> -    # GCE takes sshKeys attribute in the format of '<user>:<public_key>'
> -    # so we have to trim each key to remove the username part
> +def _has_expired(public_key):
> +    # Check whether an SSH key is expired. Public key input is a single SSH
> +    # public key in the GCE specific key format documented here:
> +    # 
> https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys#sshkeyformat
> +    try:
> +        # Check for the Google-specific schema identifier.
> +        schema, json_str = public_key.split(None, 3)[2:]
> +    except (ValueError, AttributeError):
> +        return False
> +
> +    # Do not expire keys if they do not have the expected schema identifier.
> +    if schema != 'google-ssh':
> +        return False
> +
> +    try:
> +        json_obj = json.loads(json_str)
> +    except ValueError:
> +        return False
> +
> +    # Do not expire keys if there is no expriation timestamp.
> +    if 'expireOn' not in json_obj:
> +        return False
> +
> +    expire_str = json_obj['expireOn']
> +    format_str = '%Y-%m-%dT%H:%M:%S+0000'
>      try:
> -        index = public_key.index(':')
> -        if index > 0:
> -            return public_key[(index + 1):]
> -    except Exception:
> -        return public_key
> +        expire_time = datetime.datetime.strptime(expire_str, format_str)
> +    except ValueError:
> +        return False
> +
> +    # Expire the key if and only if we have exceeded the expiration 
> timestamp.
> +    return datetime.datetime.utcnow() > expire_time
> +
> +
> +def _parse_public_keys(public_keys_data):
> +    # Parse the SSH key data for the Ubuntu user account. Public keys input 
> is
> +    # a newline separated string containing SSH public keys in the GCE 
> specific
> +    # key format documented here:
> +    # 
> https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys#sshkeyformat
> +    public_keys = []
> +    if not public_keys_data:
> +        return public_keys
> +    lines = [line for line in public_keys_data.splitlines() if line]
> +    for line in lines:
> +        if not all(ord(c) < 128 for c in line):
> +            continue
> +        split_line = line.split(':', 1)
> +        if len(split_line) != 2:
> +            continue
> +        user, key = split_line
> +        if user == 'ubuntu' and not _has_expired(key):

maybe 'default' or default_user as described above would be sufficient here.

Then if i added a key for user 'default', it'd get into the public keys
and further into the 'ubuntu' user (or whatever user these should go to).

And 'ubuntu' would also get in there on Ubuntu and 'centos' on centos.

If the user wanted to change what the default user was in user-data, then 
they'd have to populate keys with 'default' as the name to make it stick.

> +            public_keys.append(key)
> +    return public_keys
>  
>  
>  def read_md(address=None, platform_check=True):
> @@ -149,17 +195,25 @@ def read_md(address=None, platform_check=True):
>              return ret
>          md[mkey] = value
>  
> -    if md['public-keys']:
> -        lines = md['public-keys'].splitlines()
> -        md['public-keys'] = [_trim_key(k) for k in lines]
> +    print('Instance: %s' % md['instance-data'])
> +    print('Instance Type: %s' % type(md['instance-data']))

drop prints

> +    instance_data = json.loads(md['instance-data'] or '{}')
> +    project_data = json.loads(md['project-data'] or '{}')
> +    valid_keys = [instance_data.get('sshKeys'), 
> instance_data.get('ssh-keys')]
> +    block_project = instance_data.get('block-project-ssh-keys', '').lower()
> +    if block_project != 'true' and not instance_data.get('sshKeys'):
> +        valid_keys.append(project_data.get('ssh-keys'))
> +        valid_keys.append(project_data.get('sshKeys'))
> +    public_keys_data = '\n'.join([key for key in valid_keys if key])
> +    md['public-keys'] = _parse_public_keys(public_keys_data)
>  
>      if md['availability-zone']:
>          md['availability-zone'] = md['availability-zone'].split('/')[-1]
>  
> -    encoding = md.get('user-data-encoding')
> +    encoding = instance_data.get('user-data-encoding')
>      if encoding:
>          if encoding == 'base64':
> -            md['user-data'] = b64decode(md['user-data'])
> +            md['user-data'] = b64decode(instance_data.get('user-data'))
>          else:
>              LOG.warning('unknown user-data-encoding: %s, ignoring', encoding)
>  


-- 
https://code.launchpad.net/~illfelder/cloud-init/+git/cloud-init/+merge/334777
Your team cloud-init commiters is requested to review the proposed merge of 
~illfelder/cloud-init:master into cloud-init:master.

_______________________________________________
Mailing list: https://launchpad.net/~cloud-init-dev
Post to     : cloud-init-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~cloud-init-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to