Skip to content

Commit

Permalink
BuildWorkloadJWTSVIDClaims fix for real credential composer implement…
Browse files Browse the repository at this point in the history
…ation (#4489)

BuildWorkloadJWTSVIDClaims fix for real credential composer implementation

Signed-off-by: Monis Khan <i@monis.app>
  • Loading branch information
enj authored Sep 22, 2023
1 parent 54fc60c commit dcd1c90
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
51 changes: 51 additions & 0 deletions pkg/server/credtemplate/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import (
"time"

"github.com/spiffe/go-spiffe/v2/spiffeid"
credentialcomposerv1 "github.com/spiffe/spire-plugin-sdk/proto/spire/plugin/server/credentialcomposer/v1"
"github.com/spiffe/spire/pkg/common/catalog"
"github.com/spiffe/spire/pkg/common/x509svid"
"github.com/spiffe/spire/pkg/common/x509util"
"github.com/spiffe/spire/pkg/server/credtemplate"
"github.com/spiffe/spire/pkg/server/plugin/credentialcomposer"
"github.com/spiffe/spire/test/clock"
"github.com/spiffe/spire/test/plugintest"
"github.com/spiffe/spire/test/testkey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -185,6 +187,12 @@ func TestBuildSelfSignedX509CATemplate(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -283,6 +291,12 @@ func TestBuildUpstreamSignedX509CACSR(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -410,6 +424,12 @@ func TestBuildDownstreamX509CATemplate(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -541,6 +561,12 @@ func TestBuildServerX509SVIDTemplate(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -700,6 +726,12 @@ func TestBuildAgentX509SVIDTemplate(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -923,6 +955,12 @@ func TestBuildWorkloadX509SVIDTemplate(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -1089,6 +1127,12 @@ func TestBuildWorkloadJWTSVIDClaims(t *testing.T) {
},
expectErr: "oh no",
},
{
desc: "real no-op composer",
overrideConfig: func(config *credtemplate.Config) {
config.CredentialComposers = []credentialcomposer.CredentialComposer{loadNoopV1Plugin(t)}
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
testBuilder(t, tc.overrideConfig, func(t *testing.T, credBuilder *credtemplate.Builder) {
Expand Down Expand Up @@ -1218,3 +1262,10 @@ func makeOID(id byte) []int {
func idURIs(id spiffeid.ID) []*url.URL {
return []*url.URL{id.URL()}
}

func loadNoopV1Plugin(t *testing.T) credentialcomposer.CredentialComposer {
server := credentialcomposerv1.CredentialComposerPluginServer(credentialcomposerv1.UnimplementedCredentialComposerServer{})
cc := new(credentialcomposer.V1)
plugintest.Load(t, catalog.MakeBuiltIn("noop", server), cc)
return cc
}
8 changes: 7 additions & 1 deletion pkg/server/plugin/credentialcomposer/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/json"
"errors"
"fmt"
"strconv"
Expand Down Expand Up @@ -221,8 +222,13 @@ func jwtSVIDAttributesToV1(attributes JWTSVIDAttributes) (*credentialcomposerv1.
if len(attributes.Claims) == 0 {
return nil, errors.New("invalid claims: cannot be empty")
}
claims, err := structpb.NewStruct(attributes.Claims)
// structpb.NewValue cannot handle Go types such as jwt.NumericDate so we marshal them into their JSON representation first
jsonClaims, err := json.Marshal(attributes.Claims)
if err != nil {
return nil, fmt.Errorf("failed to marshal claims: %w", err)
}
claims := &structpb.Struct{}
if err := claims.UnmarshalJSON(jsonClaims); err != nil {
return nil, fmt.Errorf("failed to encode claims: %w", err)
}
return &credentialcomposerv1.JWTSVIDAttributes{
Expand Down

0 comments on commit dcd1c90

Please sign in to comment.