コード例 #1
0
ファイル: hmacurl.go プロジェクト: jburks725/hmacurl
func main() {

	var accessKey string
	var secretKey string

	// if we werent provided these arguments, pull from environment
	if opts.AccessKey == "" {
		if os.Getenv("HMACURL_ACCESS_KEY") == "" {
			fmt.Println("Please provide access key via argument or environment variable HMACURL_ACCESS_KEY")
			os.Exit(3)
		} else {
			accessKey = os.Getenv("HMACURL_ACCESS_KEY")
		}
	} else {
		accessKey = opts.AccessKey
	}
	if opts.SecretKey == "" {
		if os.Getenv("HMACURL_SECRET_KEY") == "" {
			fmt.Println("Please provide secret key via argument or environment variable HMACURL_SECRET_KEY")
			os.Exit(3)
		} else {
			secretKey = os.Getenv("HMACURL_SECRET_KEY")
		}
	} else {
		secretKey = opts.SecretKey
	}

	if validation.Method(opts.Request) == false {
		fmt.Printf("method %s is invalid\n", opts.Request)
		os.Exit(1)
	}

	urlString, err := url.Parse(opts.Args.Url)

	if err != nil {
		fmt.Printf("Invalid url %s\n", opts.Args.Url)
		os.Exit(2)
	}

	var payload string
	if opts.Request == "POST" {
		if opts.Data != "" {
			payload = opts.Data
		} else if opts.File != "" {
			fileContents, err := ioutil.ReadFile(opts.File)
			if err != nil {
				panic(err)
			}
			// reading from file seems to put a newline at end - trim this
			payload = strings.TrimSuffix(string(fileContents[:]), "\n")
		}
	}
	requestTime := time.Now().UTC()
	host, _, err := net.SplitHostPort(urlString.Host)
	// likely no port
	if err != nil {
		host = urlString.Host
	}

	credentialScope := opts.CredentialScope
	if opts.CredentialScope == "" {
		credentialScope = strings.Split(host, ".")[0]
	}

	// setup headers
	headerMap := map[string]string{"x-amz-date": requestTime.Format("20060102T150405Z")}

	if opts.SkipHost == false {
		headerMap["host"] = urlString.Host
	}

	// add headers passed in from -H options to headerMap
	for k, v := range opts.Headers {
		headerMap[strings.ToLower(k)] = strings.ToLower(v)
	}

	// if we were not given a Content-Type, use the default standard
	if _, ok := headerMap["content-type"]; !ok {
		headerMap["content-type"] = "application/octet-stream"
	}

	// where we start the signing process - pass in http method, url, headers and payload. for GET requests payload should be ""
	canonicalString := canonicalRequest.FormatCanonicalString(opts.Request, urlString, headerMap, payload)
	if opts.Debug == true {
		fmt.Println("Canonical String:")
		fmt.Println(canonicalString)
		fmt.Println("================")
	}
	canonicalStringHashed := utilities.DataToSha256Encoded([]byte(canonicalString))
	if opts.Debug == true {
		fmt.Println("Canonical String Hashed:")
		fmt.Println(canonicalStringHashed)
		fmt.Println("================")
	}
	stringToSign := signString.StringToSign(requestTime, canonicalStringHashed, opts.Region, credentialScope)
	if opts.Debug == true {
		fmt.Println("String to sign:")
		fmt.Println(stringToSign)
		fmt.Println("================")
	}

	signature := signature.CalculateSignature(requestTime, stringToSign, opts.Region, credentialScope, secretKey)
	headerMap["Authorization"] = utilities.GenerateSignedHeader(accessKey, signature, opts.Region, credentialScope, requestTime.Format("20060102"), canonicalRequest.FormatSignedHeaders(headerMap))
	if opts.Debug == true {
		fmt.Println("signature:")
		fmt.Println(headerMap["Authorization"])
		fmt.Println("================")
	}

	// signing process is complete start http calls

	// if we had a flag to only output the curl command, dump that and be done
	if opts.CurlOnly == true {
		headerStringBuild := ""
		for k, v := range headerMap {
			headerStringBuild += fmt.Sprintf(" %s '%s:%s'", "-H", k, v)
		}
		if opts.Request == "POST" {
			fmt.Printf("curl -X%s %s '%s' -v -d'%s'", opts.Request, headerStringBuild, urlString, payload)
		} else if opts.Request == "GET" {
			fmt.Printf("curl -X%s %s '%s' -v", opts.Request, headerStringBuild, urlString)
		}
		fmt.Println()
		os.Exit(0)
	}

	var client *http.Client
	if len(opts.Proxy) > 0 {
		proxyURL, err := url.Parse(opts.Proxy)
		if err != nil {
			fmt.Println("Error parsing proxy: " + err.Error())
			os.Exit(1)
		}
		client = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}}
	} else {
		client = &http.Client{}
	}

	// make either a GET Request or POST Request
	if opts.Request == "GET" {
		req, err := http.NewRequest("GET", urlString.String(), nil)
		// add headers to request
		for k, v := range headerMap {
			req.Header.Add(k, v)
		}
		resp, err := client.Do(req)
		if err != nil {
			fmt.Println("error in http call")
			os.Exit(4)
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		fmt.Println(string(body[:]))
	} else if opts.Request == "POST" {
		req, err := http.NewRequest("POST", urlString.String(), bytes.NewBufferString(payload))
		// add headers to request
		for k, v := range headerMap {
			req.Header.Add(k, v)
		}
		resp, err := client.Do(req)
		if err != nil {
			fmt.Println("error in http call")
			os.Exit(4)
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		fmt.Println(string(body[:]))
	}
}
コード例 #2
0
ファイル: canonicalRequest.go プロジェクト: jburks725/hmacurl
func FormatCanonicalString(method string, url *url.URL, headerMap map[string]string, payload string) string {
	// format string in HTTPRequestMethod, CanonicalURI, CanonicalQueryString, CanonicalHeaders, SignedHeaders, HexEncode(Hash(RequestPayload))
	canonicalQueryStrings := strings.Replace(url.Query().Encode(), "+", "%20", -1)
	canonicalString := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", method, url.Path, canonicalQueryStrings, formatHeaders(headerMap), FormatSignedHeaders(headerMap), utilities.DataToSha256Encoded([]byte(payload)))
	return canonicalString
}