apolloconfig / apollo

Apollo is a reliable configuration management system suitable for microservice configuration management scenarios.
https://www.apolloconfig.com
Apache License 2.0
28.93k stars 10.19k forks source link

请教 Bash 脚本如何请求开启了访问密钥的配置项 #5114

Closed gotnix closed 1 month ago

gotnix commented 3 months ago

描述疑问

通过查看上述文档,使用 openssl 生产签名,curl 获取配置,请求依然返回 401 Unauthorized,调试无果,请求支援。

复现

通过如下步骤可以复现: 编写脚本test_sec.sh,内容如下:

#!/bin/bash

# Function to sign a string with HmacSHA1
function signature() {
  # Get arguments: timestamp in milliseconds, path with query, and secret
  timestamp_ms="$1"
  path_with_query="$2"
  secret="$3"

  # Define delimiter for string construction
  delimiter="\n"

  # Construct string to sign
  string_to_sign="$timestamp_ms$delimiter$path_with_query"

  # Use openssl for HmacSHA1 (assuming it's installed)
  signature=$(echo -n "${string_to_sign}" | openssl dgst -sha1 -hmac "${secret}" -binary | openssl enc -base64 -A)

  # Return the signature
  echo "$signature"
}

# 请求 Apollo
timestamp_ns=$(date +%s%N)  # Get current timestamp in milliseconds
timestamp_ms=$((timestamp_ns / 1000000))
secret="$1"
path_with_query="$2"
# url_encode="$(printf %s ${path_with_query} | jq -sRr @uri)"

signature=$(signature "$timestamp_ms" "${path_with_query}" "$secret")

#echo "Signature: $signature"
curl -v -H "Authorization: Apollo biz-sea-zl-api:${signature}" \
        -H "Timestamp: ${timestamp_ms}" \
        http://10.200.12.104:8080${path_with_query}

执行测试脚本

# 1.2 通过带缓存的Http接口从Apollo读取配置
# URL: {config_server_url}/configfiles/json/{appId}/{clusterName}/{namespaceName}?ip={clientIp}
test_sec.sh 3ec73558384d43f080510556896fec1f /configfiles/json/biz-sea-zl-api/default/system.yaml
或者
# 1.3 通过不带缓存的Http接口从Apollo读取配置
# URL: {config_server_url}/configs/{appId}/{clusterName}/{namespaceName}?releaseKey={releaseKey}&messages={messages}&label={label}&ip={clientIp}
test_sec.sh 3ec73558384d43f080510556896fec1f /configs/biz-sea-zl-api/default/system.yaml

响应如下:

{"timestamp":"2024-03-26T13:29:10.921+0800","status":401,"error":"Unauthorized","message":"Unauthorized","path":"/configfiles/json/biz-sea-zl-api/default/system.yaml"}

期望

能通过 bash 脚本获取 Apollo 启用密钥的配置项,学习在 bash 中如何使用 openssl 加签名请求 Apollo 接口。

截图

额外的细节和日志

dosubot[bot] commented 3 months ago

你好 @gotnix,很高兴再次看到你在这里提问!希望你一切都好。

您的 Bash 脚本看起来是正确的,但是我注意到您在构造签名字符串时,可能没有正确地处理路径和查询参数。在 Apollo 的 Java 和 Python 实现中,路径和查询参数都是 URL 编码的。这意味着所有的特殊字符,如空格和某些符号,都被转换为 URL 安全的编码。在 Bash 脚本中,您可以使用 curl-G--data-urlencode 选项来实现这一点。

另外,我注意到您在构造签名字符串时,使用的是 "\n" 作为分隔符。在 Bash 中,这可能不会被解析为换行符,而是被解析为两个字符:反斜杠和 n。您可以尝试使用 $'\n' 来表示换行符。

以下是一个修改后的 Bash 脚本示例:

#!/bin/bash

# Function to sign a string with HmacSHA1
function signature() {
  # Get arguments: timestamp in milliseconds, path with query, and secret
  timestamp_ms="$1"
  path_with_query="$2"
  secret="$3"

  # Define delimiter for string construction
  delimiter=$'\n'

  # Construct string to sign
  string_to_sign="$timestamp_ms$delimiter$path_with_query"

  # Use openssl for HmacSHA1 (assuming it's installed)
  signature=$(echo -n "${string_to_sign}" | openssl dgst -sha1 -hmac "${secret}" -binary | openssl enc -base64 -A)

  # Return the signature
  echo "$signature"
}

# 请求 Apollo
timestamp_ns=$(date +%s%N)  # Get current timestamp in milliseconds
timestamp_ms=$((timestamp_ns / 1000000))
secret="$1"
path_with_query="$2"
url_encode="$(printf %s ${path_with_query} | jq -sRr @uri)"

signature=$(signature "$timestamp_ms" "${url_encode}" "$secret")

#echo "Signature: $signature"
curl -v -G -H "Authorization: Apollo biz-sea-zl-api:${signature}" \
        -H "Timestamp: ${timestamp_ms}" \
        --data-urlencode "${url_encode}" \
        http://10.200.12.104:8080

如果这个修改后的脚本仍然无法解决您的问题,那么可能需要进一步检查 Apollo 服务器的日志,看看是否有更多关于 401 错误的详细信息。

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
gotnix commented 3 months ago

@dosu-bot 的回答是正确的,用 $'\n' 来表示换行符,delimiter="\n" 修改为 delimiter=$'\n' 解决了问题。

感觉这个问题太小白了,更适合在 Discussions讨论,准备在 Discussions 建好帖子来关闭这个 Issue 的,结果发现 dosu-bot 已经解决问题了。

之前没有用过 Discussions ,我以后注意,优先使用 Discussions,打扰各位了。

dosubot[bot] commented 3 months ago

I'm glad to hear that the suggested changes resolved your issue, @gotnix! It's completely okay to seek help here, and I'm here to assist you. If you have any more questions or run into any other issues in the future, feel free to reach out. Utilizing Discussions for smaller issues is a great idea, and it can also help other community members who might have similar questions.

If you have any more questions or need further assistance, don't hesitate to ask. I'm here to help!

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
nobodyiam commented 3 months ago

@dosu-bot Awesome response! Really cool to see you getting better and better.

stale[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

stale[bot] commented 1 month ago

This issue has been automatically closed because it has not had activity in the last 7 days. If this issue is still valid, please ping a maintainer and ask them to label it as "help wanted". Thank you for your contributions.