Zack Williams | e940c7a | 2019-08-21 14:25:39 -0700 | [diff] [blame] | 1 | /* |
| 2 | Copyright 2014 The Kubernetes Authors. |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package cert |
| 18 | |
| 19 | import ( |
| 20 | "crypto/x509" |
| 21 | "fmt" |
| 22 | "io/ioutil" |
| 23 | "os" |
| 24 | "path/filepath" |
| 25 | ) |
| 26 | |
| 27 | // CanReadCertAndKey returns true if the certificate and key files already exists, |
| 28 | // otherwise returns false. If lost one of cert and key, returns error. |
| 29 | func CanReadCertAndKey(certPath, keyPath string) (bool, error) { |
| 30 | certReadable := canReadFile(certPath) |
| 31 | keyReadable := canReadFile(keyPath) |
| 32 | |
| 33 | if certReadable == false && keyReadable == false { |
| 34 | return false, nil |
| 35 | } |
| 36 | |
| 37 | if certReadable == false { |
| 38 | return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", certPath) |
| 39 | } |
| 40 | |
| 41 | if keyReadable == false { |
| 42 | return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", keyPath) |
| 43 | } |
| 44 | |
| 45 | return true, nil |
| 46 | } |
| 47 | |
| 48 | // If the file represented by path exists and |
| 49 | // readable, returns true otherwise returns false. |
| 50 | func canReadFile(path string) bool { |
| 51 | f, err := os.Open(path) |
| 52 | if err != nil { |
| 53 | return false |
| 54 | } |
| 55 | |
| 56 | defer f.Close() |
| 57 | |
| 58 | return true |
| 59 | } |
| 60 | |
| 61 | // WriteCert writes the pem-encoded certificate data to certPath. |
| 62 | // The certificate file will be created with file mode 0644. |
| 63 | // If the certificate file already exists, it will be overwritten. |
| 64 | // The parent directory of the certPath will be created as needed with file mode 0755. |
| 65 | func WriteCert(certPath string, data []byte) error { |
| 66 | if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil { |
| 67 | return err |
| 68 | } |
| 69 | return ioutil.WriteFile(certPath, data, os.FileMode(0644)) |
| 70 | } |
| 71 | |
| 72 | // NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file. |
| 73 | // Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates |
| 74 | func NewPool(filename string) (*x509.CertPool, error) { |
| 75 | certs, err := CertsFromFile(filename) |
| 76 | if err != nil { |
| 77 | return nil, err |
| 78 | } |
| 79 | pool := x509.NewCertPool() |
| 80 | for _, cert := range certs { |
| 81 | pool.AddCert(cert) |
| 82 | } |
| 83 | return pool, nil |
| 84 | } |
| 85 | |
| 86 | // CertsFromFile returns the x509.Certificates contained in the given PEM-encoded file. |
| 87 | // Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates |
| 88 | func CertsFromFile(file string) ([]*x509.Certificate, error) { |
| 89 | pemBlock, err := ioutil.ReadFile(file) |
| 90 | if err != nil { |
| 91 | return nil, err |
| 92 | } |
| 93 | certs, err := ParseCertsPEM(pemBlock) |
| 94 | if err != nil { |
| 95 | return nil, fmt.Errorf("error reading %s: %s", file, err) |
| 96 | } |
| 97 | return certs, nil |
| 98 | } |