mirror of
https://github.com/hanzozt/x509-claims.git
synced 2026-10-30 20:36:36 +00:00
120 lines
4.0 KiB
Go
120 lines
4.0 KiB
Go
// Package x509claims provides declaration based configuration for retrieving string claims from a x509 certificate.
|
|
// This package does not attempt to verify the signature or chains of trust associated with a certificate as that is
|
|
// a solved problem. It is expected, that any claims retrieved with this package are being done so on certificates
|
|
// that have already been verified as "trusted".
|
|
//
|
|
// Package x509claims provides an interface framework that is meant to be extended with project specific claims
|
|
// needs. Out of the box it supports Locator -> Matcher -> Parser (LMP) Definition (DefinitionLMP). Users can either add
|
|
// their own Definition with their own conventions or add custom Locator, Matcher, and/or Parser implementations to plug
|
|
// into the existing DefinitionLMP. They can even implement their own Provider with its own rules if necessary.
|
|
//
|
|
// The following example show how to add a DefinitionLMP that will parse out any SPIFFE ID from a x509.Certificate
|
|
// SVID. As a note, the current SPIFFE spec allows only 1 SPIFFE ID per SVID. This example would return ALL
|
|
// URI SANs wit the scheme `spiffe`. It would be up the implementor to only use the first value per the SPIFFE spec.
|
|
//
|
|
// Example:
|
|
// ```
|
|
//
|
|
// provider := ProviderBasic{
|
|
// Definitions: []Definition{
|
|
// &DefinitionLMP[*url.URL]{
|
|
// Locator: &LocatorSanUri{},
|
|
// Matcher: &MatcherScheme{Scheme: "spiffe"},
|
|
// Parser: &ParserNoOp{},
|
|
// },
|
|
// },
|
|
// }
|
|
//
|
|
// ```
|
|
//
|
|
// The following example returns SPIFFE IDs as well as email claims from an email SAN:
|
|
// Example:
|
|
// ```
|
|
//
|
|
// provider := ProviderBasic{
|
|
// Definitions: []Definition{
|
|
// &DefinitionLMP[*url.URL]{
|
|
// Locator: &LocatorSanUri{},
|
|
// Matcher: &MatcherScheme{Scheme: "spiffe"},
|
|
// Parser: &ParserNoOp{},
|
|
// },
|
|
// },
|
|
// &DefinitionLMP[string]{
|
|
// Locator: &LocatorSanEmail{},
|
|
// Matcher: &MatcherSuffix{Suffix: "@my.domain.dev"},
|
|
// Parser: &ParserSplit{Separator: "."},
|
|
// },
|
|
// }
|
|
//
|
|
// ```
|
|
package x509claims
|
|
|
|
import (
|
|
"crypto/x509"
|
|
)
|
|
|
|
// Provider is the top level interface. When Claims() is invoked on a
|
|
// given x509.Certificate it should return an array of string claims.
|
|
type Provider interface {
|
|
Claims(cert *x509.Certificate) []string
|
|
}
|
|
|
|
// ProviderBasic is a default implementation of Provider. It holds all the claims
|
|
// definitions that should be used to return string claims via Claims() by invoking
|
|
// Definition.Claims().
|
|
type ProviderBasic struct {
|
|
Definitions []Definition
|
|
}
|
|
|
|
// Claims returns a string array of claims that have been retrieved
|
|
// from a certificate based upon the ProviderBasic's definitions.
|
|
func (c *ProviderBasic) Claims(cert *x509.Certificate) []string {
|
|
var result []string
|
|
|
|
if c == nil || cert == nil {
|
|
return result
|
|
}
|
|
|
|
for _, def := range c.Definitions {
|
|
if def != nil {
|
|
result = append(result, def.Claims(cert)...)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Definition implementors should be able to return an array string claims
|
|
// based on a given x509.Certificate. `x509-claims` comes with one
|
|
// implementation of this interface: DefinitionLMP.
|
|
type Definition interface {
|
|
Claims(cert *x509.Certificate) []string
|
|
}
|
|
|
|
// DefinitionLMP implements Definition and allows for assembly of a Locator,
|
|
// Matcher, and Parser (LMP). The Locator retrieves data structures of type `M`.
|
|
// Those data structures are fed into a Matcher which matches and modifies
|
|
// those structures (i.e. to remove non-claims values like sentinel values).
|
|
// Finally, the locator values are converted into strings that are passed to a
|
|
// Parser to convert a single string to multiple string claims.
|
|
type DefinitionLMP[M any] struct {
|
|
Locator Locator[M]
|
|
Matcher Matcher[M]
|
|
Parser Parser
|
|
}
|
|
|
|
// Claims invokes the definitions Locator and Matcher to produce an array
|
|
// of string values that can be parsed into claims.
|
|
func (d *DefinitionLMP[M]) Claims(cert *x509.Certificate) []string {
|
|
var result []string
|
|
|
|
if d == nil {
|
|
return result
|
|
}
|
|
|
|
for _, value := range d.Locator.Locate(cert, d.Matcher) {
|
|
result = append(result, d.Parser.Parse(value)...)
|
|
}
|
|
|
|
return result
|
|
}
|