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 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") return errors.New("identity is missing")
} }

View File

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

View File

@ -20,6 +20,7 @@ import (
"storj.io/storj/pkg/peertls" "storj.io/storj/pkg/peertls"
"storj.io/storj/pkg/pkcrypto" "storj.io/storj/pkg/pkcrypto"
"storj.io/storj/pkg/process" "storj.io/storj/pkg/process"
"storj.io/storj/pkg/utils"
) )
const ( const (
@ -71,6 +72,11 @@ func init() {
} }
func main() { 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) process.Exec(rootCmd)
} }
@ -95,8 +101,12 @@ func cmdNewService(cmd *cobra.Command, args []string) error {
ParentKeyPath: config.ParentKeyPath, ParentKeyPath: config.ParentKeyPath,
} }
if caConfig.Status() != identity.NoCertNoKey { status, err := caConfig.Status()
return errs.New("CA certificate and/or key already exits, NOT overwriting!") if err != nil {
return err
}
if status != identity.NoCertNoKey {
return errs.New("CA certificate and/or key already exists, NOT overwriting!")
} }
identConfig := identity.SetupConfig{ identConfig := identity.SetupConfig{
@ -104,8 +114,12 @@ func cmdNewService(cmd *cobra.Command, args []string) error {
KeyPath: identKeyPath, KeyPath: identKeyPath,
} }
if identConfig.Status() != identity.NoCertNoKey { status, err = identConfig.Status()
return errs.New("Identity certificate and/or key already exits, NOT overwriting!") 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) 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) ctx := process.Ctx(cmd)
serviceDir := serviceDirectory(args[0]) serviceDir := serviceDirectory(args[0])
authToken := args[1] authToken := args[1]
caCertPath := filepath.Join(serviceDir, "ca.cert") 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 // 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) 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 // 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) 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 return nil
} }
func statTLSFiles(certPath, keyPath string) TLSFilesStatus { func statTLSFiles(certPath, keyPath string) (status TLSFilesStatus, err error) {
_, err := os.Stat(certPath) hasKey := true
hasCert := !os.IsNotExist(err) hasCert := true
_, err = os.Stat(keyPath) _, err = os.Stat(certPath)
hasKey := !os.IsNotExist(err) if err != nil {
if os.IsNotExist(err) {
if hasCert && hasKey { hasCert = false
return CertKey } else {
} else if hasCert { return NoCertNoKey, err
return CertNoKey }
} else if hasKey {
return NoCertKey
} }
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 { func (t TLSFilesStatus) String() string {

View File

@ -4,6 +4,8 @@
package utils package utils
import ( import (
"os"
"path"
"time" "time"
"github.com/zeebo/errs" "github.com/zeebo/errs"
@ -84,3 +86,35 @@ func discardNil(ch chan error) chan error {
}() }()
return r 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
}