2017-07-17 83 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

相关问题