Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add immutable action check #2496

Closed
wants to merge 104 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
8daceb1
Merge pull request #1299 from Devils-Knight/fix-dependabot
ashishkurmi Oct 21, 2022
7105c41
remediate files & packages
Devils-Knight Oct 25, 2022
b99b655
mod tidy
Devils-Knight Oct 26, 2022
f6256ca
add version comment to pinned actions
Devils-Knight Nov 4, 2022
ffdfe27
Merge pull request #1374 from Devils-Knight/comment
varunsh-coder Nov 7, 2022
088800b
Merge branch 'int' into pr/1352
varunsh-coder Nov 7, 2022
3da1738
Merge pull request #1352 from Devils-Knight/remediation
varunsh-coder Nov 7, 2022
7bcb807
Update harden runner version
varunsh-coder Nov 9, 2022
cc5afdc
Merge pull request #1379 from step-security/update-harden-harden-int
varunsh-coder Nov 9, 2022
b994863
[UPDATE] Pin actions to vx.y.z format (#1469)
Devils-Knight Nov 19, 2022
e9482c1
Update test command
varunsh-coder Nov 21, 2022
361b35a
Merge pull request #1476 from step-security/update-workflow-test-cmd
varunsh-coder Nov 21, 2022
8e7b11c
Update test cases
varunsh-coder Nov 21, 2022
4672343
Merge pull request #1477 from step-security/update-tests
varunsh-coder Nov 21, 2022
c096e5f
Merge branch 'main' into int
varunsh-coder Nov 21, 2022
9c234e9
update pinning remediation
Devils-Knight Nov 30, 2022
a84a433
Return secret metadata
varunsh-coder Dec 1, 2022
787f313
Merge pull request #1597 from step-security/return-secret-metadata
varunsh-coder Dec 1, 2022
9372c3f
Update secrets.go
varunsh-coder Dec 1, 2022
ea1fb43
Merge pull request #1598 from step-security/return-secret-metadata
varunsh-coder Dec 1, 2022
7906268
Merge pull request #1582 from Devils-Knight/pinIssue
varunsh-coder Dec 5, 2022
0e48ac5
configuring dependabot to use INT for upggrading dependencies
ashishkurmi Dec 7, 2022
e7de507
Merge pull request #1618 from step-security/ak-dependabot-int
ashishkurmi Dec 7, 2022
b57f3f7
Merge branch 'main' into int
varunsh-coder Dec 8, 2022
086252d
Merge branch 'main' into int
varunsh-coder Dec 8, 2022
582a89d
[FEATURE] Added Template and addWorkflow function to generate Codeql …
Devils-Knight Dec 10, 2022
ee52f8f
fixed typo
Devils-Knight Dec 10, 2022
ad10892
Merge pull request #1643 from Devils-Knight/issue
varunsh-coder Dec 12, 2022
23233ec
Update addworkflow.go
varunsh-coder Dec 14, 2022
14cc00f
Merge pull request #1657 from step-security/update-workflow-env
varunsh-coder Dec 14, 2022
1c68758
Update template
varunsh-coder Dec 17, 2022
8fe562e
Merge pull request #1667 from step-security/fix-template
varunsh-coder Dec 17, 2022
7903c6b
[FEATURE] Added template for Dependency-review and Scorecards (#1755)
Devils-Knight Jan 4, 2023
559d233
Merge branch 'main' into int
varunsh-coder Feb 9, 2023
e0c7869
Update expected-codeql.yml
varunsh-coder Feb 9, 2023
571b89a
Update reference from Secure-Workflow to Secure-Repo (#1905)
Devils-Knight Feb 9, 2023
0a7ecc9
Merge branch 'main' into int
varunsh-coder Feb 12, 2023
a5395f3
Update scorecards.yml
varunsh-coder Feb 12, 2023
8673c00
Update expected-scorecards.yml
varunsh-coder Feb 12, 2023
09a145c
updated pinning docker image
Devils-Knight Mar 9, 2023
6d49773
comment added
Devils-Knight Mar 9, 2023
abc34e3
update pin docker
Devils-Knight Mar 9, 2023
e4612f7
Merge pull request #1989 from Devils-Knight/bug2
varunsh-coder Mar 14, 2023
97fa737
Merge pull request #1988 from Devils-Knight/bug
varunsh-coder Mar 14, 2023
acfa53b
fix pinning docker issue
Devils-Knight Mar 15, 2023
01a8c09
Merge pull request #2006 from Devils-Knight/pinBug
varunsh-coder Mar 16, 2023
b9b32d3
Merge branch 'main' into int
varunsh-coder Mar 16, 2023
7bc0089
Trim comments
arjundashrath Mar 16, 2023
25f90b0
update docker action format
Devils-Knight Mar 17, 2023
161b8b0
Merge pull request #2014 from Devils-Knight/issue-docker
varunsh-coder Mar 19, 2023
4af0234
Merge pull request #2010 from arjundashrath/main
varunsh-coder Mar 19, 2023
ff05a33
update secureWorkflow
Devils-Knight Mar 29, 2023
03f4760
Merge pull request #2044 from Devils-Knight/updateSecure
ashishkurmi Mar 29, 2023
adfb0fa
Merge branch 'main' into int
varunsh-coder Apr 10, 2023
830739d
Fix sentence and remove existing action comments (#2067)
arjundashrath Apr 13, 2023
eadfcec
Revert "Fix sentence and remove existing action comments (#2067)"
varunsh-coder Apr 13, 2023
22dbc7f
Change comment removal logic (#2092)
arjundashrath Apr 23, 2023
6ecd88d
[UPDATE] Add pre-commit hooks to catch linting issues (#2098)
Devils-Knight Apr 26, 2023
837e44e
adding a workflow for reviewing code using stepsecurity code reviewer
ashishkurmi Apr 30, 2023
f101b58
Merge pull request #2101 from step-security/ak-code-reviewer
ashishkurmi Apr 30, 2023
953d1e1
adding permissions for code review workflow
ashishkurmi Apr 30, 2023
e62e8f4
Merge pull request #2102 from step-security/ak-code-review-permissions
ashishkurmi Apr 30, 2023
d81817d
Update code-review.yml
varunsh-coder Apr 30, 2023
9512ea4
Merge pull request #2105 from step-security/ak-main-to-int-code-review
ashishkurmi May 1, 2023
9da4543
updated getHooks
Devils-Knight May 1, 2023
cfc9d10
Merge pull request #2107 from Devils-Knight/upd
varunsh-coder May 2, 2023
76518e2
adding id-token write permission for code review action
ashishkurmi May 7, 2023
7dd4c19
Merge pull request #2111 from step-security/ak-updating-code-reviewer…
ashishkurmi May 7, 2023
1e3d19f
using ai-codewise int for dogfooding
ashishkurmi May 14, 2023
ab6b1a0
Merge pull request #2129 from step-security/ak-codewise-int
ashishkurmi May 14, 2023
0a314e6
adding int backend endpoint
ashishkurmi May 14, 2023
287df91
Merge pull request #2131 from step-security/ak-code-review-int-endpoint
ashishkurmi May 14, 2023
2c6acf6
updated precommit filePath
Devils-Knight May 16, 2023
d83b06a
Merge pull request #2135 from Devils-Knight/fixPrecommit
varunsh-coder May 16, 2023
754651f
Merge branch 'main' into int
varunsh-coder May 18, 2023
69f0820
Fix Dependabot config indentation issue (#2140)
varunsh-coder May 18, 2023
6ad2893
Merge branch 'main' into int
varunsh-coder Jul 3, 2023
32f4cc0
Update pre-commit logic
varunsh-coder Jul 3, 2023
a45e0e3
Merge pull request #2205 from step-security/pre-commit-line
varunsh-coder Jul 3, 2023
0eb8144
Merge branch 'main' into int
varunsh-coder Jul 6, 2023
92198fc
[StepSecurity] ci: Harden GitHub Actions
step-security-bot Jul 12, 2023
f1c6979
Merge pull request #2230 from step-security/ak-int-harden-runner
ashishkurmi Jul 12, 2023
cb9e08f
directory path test case added
Devils-Knight Jul 26, 2023
630c1e2
Merge pull request #2257 from Devils-Knight/fix2
varunsh-coder Aug 2, 2023
6423e32
update workflow templates to latest versions
shubham-stepsecurity Jul 4, 2024
7a92f67
bump codeql version
shubham-stepsecurity Jul 4, 2024
1e0ada6
updating harden-runner version in code review workflow
ashishkurmi Jul 4, 2024
729990c
Merge pull request #2461 from step-security/ak-codewise-hr-upgrade
ashishkurmi Jul 4, 2024
735c02a
Merge pull request #2460 from step-security/issue2120
ashishkurmi Jul 4, 2024
197383b
removing knowledge base for tomwillis608/detect-secrets-action as it …
ashishkurmi Jul 4, 2024
99b254c
Merge pull request #2464 from step-security/ak-remove-tomwillis608-de…
ashishkurmi Jul 4, 2024
fea221a
Do not set permissions for jobs with GITHUB_TOKEN in job level env
shubham-stepsecurity Sep 6, 2024
95abd71
Merge pull request #2480 from step-security/issue2479
varunsh-coder Sep 6, 2024
6f91094
Update KB and action tags
varunsh-coder Sep 6, 2024
5259779
Merge pull request #2481 from step-security/fix-tests
varunsh-coder Sep 6, 2024
fa7c85b
add additional prms for scorecard template for private repos
shubham-stepsecurity Sep 12, 2024
929021e
Merge pull request #2484 from step-security/issue2483
varunsh-coder Sep 16, 2024
4b43059
add immutable action check
sailikhith-stepsecurity Jan 16, 2025
93e48d5
fix test
sailikhith-stepsecurity Jan 16, 2025
31acb70
update kb by moving remove-disabled-formulae to remove-disabled-pack…
sailikhith-stepsecurity Jan 16, 2025
837f1d1
removing unwanted change
sailikhith-stepsecurity Jan 16, 2025
fe96d6f
mocking http server for unit tests
sailikhith-stepsecurity Jan 18, 2025
1283961
updating pinnig logic to use immutable version instead of hash
sailikhith-stepsecurity Jan 20, 2025
3a3a0b2
Merge branch 'int' of github.com:step-security/secure-repo into immut…
sailikhith-stepsecurity Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ jobs:
int.api.stepsecurity.io:443

- name: Code Review
uses: step-security/ai-codewise@int
uses: step-security/ai-codewise@ab9fe138367d6094b2df7f8469ddc2c5a79c9cf4 # int
2 changes: 1 addition & 1 deletion .github/workflows/kb-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
contents: read
runs-on: ubuntu-latest
steps:
- uses: step-security/harden-runner@ebacdc22ef6c2cfb85ee5ded8f2e640f4c776dd5 # v1
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
allowed-endpoints: >
api.github.com:443
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
env:
PAT: ${{ secrets.PAT }}

- uses: step-security/wait-for-secrets@1204ba02d7a707c4ef2e906d2ea1e36eebd9bbd2
- uses: step-security/wait-for-secrets@5809f7d044804a5a1d43217fa8f3e855939fc9ef
id: wait-for-secrets
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: Remove disabled packages # Homebrew/actions/remove-disabled-packages
# GITHUB_TOKEN not used
2 changes: 1 addition & 1 deletion remediation/dependabot/dependabotconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func UpdateDependabotConfig(dependabotConfig string) (*UpdateDependabotConfigRes
for _, Update := range updateDependabotConfigRequest.Ecosystems {
updateAlreadyExist := false
for _, update := range configMetadata.Updates {
if update.PackageEcosystem == Update.PackageEcosystem && update.Directory == Update.Directory {
if update.PackageEcosystem == Update.PackageEcosystem && (update.Directory == Update.Directory || update.Directory == Update.Directory+"/") {
updateAlreadyExist = true
break
}
Expand Down
5 changes: 5 additions & 0 deletions remediation/dependabot/dependabotconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func TestConfigDependabotFile(t *testing.T) {
Ecosystems: []Ecosystem{{"npm", "/sample", "daily"}},
isChanged: true,
},
{
fileName: "extra-slash.yml",
Ecosystems: []Ecosystem{{"npm", "/sample", "daily"}},
isChanged: false,
},
}

for _, test := range tests {
Expand Down
1 change: 1 addition & 0 deletions remediation/workflow/metadata/actionmetadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Step struct {
type Job struct {
Permissions Permissions `yaml:"permissions"`
Uses string `yaml:"uses"`
Env Env `yaml:"env"`
// RunsOn []string `yaml:"runs-on"`
Steps []Step `yaml:"steps"`
}
Expand Down
1 change: 1 addition & 0 deletions remediation/workflow/metadata/actionmetadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func TestKnowledgeBase(t *testing.T) {

func doesActionRepoExist(filePath string) bool {
splitOnSlash := strings.Split(filePath, "/")

owner := splitOnSlash[5]
repo := splitOnSlash[6]

Expand Down
16 changes: 16 additions & 0 deletions remediation/workflow/permissions/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const errorMissingAction = "KnownIssue-4: Action %s is not in the knowledge base
const errorAlreadyHasPermissions = "KnownIssue-5: Permissions were not added to the job since it already had permissions defined"
const errorDockerAction = "KnownIssue-6: Action %s is a docker action which uses Github token. Docker actions that uses token are not supported"
const errorReusableWorkflow = "KnownIssue-7: Action %s is a reusable workflow. Reusable workflows are not supported as of now."
const errorGithubTokenInJobEnv = "KnownIssue-8: Permissions were not added to the jobs since it has GITHUB_TOKEN in job level env variable"
const errorIncorrectYaml = "Unable to parse the YAML workflow file"

// To avoid a typo while adding the permissions
Expand Down Expand Up @@ -78,6 +79,15 @@ func alreadyHasWorkflowPermissions(workflow metadata.Workflow) bool {
return workflow.Permissions.IsSet
}

func githubTokenInJobLevelEnv(job metadata.Job) bool {
for _, envValue := range job.Env {
if strings.Contains(envValue, "secrets.GITHUB_TOKEN") || strings.Contains(envValue, "github.token") {
return true
}
}
return false
}

func AddWorkflowLevelPermissions(inputYaml string, addProjectComment bool) (string, error) {
workflow := metadata.Workflow{}

Expand Down Expand Up @@ -177,6 +187,12 @@ func AddJobLevelPermissions(inputYaml string) (*SecureWorkflowReponse, error) {
continue
}

if githubTokenInJobLevelEnv(job) {
fixWorkflowPermsReponse.HasErrors = true
errors[jobName] = append(errors[jobName], errorGithubTokenInJobEnv)
continue
}

if metadata.IsCallingReusableWorkflow(job) {
fixWorkflowPermsReponse.HasErrors = true
errors[jobName] = append(errors[jobName], fmt.Sprintf(errorReusableWorkflow, job.Uses))
Expand Down
112 changes: 112 additions & 0 deletions remediation/workflow/pin/action_image_manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package pin

import (
"encoding/json"
"fmt"
"regexp"
"strings"

"net/http"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/sirupsen/logrus"
)

var (
githubImmutableActionArtifactType = "application/vnd.github.actions.package.v1+json"
semanticTagRegex = regexp.MustCompile(`v[0-9]+\.[0-9]+\.[0-9]+$`)
)

type ociManifest struct {
ArtifactType string `json:"artifactType"`
}

// isImmutableAction checks if the action is an immutable action or not
// It queries the OCI manifest for the action and checks if the artifact type is "application/vnd.github.actions.package.v1+json"
//
// Example usage:
//
// # Immutable action (returns true)
// isImmutableAction("actions/[email protected]")
//
// # Non-Immutable action (returns false)
// isImmutableAction("actions/[email protected]")
//
// REF - https://github.com/actions/publish-immutable-action/issues/216#issuecomment-2549914784
func IsImmutableAction(action string) bool {

artifactType, err := getOCIImageArtifactTypeForGhAction(action)
if err != nil {
// log the error
logrus.WithFields(logrus.Fields{"action": action}).WithError(err).Error("error in getting OCI manifest for image")
return false
}

if artifactType == githubImmutableActionArtifactType {
return true
}
return false

Check warning on line 49 in remediation/workflow/pin/action_image_manifest.go

View check run for this annotation

Codecov / codecov/patch

remediation/workflow/pin/action_image_manifest.go#L49

Added line #L49 was not covered by tests

}

// getOCIImageArtifactTypeForGhAction retrieves the artifact type from a GitHub Action's OCI manifest.
// This function is used to determine if an action is immutable by checking its artifact type.
//
// Example usage:
//
// # Immutable action (returns "application/vnd.github.actions.package.v1+json", nil)
// artifactType, err := getOCIImageArtifactTypeForGhAction("actions/[email protected]")
//
// Returns:
// - artifactType: The artifact type string from the OCI manifest
// - error: An error if the action format is invalid or if there's a problem retrieving the manifest
func getOCIImageArtifactTypeForGhAction(action string) (string, error) {

// Split the action into parts (e.g., "actions/checkout@v2" -> ["actions/checkout", "v2"])
parts := strings.Split(action, "@")
if len(parts) != 2 {
return "", fmt.Errorf("invalid action format")
}

// convert v1.x.x to 1.x.x which is
// use regexp to match tag version format and replace v in prefix
// as immutable actions image tag is in format 1.x.x (without v prefix)
// REF - https://github.com/actions/publish-immutable-action/issues/216#issuecomment-2549914784
if semanticTagRegex.MatchString(parts[1]) {
// v1.x.x -> 1.x.x
parts[1] = strings.TrimPrefix(parts[1], "v")
}

// Convert GitHub action to GHCR image reference using proper OCI reference format
image := fmt.Sprintf("ghcr.io/%s:%s", parts[0], parts[1])
imageManifest, err := getOCIManifestForImage(image)
if err != nil {
return "", err
}

var ociManifest ociManifest
err = json.Unmarshal([]byte(imageManifest), &ociManifest)
if err != nil {
return "", err
}

Check warning on line 92 in remediation/workflow/pin/action_image_manifest.go

View check run for this annotation

Codecov / codecov/patch

remediation/workflow/pin/action_image_manifest.go#L91-L92

Added lines #L91 - L92 were not covered by tests
return ociManifest.ArtifactType, nil
}

// getOCIManifestForImage retrieves the artifact type from the OCI image manifest
func getOCIManifestForImage(imageRef string) (string, error) {

// Parse the image reference
ref, err := name.ParseReference(imageRef)
if err != nil {
return "", fmt.Errorf("error parsing reference: %v", err)
}

// Get the image manifest
desc, err := remote.Get(ref, remote.WithTransport(http.DefaultTransport))
if err != nil {
return "", fmt.Errorf("error getting manifest: %v", err)
}

return string(desc.Manifest), nil
}
163 changes: 163 additions & 0 deletions remediation/workflow/pin/action_image_manifest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package pin

import (
"crypto/tls"
"io/ioutil"
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
)

type customTransport struct {
base http.RoundTripper
baseURL string
}

func (t *customTransport) RoundTrip(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Host, "ghcr.io") {
req2 := req.Clone(req.Context())
req2.URL.Scheme = "https"
req2.URL.Host = strings.TrimPrefix(t.baseURL, "https://")
return t.base.RoundTrip(req2)
}
return t.base.RoundTrip(req)
}

func createGhesTestServer(t *testing.T) *httptest.Server {
return httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

w.Header().Set("Content-Type", "application/json")

if !strings.Contains(r.Host, "ghcr.io") {
w.WriteHeader(http.StatusNotFound)
return
}
// Mock manifest endpoints
switch r.URL.Path {

case "/v2/": // simulate ping request
w.WriteHeader(http.StatusOK)

case "/token":
// for immutable actions, since image will be present in registry...it returns 200 OK with token
// otherwise it returns 403 Forbidden
scope := r.URL.Query().Get("scope")
switch scope {
case "repository:actions/checkout:pull":
fallthrough
case "repository:step-security/wait-for-secrets:pull":

w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"token": "test-token", "access_token": "test-token"}`))
default:
w.WriteHeader(http.StatusForbidden)
w.Write([]byte(`{"errors": [{"code": "DENIED", "message": "requested access to the resource is denied"}]}`))
}

case "/v2/actions/checkout/manifests/4.2.2":
fallthrough
case "/v2/actions/checkout/manifests/1.2.0":
fallthrough
case "/v2/step-security/wait-for-secrets/manifests/1.2.0":
w.Write(readHttpResponseForAction(t, r.URL.Path))
case "/v2/actions/checkout/manifests/1.2.3": // since this version doesn't exist
fallthrough
default:
w.WriteHeader(http.StatusNotFound)
w.Write(readHttpResponseForAction(t, "default"))
}
}))
}

func Test_isImmutableAction(t *testing.T) {
// Create test server that mocks GitHub Container Registry
server := createGhesTestServer(t)
defer server.Close()

// Create a custom client that redirects ghcr.io to our test server
originalClient := http.DefaultClient
http.DefaultClient = &http.Client{
Transport: &customTransport{
base: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
baseURL: server.URL,
},
}

// update default transport
OriginalTransport := http.DefaultTransport
http.DefaultTransport = http.DefaultClient.Transport

defer func() {
http.DefaultClient = originalClient
http.DefaultTransport = OriginalTransport
}()

tests := []struct {
name string
action string
want bool
}{
{
name: "immutable action - 1",
sailikhith-stepsecurity marked this conversation as resolved.
Show resolved Hide resolved
action: "actions/[email protected]",
want: true,
},
{
name: "immutable action - 2",
action: "step-security/[email protected]",
want: true,
},
{
name: "non immutable action(valid action)",
action: "sailikhith-stepsecurity/[email protected]",
want: false,
},
{
name: "non immutable action(invalid action)",
action: "sailikhith-stepsecurity/[email protected]",
want: false,
},
{
name: " action with release tag doesn't exist",
action: "actions/[email protected]",
want: false,
},
{
name: "invalid action format",
action: "invalid-format",
want: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

got := IsImmutableAction(tt.action)
if got != tt.want {
t.Errorf("isImmutableAction() = %v, want %v", got, tt.want)
}
})
}
}

func readHttpResponseForAction(t *testing.T, actionPath string) []byte {
// remove v2 prefix from action path
actionPath = strings.TrimPrefix(actionPath, "/v2/")

fileName := strings.ReplaceAll(actionPath, "/", "-") + ".json"
testFilesDir := "../../../testfiles/pinactions/immutableActionResponses/"
respFilePath := filepath.Join(testFilesDir, fileName)

resp, err := ioutil.ReadFile(respFilePath)
if err != nil {
t.Fatalf("error reading test file:%v", err)
}

return resp
}
Loading
Loading