如何在GitHub Actions中不掩盖输出?

4
作为 GitHub Actions 中 PowerShell 脚本的一部分,我正在尝试输出一个对象列表的 JSON 格式,以后可以将其重复使用作为另一个任务的矩阵。使用以下命令进行输出:
Write-Host "::set-output name=value::$( $array1 | ConvertTo-JSON -Compress)"

变量$array1的输出(转换为JSON格式)应该如下所示:
[ 
  {
    "variable1": "hello1"
  },
  {
    "variable1": "hello2"
  }
]

然而,花括号被掩盖了,所以输出结果看起来像这样:

[ 
  ***
    "variable1": "hello1"
  ***,
  ***
    "variable1": "hello2"
  ***
]

同时,在GitHub Actions中仅仅回显JSON转换的$array1时,上述问题也存在。

是否有办法克服花括号的掩码?在本地使用PowerShell时,列表输出非常完美 - 只有在GitHub Actions中才会出现此问题。

$array1是这样创建的:

$array1 = $()
foreach ($var in $vars) {
   # Do some stuff to get to output for each var
   $output = dostuff($var)
   $array1 += @(@{"variable1" = $output})

}

$array1 包含什么? - Mathias R. Jessen
好的,那么它已经是JSON格式了吗?那么你可以跳过ConvertTo-Json... - Mathias R. Jessen
@MathiasR.Jessen 不是 JSON 格式,而是变量列表。 - Onno van der Horst
1
你在仓库/组织中是否定义了任何“Secrets”操作?它们将在显示输出中被掩盖。不可否认,如果有一个只包含{}的Secret,那么输出结果会有点奇怪... - mclayton
为了测试是否只是一个“显示”问题,您可以尝试对输出进行base64编码,并查看它显示的值。然后,您可以在您的计算机上对该字符串进行base64解码以验证原始字符串,如果它看起来正确,则说明它具有正确的值,即使日志输出掩盖了其中的部分。 - mclayton
显示剩余3条评论
2个回答

4

tl;dr - 要停止掩码,您需要停止引用与值{}相等的任何Actions Secrets。

长篇版本

如果您首先创建了两个Actions Secrets并将其纳入工作流程范围(即在存储库或组织级别),则可以使用此GitHub Actions工作流程文件重现行为:

Actions Secrets

秘密名称 价值
LEFT_CURLY {
RIGHT_CURLY }

myWorkflow.yaml

有趣的部分是 activate-masking 步骤...

name: myWorkflow

on:
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - id: define-output
        name: define output
        shell: pwsh
        run: |
          $array1 = @(
            [pscustomobject] @{
              "variable1" = "hello1"
            },
            [pscustomobject] @{
              "variable1" = "hello2"
            }
          );
          write-host "::set-output name=myjson::$( $array1 | ConvertTo-JSON -Compress)"

      - id: activate-masking
        name: activate masking
        shell: pwsh
        run: |
          # referencing a secret anywhere in a step activates
          # log masking for its value in the *entire* workflow
          write-host "left = '${{ secrets.LEFT_CURLY}}'"
          write-host "right = '${{ secrets.RIGHT_CURLY }}'"

      - id: consume-output
        name: consume output
        shell: pwsh
        run: |

          # decode and re-encode the data to remove "compressed"
          # output format as noted by @mklement0 in comments
          $json = '${{ steps.define-output.outputs.myjson }}'
          $data = $json | ConvertFrom-Json

          # write the json to the log output. if masking is activate
          # then any secrets in the output will be masked with "***"
          write-host ($data| ConvertTo-Json)

          # encode the json so it bypasses masking and we can get the true
          # value contained in the variable
          write-host "base64 = '$([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($json)))'"

"consume output" 步骤的输出如下所示:
[v] consume output
 1  Run write-host "left = '***'"
 9  left = '***'
10  right = '***'
11  [
12    ***
13     "variable1": "hello1"
14    ***,
15    ***
16     "variable1": "hello2"
17    ***
18  ]
19  base64 = 'W3sidmFyaWFibGUxIjoiaGVsbG8xIn0seyJ2YXJpYWJsZTEiOiJoZWxsbzIifV0='

请注意,***掩码只是在日志文件中添加的混淆,而不是变量值本身。如果你解码base64字符串,则会得到:
[{"variable1":"hello1"},{"variable1":"hello2"}]

因此,您可以看到变量的值与预期相同。

还要注意,只有在步骤中引用秘密时才会发生掩码操作-例如,如果您从“激活掩码”步骤中删除这些行,则它将停止遮盖值,即使工作流的范围仍然定义了秘密:

# remove these lines to stop masking their values
# write-host "left = '${{ secrets.LEFT_CURLY}}'"
# write-host "right = '${{ secrets.RIGHT_CURLY }}'"

为了停止遮蔽,你需要停止引用任何等于值{}的操作密钥。
奖励回合 请注意,由于恶意输入,我的Action中存在注入漏洞,用于特殊制作的JSON值 - 例如,如果我可以以某种方式使您的JSON变量1的值最终成为这个神秘的字符串(例如,通过将其作为用户输入提供给您):
}]';write-host aaa;$y='

那么上述操作将会执行以下PowerShell命令:

$json = '[{"variable1":"}]';write-host aaa;$y='}]'

这相当于

$json = '[{"variable1":"}]';
write-host aaa;
$y='}]'

这将实际执行write-host aaa;作为命令,而不是将其视为输入数据。

为了避免这种情况,您可能需要考虑将输出作为base64编码的字符串传递 - 例如:

- id: define-output
  ...
  $base64 = [System.Convert]::ToBase64String(
    [System.Text.Encoding]::UTF8.GetBytes(
      ($array1 | ConvertTo-JSON -Compress)
    )
  )
  write-host "::set-output name=myjson::$base64"

- id: consume-output
  ...
  $base64 = '${{ steps.define-output.outputs.myjson }}'
  $json = [System.Text.Encoding]::UTF8.GetString(
    [System.Convert]::FromBase64String(
      $base64
    )
  )

那样,您的JSON数据就不会意外地被晋升为可执行的代码...

非常感谢您的所有研究!我没有引用任何存储库/环境/组织机密,所以有点困惑。我将尝试使用Base64变量的方法。但是我需要弄清楚的一件事是如何在yaml输入字段中转换这个base64。我认为应该像这样:example_matrix: needs: [gather_data] strategy: matrix: include: ${{ fromJson(fromBase64String(needs.gather_data.outputs.matrix)) }} - Onno van der Horst
1
@OnnovanderHorst - 看起来如果在工作流中引用了秘密,不仅仅是在同一步骤中,秘密掩码功能就会被激活。我已经更新了我的答案以反映这一点。也许尝试创建一个只包含您的JSON代码的新的最小化工作流,并查看是否能够重现此问题... - mclayton

1

有一个很棒的 GitHub Actions 功能 - 配置变量

这个功能允许将非敏感数据存储为纯文本变量,在您的存储库或组织中的工作流程中可以重复使用。

与存储库密钥不同,配置变量的值在工作流程运行期间不会被掩盖

更多详细信息,请参阅此帖子:https://dev59.com/b9H7oIgBc1ULPQZFdQ_y#75086864


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接