Skip to content

Commit

Permalink
Merge pull request #61 from equinor/main
Browse files Browse the repository at this point in the history
Release Workload Identity
  • Loading branch information
Richard87 authored Apr 15, 2024
2 parents 488bfb6 + 8718078 commit adb03fc
Show file tree
Hide file tree
Showing 36 changed files with 929 additions and 413 deletions.
1 change: 1 addition & 0 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ RVS_APP_NAME_EXCLUDE_LIST=
RVS_WORKERS=
RVS_DB_SERVER=
RVS_DB_DATABASE=
RVS_WORKLOAD_IDENTITY_REGISTRIES=radixdev.azurecr.io
10 changes: 3 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,18 @@ COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o ./rootfs/radix-vulnerability-scanner

# Install SNYK

FROM alpine:3 as tools

COPY install_tools.sh /install/install_tools.sh
RUN chmod +x /install/install_tools.sh
RUN sh /install/install_tools.sh
ADD https://github.com/snyk/snyk/releases/download/v1.1286.1/snyk-alpine /
RUN chmod +x /snyk-alpine

# Run scanner

FROM alpine:3

RUN apk update && \
apk add ca-certificates libstdc++

COPY --from=builder /go/src/github.com/equinor/radix-vulnerability-scanner/rootfs/radix-vulnerability-scanner /usr/local/bin/radix-vulnerability-scanner
COPY --from=tools /usr/local/bin/snyk /usr/local/bin/snyk
COPY --from=tools /snyk-alpine /usr/local/bin/snyk

RUN addgroup -S -g 1000 radix-vulnerability-scanner
RUN adduser -S -u 1000 -G radix-vulnerability-scanner radix-vulnerability-scanner
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ lint: bootstrap
mocks: bootstrap
mockgen -source ./pkg/db/repository.go -destination ./pkg/db/mock/repository.go -package mock
mockgen -source ./pkg/scan/scanner.go -destination ./pkg/scan/mock/scanner.go -package mock
mockgen -source ./pkg/scan/executor/executor.go -destination ./pkg/scan/executor/mock/executor.go -package mock
mockgen -source ./pkg/registry/auth.go -destination ./pkg/registry/mock/auth.go -package mock

HAS_GOLANGCI_LINT := $(shell command -v golangci-lint;)
HAS_MOCKGEN := $(shell command -v mockgen;)
Expand Down
4 changes: 2 additions & 2 deletions charts/radix-vulnerability-scanner/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: v1
appVersion: 1.0.0
version: 1.0.0
appVersion: 1.1.2
version: 1.1.2
description: Scan images in RadixDeployments for vulnerabilities
name: radix-vulnerability-scanner
5 changes: 4 additions & 1 deletion charts/radix-vulnerability-scanner/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ spec:
{{- if not (empty .Values.appNameExcludeList) }}
- --app-name-exclude-list={{ uniq .Values.appNameExcludeList | join "," }}
{{- end}}
{{- if not (empty .Values.workloadIdentityRegistries) }}
- --workload-identity-registries={{ uniq .Values.workloadIdentityRegistries | join "," }}
{{- end}}
{{- if ge (.Values.workers | int) 1 }}
- --workers={{ .Values.workers | int }}
{{- end}}
Expand Down Expand Up @@ -78,7 +81,7 @@ spec:
mountPath: {{ template "vulnerability-scan.dockerConfigFilePath" . }}
{{- end }}
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 14 }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
resources:
Expand Down
4 changes: 4 additions & 0 deletions charts/radix-vulnerability-scanner/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ appNameExcludeList: []
# - canarycicd-test2
# - canarycicd-test1

workloadIdentityRegistries: []
# - radixdev.azurecr.io
# - radixprod.azurecr.io

# Number of workers to process images
# workers: 1

Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ go 1.21
toolchain go1.21.0

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
github.com/containerd/containerd v1.7.14
github.com/equinor/radix-common v1.9.2
github.com/equinor/radix-operator v1.50.2
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/golang/mock v1.6.0
github.com/microsoft/go-mssqldb v1.7.0
github.com/mitchellh/mapstructure v1.5.0
Expand All @@ -16,6 +19,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
golang.org/x/oauth2 v0.15.0
gorm.io/driver/sqlserver v1.5.3
gorm.io/gorm v1.25.7
k8s.io/api v0.29.0
Expand All @@ -26,8 +30,6 @@ require (

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
Expand All @@ -39,7 +41,6 @@ require (
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/swag v0.22.7 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
Expand Down Expand Up @@ -77,7 +78,6 @@ require (
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
Expand Down
7 changes: 0 additions & 7 deletions install_tools.sh

This file was deleted.

96 changes: 92 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,28 @@ import (
"syscall"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned"
"github.com/equinor/radix-vulnerability-scanner/pkg/db"
"github.com/equinor/radix-vulnerability-scanner/pkg/dockercfg"
"github.com/equinor/radix-vulnerability-scanner/pkg/options"
"github.com/equinor/radix-vulnerability-scanner/pkg/scan"
"github.com/equinor/radix-vulnerability-scanner/pkg/scan/executor"
"github.com/equinor/radix-vulnerability-scanner/pkg/server"
"github.com/equinor/radix-vulnerability-scanner/pkg/tokenstore"
"github.com/equinor/radix-vulnerability-scanner/pkg/tokenstore/tokensource"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

func main() {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()

opts, err := server.LoadOptions(os.Args[1:])
opts, err := options.LoadOptions(os.Args[1:])
if err != nil {
log.Fatal().Msg(err.Error())
}
Expand All @@ -28,8 +40,20 @@ func main() {
}

logOptions(opts)
scanOptions := setupScanOptions(ctx, opts)
scanner := scan.NewSnykScanner(executor.New(), scanOptions...)

srv, err := server.New(opts)
repo, err := db.NewGormRepository(&opts.DB)
if err != nil {
log.Fatal().Msg(err.Error())
}

kubeClient, radixClient, err := getKubernetesClients(&opts.Kube)
if err != nil {
log.Fatal().Msg(err.Error())
}

srv, err := server.New(kubeClient, radixClient, scanner, repo, opts)
if err != nil {
log.Fatal().Msg(err.Error())
}
Expand All @@ -40,7 +64,42 @@ func main() {
}
}

func setupLogger(opts *server.Options, ctx context.Context) (context.Context, error) {
func setupScanOptions(ctx context.Context, opts *options.Options) []scan.SnykOption {
tokenstore, err := setupTokenStore(ctx, opts.WorkloadIdentityForRegistries)
if err != nil {
log.Fatal().Msg(err.Error())
}

scanOptions := []scan.SnykOption{scan.WithAuthProvider(tokenstore)}

if opts.Docker.AuthsFile != "" {
dockerConfig, err := dockercfg.NewFromFile(opts.Docker.AuthsFile)
if err != nil {
log.Fatal().Msg(err.Error())
}
scanOptions = append(scanOptions, scan.WithAuthProvider(dockerConfig))
}
return scanOptions
}

func setupTokenStore(ctx context.Context, registries []string) (*tokenstore.TokenStore, error) {
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
return nil, err
}

var sources []tokenstore.SourceOption
for _, registry := range registries {
source := tokensource.NewACRTokenSource(ctx, registry, tokensource.WithCredentialOption(cred))

sources = append(sources, tokenstore.WithTokenSource(registry, source))
}

ts := tokenstore.New(sources...)
return ts, nil
}

func setupLogger(opts *options.Options, ctx context.Context) (context.Context, error) {
zerolog.DurationFieldUnit = time.Millisecond
level, err := zerolog.ParseLevel(opts.LogLevel)
if err != nil {
Expand All @@ -56,7 +115,7 @@ func setupLogger(opts *server.Options, ctx context.Context) (context.Context, er
return ctx, nil
}

func logOptions(opts *server.Options) {
func logOptions(opts *options.Options) {
log.Info().Msg("Configuration")
log.Info().Msgf(" full-sync-cron-spec: %v", opts.FullSyncCronSpec)
log.Info().Msgf(" app-name-exclude-list: %v", strings.Join(opts.AppNameExcludeList, ","))
Expand All @@ -67,4 +126,33 @@ func logOptions(opts *server.Options) {
log.Info().Msgf(" vulnerability-rescan-age: %s", opts.VulnerabilityScan.RescanAge)
log.Info().Msgf(" docker-config-file: %s", opts.Docker.AuthsFile)
log.Info().Msgf(" kube-config-file: %s", opts.Kube.KubeConfigFile)
log.Info().Msgf(" workload-identity-registries: %s", strings.Join(opts.WorkloadIdentityForRegistries, ","))
}

func getKubernetesClients(opts *options.KubeOptions) (kubernetes.Interface, radix.Interface, error) {
var clientConfig *rest.Config
var err error

if len(opts.KubeConfigFile) > 0 {
loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: opts.KubeConfigFile}
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
clientConfig, err = loader.ClientConfig()
} else {
clientConfig, err = rest.InClusterConfig()
}
if err != nil {
return nil, nil, err
}

kubeClient, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return nil, nil, err
}

radixClient, err := radix.NewForConfig(clientConfig)
if err != nil {
return nil, nil, err
}

return kubeClient, radixClient, nil
}
28 changes: 25 additions & 3 deletions pkg/db/gorm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ package db
import (
"context"
"database/sql"
"fmt"
"time"

commongorm "github.com/equinor/radix-common/pkg/gorm"
"github.com/equinor/radix-vulnerability-scanner/pkg/generic"
"github.com/equinor/radix-vulnerability-scanner/pkg/options"
mssql "github.com/microsoft/go-mssqldb"
"github.com/microsoft/go-mssqldb/azuread"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
)

const vulnerabilityBulkTypeTvpName = "dbo.VulnerabilityBulkType"
Expand All @@ -20,10 +26,26 @@ type gormRepository struct {
}

// NewGormRepository returns a Repository using a Gorm ORM (https://gorm.io/index.html) database to access data
func NewGormRepository(db *gorm.DB) Repository {
return &gormRepository{
db: db,
func NewGormRepository(opts *options.DBOptions) (Repository, error) {

dsn := fmt.Sprintf("server=%s;database=%s;fedauth=ActiveDirectoryDefault", opts.Server, opts.Database)
dialector := sqlserver.New(sqlserver.Config{
DriverName: azuread.DriverName,
DSN: dsn,
})

gormdb, err := gorm.Open(dialector, &gorm.Config{
NamingStrategy: schema.NamingStrategy{NoLowerCase: true},
Logger: commongorm.NewLogger(),
DisableAutomaticPing: false,
})
if err != nil {
return nil, err
}

return &gormRepository{
db: gormdb,
}, nil
}

func (r *gormRepository) GetLastImageScan(ctx context.Context, image string) (*ImageScanDto, error) {
Expand Down
16 changes: 7 additions & 9 deletions pkg/db/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import (
"time"
)

type (
// Repository defines methods for reading and storing data about vulnerability scans
Repository interface {
// GetLastImageScan returns the last vulnerability scan for an image
GetLastImageScan(ctx context.Context, image string) (*ImageScanDto, error)
// RegisterImageScan stores information about a vulnerability scan for an image
RegisterImageScan(ctx context.Context, image string, baseImage *string, scanTime time.Time, success bool, vulnerabilities []VulnerabilityBulkDto, identifiers []VulnerabilityIdentifierBulkDto, references []VulnerabilityReferenceBulkDto) error
}
)
// Repository defines methods for reading and storing data about vulnerability scans
type Repository interface {
// GetLastImageScan returns the last vulnerability scan for an image
GetLastImageScan(ctx context.Context, image string) (*ImageScanDto, error)
// RegisterImageScan stores information about a vulnerability scan for an image
RegisterImageScan(ctx context.Context, image string, baseImage *string, scanTime time.Time, success bool, vulnerabilities []VulnerabilityBulkDto, identifiers []VulnerabilityIdentifierBulkDto, references []VulnerabilityReferenceBulkDto) error
}
Loading

0 comments on commit adb03fc

Please sign in to comment.