Upgrade dependent version: github.com/open-policy-agent/opa (#5315)

Upgrade dependent version: github.com/open-policy-agent/opa v0.18.0 -> v0.45.0

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-10-31 10:58:55 +08:00
committed by GitHub
parent 668fca1773
commit ef03b1e3df
363 changed files with 277341 additions and 13544 deletions

View File

@@ -0,0 +1,120 @@
package jwk
import (
"crypto/ecdsa"
"crypto/elliptic"
"errors"
"fmt"
"math/big"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
func newECDSAPublicKey(key *ecdsa.PublicKey) (*ECDSAPublicKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.EC)
if err != nil {
return nil, fmt.Errorf("failed to set Key Type: %w", err)
}
return &ECDSAPublicKey{
StandardHeaders: &hdr,
key: key,
}, nil
}
func newECDSAPrivateKey(key *ecdsa.PrivateKey) (*ECDSAPrivateKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.EC)
if err != nil {
return nil, fmt.Errorf("failed to set Key Type: %w", err)
}
return &ECDSAPrivateKey{
StandardHeaders: &hdr,
key: key,
}, nil
}
// Materialize returns the EC-DSA public key represented by this JWK
func (k ECDSAPublicKey) Materialize() (interface{}, error) {
return k.key, nil
}
// Materialize returns the EC-DSA private key represented by this JWK
func (k ECDSAPrivateKey) Materialize() (interface{}, error) {
return k.key, nil
}
// GenerateKey creates a ECDSAPublicKey from JWK format
func (k *ECDSAPublicKey) GenerateKey(keyJSON *RawKeyJSON) error {
var x, y big.Int
if keyJSON.X == nil || keyJSON.Y == nil || keyJSON.Crv == "" {
return errors.New("missing mandatory key parameters X, Y or Crv")
}
x.SetBytes(keyJSON.X.Bytes())
y.SetBytes(keyJSON.Y.Bytes())
var curve elliptic.Curve
switch keyJSON.Crv {
case jwa.P256:
curve = elliptic.P256()
case jwa.P384:
curve = elliptic.P384()
case jwa.P521:
curve = elliptic.P521()
default:
return fmt.Errorf("invalid curve name %s", keyJSON.Crv)
}
*k = ECDSAPublicKey{
StandardHeaders: &keyJSON.StandardHeaders,
key: &ecdsa.PublicKey{
Curve: curve,
X: &x,
Y: &y,
},
}
return nil
}
// GenerateKey creates a ECDSAPrivateKey from JWK format
func (k *ECDSAPrivateKey) GenerateKey(keyJSON *RawKeyJSON) error {
if keyJSON.D == nil {
return errors.New("missing mandatory key parameter D")
}
eCDSAPublicKey := &ECDSAPublicKey{}
err := eCDSAPublicKey.GenerateKey(keyJSON)
if err != nil {
return fmt.Errorf("failed to generate public key: %w", err)
}
dBytes := keyJSON.D.Bytes()
// The length of this octet string MUST be ceiling(log-base-2(n)/8)
// octets (where n is the order of the curve). This is because the private
// key d must be in the interval [1, n-1] so the bitlength of d should be
// no larger than the bitlength of n-1. The easiest way to find the octet
// length is to take bitlength(n-1), add 7 to force a carry, and shift this
// bit sequence right by 3, which is essentially dividing by 8 and adding
// 1 if there is any remainder. Thus, the private key value d should be
// output to (bitlength(n-1)+7)>>3 octets.
n := eCDSAPublicKey.key.Params().N
octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3
if octetLength-len(dBytes) != 0 {
return errors.New("failed to generate private key. Incorrect D value")
}
privateKey := &ecdsa.PrivateKey{
PublicKey: *eCDSAPublicKey.key,
D: (&big.Int{}).SetBytes(keyJSON.D.Bytes()),
}
k.key = privateKey
k.StandardHeaders = &keyJSON.StandardHeaders
return nil
}

View File

