Skip to content

Commit

Permalink
bundle: Support for handling PEM file containing the public key
Browse files Browse the repository at this point in the history
The "verification-key" flag used by the `run` and `build` commands
should be able to handle a PEM file containing a public key.
Earlier we were not checking if the value of the flag represents
a file on disk. This change will check if the value points to a
file, then read it contents and set the public key accordingly.

Fixes: #2796

Signed-off-by: Ashutosh Narkar <anarkar4387@gmail.com>
  • Loading branch information
ashutosh-narkar committed Oct 19, 2020
1 parent deb61d0 commit 1562c8e
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 14 deletions.
19 changes: 16 additions & 3 deletions bundle/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,25 @@ type KeyConfig struct {
}

// NewKeyConfig return a new KeyConfig
func NewKeyConfig(key, alg, scope string) *KeyConfig {
func NewKeyConfig(key, alg, scope string) (*KeyConfig, error) {
var pubKey string
if _, err := os.Stat(key); err == nil {
bs, err := ioutil.ReadFile(key)
if err != nil {
return nil, err
}
pubKey = string(bs)
} else if os.IsNotExist(err) {
pubKey = key
} else {
return nil, err
}

return &KeyConfig{
Key: key,
Key: pubKey,
Algorithm: alg,
Scope: scope,
}
}, nil
}

// ParseKeysConfig returns a map containing the public key and the signing algorithm
Expand Down
86 changes: 82 additions & 4 deletions bundle/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package bundle
import (
"crypto/rsa"
"fmt"
"os"
"path/filepath"
"reflect"
"testing"
Expand Down Expand Up @@ -286,6 +287,67 @@ EXrJfkELSzO66/ZSjyyWEczXHLyr+Q719BsaGsxie117zSNF6B6UXiitjCr/qQ==
})
}

func TestNewKeyConfig(t *testing.T) {
publicKey := `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9KaakMv1XKKDaSch3PFR
3a27oaHp1GNTTNqvb1ZaHZXp+wuhYDwc/MTE67x9GCifvQBWzEGorgTq7aisiOyl
vKifwz6/wQ+62WHKG/sqKn2Xikp3P63aBIPlZcHbkyyRmL62yeyuzYoGvLEYel+m
z5SiKGBwviSY0Th2L4e5sGJuk2HOut6emxDi+E2Fuuj5zokFJvIT6Urlq8f3h6+l
GeR6HUOXqoYVf7ff126GP7dticTVBgibxkkuJFmpvQSW6xmxruT4k6iwjzbZHY7P
ypZ/TdlnuGC1cOpAVyU7k32IJ9CRbt3nwEf5U54LRXLLQjFixWZHwKdDiMTF4ws0
+wIDAQAB
-----END PUBLIC KEY-----`

files := map[string]string{
"public.pem": publicKey,
}

test.WithTempFS(files, func(rootDir string) {

kc, err := NewKeyConfig(filepath.Join(rootDir, "public.pem"), "RS256", "read")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

expected := &KeyConfig{
Key: publicKey,
Algorithm: "RS256",
Scope: "read",
}

if !reflect.DeepEqual(kc, expected) {
t.Fatalf("Expected key config %v but got %v", expected, kc)
}

// secret provided on command-line
kc, err = NewKeyConfig(publicKey, "HS256", "")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

expected = &KeyConfig{
Key: publicKey,
Algorithm: "HS256",
Scope: "",
}

if !reflect.DeepEqual(kc, expected) {
t.Fatalf("Expected key config %v but got %v", expected, kc)
}

// simulate error while reading file
err = os.Chmod(filepath.Join(rootDir, "public.pem"), 0111)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

_, err = NewKeyConfig(filepath.Join(rootDir, "public.pem"), "RS256", "read")
if err == nil {
t.Fatal("Expected error but got nil")
}
})
}

