cURL通过终端/邮递员工作,但不能通过Shell脚本或Python

时间:2019-11-26 06:29:19

标签: python bash curl

我有一个Shell脚本,该脚本从AWS SSM参数存储中提取参数,并在某些cURL命令中将其使用到第三方API。如果我通过终端手动执行每个命令,它们都可以正常运行而不会出现问题。但是,一旦将它们放在下面的脚本中,用于创建AWS账户连接器的cURL命令就会不断抛出500 Internal service错误。

下面是一个代码段:

#!/bin/bash

# Creating random guid to use for ExternalId
    UUID=$(uuidgen)
    echo "UUID: $UUID"

    # Replacing ExternalId in assumepolicy doc with created guid
    $SED_COMMAND -i "s/\"sts:ExternalId\": \".*\"/\"sts:ExternalId\": \"${UUID}\"/g" ./trust-policy.json

    # Create new cross-account role with assume role policy
    echo "Creating new cross-account role."
    aws iam create-role --role-name ${ROLENAME} --assume-role-policy-document file://trust-policy.json

    # Attach role policy to newly created role
    aws iam put-role-policy --role-name ${ROLENAME} --policy-name ${POLICYNAME} --policy-document file://inline-policy.json

    # Grabbing role arn
    ARN=$(aws iam get-role --role-name ${ROLENAME} | jq -r '.Role.Arn')

    # Logging into SaaS instance; retrieving SID for subsequent API calls
    SID=`curl -ks -H "Content-Type: application/json" "Accept: application/json" -X POST "${URL}/rest/authentication/login" -d '{"dsCredentials":{"userName":"'${USER_ID}'","password":"'${PASSWORD}'"}}'`

    # Create AWS account connector
    echo "Creating AWS account connector."
    curl -ks --cookie "sID=${SID}" -H "Content-Type: application/json" "Accept: application/json" -X POST "${URL}/rest/cloudaccounts/aws" -d '{"AddAwsAccountRequest": {"useInstanceRole": false,"crossAccountRole": {"roleArn": "'${ARN}'","externalId": "'${UUID}'"},"workspacesEnabled": false}}'

    # Log out of SaaS instance
    echo "Logging out."
    curl -k -X DELETE ${URL}/rest/authentication/logout?sID=${SID}

第一个cURL语句在脚本中可以正常工作,该脚本可以获取用于身份验证的SID。

SID=`curl -ks -H "Content-Type: application/json" "Accept: application/json" -X POST "${URL}/rest/authentication/login" -d '{"dsCredentials":{"userName":"'${USER_ID}'","password":"'${PASSWORD}'"}}'`

但是,通过外壳程序脚本{"error":{"message":"Internal server error"}}

运行时,第二个cURL语句始终抛出500。

curl -ks --cookie "sID=${SID}" -H "Content-Type: application/json" "Accept: application/json" -X POST "${URL}/rest/cloudaccounts/aws" -d '{"AddAwsAccountRequest": {"useInstanceRole": false,"crossAccountRole": {"roleArn": "'${ARN}'","externalId": "'${UUID}'"},"workspacesEnabled": false}}'

如果我使用 exact 相同的cURL命令并在终端中手动执行,则可以正常运行。我也可以在Postman中进行这项工作。

在Postman中,我发现如果请求中的一部分数据格式错误或为空,则会返回相同的“内部服务器错误”,因此我的直觉是请求正文有问题;但是,我可以在终端上通过bash -x运行确切的curl命令输出,并且可以正常工作。

例如,这是使用以下命令运行上述脚本的输出:bash -x ./cloudConnectorAutomation.sh

+ echo 'Creating AWS account connector.'
Creating AWS account connector.
+ curl -ks --cookie sID=XXXX -H 'Content-Type: application/json' 'Accept: application/json' -X POST https://XXXX/rest/cloudaccounts/aws -d '{"AddAwsAccountRequest": {"useInstanceRole": false,"crossAccountRole": {"roleArn": "arn:aws:iam::XXXXXXXXXXXX:role/XXXX","externalId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"},"workspacesEnabled": false}}'
{"error":{"message":"Internal server error"}}

如果我直接从终端的输出中复制并粘贴 exact 相同的curl命令并执行该命令,它将完美执行。

我记下了脚本和终端中运行的命令的curl -v输出,除了不同的SID(由于不同的身份验证会话)外,它们是相同的。在脚本中运行的一个显示为状态代码:< HTTP/1.1 500,而我手动运行的一个显示为状态代码:< HTTP/1.1 200


在最后的努力中,我什至测试了调用python脚本而不是使用cURL。下面的Python脚本。在本文开头的初始脚本中,它是在有问题的cURL请求的地方调用的:

import requests
import sys
import json

SID = sys.argv[1]
URL = sys.argv[2]
ARN = sys.argv[3]
UUID = sys.argv[4]

# Do not proceed if required parameters are empty
if not SID or not URL or not ARN or not UUID:
    print ("\nERROR: Required parameters are empty.")
    print ("SID: " + SID)
    print ("URL: " + URL)
    print ("ARN: " + ARN)
    print ("UUID: " + UUID)
    exit()

endpoint = URL + '/rest/cloudaccounts/aws'

cookies = {
    'sID': SID
}

headers = {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
}

payload = {'AddAwsAccountRequest': {'useInstanceRole': False,'crossAccountRole': {'roleArn': ARN,'externalId': UUID},'workspacesEnabled': False}}

response = requests.post(endpoint, headers=headers, cookies=cookies, data=json.dumps(payload), verify=False)

它返回相同的内部服务器错误:

Creating AWS account connector.
+ python3 ./account_connector.py XXXX https://XXXX.com arn:aws:iam::XXXXXXXXX:role/XXXX XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
{"error":{"message":"Internal server error"}}

但是,如果我在ipython中逐行执行,它会完美地工作。

我在这里不知所措,并且花了整整一天的时间试图弄清楚这一点。

再次,我真正地相信问题是我的数据块以某种方式变形,但是我看不到它在哪里。对于为什么我可以使用完全相同的cURL命令并且它可以在终端中运行,我也感到困惑。我正在研究通过终端与Shell脚本运行cURL命令时是否存在细微差别或细微差别,但我没有发现存在。

在此方面的任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您能尝试逃脱吗:

"{\"AddAwsAccountRequest\": {\"useInstanceRole\": false,\"crossAccountRole\": {\"roleArn\": \"${ARN}\",\"externalId\": \"${UUID}\"},\"workspacesEnabled\": false}}"

从终端运行与运行脚本相比,在某些逃避方面有一些微妙之处,如此处所述:curl works, but won't execute in BASH script

让我知道是否有帮助!