Skip to content

Commit

Permalink
crypto/x509: ModuleV2 migration
Browse files Browse the repository at this point in the history
  • Loading branch information
codebien committed Nov 25, 2021
1 parent 0e85852 commit 1407977
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 40 deletions.
89 changes: 57 additions & 32 deletions js/modules/k6/crypto/x509/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package x509

import (
"context"
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
Expand All @@ -34,10 +33,47 @@ import (
"time"

"go.k6.io/k6/js/common"
"go.k6.io/k6/js/modules"
)

// X509 certificate functionality
type X509 struct{}
type (
// RootModule is the global module instance that will create module
// instances for each VU.
RootModule struct{}

// X509 represents an instance of the X509 certificate module.
X509 struct {
vu modules.VU
}
)

var (
_ modules.Module = &RootModule{}
_ modules.Instance = &X509{}
)

// New returns a pointer to a new RootModule instance.
func New() *RootModule {
return &RootModule{}
}

// NewModuleInstance implements the modules.Module interface to return
// a new instance for each VU.
func (*RootModule) NewModuleInstance(vu modules.VU) modules.Instance {
return &X509{vu: vu}
}

// Exports returns the exports of the execution module.
func (mi *X509) Exports() modules.Exports {
return modules.Exports{
Named: map[string]interface{}{
"parse": mi.parse,
"getAltNames": mi.altNames,
"getIssuer": mi.issuer,
"getSubject": mi.subject,
},
}
}

// Certificate is an X.509 certificate
type Certificate struct {
Expand Down Expand Up @@ -86,61 +122,54 @@ type PublicKey struct {
Key interface{}
}

// New constructs the X509 interface
func New() *X509 {
return &X509{}
}

// Parse produces an entire X.509 certificate
func (X509) Parse(ctx context.Context, encoded []byte) Certificate {
// parse produces an entire X.509 certificate
func (mi X509) parse(encoded []byte) (Certificate, error) {
parsed, err := parseCertificate(encoded)
if err != nil {
throw(ctx, err)
return Certificate{}, err
}
certificate, err := makeCertificate(parsed)
if err != nil {
throw(ctx, err)
return Certificate{}, err
}
return certificate
return certificate, nil
}

// GetAltNames extracts alt names
func (X509) GetAltNames(ctx context.Context, encoded []byte) []string {
// altNames extracts alt names
func (mi X509) altNames(encoded []byte) ([]string, error) {
parsed, err := parseCertificate(encoded)
if err != nil {
throw(ctx, err)
return nil, err
}
return altNames(parsed)
return altNames(parsed), nil
}

// GetIssuer extracts certificate issuer
func (X509) GetIssuer(ctx context.Context, encoded []byte) Issuer {
// issuer extracts certificate issuer
func (mi X509) issuer(encoded []byte) (Issuer, error) {
parsed, err := parseCertificate(encoded)
if err != nil {
throw(ctx, err)
return Issuer{}, err
}
return makeIssuer(parsed.Issuer)
return makeIssuer(parsed.Issuer), nil
}

// GetSubject extracts certificate subject
func (X509) GetSubject(ctx context.Context, encoded []byte) Subject {
// subject extracts certificate subject
func (mi X509) subject(encoded []byte) Subject {
parsed, err := parseCertificate(encoded)
if err != nil {
throw(ctx, err)
common.Throw(mi.vu.Runtime(), err)
}
return makeSubject(parsed.Subject)
}

func parseCertificate(encoded []byte) (*x509.Certificate, error) {
decoded, _ := pem.Decode(encoded)
if decoded == nil {
err := errors.New("failed to decode certificate PEM file")
return nil, err
return nil, fmt.Errorf("failed to decode certificate PEM file")
}
parsed, err := x509.ParseCertificate(decoded.Bytes)
if err != nil {
err = fmt.Errorf("failed to parse certificate: %w", err)
return nil, err
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
return parsed, nil
}
Expand Down Expand Up @@ -268,7 +297,3 @@ func fingerPrint(parsed *x509.Certificate) []byte {
bytes := sha1.Sum(parsed.Raw) // #nosec G401
return bytes[:]
}

func throw(ctx context.Context, err error) {
common.Throw(common.GetRuntime(ctx), err)
}
26 changes: 18 additions & 8 deletions js/modules/k6/crypto/x509/x509_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,26 @@ import (

"github.com/dop251/goja"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.k6.io/k6/js/common"
"go.k6.io/k6/js/modulestest"
)

func makeRuntime() *goja.Runtime {
func makeRuntime(t *testing.T) *goja.Runtime {
rt := goja.New()
rt.SetFieldNameMapper(common.FieldNameMapper{})
ctx := context.Background()
ctx = common.WithRuntime(ctx, rt)
rt.Set("x509", common.Bind(rt, New(), &ctx))
ctx := common.WithRuntime(context.Background(), rt)
m, ok := New().NewModuleInstance(
&modulestest.VU{
RuntimeField: rt,
InitEnvField: &common.InitEnvironment{},
CtxField: ctx,
StateField: nil,
},
).(*X509)
require.True(t, ok)
require.NoError(t, rt.Set("x509", m.Exports().Named))
return rt
}

Expand Down Expand Up @@ -144,7 +154,7 @@ func TestParse(t *testing.T) {
if testing.Short() {
return
}
rt := makeRuntime()
rt := makeRuntime(t)

t.Run("DecodeFailure", func(t *testing.T) {
_, err := rt.RunString(`
Expand Down Expand Up @@ -572,7 +582,7 @@ func TestGetAltNames(t *testing.T) {
if testing.Short() {
return
}
rt := makeRuntime()
rt := makeRuntime(t)

t.Run("Failure", func(t *testing.T) {
_, err := rt.RunString(`
Expand Down Expand Up @@ -606,7 +616,7 @@ func TestGetIssuer(t *testing.T) {
if testing.Short() {
return
}
rt := makeRuntime()
rt := makeRuntime(t)

t.Run("Failure", func(t *testing.T) {
_, err := rt.RunString(`
Expand Down Expand Up @@ -638,7 +648,7 @@ func TestGetSubject(t *testing.T) {
if testing.Short() {
return
}
rt := makeRuntime()
rt := makeRuntime(t)

t.Run("Failure", func(t *testing.T) {
_, err := rt.RunString(`
Expand Down

0 comments on commit 1407977

Please sign in to comment.