func TestGetClaimsErrors(t *testing.T) {
files := map[string]string{
"claims.json": `["foo", "read"]`,
Expand Down Expand Up @@ -320,13 +382,29 @@ func TestKeyConfigEqual(t *testing.T) {
exp bool
}{
"equal": {
NewKeyConfig("foo", "RS256", "read"),
NewKeyConfig("foo", "RS256", "read"),
&KeyConfig{
Key: "foo",
Algorithm: "RS256",
Scope: "read",
},
&KeyConfig{
Key: "foo",
Algorithm: "RS256",
Scope: "read",
},
true,
},
"not_equal": {
NewKeyConfig("foo", "RS256", "read"),
NewKeyConfig("foo", "RS256", "write"),
&KeyConfig{
Key: "foo",
Algorithm: "RS256",
Scope: "read",
},
&KeyConfig{
Key: "foo",
Algorithm: "RS256",
Scope: "write",
},
false,
},
}
Expand Down
19 changes: 13 additions & 6 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,11 @@ func dobuild(params buildParams, args []string) error {
buf := bytes.NewBuffer(nil)

// generate the bundle verification and signing config
bvc := buildVerificationConfig(params.pubKey, params.pubKeyID, params.algorithm, params.scope, params.excludeVerifyFiles)
bvc, err := buildVerificationConfig(params.pubKey, params.pubKeyID, params.algorithm, params.scope, params.excludeVerifyFiles)
if err != nil {
return err
}

bsc := buildSigningConfig(params.key, params.algorithm, params.claimsFile)

if bvc != nil || bsc != nil {
Expand Down Expand Up @@ -275,7 +279,7 @@ func dobuild(params buildParams, args []string) error {
compiler = compiler.WithBundleVerificationKeyID(params.pubKeyID)
}

err := compiler.Build(context.Background())
err = compiler.Build(context.Background())

if params.debug {
printdebug(os.Stderr, compiler.Debug())
Expand Down Expand Up @@ -309,13 +313,16 @@ func buildCommandLoaderFilter(bundleMode bool, ignore []string) func(string, os.
}
}

func buildVerificationConfig(pubKey, pubKeyID, alg, scope string, excludeFiles []string) *bundle.VerificationConfig {
func buildVerificationConfig(pubKey, pubKeyID, alg, scope string, excludeFiles []string) (*bundle.VerificationConfig, error) {
if pubKey == "" {
return nil
return nil, nil
}

keyConfig := bundle.NewKeyConfig(pubKey, alg, scope)
return bundle.NewVerificationConfig(map[string]*bundle.KeyConfig{pubKeyID: keyConfig}, pubKeyID, scope, excludeFiles)
keyConfig, err := bundle.NewKeyConfig(pubKey, alg, scope)
if err != nil {
return nil, err
}
return bundle.NewVerificationConfig(map[string]*bundle.KeyConfig{pubKeyID: keyConfig}, pubKeyID, scope, excludeFiles), nil
}

func buildSigningConfig(key, alg, claimsFile string) *bundle.SigningConfig {
Expand Down
20 changes: 20 additions & 0 deletions cmd/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"os"
"path"
"path/filepath"
"strings"
"testing"

Expand Down Expand Up @@ -117,3 +118,22 @@ func TestBuildErrorVerifyNonBundle(t *testing.T) {
}
})
}

func TestBuildVerificationConfigError(t *testing.T) {
files := map[string]string{
"public.pem": "foo",
}

test.WithTempFS(files, func(rootDir string) {
// simulate error while reading file
err := os.Chmod(filepath.Join(rootDir, "public.pem"), 0111)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

_, err = buildVerificationConfig(filepath.Join(rootDir, "public.pem"), "default", "", "", nil)
if err == nil {
t.Fatal("Expected error but got nil")
}
})
}
6 changes: 5 additions & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,11 @@ func initRuntime(ctx context.Context, params runCmdParams, args []string) (*runt

params.rt.SkipBundleVerification = params.skipBundleVerify

params.rt.BundleVerificationConfig = buildVerificationConfig(params.pubKey, params.pubKeyID, params.algorithm, params.scope, params.excludeVerifyFiles)
bvc, err := buildVerificationConfig(params.pubKey, params.pubKeyID, params.algorithm, params.scope, params.excludeVerifyFiles)
if err != nil {
return nil, err
}
params.rt.BundleVerificationConfig = bvc

if params.rt.BundleVerificationConfig != nil && !params.rt.BundleMode {
return nil, fmt.Errorf("enable bundle mode (ie. --bundle) to verify bundle files or directories")
Expand Down

0 comments on commit 1562c8e

Please sign in to comment.