2017-02-10 86 views
0

我寫了一個小小的Python腳本,該腳本應該使用Python的requests模塊訪問描述爲here的IBM Bluemix容器API。IBM Bluemix身份驗證令牌始終無效

下面是腳本:

""" 
You can run this script for example as follows: 

python test-script.py \ 
--user <YOUR IBM BLUEMIX USER NAME> \ 
--ca-certificate <PATH TO YOUR ca.pem> \ 
--oauth-token "$(cf oauth-token)" \ 
--space-id "$(cf space dev --guid)" \ 
--request-url https://containers-api.ng.bluemix.net/v3/containers/version \ 
--method GET 

The request-url is an EXAMPLE! 
""" 

import argparse 
import getpass 
import requests 
import json 

# for parsing arguments provided on command line 
parser = argparse.ArgumentParser() 
parser.add_argument(
    '-u', '--user', 
    required=True, 
    help='Specify the username for IBM Bluemix.', 
) 
parser.add_argument(
    '-c', '--ca-certificate', 
    required=True, 
    help='Specify the location of the certificate of the trusted certification authority (ca.pem).' 
) 
parser.add_argument(
    '-t', '--oauth-token', 
    required=True, 
    help='Specify your IBM Bluemix oauth-token.' 
) 
parser.add_argument(
    '-s', '--space-id', 
    required=True, 
    help='Specify your IBM Bluemix space id (cf space <your space> --guid). Beware, the space needs to be available in the region you are logged in to (US South, United Kindom).' 
) 
parser.add_argument(
    '-l', '--request-url', 
    required=True, 
    default='https://containers-api.ng.bluemix.net/v3/containers/version', 
    help='Specify the URL you want to send the request to.' 
) 
parser.add_argument(
    '-m', '--method', 
    default='GET', 
    help='Specify the HTTP method.' 
) 

args = parser.parse_args() 

def run_script(): 
    password = getpass.getpass(prompt='IBM Bluemix password:') 
    # for now hard coded 
    headers = { 
     'Accept': 'application/json', 
     'X-Auth-Token': args.oauth_token, 
     'X-Auth-Project-Id': args.space_id 
    } 

    # first we get the appropriate HTTP request method 
    request_method = getattr(requests, args.method.lower()) 

    # then we try to make the request with that method 
    try: 
     response = request_method(
      args.request_url, 
      auth=(args.user, password), 
      data=None, # expects a dict or json.dumps return type 
      verify=args.ca_certificate, 
      headers=headers 
     ) 
     print(response) 
     print(response.json()) 
    except Exception as exc: 
     print('ERROR!') 

def main(): 
    try: 
     run_script() 
    except KeyboardInterrupt as exc: 
     exit('Interrupted, exiting ...') 

main() 

這個腳本我打電話:

python script.py \ 
--user <IBM Bluemix login name> \ 
--ca-certificate /home/<USER>/.ice/certs/containers-api.eu-gb.bluemix.net/<ID>/ca.pem \ 
--oauth-token "$(cf oauth-token)" \ 
--space-id "$(cf space dev --guid)" \ 
--request-url https://containers-api.ng.bluemix.net/v3/images/json \ 
--method GET 

對於--user參數我試過幾件事情:

  • 名字加上姓氏從IBM Bluemix儀表板頁面以兩個空格之間的空格作爲字符串"
  • 完整的電子郵件我用於註冊,這也標記User:當我做cf login
  • 組織名稱,其中顯示,當我做cf login

至於--space-id和身份驗證令牌--oauth-token: APi本身的文檔讓我按照自己的方式獲得它們。我也嘗試通過複製&粘貼我使用的子命令的粘貼,並從腳本中將它們打印出來,以確保它們全部進入腳本。它的確如此。

--request-url參數值我也從API文檔中獲得了,通過使用「Try it」按鈕並複製顯示的curl命令的URL,這被用於嘗試,因此也應該是正確的。

但是,在每個需要身份驗證的請求中(例如列出空間中所有圖像的請求),我從API獲得401響應,告訴我身份驗證令牌無效,我應該嘗試執行再次使用cf logincf ic init。做到這一點,不會更改我的令牌或任何東西,並且不會修復錯誤。

下面是一個例子迴應,我得到:

<Response [401]> 
{'code': 'IC5097E', 
'description': "Authentication was not successful: bearer <SOME ID> Please login via 'cf login ...' + 'cf ic init ...' and try again.", 
'environment': 'prod-dal09', 
'host_id': '176', 
'incident_id': '<SOME ID>', 
'name': 'InvalidToken', 
'rc': '401', 
'type': 'Infrastructure'} 

(我打破了線,以使其更具可讀性這裏SO)

所以我不知道我做錯了與令牌。我如何使用身份驗證令牌創建正確的請求?

編輯#1

我也使用解碼的https://jwt.io/ JSON網絡令牌。它顯示我輸入的用戶名確實是該令牌包含的用戶名。

編輯#2

我還檢查(再次)的空間可用:

IBM Bluemix Dashboard spaces overview

正如你可以看到有一個在這兩個地區命名爲dev空間。

回答

1

看起來你在混合英國和美國地區 - 我看到了eu-gb.bluemix.net和美國API服務器的證書。這可能是問題所在。我只在美國有一個空間,所以我無法測試這個,但是...

如果您在英國使用空間,請使用containers-api.eu-gb.bluemix.net cert和英國地區api服務器:https://containers-api.eu-gb.bluemix.net

如果您在美國使用空間,請使用containers-api.ng.bluemix.net的cert並使用該API服務器。

+0

這解決了它。我登錄了1個區域,但使用了另一個區域的API,認爲它是獨立的。然後'cf oauth-token'爲請求URL返回了錯誤的標記。另外需要知道的是,不能使用'cf oauth-token'的完整輸出,而只能使用'承載'(即承載空間)之後的所有輸出。 – Zelphir