From ef6cb59ea662626e8d2e71fcf5f2fbb7ac0a3cac Mon Sep 17 00:00:00 2001 From: johnabass Date: Fri, 15 Nov 2024 11:13:00 -0800 Subject: [PATCH] enforce TLS peer certificate presence for trust --- token/claimBuilder.go | 33 +++++++++++++++++++++++++++++++++ token/transport.go | 6 ------ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/token/claimBuilder.go b/token/claimBuilder.go index e7beb58..d6b9a04 100644 --- a/token/claimBuilder.go +++ b/token/claimBuilder.go @@ -17,6 +17,12 @@ import ( kithttp "github.com/go-kit/kit/transport/http" ) +const ( + // ClaimTrust is the name of the trust value within JWT claims issued + // by themis. This claim will be overridden based upon TLS connection state. + ClaimTrust = "trust" +) + var ( ErrRemoteURLRequired = errors.New("A URL for the remote claimer is required") ErrMissingKey = errors.New("A key is required for all claims and metadata values") @@ -172,6 +178,16 @@ func newRemoteClaimBuilder(client xhttpclient.Interface, metadata map[string]int return &remoteClaimBuilder{endpoint: c.Endpoint(), url: r.URL, extra: metadata}, nil } +// enforcePeerCertificate is a ClaimsBuilderFunc that overrides trust as necessary +// given the TLS peer certificates (if any) +func enforcePeerCertificate(_ context.Context, r *Request, target map[string]interface{}) error { + if len(r.ConnectionState.PeerCertificates) == 0 { + target[ClaimTrust] = 0 + } + + return nil +} + // NewClaimBuilders constructs a ClaimBuilders from configuration. The returned instance is typically // used in configuration a token Factory. It can be used as a standalone service component with an endpoint. // @@ -182,6 +198,7 @@ func NewClaimBuilders(n random.Noncer, client xhttpclient.Interface, o Options) builders = ClaimBuilders{requestClaimBuilder{}} staticClaimBuilder = make(staticClaimBuilder) ) + if o.Remote != nil { // scan the metadata looking for static values that should be applied when invoking the remote server metadata := make(map[string]interface{}) for _, value := range o.Metadata { @@ -200,34 +217,44 @@ func NewClaimBuilders(n random.Noncer, client xhttpclient.Interface, o Options) metadata[value.Key] = msg } } + remoteClaimBuilder, err := newRemoteClaimBuilder(client, metadata, o.Remote) if err != nil { return nil, err } + builders = append(builders, remoteClaimBuilder) } + for _, value := range o.Claims { switch { case len(value.Key) == 0: return nil, ErrMissingKey + case value.IsFromHTTP(): continue + case !value.IsStatic(): return nil, fmt.Errorf("A value is required for the static claim: %s", value.Key) + default: msg, err := value.RawMessage() if err != nil { return nil, err } + staticClaimBuilder[value.Key] = msg } } + if len(staticClaimBuilder) > 0 { builders = append(builders, staticClaimBuilder) } + if o.Nonce && n != nil { builders = append(builders, nonceClaimBuilder{n: n}) } + if !o.DisableTime { builders = append( builders, @@ -238,5 +265,11 @@ func NewClaimBuilders(n random.Noncer, client xhttpclient.Interface, o Options) notBeforeDelta: o.NotBeforeDelta, }) } + + builders = append( + builders, + ClaimBuilderFunc(enforcePeerCertificate), + ) + return builders, nil } diff --git a/token/transport.go b/token/transport.go index 76ab8aa..7c8a774 100644 --- a/token/transport.go +++ b/token/transport.go @@ -19,12 +19,6 @@ import ( "go.uber.org/multierr" ) -const ( - // ClaimTrust is the name of the trust value within JWT claims issued - // by themis. - ClaimTrust = "trust" -) - var ( ErrVariableNotAllowed = errors.New("Either header/parameter or variable can specified, but not all three") )