Warn about permissions when creating identity (#1384)

* Warn about permissions when creating identity

* Function to determine if directory is writeable

* Check if writable before authorizing

* Remove redeclatarion

* remove windows specific utils

* Nat nits

* Actually test if directory is writeable with file creation
This commit is contained in:
Alexander Leitner 2019-03-12 10:42:38 -04:00 committed by GitHub
parent 56ace481c1
commit bb77d9b4a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 21 deletions

View File

@ -55,7 +55,11 @@ func cmdSetup(cmd *cobra.Command, args []string) error {
return err
}
if config.Identity.Status() != identity.CertKey {
status, err := config.Identity.Status()
if err != nil {
return err
}
if status != identity.CertKey {
return errors.New("identity is missing")
}

View File

@ -79,7 +79,10 @@ func cmdNewID(cmd *cobra.Command, args []string) (err error) {
return err
}
s := newIDCfg.Identity.Status()
s, err := newIDCfg.Identity.Status()
if err != nil {
return err
}
if s == identity.NoCertNoKey || newIDCfg.Identity.Overwrite {
_, err := newIDCfg.Identity.Create(ca)
return err

View File

@ -20,6 +20,7 @@ import (
"storj.io/storj/pkg/peertls"
"storj.io/storj/pkg/pkcrypto"
"storj.io/storj/pkg/process"
"storj.io/storj/pkg/utils"
)
const (
@ -71,6 +72,11 @@ func init() {
}
func main() {
if writable, err := utils.IsWritable(identityDir); !writable || err != nil {
fmt.Printf("%s is not a writeable directory: %s\n", identityDir, err)
return
}
process.Exec(rootCmd)
}
@ -95,8 +101,12 @@ func cmdNewService(cmd *cobra.Command, args []string) error {
ParentKeyPath: config.ParentKeyPath,
}
if caConfig.Status() != identity.NoCertNoKey {
return errs.New("CA certificate and/or key already exits, NOT overwriting!")
status, err := caConfig.Status()
if err != nil {
return err
}
if status != identity.NoCertNoKey {
return errs.New("CA certificate and/or key already exists, NOT overwriting!")
}
identConfig := identity.SetupConfig{
@ -104,8 +114,12 @@ func cmdNewService(cmd *cobra.Command, args []string) error {
KeyPath: identKeyPath,
}
if identConfig.Status() != identity.NoCertNoKey {
return errs.New("Identity certificate and/or key already exits, NOT overwriting!")
status, err = identConfig.Status()
if err != nil {
return err
}
if status != identity.NoCertNoKey {
return errs.New("Identity certificate and/or key already exists, NOT overwriting!")
}
ca, caerr := caConfig.Create(process.Ctx(cmd), os.Stdout)
@ -128,6 +142,7 @@ func cmdAuthorize(cmd *cobra.Command, args []string) error {
ctx := process.Ctx(cmd)
serviceDir := serviceDirectory(args[0])
authToken := args[1]
caCertPath := filepath.Join(serviceDir, "ca.cert")

View File

@ -176,7 +176,7 @@ func NewCA(ctx context.Context, opts NewCAOptions) (_ *FullCertificateAuthority,
}
// Status returns the status of the CA cert/key files for the config
func (caS CASetupConfig) Status() TLSFilesStatus {
func (caS CASetupConfig) Status() (TLSFilesStatus, error) {
return statTLSFiles(caS.CertPath, caS.KeyPath)
}

View File

@ -263,7 +263,7 @@ func ToChains(chains ...[]*x509.Certificate) [][]*x509.Certificate {
}
// Status returns the status of the identity cert/key files for the config
func (is SetupConfig) Status() TLSFilesStatus {
func (is SetupConfig) Status() (TLSFilesStatus, error) {
return statTLSFiles(is.CertPath, is.KeyPath)
}

View File

@ -58,22 +58,37 @@ func writeFile(path string, dirmode, filemode os.FileMode, data []byte) error {
return nil
}
func statTLSFiles(certPath, keyPath string) TLSFilesStatus {
_, err := os.Stat(certPath)
hasCert := !os.IsNotExist(err)
func statTLSFiles(certPath, keyPath string) (status TLSFilesStatus, err error) {
hasKey := true
hasCert := true
_, err = os.Stat(keyPath)
hasKey := !os.IsNotExist(err)
if hasCert && hasKey {
return CertKey
} else if hasCert {
return CertNoKey
} else if hasKey {
return NoCertKey
_, err = os.Stat(certPath)
if err != nil {
if os.IsNotExist(err) {
hasCert = false
} else {
return NoCertNoKey, err
}
}
return NoCertNoKey
_, err = os.Stat(keyPath)
if err != nil {
if os.IsNotExist(err) {
hasKey = false
} else {
return NoCertNoKey, err
}
}
if hasCert && hasKey {
return CertKey, nil
} else if hasCert {
return CertNoKey, nil
} else if hasKey {
return NoCertKey, nil
}
return NoCertNoKey, nil
}
func (t TLSFilesStatus) String() string {

View File

@ -4,6 +4,8 @@
package utils
import (
"os"
"path"
"time"
"github.com/zeebo/errs"
@ -84,3 +86,35 @@ func discardNil(ch chan error) chan error {
}()
return r
}
// IsWritable determines if a directory is writeable
func IsWritable(filepath string) (bool, error) {
info, err := os.Stat(filepath)
if err != nil {
return false, err
}
if !info.IsDir() {
return false, errs.New("Path %s is not a directory", filepath)
}
// Check if the user bit is enabled in file permission
if info.Mode().Perm()&0200 == 0 {
return false, errs.New("Write permission bit is not set on this file for user")
}
// Test if user can create file
// There is no OS cross-compatible method for
// determining if a user has write permissions on a folder.
// We can test by attempting to create a file in the folder.
testFile := path.Join(filepath, ".perm")
file, err := os.Create(testFile) // For read access.
if err != nil {
return false, errs.New("Write permission bit is not set on this file for user")
}
_ = file.Close()
_ = os.Remove(testFile)
return true, nil
}