mitre / saf_action

GitHub Action for SAF CLI
https://github.com/marketplace/actions/saf-cli-action
Other
6 stars 0 forks source link

Unable to put variables in `command_string` #41

Closed spencer-cdw closed 1 year ago

spencer-cdw commented 1 year ago

First of all, thank you for making this tool and releasing it as a github action.

Is it possible to use string interpolation in the command_string stanza?

For example, I want to:

  1. Find the latest inspec.json file using the find command
  2. Pass that into saf validate threshold

I'm finding that variables are not expanded

      - name: Verify inspec failures
        uses: mitre/saf_action@v1
        with:
          command_string: |
            INSPEC_JSON=$(find "${{ env.PKR_VAR_root_file_path }}/output/${{ env.CLOUD }}/${{ matrix.image }}" -name "inspec*.json" -ls | sort -n | tail -n 1 | awk '{print $NF}' | grep .)
            validate threshold -i $INSPEC_JSON -T "{"error.total": 0, "compliance.min": 50}"

It produces this error

Notice the line Error: ENOENT: no such file or directory, open '$(find'

command_string should be expanding $INSPEC_JSON to a path, however I find that it is treating the variable expansion as a literal string $(find.

(node:27846) [ERR_REQUIRE_ESM] Error Plugin: @mitre/saf [ERR_REQUIRE_ESM]: require() of ES Module /data/_work/_actions/mitre/saf_action/v1/node_modules/inquirer-file-tree-selection-prompt/dist/index.js from /data/_work/_actions/mitre/saf_action/v1/node_modules/@mitre/saf/lib/utils/emasser/generateConfig.js not supported.
Instead change the require of index.js in /data/_work/_actions/mitre/saf_action/v1/node_modules/@mitre/saf/lib/utils/emasser/generateConfig.js to a dynamic import() which is available in all CommonJS modules.
module: @oclif/core@1.20.4
task: toCached
plugin: @mitre/saf
root: /data/_work/_actions/mitre/saf_action/v1/node_modules/@mitre/saf
See more details with DEBUG=*
(Use `node --trace-warnings ...` to show where the warning was created)
node:fs:585
  handleErrorFromBinding(ctx);
  ^

Error: ENOENT: no such file or directory, open '$(find'
    at Object.openSync (node:fs:585:3)
    at Object.readFileSync (node:fs:453:35)
    at /data/_work/_actions/mitre/saf_action/v1/node_modules/@mitre/saf/lib/commands/view/summary.js:19:82
    at Array.forEach (<anonymous>)
    at Summary.run (/data/_work/_actions/mitre/saf_action/v1/node_modules/@mitre/saf/lib/commands/view/summary.js:[18](https://github.com/spencer-cdw/managed-golden-image-service/actions/runs/4491791669/jobs/7900781859#step:12:19):[21](https://github.com/spencer-cdw/managed-golden-image-service/actions/runs/4491791669/jobs/7900781859#step:12:22))
    at async Summary._run (/data/_work/_actions/mitre/saf_action/v1/node_modules/@oclif/core/lib/command.js:80:[22](https://github.com/spencer-cdw/managed-golden-image-service/actions/runs/4491791669/jobs/7900781859#step:12:23))
    at async Config.runCommand (/data/_work/_actions/mitre/saf_action/v1/node_modules/@oclif/core/lib/config/config.js:272:[25](https://github.com/spencer-cdw/managed-golden-image-service/actions/runs/4491791669/jobs/7900781859#step:12:26))
    at async Object.run (/data/_work/_actions/mitre/saf_action/v1/node_modules/@oclif/core/lib/main.js:74:5) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '$(find'
}

Research

Looking at the code, I see it parses the input then runs saf.run

https://github.com/mitre/saf_action/blob/main/run_command.js#L19-L25

I don't see where/how saf.run actually shells out to run a command.

It appears that others have used this syntax succesfully

Any feedback welcome.

spencer-cdw commented 1 year ago

It appears that github string interpolation also does not work.

      - name: Inspec Summary
        uses: mitre/saf_action@v1
        with:
          command_string: view summary -i {{ env.INSPEC_REPORT }}

produces error

Error: ENOENT: no such file or directory, open '{{'
spencer-cdw commented 1 year ago

Also failing with this syntax

UnexpectedArgsError: Unexpected arguments: 0,, \"compliance.min\":, 50}"

      - name: Verify inspec failures
        uses: mitre/saf_action@v1
        with:
          command_string: 'validate threshold -i ${{ env.INSPEC_REPORT }} -T "{\"error.total\": 0, \"compliance.min\": 50}"'  
spencer-cdw commented 1 year ago

And failing with this syntax

UnexpectedArgsError: Unexpected arguments: 0,, "compliance.min":, 50}'

      - name: Verify inspec failures
        uses: mitre/saf_action@v1
        with:
          command_string: 'validate threshold -i ${{ env.INSPEC_REPORT }} -T ''{"error.total": 0, "compliance.min": 50}'''
spencer-cdw commented 1 year ago

Another syntax failing

UnexpectedArgsError: Unexpected arguments: 0,, \\"compliance.min\\":, 50}"

      - name: Verify inspec failures
        uses: mitre/saf_action@v1
        with:
          command_string: 'validate threshold -i ${{ env.INSPEC_REPORT }} -T "{\\"error.total\\": 0, \\"compliance.min\\": 50}"'
spencer-cdw commented 1 year ago

The only syntax I was able to get working was to abandon -T and use -F instead

      - name: Verify inspec failures
        uses: mitre/saf_action@v1
        with:
          command_string: 'validate threshold -i ${{ env.INSPEC_REPORT }} -F ${{ env.PKR_VAR_root_file_path }}/inspec/threshold.yml'
Amndeep7 commented 1 year ago

Thanks for bringing this to our attention @spencer-cdw. The source of the problem was that we were splitting the command string by space instead of treating it how the shell usually does (i.e. quoted strings with spaces inside them are one token). This commit fixes that issue 7cc89248961d5462bfbecea25fbda43221bb386a.

Amndeep7 commented 1 year ago

@spencer-cdw you might be interested in this example showcasing what you were trying to do (but now working): https://github.com/mitre/saf_action/blob/7cc89248961d5462bfbecea25fbda43221bb386a/.github/workflows/example-usages.yml#L16-L19

Please don't worry about that workflow having an overarching fail - that turns out to be due to us not processing paths with spaces inside properly on the saf cli side.