在PostgreSQL和Dynamics 365 Web API之间构建Python3身份验证代理服务器

在PostgreSQL和Dynamics 365 Web API之间构建Python3身份验证代理服务器,python,django,postgresql,proxy,microsoft-dynamics,Python,Django,Postgresql,Proxy,Microsoft Dynamics,经过几天的进步,我逐渐认识到,我缺乏知识或技能水平,无法把所有这些东西组合起来完成这个项目。因此,我呼吁并感谢任何能够帮助我解决这一问题的人 技术 CentOS 7.5 Python 3.6.0 Django 1.10.5 PostResql9.2 Microsoft CRM Dynamics 365 online拥有最新的客户端数据,因此必须使用Web API: 问题 CRM中包含最新的客户机数据,并希望将其引入PostgreSQL以用于多种用途 想要使用www_fdw,因为它是我见过的

经过几天的进步,我逐渐认识到,我缺乏知识或技能水平,无法把所有这些东西组合起来完成这个项目。因此,我呼吁并感谢任何能够帮助我解决这一问题的人

技术

  • CentOS 7.5
  • Python 3.6.0
  • Django 1.10.5
  • PostResql9.2
  • Microsoft CRM Dynamics 365 online拥有最新的客户端数据,因此必须使用Web API:
问题

  • CRM中包含最新的客户机数据,并希望将其引入PostgreSQL以用于多种用途
  • 想要使用
    www_fdw
    ,因为它是我见过的唯一一个可以使用Web API的PostgreSQL外部数据包装器:
  • Dynamics Web API使用OAuth2,并且
    www_fdw
    不支持任何类型的本机身份验证
  • www_fdw
    的开发人员交谈,他们建议使用代理服务器来处理与Microsoft的OAuth2身份验证
  • 带有
    www_fdw
    的PostgreSQL将与代理进行对话,代理将向Microsoft发送身份验证,最终能够将Web API视为外来表,从而将其视为任何其他表
这三个部分以及迄今为止已尝试的内容

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

  • www_fdw
    :基于此,我使用以下参数进行设置:

  • crmproxytest.py
    对于代理服务器,我一直在尝试使用以下链接创建一个简单的代理服务器:

    这看起来像是控制台上的
    端口12345服务,显示运行
    nmap-sT-O localhost
    ,当运行
    nmap
    时,控制台上运行服务器的一些活动。否则就无法从中获得任何活动

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

  • OAuth2。我整理了
    crm.py
    ,在与Microsoft交谈、整理了他们的文档并找到了以下链接后,它开始工作:

    简而言之,除了能够获得
    OAuth 2.0令牌URI
    OAuth 2.0授权URI
    之外,您还必须在Azure Active Directory中注册应用程序,以便获得
    client\u id
    client\u secret
    。然后,您可以向
    授权端点
    发送请求,如果凭据匹配,则会返回令牌,然后将令牌发送到
    令牌端点
    ,并最终授予对Web API的访问权

    这是我最后使用的代码,它可以工作,从Dynamics Web API检索数据,并在控制台中填充数据:

    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查询

  • 不管怎样,我希望我解释得足够好。看起来我得到了三个独立的拼图块,它们都是有效的,或者说是某种工作,但把它们都放在一起是我的难题
    crm.py
    crmtest.py
    可能需要组合,但不确定如何组合

    提前感谢您的帮助


    编辑:显然,在任何地方都有
    www\u ftw
    ,而不是
    www\u fdw

    在步骤1中设置fdw对我来说似乎没问题

    步骤2中的Python脚本顶部需要一个shebang。否则它将被视为bash,因此前3行将运行并将屏幕截图保存到名为
    http.server
    socketserver
    urllib
    的新文件中。这会使脚本在
    端口
    行上停止之前忙碌一段时间。同时(甚至在它死后),只运行
    curlhttp://localhost:12345
    给出与Postgres相同的错误:

    curl: (7) Failed to connect to localhost port 12345: Connection refused
    
    添加
    #后/usr/bin/env python3
    您的脚本将响应请求。例如,我可以说
    curlhttp://localhost:12345/etc/passwd
    并获得结果


    我不确定您打算如何连接第3步(OAuth),但希望这个答案能帮助您克服目前的障碍。

    嗨,保罗,我将按照您今天上午的建议进行操作。我认为目前最大的问题是将第2步和第3步结合在一起:设置一个Postgres可以与之对话的持久化进程,该进程将授权传递给Microsoft的OAuth2,以便它可以使用外部数据包装器查询Dynamics CRM Web API。@sockpuppet Paul的回答有帮助吗?如果是这样,请确保您接受它或添加注释,解释为什么这不是一个解决方案。
    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')
    
    curl: (7) Failed to connect to localhost port 12345: Connection refused