helpers.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. // Package helpers implements utility functionality common to many
  2. // CFSSL packages.
  3. package helpers
  4. import (
  5. "bytes"
  6. "crypto"
  7. "crypto/ecdsa"
  8. "crypto/elliptic"
  9. "crypto/rsa"
  10. "crypto/tls"
  11. "crypto/x509"
  12. "crypto/x509/pkix"
  13. "encoding/asn1"
  14. "encoding/pem"
  15. "errors"
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. ct "github.com/google/certificate-transparency-go"
  20. cttls "github.com/google/certificate-transparency-go/tls"
  21. ctx509 "github.com/google/certificate-transparency-go/x509"
  22. "golang.org/x/crypto/ocsp"
  23. "strings"
  24. "time"
  25. "github.com/cloudflare/cfssl/crypto/pkcs7"
  26. cferr "github.com/cloudflare/cfssl/errors"
  27. "github.com/cloudflare/cfssl/helpers/derhelpers"
  28. "github.com/cloudflare/cfssl/log"
  29. "golang.org/x/crypto/pkcs12"
  30. )
  31. // OneYear is a time.Duration representing a year's worth of seconds.
  32. const OneYear = 8760 * time.Hour
  33. // OneDay is a time.Duration representing a day's worth of seconds.
  34. const OneDay = 24 * time.Hour
  35. // DelegationUsage is the OID for the DelegationUseage extensions
  36. var DelegationUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44}
  37. // DelegationExtension
  38. var DelegationExtension = pkix.Extension{
  39. Id: DelegationUsage,
  40. Critical: false,
  41. Value: []byte{0x05, 0x00}, // ASN.1 NULL
  42. }
  43. // InclusiveDate returns the time.Time representation of a date - 1
  44. // nanosecond. This allows time.After to be used inclusively.
  45. func InclusiveDate(year int, month time.Month, day int) time.Time {
  46. return time.Date(year, month, day, 0, 0, 0, 0, time.UTC).Add(-1 * time.Nanosecond)
  47. }
  48. // Jul2012 is the July 2012 CAB Forum deadline for when CAs must stop
  49. // issuing certificates valid for more than 5 years.
  50. var Jul2012 = InclusiveDate(2012, time.July, 01)
  51. // Apr2015 is the April 2015 CAB Forum deadline for when CAs must stop
  52. // issuing certificates valid for more than 39 months.
  53. var Apr2015 = InclusiveDate(2015, time.April, 01)
  54. // KeyLength returns the bit size of ECDSA or RSA PublicKey
  55. func KeyLength(key interface{}) int {
  56. if key == nil {
  57. return 0
  58. }
  59. if ecdsaKey, ok := key.(*ecdsa.PublicKey); ok {
  60. return ecdsaKey.Curve.Params().BitSize
  61. } else if rsaKey, ok := key.(*rsa.PublicKey); ok {
  62. return rsaKey.N.BitLen()
  63. }
  64. return 0
  65. }
  66. // ExpiryTime returns the time when the certificate chain is expired.
  67. func ExpiryTime(chain []*x509.Certificate) (notAfter time.Time) {
  68. if len(chain) == 0 {
  69. return
  70. }
  71. notAfter = chain[0].NotAfter
  72. for _, cert := range chain {
  73. if notAfter.After(cert.NotAfter) {
  74. notAfter = cert.NotAfter
  75. }
  76. }
  77. return
  78. }
  79. // MonthsValid returns the number of months for which a certificate is valid.
  80. func MonthsValid(c *x509.Certificate) int {
  81. issued := c.NotBefore
  82. expiry := c.NotAfter
  83. years := (expiry.Year() - issued.Year())
  84. months := years*12 + int(expiry.Month()) - int(issued.Month())
  85. // Round up if valid for less than a full month
  86. if expiry.Day() > issued.Day() {
  87. months++
  88. }
  89. return months
  90. }
  91. // ValidExpiry determines if a certificate is valid for an acceptable
  92. // length of time per the CA/Browser Forum baseline requirements.
  93. // See https://cabforum.org/wp-content/uploads/CAB-Forum-BR-1.3.0.pdf
  94. func ValidExpiry(c *x509.Certificate) bool {
  95. issued := c.NotBefore
  96. var maxMonths int
  97. switch {
  98. case issued.After(Apr2015):
  99. maxMonths = 39
  100. case issued.After(Jul2012):
  101. maxMonths = 60
  102. case issued.Before(Jul2012):
  103. maxMonths = 120
  104. }
  105. if MonthsValid(c) > maxMonths {
  106. return false
  107. }
  108. return true
  109. }
  110. // SignatureString returns the TLS signature string corresponding to
  111. // an X509 signature algorithm.
  112. func SignatureString(alg x509.SignatureAlgorithm) string {
  113. switch alg {
  114. case x509.MD2WithRSA:
  115. return "MD2WithRSA"
  116. case x509.MD5WithRSA:
  117. return "MD5WithRSA"
  118. case x509.SHA1WithRSA:
  119. return "SHA1WithRSA"
  120. case x509.SHA256WithRSA:
  121. return "SHA256WithRSA"
  122. case x509.SHA384WithRSA:
  123. return "SHA384WithRSA"
  124. case x509.SHA512WithRSA:
  125. return "SHA512WithRSA"
  126. case x509.DSAWithSHA1:
  127. return "DSAWithSHA1"
  128. case x509.DSAWithSHA256:
  129. return "DSAWithSHA256"
  130. case x509.ECDSAWithSHA1:
  131. return "ECDSAWithSHA1"
  132. case x509.ECDSAWithSHA256:
  133. return "ECDSAWithSHA256"
  134. case x509.ECDSAWithSHA384:
  135. return "ECDSAWithSHA384"
  136. case x509.ECDSAWithSHA512:
  137. return "ECDSAWithSHA512"
  138. default:
  139. return "Unknown Signature"
  140. }
  141. }
  142. // HashAlgoString returns the hash algorithm name contains in the signature
  143. // method.
  144. func HashAlgoString(alg x509.SignatureAlgorithm) string {
  145. switch alg {
  146. case x509.MD2WithRSA:
  147. return "MD2"
  148. case x509.MD5WithRSA:
  149. return "MD5"
  150. case x509.SHA1WithRSA:
  151. return "SHA1"
  152. case x509.SHA256WithRSA:
  153. return "SHA256"
  154. case x509.SHA384WithRSA:
  155. return "SHA384"
  156. case x509.SHA512WithRSA:
  157. return "SHA512"
  158. case x509.DSAWithSHA1:
  159. return "SHA1"
  160. case x509.DSAWithSHA256:
  161. return "SHA256"
  162. case x509.ECDSAWithSHA1:
  163. return "SHA1"
  164. case x509.ECDSAWithSHA256:
  165. return "SHA256"
  166. case x509.ECDSAWithSHA384:
  167. return "SHA384"
  168. case x509.ECDSAWithSHA512:
  169. return "SHA512"
  170. default:
  171. return "Unknown Hash Algorithm"
  172. }
  173. }
  174. // StringTLSVersion returns underlying enum values from human names for TLS
  175. // versions, defaults to current golang default of TLS 1.0
  176. func StringTLSVersion(version string) uint16 {
  177. switch version {
  178. case "1.2":
  179. return tls.VersionTLS12
  180. case "1.1":
  181. return tls.VersionTLS11
  182. default:
  183. return tls.VersionTLS10
  184. }
  185. }
  186. // EncodeCertificatesPEM encodes a number of x509 certificates to PEM
  187. func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
  188. var buffer bytes.Buffer
  189. for _, cert := range certs {
  190. pem.Encode(&buffer, &pem.Block{
  191. Type: "CERTIFICATE",
  192. Bytes: cert.Raw,
  193. })
  194. }
  195. return buffer.Bytes()
  196. }
  197. // EncodeCertificatePEM encodes a single x509 certificates to PEM
  198. func EncodeCertificatePEM(cert *x509.Certificate) []byte {
  199. return EncodeCertificatesPEM([]*x509.Certificate{cert})
  200. }
  201. // ParseCertificatesPEM parses a sequence of PEM-encoded certificate and returns them,
  202. // can handle PEM encoded PKCS #7 structures.
  203. func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) {
  204. var certs []*x509.Certificate
  205. var err error
  206. certsPEM = bytes.TrimSpace(certsPEM)
  207. for len(certsPEM) > 0 {
  208. var cert []*x509.Certificate
  209. cert, certsPEM, err = ParseOneCertificateFromPEM(certsPEM)
  210. if err != nil {
  211. return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
  212. } else if cert == nil {
  213. break
  214. }
  215. certs = append(certs, cert...)
  216. }
  217. if len(certsPEM) > 0 {
  218. return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  219. }
  220. return certs, nil
  221. }
  222. // ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key,
  223. // either PKCS #7, PKCS #12, or raw x509.
  224. func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certificate, key crypto.Signer, err error) {
  225. certsDER = bytes.TrimSpace(certsDER)
  226. pkcs7data, err := pkcs7.ParsePKCS7(certsDER)
  227. if err != nil {
  228. var pkcs12data interface{}
  229. certs = make([]*x509.Certificate, 1)
  230. pkcs12data, certs[0], err = pkcs12.Decode(certsDER, password)
  231. if err != nil {
  232. certs, err = x509.ParseCertificates(certsDER)
  233. if err != nil {
  234. return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  235. }
  236. } else {
  237. key = pkcs12data.(crypto.Signer)
  238. }
  239. } else {
  240. if pkcs7data.ContentInfo != "SignedData" {
  241. return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info"))
  242. }
  243. certs = pkcs7data.Content.SignedData.Certificates
  244. }
  245. if certs == nil {
  246. return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  247. }
  248. return certs, key, nil
  249. }
  250. // ParseSelfSignedCertificatePEM parses a PEM-encoded certificate and check if it is self-signed.
  251. func ParseSelfSignedCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
  252. cert, err := ParseCertificatePEM(certPEM)
  253. if err != nil {
  254. return nil, err
  255. }
  256. if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
  257. return nil, cferr.Wrap(cferr.CertificateError, cferr.VerifyFailed, err)
  258. }
  259. return cert, nil
  260. }
  261. // ParseCertificatePEM parses and returns a PEM-encoded certificate,
  262. // can handle PEM encoded PKCS #7 structures.
  263. func ParseCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
  264. certPEM = bytes.TrimSpace(certPEM)
  265. cert, rest, err := ParseOneCertificateFromPEM(certPEM)
  266. if err != nil {
  267. // Log the actual parsing error but throw a default parse error message.
  268. log.Debugf("Certificate parsing error: %v", err)
  269. return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
  270. } else if cert == nil {
  271. return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  272. } else if len(rest) > 0 {
  273. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PEM file should contain only one object"))
  274. } else if len(cert) > 1 {
  275. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PKCS7 object in the PEM file should contain only one certificate"))
  276. }
  277. return cert[0], nil
  278. }
  279. // ParseOneCertificateFromPEM attempts to parse one PEM encoded certificate object,
  280. // either a raw x509 certificate or a PKCS #7 structure possibly containing
  281. // multiple certificates, from the top of certsPEM, which itself may
  282. // contain multiple PEM encoded certificate objects.
  283. func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, error) {
  284. block, rest := pem.Decode(certsPEM)
  285. if block == nil {
  286. return nil, rest, nil
  287. }
  288. cert, err := x509.ParseCertificate(block.Bytes)
  289. if err != nil {
  290. pkcs7data, err := pkcs7.ParsePKCS7(block.Bytes)
  291. if err != nil {
  292. return nil, rest, err
  293. }
  294. if pkcs7data.ContentInfo != "SignedData" {
  295. return nil, rest, errors.New("only PKCS #7 Signed Data Content Info supported for certificate parsing")
  296. }
  297. certs := pkcs7data.Content.SignedData.Certificates
  298. if certs == nil {
  299. return nil, rest, errors.New("PKCS #7 structure contains no certificates")
  300. }
  301. return certs, rest, nil
  302. }
  303. var certs = []*x509.Certificate{cert}
  304. return certs, rest, nil
  305. }
  306. // LoadPEMCertPool loads a pool of PEM certificates from file.
  307. func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
  308. if certsFile == "" {
  309. return nil, nil
  310. }
  311. pemCerts, err := ioutil.ReadFile(certsFile)
  312. if err != nil {
  313. return nil, err
  314. }
  315. return PEMToCertPool(pemCerts)
  316. }
  317. // PEMToCertPool concerts PEM certificates to a CertPool.
  318. func PEMToCertPool(pemCerts []byte) (*x509.CertPool, error) {
  319. if len(pemCerts) == 0 {
  320. return nil, nil
  321. }
  322. certPool := x509.NewCertPool()
  323. if !certPool.AppendCertsFromPEM(pemCerts) {
  324. return nil, errors.New("failed to load cert pool")
  325. }
  326. return certPool, nil
  327. }
  328. // ParsePrivateKeyPEM parses and returns a PEM-encoded private
  329. // key. The private key may be either an unencrypted PKCS#8, PKCS#1,
  330. // or elliptic private key.
  331. func ParsePrivateKeyPEM(keyPEM []byte) (key crypto.Signer, err error) {
  332. return ParsePrivateKeyPEMWithPassword(keyPEM, nil)
  333. }
  334. // ParsePrivateKeyPEMWithPassword parses and returns a PEM-encoded private
  335. // key. The private key may be a potentially encrypted PKCS#8, PKCS#1,
  336. // or elliptic private key.
  337. func ParsePrivateKeyPEMWithPassword(keyPEM []byte, password []byte) (key crypto.Signer, err error) {
  338. keyDER, err := GetKeyDERFromPEM(keyPEM, password)
  339. if err != nil {
  340. return nil, err
  341. }
  342. return derhelpers.ParsePrivateKeyDER(keyDER)
  343. }
  344. // GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes.
  345. func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) {
  346. // Ignore any EC PARAMETERS blocks when looking for a key (openssl includes
  347. // them by default).
  348. var keyDER *pem.Block
  349. for {
  350. keyDER, in = pem.Decode(in)
  351. if keyDER == nil || keyDER.Type != "EC PARAMETERS" {
  352. break
  353. }
  354. }
  355. if keyDER != nil {
  356. if procType, ok := keyDER.Headers["Proc-Type"]; ok {
  357. if strings.Contains(procType, "ENCRYPTED") {
  358. if password != nil {
  359. return x509.DecryptPEMBlock(keyDER, password)
  360. }
  361. return nil, cferr.New(cferr.PrivateKeyError, cferr.Encrypted)
  362. }
  363. }
  364. return keyDER.Bytes, nil
  365. }
  366. return nil, cferr.New(cferr.PrivateKeyError, cferr.DecodeFailed)
  367. }
  368. // ParseCSR parses a PEM- or DER-encoded PKCS #10 certificate signing request.
  369. func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error) {
  370. in = bytes.TrimSpace(in)
  371. p, rest := pem.Decode(in)
  372. if p != nil {
  373. if p.Type != "NEW CERTIFICATE REQUEST" && p.Type != "CERTIFICATE REQUEST" {
  374. return nil, rest, cferr.New(cferr.CSRError, cferr.BadRequest)
  375. }
  376. csr, err = x509.ParseCertificateRequest(p.Bytes)
  377. } else {
  378. csr, err = x509.ParseCertificateRequest(in)
  379. }
  380. if err != nil {
  381. return nil, rest, err
  382. }
  383. err = csr.CheckSignature()
  384. if err != nil {
  385. return nil, rest, err
  386. }
  387. return csr, rest, nil
  388. }
  389. // ParseCSRPEM parses a PEM-encoded certificate signing request.
  390. // It does not check the signature. This is useful for dumping data from a CSR
  391. // locally.
  392. func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
  393. block, _ := pem.Decode([]byte(csrPEM))
  394. if block == nil {
  395. return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
  396. }
  397. csrObject, err := x509.ParseCertificateRequest(block.Bytes)
  398. if err != nil {
  399. return nil, err
  400. }
  401. return csrObject, nil
  402. }
  403. // SignerAlgo returns an X.509 signature algorithm from a crypto.Signer.
  404. func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
  405. switch pub := priv.Public().(type) {
  406. case *rsa.PublicKey:
  407. bitLength := pub.N.BitLen()
  408. switch {
  409. case bitLength >= 4096:
  410. return x509.SHA512WithRSA
  411. case bitLength >= 3072:
  412. return x509.SHA384WithRSA
  413. case bitLength >= 2048:
  414. return x509.SHA256WithRSA
  415. default:
  416. return x509.SHA1WithRSA
  417. }
  418. case *ecdsa.PublicKey:
  419. switch pub.Curve {
  420. case elliptic.P521():
  421. return x509.ECDSAWithSHA512
  422. case elliptic.P384():
  423. return x509.ECDSAWithSHA384
  424. case elliptic.P256():
  425. return x509.ECDSAWithSHA256
  426. default:
  427. return x509.ECDSAWithSHA1
  428. }
  429. default:
  430. return x509.UnknownSignatureAlgorithm
  431. }
  432. }
  433. // LoadClientCertificate load key/certificate from pem files
  434. func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, error) {
  435. if certFile != "" && keyFile != "" {
  436. cert, err := tls.LoadX509KeyPair(certFile, keyFile)
  437. if err != nil {
  438. log.Criticalf("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
  439. return nil, err
  440. }
  441. log.Debug("Client certificate loaded ")
  442. return &cert, nil
  443. }
  444. return nil, nil
  445. }
  446. // CreateTLSConfig creates a tls.Config object from certs and roots
  447. func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Config {
  448. var certs []tls.Certificate
  449. if cert != nil {
  450. certs = []tls.Certificate{*cert}
  451. }
  452. return &tls.Config{
  453. Certificates: certs,
  454. RootCAs: remoteCAs,
  455. }
  456. }
  457. // SerializeSCTList serializes a list of SCTs.
  458. func SerializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
  459. list := ctx509.SignedCertificateTimestampList{}
  460. for _, sct := range sctList {
  461. sctBytes, err := cttls.Marshal(sct)
  462. if err != nil {
  463. return nil, err
  464. }
  465. list.SCTList = append(list.SCTList, ctx509.SerializedSCT{Val: sctBytes})
  466. }
  467. return cttls.Marshal(list)
  468. }
  469. // DeserializeSCTList deserializes a list of SCTs.
  470. func DeserializeSCTList(serializedSCTList []byte) ([]ct.SignedCertificateTimestamp, error) {
  471. var sctList ctx509.SignedCertificateTimestampList
  472. rest, err := cttls.Unmarshal(serializedSCTList, &sctList)
  473. if err != nil {
  474. return nil, err
  475. }
  476. if len(rest) != 0 {
  477. return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT list contained trailing garbage"))
  478. }
  479. list := make([]ct.SignedCertificateTimestamp, len(sctList.SCTList))
  480. for i, serializedSCT := range sctList.SCTList {
  481. var sct ct.SignedCertificateTimestamp
  482. rest, err := cttls.Unmarshal(serializedSCT.Val, &sct)
  483. if err != nil {
  484. return nil, err
  485. }
  486. if len(rest) != 0 {
  487. return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT contained trailing garbage"))
  488. }
  489. list[i] = sct
  490. }
  491. return list, nil
  492. }
  493. // SCTListFromOCSPResponse extracts the SCTList from an ocsp.Response,
  494. // returning an empty list if the SCT extension was not found or could not be
  495. // unmarshalled.
  496. func SCTListFromOCSPResponse(response *ocsp.Response) ([]ct.SignedCertificateTimestamp, error) {
  497. // This loop finds the SCTListExtension in the OCSP response.
  498. var SCTListExtension, ext pkix.Extension
  499. for _, ext = range response.Extensions {
  500. // sctExtOid is the ObjectIdentifier of a Signed Certificate Timestamp.
  501. sctExtOid := asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 5}
  502. if ext.Id.Equal(sctExtOid) {
  503. SCTListExtension = ext
  504. break
  505. }
  506. }
  507. // This code block extracts the sctList from the SCT extension.
  508. var sctList []ct.SignedCertificateTimestamp
  509. var err error
  510. if numBytes := len(SCTListExtension.Value); numBytes != 0 {
  511. var serializedSCTList []byte
  512. rest := make([]byte, numBytes)
  513. copy(rest, SCTListExtension.Value)
  514. for len(rest) != 0 {
  515. rest, err = asn1.Unmarshal(rest, &serializedSCTList)
  516. if err != nil {
  517. return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
  518. }
  519. }
  520. sctList, err = DeserializeSCTList(serializedSCTList)
  521. }
  522. return sctList, err
  523. }
  524. // ReadBytes reads a []byte either from a file or an environment variable.
  525. // If valFile has a prefix of 'env:', the []byte is read from the environment
  526. // using the subsequent name. If the prefix is 'file:' the []byte is read from
  527. // the subsequent file. If no prefix is provided, valFile is assumed to be a
  528. // file path.
  529. func ReadBytes(valFile string) ([]byte, error) {
  530. switch splitVal := strings.SplitN(valFile, ":", 2); len(splitVal) {
  531. case 1:
  532. return ioutil.ReadFile(valFile)
  533. case 2:
  534. switch splitVal[0] {
  535. case "env":
  536. return []byte(os.Getenv(splitVal[1])), nil
  537. case "file":
  538. return ioutil.ReadFile(splitVal[1])
  539. default:
  540. return nil, fmt.Errorf("unknown prefix: %s", splitVal[0])
  541. }
  542. default:
  543. return nil, fmt.Errorf("multiple prefixes: %s",
  544. strings.Join(splitVal[:len(splitVal)-1], ", "))
  545. }
  546. }