fix: csr keyusage check

DeepEqual sees different in unsorted slices.
We will check allowed keyUsage options,
and makes chore that it has two important flags.

Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev>
This commit is contained in:
Serge Logvinov
2023-05-08 10:12:40 +03:00
parent 2b53c2b9e7
commit 5d65b1d694
8 changed files with 60 additions and 30 deletions

View File

@@ -10,7 +10,7 @@ COPY go.mod go.sum /src
RUN go mod download && go mod verify
COPY . .
ARG TAG
ARG VERSION
RUN make build-all-archs
########################################

View File

@@ -5,11 +5,12 @@ IMAGE ?= $(REGISTRY)/$(USERNAME)/$(PROJECT)
PLATFORM ?= linux/arm64,linux/amd64
PUSH ?= false
VERSION ?= $(shell git describe --dirty --tag --match='v*')
SHA ?= $(shell git describe --match=none --always --abbrev=8 --dirty)
TAG ?= $(shell git describe --tag --always --match v[0-9]\*)
ifneq ($(TAG),edge)
GO_LDFLAGS ?= -ldflags '-X k8s.io/component-base/version.gitVersion=$(TAG)'
endif
TAG ?= $(VERSION)
GO_LDFLAGS := -s -w
GO_LDFLAGS += -X k8s.io/component-base/version.gitVersion=$(VERSION)
OS ?= $(shell go env GOOS)
ARCH ?= $(shell go env GOARCH)
@@ -53,12 +54,12 @@ build-all-archs:
.PHONY: build
build: ## Build
CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build $(GO_LDFLAGS) \
CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -ldflags "$(GO_LDFLAGS)" \
-o talos-cloud-controller-manager-$(ARCH) ./cmd/talos-cloud-controller-manager
.PHONY: run
run: build
./talos-cloud-controller-manager-$(ARCH) --v=4 --kubeconfig=kubeconfig --cloud-config=hack/talos-config.yaml --controllers=cloud-node \
./talos-cloud-controller-manager-$(ARCH) --v=5 --kubeconfig=kubeconfig --cloud-config=hack/talos-config.yaml --controllers=cloud-node \
--use-service-account-credentials --leader-elect=false --bind-address=127.0.0.1
.PHONY: lint
@@ -96,6 +97,6 @@ docker-init:
images:
@docker buildx build $(BUILD_ARGS) \
--build-arg TAG=$(TAG) \
--build-arg VERSION="$(VERSION)" \
-t $(IMAGE):$(TAG) \
-f Dockerfile .

View File

@@ -1,5 +1,6 @@
global:
approveNodeCSR: true
skipForeignNode: false
# endpoints:
# - 1.2.3.4
# - 4.3.2.1

View File

