diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a647a104f..79d8608abf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Ansible Changes By Release * cron module can now also manipulate cron.d files * virtualenv module can now inherit system site packages (or not) * able to set the environment by setting "environment:" as a dictionary on any task (go proxy support!) +* added ansible_ssh_user and ansible_ssh_pass for per-host/group username and password 1.0 "Eruption" -- Feb 1 2013 diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index 79f161568a..268371dea1 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -374,7 +374,6 @@ class Runner(object): module_name = utils.template(self.basedir, module_name, inject) module_args = utils.template(self.basedir, module_args, inject) - self.remote_user = utils.template(self.basedir, self.remote_user, inject) if module_name in utils.plugins.action_loader: if self.background != 0: @@ -394,6 +393,8 @@ class Runner(object): conn = None actual_host = inject.get('ansible_ssh_host', host) actual_port = port + actual_user = inject.get('ansible_ssh_user', self.remote_user) + actual_pass = inject.get('ansible_ssh_pass', self.remote_pass) if self.transport in [ 'paramiko', 'ssh' ]: actual_port = inject.get('ansible_ssh_port', port) @@ -414,6 +415,8 @@ class Runner(object): delegate_info = inject['hostvars'][delegate_to] actual_host = delegate_info.get('ansible_ssh_host', delegate_to) actual_port = delegate_info.get('ansible_ssh_port', port) + actual_user = delegate_info.get('ansible_ssh_user', actual_user) + actual_pass = delegate_info.get('ansible_ssh_pass', actual_pass) for i in delegate_info: if i.startswith("ansible_") and i.endswith("_interpreter"): inject[i] = delegate_info[i] @@ -421,6 +424,9 @@ class Runner(object): actual_host = delegate_to actual_port = port + actual_user = utils.template(self.basedir, actual_user, inject) + actual_pass = utils.template(self.basedir, actual_pass, inject) + try: if actual_port is not None: actual_port = int(actual_port) @@ -429,7 +435,7 @@ class Runner(object): return ReturnData(host=host, comm_ok=False, result=result) try: - conn = self.connector.connect(actual_host, actual_port) + conn = self.connector.connect(actual_host, actual_port, actual_user, actual_pass) if delegate_to or host != actual_host: conn.delegate = host diff --git a/lib/ansible/runner/connection.py b/lib/ansible/runner/connection.py index 46d61a336c..2e936f3652 100644 --- a/lib/ansible/runner/connection.py +++ b/lib/ansible/runner/connection.py @@ -31,10 +31,10 @@ class Connection(object): def __init__(self, runner): self.runner = runner - def connect(self, host, port): + def connect(self, host, port, user, password): conn = None transport = self.runner.transport - conn = utils.plugins.connection_loader.get(transport, self.runner, host, port) + conn = utils.plugins.connection_loader.get(transport, self.runner, host, port, user=user, password=password) if conn is None: raise AnsibleError("unsupported connection type: %s" % transport) self.active = conn.connect() diff --git a/lib/ansible/runner/connection_plugins/fireball.py b/lib/ansible/runner/connection_plugins/fireball.py index a126545f93..45fd4f524e 100644 --- a/lib/ansible/runner/connection_plugins/fireball.py +++ b/lib/ansible/runner/connection_plugins/fireball.py @@ -34,7 +34,7 @@ except ImportError: class Connection(object): ''' ZeroMQ accelerated connection ''' - def __init__(self, runner, host, port): + def __init__(self, runner, host, port, **kwargs): self.runner = runner diff --git a/lib/ansible/runner/connection_plugins/local.py b/lib/ansible/runner/connection_plugins/local.py index ea8c4ff359..dd044f2fff 100644 --- a/lib/ansible/runner/connection_plugins/local.py +++ b/lib/ansible/runner/connection_plugins/local.py @@ -29,7 +29,7 @@ from ansible.callbacks import vvv class Connection(object): ''' Local based connections ''' - def __init__(self, runner, host, port): + def __init__(self, runner, host, port, **kwargs): self.runner = runner self.host = host # port is unused, since this is local diff --git a/lib/ansible/runner/connection_plugins/paramiko_ssh.py b/lib/ansible/runner/connection_plugins/paramiko_ssh.py index 813abfca6e..67b5ce83cd 100644 --- a/lib/ansible/runner/connection_plugins/paramiko_ssh.py +++ b/lib/ansible/runner/connection_plugins/paramiko_ssh.py @@ -43,18 +43,18 @@ SFTP_CONNECTION_CACHE = {} class Connection(object): ''' SSH based connections with Paramiko ''' - def __init__(self, runner, host, port=None): + def __init__(self, runner, host, port, user, password): self.ssh = None self.sftp = None self.runner = runner self.host = host self.port = port - if port is None: - self.port = self.runner.remote_port + self.user = user + self.password = password def _cache_key(self): - return "%s__%s__" % (self.host, self.runner.remote_user) + return "%s__%s__" % (self.host, self.user) def connect(self): cache_key = self._cache_key() @@ -70,23 +70,21 @@ class Connection(object): if not HAVE_PARAMIKO: raise errors.AnsibleError("paramiko is not installed") - user = self.runner.remote_user - - vvv("ESTABLISH CONNECTION FOR USER: %s on PORT %s TO %s" % (user, self.port, self.host), host=self.host) + vvv("ESTABLISH CONNECTION FOR USER: %s on PORT %s TO %s" % (self.user, self.port, self.host), host=self.host) ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) allow_agent = True - if self.runner.remote_pass is not None: + if self.password is not None: allow_agent = False try: if self.runner.private_key_file: key_filename = os.path.expanduser(self.runner.private_key_file) else: key_filename = None - ssh.connect(self.host, username=user, allow_agent=allow_agent, look_for_keys=True, - key_filename=key_filename, password=self.runner.remote_pass, + ssh.connect(self.host, username=self.user, allow_agent=allow_agent, look_for_keys=True, + key_filename=key_filename, password=self.password, timeout=self.runner.timeout, port=self.port) except Exception, e: msg = str(e) @@ -94,7 +92,7 @@ class Connection(object): raise errors.AnsibleError("paramiko version issue, please upgrade paramiko on the machine running ansible") elif "Private key file is encrypted" in msg: msg = 'ssh %s@%s:%s : %s\nTo connect as a different user, use -u .' % ( - user, self.host, self.port, msg) + self.user, self.host, self.port, msg) raise errors.AnsibleConnectionFailed(msg) else: raise errors.AnsibleConnectionFailed(msg) @@ -161,7 +159,7 @@ class Connection(object): raise errors.AnsibleError("failed to transfer file to %s" % out_path) def _connect_sftp(self): - cache_key = "%s__%s__" % (self.host, self.runner.remote_user) + cache_key = "%s__%s__" % (self.host, self.user) if cache_key in SFTP_CONNECTION_CACHE: return SFTP_CONNECTION_CACHE[cache_key] else: diff --git a/lib/ansible/runner/connection_plugins/ssh.py b/lib/ansible/runner/connection_plugins/ssh.py index 1a9f623288..b7043a149d 100644 --- a/lib/ansible/runner/connection_plugins/ssh.py +++ b/lib/ansible/runner/connection_plugins/ssh.py @@ -31,15 +31,17 @@ from ansible import utils class Connection(object): ''' ssh based connections ''' - def __init__(self, runner, host, port): + def __init__(self, runner, host, port, user, password): self.runner = runner self.host = host self.port = port + self.user = user + self.password = password def connect(self): ''' connect to the remote host ''' - vvv("ESTABLISH CONNECTION FOR USER: %s" % self.runner.remote_user, host=self.host) + vvv("ESTABLISH CONNECTION FOR USER: %s" % self.user, host=self.host) self.common_args = [] extra_args = C.ANSIBLE_SSH_ARGS @@ -54,19 +56,19 @@ class Connection(object): self.common_args += ["-o", "Port=%d" % (self.port)] if self.runner.private_key_file is not None: self.common_args += ["-o", "IdentityFile="+os.path.expanduser(self.runner.private_key_file)] - if self.runner.remote_pass: + if self.password: self.common_args += ["-o", "GSSAPIAuthentication=no", "-o", "PubkeyAuthentication=no"] else: self.common_args += ["-o", "KbdInteractiveAuthentication=no", "-o", "PasswordAuthentication=no"] - self.common_args += ["-o", "User="+self.runner.remote_user] - self.common_args += ["-o", "ConnectTimeout="+str(self.runner.timeout)] + self.common_args += ["-o", "User="+self.user] + self.common_args += ["-o", "ConnectTimeout=%d" % self.runner.timeout] return self def _password_cmd(self): - if self.runner.remote_pass: + if self.password: try: p = subprocess.Popen(["sshpass"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -78,9 +80,9 @@ class Connection(object): return [] def _send_password(self): - if self.runner.remote_pass: + if self.password: os.close(self.rfd) - os.write(self.wfd, "%s\n" % self.runner.remote_pass) + os.write(self.wfd, "%s\n" % self.password) os.close(self.wfd) def exec_command(self, cmd, tmp_path, sudo_user,sudoable=False, executable='/bin/sh'):