saltstack-api使用详解

目录

1.1 salt-api安装

1.2 编写python脚本请求salt api接口

1.1 salt-api安装

  参考博客:https://www.jianshu.com/p/012ccdff93cc

  1、介绍

    1. saltsatck本身就提供了一套算完整的api,使用 CherryPy 来实现 restful 的 api,供外部的程序调用。

    2. salt-api需要安装,然后进行一些配置才可以正常使用

  2、安装salt-api,并设置开机启动

    yum -y install salt-api pyOpenSSL

    systemctl enable salt-api

  3、配置自签名证书

      cd /etc/pki/tls/certs/

      make testcert

Enter pass phrase:    ===>  输入加密短语,这里我使用salt2017
Verifying - Enter pass phrase:    ===>  确认加密短语
umask 77 ; \
/usr/bin/openssl req -utf8 -new -key /etc/pki/tls/private/localhost.key -x509 -days 365 -out /etc/pki/tls/certs/localhost.crt -set_serial 0
Enter pass phrase for /etc/pki/tls/private/localhost.key:    ===>  再次输入相同的加密短语
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

交互模式输入密码等
交互模式输入密码等

  4、解密key文件,生成无密码的key文件

    注:过程中需要输入key密码,该密码为之前生成证书时设置的密码

    cd /etc/pki/tls/private/

    openssl rsa -in localhost.key -out localhost_nopass.key

  5、修改文件权限

    chmod 755 /etc/pki/tls/certs/localhost.crt
    chmod 755 /etc/pki/tls/private/localhost.key
    chmod 755 /etc/pki/tls/private/localhost_nopass.key

  6、添加用户

    注:生产环境请使用密码复杂度高的密码,这里我使用 chnsys@2016

    useradd -M -s /sbin/nologin saltapi          # 创建用户 saltapi

    passwd saltapi                                    # 为用户saltapi设置密码

  7、配置salt-api

    sed -i '/#default_include/s/#default/default/g' /etc/salt/master

  8、创建/etc/salt/master.d/目录    

    mkdir -p /etc/salt/master.d/
    cd /etc/salt/master.d/
    touch eauth.conf
    touch api.conf

external_auth:
  pam:
    saltapi:   # 用户
      - .*     # 该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
eauth.conf
rest_cherrypy:
  port: 8001
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost_nopass.key
api.conf

  9、启动salt-api

    systemctl restart salt-master
    systemctl start salt-api
    ps -ef|grep salt-api
    netstat -lnput|grep 8001

  10、测试获取token

    curl -k https://192.168.56.11:8001/login -H "Accept: application/x-yaml"  -d username='saltapi'  -d password='chnsys@2016'  -d eauth='pam'

  11、调用test.ping

    curl -k https://192.168.56.11:8001/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 87cbb68e0babf3d0ad6b3741795667dbe62b3c11" -d client='local' -d tgt='*' -d fun='test.ping'

1.2 编写python脚本请求salt api接口

  1、使用python简单测试接口执行命令

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'junxi'


import requests
import json
try:
    import cookielib
except:
    import http.cookiejar as cookielib

# 使用urllib2请求https出错,做的设置
import ssl
context = ssl._create_unverified_context()

# 使用requests请求https出现警告,做的设置
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


salt_api = "https://192.168.56.11:8001/"


class SaltApi:
    """
    定义salt api接口的类
    初始化获得token
    """
    def __init__(self, url):
        self.url = url
        self.username = "saltapi"
        self.password = "chnsys@2016"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
            "Content-type": "application/json"
        }
        self.params = {'client': 'local', 'fun': '', 'tgt': ''}
        self.login_url = salt_api + "login"
        self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'}
        self.token = self.get_data(self.login_url, self.login_params)['token']
        self.headers['X-Auth-Token'] = self.token

    def get_data(self, url, params):
        send_data = json.dumps(params)
        request = requests.post(url, data=send_data, headers=self.headers, verify=False)
        response = request.json()
        result = dict(response)
        return result['return'][0]

    def salt_command(self, tgt, method, arg=None):
        """远程执行命令,相当于salt 'client1' cmd.run 'free -m'"""
        if arg:
            params = {'client': 'local', 'fun': method, 'tgt': tgt, 'arg': arg}
        else:
            params = {'client': 'local', 'fun': method, 'tgt': tgt}
        print '命令参数: ', params
        result = self.get_data(self.url, params)
        return result

def main():
    salt = SaltApi(salt_api)
    salt_client = '*'
    salt_test = 'test.ping'
    result1 = salt.salt_command(salt_client, salt_test)
    print result1
    # 返回结果:{u'linux-node1.example.com': True, u'linux-node2.example.com': True}

if __name__ == '__main__':
    main()

使用python简单测试接口执行命令
使用python简单测试接口执行命令

  2、使用requests模块获取基本信息

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import json
import logging
logging.captureWarnings(True)  # 屏蔽由于访问https时没有证书警告问题

SALT_BASE_URL = 'https://192.168.56.11:8001/'
SALT_USER = 'saltapi'
SALT_PWD = 'chnsys@2016'


class SaltAPI(object):
    __token_id = ''

    def __init__(self):
        self.__url = SALT_BASE_URL
        self.__user = SALT_USER
        self.__password = SALT_PWD

    def token_id(self):
        """
            用户登陆和获取token
        :return:
        """
        params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
        content = self.postRequest(self.__url + '/login', data=params)
        try:
            self.__token_id = content[0]['token']
        except Exception as e:
            print '**** Failed to get token, {} ****'.format(str(e))

    def postRequest(self, url, data=None):
        headers = {"X-Auth-Token": self.__token_id}
        ret = requests.post(url=url, data=data, json='json', headers=headers, verify=False)
        if ret.status_code == 200:
            return ret.json()['return']
        return ret.text

    def remote_execution_module(self, tgt, fun, arg):
        """
            远程执行模块,有参数
        :param tgt: minion list
        :param fun: 模块
        :param arg: 参数
        :return: dict, {'minion1': 'ret', 'minion2': 'ret'}
        """
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
        self.token_id()
        return self.postRequest(self.__url, params)

    def salt_alive(self, tgt):
        '''
        salt主机存活检测
        '''
        params = {'client': 'local', 'tgt': tgt, 'fun': 'test.ping'}
        self.token_id()
        return self.postRequest(self.__url, params)


if __name__ == '__main__':
    salt = SaltAPI()
    minions_list = [
        'cloud:type',
        'cluster:domain',
        'cluster:name',
        'cpu_model',
        'fqdn_ip4',
        'hospital:type',
        'kernelrelease',
        'nodename',
        'os',
        'osmajorrelease',
        'osrelease',
        'saltversion',
        'serialnumber',
        'virtual',
        'num_cpus',
        'mem_total',
        'cloud:region',
        'ipv4',
    ]
    ret = salt.remote_execution_module('*', 'grains.item', minions_list)
    print json.dumps(ret, ensure_ascii=False)


'''
[{
    "linux-node1.example.com": {
        "osrelease": "7.6.1810",
        "fqdn_ip4": ["192.168.56.11"],
        "serialnumber": "VMware-56 4d 26 83 60 7c bb 5a-14 17 6a ab c2 45 f2 7a",
        "nodename": "linux-node1.example.com",
        "kernelrelease": "3.10.0-957.1.3.el7.x86_64",
        "cloud:type": "",
        "num_cpus": 1,
        "saltversion": "2018.3.3",
        "cpu_model": "Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz",
        "virtual": "VMware",
        "cluster:domain": "",
        "cluster:name": "",
        "osmajorrelease": 7,
        "hospital:type": "",
        "cloud:region": "",
        "os": "CentOS",
        "ipv4": ["127.0.0.1", "192.168.56.11"],
        "mem_total": 1819
    },
    "linux-node2.example.com": {
        "osrelease": "7.6.1810",
        "fqdn_ip4": ["192.168.56.12"],
        "serialnumber": "VMware-56 4d 09 af 9d 33 70 99-e9 7b 6d b2 5a 3b 7f 22",
        "nodename": "linux-node2.example.com",
        "kernelrelease": "3.10.0-957.1.3.el7.x86_64",
        "cloud:type": "",
        "num_cpus": 1,
        "saltversion": "2018.3.3",
        "cpu_model": "Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz",
        "virtual": "VMware",
        "cluster:domain": "",
        "cluster:name": "",
        "osmajorrelease": 7,
        "hospital:type": "",
        "cloud:region": "",
        "os": "CentOS",
        "ipv4": ["127.0.0.1", "192.168.56.12"],
        "mem_total": 1819
    }
}]
'''

使用requests模块获取基本信息
使用requests模块获取基本信息

  3、解决访问无证书https报错:requests.exceptions.SSLError: HTTPSConnectionPool

    参考博客:https://blog.csdn.net/qq_31077649/article/details/79013199

    1)安装相关模块:

      pip install cryptography
      pip install pyOpenSSL
      pip install certifi

    2)关闭证书验证(verify=False)

      ret = requests.post(url=url, data=data, json='json', headers=headers, verify=False)

posted @ 2020-05-10 15:15  Mr-刘  阅读(756)  评论(0编辑  收藏  举报