@@ -0,0 +1,178 @@
package jwk
import (
"fmt"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
// Convenience constants for common JWK parameters
const (
AlgorithmKey = "alg"
KeyIDKey = "kid"
KeyOpsKey = "key_ops"
KeyTypeKey = "kty"
KeyUsageKey = "use"
PrivateParamsKey = "privateParams"
)
// Headers provides a common interface to all future possible headers
type Headers interface {
Get(string) (interface{}, bool)
Set(string, interface{}) error
Walk(func(string, interface{}) error) error
GetAlgorithm() jwa.SignatureAlgorithm
GetKeyID() string
GetKeyOps() KeyOperationList
GetKeyType() jwa.KeyType
GetKeyUsage() string
GetPrivateParams() map[string]interface{}
}
// StandardHeaders stores the common JWK parameters
type StandardHeaders struct {
Algorithm *jwa.SignatureAlgorithm `json:"alg,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.4
KeyID string `json:"kid,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.4
KeyOps KeyOperationList `json:"key_ops,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.3
KeyType jwa.KeyType `json:"kty,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.1
KeyUsage string `json:"use,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.2
PrivateParams map[string]interface{} `json:"privateParams,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.4
}
// GetAlgorithm is a convenience function to retrieve the corresponding value stored in the StandardHeaders
func (h *StandardHeaders) GetAlgorithm() jwa.SignatureAlgorithm {
if v := h.Algorithm; v != nil {
return *v
}
return jwa.NoValue
}
// GetKeyID is a convenience function to retrieve the corresponding value stored in the StandardHeaders
func (h *StandardHeaders) GetKeyID() string {
return h.KeyID
}
// GetKeyOps is a convenience function to retrieve the corresponding value stored in the StandardHeaders
func (h *StandardHeaders) GetKeyOps() KeyOperationList {
return h.KeyOps
}
// GetKeyType is a convenience function to retrieve the corresponding value stored in the StandardHeaders
func (h *StandardHeaders) GetKeyType() jwa.KeyType {
return h.KeyType
}
// GetKeyUsage is a convenience function to retrieve the corresponding value stored in the StandardHeaders
func (h *StandardHeaders) GetKeyUsage() string {
return h.KeyUsage
}
// GetPrivateParams is a convenience function to retrieve the corresponding value stored in the StandardHeaders
func (h *StandardHeaders) GetPrivateParams() map[string]interface{} {
return h.PrivateParams
}
// Get is a general getter function for JWK StandardHeaders structure
func (h *StandardHeaders) Get(name string) (interface{}, bool) {
switch name {
case AlgorithmKey:
alg := h.GetAlgorithm()
if alg != jwa.NoValue {
return alg, true
}
return nil, false
case KeyIDKey:
v := h.KeyID
if v == "" {
return nil, false
}
return v, true
case KeyOpsKey:
v := h.KeyOps
if v == nil {
return nil, false
}
return v, true
case KeyTypeKey:
v := h.KeyType
if v == jwa.InvalidKeyType {
return nil, false
}
return v, true
case KeyUsageKey:
v := h.KeyUsage
if v == "" {
return nil, false
}
return v, true
case PrivateParamsKey:
v := h.PrivateParams
if len(v) == 0 {
return nil, false
}
return v, true
default:
return nil, false
}
}
// Set is a general getter function for JWK StandardHeaders structure
func (h *StandardHeaders) Set(name string, value interface{}) error {
switch name {
case AlgorithmKey:
var acceptor jwa.SignatureAlgorithm
if err := acceptor.Accept(value); err != nil {
return fmt.Errorf("invalid value for %s key: %w", AlgorithmKey, err)
}
h.Algorithm = &acceptor
return nil
case KeyIDKey:
if v, ok := value.(string); ok {
h.KeyID = v
return nil
}
return fmt.Errorf("invalid value for %s key: %T", KeyIDKey, value)
case KeyOpsKey:
if err := h.KeyOps.Accept(value); err != nil {
return fmt.Errorf("invalid value for %s key: %w", KeyOpsKey, err)
}
return nil
case KeyTypeKey:
if err := h.KeyType.Accept(value); err != nil {
return fmt.Errorf("invalid value for %s key: %w", KeyTypeKey, err)
}
return nil
case KeyUsageKey:
if v, ok := value.(string); ok {
h.KeyUsage = v
return nil
}
return fmt.Errorf("invalid value for %s key: %T", KeyUsageKey, value)
case PrivateParamsKey:
if v, ok := value.(map[string]interface{}); ok {
h.PrivateParams = v
return nil
}
return fmt.Errorf("invalid value for %s key: %T", PrivateParamsKey, value)
default:
return fmt.Errorf("invalid key: %s", name)
}
}
// Walk iterates over all JWK standard headers fields while applying a function to its value.
func (h StandardHeaders) Walk(f func(string, interface{}) error) error {
for _, key := range []string{AlgorithmKey, KeyIDKey, KeyOpsKey, KeyTypeKey, KeyUsageKey, PrivateParamsKey} {
if v, ok := h.Get(key); ok {
if err := f(key, v); err != nil {
return fmt.Errorf("walk function returned error for %s: %w", key, err)
}
}
}
for k, v := range h.PrivateParams {
if err := f(k, v); err != nil {
return fmt.Errorf("walk function returned error for %s: %w", k, err)
}
}
return nil
}

View File

@@ -0,0 +1,71 @@
package jwk
import (
"crypto/ecdsa"
"crypto/rsa"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
// Set is a convenience struct to allow generating and parsing
// JWK sets as opposed to single JWKs
type Set struct {
Keys []Key `json:"keys"`
}
// Key defines the minimal interface for each of the
// key types. Their use and implementation differ significantly
// between each key types, so you should use type assertions
// to perform more specific tasks with each key
type Key interface {
Headers
// Materialize creates the corresponding key. For example,
// RSA types would create *rsa.PublicKey or *rsa.PrivateKey,
// EC types would create *ecdsa.PublicKey or *ecdsa.PrivateKey,
// and OctetSeq types create a []byte key.
Materialize() (interface{}, error)
GenerateKey(*RawKeyJSON) error
}
// RawKeyJSON is generic type that represents any kind JWK
type RawKeyJSON struct {
StandardHeaders
jwa.AlgorithmParameters
}
// RawKeySetJSON is generic type that represents a JWK Set
type RawKeySetJSON struct {
Keys []RawKeyJSON `json:"keys"`
}
// RSAPublicKey is a type of JWK generated from RSA public keys
type RSAPublicKey struct {
*StandardHeaders
key *rsa.PublicKey
}
// RSAPrivateKey is a type of JWK generated from RSA private keys
type RSAPrivateKey struct {
*StandardHeaders
*jwa.AlgorithmParameters
key *rsa.PrivateKey
}
// SymmetricKey is a type of JWK generated from symmetric keys
type SymmetricKey struct {
*StandardHeaders
key []byte
}
// ECDSAPublicKey is a type of JWK generated from ECDSA public keys
type ECDSAPublicKey struct {
*StandardHeaders
key *ecdsa.PublicKey
}
// ECDSAPrivateKey is a type of JWK generated from ECDH-ES private keys
type ECDSAPrivateKey struct {
*StandardHeaders
key *ecdsa.PrivateKey
}

View File

@@ -0,0 +1,153 @@
// Package jwk implements JWK as described in https://tools.ietf.org/html/rfc7517
package jwk
import (
"crypto/ecdsa"
"crypto/rsa"
"encoding/json"
"errors"
"fmt"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
// GetPublicKey returns the public key based on the private key type.
// For rsa key types *rsa.PublicKey is returned; for ecdsa key types *ecdsa.PublicKey;
// for byte slice (raw) keys, the key itself is returned. If the corresponding
// public key cannot be deduced, an error is returned
func GetPublicKey(key interface{}) (interface{}, error) {
if key == nil {
return nil, errors.New("jwk.New requires a non-nil key")
}
switch v := key.(type) {
// Mental note: although Public() is defined in both types,
// you can not coalesce the clauses for rsa.PrivateKey and
// ecdsa.PrivateKey, as then `v` becomes interface{}
// b/c the compiler cannot deduce the exact type.
case *rsa.PrivateKey:
return v.Public(), nil
case *ecdsa.PrivateKey:
return v.Public(), nil
case []byte:
return v, nil
default:
return nil, fmt.Errorf("invalid key type %T", key)
}
}
// GetKeyTypeFromKey creates a jwk.Key from the given key.
func GetKeyTypeFromKey(key interface{}) jwa.KeyType {
switch key.(type) {
case *rsa.PrivateKey, *rsa.PublicKey:
return jwa.RSA
case *ecdsa.PrivateKey, *ecdsa.PublicKey:
return jwa.EC
case []byte:
return jwa.OctetSeq
default:
return jwa.InvalidKeyType
}
}
// New creates a jwk.Key from the given key.
func New(key interface{}) (Key, error) {
if key == nil {
return nil, errors.New("jwk.New requires a non-nil key")
}
switch v := key.(type) {
case *rsa.PrivateKey:
return newRSAPrivateKey(v)
case *rsa.PublicKey:
return newRSAPublicKey(v)
case *ecdsa.PrivateKey:
return newECDSAPrivateKey(v)
case *ecdsa.PublicKey:
return newECDSAPublicKey(v)
case []byte:
return newSymmetricKey(v)
default:
return nil, fmt.Errorf("invalid key type %T", key)
}
}
func parse(jwkSrc string) (*Set, error) {
var jwkKeySet Set
var jwkKey Key
rawKeySetJSON := &RawKeySetJSON{}
err := json.Unmarshal([]byte(jwkSrc), rawKeySetJSON)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal JWK Set: %w", err)
}
if len(rawKeySetJSON.Keys) == 0 {
// It might be a single key
rawKeyJSON := &RawKeyJSON{}
err := json.Unmarshal([]byte(jwkSrc), rawKeyJSON)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal JWK: %w", err)
}
jwkKey, err = rawKeyJSON.GenerateKey()
if err != nil {
return nil, fmt.Errorf("failed to generate key: %w", err)
}
// Add to set
jwkKeySet.Keys = append(jwkKeySet.Keys, jwkKey)
} else {
for i := range rawKeySetJSON.Keys {
rawKeyJSON := rawKeySetJSON.Keys[i]
if rawKeyJSON.Algorithm != nil && *rawKeyJSON.Algorithm == jwa.Unsupported {
continue
}
jwkKey, err = rawKeyJSON.GenerateKey()
if err != nil {
return nil, fmt.Errorf("failed to generate key: %w", err)
}
jwkKeySet.Keys = append(jwkKeySet.Keys, jwkKey)
}
}
return &jwkKeySet, nil
}
// ParseBytes parses JWK from the incoming byte buffer.
func ParseBytes(buf []byte) (*Set, error) {
return parse(string(buf[:]))
}
// ParseString parses JWK from the incoming string.
func ParseString(s string) (*Set, error) {
return parse(s)
}
// GenerateKey creates an internal representation of a key from a raw JWK JSON
func (r *RawKeyJSON) GenerateKey() (Key, error) {
var key Key
switch r.KeyType {
case jwa.RSA:
if r.D != nil {
key = &RSAPrivateKey{}
} else {
key = &RSAPublicKey{}
}
case jwa.EC:
if r.D != nil {
key = &ECDSAPrivateKey{}
} else {
key = &ECDSAPublicKey{}
}
case jwa.OctetSeq:
key = &SymmetricKey{}
default:
return nil, errors.New("unrecognized key type")
}
err := key.GenerateKey(r)
if err != nil {
return nil, fmt.Errorf("failed to generate key from JWK: %w", err)
}
return key, nil
}

View File

@@ -0,0 +1,68 @@
package jwk
import (
"encoding/json"
"fmt"
"github.com/pkg/errors"
)
// KeyUsageType is used to denote what this key should be used for
type KeyUsageType string
const (
// ForSignature is the value used in the headers to indicate that
// this key should be used for signatures
ForSignature KeyUsageType = "sig"
// ForEncryption is the value used in the headers to indicate that
// this key should be used for encryptiong
ForEncryption KeyUsageType = "enc"
)
// KeyOperation is used to denote the allowed operations for a Key
type KeyOperation string
// KeyOperationList represents an slice of KeyOperation
type KeyOperationList []KeyOperation
var keyOps = map[string]struct{}{"sign": {}, "verify": {}, "encrypt": {}, "decrypt": {}, "wrapKey": {}, "unwrapKey": {}, "deriveKey": {}, "deriveBits": {}}
// KeyOperation constants
const (
KeyOpSign KeyOperation = "sign" // (compute digital signature or MAC)
KeyOpVerify KeyOperation = "verify" // (verify digital signature or MAC)
KeyOpEncrypt KeyOperation = "encrypt" // (encrypt content)
KeyOpDecrypt KeyOperation = "decrypt" // (decrypt content and validate decryption, if applicable)
KeyOpWrapKey KeyOperation = "wrapKey" // (encrypt key)
KeyOpUnwrapKey KeyOperation = "unwrapKey" // (decrypt key and validate decryption, if applicable)
KeyOpDeriveKey KeyOperation = "deriveKey" // (derive key)
KeyOpDeriveBits KeyOperation = "deriveBits" // (derive bits not to be used as a key)
)
// Accept determines if Key Operation is valid
func (keyOperationList *KeyOperationList) Accept(v interface{}) error {
switch x := v.(type) {
case KeyOperationList:
*keyOperationList = x
return nil
default:
return errors.Errorf(`invalid value %T`, v)
}
}
// UnmarshalJSON unmarshals and checks data as KeyType Algorithm
func (keyOperationList *KeyOperationList) UnmarshalJSON(data []byte) error {
var tempKeyOperationList []string
err := json.Unmarshal(data, &tempKeyOperationList)
if err != nil {
return fmt.Errorf("invalid key operation")
}
for _, value := range tempKeyOperationList {
_, ok := keyOps[value]
if !ok {
return fmt.Errorf("unknown key operation")
}
*keyOperationList = append(*keyOperationList, KeyOperation(value))
}
return nil
}

View File

@@ -0,0 +1,133 @@
package jwk
import (
"crypto/rsa"
"encoding/binary"
"errors"
"fmt"
"math/big"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
func newRSAPublicKey(key *rsa.PublicKey) (*RSAPublicKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.RSA)
if err != nil {
return nil, fmt.Errorf("failed to set Key Type: %w", err)
}
return &RSAPublicKey{
StandardHeaders: &hdr,
key: key,
}, nil
}
func newRSAPrivateKey(key *rsa.PrivateKey) (*RSAPrivateKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.RSA)
if err != nil {
return nil, fmt.Errorf("failed to set Key Type: %w", err)
}
var algoParams jwa.AlgorithmParameters
// it is needed to use raw encoding to omit the "=" paddings at the end
algoParams.D = key.D.Bytes()
algoParams.P = key.Primes[0].Bytes()
algoParams.Q = key.Primes[1].Bytes()
algoParams.Dp = key.Precomputed.Dp.Bytes()
algoParams.Dq = key.Precomputed.Dq.Bytes()
algoParams.Qi = key.Precomputed.Qinv.Bytes()
// "modulus" (N) from the public key in the private key
algoParams.N = key.PublicKey.N.Bytes()
// make the E a.k.a "coprime"
// https://en.wikipedia.org/wiki/RSA_(cryptosystem)
coprime := make([]byte, 8)
binary.BigEndian.PutUint64(coprime, uint64(key.PublicKey.E))
// find the 1st index of non 0x0 paddings from the beginning
i := 0
for ; i < len(coprime); i++ {
if coprime[i] != 0x0 {
break
}
}
algoParams.E = coprime[i:]
return &RSAPrivateKey{
StandardHeaders: &hdr,
AlgorithmParameters: &algoParams,
key: key,
}, nil
}
// Materialize returns the standard RSA Public Key representation stored in the internal representation
func (k *RSAPublicKey) Materialize() (interface{}, error) {
if k.key == nil {
return nil, errors.New("key has no rsa.PublicKey associated with it")
}
return k.key, nil
}
// Materialize returns the standard RSA Private Key representation stored in the internal representation
func (k *RSAPrivateKey) Materialize() (interface{}, error) {
if k.key == nil {
return nil, errors.New("key has no rsa.PrivateKey associated with it")
}
return k.key, nil
}
// GenerateKey creates a RSAPublicKey from a RawKeyJSON
func (k *RSAPublicKey) GenerateKey(keyJSON *RawKeyJSON) error {
if keyJSON.N == nil || keyJSON.E == nil {
return errors.New("missing mandatory key parameters N or E")
}
rsaPublicKey := &rsa.PublicKey{
N: (&big.Int{}).SetBytes(keyJSON.N.Bytes()),
E: int((&big.Int{}).SetBytes(keyJSON.E.Bytes()).Int64()),
}
k.key = rsaPublicKey
k.StandardHeaders = &keyJSON.StandardHeaders
return nil
}
// GenerateKey creates a RSAPublicKey from a RawKeyJSON
func (k *RSAPrivateKey) GenerateKey(keyJSON *RawKeyJSON) error {
rsaPublicKey := &RSAPublicKey{}
err := rsaPublicKey.GenerateKey(keyJSON)
if err != nil {
return fmt.Errorf("failed to generate public key: %w", err)
}
if keyJSON.D == nil || keyJSON.P == nil || keyJSON.Q == nil {
return errors.New("missing mandatory key parameters D, P or Q")
}
privateKey := &rsa.PrivateKey{
PublicKey: *rsaPublicKey.key,
D: (&big.Int{}).SetBytes(keyJSON.D.Bytes()),
Primes: []*big.Int{
(&big.Int{}).SetBytes(keyJSON.P.Bytes()),
(&big.Int{}).SetBytes(keyJSON.Q.Bytes()),
},
}
if keyJSON.Dp.Len() > 0 {
privateKey.Precomputed.Dp = (&big.Int{}).SetBytes(keyJSON.Dp.Bytes())
}
if keyJSON.Dq.Len() > 0 {
privateKey.Precomputed.Dq = (&big.Int{}).SetBytes(keyJSON.Dq.Bytes())
}
if keyJSON.Qi.Len() > 0 {
privateKey.Precomputed.Qinv = (&big.Int{}).SetBytes(keyJSON.Qi.Bytes())
}
k.key = privateKey
k.StandardHeaders = &keyJSON.StandardHeaders
k.AlgorithmParameters = &keyJSON.AlgorithmParameters
return nil
}

View File

@@ -0,0 +1,41 @@
package jwk
import (
"fmt"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
)
func newSymmetricKey(key []byte) (*SymmetricKey, error) {
var hdr StandardHeaders
err := hdr.Set(KeyTypeKey, jwa.OctetSeq)
if err != nil {
return nil, fmt.Errorf("failed to set Key Type: %w", err)
}
return &SymmetricKey{
StandardHeaders: &hdr,
key: key,
}, nil
}
// Materialize returns the octets for this symmetric key.
// Since this is a symmetric key, this just calls Octets
func (s SymmetricKey) Materialize() (interface{}, error) {
return s.Octets(), nil
}
// Octets returns the octets in the key
func (s SymmetricKey) Octets() []byte {
return s.key
}
// GenerateKey creates a Symmetric key from a RawKeyJSON
func (s *SymmetricKey) GenerateKey(keyJSON *RawKeyJSON) error {
*s = SymmetricKey{
StandardHeaders: &keyJSON.StandardHeaders,
key: keyJSON.K,
}
return nil
}