Add support for changing the password at next logon
This patch exports a new option, `password_next_logon`, which determines what will happen at the next logon in certain conditions. The option can accept three possible arguments: `always`, which forces the user to change the password at next logon, 'no', which doesn't change anything and `clear_text_injected_only`, which forces the user to change the password at the next logon if the password comes in clear text from the metadata. Change-Id: Ic6a0526ea9c9902e183898c42497133a135b5c53
This commit is contained in:
@@ -31,7 +31,7 @@ opts = [
|
||||
'SetUserSSHPublicKeysPlugin',
|
||||
'cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin',
|
||||
'cloudbaseinit.plugins.common.userdata.UserDataPlugin',
|
||||
'cloudbaseinit.plugins.common.setuserpassword.'
|
||||
'cloudbaseinit.plugins.windows.setuserpassword.'
|
||||
'SetUserPasswordPlugin',
|
||||
'cloudbaseinit.plugins.windows.winrmlistener.'
|
||||
'ConfigWinRMListenerPlugin',
|
||||
@@ -71,8 +71,8 @@ OLD_PLUGINS = {
|
||||
'cloudbaseinit.plugins.windows.userdata.UserDataPlugin':
|
||||
'cloudbaseinit.plugins.common.userdata.UserDataPlugin',
|
||||
|
||||
'cloudbaseinit.plugins.windows.setuserpassword.SetUserPasswordPlugin':
|
||||
'cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin',
|
||||
'cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin':
|
||||
'cloudbaseinit.plugins.windows.setuserpassword.SetUserPasswordPlugin',
|
||||
|
||||
'cloudbaseinit.plugins.windows.localscripts.LocalScriptsPlugin':
|
||||
'cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin',
|
||||
|
||||
@@ -50,18 +50,20 @@ class SetUserPasswordPlugin(base.BasePlugin):
|
||||
return list(public_keys)[0]
|
||||
|
||||
def _get_password(self, service, shared_data):
|
||||
injected = False
|
||||
if CONF.inject_user_password:
|
||||
password = service.get_admin_password()
|
||||
else:
|
||||
password = None
|
||||
|
||||
if password:
|
||||
injected = True
|
||||
LOG.warn('Using admin_pass metadata user password. Consider '
|
||||
'changing it as soon as possible')
|
||||
else:
|
||||
password = shared_data.get(constants.SHARED_DATA_PASSWORD)
|
||||
|
||||
return password
|
||||
return password, injected
|
||||
|
||||
def _set_metadata_password(self, password, service):
|
||||
if service.is_password_set:
|
||||
@@ -93,7 +95,7 @@ class SetUserPasswordPlugin(base.BasePlugin):
|
||||
LOG.info('Updating password is not required.')
|
||||
return None
|
||||
|
||||
password = self._get_password(service, shared_data)
|
||||
password, injected = self._get_password(service, shared_data)
|
||||
if not password:
|
||||
LOG.debug('Generating a random user password')
|
||||
maximum_length = osutils.get_maximum_password_length()
|
||||
@@ -101,8 +103,16 @@ class SetUserPasswordPlugin(base.BasePlugin):
|
||||
maximum_length)
|
||||
|
||||
osutils.set_user_password(user_name, password)
|
||||
self.post_set_password(user_name, password,
|
||||
password_injected=injected)
|
||||
return password
|
||||
|
||||
def post_set_password(self, username, password, password_injected=False):
|
||||
"""Executes post set password logic.
|
||||
|
||||
This is called by :meth:`execute` after the password was set.
|
||||
"""
|
||||
|
||||
def execute(self, service, shared_data):
|
||||
# TODO(alexpilotti): The username selection logic must be set in the
|
||||
# CreateUserPlugin instead if using CONF.username
|
||||
|
||||
65
cloudbaseinit/plugins/windows/setuserpassword.py
Normal file
65
cloudbaseinit/plugins/windows/setuserpassword.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Copyright 2015 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from cloudbaseinit.osutils import factory
|
||||
from cloudbaseinit.plugins.common import setuserpassword
|
||||
|
||||
CLEAR_TEXT_INJECTED_ONLY = 'clear_text_injected_only'
|
||||
ALWAYS_CHANGE = 'always'
|
||||
NEVER_CHANGE = 'no'
|
||||
LOGON_PASSWORD_CHANGE_OPTIONS = [
|
||||
CLEAR_TEXT_INJECTED_ONLY,
|
||||
NEVER_CHANGE,
|
||||
ALWAYS_CHANGE,
|
||||
]
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('first_logon_behaviour',
|
||||
default=CLEAR_TEXT_INJECTED_ONLY,
|
||||
choices=LOGON_PASSWORD_CHANGE_OPTIONS,
|
||||
help='Control the behaviour of what happens at '
|
||||
'next logon. If this option is set to `always`, '
|
||||
'then the user will be forced to change the password '
|
||||
'at next logon. If it is set to '
|
||||
'`clear_text_injected_only`, '
|
||||
'then the user will have to change the password only if '
|
||||
'the password is a clear text password, coming from the '
|
||||
'metadata. The last option is `no`, when the user is '
|
||||
'never forced to change the password.'),
|
||||
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(opts)
|
||||
|
||||
|
||||
class SetUserPasswordPlugin(setuserpassword.SetUserPasswordPlugin):
|
||||
"""Plugin for changing the password, tailored to Windows."""
|
||||
|
||||
def post_set_password(self, username, _, password_injected=False):
|
||||
"""Post set password logic
|
||||
|
||||
If the option is activated, force the user to change the
|
||||
password at next logon.
|
||||
"""
|
||||
if CONF.first_logon_behaviour == NEVER_CHANGE:
|
||||
return
|
||||
|
||||
clear_text = CONF.first_logon_behaviour == CLEAR_TEXT_INJECTED_ONLY
|
||||
always = CONF.first_logon_behaviour == ALWAYS_CHANGE
|
||||
if always or (clear_text and password_injected):
|
||||
osutils = factory.get_os_utils()
|
||||
osutils.change_password_next_logon(username)
|
||||
Reference in New Issue
Block a user