Open naroraindeed opened 7 months ago
Wanted to add that we distilled our composer plugin to:
func (p *Plugin) ComposeWorkloadJWTSVID(_ context.Context, req *credentialcomposerv1.ComposeWorkloadJWTSVIDRequest) (*credentialcomposerv1.ComposeWorkloadJWTSVIDResponse, error) {
return &credentialcomposerv1.ComposeWorkloadJWTSVIDResponse{
Attributes: req.Attributes,
}, nil
}
and verified the timestamps were still float. The issue is in the implementation of the plugin model. This essentially makes integer claims impossible when using the plugin.
We made some more progress in the investigation. I added custom claims like so:
attributes.Claims["i64"] = math.MaxInt64
attributes.Claims["i32"] = math.MaxInt32
attributes.Claims["i16"] = math.MaxInt16
attributes.Claims["i8"] = math.MaxInt8
and here's the resultant payload:
eyJhdWQiOlsic3RzLmFtYXpvbmF3cy5jb20iXSwiZXhwIjoxLjcxNDA3MjUxN2UrMDksImh0dHBzOi8vYXdzLmFtYXpvbi5jb20vdGFncyI6eyJwcmluY2lwYWxfdGFncyI6eyJEMCI6WyJhYmMiXX0sInRyYW5zaXRpdmVfdGFnX2tleXMiOlsiRDAiXX0sImkxNiI6MzI3NjcsImkzMiI6Mi4xNDc0ODM2NDdlKzA5LCJpNjQiOjkuMjIzMzcyMDM2ODU0Nzc2ZSsxOCwiaTgiOjEyNywiaWF0IjoxLjcxNDA3MDcxN2UrMDksInB1cnBvc2UiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZSI6IkQwOmEgRDA6YiBEMDpjIiwic3ViIjoic3BpZmZlOi8vZXhhbXBsZS5jb20vdGVzdDEifQ
The i8
and i16
claim are formatted as integer only, i32
and i64
are in exponent format. Of course all of these claims are represented asstructpb.Value
. E.g.
But the final serialization preserves integer format for small integers. I'm wondering if we can implement a custom marshaller to revert floats back to integers inside SPIRE when composer plugins are used. Any ideas are appreciated.
I think the long term fix will involve changing the proto definition of Claims: https://github.com/spiffe/spire-plugin-sdk/blob/a2e5ba68e76045c0ca332264af935ea8c3a59f99/proto/spire/plugin/server/credentialcomposer/v1/credentialcomposer.pb.go#L991
Temporarily fixed with:
if len(b.config.CredentialComposers) > 0 {
// reset iat and exp from float64 to jwt.NumericDate type
if iat, ok := attributes.Claims["iat"].(float64); ok {
attributes.Claims["iat"] = int64(iat)
}
if exp, ok := attributes.Claims["exp"].(float64); ok {
attributes.Claims["exp"] = int64(exp)
}
}
right before https://github.com/spiffe/spire/blob/9e23dbe97dc017ab3c24675836026c38c733457d/pkg/server/credtemplate/builder.go#L348
Linux server-1 5.15.0-1053-aws #58~20.04.1-Ubuntu SMP Mon Jan 22 17:15:01 UTC 2024 x86_64 Linux
Problem: Using the composer plugin for modifying JWT-SVIDs yields in timestamp claims like
iat
,exp
etc. to be formatted as typefloat
. While numeric type is valid for timestamps and the the token can be successfully validated using jwt.io, AWS rejects it. I've already reached out to AWS support and they have asked us to fix the issue on our end.Here's a sample spire JWT-SVID payload when not using the composer plugin
Note,
exp
andiat
are integer.Here's a sample spire JWT-SVID payload when using the credential composer plugin (our plugin implementation never modifies those claims)
Note,
exp
andiat
are floats. Still valid JWTs and valid timestamps, but AWS SDK will reject the use of such JWT with:Upon initial investigation is looks like an issue with the proto definition of
Claims
. We believe it’s due to the following representation:Claims *structpb.Struct
The protobuf struct doesn’t support integers and prefers to represent numbers as double.double number_value = 2;
The translations of Claims as protobuf Struct and then further JSON serialization is likely yielding the final format of
float
type.Goal: Stick to integer representation for well known timestamp claims for compatibility with AWS.