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:
parent
56ace481c1
commit
bb77d9b4a6
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user