2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-08-13 09:39:45 +01:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2019-01-02 10:23:25 +00:00
|
|
|
package identity
|
2018-08-13 09:39:45 +01:00
|
|
|
|
|
|
|
import (
|
2018-12-13 13:50:05 +00:00
|
|
|
"io/ioutil"
|
2018-08-13 09:39:45 +01:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"github.com/zeebo/errs"
|
2019-03-27 22:20:10 +00:00
|
|
|
|
2019-11-14 19:46:15 +00:00
|
|
|
"storj.io/storj/private/fpath"
|
2018-08-13 09:39:45 +01:00
|
|
|
)
|
|
|
|
|
2018-08-27 18:28:16 +01:00
|
|
|
// TLSFilesStatus is the status of keys
|
|
|
|
type TLSFilesStatus int
|
2018-08-13 09:39:45 +01:00
|
|
|
|
2018-08-27 18:28:16 +01:00
|
|
|
// Four possible outcomes for four files
|
2018-08-13 09:39:45 +01:00
|
|
|
const (
|
2018-08-27 18:28:16 +01:00
|
|
|
NoCertNoKey = TLSFilesStatus(iota)
|
2018-08-13 09:39:45 +01:00
|
|
|
CertNoKey
|
|
|
|
NoCertKey
|
|
|
|
CertKey
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2018-08-27 18:28:16 +01:00
|
|
|
// ErrZeroBytes is returned for zero slice
|
2018-08-13 09:39:45 +01:00
|
|
|
ErrZeroBytes = errs.New("byte slice was unexpectedly empty")
|
|
|
|
)
|
|
|
|
|
2018-12-18 11:55:55 +00:00
|
|
|
// writeChainData writes data to path ensuring permissions are appropriate for a cert
|
|
|
|
func writeChainData(path string, data []byte) error {
|
2018-12-13 13:50:05 +00:00
|
|
|
err := writeFile(path, 0744, 0644, data)
|
|
|
|
if err != nil {
|
|
|
|
return errs.New("unable to write certificate to \"%s\": %v", path, err)
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
2018-12-13 13:50:05 +00:00
|
|
|
return nil
|
|
|
|
}
|
2018-08-13 09:39:45 +01:00
|
|
|
|
2018-12-13 13:50:05 +00:00
|
|
|
// writeKeyData writes data to path ensuring permissions are appropriate for a cert
|
|
|
|
func writeKeyData(path string, data []byte) error {
|
|
|
|
err := writeFile(path, 0700, 0600, data)
|
2018-08-13 09:39:45 +01:00
|
|
|
if err != nil {
|
2018-12-13 13:50:05 +00:00
|
|
|
return errs.New("unable to write key to \"%s\": %v", path, err)
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
2018-12-13 13:50:05 +00:00
|
|
|
return nil
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
|
|
|
|
2018-12-13 13:50:05 +00:00
|
|
|
// writeFile writes to path, creating directories and files with the necessary permissions
|
|
|
|
func writeFile(path string, dirmode, filemode os.FileMode, data []byte) error {
|
|
|
|
if err := os.MkdirAll(filepath.Dir(path), dirmode); err != nil {
|
|
|
|
return errs.Wrap(err)
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
2019-03-27 22:20:10 +00:00
|
|
|
if writable, err := fpath.IsWritable(filepath.Dir(path)); !writable || err != nil {
|
|
|
|
return errs.Wrap(errs.New("%s is not a writeable directory: %s\n", path, err))
|
|
|
|
}
|
2018-12-13 13:50:05 +00:00
|
|
|
if err := ioutil.WriteFile(path, data, filemode); err != nil {
|
|
|
|
return errs.Wrap(err)
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
2018-12-13 13:50:05 +00:00
|
|
|
|
|
|
|
return nil
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
|
|
|
|
2019-03-12 14:42:38 +00:00
|
|
|
func statTLSFiles(certPath, keyPath string) (status TLSFilesStatus, err error) {
|
|
|
|
hasKey := true
|
|
|
|
hasCert := true
|
|
|
|
|
|
|
|
_, err = os.Stat(certPath)
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
hasCert = false
|
|
|
|
} else {
|
|
|
|
return NoCertNoKey, err
|
|
|
|
}
|
|
|
|
}
|
2018-08-27 18:28:16 +01:00
|
|
|
|
2018-08-13 09:39:45 +01:00
|
|
|
_, err = os.Stat(keyPath)
|
2019-03-12 14:42:38 +00:00
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
hasKey = false
|
|
|
|
} else {
|
|
|
|
return NoCertNoKey, err
|
|
|
|
}
|
|
|
|
}
|
2019-05-29 14:14:25 +01:00
|
|
|
switch {
|
|
|
|
case hasCert && hasKey:
|
2019-03-12 14:42:38 +00:00
|
|
|
return CertKey, nil
|
2019-05-29 14:14:25 +01:00
|
|
|
case hasCert:
|
2019-03-12 14:42:38 +00:00
|
|
|
return CertNoKey, nil
|
2019-05-29 14:14:25 +01:00
|
|
|
case hasKey:
|
2019-03-12 14:42:38 +00:00
|
|
|
return NoCertKey, nil
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
2018-08-27 18:28:16 +01:00
|
|
|
|
2019-03-12 14:42:38 +00:00
|
|
|
return NoCertNoKey, nil
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|
|
|
|
|
2018-08-27 18:28:16 +01:00
|
|
|
func (t TLSFilesStatus) String() string {
|
2018-08-13 09:39:45 +01:00
|
|
|
switch t {
|
|
|
|
case CertKey:
|
|
|
|
return "certificate and key"
|
|
|
|
case CertNoKey:
|
|
|
|
return "certificate"
|
|
|
|
case NoCertKey:
|
|
|
|
return "key"
|
|
|
|
}
|
2018-08-27 18:28:16 +01:00
|
|
|
return ""
|
2018-08-13 09:39:45 +01:00
|
|
|
}
|