goast

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 28, 2023 License: Apache-2.0 Imports: 15 Imported by: 0

README

goast testgosec trivy

Go AST (Abstract Syntax Tree) based static analysis tool with Rego.

Motivation

There are a lot of static analysis tools for Go language. They inspect Go source code with best practices. However, we need to care not only common best practice but also internal rules of individual, team or organization when reviewing code. Additionally, some kind of function and resource has a rule to use them (e.g. required initialize at first). It may be difficult to check such original rules by a common static analysis tool.

goast is static analysis tool with OPA that is generic policy engine of Rego. It can separate static analysis tool to implementation and policy that a user can customize.

Features

  • Dump Go AST as JSON format (excluding ast.Object to avoid reference cycle)
  • Evaluate Go source code with Rego policy
  • Output the evaluation result as text or JSON format (compatible with reviewdog)

Usage

Install
$ go install github.com/m-mizutani/goast/cmd/goast@latest
Dump source code to confirm AST

dump subcommand output AST as JSON format. --line can specify line number and --func can specify function name for dump.

$ goast dump --line 6 examples/println/main.go | jq
{
  "Path": "examples/println/main.go",
  "Node": {
    "X": {
      "Fun": {
        "X": {
          "NamePos": 44,
          "Name": "fmt",
          "Obj": null
        },
        "Sel": {
          "NamePos": 48,
          "Name": "Println",
          "Obj": null
        }
      },
      "Lparen": 55,
      "Args": [
        {
          "ValuePos": 56,
          "Kind": 9,
          "Value": "\"hello\""
        }
      ],
      "Ellipsis": 0,
      "Rparen": 63
    }
  },
  "Kind": "ExprStmt"
}
Write Rego policy

Here is example of a policy to prohibit fmt.Println.

package goast

fail[res] {
    input.Kind == "ExprStmt"
    input.Node.X.Fun.X.Name == "fmt"
    input.Node.X.Fun.Sel.Name == "Println"

    res := {
        "msg": "do not use fmt.Println",
        "pos": input.Node.X.Fun.X.NamePos,
        "sev": "ERROR",
    }
}

goast's policy rule is following.

  • Package name: goast
  • Input
    • Path: Source code file path
    • Node: Dumped AST (without *ast.Object)
    • Kind: Type of node
  • Output
    • fail: A set of violation results
      • pos: Integer of *Pos (e.g. NamePos). It will be converted to line number and column of source code file
      • msg: Error message
      • sev: Severity. Choose one from INFO, WARNING or ERROR
Evaluation

eval subcommand evaluates go source code (file or directly recursively) with Rego policy file(s).

$ goast eval -p ./policy/do_not_use_println.rego examples/println/main.go
[examples/println/main.go:6] - do not use fmt.Println

        Detected 1 violations

--format, -f option can specify output format text or json. JSON schema is according to Reviewdog Diagnostic Format.

Debug

Also, you can use original opa command to debug policy. A schema of dump output is same with one to be evaluated. Then, opa command can use it with Rego file(s). An example is following.

goast . dump -l 6 examples/println/main.go | opa eval -b ./policy/ -I data
{
  "result": [
    {
      "expressions": [
        {
          "value": {
            "goast": {
              "fail": [
                {
                  "msg": "do not use fmt.Println",
                  "pos": 44,
                  "sev": "ERROR"
                }
              ]
            }
          },
          "text": "data",
          "location": {
            "row": 1,
            "col": 1
          }
        }
      ]
    }
  ]
}

License

Apache License v2

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Inspect

func Inspect(f *ast.File, fSet *token.FileSet, cb callback, options ...InspectOption) error

func Logger

func Logger() *zlog.Logger

func RenewLogger

func RenewLogger(options []zlog.Option)

Types

type DumpHook

type DumpHook func(node *Node, w io.Writer) error

type Fail

type Fail struct {
	Path   string
	Line   int
	Column int
	Msg    string
	Sev    string
}

type Goast

type Goast struct {
	// contains filtered or unexported fields
}

func New

func New(options ...Option) *Goast

func (*Goast) Dump

func (x *Goast) Dump(filePath string, r io.Reader, w io.Writer) error

func (*Goast) Eval

func (x *Goast) Eval(filePath string, r io.Reader) ([]*Fail, error)

func (*Goast) Sync

func (x *Goast) Sync(src string) error

type InspectOption

type InspectOption func(options *inspectOptions)

func WithAllMatched

func WithAllMatched() InspectOption

func WithFuncName

func WithFuncName(funcName string) InspectOption

func WithLine

func WithLine(line int) InspectOption

func WithObjectDepth

func WithObjectDepth(depth int) InspectOption

func WithRootOnly

func WithRootOnly() InspectOption

type Node

type Node struct {
	Path     string
	FileName string
	DirName  string

	Node ast.Node
	Kind string
	// contains filtered or unexported fields
}

func (*Node) Pos

func (x *Node) Pos(p token.Pos) token.Position

type Option

type Option func(g *Goast)

func WithCompact

func WithCompact(enable bool) Option

func WithDumpHook

func WithDumpHook(hook DumpHook) Option

func WithIgnoreAutoGen

func WithIgnoreAutoGen() Option

func WithInspectOptions

func WithInspectOptions(options ...InspectOption) Option

func WithOpacClient

func WithOpacClient(client opac.Client) Option

Directories

Path Synopsis
cmd
examples
autogen
Code generated by yo.
Code generated by yo.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL