diff --git a/.github/actions/golangci-lint/action.yaml b/.github/actions/golangci-lint/action.yaml new file mode 100644 index 0000000..9afbb68 --- /dev/null +++ b/.github/actions/golangci-lint/action.yaml @@ -0,0 +1,18 @@ +# This action runs golangci-lint using Makefile. +# It ensures the same version of golangci-lint is used in CI as in local development. +name: golangci-lint +description: 'Run golangci-lint' +inputs: + working-directory: + description: 'Working directory' + required: false + default: '.' +runs: + using: 'composite' + steps: + - name: Run golangci-lint + run: | + echo "::add-matcher::${{ inputs.working-directory }}/.github/actions/golangci-lint/matcher.json" + make lint + echo "::remove-matcher owner=golangci-lint::" + shell: bash diff --git a/.github/actions/golangci-lint/matcher.json b/.github/actions/golangci-lint/matcher.json new file mode 100644 index 0000000..e6c5ac7 --- /dev/null +++ b/.github/actions/golangci-lint/matcher.json @@ -0,0 +1,17 @@ +{ + "problemMatcher": [ + { + "owner": "golangci-lint-colored-line-number", + "severity": "error", + "pattern": [ + { + "regexp": "^([^:]+):(\\d+):(?:(\\d+):)?\\s+(.+ \\(.+\\))$", + "file": 1, + "line": 2, + "column": 3, + "message": 4 + } + ] + } + ] +} diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 0221189..217e6a5 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -3,7 +3,6 @@ on: push: branches: - master - pull_request: jobs: build: name: Build diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 674aa16..908e48a 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -21,18 +21,8 @@ jobs: go-version: "stable" id: go - - name: Get dependencies - run: | - go get -v -t -d ./... - - # https://github.com/golangci/golangci-lint-action - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: v1.61.0 - # Workaround for "file exists" errors while running tar. - # golangci-lint-action conflicts with caching in setup-go - skip-pkg-cache: true + uses: ./.github/actions/golangci-lint - name: Build run: make build diff --git a/.gitignore b/.gitignore index 8839b2a..63f02cc 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ # Local History for Visual Studio Code .history/ -./certyaml +certyaml diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..2bdfa9b --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,14 @@ +linters: +# https://golangci-lint.run/usage/linters/#enabled-by-default + enable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - unused + - gosec + - gofmt + - goimports + - misspell + - revive diff --git a/Makefile b/Makefile index 36f9941..2d317c3 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ all: check build +check: test lint + test: go test --race -v ./... -check: test - golangci-lint run - gosec -quiet ./... +lint: + go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 run build: go build -v ./cmd/certyaml @@ -13,9 +14,5 @@ build: install: go install -v ./cmd/certyaml -install-tools: - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 - go install github.com/securego/gosec/v2/cmd/gosec@v2.18.2 - update-modules: go get -u -t ./... && go mod tidy diff --git a/certificate_test.go b/certificate_test.go index ad28a01..399e768 100644 --- a/certificate_test.go +++ b/certificate_test.go @@ -323,17 +323,17 @@ func TestWritingPEMFiles(t *testing.T) { func TestRegenerate(t *testing.T) { cert := Certificate{Subject: "CN=Joe"} - old, err := cert.TLSCertificate() + older, err := cert.TLSCertificate() assert.Nil(t, err) err = cert.Generate() assert.Nil(t, err) - new, err := cert.TLSCertificate() + newer, err := cert.TLSCertificate() assert.Nil(t, err) - assert.NotEqual(t, old.Certificate, new.Certificate) - assert.NotEqual(t, old.PrivateKey, new.PrivateKey) + assert.NotEqual(t, older.Certificate, newer.Certificate) + assert.NotEqual(t, older.PrivateKey, newer.PrivateKey) } func TestSerial(t *testing.T) { diff --git a/crl_test.go b/crl_test.go index 3e6ff78..eb31771 100644 --- a/crl_test.go +++ b/crl_test.go @@ -109,7 +109,7 @@ func TestParallelCRLLazyInitialization(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) - go func(cert *Certificate) { + go func(_ *Certificate) { defer wg.Done() _, err := crl.DER() assert.Nil(t, err) diff --git a/go.mod b/go.mod index 31ac159..02098c3 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,11 @@ module github.com/tsaarni/certyaml -go 1.22.0 - -toolchain go1.22.4 +go 1.19 require ( github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 github.com/stretchr/testify v1.9.0 github.com/tsaarni/x500dn v1.0.0 - golang.org/x/mod v0.21.0 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index 6e85a0b..f11ed76 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tsaarni/x500dn v1.0.0 h1:LvaWTkqRpse4VHBhB5uwf3wytokK4vF9IOyNAEyiA+U= github.com/tsaarni/x500dn v1.0.0/go.mod h1:QaHa3EcUKC4dfCAZmj8+ZRGLKukWgpGv9H3oOCsAbcE= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/manifest/manifest_test.go b/internal/manifest/manifest_test.go index 72f6ec9..f1a10fb 100644 --- a/internal/manifest/manifest_test.go +++ b/internal/manifest/manifest_test.go @@ -19,20 +19,22 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" + "crypto/sha256" "crypto/tls" "crypto/x509" "encoding/pem" + "io/fs" "math/big" "net" "net/url" "os" "path" + "path/filepath" "sort" "testing" "time" "github.com/stretchr/testify/assert" - "golang.org/x/mod/sumdb/dirhash" ) func TestManifestHandling(t *testing.T) { @@ -87,12 +89,12 @@ func TestStateHandling(t *testing.T) { assert.Nil(t, err) // Check stable hashing: calling generate again on same manifest does not alter the state. - h1, err := dirhash.HashDir(dir, "", dirhash.Hash1) + h1, err := dirHash(dir) assert.Nil(t, err) err = GenerateCertificates(&output, "testdata/certs-state-1.yaml", path.Join(dir, "state.yaml"), dir) assert.Nil(t, err) - h2, err := dirhash.HashDir(dir, "", dirhash.Hash1) + h2, err := dirHash(dir) assert.Nil(t, err) assert.Equal(t, h1, h2) @@ -102,7 +104,7 @@ func TestStateHandling(t *testing.T) { err = GenerateCertificates(&output, "testdata/certs-state-1.yaml", path.Join(dir, "state.yaml"), dir) assert.Nil(t, err) - h3, err := dirhash.HashDir(dir, "", dirhash.Hash1) + h3, err := dirHash(dir) assert.Nil(t, err) assert.NotEqual(t, h2, h3) @@ -110,7 +112,7 @@ func TestStateHandling(t *testing.T) { err = GenerateCertificates(&output, "testdata/certs-state-2.yaml", path.Join(dir, "state.yaml"), dir) assert.Nil(t, err) - h4, err := dirhash.HashDir(dir, "", dirhash.Hash1) + h4, err := dirHash(dir) assert.Nil(t, err) assert.NotEqual(t, h3, h4) } @@ -298,3 +300,29 @@ func TestInvalidRevocation(t *testing.T) { err = GenerateCertificates(&output, "testdata/cert-invalid-revoke-self-signed.yaml", path.Join(dir, "state.yaml"), dir) assert.NotNil(t, err) } + +// Helpers + +// dirHash returns a hash of all files in a directory. +func dirHash(dir string) (string, error) { + hash := sha256.New() + + err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + buf, err := os.ReadFile(path) + if err != nil { + return err + } + hash.Write(buf) + } + return nil + }) + if err != nil { + return "", err + } + + return string(hash.Sum(nil)), nil +}