@@ -93,13 +93,12 @@ func (r *Reconciler) Run(ctx context.Context) {
continue
}
_, err = r.kclient.CertificatesV1().CertificateSigningRequests().UpdateApproval(ctx, csr.Name, csr, metav1.UpdateOptions{})
if err != nil {
if _, err := r.kclient.CertificatesV1().CertificateSigningRequests().UpdateApproval(ctx, csr.Name, csr, metav1.UpdateOptions{}); err != nil {
klog.Errorf("CertificateSigningRequestReconciler: failed to approve/deny CSR %s: %v", csr.Name, err)
}
if !valid {
klog.V(3).Infof("CertificateSigningRequestReconciler: has been denied: %s, %+v", csr.Name, err.Error())
klog.Warningf("CertificateSigningRequestReconciler: has been denied: %s", csr.Name)
} else {
klog.V(3).Infof("CertificateSigningRequestReconciler: has been approved: %s", csr.Name)
}

View File

@@ -52,17 +52,11 @@ var (
errKeyUsageMismatch = fmt.Errorf("key usage does not match")
)
var (
kubeletServingRequiredUsages = []certificatesv1.KeyUsage{
certificatesv1.UsageKeyEncipherment,
certificatesv1.UsageDigitalSignature,
certificatesv1.UsageServerAuth,
}
kubeletServingRequiredUsagesNoRSA = []certificatesv1.KeyUsage{
certificatesv1.UsageDigitalSignature,
certificatesv1.UsageServerAuth,
}
)
var kubeletServingRequiredUsages = []certificatesv1.KeyUsage{
certificatesv1.UsageKeyEncipherment,
certificatesv1.UsageDigitalSignature,
certificatesv1.UsageServerAuth,
}
func validateKubeletServingCSR(req *x509.CertificateRequest, keyUsages []certificatesv1.KeyUsage) error {
if len(req.DNSNames) == 0 && len(req.IPAddresses) == 0 {
@@ -85,9 +79,22 @@ func validateKubeletServingCSR(req *x509.CertificateRequest, keyUsages []certifi
return errCommonNameNotSystemNode
}
if !reflect.DeepEqual(kubeletServingRequiredUsages, keyUsages) && !reflect.DeepEqual(kubeletServingRequiredUsagesNoRSA, keyUsages) {
return errKeyUsageMismatch
usageMap := map[certificatesv1.KeyUsage]bool{}
for _, u := range kubeletServingRequiredUsages {
usageMap[u] = false
}
return nil
for _, ku := range keyUsages {
if _, u := usageMap[ku]; !u {
return errKeyUsageMismatch
}
usageMap[ku] = true
}
if usageMap[certificatesv1.UsageServerAuth] && usageMap[certificatesv1.UsageDigitalSignature] {
return nil
}
return errKeyUsageMismatch
}

View File

@@ -239,6 +239,22 @@ func TestValidateKubeletServingCSRInvalid(t *testing.T) {
},
expectedError: errKeyUsageMismatch,
},
{
msg: "Invalid key usages, ServerAuth missing",
x509cr: x509.CertificateRequest{
Subject: pkix.Name{
CommonName: cname,
Organization: []string{org},
},
DNSNames: dnsNames,
IPAddresses: ipAddresses,
},
keyUsages: []certificatesv1.KeyUsage{
certificatesv1.UsageDigitalSignature,
certificatesv1.UsageDigitalSignature,
},
expectedError: errKeyUsageMismatch,
},
}
for _, testCase := range tests {

View File

@@ -90,6 +90,8 @@ func (c *cloud) Initialize(clientBuilder cloudprovider.ControllerClientBuilder,
}(c)
if c.cfg.Global.ApproveNodeCSR {
klog.Infof("Started CSR Node controller")
c.csrController = certificatesigningrequest.NewCsrController(c.client.kclient, csrNodeChecks)
go c.csrController.Run(c.ctx)
}

View File

@@ -78,13 +78,17 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalDNS, Address: meta.Hostname})
}
// Skip initialized nodes.
// Foreign node, update network only.
if i.c.config.Global.SkipForeignNode && !strings.HasPrefix(node.Spec.ProviderID, ProviderName) {
klog.V(4).Infof("instances.InstanceMetadata() node %s has foreign providerID: %s, skipped", node.Name, node.Spec.ProviderID)
if err := syncNodeLabels(i.c, node, meta); err != nil {
klog.Errorf("failed update labels for node %s, %w", node.Name, err)
}
return &cloudprovider.InstanceMetadata{
NodeAddresses: addresses,
}, nil
}
if err := syncNodeLabels(i.c, node, meta); err != nil {
klog.Errorf("failed update labels for node %s, %w", node.Name, err)
}
return &cloudprovider.InstanceMetadata{
@@ -96,7 +100,7 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
}, nil
}
klog.V(4).Infof("instances.InstanceMetadata() is kubelet has --cloud-provider=external on the node %s?", node.Name)
klog.Warningf("instances.InstanceMetadata() is kubelet has --cloud-provider=external on the node %s?", node.Name)
return &cloudprovider.InstanceMetadata{}, nil
}