#!/usr/bin/env bash # Author:: Paul Mooring () # Author:: Steven Danna () # Copyright:: Copyright (c) 2013 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ## Default values ## verb=0 chef_server='api.opscode.com' ##################### help_msg(){ cat << EOF usage: ${0} [options] Options: -q Quiet -v Verbose -h Help -p Private Chef server (must provide -o ) -o Organization name (Hosted/Private Chef only) -c Name of requesting client (assumes key is named ${client_name}.pem) -s Chef server (host name or IP address) EOF } debug(){ if [ -z $2 ] ; then lvl=0 else lvl=$2 fi if [ $verb -gt $lvl ] ; then echo $1 fi } while getopts ":vqho:c:s:" opt; do case $opt in h) help_msg exit 0 ;; v) verb=$(expr $verb + 1) ;; q) verb=$(expr $verb - 1) ;; p) opc="true" ;; o) org_name=${OPTARG} ;; c) client_name=${OPTARG} ;; s) chef_server=${OPTARG} ;; \?) echo "Invalid option: -$OPTARG" >&2 help_msg exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 help_msg exit 1 ;; esac done body=$1 chomp(){ # helper function to remove newlines awk '{printf "%s", $0}' } chef_dir(){ # Use the argument if provided if [ ! -z $1 ] ; then echo -n $1 return # otherwise, look for the '.chef' directory elif [ "$PWD" = "/" ]; then if [ -d ".chef" ]; then echo -n "/.chef" elif [ -d "$HOME/.chef" ]; then echo -n "$HOME/.chef" fi else if [ -d '.chef' ];then echo -n "${PWD}/.chef" else (cd ..; chef_dir) fi fi } chef_server_path(){ if (echo $chef_server | grep -q "\.opscode\.com") || [ ! -z $opc ] ; then echo -n "https://${chef_server}/organizations/${org_name}" else echo -n "https://${chef_server}" fi } hash_string(){ echo -n $(echo -n $1 | openssl dgst -sha1 -binary | openssl enc -base64) } timestamp(){ echo -n $(date -u "+%Y-%m-%dT%H:%M:%SZ") } # takes method, hashed_path, hashed_body and client_name canonical_request(){ echo -n "Method:${1}\n\ Hashed Path:${2}\n\ X-Ops-Content-Hash:${3}\n\ X-Ops-Timestamp:$(timestamp)\n\ X-Ops-UserId:${4}" } # takes hashed_body, client_name headers(){ echo -n "-H X-Ops-Timestamp:$(timestamp) \ -H X-Ops-Userid:${2} \ -H X-Chef-Version:0.10.4 \ -H Accept:application/json \ -H X-Ops-Content-Hash:${1} \ -H X-Ops-Sign:version=1.0" } auth_headers(){ full_uri=$(hash_string $(chef_server_path)) req_body=$(hash_string ${body}) echo -n $(canonical_request "GET" $full_uri $req_body $client_name | \ openssl rsautl -sign -inkey "$(chef_dir)/${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 }}') } hdrs=$(headers $(hash_string $body) $client_name) auth_hdrs=$(auth_headers) path=$(chef_server_path) curl_command="curl $hdrs $auth_hdrs $path" $curl_command