从 golang 脚本中检索带有空格的 Github 个秘密
Retrieving Github secrets with spaces from golang script
我想通过 Golang 从脚本中检索 Github 秘密内容,该脚本是从 Github 操作执行的。
在这种特殊情况下,存储在 Github secrets 中的秘密值具有 space。我的意思是秘密值是:JWT <token-string>
.
只要在 Github 动作运行器中执行,从任何语言的任何脚本检索 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 动作运行器时,我没有从 Github 秘密中获得价值。我知道这是在发生,因为我尝试以这种方式打印它,但什么也没有出现:
fmt.Println("My JWT", os.Getenv("USER_JWT"))
恐怕这是因为 "JWT "
和令牌之间的 space,我的意思是 JWT <token-string>
。
Here 说:
Secret names can only contain alphanumeric characters ([a-z], [A-Z], [0-9]) or underscores (_). Spaces are not allowed.
一个重要的事实是,我的令牌秘密值的值中还包含 .
个字符。值是这样的:
JWT xxxxxxx8888xxxxdsdsfsfsf9.eyJxxxxxxx8888xxxxdsdsfsfsf9.Tfgxadsdsfsfsasasad_s7sdsdsfgsgcs
所以我相信,这就是我无法获取秘密值的原因。
我不确定如何从我的 Golang 脚本中获取它,我什至尝试修改 Github 秘密值只是将其作为值 <token-string>
以避免 space 在值中,我以这种方式从 go 中调用它:
"Authorization": []string{"JWT ", os.Getenv("SPECKLE_USER_JWT")}
但是没有用。
我读到 here 当从 github 操作调用带有特殊字符的秘密时,我们必须用单引号 ' '
转义它们,但这个过程来自 .yaml
文件 github动作。
我正在尝试的以前的替代解决方案,它们适用于我的本地计算机,因为我的 bash cli 能够获取其值中包含 spaces 的环境变量。我不确定我怎么能 - 让我们说“转义” - 一个字符串中带有 space 的秘密,就像我从 golang 那里得到的那样。
我设法从执行 golang terratest 代码的 GitHub 操作中读取存储在 GitHub secrets 中的 JWT secret。
如前所述,由于 Github 秘密不允许 spaces " "
和点 .
字符并且令牌有一些点加一 space ,我首先做的是对其进行编码
echo -n '<token-value>' | base64
这会生成一个没有 .
或 space 的完整字符串,然后我将这个值存储在 Github 秘密中。我以这种方式从 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"
// The encoded token is read from github secrets
b64EncodeJwt := os.Getenv("USER_JWT_ENCODE")
// fmt.Println("The encode JWT is:", b64EncodeJwt)
// The encoded read token is decoded
b64DecodeJwt, _ := b64.StdEncoding.DecodeString(b64EncodeJwt)
// fmt.Println("JWT Decoded", string(b64DecodeJwt))
// fmt.Println()
headers := map[string][]string{
"Content-Type": []string{"application/json, text/plain, */*"},
// The content of the token already decoded is included in the headers slice of strings.
"Authorization": []string{(string(b64DecodeJwt))},
}
jsonLogin := []byte(fmt.Sprintf(`{
"email":"%s",
"password": "%s"
}`, os.Getenv("USER_EMAIL"), os.Getenv("USER_PASSWORD")))
// The HTTP request is created
reqLogin, errReq := http.NewRequest(method, serverURL+"/api/accounts", bytes.NewBuffer(jsonLogin))
// The headers are added to the HTTP request
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,
},
},
}
// Sending the request
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")
}
// We take the API token from the response
data := speckleLogin["resource"].(map[string]interface{})["apitoken"]
if speckleToken, ok := data.(string); ok {
// Here we assert the token is not empty
assert.NotEmpty(t, speckleToken)
}
但除此之外,@WishwaPerera 试图告诉我,我在上面使用的来自 golang 的名为 SPECKLE_USER_JWT_ENCODE
的新环境变量必须包含在我的 github 操作中时刻 运行 这些测试来自 go test
命令。所以我的 github 操作 .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
// executing the test
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 }}
# 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
很好的参考资料,可以稍微理解一下how to handle the HTTP package
我想通过 Golang 从脚本中检索 Github 秘密内容,该脚本是从 Github 操作执行的。
在这种特殊情况下,存储在 Github secrets 中的秘密值具有 space。我的意思是秘密值是:JWT <token-string>
.
只要在 Github 动作运行器中执行,从任何语言的任何脚本检索 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 动作运行器时,我没有从 Github 秘密中获得价值。我知道这是在发生,因为我尝试以这种方式打印它,但什么也没有出现:
fmt.Println("My JWT", os.Getenv("USER_JWT"))
恐怕这是因为 "JWT "
和令牌之间的 space,我的意思是 JWT <token-string>
。
Here 说:
Secret names can only contain alphanumeric characters ([a-z], [A-Z], [0-9]) or underscores (_). Spaces are not allowed.
一个重要的事实是,我的令牌秘密值的值中还包含 .
个字符。值是这样的:
JWT xxxxxxx8888xxxxdsdsfsfsf9.eyJxxxxxxx8888xxxxdsdsfsfsf9.Tfgxadsdsfsfsasasad_s7sdsdsfgsgcs
所以我相信,这就是我无法获取秘密值的原因。
我不确定如何从我的 Golang 脚本中获取它,我什至尝试修改 Github 秘密值只是将其作为值 <token-string>
以避免 space 在值中,我以这种方式从 go 中调用它:
"Authorization": []string{"JWT ", os.Getenv("SPECKLE_USER_JWT")}
但是没有用。
我读到 here 当从 github 操作调用带有特殊字符的秘密时,我们必须用单引号 ' '
转义它们,但这个过程来自 .yaml
文件 github动作。
我正在尝试的以前的替代解决方案,它们适用于我的本地计算机,因为我的 bash cli 能够获取其值中包含 spaces 的环境变量。我不确定我怎么能 - 让我们说“转义” - 一个字符串中带有 space 的秘密,就像我从 golang 那里得到的那样。
我设法从执行 golang terratest 代码的 GitHub 操作中读取存储在 GitHub secrets 中的 JWT secret。
如前所述,由于 Github 秘密不允许 spaces " "
和点 .
字符并且令牌有一些点加一 space ,我首先做的是对其进行编码
echo -n '<token-value>' | base64
这会生成一个没有 .
或 space 的完整字符串,然后我将这个值存储在 Github 秘密中。我以这种方式从 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"
// The encoded token is read from github secrets
b64EncodeJwt := os.Getenv("USER_JWT_ENCODE")
// fmt.Println("The encode JWT is:", b64EncodeJwt)
// The encoded read token is decoded
b64DecodeJwt, _ := b64.StdEncoding.DecodeString(b64EncodeJwt)
// fmt.Println("JWT Decoded", string(b64DecodeJwt))
// fmt.Println()
headers := map[string][]string{
"Content-Type": []string{"application/json, text/plain, */*"},
// The content of the token already decoded is included in the headers slice of strings.
"Authorization": []string{(string(b64DecodeJwt))},
}
jsonLogin := []byte(fmt.Sprintf(`{
"email":"%s",
"password": "%s"
}`, os.Getenv("USER_EMAIL"), os.Getenv("USER_PASSWORD")))
// The HTTP request is created
reqLogin, errReq := http.NewRequest(method, serverURL+"/api/accounts", bytes.NewBuffer(jsonLogin))
// The headers are added to the HTTP request
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,
},
},
}
// Sending the request
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")
}
// We take the API token from the response
data := speckleLogin["resource"].(map[string]interface{})["apitoken"]
if speckleToken, ok := data.(string); ok {
// Here we assert the token is not empty
assert.NotEmpty(t, speckleToken)
}
但除此之外,@WishwaPerera 试图告诉我,我在上面使用的来自 golang 的名为 SPECKLE_USER_JWT_ENCODE
的新环境变量必须包含在我的 github 操作中时刻 运行 这些测试来自 go test
命令。所以我的 github 操作 .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
// executing the test
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 }}
# 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
很好的参考资料,可以稍微理解一下how to handle the HTTP package