Skip to content

Commit

Permalink
✨ Allowing better configuration for the action (#3)
Browse files Browse the repository at this point in the history
* 📌 Pinning feature branch for integration test

* ✨ Back to composite with build args

* 🚚 Backed up old action.yml

* 🐛 Corrected Image Name

* 🐛 Forgot parameter

* Test

* 🚚 Moved old action definition as backup

* 🐛 Fixed Bug where Action is not build correctly

* 📝 Updated docs to reflect new inputs

* ➕ Added zerolog

* ✨ Introduced Logging via zerolog

* ✨ Implemented Call Chain Lookup

* 🔧 Making docker build less verbose
  • Loading branch information
Templum authored Sep 15, 2022
1 parent ce01fa0 commit 980bdc5
Show file tree
Hide file tree
Showing 14 changed files with 287 additions and 200 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ jobs:
shell: bash
- name: Integration Test
id: integration-test
uses: Templum/govulncheck-action@main
uses: Templum/govulncheck-action@feature/2
with:
go-version: 1.18.3
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
ARG GOLANG_VERSION=1.19
FROM golang:1.19 as builder

WORKDIR /go/src/github.com/Templum/govulncheck-action/
ENV GO111MODULE=on

RUN CGO_ENABLED=0 go install golang.org/x/vuln/cmd/govulncheck@latest

COPY go.mod go.sum ./
RUN go mod download

Expand All @@ -13,8 +12,9 @@ COPY . .
# Statically compile our app for use in a distroless container
RUN CGO_ENABLED=0 go build -ldflags="-w -s" -v -o action .

FROM golang:1.19
COPY --from=builder /go/src/github.com/Templum/govulncheck-action/action /action
COPY --from=builder /go/bin/govulncheck /usr/local/bin/govulncheck
FROM golang:$GOLANG_VERSION
ARG VULNCHECK_VERSION=latest
RUN go install golang.org/x/vuln/cmd/govulncheck@$VULNCHECK_VERSION

COPY --from=builder /go/src/github.com/Templum/govulncheck-action/action /action
ENTRYPOINT ["/action"]
31 changes: 21 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ Performs vulnerability scan using govulncheck and afterwards uploads it as [Sari

[![Build](https://github.com/Templum/govulncheck-action/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/Templum/govulncheck-action/actions/workflows/build.yml)

- [Vulnerability Management for Go](https://go.dev/blog/vuln)
- [govulncheck docs](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)
## :information_source: Limitations of govulncheck :information_source:

For a full list of currently known limitations please head over to [here](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck#hdr-Limitations). Listed below are an important overview.

* Govulncheck only reads binaries compiled with Go 1.18 and later.
* Govulncheck only reports vulnerabilities that apply to the current Go build system and configuration (GOOS/GOARCH settings).

## :books: Useful links & resources on govulncheck :books:

* Official Package Documentation: [Link](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)
* Introduction Blogpost: [Link](https://go.dev/blog/vuln)

## Usage

### Example Workflow

Please be aware that this workflow highlights all available inputs. But all inputs come with a default value.
Hence it is not required to provide any values.

```yaml
name: My Workflow
on: [push, pull_request]
Expand All @@ -25,15 +30,21 @@ jobs:
- name: Running govulncheck
uses: Templum/govulncheck-action@<version>
with:
go-version: 1.18
vulncheck-version: latest
package: ./...
github-token: ${{ secrets.GITHUB_TOKEN }}
```
### Inputs
| Input | Description |
|-----------------------------|--------------------------------------------------------------------------------------|
| `package` _(optional)_ | The package you want to scan, by default will be `./...` |
| `github-token` _(optional)_ | Github Token to upload sarif report. Needs *write* permissions for `security_events` |
| Input | Description |
|----------------------------------|---------------------------------------------------------------------------------------------------|
| `go-version` _(optional)_ | Version of Go used for scanning the code, should equal *your* runtime version. Defaults to `1.19` |
| `vulncheck-version` _(optional)_ | Version of govulncheck that should be used, by default `latest` |
| `package` _(optional)_ | The package you want to scan, by default will be `./...` |
| `github-token` _(optional)_ | Github Token to upload sarif report. Needs *write* permissions for `security_events` |

> :warning: Please be aware that go-version should be a valid tag name for the [golang dockerhub image](https://hub.docker.com/_/golang/tags).

> Please be aware if the token is not specified it uses `github.token` for more details on that check [those docs](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
> :lock: Please be aware if the token is not specified it uses `github.token` for more details on that check [those docs](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
23 changes: 17 additions & 6 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,28 @@ inputs:
description: "The package you want to scan, by default will be ./..."
required: false
default: "./..."
go-version:
description: "Can be any Tag for the golang docker image, but should ideally match your runtime go version. By default 1.19 is assumed"
required: false
default: "1.19"
vulncheck-version:
description: "Version of govulncheck that should be used, by default latest"
required: false
default: "latest"
github-token:
description: "Github App token to upload sarif report. Needs write permissions for security_events. By default it will use 'github.token' value"
default: ${{ github.token }}
required: true
required: false

runs:
using: "docker"
image: "Dockerfile"
env:
GITHUB_TOKEN: "${{ inputs.github-token }}"
PACKAGE: "${{ inputs.package }}"
using: "composite"
steps:
- id: build
run: docker build --build-arg GOLANG_VERSION=${{ inputs.go-version }} --build-arg VULNCHECK_VERSION=${{ inputs.vulncheck-version }} -q -f $GITHUB_ACTION_PATH/Dockerfile -t templum/govulncheck-action:local $GITHUB_ACTION_PATH
shell: bash
- id: run
run: docker run --rm -v $(pwd):/github/workspace --workdir /github/workspace -e GITHUB_TOKEN=${{ inputs.github-token }} -e PACKAGE=${{ inputs.package }} -e VERSION=${{ inputs.version }} -e GITHUB_REPOSITORY=${{ github.repository }} -e GITHUB_REF=${{ github.ref }} -e GITHUB_SHA=${{ github.sha }} templum/govulncheck-action:local
shell: bash

branding:
icon: "alert-octagon"
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require golang.org/x/vuln v0.0.0-20220908210932-64dbbd7bba4f
require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand All @@ -16,6 +18,7 @@ require (
require (
github.com/google/go-github/v47 v47.0.0
github.com/owenrumney/go-sarif/v2 v2.1.2
github.com/rs/zerolog v1.28.0
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
Expand All @@ -20,11 +22,19 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
github.com/owenrumney/go-sarif/v2 v2.1.2 h1:PMDK7tXShJ9zsB7bfvlpADH5NEw1dfA9xwU8Xtdj73U=
github.com/owenrumney/go-sarif/v2 v2.1.2/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand All @@ -45,6 +55,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
23 changes: 23 additions & 0 deletions hack/old.action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: "Golang Vulncheck"
description: "Performs vulnerability scan using govulncheck and afterwards uploads it as Sarif Report to Github"
author: "Templum"
inputs:
package:
description: "The package you want to scan, by default will be ./..."
required: false
default: "./..."
github-token:
description: "Github App token to upload sarif report. Needs write permissions for security_events. By default it will use 'github.token' value"
default: ${{ github.token }}
required: true

runs:
using: "docker"
image: "Dockerfile"
env:
GITHUB_TOKEN: "${{ inputs.github-token }}"
PACKAGE: "${{ inputs.package }}"

branding:
icon: "alert-octagon"
color: "red"
39 changes: 27 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,57 @@
package main

import (
"fmt"
"os"
"runtime"

"github.com/Templum/govulncheck-action/pkg/github"
"github.com/Templum/govulncheck-action/pkg/sarif"
"github.com/Templum/govulncheck-action/pkg/vulncheck"
"github.com/rs/zerolog"
)

func main() {
scanner := vulncheck.NewScanner()
zerolog.SetGlobalLevel(zerolog.InfoLevel)

if os.Getenv("LOCAL") == "true" {
scanner = vulncheck.NewLocalScanner()
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: zerolog.TimeFormatUnix}).
With().
Timestamp().
Logger() // Main Logger

reporter := sarif.NewSarifReporter(logger)
github := github.NewSarifUploader(logger)
scanner := vulncheck.NewScanner(logger)

if os.Getenv("DEBUG") == "true" {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
logger.Debug().Msg("Running in Debug-Mode will use hardcoded scan result and enable debug logs")

scanner = vulncheck.NewLocalScanner(logger, "/workspaces/govulncheck-action/hack/output.json")
}

reporter := sarif.NewSarifReporter()
converter := vulncheck.NewVulncheckConverter(reporter)
github := github.NewSarifUploader()
logger.Info().
Str("Go-Version", runtime.Version()).
Str("Go-Os", runtime.GOOS).
Str("Go-Arch", runtime.GOARCH).
Msg("GoEnvironment Details:")

result, err := scanner.Scan()
if err != nil {
fmt.Printf("%v \n", err) // TODO: Start using proper logger
logger.Error().Err(err).Msg("Scanning yielded error")
os.Exit(2)
}

err = converter.Convert(result)
err = reporter.Convert(result)
if err != nil {
fmt.Printf("%v \n", err) // TODO: Start using proper logger
logger.Error().Err(err).Msg("Conversion of Scan yielded error")
os.Exit(2)
}

err = github.UploadReport(reporter)
if err != nil {
fmt.Printf("%v \n", err) // TODO: Start using proper logger
logger.Error().Err(err).Msg("Upload of Sarif Report GitHub yielded error")
os.Exit(2)
}

fmt.Println("Successfully processed uploaded vulncheck report to Github")
logger.Info().Msg("Successfully uploaded Sarif Report to Github, it will be available after processing")
}
47 changes: 23 additions & 24 deletions pkg/github/sarif_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"os"
"strings"

"github.com/Templum/govulncheck-action/pkg/sarif"
"github.com/Templum/govulncheck-action/pkg/types"
"github.com/google/go-github/v47/github"
"github.com/rs/zerolog"
"golang.org/x/oauth2"
)

Expand All @@ -25,29 +25,34 @@ const (
)

type SarifUploader interface {
UploadReport(report sarif.Report) error
UploadReport(report types.Reporter) error
}

type GithubSarifUploader struct {
client *github.Client
log zerolog.Logger
}

func NewSarifUploader() SarifUploader {
func NewSarifUploader(logger zerolog.Logger) SarifUploader {
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: os.Getenv(envToken)},
)
tc := oauth2.NewClient(ctx, ts)

return &GithubSarifUploader{client: github.NewClient(tc)}
return &GithubSarifUploader{client: github.NewClient(tc), log: logger}
}

func (g *GithubSarifUploader) UploadReport(report sarif.Report) error {
func (g *GithubSarifUploader) UploadReport(report types.Reporter) error {
ownerAndRepo := strings.Split(os.Getenv(envRepo), "/")
commit := os.Getenv(envSha)
gitRef := os.Getenv(envGitRef)

fmt.Printf("Preparing Report for commit %s on ref %s \n", commit, gitRef)
g.log.Info().
Str("Commit", commit).
Str("Ref", gitRef).
Msg("Preparing Report for upload to Github")

encodedAndCompressedReport, err := g.prepareReport(report)
if err != nil {
return err
Expand All @@ -58,11 +63,14 @@ func (g *GithubSarifUploader) UploadReport(report sarif.Report) error {
Ref: &gitRef,
Sarif: &encodedAndCompressedReport,
})

if _, ok := err.(*github.AcceptedError); ok {
var response github.SarifID
_ = json.Unmarshal(err.(*github.AcceptedError).Raw, &response)

fmt.Printf("Successfully uploaded Report to Github it received ID %s \n", *response.ID)
g.log.Info().
Str("sarif_id", *response.ID).
Msg("Report was uploaded to GitHub")
return nil
}

Expand All @@ -73,13 +81,13 @@ func (g *GithubSarifUploader) UploadReport(report sarif.Report) error {
return errors.New("unexpected response from github")
}

func (g *GithubSarifUploader) prepareReport(report sarif.Report) (string, error) {
func (g *GithubSarifUploader) prepareReport(report types.Reporter) (string, error) {
var b bytes.Buffer

// Can only throw for invalid level, which can not be the case here
writer, _ := gzip.NewWriterLevel(&b, flate.BestSpeed)

err := report.Flush(writer)
err := report.Write(writer)
if err != nil {
return "", err
}
Expand All @@ -90,19 +98,10 @@ func (g *GithubSarifUploader) prepareReport(report sarif.Report) (string, error)
return "", err
}

return base64.StdEncoding.EncodeToString(b.Bytes()), nil
}

/**
func debugCompressedContent(raw []byte) {
var readB = bytes.NewBuffer(raw)
g.log.Debug().
Int("Original Size", b.Len()).
Int("Compressed Size", b.Cap()).
Msg("Report was successfully gzipped")

reader, _ := gzip.NewReader(readB)
b, err := io.ReadAll(reader)
if err != nil {
fmt.Printf("Error %v", err)
} else {
fmt.Printf("Decoded string %s", string(b))
}
return base64.StdEncoding.EncodeToString(b.Bytes()), nil
}
**/
Loading

0 comments on commit 980bdc5

Please sign in to comment.