Skip to content

Commit

Permalink
Added --client-signing-algorithms flag
Browse files Browse the repository at this point in the history
Signed-off-by: Riccardo Schirone <[email protected]>
  • Loading branch information
ret2libc committed Jan 23, 2024
1 parent 9865ca9 commit ee1f9ae
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 3 deletions.
84 changes: 81 additions & 3 deletions cmd/rekor-server/app/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,25 @@ import (
"net/http"
"net/http/pprof"
"os"
"sort"
"strings"
"time"

homedir "github.com/mitchellh/go-homedir"
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
"github.com/sigstore/rekor/pkg/log"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"sigs.k8s.io/release-utils/version"
)

var (
cfgFile string
logType string
enablePprof bool
cfgFile string
logType string
enablePprof bool
clientSigningAlgorithms ClientSigningAlgorithmOptions
// these map to the operationId as defined in openapi.yaml file
operationIds = []string{
"searchIndex",
Expand Down Expand Up @@ -68,6 +73,64 @@ func Execute() {
}
}

type ClientSigningAlgorithmOptions []v1.KnownSignatureAlgorithm

func (sa *ClientSigningAlgorithmOptions) String() string {
var algos []v1.KnownSignatureAlgorithm
if len(*sa) == 0 {
algos = []v1.KnownSignatureAlgorithm{}
for keyAlgorithmId := range v1.KnownSignatureAlgorithm_name {
if keyAlgorithmId == 0 {
continue
}
algos = append(algos, v1.KnownSignatureAlgorithm(keyAlgorithmId))
}
} else {
algos = []v1.KnownSignatureAlgorithm(*sa)
}
algos_str := []string{}
for _, algo := range algos {
algo_str, err := signature.FormatSignatureAlgorithmFlag(algo)
if err != nil {
panic(err)
}
algos_str = append(algos_str, *algo_str)
}
return strings.Join(algos_str, ",")
}

func (sa *ClientSigningAlgorithmOptions) Set(s string) error {
algos := strings.Split(s, ",")
options := []v1.KnownSignatureAlgorithm{}
for _, algo := range algos {
signatureAlgorithm, err := signature.ParseSignatureAlgorithmFlag(algo)
if err != nil {
return err
}
options = append(options, signatureAlgorithm)
}
*sa = ClientSigningAlgorithmOptions(options)
return nil
}

func (sa *ClientSigningAlgorithmOptions) Type() string {
return "stringSlice"
}

func (sa *ClientSigningAlgorithmOptions) Value() []v1.KnownSignatureAlgorithm {
if len(*sa) == 0 {
algos := []v1.KnownSignatureAlgorithm{}
for keyAlgorithmId := range v1.KnownSignatureAlgorithm_name {
if keyAlgorithmId == 0 {
continue
}
algos = append(algos, v1.KnownSignatureAlgorithm(keyAlgorithmId))
}
return algos
}
return []v1.KnownSignatureAlgorithm(*sa)
}

func init() {
cobra.OnInitialize(initConfig)

Expand Down Expand Up @@ -131,6 +194,21 @@ Memory and file-based signers should only be used for testing.`)
rootCmd.PersistentFlags().Int("search_index.mysql.max_open_connections", 0, "maximum open connections")
rootCmd.PersistentFlags().Int("search_index.mysql.max_idle_connections", 0, "maximum idle connections")

keyAlgorithmTypes := []string{}
for keyAlgorithmId := range v1.KnownSignatureAlgorithm_name {
if keyAlgorithmId == 0 {
continue
}
keyFlag, err := signature.FormatSignatureAlgorithmFlag(v1.KnownSignatureAlgorithm(keyAlgorithmId))
if err != nil {
panic(err)
}
keyAlgorithmTypes = append(keyAlgorithmTypes, *keyFlag)
}
sort.Strings(keyAlgorithmTypes)
keyAlgorithmHelp := fmt.Sprintf("signing algorithm to use for signing/hashing (allowed %s)", strings.Join(keyAlgorithmTypes, ", "))
rootCmd.PersistentFlags().Var(&clientSigningAlgorithms, "client-signing-algorithms", keyAlgorithmHelp)

if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
log.Logger.Fatal(err)
}
Expand Down
17 changes: 17 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
"github.com/sigstore/rekor/pkg/indexstorage"
"github.com/sigstore/rekor/pkg/log"
"github.com/sigstore/rekor/pkg/pubsub"
Expand Down Expand Up @@ -70,6 +71,7 @@ type API struct {
// Publishes notifications when new entries are added to the log. May be
// nil if no publisher is configured.
newEntryPublisher pubsub.Publisher
algorithmRegistry *signature.AlgorithmRegistryConfig

Check failure on line 74 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

undefined: signature.AlgorithmRegistryConfig

Check failure on line 74 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / container-build

undefined: signature.AlgorithmRegistryConfig

Check failure on line 74 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / build

undefined: signature.AlgorithmRegistryConfig
}

func NewAPI(treeID uint) (*API, error) {
Expand Down Expand Up @@ -102,6 +104,20 @@ func NewAPI(treeID uint) (*API, error) {
log.Logger.Infof("Starting Rekor server with active tree %v", tid)
ranges.SetActive(tid)

algorithms_str := viper.GetStringSlice("client-signing-algorithms")
var algorithms []v1.KnownSignatureAlgorithm

Check failure on line 108 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

undefined: v1.KnownSignatureAlgorithm

Check failure on line 108 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / container-build

undefined: v1.KnownSignatureAlgorithm

Check failure on line 108 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / build

undefined: v1.KnownSignatureAlgorithm
for _, a := range algorithms_str {
algorithm, err := signature.ParseSignatureAlgorithmFlag(a)

Check failure on line 110 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

undefined: signature.ParseSignatureAlgorithmFlag

Check failure on line 110 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / container-build

undefined: signature.ParseSignatureAlgorithmFlag

Check failure on line 110 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / build

undefined: signature.ParseSignatureAlgorithmFlag
if err != nil {
return nil, fmt.Errorf("parsing signature algorithm flag: %w", err)
}
algorithms = append(algorithms, algorithm)
}
algorithmRegistry, err := signature.NewAlgorithmRegistryConfig(algorithms)

Check failure on line 116 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

undefined: signature.NewAlgorithmRegistryConfig

Check failure on line 116 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / container-build

undefined: signature.NewAlgorithmRegistryConfig

Check failure on line 116 in pkg/api/api.go

View workflow job for this annotation

GitHub Actions / build

undefined: signature.NewAlgorithmRegistryConfig
if err != nil {
return nil, fmt.Errorf("getting algorithm registry: %w", err)
}

rekorSigner, err := signer.New(ctx, viper.GetString("rekor_server.signer"),
viper.GetString("rekor_server.signer-passwd"))
if err != nil {
Expand Down Expand Up @@ -142,6 +158,7 @@ func NewAPI(treeID uint) (*API, error) {
signer: rekorSigner,
// Utility functionality not required for operation of the core service
newEntryPublisher: newEntryPublisher,
algorithmRegistry: algorithmRegistry,
}, nil
}

Expand Down
68 changes: 68 additions & 0 deletions pkg/api/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ package api
import (
"bytes"
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"errors"
"fmt"
"net/http"
"net/url"
"strings"

"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
"github.com/go-openapi/runtime"
Expand Down Expand Up @@ -177,12 +183,74 @@ func GetLogEntryByIndexHandler(params entries.GetLogEntryByIndexParams) middlewa
return entries.NewGetLogEntryByIndexOK().WithPayload(logEntry)
}

func checkEntryAlgorithms(entry types.EntryImpl) (bool, error) {
verifiers, err := entry.Verifiers()
if err != nil {
return false, fmt.Errorf("getting verifiers: %w", err)
}
// Get artifact hash from entry
artifactHash, err := entry.ArtifactHash()
if err != nil {
return false, fmt.Errorf("getting artifact hash: %w", err)
}
artifactHashAlgorithm := artifactHash[:strings.Index(artifactHash, ":")]
var artifactHashValue crypto.Hash
switch artifactHashAlgorithm {
case "sha256":
artifactHashValue = crypto.SHA256
case "sha384":
artifactHashValue = crypto.SHA384
case "sha512":
artifactHashValue = crypto.SHA512
default:
return false, fmt.Errorf("unsupported artifact hash algorithm %s", artifactHashAlgorithm)
}

// Check if all the verifiers public keys (together with the ArtifactHash)
// are allowed according to the policy
for _, v := range verifiers {
identities, err := v.Identities()
if err != nil {
return false, fmt.Errorf("getting identities: %w", err)
}

for _, identity := range identities {
var publicKey crypto.PublicKey
switch identityCrypto := identity.Crypto.(type) {
case *x509.Certificate:
publicKey = identityCrypto.PublicKey
case *rsa.PublicKey:
publicKey = identityCrypto
case *ecdsa.PublicKey:
publicKey = identityCrypto
case ed25519.PublicKey:
publicKey = identityCrypto
default:
continue
}
if !api.algorithmRegistry.IsAlgorithmPermitted(publicKey, artifactHashValue) {
return false, nil
}
}
}
return true, nil
}

func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middleware.Responder) {
ctx := params.HTTPRequest.Context()
entry, err := types.CreateVersionedEntry(params.ProposedEntry)
if err != nil {
return nil, handleRekorAPIError(params, http.StatusBadRequest, err, fmt.Sprintf(validationError, err))
}

areEntryAlgorithmsAllowed, err := checkEntryAlgorithms(entry)
if err != nil {
return nil, handleRekorAPIError(params, http.StatusBadRequest, err, fmt.Sprintf(validationError, err))
}
if !areEntryAlgorithmsAllowed {
return nil, handleRekorAPIError(params, http.StatusBadRequest, errors.New("entry algorithms are not allowed"), fmt.Sprintf(validationError, "entry algorithms are not allowed"))
}

leaf, err := types.CanonicalizeEntry(ctx, entry)
if err != nil {
if _, ok := (err).(types.ValidationError); ok {
Expand Down

0 comments on commit ee1f9ae

Please sign in to comment.