mirror of https://github.com/jumpserver/jumpserver
perf: 修改change password linux ansible yaml
parent
a2c006f01b
commit
139540fafe
|
@ -49,10 +49,10 @@ class AccountViewSet(OrgBulkModelViewSet):
|
|||
filterset_class = AccountFilterSet
|
||||
serializer_classes = {
|
||||
'default': serializers.AccountSerializer,
|
||||
'verify_account': serializers.AssetTaskSerializer
|
||||
'verify': serializers.AssetTaskSerializer
|
||||
}
|
||||
rbac_perms = {
|
||||
'verify_account': 'assets.test_authbook',
|
||||
'verify': 'assets.test_authbook',
|
||||
'partial_update': 'assets.change_assetaccountsecret',
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
|||
def get_target_ip(self):
|
||||
return self.ip
|
||||
|
||||
def get_target_ssh_port(self):
|
||||
protocol = self.protocols.all().filter(name='ssh').first()
|
||||
return protocol.port if protocol else 22
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
warning = ''
|
||||
|
|
|
@ -66,7 +66,7 @@ class Platform(models.Model):
|
|||
'su_method': 'sudo',
|
||||
'domain_enabled': True,
|
||||
'change_password_enabled': True,
|
||||
'change_password_method': 'change_password_linux',
|
||||
'change_password_method': 'linux',
|
||||
'verify_account_enabled': True,
|
||||
'verify_account_method': 'ansible_posix_ping',
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ class Platform(models.Model):
|
|||
platform_ops_map = {
|
||||
('host', 'linux'): {
|
||||
**default_ok,
|
||||
'change_password_method': 'change_password_linux',
|
||||
'change_password_method': 'linux',
|
||||
'verify_account_method': 'ansible_posix_ping'
|
||||
},
|
||||
('host', 'windows'): {
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{% for account in accounts %}
|
||||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
||||
{% endfor %}
|
|
@ -1,6 +0,0 @@
|
|||
id: change_password_mysql
|
||||
name: Change password for MySQL
|
||||
category: database
|
||||
type:
|
||||
- mysql
|
||||
method: change_password
|
|
@ -1,27 +0,0 @@
|
|||
- name: ping
|
||||
ping:
|
||||
|
||||
#- name: print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.password }}"
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('des') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -1,10 +0,0 @@
|
|||
{% for account in accounts %}
|
||||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
||||
{% endfor %}
|
|
@ -1,6 +0,0 @@
|
|||
id: change_password_oracle
|
||||
name: Change password for Oracle
|
||||
method: change_password
|
||||
category: database
|
||||
type:
|
||||
- oracle
|
|
@ -1,27 +0,0 @@
|
|||
- name: ping
|
||||
ping:
|
||||
|
||||
#- name: print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.password }}"
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('des') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -1,10 +0,0 @@
|
|||
{% for account in accounts %}
|
||||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
||||
{% endfor %}
|
|
@ -1,6 +0,0 @@
|
|||
id: change_password_postgresql
|
||||
name: Change password for PostgreSQL
|
||||
category: database
|
||||
type:
|
||||
- postgresql
|
||||
method: change_password
|
|
@ -1,27 +0,0 @@
|
|||
- name: ping
|
||||
ping:
|
||||
|
||||
#- name: print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.password }}"
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('des') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -1,10 +0,0 @@
|
|||
{% for account in accounts %}
|
||||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
||||
{% endfor %}
|
|
@ -1,8 +0,0 @@
|
|||
id: change_password_sqlserver
|
||||
name: Change password for SQLServer
|
||||
version: 1
|
||||
category: database
|
||||
type:
|
||||
- sqlserver
|
||||
method: change_password
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
- name: ping
|
||||
ping:
|
||||
|
||||
#- name: print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.password }}"
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('des') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -1,10 +0,0 @@
|
|||
{% for account in accounts %}
|
||||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
||||
{% endfor %}
|
|
@ -1,6 +0,0 @@
|
|||
id: change_password_aix
|
||||
name: Change password for AIX
|
||||
category: host
|
||||
type:
|
||||
- aix
|
||||
method: change_password
|
|
@ -1,27 +0,0 @@
|
|||
- name: ping
|
||||
ping:
|
||||
|
||||
#- name: print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.password }}"
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('des') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -1,8 +0,0 @@
|
|||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
|
@ -1,7 +0,0 @@
|
|||
id: change_password_linux
|
||||
name: Change password for Linux
|
||||
category: host
|
||||
type:
|
||||
- unix
|
||||
- linux
|
||||
method: change_password
|
|
@ -1,23 +0,0 @@
|
|||
- name: Check connection
|
||||
ping:
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -1,10 +0,0 @@
|
|||
{% for account in accounts %}
|
||||
- hosts: {{ account.asset.name }}
|
||||
vars:
|
||||
account:
|
||||
username: {{ account.username }}
|
||||
password: {{ account.password }}
|
||||
public_key: {{ account.public_key }}
|
||||
roles:
|
||||
- change_password
|
||||
{% endfor %}
|
|
@ -1,7 +0,0 @@
|
|||
id: change_password_local_windows
|
||||
name: Change password local account for Windows
|
||||
version: 1
|
||||
method: change_password
|
||||
category: host
|
||||
type:
|
||||
- windows
|
|
@ -1,27 +0,0 @@
|
|||
- name: ping
|
||||
ping:
|
||||
|
||||
#- name: print variables
|
||||
# debug:
|
||||
# msg: "Username: {{ account.username }}, Password: {{ account.password }}"
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ account.username }}"
|
||||
password: "{{ account.password | password_hash('des') }}"
|
||||
update_password: always
|
||||
when: account.password
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ account.username }}"
|
||||
key: "{{ account.public_key }}"
|
||||
state: present
|
||||
when: account.public_key
|
||||
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
||||
ansible_ssh_connection: paramiko
|
|
@ -0,0 +1,32 @@
|
|||
import os
|
||||
import time
|
||||
import shutil
|
||||
from typing import List
|
||||
|
||||
from django.conf import settings
|
||||
from assets.models import Asset
|
||||
|
||||
|
||||
class BaseGeneratePlaybook:
|
||||
src_filepath: str
|
||||
|
||||
def __init__(self, assets: List[Asset], strategy):
|
||||
self.assets = assets
|
||||
self.strategy = strategy
|
||||
self.temp_folder = self.temp_folder_path()
|
||||
|
||||
@staticmethod
|
||||
def temp_folder_path():
|
||||
project_dir = settings.PROJECT_DIR
|
||||
tmp_dir = os.path.join(project_dir, 'tmp')
|
||||
filepath = os.path.join(tmp_dir, str(time.time()))
|
||||
return filepath
|
||||
|
||||
def del_temp_folder(self):
|
||||
shutil.rmtree(self.temp_folder)
|
||||
|
||||
def generate_temp_playbook(self):
|
||||
src = self.src_filepath
|
||||
dst = os.path.join(self.temp_folder, self.strategy)
|
||||
shutil.copytree(src, dst)
|
||||
return dst
|
|
@ -0,0 +1,104 @@
|
|||
import os
|
||||
import yaml
|
||||
import jinja2
|
||||
from typing import List
|
||||
|
||||
from django.conf import settings
|
||||
from assets.models import Asset
|
||||
from .base import BaseGeneratePlaybook
|
||||
|
||||
|
||||
class GenerateChangePasswordPlaybook(BaseGeneratePlaybook):
|
||||
|
||||
def __init__(
|
||||
self, assets: List[Asset], strategy, usernames, password='',
|
||||
private_key='', public_key='', key_strategy=''
|
||||
):
|
||||
super().__init__(assets, strategy)
|
||||
self.password = password
|
||||
self.public_key = public_key
|
||||
self.private_key = private_key
|
||||
self.key_strategy = key_strategy
|
||||
self.relation_asset_map = self.get_username_relation_asset_map(usernames)
|
||||
|
||||
def get_username_relation_asset_map(self, usernames):
|
||||
# TODO 没牛逼用户的资产 网关
|
||||
|
||||
complete_map = {
|
||||
asset: list(asset.accounts.value_list('username', flat=True))
|
||||
for asset in self.assets
|
||||
}
|
||||
|
||||
if '*' in usernames:
|
||||
return complete_map
|
||||
|
||||
relation_map = {}
|
||||
for asset, usernames in complete_map.items():
|
||||
relation_map[asset] = list(set(usernames) & set(usernames))
|
||||
return relation_map
|
||||
|
||||
@property
|
||||
def src_filepath(self):
|
||||
return os.path.join(
|
||||
settings.BASE_DIR, 'assets', 'playbooks', 'strategy',
|
||||
'change_password', 'roles', self.strategy
|
||||
)
|
||||
|
||||
def generate_hosts(self):
|
||||
host_pathname = os.path.join(self.temp_folder, 'hosts')
|
||||
with open(host_pathname, 'w', encoding='utf8') as f:
|
||||
for asset in self.relation_asset_map.keys():
|
||||
f.write(f'{asset.name}\n')
|
||||
|
||||
def generate_host_vars(self):
|
||||
host_vars_pathname = os.path.join(self.temp_folder, 'hosts', 'host_vars')
|
||||
os.makedirs(host_vars_pathname, exist_ok=True)
|
||||
for asset, usernames in self.relation_asset_map.items():
|
||||
host_vars = {
|
||||
'ansible_host': asset.get_target_ip(),
|
||||
'ansible_port': asset.get_target_ssh_port(), # TODO 需要根绝协议取端口号
|
||||
'ansible_user': asset.admin_user.username,
|
||||
'ansible_pass': asset.admin_user.username,
|
||||
'ansible_connection': 'ssh',
|
||||
'usernames': usernames,
|
||||
}
|
||||
pathname = os.path.join(host_vars_pathname, f'{asset.name}.yml')
|
||||
with open(pathname, 'w', encoding='utf8') as f:
|
||||
f.write(yaml.dump(host_vars, allow_unicode=True))
|
||||
|
||||
def generate_secret_key_files(self):
|
||||
if not self.private_key and not self.public_key:
|
||||
return
|
||||
|
||||
file_pathname = os.path.join(self.temp_folder, self.strategy, 'files')
|
||||
public_pathname = os.path.join(file_pathname, 'id_rsa.pub')
|
||||
private_pathname = os.path.join(file_pathname, 'id_rsa')
|
||||
|
||||
os.makedirs(file_pathname, exist_ok=True)
|
||||
with open(public_pathname, 'w', encoding='utf8') as f:
|
||||
f.write(self.public_key)
|
||||
with open(private_pathname, 'w', encoding='utf8') as f:
|
||||
f.write(self.private_key)
|
||||
|
||||
def generate_role_main(self):
|
||||
task_main_pathname = os.path.join(self.temp_folder, 'main.yaml')
|
||||
context = {
|
||||
'password': self.password,
|
||||
'key_strategy': self.key_strategy,
|
||||
'private_key_file': 'id_rsa' if self.private_key else '',
|
||||
'exclusive': 'no' if self.key_strategy == 'all' else 'yes',
|
||||
'jms_key': self.public_key.split()[2].strip() if self.public_key else '',
|
||||
}
|
||||
with open(task_main_pathname, 'r+', encoding='utf8') as f:
|
||||
string_var = f.read()
|
||||
f.seek(0, 0)
|
||||
response = jinja2.Template(string_var).render(context)
|
||||
results = yaml.safe_load(response)
|
||||
f.write(yaml.dump(results, allow_unicode=True))
|
||||
|
||||
def execute(self):
|
||||
self.generate_temp_playbook()
|
||||
self.generate_hosts()
|
||||
self.generate_host_vars()
|
||||
self.generate_secret_key_files()
|
||||
self.generate_role_main()
|
|
@ -0,0 +1,12 @@
|
|||
- hosts: all
|
||||
vars:
|
||||
connection_type: ssh
|
||||
password:
|
||||
value: {{ password}}
|
||||
public_key:
|
||||
value: {{ jms_key }}
|
||||
exclusive: {{ exclusive }}
|
||||
key_strategy: {{ key_strategy }}
|
||||
private_key_file: {{ private_key_file }}
|
||||
roles:
|
||||
- linux
|
|
@ -0,0 +1,36 @@
|
|||
- name: Check connection
|
||||
ping:
|
||||
|
||||
- name: Change password
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
password: "{{ password.value | password_hash('sha512') }}"
|
||||
update_password: always
|
||||
with_items: "{{ usernames }}"
|
||||
when: "{{ password.value }}"
|
||||
|
||||
- name: Change public key
|
||||
authorized_key:
|
||||
user: "{{ item }}"
|
||||
key: "{{ lookup('file', id_rsa.pub) }}"
|
||||
state: present
|
||||
exclusive: "{{ public_key.exclusive }}"
|
||||
with_items: "{{ usernames }}"
|
||||
when: "{{ public_key.value and key_strategy != 'set_jms' }}"
|
||||
|
||||
- name: Change public key
|
||||
lineinfile:
|
||||
user: "{{ item }}"
|
||||
dest: /home/{{ item }}/.ssh/authorized_keys regexp='.*{{ public_key.value }}$
|
||||
state: absent
|
||||
with_items: "{{ usernames }}"
|
||||
when: "{{ public_key.value and key_strategy == 'set_jms' }}"
|
||||
|
||||
- name: Verify user
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ item }}"
|
||||
ansible_pass: "{{ password.value }}"
|
||||
ansible_ssh_private_key_file: "{{ private_key_file }}"
|
||||
ansible_connection: "{{ connection_type | default('ssh') }}"
|
||||
with_items: "{{ usernames }}"
|
|
@ -0,0 +1,7 @@
|
|||
- hosts: all
|
||||
vars:
|
||||
connection_type: ssh
|
||||
password:
|
||||
value: {{ password}}
|
||||
roles:
|
||||
- linux
|
|
@ -0,0 +1,8 @@
|
|||
- name: Verify user
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ item }}"
|
||||
ansible_pass: "{{ password }}"
|
||||
ansible_connection: "{{ connection_type | default('ssh') }}"
|
||||
ansible_ssh_private_key_file: "{{ private_key_file }}"
|
||||
with_items: "{{ usernames }}"
|
|
@ -1,13 +0,0 @@
|
|||
- hosts: centos
|
||||
gather_facts: no
|
||||
vars:
|
||||
account:
|
||||
username: web
|
||||
password: test123
|
||||
|
||||
tasks:
|
||||
- name: Verify password
|
||||
ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
|
@ -1,10 +0,0 @@
|
|||
id: ansible_posix_ping
|
||||
name: Ansible posix ping
|
||||
description: Ansible ping
|
||||
category: host
|
||||
type:
|
||||
- linux
|
||||
- unix
|
||||
- macos
|
||||
- bsd
|
||||
method: verify_account
|
|
@ -1,13 +0,0 @@
|
|||
- hosts: centos
|
||||
gather_facts: no
|
||||
vars:
|
||||
account:
|
||||
username: web
|
||||
password: test123
|
||||
|
||||
tasks:
|
||||
- name: Verify password
|
||||
win_ping:
|
||||
vars:
|
||||
ansible_user: "{{ account.username }}"
|
||||
ansible_pass: "{{ account.password }}"
|
|
@ -1,6 +0,0 @@
|
|||
id: ansible_win_ping
|
||||
name: Ansible win ping
|
||||
category: host
|
||||
type:
|
||||
- windows
|
||||
method: verify_account
|
|
@ -6,7 +6,7 @@ class StrategyChoice(models.TextChoices):
|
|||
push = 'push', _('Push')
|
||||
verify = 'verify', _('Verify')
|
||||
collect = 'collect', _('Collect')
|
||||
change_auth = 'change_auth', _('Change auth')
|
||||
change_password = 'change_password', _('Change password')
|
||||
|
||||
|
||||
class SSHKeyStrategy(models.TextChoices):
|
||||
|
|
|
@ -10,7 +10,7 @@ class ExecutionManager:
|
|||
StrategyChoice.push: PushExecutionManager,
|
||||
StrategyChoice.verify: VerifyExecutionManager,
|
||||
StrategyChoice.collect: CollectExecutionManager,
|
||||
StrategyChoice.change_auth: ChangeAuthExecutionManager,
|
||||
StrategyChoice.change_password: ChangeAuthExecutionManager,
|
||||
}
|
||||
|
||||
def __new__(cls, execution):
|
||||
|
@ -23,7 +23,7 @@ class TaskHandler:
|
|||
StrategyChoice.push: PushHandler,
|
||||
StrategyChoice.verify: VerifyHandler,
|
||||
StrategyChoice.collect: CollectHandler,
|
||||
StrategyChoice.change_auth: ChangeAuthHandler,
|
||||
StrategyChoice.change_password: ChangeAuthHandler,
|
||||
}
|
||||
|
||||
def __new__(cls, task, show_step_info):
|
||||
|
|
Loading…
Reference in New Issue