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

bundle: Support for handling PEM file containing the public key #2802

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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