mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
fix(k8s/config): avoid hardcoded "insecure-skip-tls-verify" in kubeconfig [BE-11651] (#500)
This commit is contained in:
parent
993f69db37
commit
66bcf9223a
2 changed files with 254 additions and 1 deletions
|
@ -1,9 +1,14 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
|
@ -162,11 +167,38 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
|
|||
func (handler *Handler) buildCluster(r *http.Request, endpoint portainer.Endpoint, isInternal bool) clientV1.NamedCluster {
|
||||
kubeConfigInternal := handler.kubeClusterAccessService.GetClusterDetails(r.Host, endpoint.ID, isInternal)
|
||||
|
||||
selfSignedCert := false
|
||||
serverUrl, err := url.Parse(kubeConfigInternal.ClusterServerURL)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to parse server URL")
|
||||
}
|
||||
|
||||
if strings.EqualFold(serverUrl.Scheme, "https") {
|
||||
var certPem []byte
|
||||
var err error
|
||||
|
||||
if kubeConfigInternal.CertificateAuthorityData != "" {
|
||||
certPem = []byte(kubeConfigInternal.CertificateAuthorityData)
|
||||
} else if kubeConfigInternal.CertificateAuthorityFile != "" {
|
||||
certPem, err = os.ReadFile(kubeConfigInternal.CertificateAuthorityFile)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to open certificate file")
|
||||
}
|
||||
}
|
||||
|
||||
if certPem != nil {
|
||||
selfSignedCert, err = IsSelfSignedCertificate(certPem)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to verify if certificate is self-signed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clientV1.NamedCluster{
|
||||
Name: buildClusterName(endpoint.Name),
|
||||
Cluster: clientV1.Cluster{
|
||||
Server: kubeConfigInternal.ClusterServerURL,
|
||||
InsecureSkipTLSVerify: true,
|
||||
InsecureSkipTLSVerify: selfSignedCert,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -215,3 +247,38 @@ func writeFileContent(w http.ResponseWriter, r *http.Request, endpoints []portai
|
|||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; %s.json", filenameBase))
|
||||
return response.JSON(w, config)
|
||||
}
|
||||
|
||||
func IsSelfSignedCertificate(certPem []byte) (bool, error) {
|
||||
if certPem == nil {
|
||||
return false, errors.New("certificate data is empty")
|
||||
}
|
||||
|
||||
if !strings.Contains(string(certPem), "BEGIN CERTIFICATE") {
|
||||
certPem = []byte(fmt.Sprintf("-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----", string(certPem)))
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(certPem)
|
||||
if block == nil {
|
||||
return false, errors.New("failed to decode certificate")
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if cert.Issuer.String() != cert.Subject.String() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
roots := x509.NewCertPool()
|
||||
roots.AddCert(cert)
|
||||
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: roots,
|
||||
CurrentTime: cert.NotBefore,
|
||||
}
|
||||
|
||||
_, err = cert.Verify(opts)
|
||||
return err == nil, err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue