Files
kubesphere/vendor/github.com/open-policy-agent/opa/bundle/sign.go
hongzhouzi ef03b1e3df 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>
2022-10-31 10:58:55 +08:00

136 lines
3.6 KiB
Go

// Copyright 2020 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
// Package bundle provide helpers that assist in the creating a signed bundle
package bundle
import (
"crypto/rand"
"encoding/json"
"fmt"
"github.com/open-policy-agent/opa/internal/jwx/jwa"
"github.com/open-policy-agent/opa/internal/jwx/jws"
)
const defaultSignerID = "_default"
var signers map[string]Signer
// Signer is the interface expected for implementations that generate bundle signatures.
type Signer interface {
GenerateSignedToken([]FileInfo, *SigningConfig, string) (string, error)
}
// GenerateSignedToken will retrieve the Signer implementation based on the Plugin specified
// in SigningConfig, and call its implementation of GenerateSignedToken. The signer generates
// a signed token given the list of files to be included in the payload and the bundle
// signing config. The keyID if non-empty, represents the value for the "keyid" claim in the token.
func GenerateSignedToken(files []FileInfo, sc *SigningConfig, keyID string) (string, error) {
var plugin string
// for backwards compatibility, check if there is no plugin specified, and use default
if sc.Plugin == "" {
plugin = defaultSignerID
} else {
plugin = sc.Plugin
}
signer, err := GetSigner(plugin)
if err != nil {
return "", err
}
return signer.GenerateSignedToken(files, sc, keyID)
}
// DefaultSigner is the default bundle signing implementation. It signs bundles by generating
// a JWT and signing it using a locally-accessible private key.
type DefaultSigner struct{}
// GenerateSignedToken generates a signed token given the list of files to be
// included in the payload and the bundle signing config. The keyID if non-empty,
// represents the value for the "keyid" claim in the token
func (*DefaultSigner) GenerateSignedToken(files []FileInfo, sc *SigningConfig, keyID string) (string, error) {
payload, err := generatePayload(files, sc, keyID)
if err != nil {
return "", err
}
privateKey, err := sc.GetPrivateKey()
if err != nil {
return "", err
}
var headers jws.StandardHeaders
if err := headers.Set(jws.AlgorithmKey, jwa.SignatureAlgorithm(sc.Algorithm)); err != nil {
return "", err
}
if keyID != "" {
if err := headers.Set(jws.KeyIDKey, keyID); err != nil {
return "", err
}
}
hdr, err := json.Marshal(headers)
if err != nil {
return "", err
}
token, err := jws.SignLiteral(payload,
jwa.SignatureAlgorithm(sc.Algorithm),
privateKey,
hdr,
rand.Reader)
if err != nil {
return "", err
}
return string(token), nil
}
func generatePayload(files []FileInfo, sc *SigningConfig, keyID string) ([]byte, error) {
payload := make(map[string]interface{})
payload["files"] = files
if sc.ClaimsPath != "" {
claims, err := sc.GetClaims()
if err != nil {
return nil, err
}
for claim, value := range claims {
payload[claim] = value
}
} else {
if keyID != "" {
// keyid claim is deprecated but include it for backwards compatibility.
payload["keyid"] = keyID
}
}
return json.Marshal(payload)
}
// GetSigner returns the Signer registered under the given id
func GetSigner(id string) (Signer, error) {
signer, ok := signers[id]
if !ok {
return nil, fmt.Errorf("no signer exists under id %s", id)
}
return signer, nil
}
// RegisterSigner registers a Signer under the given id
func RegisterSigner(id string, s Signer) error {
if id == defaultSignerID {
return fmt.Errorf("signer id %s is reserved, use a different id", id)
}
signers[id] = s
return nil
}
func init() {
signers = map[string]Signer{
defaultSignerID: &DefaultSigner{},
}
}