2017-07-17 85 views
1

我寫了一個Bash腳本來實現廚師API,如GETPOSTchef-server-api:廚師服務器發出的「CURL」信息失敗

現在GET工程完美,而POST失敗。

#!/bin/bash 

# Chef Server API by bash. 

set -x 
_chomp() { 
    # helper function to remove newlines 
    awk '{printf "%s", $0}' 
} 

chef_api_request() { 
    # This is the meat-and-potatoes, or rice-and-vegetables, your preference really. 

    local method path body timestamp chef_server_url client_name hashed_body hashed_path 
    local canonical_request headers auth_headers 

    chef_server_url="https://chef.xxx.com:9443" 
    ca_cert="/root/.chef/trusted_certs/chef.xxx.com.crt" 

    method=$1 
    endpoint=${2%%\?*} 
    body=$3 

    path=${chef_server_url}$2 
    client_name="opscode" # from `knife user list`, and the one who is associated with the org when created by `chef-server-ctl org-create` 



    hashed_path=$(echo -n "$endpoint" | openssl dgst -sha1 -binary | openssl enc -base64) 
    hashed_body=$(echo -n "$body" | openssl dgst -sha1 -binary | openssl enc -base64) 
    timestamp=$(date -u "+%Y-%m-%dT%H:%M:%SZ") 

    canonical_request="Method:$method\nHashed Path:$hashed_path\nX-Ops-Content-Hash:$hashed_body\nX-Ops-Timestamp:$timestamp\nX-Ops-UserId:$client_name" 
    headers="-H X-Ops-Timestamp:$timestamp \ 
    -H X-Ops-Userid:$client_name \ 
    -H X-Chef-Version:12.15.8 \ 
    -H Accept:application/json \ 
    -H X-Ops-Content-Hash:$hashed_body \ 
    -H X-Ops-Sign:version=1.0" 

    auth_headers=$(printf "$canonical_request" | openssl rsautl -sign -inkey \ 
    "/etc/chef/${client_name}.pem" | openssl enc -base64 | _chomp | awk '{ll=int(length/60);i=0; \ 
    while (i<=ll) {printf " -H X-Ops-Authorization-%s:%s", i+1, substr($0,i*60+1,60);i=i+1}}') 

    case $method in 
    GET) 
     eval "curl --cacert $ca_cert $headers $auth_headers $path" 
     ;; 
    POST) 
    # Content-Type is needed when doing 'POST' and 'PUT'. 
     eval "curl --cacert $ca_cert -H Content-Type:application/json $headers $auth_headers $path" 
     ;; 
    *) 
     echo "Unknown Method. " >&2 
    exit 1 
     ;; 
    esac 
    } 

chef_api_request "[email protected]" 

現在我與

bash server_api.sh POST "/organizations"'{"name":"secure","full_name":"secure test1"}' 

運行錯誤是{"error":["Invalid signature for user or client 'opscode'"]}

而且從access_log,似乎POST不生效,GET仍在使用。

172.16.232.201 - - [17/Jul/2017:11:42:04 +0800] "GET /organizations HTTP/1.1" 401 "0.008" 60 "-" "curl/7.29.0" "127.0.0.1:8000" "401" "0.007" "12.15.8" "version=1.0" "opscode" "2017-07-17T03:42:04Z" "eWa1il2mhfy0QqcQDhcZx3Jda4w=" 785 

我知道POST通過curl將使用-d,但是從server api docs

我使用-d相當混亂。

任何幫助表示讚賞。 謝謝。

+0

你已經發布到郵件列表,你不需要發佈它獲得。那就是說,爲什麼要以所有聖潔的名義來做這件事?這可能不是不可能的,但使用像「chef-api」或「PyChef」這樣的真正的客戶端庫會更容易和更強大。 – coderanger

回答

1

一些事情。

首先,如果在eval行之前執行相同的操作,但是使用echo代替,則會發現更容易調試。這將把你的整個命令輸出到控制檯,你可以看到它在做什麼(並確保它按照你的預期格式化)。然後,您可以將其複製/粘貼到bash中,查看捲曲對其造成的影響。其次,當我看看我的示例curl命令躺在周圍,我已經把-H放在每個單獨的標題之前,而不是-H然後所有的標題必要的。現在,我想知道這是你需要做的事情,還是我不需要做的事情。

但主要的問題不放,與捲曲POST:

  • 你告訴它張貼與-X POST
  • 然後你提供的數據與-d選項

大概就像這個:

curl --cacert $ca_cert -H Content-Type:application/json $headers $auth_headers -X POST -d '$body' $path 
+0

謝謝你的啓發。有用。 官方文檔有點困惑。你的猜測是正確的。 再次感謝。 – newbie

+0

我以爲'body'是'base64(sha1(BODY))',並且不需要再次出現在POST請求中,這是完全錯誤的。 – newbie

+0

噢,access.log中的'GET'是因爲我沒有使用'-X',這會導致默認方法是'GET',它解釋了很多。 -X,--request (HTTP)指定在與HTTP服務器通信時使用的自定義請求方法。指定的請求將使用 而不是其他方法(默認爲GET)。 更多。 – newbie

相關問題