Documentation ¶
Index ¶
- Variables
- type CoordinationClientGetter
- type InClusterCoordinationClientGetter
- type JWTIssuer
- func (i *JWTIssuer) DecodeJWEToken(ctx context.Context, tokenString string, claims interface{}, ...) error
- func (i *JWTIssuer) DecodeJWT(ctx context.Context, tokenString string, claims interface{}) error
- func (i *JWTIssuer) EncodeJWEToken(ctx context.Context, claims interface{}, tokenType TokenType) (string, error)
- func (i *JWTIssuer) EncodeJWT(ctx context.Context, claims interface{}) (string, error)
- func (i *JWTIssuer) GetKeyPair(ctx context.Context, name string) (*KeyPair, error)
- func (i *JWTIssuer) GetKeyPairs(ctx context.Context) []*KeyPair
- func (i *JWTIssuer) GetPrimaryKeyName() string
- func (i *JWTIssuer) GetSecondaryKeyName() string
- func (i *JWTIssuer) JWKS(ctx context.Context) (*jose.JSONWebKeySet, error)
- func (i *JWTIssuer) Run(ctx context.Context, coordinationClientGetter CoordinationClientGetter) error
- func (i *JWTIssuer) StartLeading(ctx context.Context)
- func (i *JWTIssuer) StopLeading()
- type KeyPair
- type Options
- type TokenType
Constants ¶
This section is empty.
Variables ¶
var ( // ErrKeyFormat is raised when something is wrong with the // encryption keys. ErrKeyFormat = errors.New("key format error") // ErrTokenVerification is raised when token verification fails. ErrTokenVerification = errors.New("failed to verify token") // ErrMissingKey is raised when a key is missing from a secret. ErrMissingKey = errors.New("failed to lookup key") // ErrContextError is raised when a required value cannot be retrieved // from a context. ErrContextError = errors.New("value missing from context") )
Functions ¶
This section is empty.
Types ¶
type CoordinationClientGetter ¶ added in v0.2.4
type CoordinationClientGetter interface {
Client() (coordinationv1.CoordinationV1Interface, error)
}
type InClusterCoordinationClientGetter ¶ added in v0.2.4
type InClusterCoordinationClientGetter struct{}
func (*InClusterCoordinationClientGetter) Client ¶ added in v0.2.4
func (*InClusterCoordinationClientGetter) Client() (coordinationv1.CoordinationV1Interface, error)
type JWTIssuer ¶
type JWTIssuer struct {
// contains filtered or unexported fields
}
JWTIssuer is in charge of API token issue and verification. It is expected that the keys come from a mounted kubernetes.io/tls secret, and that is managed by cert-manager. As a result the keys will rotate every 60 days (by default), so you MUST ensure they are not cached in perpetuity. Additionally, due to horizontal scale-out these secrets need to be shared between all replicas so that a token issued by one, can be verified by another. As such if you ever do cache the certificate load, it will need to be coordinated between all instances.
func NewJWTIssuer ¶
NewJWTIssuer returns a new JWT issuer and validator.
func (*JWTIssuer) DecodeJWEToken ¶
func (*JWTIssuer) EncodeJWEToken ¶
func (i *JWTIssuer) EncodeJWEToken(ctx context.Context, claims interface{}, tokenType TokenType) (string, error)
EncodeJWEToken encodes, signs and encrypts as set of claims. For access tokens this implemenrs https://datatracker.ietf.org/doc/html/rfc9068
func (*JWTIssuer) GetKeyPair ¶
GetKeyPair returns the public key, private key and key id from the configuration data. The key id is inspired by X.509 subject key identifiers, so a hash over the subject public key info.
func (*JWTIssuer) GetKeyPairs ¶ added in v0.2.4
GetKeyPairs returns all key pairs that exist.
func (*JWTIssuer) GetPrimaryKeyName ¶ added in v0.2.4
func (*JWTIssuer) GetSecondaryKeyName ¶ added in v0.2.4
func (*JWTIssuer) Run ¶ added in v0.2.4
func (i *JWTIssuer) Run(ctx context.Context, coordinationClientGetter CoordinationClientGetter) error
Run starts the certificate management loop. The certificate itself is managed by cert-manager, as a reissue duration of N and a lifetime of 2N. Tokens may be issued for a maximum duration of N. Tokens issued just before the certificates N will be able to be verified until their expiration. Now, to pull this off we need to:
- Keep a primary copy of the current key pair so we can see when it changes. with reference to the master copy managed by cert-manager.
- When it does change, we need to demote the primary copy to the secondary, then update the new primary.
Tokens will always be issued by the current primary, but may be verified by either the primary or secondary.
As identity is hoizontally scalable, we have another pain in the arse that is split brain, so use leadership election to ease the burden.
func (*JWTIssuer) StartLeading ¶ added in v0.2.4
StartLeading does certificate rotation handling. NOTE: there is a startup penalty waiting for the first tick, but on the first invocation it's expected there won't be any traffic immediately anyway.
func (*JWTIssuer) StopLeading ¶ added in v0.2.4
func (i *JWTIssuer) StopLeading()
type KeyPair ¶ added in v0.2.4
type KeyPair struct { Cert *x509.Certificate Key crypto.PrivateKey }
type Options ¶
type TokenType ¶ added in v0.2.4
type TokenType string
TokenType is used to define the specific use of a token.
const ( // TokenTypeAccessToken is defined by RFC9068 to prevent reuse in other contexts. TokenTypeAccessToken TokenType = "at+jwt" // TokenTypeAuthorizationCode is defined by us to prevent reuse in other contexts. //nolint:gosec TokenTypeAuthorizationCode TokenType = "unikorn-cloud.org/authcode+jwt" // TokenTypeLoginState is deinfed by us to prevent reuse in other contexts. //nolint:gosec TokenTypeLoginState TokenType = "unikorn-cloud.org/loginstate+jwt" // TokenTypeRefreshToken is defined to prevent reuse in other contexts. //nolint:gosec TokenTypeRefreshToken TokenType = "unikorn-cloud.org/rt+jwt" )