mirror of https://github.com/jumpserver/jumpserver
perf: automations push ping verify
parent
994a484adb
commit
121ba1df07
|
@ -1,19 +1,68 @@
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import yaml
|
import yaml
|
||||||
|
import shutil
|
||||||
|
from hashlib import md5
|
||||||
|
from copy import deepcopy
|
||||||
|
from socket import gethostname
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.db.models import Model
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
|
from common.utils import ssh_pubkey_gen, ssh_key_string_to_obj
|
||||||
|
from assets.const import SecretType
|
||||||
from assets.automations.methods import platform_automation_methods
|
from assets.automations.methods import platform_automation_methods
|
||||||
from ops.ansible import JMSInventory, PlaybookRunner, DefaultCallback
|
from ops.ansible import JMSInventory, PlaybookRunner, DefaultCallback
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PushOrVerifyHostCallbackMixin:
|
||||||
|
execution: Model()
|
||||||
|
host_account_mapper: dict
|
||||||
|
ignore_account: bool
|
||||||
|
generate_public_key: callable
|
||||||
|
generate_private_key_path: callable
|
||||||
|
|
||||||
|
def host_callback(self, host, asset=None, account=None, automation=None, path_dir=None, **kwargs):
|
||||||
|
host = super().host_callback(host, asset=asset, account=account, automation=automation, **kwargs)
|
||||||
|
if host.get('error'):
|
||||||
|
return host
|
||||||
|
|
||||||
|
accounts = asset.accounts.all()
|
||||||
|
if self.ignore_account and account:
|
||||||
|
accounts = accounts.exclude(id=account.id)
|
||||||
|
|
||||||
|
if '*' not in self.execution.snapshot['accounts']:
|
||||||
|
accounts = accounts.filter(username__in=self.execution.snapshot['accounts'])
|
||||||
|
|
||||||
|
inventory_hosts = []
|
||||||
|
for account in accounts:
|
||||||
|
h = deepcopy(host)
|
||||||
|
h['name'] += '_' + account.username
|
||||||
|
self.host_account_mapper[h['name']] = account
|
||||||
|
secret = account.secret
|
||||||
|
|
||||||
|
private_key_path = None
|
||||||
|
if account.secret_type == SecretType.ssh_key:
|
||||||
|
private_key_path = self.generate_private_key_path(secret, path_dir)
|
||||||
|
secret = self.generate_public_key(secret)
|
||||||
|
|
||||||
|
h['secret_type'] = account.secret_type
|
||||||
|
h['account'] = {
|
||||||
|
'name': account.name,
|
||||||
|
'username': account.username,
|
||||||
|
'secret_type': account.secret_type,
|
||||||
|
'secret': secret,
|
||||||
|
'private_key_path': private_key_path
|
||||||
|
}
|
||||||
|
inventory_hosts.append(h)
|
||||||
|
return inventory_hosts
|
||||||
|
|
||||||
|
|
||||||
class PlaybookCallback(DefaultCallback):
|
class PlaybookCallback(DefaultCallback):
|
||||||
def playbook_on_stats(self, event_data, **kwargs):
|
def playbook_on_stats(self, event_data, **kwargs):
|
||||||
super().playbook_on_stats(event_data, **kwargs)
|
super().playbook_on_stats(event_data, **kwargs)
|
||||||
|
@ -66,20 +115,33 @@ class BasePlaybookManager:
|
||||||
method_attr = '{}_method'.format(self.__class__.method_type())
|
method_attr = '{}_method'.format(self.__class__.method_type())
|
||||||
|
|
||||||
method_enabled = automation and \
|
method_enabled = automation and \
|
||||||
getattr(automation, enabled_attr) and \
|
getattr(automation, enabled_attr) and \
|
||||||
getattr(automation, method_attr) and \
|
getattr(automation, method_attr) and \
|
||||||
getattr(automation, method_attr) in self.method_id_meta_mapper
|
getattr(automation, method_attr) in self.method_id_meta_mapper
|
||||||
|
|
||||||
if not method_enabled:
|
if not method_enabled:
|
||||||
host['error'] = _('{} disabled'.format(self.__class__.method_type()))
|
host['error'] = _('{} disabled'.format(self.__class__.method_type()))
|
||||||
return host
|
return host
|
||||||
return host
|
return host
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_public_key(private_key):
|
||||||
|
return ssh_pubkey_gen(private_key=private_key, hostname=gethostname())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_private_key_path(secret, path_dir):
|
||||||
|
key_name = '.' + md5(secret.encode('utf-8')).hexdigest()
|
||||||
|
key_path = os.path.join(path_dir, key_name)
|
||||||
|
if not os.path.exists(key_path):
|
||||||
|
ssh_key_string_to_obj(secret, password=None).write_private_key_file(key_path)
|
||||||
|
os.chmod(key_path, 0o400)
|
||||||
|
return key_path
|
||||||
|
|
||||||
def generate_inventory(self, platformed_assets, inventory_path):
|
def generate_inventory(self, platformed_assets, inventory_path):
|
||||||
inventory = JMSInventory(
|
inventory = JMSInventory(
|
||||||
manager=self,
|
|
||||||
assets=platformed_assets,
|
assets=platformed_assets,
|
||||||
account_policy=self.ansible_account_policy,
|
account_policy=self.ansible_account_policy,
|
||||||
|
host_callback=self.host_callback,
|
||||||
)
|
)
|
||||||
inventory.write_to_file(inventory_path)
|
inventory.write_to_file(inventory_path)
|
||||||
|
|
||||||
|
@ -105,7 +167,7 @@ class BasePlaybookManager:
|
||||||
def get_runners(self):
|
def get_runners(self):
|
||||||
runners = []
|
runners = []
|
||||||
for platform, assets in self.get_assets_group_by_platform().items():
|
for platform, assets in self.get_assets_group_by_platform().items():
|
||||||
assets_bulked = [assets[i:i+self.bulk_size] for i in range(0, len(assets), self.bulk_size)]
|
assets_bulked = [assets[i:i + self.bulk_size] for i in range(0, len(assets), self.bulk_size)]
|
||||||
|
|
||||||
for i, _assets in enumerate(assets_bulked, start=1):
|
for i, _assets in enumerate(assets_bulked, start=1):
|
||||||
sub_dir = '{}_{}'.format(platform.name, i)
|
sub_dir = '{}_{}'.format(platform.name, i)
|
||||||
|
@ -148,7 +210,7 @@ class BasePlaybookManager:
|
||||||
print(" inventory: {}".format(runner.inventory))
|
print(" inventory: {}".format(runner.inventory))
|
||||||
print(" playbook: {}".format(runner.playbook))
|
print(" playbook: {}".format(runner.playbook))
|
||||||
|
|
||||||
def run(self, *args, **kwargs):
|
def run(self, *args, **kwargs):
|
||||||
runners = self.get_runners()
|
runners = self.get_runners()
|
||||||
if len(runners) > 1:
|
if len(runners) > 1:
|
||||||
print("### 分批次执行开始任务, 总共 {}\n".format(len(runners)))
|
print("### 分批次执行开始任务, 总共 {}\n".format(len(runners)))
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
login_password: "{{ jms_account.secret }}"
|
login_password: "{{ jms_account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
login_db: "{{ jms_asset.database }}"
|
login_db: "{{ jms_asset.category_property.db_name }}"
|
||||||
register: db_info
|
register: db_info
|
||||||
|
|
||||||
- name: Display PostgreSQL version
|
- name: Display PostgreSQL version
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
login_password: "{{ jms_account.secret }}"
|
login_password: "{{ jms_account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
db: "{{ jms_asset.database }}"
|
db: "{{ jms_asset.category_property.db_name }}"
|
||||||
name: "{{ account.username }}"
|
name: "{{ account.username }}"
|
||||||
password: "{{ account.secret }}"
|
password: "{{ account.secret }}"
|
||||||
when: db_info is succeeded
|
when: db_info is succeeded
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
login_password: "{{ account.secret }}"
|
login_password: "{{ account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
db: "{{ jms_asset.database }}"
|
db: "{{ jms_asset.category_property.db_name }}"
|
||||||
when:
|
when:
|
||||||
- db_info is succeeded
|
- db_info is succeeded
|
||||||
- change_info is succeeded
|
- change_info is succeeded
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
- hosts: demo
|
|
||||||
gather_facts: no
|
|
||||||
tasks:
|
|
||||||
- name: Test privileged account
|
|
||||||
ansible.builtin.ping:
|
|
||||||
#
|
|
||||||
# - name: print variables
|
|
||||||
# debug:
|
|
||||||
# msg: "Username: {{ account.username }}, Secret: {{ account.secret }}, Secret type: {{ secret_type }}"
|
|
||||||
|
|
||||||
- name: Change password
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: "{{ account.username }}"
|
|
||||||
password: "{{ account.secret | password_hash('sha512') }}"
|
|
||||||
update_password: always
|
|
||||||
when: secret_type == "password"
|
|
||||||
|
|
||||||
- name: create user If it already exists, no operation will be performed
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: "{{ account.username }}"
|
|
||||||
when: secret_type == "ssh_key"
|
|
||||||
|
|
||||||
- name: remove jumpserver ssh key
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
dest: "{{ kwargs.dest }}"
|
|
||||||
regexp: "{{ kwargs.regexp }}"
|
|
||||||
state: absent
|
|
||||||
when:
|
|
||||||
- secret_type == "ssh_key"
|
|
||||||
- kwargs.strategy == "set_jms"
|
|
||||||
|
|
||||||
- name: Change SSH key
|
|
||||||
ansible.builtin.authorized_key:
|
|
||||||
user: "{{ account.username }}"
|
|
||||||
key: "{{ account.secret }}"
|
|
||||||
exclusive: "{{ kwargs.exclusive }}"
|
|
||||||
when: secret_type == "ssh_key"
|
|
||||||
|
|
||||||
- name: Refresh connection
|
|
||||||
ansible.builtin.meta: reset_connection
|
|
||||||
|
|
||||||
- name: Verify password
|
|
||||||
ansible.builtin.ping:
|
|
||||||
become: no
|
|
||||||
vars:
|
|
||||||
ansible_user: "{{ account.username }}"
|
|
||||||
ansible_password: "{{ account.secret }}"
|
|
||||||
ansible_become: no
|
|
||||||
when: secret_type == "password"
|
|
||||||
|
|
||||||
- name: Verify SSH key
|
|
||||||
ansible.builtin.ping:
|
|
||||||
become: no
|
|
||||||
vars:
|
|
||||||
ansible_user: "{{ account.username }}"
|
|
||||||
ansible_ssh_private_key_file: "{{ account.private_key_path }}"
|
|
||||||
ansible_become: no
|
|
||||||
when: secret_type == "ssh_key"
|
|
|
@ -1,6 +0,0 @@
|
||||||
id: change_secret_aix
|
|
||||||
name: Change password for AIX
|
|
||||||
category: host
|
|
||||||
type:
|
|
||||||
- aix
|
|
||||||
method: change_secret
|
|
|
@ -1,14 +1,11 @@
|
||||||
import os
|
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
from hashlib import md5
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from socket import gethostname
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from common.utils import lazyproperty, gen_key_pair, ssh_pubkey_gen, ssh_key_string_to_obj
|
from common.utils import lazyproperty, gen_key_pair
|
||||||
from assets.models import ChangeSecretRecord
|
from assets.models import ChangeSecretRecord
|
||||||
from assets.const import (
|
from assets.const import (
|
||||||
AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy, DEFAULT_PASSWORD_RULES
|
AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy, DEFAULT_PASSWORD_RULES
|
||||||
|
@ -39,19 +36,6 @@ class ChangeSecretManager(BasePlaybookManager):
|
||||||
private_key, public_key = gen_key_pair()
|
private_key, public_key = gen_key_pair()
|
||||||
return private_key
|
return private_key
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def generate_public_key(private_key):
|
|
||||||
return ssh_pubkey_gen(private_key=private_key, hostname=gethostname())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def generate_private_key_path(secret, path_dir):
|
|
||||||
key_name = '.' + md5(secret.encode('utf-8')).hexdigest()
|
|
||||||
key_path = os.path.join(path_dir, key_name)
|
|
||||||
if not os.path.exists(key_path):
|
|
||||||
ssh_key_string_to_obj(secret, password=None).write_private_key_file(key_path)
|
|
||||||
os.chmod(key_path, 0o400)
|
|
||||||
return key_path
|
|
||||||
|
|
||||||
def generate_password(self):
|
def generate_password(self):
|
||||||
kwargs = self.execution.snapshot['password_rules'] or {}
|
kwargs = self.execution.snapshot['password_rules'] or {}
|
||||||
length = int(kwargs.get('length', DEFAULT_PASSWORD_RULES['length']))
|
length = int(kwargs.get('length', DEFAULT_PASSWORD_RULES['length']))
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from .change_secret.manager import ChangeSecretManager
|
from .change_secret.manager import ChangeSecretManager
|
||||||
from .gather_facts.manager import GatherFactsManager
|
from .gather_facts.manager import GatherFactsManager
|
||||||
from .gather_accounts.manager import GatherAccountsManager
|
from .gather_accounts.manager import GatherAccountsManager
|
||||||
|
from .verify_account.manager import VerifyAccountManager
|
||||||
|
from .push_account.manager import PushAccountManager
|
||||||
from ..const import AutomationTypes
|
from ..const import AutomationTypes
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +11,8 @@ class ExecutionManager:
|
||||||
AutomationTypes.change_secret: ChangeSecretManager,
|
AutomationTypes.change_secret: ChangeSecretManager,
|
||||||
AutomationTypes.gather_facts: GatherFactsManager,
|
AutomationTypes.gather_facts: GatherFactsManager,
|
||||||
AutomationTypes.gather_accounts: GatherAccountsManager,
|
AutomationTypes.gather_accounts: GatherAccountsManager,
|
||||||
|
AutomationTypes.verify_account: VerifyAccountManager,
|
||||||
|
AutomationTypes.push_account: PushAccountManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, execution):
|
def __init__(self, execution):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
- hosts: mysql
|
- hosts: mysql
|
||||||
gather_facts: no
|
gather_facts: no
|
||||||
vars:
|
vars:
|
||||||
ansible_python_interpreter: /usr/local/bin/python
|
ansible_python_interpreter: /Users/xiaofeng/Desktop/jumpserver/venv/bin/python
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Get info
|
- name: Get info
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
login_user: "{{ jms_account.username }}"
|
login_user: "{{ jms_account.username }}"
|
||||||
login_password: "{{ jms_account.secret }}"
|
login_password: "{{ jms_account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: 1234
|
||||||
filter: users
|
filter: users
|
||||||
register: db_info
|
register: db_info
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
login_password: "{{ jms_account.secret }}"
|
login_password: "{{ jms_account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
login_db: "{{ jms_asset.database }}"
|
login_db: "{{ jms_asset.category_property.db_name }}"
|
||||||
filter: "roles"
|
filter: "roles"
|
||||||
register: db_info
|
register: db_info
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
gather_facts: no
|
gather_facts: no
|
||||||
tasks:
|
tasks:
|
||||||
- name: Gather posix account
|
- name: Gather posix account
|
||||||
ansible.builtin.win_shell:
|
ansible.builtin.shell:
|
||||||
cmd: net user
|
cmd: >
|
||||||
|
users=$(getent passwd | grep -v nologin | grep -v shutdown | awk -F":" '{ print $1 }');for i in $users;
|
||||||
|
do last -w -F $i -1 | head -1 | grep -v ^$ | awk '{ print $1"@"$3"@"$5,$6,$7,$8 }';done
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
- name: Define info by set_fact
|
- name: Define info by set_fact
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
- hosts: windows
|
- hosts: demo
|
||||||
gather_facts: yes
|
gather_facts: no
|
||||||
tasks:
|
tasks:
|
||||||
- name: Get info
|
- name: Gather posix account
|
||||||
set_fact:
|
ansible.builtin.win_shell:
|
||||||
info:
|
cmd: net user
|
||||||
arch: "{{ ansible_architecture2 }}"
|
register: result
|
||||||
distribution: "{{ ansible_distribution }}"
|
|
||||||
distribution_version: "{{ ansible_distribution_version }}"
|
- name: Define info by set_fact
|
||||||
kernel: "{{ ansible_kernel }}"
|
ansible.builtin.set_fact:
|
||||||
vendor: "{{ ansible_system_vendor }}"
|
info: "{{ result.stdout_lines }}"
|
||||||
model: "{{ ansible_product_name }}"
|
|
||||||
sn: "{{ ansible_product_serial }}"
|
|
||||||
cpu_vcpus: "{{ ansible_processor_vcpus }}"
|
|
||||||
memory: "{{ ansible_memtotal_mb }}"
|
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
var: info
|
var: info
|
|
@ -2,7 +2,7 @@ from common.utils import get_logger
|
||||||
from assets.const import AutomationTypes
|
from assets.const import AutomationTypes
|
||||||
from orgs.utils import tmp_to_org
|
from orgs.utils import tmp_to_org
|
||||||
from .filter import GatherAccountsFilter
|
from .filter import GatherAccountsFilter
|
||||||
from ...models import Account, GatheredUser
|
from ...models import GatheredUser
|
||||||
from ..base.manager import BasePlaybookManager
|
from ..base.manager import BasePlaybookManager
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
@ -42,4 +42,4 @@ class GatherAccountsManager(BasePlaybookManager):
|
||||||
defaults['ip_last_login'] = data['address'][:32]
|
defaults['ip_last_login'] = data['address'][:32]
|
||||||
GatheredUser.objects.update_or_create(defaults=defaults, asset=asset, username=username)
|
GatheredUser.objects.update_or_create(defaults=defaults, asset=asset, username=username)
|
||||||
else:
|
else:
|
||||||
logger.error("Not found info, task name must be 'Get info': {}".format(host))
|
logger.error("Not found info".format(host))
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
login_password: "{{ jms_account.secret }}"
|
login_password: "{{ jms_account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
login_db: "{{ jms_asset.database }}"
|
login_db: "{{ jms_asset.category_property.db_name }}"
|
||||||
register: db_info
|
register: db_info
|
||||||
|
|
||||||
- name: Define info by set_fact
|
- name: Define info by set_fact
|
||||||
|
|
|
@ -26,4 +26,4 @@ class GatherFactsManager(BasePlaybookManager):
|
||||||
asset.info = info
|
asset.info = info
|
||||||
asset.save()
|
asset.save()
|
||||||
else:
|
else:
|
||||||
logger.error("Not found info, task name must be 'Get info': {}".format(host))
|
logger.error("Not found info: {}".format(host))
|
||||||
|
|
|
@ -2,12 +2,6 @@
|
||||||
gather_facts: no
|
gather_facts: no
|
||||||
vars:
|
vars:
|
||||||
ansible_python_interpreter: /usr/local/bin/python
|
ansible_python_interpreter: /usr/local/bin/python
|
||||||
jms_account:
|
|
||||||
username: root
|
|
||||||
password: redhat
|
|
||||||
jms_asset:
|
|
||||||
address: 127.0.0.1
|
|
||||||
port: 3306
|
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test MySQL connection
|
- name: Test MySQL connection
|
||||||
|
@ -17,4 +11,3 @@
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
filter: version
|
filter: version
|
||||||
register: db_info
|
|
||||||
|
|
|
@ -2,16 +2,6 @@
|
||||||
gather_facts: no
|
gather_facts: no
|
||||||
vars:
|
vars:
|
||||||
ansible_python_interpreter: /usr/local/bin/python
|
ansible_python_interpreter: /usr/local/bin/python
|
||||||
jms_account:
|
|
||||||
username: postgre
|
|
||||||
secret: postgre
|
|
||||||
jms_asset:
|
|
||||||
address: 127.0.0.1
|
|
||||||
port: 5432
|
|
||||||
database: testdb
|
|
||||||
account:
|
|
||||||
username: test
|
|
||||||
secret: jumpserver
|
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test PostgreSQL connection
|
- name: Test PostgreSQL connection
|
||||||
|
@ -20,4 +10,4 @@
|
||||||
login_password: "{{ jms_account.secret }}"
|
login_password: "{{ jms_account.secret }}"
|
||||||
login_host: "{{ jms_asset.address }}"
|
login_host: "{{ jms_asset.address }}"
|
||||||
login_port: "{{ jms_asset.port }}"
|
login_port: "{{ jms_asset.port }}"
|
||||||
login_db: "{{ jms_asset.database }}"
|
login_db: "{{ jms_asset.category_property.db_name }}"
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
gather_facts: no
|
gather_facts: no
|
||||||
tasks:
|
tasks:
|
||||||
- name: Windows ping
|
- name: Windows ping
|
||||||
win_ping:
|
ansible.builtin.win_ping:
|
||||||
|
|
|
@ -6,4 +6,15 @@ logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PingManager(BasePlaybookManager):
|
class PingManager(BasePlaybookManager):
|
||||||
pass
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.host_asset_mapper = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def method_type(cls):
|
||||||
|
return AutomationTypes.ping
|
||||||
|
|
||||||
|
def host_callback(self, host, asset=None, **kwargs):
|
||||||
|
super().host_callback(host, asset=asset, **kwargs)
|
||||||
|
self.host_asset_mapper[host['name']] = asset
|
||||||
|
return host
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
- hosts: mysql
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /usr/local/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Add user account.username
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
login_user: "{{ jms_account.username }}"
|
||||||
|
login_password: "{{ jms_account.secret }}"
|
||||||
|
login_host: "{{ jms_asset.address }}"
|
||||||
|
login_port: "{{ jms_asset.port }}"
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
password: "{{ account.secret }}"
|
||||||
|
host: "%"
|
|
@ -0,0 +1,6 @@
|
||||||
|
id: push_account_mysql
|
||||||
|
name: Push account from MySQL
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- mysql
|
||||||
|
method: push_account
|
|
@ -0,0 +1,16 @@
|
||||||
|
- hosts: postgresql
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /usr/local/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Add user account.username
|
||||||
|
community.postgresql.postgresql_user:
|
||||||
|
login_user: "{{ jms_account.username }}"
|
||||||
|
login_password: "{{ jms_account.secret }}"
|
||||||
|
login_host: "{{ jms_asset.address }}"
|
||||||
|
login_port: "{{ jms_asset.port }}"
|
||||||
|
db: "{{ jms_asset.category_property.db_name }}"
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
password: "{{ account.secret }}"
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
id: push_account_postgresql
|
||||||
|
name: Push account for PostgreSQL
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- postgresql
|
||||||
|
method: push_account
|
|
@ -0,0 +1,19 @@
|
||||||
|
- hosts: demo
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- name: Add user account.username
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
|
||||||
|
- name: Set account.username password
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
password: "{{ account.secret | password_hash('sha512') }}"
|
||||||
|
update_password: always
|
||||||
|
when: secret_type == "password"
|
||||||
|
|
||||||
|
- name: Set account.username SSH key
|
||||||
|
ansible.builtin.authorized_key:
|
||||||
|
user: "{{ account.username }}"
|
||||||
|
key: "{{ account.secret }}"
|
||||||
|
when: secret_type == "ssh_key"
|
|
@ -0,0 +1,7 @@
|
||||||
|
id: push_account_posix
|
||||||
|
name: Push posix account
|
||||||
|
category: host
|
||||||
|
type:
|
||||||
|
- linux
|
||||||
|
- unix
|
||||||
|
method: push_account
|
|
@ -0,0 +1,13 @@
|
||||||
|
- hosts: windows
|
||||||
|
gather_facts: yes
|
||||||
|
tasks:
|
||||||
|
- name: Add user account.username
|
||||||
|
ansible.windows.win_user:
|
||||||
|
vars:
|
||||||
|
fullname: "{{ account.username }}"
|
||||||
|
name: "{{ account.username }}"
|
||||||
|
password: "{{ account.secret }}"
|
||||||
|
state: present
|
||||||
|
password_expired: no
|
||||||
|
update_password: always
|
||||||
|
password_never_expires: yes
|
|
@ -0,0 +1,7 @@
|
||||||
|
id: push_account_windows
|
||||||
|
name: Push account windows
|
||||||
|
version: 1
|
||||||
|
method: push_account
|
||||||
|
category: host
|
||||||
|
type:
|
||||||
|
- windows
|
|
@ -0,0 +1,17 @@
|
||||||
|
from common.utils import get_logger
|
||||||
|
from assets.const import AutomationTypes
|
||||||
|
from ..base.manager import BasePlaybookManager, PushOrVerifyHostCallbackMixin
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PushAccountManager(PushOrVerifyHostCallbackMixin, BasePlaybookManager):
|
||||||
|
ignore_account = True
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.host_account_mapper = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def method_type(cls):
|
||||||
|
return AutomationTypes.push_account
|
|
@ -0,0 +1,13 @@
|
||||||
|
- hosts: mysql
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /usr/local/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Verify account
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
login_user: "{{ account.username }}"
|
||||||
|
login_password: "{{ account.secret }}"
|
||||||
|
login_host: "{{ jms_asset.address }}"
|
||||||
|
login_port: "{{ jms_asset.port }}"
|
||||||
|
filter: version
|
|
@ -0,0 +1,6 @@
|
||||||
|
id: verify_account_mysql
|
||||||
|
name: Verify account from MySQL
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- mysql
|
||||||
|
method: verify_account
|
|
@ -0,0 +1,13 @@
|
||||||
|
- hosts: postgresql
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_python_interpreter: /usr/local/bin/python
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Verify account
|
||||||
|
community.postgresql.postgresql_ping:
|
||||||
|
login_user: "{{ account.username }}"
|
||||||
|
login_password: "{{ account.secret }}"
|
||||||
|
login_host: "{{ jms_asset.address }}"
|
||||||
|
login_port: "{{ jms_asset.port }}"
|
||||||
|
db: "{{ jms_asset.category_property.db_name }}"
|
|
@ -0,0 +1,6 @@
|
||||||
|
id: verify_account_postgresql
|
||||||
|
name: Verify account for PostgreSQL
|
||||||
|
category: database
|
||||||
|
type:
|
||||||
|
- postgresql
|
||||||
|
method: verify_account
|
|
@ -0,0 +1,11 @@
|
||||||
|
- hosts: demo
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- name: Verify account
|
||||||
|
ansible.builtin.ping:
|
||||||
|
become: no
|
||||||
|
vars:
|
||||||
|
ansible_user: "{{ account.username }}"
|
||||||
|
ansible_password: "{{ account.secret }}"
|
||||||
|
ansible_ssh_private_key_file: "{{ account.private_key_path }}"
|
||||||
|
ansible_become: no
|
|
@ -0,0 +1,7 @@
|
||||||
|
id: verify_account_posix
|
||||||
|
name: Verify posix account
|
||||||
|
category: host
|
||||||
|
type:
|
||||||
|
- linux
|
||||||
|
- unix
|
||||||
|
method: verify_account
|
|
@ -0,0 +1,8 @@
|
||||||
|
- hosts: windows
|
||||||
|
gather_facts: yes
|
||||||
|
tasks:
|
||||||
|
- name: Verify account
|
||||||
|
ansible.windows.win_ping:
|
||||||
|
vars:
|
||||||
|
ansible_user: "{{ account.username }}"
|
||||||
|
ansible_password: "{{ account.secret }}"
|
|
@ -0,0 +1,7 @@
|
||||||
|
id: verify_account_windows
|
||||||
|
name: Verify account windows
|
||||||
|
version: 1
|
||||||
|
method: verify_account
|
||||||
|
category: host
|
||||||
|
type:
|
||||||
|
- windows
|
|
@ -0,0 +1,25 @@
|
||||||
|
from common.utils import get_logger
|
||||||
|
from assets.const import AutomationTypes, Connectivity
|
||||||
|
from ..base.manager import BasePlaybookManager, PushOrVerifyHostCallbackMixin
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class VerifyAccountManager(PushOrVerifyHostCallbackMixin, BasePlaybookManager):
|
||||||
|
ignore_account = False
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.host_account_mapper = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def method_type(cls):
|
||||||
|
return AutomationTypes.verify_account
|
||||||
|
|
||||||
|
def on_host_success(self, host, result):
|
||||||
|
account = self.host_account_mapper.get(host)
|
||||||
|
account.set_connectivity(Connectivity.ok)
|
||||||
|
|
||||||
|
def on_host_error(self, host, error, result):
|
||||||
|
account = self.host_account_mapper.get(host)
|
||||||
|
account.set_connectivity(Connectivity.failed)
|
|
@ -1,6 +1,6 @@
|
||||||
from .change_secret import *
|
from .change_secret import *
|
||||||
from .discovery_account import *
|
from .discovery_account import *
|
||||||
from .push_account import *
|
from .push_account import *
|
||||||
from .verify_secret import *
|
|
||||||
from .gather_facts import *
|
from .gather_facts import *
|
||||||
from .gather_accounts import *
|
from .gather_accounts import *
|
||||||
|
from .verify_account import *
|
||||||
|
|
|
@ -2,7 +2,6 @@ from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from common.db import fields
|
from common.db import fields
|
||||||
from common.const.choices import Trigger
|
|
||||||
from common.db.models import JMSBaseModel
|
from common.db.models import JMSBaseModel
|
||||||
from assets.const import AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy
|
from assets.const import AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy
|
||||||
from .base import BaseAutomation
|
from .base import BaseAutomation
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from assets.const import AutomationTypes
|
||||||
from .base import BaseAutomation
|
from .base import BaseAutomation
|
||||||
|
|
||||||
|
__all__ = ['PushAccountAutomation']
|
||||||
|
|
||||||
|
|
||||||
class PushAccountAutomation(BaseAutomation):
|
class PushAccountAutomation(BaseAutomation):
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Push automation")
|
|
||||||
|
|
||||||
def to_attr_json(self):
|
def save(self, *args, **kwargs):
|
||||||
attr_json = super().to_attr_json()
|
self.type = AutomationTypes.verify_account
|
||||||
attr_json.update({
|
super().save(*args, **kwargs)
|
||||||
'type': 'push_account'
|
|
||||||
})
|
class Meta:
|
||||||
return attr_json
|
verbose_name = _("Push asset account")
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from assets.const import AutomationTypes
|
||||||
from .base import BaseAutomation
|
from .base import BaseAutomation
|
||||||
|
|
||||||
|
__all__ = ['VerifyAccountAutomation']
|
||||||
|
|
||||||
|
|
||||||
class VerifyAccountAutomation(BaseAutomation):
|
class VerifyAccountAutomation(BaseAutomation):
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Verify account automation")
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
self.type = 'verify_account'
|
self.type = AutomationTypes.verify_account
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Verify asset account")
|
|
@ -49,7 +49,7 @@ class DefaultCallback:
|
||||||
}
|
}
|
||||||
self.result['ok'][host][task] = detail
|
self.result['ok'][host][task] = detail
|
||||||
|
|
||||||
def runer_on_failed(self, event_data, host=None, task=None, res=None, **kwargs):
|
def runner_on_failed(self, event_data, host=None, task=None, res=None, **kwargs):
|
||||||
detail = {
|
detail = {
|
||||||
'action': event_data.get('task_action', ''),
|
'action': event_data.get('task_action', ''),
|
||||||
'res': res,
|
'res': res,
|
||||||
|
|
|
@ -9,8 +9,10 @@ __all__ = ['JMSInventory']
|
||||||
|
|
||||||
|
|
||||||
class JMSInventory:
|
class JMSInventory:
|
||||||
def __init__(self, manager, assets=None, account_policy='smart',
|
def __init__(
|
||||||
account_prefer='root,administrator', host_callback=None):
|
self, assets=None, account_policy='smart',
|
||||||
|
account_prefer='root,administrator', host_callback=None
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
:param assets:
|
:param assets:
|
||||||
:param account_prefer: account username name if not set use account_policy
|
:param account_prefer: account username name if not set use account_policy
|
||||||
|
@ -79,10 +81,7 @@ class JMSInventory:
|
||||||
ssh_protocol_matched = list(filter(lambda x: x.name == 'ssh', protocols))
|
ssh_protocol_matched = list(filter(lambda x: x.name == 'ssh', protocols))
|
||||||
ssh_protocol = ssh_protocol_matched[0] if ssh_protocol_matched else None
|
ssh_protocol = ssh_protocol_matched[0] if ssh_protocol_matched else None
|
||||||
host['ansible_host'] = asset.address
|
host['ansible_host'] = asset.address
|
||||||
if asset.port == 0:
|
host['ansible_port'] = ssh_protocol.port if ssh_protocol else 22
|
||||||
host['ansible_port'] = ssh_protocol.port if ssh_protocol else 22
|
|
||||||
else:
|
|
||||||
host['ansible_port'] = asset.port
|
|
||||||
|
|
||||||
su_from = account.su_from
|
su_from = account.su_from
|
||||||
if platform.su_enabled and su_from:
|
if platform.su_enabled and su_from:
|
||||||
|
@ -166,9 +165,9 @@ class JMSInventory:
|
||||||
platform_assets = self.group_by_platform(self.assets)
|
platform_assets = self.group_by_platform(self.assets)
|
||||||
for platform, assets in platform_assets.items():
|
for platform, assets in platform_assets.items():
|
||||||
automation = platform.automation
|
automation = platform.automation
|
||||||
protocols = platform.protocols.all()
|
|
||||||
|
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
|
protocols = asset.protocols.all()
|
||||||
account = self.select_account(asset)
|
account = self.select_account(asset)
|
||||||
host = self.asset_to_host(asset, account, automation, protocols, platform)
|
host = self.asset_to_host(asset, account, automation, protocols, platform)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue