在PostgreSQL和Dynamics 365 Web API之间构建Python3验证代理服务器 [英] Building Python3 auth proxy server between PostgreSQL and Dynamics 365 Web API

查看:202
本文介绍了在PostgreSQL和Dynamics 365 Web API之间构建Python3验证代理服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过几天的进展,我正在考虑到我缺乏知识或技能水平,将所有这些作品整理在一起,完成这个项目。因此,我呼吁并感谢任何可以帮助我的人。

After several days of some progress, I am coming to terms with the fact I lack the knowledge, or level of skill, to put all of these pieces together and finish this project. Thus, I am appealing to, and grateful to, anyone who can help me out with this.

技术

  • CentOS 7.5
  • Python 3.6.0
  • Django 1.10.5
  • PostreSQL 9.2
  • Microsoft CRM Dynamics 365 online which has most current client data, thus have to use the Web API: https://msdn.microsoft.com/en-us/library/gg334767.aspx

问题


  • CRM拥有最新的客户端数据,并希望将其带入PostgreSQL以用于众多的东西

  • 要使用 www_fdw ,因为它是PostgreSQL看到的唯一可以使用Web API的外部数据包装器: https://github.com / cyga / www_fdw / wiki

  • Dynamics Web API使用OA uth2和 www_fdw 本身不支持任何类型的身份验证

  • www_fdw 谁建议使用代理服务器来处理与Microsoft的OAuth2身份验证

  • PostgreSQL与 www_fdw 会与代理商谈话,这将反过来将身份验证发送给Microsoft,最终能够将Web API视为外部表,以便像其他表格一样对待。

  • CRM has the most current client data in it and want to bring it into PostgreSQL to use for numerous things
  • Want to use www_fdw since it is the only foreign data wrapper I have seen for PostgreSQL than can use Web API's: https://github.com/cyga/www_fdw/wiki
  • The Dynamics Web API uses OAuth2 and www_fdw does not support any type of authentication natively
  • Talked to the dev of www_fdw who recommended making a proxy server to handle the OAuth2 authentication with Microsoft
  • PostgreSQL with www_fdw would talk to the proxy, which would in turn send authentication to Microsoft culminating in the ability to treat the Web API as a Foreign Table so that it is treated like any other table

三部分以及迄今为止所尝试的内容

三部分= www_fdw +代理服务器+ OAuth2


  1. www_fdw :我已根据以下参数进行安装: https://github.com / cyga / www_fdw / wiki /示例

  1. www_fdw: I have setup using the following parameters based on this: https://github.com/cyga/www_fdw/wiki/Examples

DROP EXTENSION IF EXISTS www_fdw CASCADE;
CREATE EXTENSION www_fdw;
CREATE SERVER crm FOREIGN DATA WRAPPER www_fdw OPTIONS
    (uri 'http://localhost:12345');  -- proxy server
CREATE USER MAPPING FOR current_user SERVER crm;

-- for testing trying to get 'name' out of the CRM 'accounts' table and
   naming the foreign table the same as the table in CRM
CREATE FOREIGN TABLE accounts (
    name varchar(255)
) SERVER crm;


  • crmproxytest.py 代理服务器,我一直在尝试使用这个链接来制作一个裸机: http://effbot.org/librarybook/simplehttpserver.htm

    import socketserver
    import http.server
    import urllib
    
    PORT = 12345
    
    class Proxy(http.server.SimpleHTTPRequestHandler):
        def do_GET(self):
            self.copyfile(urllib.urlopen(self.path), self.wfile)
    
    httpd = socketserver.ForkingTCPServer(('', PORT), Proxy)
    print ("serving at port", PORT)
    httpd.serve_forever()
    

    这似乎工作,因为它说在控制台上的端口12345 上运行,显示运行 nmap -sT -O localhost ,控制台上有一些活动运行运行 nmap 时的服务器。否则无法从中获取任何活动。

    This seems to work as it says serving at port 12345 on console, shows up running nmap -sT -O localhost, there is some activity on the console running the server when nmap is run. Otherwise can't get any activity out of it.

    运行 PostgreSQL中的SELECT * FROM accounts 导致无法从服务器获取响应:无法连接到:: 1:权限被拒绝

    的OAuth2 。我把它放在一起 crm.py ,并在与Microsoft交谈后排序文档,并找到以下链接: http://alexanderdevelopment.net/post/2016/11/ 27 / dynamics-365-and-python-integration-using-the-web-api /

    OAuth2. I put together crm.py and got it working after talking to Microsoft, sorting through their documentation, and the finding this link: http://alexanderdevelopment.net/post/2016/11/27/dynamics-365-and-python-integration-using-the-web-api/

    简而言之,你必须注册你的应用程序Azure Active Directory,以便您可以获得 client_id client_secret ,除了能够获取 OAuth 2.0令牌URI OAuth 2.0授权URI 。然后,您可以向 authorizationendpoint 发送请求,如果凭据匹配返回一个令牌,则该令牌将被发送到 tokenendpoint 并最终授予对Web API的访问权限。

    In a nutshell, you have to register your app with Azure Active Directory so that you can get a client_id, client_secret, in addition to being able to obtain the OAuth 2.0 Token URI and the OAuth 2.0 Authorization URI. You can then send a request to the authorizationendpoint, which if the credentials match it returns an token, the token is then sent to the tokenendpoint and access to the Web API is ultimately granted.

    这是我最终用到的代码,从Dynamics Web API中检索数据,并填充它在控制台中:

    This is the code I ended up with that works, retrieves data from the Dynamics Web API, and populates it in the console:

    import requests  
    import json
    
    #set these values to retrieve the oauth token
    crmorg = 'https://ORG.crm.dynamics.com' #base url for crm org  
    clientid = '00000000-0000-0000-0000-000000000000' #application client id  
    client_secret = 'SUPERSECRET'
    username = 'asd@asd.com' #username  
    userpassword = 'qwerty' #password
    authorizationendpoint =  'https://login.windows.net/ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ/oauth2/authorize'
    tokenendpoint = 'https://login.windows.net/ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ/oauth2/token' #oauth token endpoint
    
    #set these values to query your crm data
    crmwebapi = 'https://ORG.api.crm.dynamics.com/api/data/v8.2' #full path to web api endpoint  
    crmwebapiquery = '/accounts?$select=name&$orderby=name' #web api query (include leading /)
    
    #build the authorization token request
    tokenpost = {  
        'client_id':clientid,
        'client_secret': client_secret,
        'resource':crmorg,
        'oauthUrl': authorizationendpoint,
        'username':username,
        'password':userpassword,
        'grant_type':'password'
        }
    
    #make the token request
    tokenres = requests.post(tokenendpoint, data=tokenpost)
    
    #check the value of tokenres
    print(tokenres)
    
    #set accesstoken variable to empty string
    accesstoken = ''
    
    #extract the access token
    try:  
        accesstoken = tokenres.json()['access_token']
    except(KeyError):  
        #handle any missing key errors
        print('Could not get access token')
    
    # check point for debugging
    # print(accesstoken)
    
    #if we have an accesstoken
    if(accesstoken!=''):  
        #prepare the crm request headers
        crmrequestheaders = {
            'Authorization': 'Bearer ' + accesstoken,
            'OData-MaxVersion': '4.0',
            'OData-Version': '4.0',
            'Accept': 'application/json',
            'Content-Type': 'application/json; charset=utf-8',
            'Prefer': 'odata.maxpagesize=500',
            'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue'
            }
    
        #make the crm request
        crmres = requests.get(crmwebapi+crmwebapiquery, headers=crmrequestheaders)
    
        try:
            #get the response json
            crmresults = crmres.json()
    
            #loop through it
            for x in crmresults['value']:
                # print (x['fullname'] + ' - ' + x['contactid'])
                print (x['name'])
        except KeyError:
            #handle any missing key errors
            print('Could not parse CRM results')
    

    这样做就像一个魅力,但实际上是用来测试OAuth2用户。变量 crmwebapi crmwebapiquery 的组合查询并不是真的需要在PostgreSQL中,如果FDW正在工作,应该允许针对Web API运行SQL查询。

    This works like a charm, but is really for testing the OAuth2. The query in combination of variables crmwebapi and crmwebapiquery doesn't really need to be in there since PostgreSQL, if the FDW is working right, should allow for running SQL queries against the Web API.

    无论如何,我希望我很好地解释了这一切。似乎我有三个独立的拼图,工作,或工作,但把它在一起是我被卡住的地方。 crm.py crmtest.py 可能需要组合,但不知道如何。

    Anyway, I hope I explained this all well enough. It seems that I got three independent pieces of the puzzle that work, or kind of work, but bringing it all together is where I am stuck. crm.py and crmtest.py probably need to be combined, but not sure how.

    提前感谢帮助!

    编辑:显然已经有$ code> www_ftw 而不是 www_fdw

    Apparently had www_ftw everywhere instead of www_fdw.

    推荐答案

    在步骤1中设置FDW对我而言

    Setting up the FDW in Step 1 looks okay to me.

    您在第2步中的Python脚本需要顶部的一个shebang。否则将被视为bash,因此前3行运行 import(1 ) ,并将屏幕截图保存到名为 http.server socketserver ,和 urllib 。在 PORT 行之前,脚本会停止一段时间。在此期间(甚至死后),只运行 curl http:// localhost:12345 给出与Postgres相同的错误:

    Your Python script in Step 2 needs a shebang at the top. Otherwise it is treated as bash, so the first 3 lines run import(1) and save screenshots to new files named http.server, socketserver, and urllib. That keeps the script busy for a little while before it dies on the PORT line. In the meantime (or even after it dies), running just curl http://localhost:12345 gives the same error as Postgres:

    curl: (7) Failed to connect to localhost port 12345: Connection refused
    

    添加#!/ usr / bin / env python3 后,您的脚本将会回复请求。例如我可以说 curl http:// localhost:12345 / etc / passwd 并得到结果。

    After adding #!/usr/bin/env python3 your script will answer requests. For instance I can say curl http://localhost:12345/etc/passwd and get a result.

    我不知道你打算如何连接第3步(OAuth),但是希望这个答案可以让你过去阻碍你的目标。

    I'm not sure how you intend to wire up Step 3 (the OAuth), but hopefully this answer will get you past what is blocking you right now.

    这篇关于在PostgreSQL和Dynamics 365 Web API之间构建Python3验证代理服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