mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-20 17:38:50 +00:00
move jws to k8s.io/cluster-bootstrap
Signed-off-by: Yassine TIJANI <ytijani@vmware.com>
This commit is contained in:
@@ -1,9 +1,35 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstrapsigner.go",
|
||||
"doc.go",
|
||||
"tokencleaner.go",
|
||||
"util.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/controller/bootstrap",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/util/metrics:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/jws:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/util/secrets:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
@@ -11,7 +37,6 @@ go_test(
|
||||
srcs = [
|
||||
"bootstrapsigner_test.go",
|
||||
"common_test.go",
|
||||
"jws_test.go",
|
||||
"tokencleaner_test.go",
|
||||
"util_test.go",
|
||||
],
|
||||
@@ -29,39 +54,6 @@ go_test(
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstrapsigner.go",
|
||||
"doc.go",
|
||||
"jws.go",
|
||||
"tokencleaner.go",
|
||||
"util.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/controller/bootstrap",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/util/metrics:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/util/secrets:go_default_library",
|
||||
"//vendor/gopkg.in/square/go-jose.v2:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -76,4 +68,5 @@ filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
@@ -23,7 +23,8 @@ import (
|
||||
"k8s.io/klog"
|
||||
|
||||
"fmt"
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
@@ -34,6 +35,7 @@ import (
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
jws "k8s.io/cluster-bootstrap/token/jws"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/util/metrics"
|
||||
@@ -214,7 +216,7 @@ func (e *Signer) signConfigMap() {
|
||||
// Now recompute signatures and store them on the new map
|
||||
tokens := e.getTokens()
|
||||
for tokenID, tokenValue := range tokens {
|
||||
sig, err := computeDetachedSig(content, tokenID, tokenValue)
|
||||
sig, err := jws.ComputeDetachedSignature(content, tokenID, tokenValue)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
}
|
||||
|
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
jose "gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
// computeDetachedSig takes content and token details and computes a detached
|
||||
// JWS signature. This is described in Appendix F of RFC 7515. Basically, this
|
||||
// is a regular JWS with the content part of the signature elided.
|
||||
func computeDetachedSig(content, tokenID, tokenSecret string) (string, error) {
|
||||
jwk := &jose.JSONWebKey{
|
||||
Key: []byte(tokenSecret),
|
||||
KeyID: tokenID,
|
||||
}
|
||||
|
||||
opts := &jose.SignerOptions{
|
||||
// Since this is a symmetric key, go-jose doesn't automatically include
|
||||
// the KeyID as part of the protected header. We have to pass it here
|
||||
// explicitly.
|
||||
ExtraHeaders: map[jose.HeaderKey]interface{}{
|
||||
"kid": tokenID,
|
||||
},
|
||||
}
|
||||
|
||||
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: jwk}, opts)
|
||||
if err != 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 "", fmt.Errorf("can't HS256-sign the given token: %v", err)
|
||||
}
|
||||
|
||||
fullSig, err := jws.CompactSerialize()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can't serialize the given token: %v", err)
|
||||
}
|
||||
return stripContent(fullSig)
|
||||
}
|
||||
|
||||
// stripContent will remove the content part of a compact JWS
|
||||
//
|
||||
// The `go-jose` library doesn't support generating signatures with "detached"
|
||||
// content. To make up for this we take the full compact signature, break it
|
||||
// apart and put it back together without the content section.
|
||||
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 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
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
content = "Hello from the other side. I must have called a thousand times."
|
||||
secret = "my voice is my passcode"
|
||||
id = "joshua"
|
||||
)
|
||||
|
||||
func TestComputeDetachedSig(t *testing.T) {
|
||||
sig, err := computeDetachedSig(content, id, secret)
|
||||
assert.NoError(t, err, "Error when computing signature: %v", err)
|
||||
assert.Equal(
|
||||
t,
|
||||
"eyJhbGciOiJIUzI1NiIsImtpZCI6Impvc2h1YSJ9..VShe2taLd-YTrmWuRkcL_8QTNDHYxQIEBsAYYiIj1_8",
|
||||
sig,
|
||||
"Wrong signature. Got: %v", sig)
|
||||
|
||||
// Try with null content
|
||||
sig, err = computeDetachedSig("", id, secret)
|
||||
assert.NoError(t, err, "Error when computing signature: %v", err)
|
||||
assert.Equal(
|
||||
t,
|
||||
"eyJhbGciOiJIUzI1NiIsImtpZCI6Impvc2h1YSJ9..7Ui1ALizW4jXphVUB7xUqC9vLYLL9RZeOFfVLoB7Tgk",
|
||||
sig,
|
||||
"Wrong signature. Got: %v", sig)
|
||||
|
||||
// Try with no secret
|
||||
sig, err = computeDetachedSig(content, id, "")
|
||||
assert.NoError(t, err, "Error when computing signature: %v", err)
|
||||
assert.Equal(
|
||||
t,
|
||||
"eyJhbGciOiJIUzI1NiIsImtpZCI6Impvc2h1YSJ9..UfkqvDGiIFxrMnFseDj9LYJOLNrvjW8aHhF71mvvAs8",
|
||||
sig,
|
||||
"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"
|
||||
assert.True(t, DetachedTokenIsValid(sig, content, id, secret),
|
||||
"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"
|
||||
assert.False(t, DetachedTokenIsValid(sig2, content, id, secret),
|
||||
"Content %q and token \"%s:%s\" should not equal signature: %q", content, id, secret, sig)
|
||||
}
|
Reference in New Issue
Block a user