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

✨ Allowing better configuration for the action #3

Merged
merged 13 commits into from
Sep 15, 2022
Merged
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