使用golang脚本从Github检索带有空格的密钥

huangapple go评论90阅读模式
英文:

Retrieving Github secrets with spaces from golang script

问题

我想通过在Github actions中执行的Golang脚本来检索Github秘密内容。在这种特殊情况下,Github秘密中存储的秘密值包含一个空格。我的意思是秘密值是:JWT <token-string>

无论使用任何语言编写的脚本,只要它们在Github actions运行器中执行,就可以通过将它们作为环境变量来读取Github秘密。所以我正在以这种方式读取它:(请参见下面字符串切片中的Authorization:元素)

func MyTestFunction(t *testing.T, serverURL string) {

	type AppLogin struct {
		token string
	}
	method := "GET";

	
	headers := map[string][]string{
		"Content-Type": []string{"application/json, text/plain, */*"},
		"Authorization": []string{os.Getenv("USER_JWT")},
	}

问题是当在Github actions运行器中运行时,我无法获取Github秘密的值。我知道这是发生的原因,因为我尝试以这种方式打印它,但没有任何输出:

fmt.Println("My JWT", os.Getenv("USER_JWT"))

我担心这是因为"JWT "和令牌之间的空格,我的意思是JWT <token-string>

这里说:
>秘密名称只能包含字母数字字符([a-z],[A-Z],[0-9])或下划线(_)。不允许使用空格。

作为一个重要的事实,我的令牌秘密值还包含其值中的.字符。值类似于:

JWT xxxxxxx8888xxxxdsdsfsfsf9.eyJxxxxxxx8888xxxxdsdsfsfsf9.Tfgxadsdsfsfsasasad_s7sdsdsfgsgcs

所以我相信这就是我无法获取秘密值的原因。

我不确定如何从我的Golang脚本中获取它,我甚至尝试修改Github秘密值,只将<token-string>作为值,以避免值中的空格,并以以下方式从go中调用它:

"Authorization": []string{"JWT ", os.Getenv("SPECKLE_USER_JWT")}

但它没有起作用。
我在这里阅读到,当从github actions中调用带有特殊字符的秘密时,我们必须使用单引号' '进行转义,但这个过程是在.yaml文件中进行的。

我正在尝试的先前解决方案在我的本地机器上工作,因为我的bash命令行界面能够获取其值中包含空格的环境变量。我不确定如何 - 比方说 - 从Golang中处理包含空格的秘密字符串。

英文:

I would like to retrieve a Github secret content from a script via Golang, that is executed from Github actions.
In this particular situation, the secret value stored in Github secrets has a space. I mean the secret value is: JWT <token-string>.

The way to retrieve Github secrets from any script in any language as long they are executed in Github actions runners is by reading them as environment variables. So what I am doing is to read it in this way: (Please see the Authorization: element in the slice of string below)

func MyTestFunction(t *testing.T, serverURL string) {

	type AppLogin struct {
		token string
	}
	method := "GET"

	
	headers := map[string][]string{
		"Content-Type": []string{"application/json, text/plain, */*"},
		"Authorization": []string{os.Getenv("USER_JWT")},
	}

The thing is that I am not getting the value from Github secrets when running Github action runner. I know this is happening since I tried to print it in this way, but nothing comes up:

fmt.Println("My JWT", os.Getenv("USER_JWT"))

I am afraid it is happening because that space between "JWT " and the token, I mean JWT <token-string>.

Here says:
>Secret names can only contain alphanumeric characters ([a-z], [A-Z], [0-9]) or underscores (_). Spaces are not allowed.

As an important fact, my token secret value also contains . character in its value. The value is something like this:

JWT xxxxxxx8888xxxxdsdsfsfsf9.eyJxxxxxxx8888xxxxdsdsfsfsf9.Tfgxadsdsfsfsasasad_s7sdsdsfgsgcs

So I believe, that is the reason why I cannot get the secret value.

I am not sure how I can fetch this from my Golang script, I even tried to modify the Github secret value just having it as a value the <token-string> in order to avoid the space in the value, and I am calling it from go in this way:

"Authorization": []string{"JWT ", os.Getenv("SPECKLE_USER_JWT")}

But it did not work.
I read here that when calling secrets with special characters from github actions we have to escape them with single quotes ' ' but this process is from .yaml file github actions.

The previous solution alternatives I am trying to, they works on my local machine, since my bash cli is able to get environment variables with spaces in their values. I am not sure how can I - let's say "escape" - a secret with space in a string as I have from golang.

答案1

得分: 0

我成功地从 GitHub 的操作中读取了存储在 GitHub secrets 中的 JWT 密钥,并执行了使用 golang terratest 代码的操作。

如前所述,由于 GitHub secrets 不允许空格 " " 和点 . 字符,而令牌中包含一些点加一个空格,所以我首先对其进行了编码。

echo -n '<token-value>' | base64

这将生成一个没有 . 或空格的完整字符串,然后我将该值存储在 GitHub secrets 中。然后我以以下方式从 golang 中读取它:

func main() {
   var t *testing.T
   serverURL := os.Getenv("SERVER_URL")
   MyTestFunction(t, serverURL)

}
func MyTestFunction(t *testing.T, serverURL string) {

	type SpeckleLogin struct {
		token string
	}
	method := "GET"

    // 从 GitHub secrets 中读取编码后的令牌
	b64EncodeJwt := os.Getenv("USER_JWT_ENCODE")
	// fmt.Println("The encode JWT is:", b64EncodeJwt)

	// 解码已读取的编码令牌
    b64DecodeJwt, _ := b64.StdEncoding.DecodeString(b64EncodeJwt)
	// fmt.Println("JWT Decoded", string(b64DecodeJwt))
    // fmt.Println()
	
	headers := map[string][]string{
		"Content-Type": []string{"application/json, text/plain, */*"},
        
        // 将已解码的令牌内容包含在字符串切片的 headers 中
		"Authorization": []string{(string(b64DecodeJwt))},
	}


	jsonLogin := []byte(fmt.Sprintf(`{
		"email":"%s",
		"password": "%s"
	}`, os.Getenv("USER_EMAIL"), os.Getenv("USER_PASSWORD")))
	
    // 创建 HTTP 请求
	reqLogin, errReq := http.NewRequest(method, serverURL+"/api/accounts", bytes.NewBuffer(jsonLogin))

    // 将 headers 添加到 HTTP 请求中
	reqLogin.Header = headers

    if errReq != nil {
		messageReq := fmt.Sprintf("Error GET login request: %s", errReq.Error())
		t.Fatal(messageReq)
	}

	clientLogin := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	// 发送请求
	respLogin, errResp := clientLogin.Do(reqLogin)

	if errResp != nil {
		messageResp := fmt.Sprintf("Error GET login response: %s", errResp.Error())
		t.Fatal(messageResp)
	}

	defer respLogin.Body.Close()

	body, _ := ioutil.ReadAll(respLogin.Body)

	// fmt.Println("BODY IS:")
  	// fmt.Println(string(body))

	var speckleLogin map[string]interface{}

	if err := json.Unmarshal([]byte(body), &speckleLogin); err != nil {
		t.Fatal("Could not unmarshal json")
	}

	// 从响应中获取 API 令牌
	data := speckleLogin["resource"].(map[string]interface{})["apitoken"]	

	if speckleToken, ok := data.(string); ok {

        // 在这里断言令牌不为空
		assert.NotEmpty(t, speckleToken)
}

此外,正如 @WishwaPerera 所尝试告诉我的那样,我正在使用 golang 中的新环境变量 SPECKLE_USER_JWT_ENCODE,在运行 go test 命令时必须将其包含在我的 GitHub actions 中。因此,我的 GitHub action .yaml 文件最终如下所示:

name: Preview_Workflow

on:
  pull_request:
    branches:
    - master

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - name: 'Checkout GitHub Action'
      uses: actions/checkout@master

    - name: Install terraform 
      uses: hashicorp/setup-terraform@v1
      with:
        terraform_version: 0.13.5
        terraform_wrapper: false

    - name: 'Terraform Version'
      shell: bash
      run: |
                terraform version

    - name: 'Login via Azure CLI'
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: 'Setup Go'
      id: go
      uses: actions/setup-go@v2
      with:
        go-version: '^1.16.5'

    - name: 'Run Terratest'
      id: terratest
      run: |
        cd tests
        go get -u github.com/Azure/azure-storage-blob-go/azblob
        go get -u github.com/gruntwork-io/terratest/modules/terraform
        go get -u github.com/stretchr/testify/assert
        // 执行测试
        go test        
      env:
        SERVER_URL: "https://my-service-application-url"
        USER_EMAIL: ${{ secrets.USER_EMAIL }}
        USER_PASSWORD: ${{ secrets.USER_PASSWORD }}
        USER_JWT_ENCODE: ${{ secrets.USER_JWT_ENCODE }}

        # 我还使用这些连接到 Azure。
        ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
        ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
        ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
        ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}

    - name: Azure logout
      run: |
                az logout

一个很好的参考资料,可以了解一些如何处理 HTTP 包的知识。

英文:

I managed to read the JWT secret stored in GitHub secrets from a GitHub action executing the golang terratest code.

As mentioned, since Github secrets does not allow spaces &quot; &quot; and dots . characters and the token has some dots plus one space, that I did first was to encode it

echo -n &#39;&lt;token-value&gt;&#39; | base64

This generates a whole string without . or spaces and then I stored this value on Github secrets. And I read it from golang in this way:


func main() {
var t *testing.T
serverURL := os.Getenv(&quot;SERVER_URL&quot;)
MyTestFunction(t, serverURL)
}
func MyTestFunction(t *testing.T, serverURL string) {
type SpeckleLogin struct {
token string
}
method := &quot;GET&quot;
// The encoded token is read from github secrets
b64EncodeJwt := os.Getenv(&quot;USER_JWT_ENCODE&quot;)
// fmt.Println(&quot;The encode JWT is:&quot;, b64EncodeJwt)
// The encoded read token is decoded
b64DecodeJwt, _ := b64.StdEncoding.DecodeString(b64EncodeJwt)
// fmt.Println(&quot;JWT Decoded&quot;, string(b64DecodeJwt))
// fmt.Println()
headers := map[string][]string{
&quot;Content-Type&quot;: []string{&quot;application/json, text/plain, */*&quot;},
// The content of the token already decoded is included in the headers slice of strings. 
&quot;Authorization&quot;: []string{(string(b64DecodeJwt))},
}
jsonLogin := []byte(fmt.Sprintf(`{
&quot;email&quot;:&quot;%s&quot;,
&quot;password&quot;: &quot;%s&quot;
}`, os.Getenv(&quot;USER_EMAIL&quot;), os.Getenv(&quot;USER_PASSWORD&quot;)))
// The HTTP request is created
reqLogin, errReq := http.NewRequest(method, serverURL+&quot;/api/accounts&quot;, bytes.NewBuffer(jsonLogin))
// The headers are added to the HTTP request
reqLogin.Header = headers
if errReq != nil {
messageReq := fmt.Sprintf(&quot;Error GET login request: %s&quot;, errReq.Error())
t.Fatal(messageReq)
}
clientLogin := &amp;http.Client{
Transport: &amp;http.Transport{
TLSClientConfig: &amp;tls.Config{
InsecureSkipVerify: true,
},
},
}
// Sending the request
respLogin, errResp := clientLogin.Do(reqLogin)
if errResp != nil {
messageResp := fmt.Sprintf(&quot;Error GET login response: %s&quot;, errResp.Error())
t.Fatal(messageResp)
}
defer respLogin.Body.Close()
body, _ := ioutil.ReadAll(respLogin.Body)
// fmt.Println(&quot;BODY IS:&quot;)
// fmt.Println(string(body))
var speckleLogin map[string]interface{}
if err := json.Unmarshal([]byte(body), &amp;speckleLogin); err != nil {
t.Fatal(&quot;Could not unmarshal json&quot;)
}
// We take the API token from the response
data := speckleLogin[&quot;resource&quot;].(map[string]interface{})[&quot;apitoken&quot;]	
if speckleToken, ok := data.(string); ok {
// Here we assert the token is not empty
assert.NotEmpty(t, speckleToken)
}

But in addition as @WishwaPerera try to tell me, the new environment variable i am using from golang called SPECKLE_USER_JWT_ENCODE above, has to be included in my github actions at the moment to run these tests from go test command. So my github action .yaml file finally is in this way:

name: Preview_Workflow
on:
pull_request:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: &#39;Checkout GitHub Action&#39;
uses: actions/checkout@master
- name: Install terraform 
uses: hashicorp/setup-terraform@v1
with:
terraform_version: 0.13.5
terraform_wrapper: false
- name: &#39;Terraform Version&#39;
shell: bash
run: |
terraform version
- name: &#39;Login via Azure CLI&#39;
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: &#39;Setup Go&#39;
id: go
uses: actions/setup-go@v2
with:
go-version: &#39;^1.16.5&#39;
- name: &#39;Run Terratest&#39;
id: terratest
run: |
cd tests
go get -u github.com/Azure/azure-storage-blob-go/azblob
go get -u github.com/gruntwork-io/terratest/modules/terraform
go get -u github.com/stretchr/testify/assert
// executing the test
go test
env:
SERVER_URL: &quot;https://my-service-application-url&quot;
USER_EMAIL: ${{ secrets.USER_EMAIL }}
USER_PASSWORD: ${{ secrets.USER_PASSWORD }}
USER_JWT_ENCODE: ${{ secrets.USER_JWT_ENCODE }}
# I am using these other ones to connect to azure.
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
- name: Azure logout
run: |
az logout

A nice reference to understand a bit how to handle the HTTP package

huangapple
  • 本文由 发表于 2021年6月29日 04:52:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/68169901.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定