mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
Expose the constants in pkg/controller/bootstrap and add a validate token method
This commit is contained in:
parent
8db5ca1fbb
commit
4940c32c39
@ -45,4 +45,13 @@ const (
|
||||
// sign configs as part of the bootstrap process. Value must be "true". Any
|
||||
// other value is assumed to be false. Optional.
|
||||
BootstrapTokenUsageSigningKey = "usage-bootstrap-signing"
|
||||
|
||||
// ConfigMapClusterInfo defines the name for the ConfigMap where the information how to connect and trust the cluster exist
|
||||
ConfigMapClusterInfo = "cluster-info"
|
||||
|
||||
// KubeConfigKey defines at which key in the Data object of the ConfigMap the KubeConfig object is stored
|
||||
KubeConfigKey = "kubeconfig"
|
||||
|
||||
// JWSSignatureKeyPrefix defines what key prefix the JWS-signed tokens have
|
||||
JWSSignatureKeyPrefix = "jws-kubeconfig-"
|
||||
)
|
||||
|
@ -38,12 +38,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
configMapClusterInfo = "cluster-info"
|
||||
kubeConfigKey = "kubeconfig"
|
||||
signaturePrefix = "jws-kubeconfig-"
|
||||
)
|
||||
|
||||
// BootstrapSignerOptions contains options for the BootstrapSigner
|
||||
type BootstrapSignerOptions struct {
|
||||
|
||||
@ -70,7 +64,7 @@ type BootstrapSignerOptions struct {
|
||||
func DefaultBootstrapSignerOptions() BootstrapSignerOptions {
|
||||
return BootstrapSignerOptions{
|
||||
ConfigMapNamespace: api.NamespacePublic,
|
||||
ConfigMapName: configMapClusterInfo,
|
||||
ConfigMapName: bootstrapapi.ConfigMapClusterInfo,
|
||||
TokenSecretNamespace: api.NamespaceSystem,
|
||||
}
|
||||
}
|
||||
@ -191,17 +185,17 @@ func (e *BootstrapSigner) signConfigMap() {
|
||||
}
|
||||
|
||||
// First capture the config we are signing
|
||||
content, ok := newCM.Data[kubeConfigKey]
|
||||
content, ok := newCM.Data[bootstrapapi.KubeConfigKey]
|
||||
if !ok {
|
||||
glog.V(3).Infof("No %s key in %s/%s ConfigMap", kubeConfigKey, origCM.Namespace, origCM.Name)
|
||||
glog.V(3).Infof("No %s key in %s/%s ConfigMap", bootstrapapi.KubeConfigKey, origCM.Namespace, origCM.Name)
|
||||
return
|
||||
}
|
||||
|
||||
// Next remove and save all existing signatures
|
||||
sigs := map[string]string{}
|
||||
for key, value := range newCM.Data {
|
||||
if strings.HasPrefix(key, signaturePrefix) {
|
||||
tokenID := strings.TrimPrefix(key, signaturePrefix)
|
||||
if strings.HasPrefix(key, bootstrapapi.JWSSignatureKeyPrefix) {
|
||||
tokenID := strings.TrimPrefix(key, bootstrapapi.JWSSignatureKeyPrefix)
|
||||
sigs[tokenID] = value
|
||||
delete(newCM.Data, key)
|
||||
}
|
||||
@ -222,7 +216,7 @@ func (e *BootstrapSigner) signConfigMap() {
|
||||
}
|
||||
delete(sigs, tokenID)
|
||||
|
||||
newCM.Data[signaturePrefix+tokenID] = sig
|
||||
newCM.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID] = sig
|
||||
}
|
||||
|
||||
// If we have signatures left over we know that some signatures were
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/client-go/pkg/api"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
core "k8s.io/client-go/testing"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -43,15 +44,15 @@ func newConfigMap(tokenID, signature string) *v1.ConfigMap {
|
||||
ret := &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: metav1.NamespacePublic,
|
||||
Name: configMapClusterInfo,
|
||||
Name: bootstrapapi.ConfigMapClusterInfo,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
Data: map[string]string{
|
||||
kubeConfigKey: "payload",
|
||||
bootstrapapi.KubeConfigKey: "payload",
|
||||
},
|
||||
}
|
||||
if len(tokenID) > 0 {
|
||||
ret.Data[signaturePrefix+tokenID] = signature
|
||||
ret.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID] = signature
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
@ -34,17 +34,17 @@ func computeDetachedSig(content, tokenID, tokenSecret string) (string, error) {
|
||||
|
||||
signer, err := jose.NewSigner(jose.HS256, jwk)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
return "", fmt.Errorf("can't make a HS256 signer from the given token: %v", err)
|
||||
}
|
||||
|
||||
jws, err := signer.Sign([]byte(content))
|
||||
if err != nil {
|
||||
return "", nil
|
||||
return "", fmt.Errorf("can't HS256-sign the given token: %v", err)
|
||||
}
|
||||
|
||||
fullSig, err := jws.CompactSerialize()
|
||||
if err != nil {
|
||||
return "", nil
|
||||
return "", fmt.Errorf("can't serialize the given token: %v", err)
|
||||
}
|
||||
return stripContent(fullSig)
|
||||
}
|
||||
@ -57,8 +57,17 @@ func computeDetachedSig(content, tokenID, tokenSecret string) (string, error) {
|
||||
func stripContent(fullSig string) (string, error) {
|
||||
parts := strings.Split(fullSig, ".")
|
||||
if len(parts) != 3 {
|
||||
return "", fmt.Errorf("Compact JWS format must have three parts")
|
||||
return "", fmt.Errorf("compact JWS format must have three parts")
|
||||
}
|
||||
|
||||
return parts[0] + ".." + parts[2], nil
|
||||
}
|
||||
|
||||
// DetachedTokenIsValid checks whether a given detached JWS-encoded token matches JWS output of the given content and token
|
||||
func DetachedTokenIsValid(detachedToken, content, tokenID, tokenSecret string) bool {
|
||||
newToken, err := computeDetachedSig(content, tokenID, tokenSecret)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return detachedToken == newToken
|
||||
}
|
||||
|
@ -51,3 +51,17 @@ func TestComputeDetachedSig(t *testing.T) {
|
||||
t.Errorf("Wrong signature. Got: %v", sig)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetachedTokenIsValid(t *testing.T) {
|
||||
// Valid detached JWS token and valid inputs should succeed
|
||||
sig := "eyJhbGciOiJIUzI1NiIsImtpZCI6Impvc2h1YSJ9..VShe2taLd-YTrmWuRkcL_8QTNDHYxQIEBsAYYiIj1_8"
|
||||
if !DetachedTokenIsValid(sig, content, id, secret) {
|
||||
t.Errorf("Content %q and token \"%s:%s\" should equal signature: %q", content, id, secret, sig)
|
||||
}
|
||||
|
||||
// Invalid detached JWS token and valid inputs should fail
|
||||
sig2 := sig + "foo"
|
||||
if DetachedTokenIsValid(sig2, content, id, secret) {
|
||||
t.Errorf("Content %q and token \"%s:%s\" should not equal signature: %q", content, id, secret, sig)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user