diff --git a/README.md b/README.md index bc50d54..42e5b7a 100644 --- a/README.md +++ b/README.md @@ -97,8 +97,7 @@ kube-system Warning coredns Deployment 2020-11-27T1 | :white_check_mark: | PodFileExists | Check for existing files| | :white_check_mark: | PodTooManyOpenFiles | The number of file /socket connections opened by the program exceeds the system set value| | :white_check_mark: | PodNoSpaceLeftOnDevice | Check for disk and inode usage| -| | NodeTokenExpiredPeriod | Check Token expiration period is one month| -| | NodeKubeletExpiredPeriod | Check Kubelet period is one month| +| :white_check_mark: | NodeApiServerExpiredPeriod | ApiServer certificate expiration date less than 30 days will be checked| | :white_check_mark: | PodSetCpuRequestsMissing | The CPU Resource Request value was not declared| | :white_check_mark: | PodSetHostIPCSet | Set the hostIP| | :white_check_mark: | PodSetHostNetworkSet | Set the hostNetwork| @@ -113,6 +112,7 @@ kube-system Warning coredns Deployment 2020-11-27T1 | :white_check_mark: | PodlivenessProbeMissing | ReadinessProbe was not declared| | :white_check_mark: | privilegeEscalationAllowed | Privilege escalation is allowed| | | NodeNotReadyAndUseOfClosedNetworkConnection | http2-max-streams-per-connection | +| | NodeNotReady | Failed to start ContainerManager Cannot set property TasksAccounting, or unknown property | > unmarked items are under heavy development diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 540ddda..6e0a2e2 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -1,3 +1,16 @@ +// Copyright 2020 KubeSphere 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 config import ( diff --git a/pkg/kube/resources_test.go b/pkg/kube/resources_test.go index c40160d..719a264 100644 --- a/pkg/kube/resources_test.go +++ b/pkg/kube/resources_test.go @@ -1,3 +1,16 @@ +// Copyright 2020 KubeSphere 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 kube import ( diff --git a/pkg/validator/audit.go b/pkg/validator/audit.go index 6144b19..03e6850 100644 --- a/pkg/validator/audit.go +++ b/pkg/validator/audit.go @@ -19,10 +19,13 @@ import ( "fmt" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" + certutil "k8s.io/client-go/util/cert" conf "kubeye/pkg/config" "kubeye/pkg/kube" "os" + "os/exec" "path/filepath" + "strconv" "strings" "text/tabwriter" "time" @@ -49,6 +52,27 @@ func Cluster(configuration string, ctx context.Context, allInformation bool) err return errors.Wrap(err3, "Failed to get nodeStatus information") } + // Get kube-apiserver certificate expiration + var certExpires []Certificate + cmd := fmt.Sprintf("cat /etc/kubernetes/pki/%s", "apiserver.crt") + output, _ := exec.Command("/bin/sh", "-c", cmd).CombinedOutput() + if output != nil { + certs, _ := certutil.ParseCertsPEM([]byte(output)) + certExpire := Certificate{ + Name: "kube-apiserver", + Expires: certs[0].NotAfter.Format("Jan 02, 2006 15:04 MST"), + Residual: ResidualTime(certs[0].NotAfter), + } + if strings.Contains(certExpire.Residual, "d") { + tmpTime, _ := strconv.Atoi(strings.TrimRight(certExpire.Residual, "d")) + if tmpTime < 30 { + certExpires = append(certExpires, certExpire) + } + } else { + certExpires = append(certExpires, certExpire) + } + } + var config conf.Configuration var goodPractice []PodResult if len(configuration) != 0 { @@ -148,6 +172,18 @@ func Cluster(configuration string, ctx context.Context, allInformation bool) err continue } } + if len(certExpires) != 0 { + fmt.Fprintln(w, "\nNAME\tEXPIRES\tRESIDUAL") + for _, certExpire := range certExpires { + s := fmt.Sprintf("%s\t%s\t%-8v", + certExpire.Name, + certExpire.Expires, + certExpire.Residual, + ) + fmt.Fprintln(w, s) + continue + } + } w.Flush() //auditData := AuditData{ @@ -231,3 +267,21 @@ func NodeStatusResult(nodes []v1.Node) ([]AllNodeStatusResults, error) { } return nodestatus, nil } + +func ResidualTime(t time.Time) string { + d := time.Until(t) + if seconds := int(d.Seconds()); seconds < -1 { + return fmt.Sprintf("") + } else if seconds < 0 { + return fmt.Sprintf("0s") + } else if seconds < 60 { + return fmt.Sprintf("%ds", seconds) + } else if minutes := int(d.Minutes()); minutes < 60 { + return fmt.Sprintf("%dm", minutes) + } else if hours := int(d.Hours()); hours < 24 { + return fmt.Sprintf("%dh", hours) + } else if hours < 24*365 { + return fmt.Sprintf("%dd", hours/24) + } + return fmt.Sprintf("%dy", int(d.Hours()/24/365)) +} diff --git a/pkg/validator/container_test.go b/pkg/validator/container_test.go index 4b3c12b..e54d0c5 100644 --- a/pkg/validator/container_test.go +++ b/pkg/validator/container_test.go @@ -1,3 +1,16 @@ +// Copyright 2020 KubeSphere 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 validator import ( diff --git a/pkg/validator/output.go b/pkg/validator/output.go index 83079de..017368d 100644 --- a/pkg/validator/output.go +++ b/pkg/validator/output.go @@ -86,3 +86,9 @@ type ResultMessage struct { Severity config.Severity `yaml:"severity" json:"severity,omitempty"` Category string `yaml:"category" json:"category,omitempty"` } + +type Certificate struct { + Name string `yaml:"name" json:"name,omitempty"` + Expires string `yaml:"expires" json:"expires,omitempty"` + Residual string `yaml:"residual" json:"residual,omitempty"` +} diff --git a/pkg/validator/pod_test.go b/pkg/validator/pod_test.go index 0b5a0a1..1eae91c 100644 --- a/pkg/validator/pod_test.go +++ b/pkg/validator/pod_test.go @@ -1,3 +1,16 @@ +// Copyright 2020 KubeSphere 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 validator import (