Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support adding untrusted root CA certificates (corp certs) #5015

Merged
merged 7 commits into from
Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 44 additions & 34 deletions pkg/minikube/bootstrapper/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ import (
"k8s.io/minikube/pkg/util"
)

const (
CACertificatesDir = "/usr/share/ca-certificates"
laozc marked this conversation as resolved.
Show resolved Hide resolved
SSLCertStoreDir = "/etc/ssl/certs"
)

var (
certs = []string{
"ca.crt", "ca.key", "apiserver.crt", "apiserver.key", "proxy-client-ca.crt",
Expand Down Expand Up @@ -219,31 +224,33 @@ func generateCerts(k8s config.KubernetesConfig) error {
return nil
}

func collectCACerts() (map[string]string, error) {
localPath := constants.GetMinipath()
// isValidPEMCertificate checks whether the input file is a valid PEM certificate (with at least one CERTIFICATE block)
func isValidPEMCertificate(filePath string) (bool, error) {
fileBytes, err := ioutil.ReadFile(filePath)
if err != nil {
return false, err
}

isValidPem := func(hostpath string) (bool, error) {
fileBytes, err := ioutil.ReadFile(hostpath)
if err != nil {
return false, err
for {
block, rest := pem.Decode(fileBytes)
if block == nil {
break
}

for {
block, rest := pem.Decode(fileBytes)
if block == nil {
break
}

if block.Type == "CERTIFICATE" {
// certificate found
return true, nil
}
fileBytes = rest
if block.Type == "CERTIFICATE" {
// certificate found
return true, nil
}

return false, nil
fileBytes = rest
}

return false, nil
}

// collectCACerts looks up all PEM certificates with .crt or .pem extension in ~/.minikube/certs to copy to the host.
// Minikube root CA is also included but libmachine certificates (ca.pem/cert.pem) are excluded.
medyagh marked this conversation as resolved.
Show resolved Hide resolved
func collectCACerts() (map[string]string, error) {
localPath := constants.GetMinipath()
certFiles := map[string]string{}

certsDir := filepath.Join(localPath, "certs")
Expand All @@ -255,14 +262,14 @@ func collectCACerts() (map[string]string, error) {
if info != nil && !info.IsDir() {
ext := strings.ToLower(filepath.Ext(hostpath))
if ext == ".crt" || ext == ".pem" {
validPem, err := isValidPem(hostpath)
validPem, err := isValidPEMCertificate(hostpath)
if err != nil {
return err
}
if validPem {
filename := filepath.Base(hostpath)
dst := fmt.Sprintf("%s.%s", strings.TrimSuffix(filename, ext), "pem")
certFiles[hostpath] = path.Join(constants.CACertificatesDir, dst)
certFiles[hostpath] = path.Join(CACertificatesDir, dst)
}
}
}
Expand All @@ -277,7 +284,7 @@ func collectCACerts() (map[string]string, error) {
}

// populates minikube CA
certFiles[filepath.Join(localPath, "ca.crt")] = path.Join(constants.CACertificatesDir, "minikubeCA.pem")
certFiles[filepath.Join(localPath, "ca.crt")] = path.Join(CACertificatesDir, "minikubeCA.pem")

filtered := map[string]string{}
for k, v := range certFiles {
Expand All @@ -288,17 +295,20 @@ func collectCACerts() (map[string]string, error) {
return filtered, nil
}

func configureCACerts(cmd command.Runner, caCerts map[string]string) error {
getSubjectHash := func(hostpath string) (string, error) {
out, err := cmd.CombinedOutput(fmt.Sprintf("openssl x509 -hash -noout -in '%s'", hostpath))
if err != nil {
return "", err
}

stringHash := strings.ReplaceAll(out, "\n", "")
return stringHash, nil
// getSubjectHash calculates Certificate Subject Hash for creating certificate symlinks
func getSubjectHash(cmd command.Runner, filePath string) (string, error) {
out, err := cmd.CombinedOutput(fmt.Sprintf("openssl x509 -hash -noout -in '%s'", filePath))
if err != nil {
return "", err
}

stringHash := strings.TrimSpace(out)
return stringHash, nil
}

// configureCACerts looks up and installs all uploaded PEM certificates in /usr/share/ca-certificates to system-wide certificate store (/etc/ssl/certs).
// OpenSSL binary required in minikube ISO
func configureCACerts(cmd command.Runner, caCerts map[string]string) error {
hasSSLBinary := true
if err := cmd.Run("which openssl"); err != nil {
hasSSLBinary = false
Expand All @@ -310,18 +320,18 @@ func configureCACerts(cmd command.Runner, caCerts map[string]string) error {

for _, caCertFile := range caCerts {
dstFilename := path.Base(caCertFile)
certStorePath := path.Join(constants.SSLCertStoreDir, dstFilename)
certStorePath := path.Join(SSLCertStoreDir, dstFilename)
if err := cmd.Run(fmt.Sprintf("sudo test -f '%s'", certStorePath)); err != nil {
if err := cmd.Run(fmt.Sprintf("sudo ln -s '%s' '%s'", caCertFile, certStorePath)); err != nil {
return errors.Wrapf(err, "error making symbol link for certificate %s", caCertFile)
}
}
if hasSSLBinary {
subjectHash, err := getSubjectHash(caCertFile)
subjectHash, err := getSubjectHash(cmd, caCertFile)
if err != nil {
return errors.Wrapf(err, "error calculating subject hash for certificate %s", caCertFile)
}
subjectHashLink := path.Join(constants.SSLCertStoreDir, fmt.Sprintf("%s.0", subjectHash))
subjectHashLink := path.Join(SSLCertStoreDir, fmt.Sprintf("%s.0", subjectHash))
if err := cmd.Run(fmt.Sprintf("sudo test -f '%s'", subjectHashLink)); err != nil {
if err := cmd.Run(fmt.Sprintf("sudo ln -s '%s' '%s'", certStorePath, subjectHashLink)); err != nil {
return errors.Wrapf(err, "error making subject hash symbol link for certificate %s", caCertFile)
Expand Down
5 changes: 0 additions & 5 deletions pkg/minikube/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,3 @@ const (
// DriverDocumentation the documentation of the KVM driver
DriverDocumentation = "https://github.com/kubernetes/minikube/blob/master/docs/drivers.md"
)

const (
CACertificatesDir = "/usr/share/ca-certificates"
SSLCertStoreDir = "/etc/ssl/certs"
)