2021-06-17 17:04:21 +00:00
package diagnose
import (
"context"
"errors"
"fmt"
"os"
"runtime"
"strings"
"github.com/hashicorp/vault/physical/raft"
)
const DatabaseFilename = "vault.db"
const owner = "owner"
const group = "group"
const other = "other"
2021-07-11 22:44:19 +00:00
const ownershipTestName = "Check Raft Folder Ownership"
const permissionsTestName = "Check Raft Folder Permissions"
const raftQuorumTestName = "Check For Raft Quorum"
2021-06-17 17:04:21 +00:00
func RaftFileChecks ( ctx context . Context , path string ) {
// Note: Stat does not return information about the symlink itself, in the case where we are dealing with one.
info , err := os . Stat ( path )
if err != nil {
2021-07-11 22:44:19 +00:00
SpotError ( ctx , permissionsTestName , fmt . Errorf ( "Error computing file permissions: %w." , err ) )
2021-06-17 17:04:21 +00:00
}
if ! IsDir ( info ) {
2021-07-11 22:44:19 +00:00
SpotError ( ctx , ownershipTestName , fmt . Errorf ( "Error: Raft storage path variable does not point to a folder." ) )
2021-06-17 17:04:21 +00:00
}
if ! HasDB ( path ) {
2021-07-11 22:44:19 +00:00
SpotWarn ( ctx , ownershipTestName , "Raft boltDB file has not been created." )
2021-06-17 17:04:21 +00:00
}
hasOnlyOwnerRW , errs := CheckFilePerms ( info )
2021-07-11 22:44:19 +00:00
for _ , err := range errs {
switch {
case strings . Contains ( err , FileIsSymlinkWarning ) || strings . Contains ( err , FileTooPermissiveWarning ) :
SpotWarn ( ctx , permissionsTestName , err )
case strings . Contains ( err , FilePermissionsMissingWarning ) :
SpotError ( ctx , permissionsTestName , errors . New ( err ) )
2021-06-17 17:04:21 +00:00
}
}
ownedByRoot := IsOwnedByRoot ( info )
requiresRoot := ownedByRoot && hasOnlyOwnerRW
if requiresRoot {
2021-07-11 22:44:19 +00:00
SpotWarn ( ctx , ownershipTestName , "Raft backend files are owned by root and are only accessible as root or with overpermissive file permissions. This prevents Vault from running as a non-privileged user." )
2021-06-17 17:04:21 +00:00
Advise ( ctx , "Please change raft path permissions to allow for non-root access." )
}
if runtime . GOOS == "windows" {
2021-07-11 22:44:19 +00:00
SpotWarn ( ctx , permissionsTestName , "Diagnose cannot determine if Vault needs to run as root to open boltDB file. Please check these permissions manually." )
2021-06-17 17:04:21 +00:00
} else if errs == nil && ! requiresRoot {
2021-07-11 22:44:19 +00:00
SpotOk ( ctx , permissionsTestName , "Raft BoltDB file has correct set of permissions." )
2021-06-17 17:04:21 +00:00
}
}
// RaftStorageQuorum checks that there is an odd number of voters present
// It returns the status message for testing purposes
func RaftStorageQuorum ( ctx context . Context , b RaftConfigurableStorageBackend ) string {
var conf * raft . RaftConfigurationResponse
var err error
conf , err = b . GetConfigurationOffline ( )
if err != nil {
2021-07-11 22:44:19 +00:00
SpotError ( ctx , raftQuorumTestName , fmt . Errorf ( "Error retrieving server configuration: %w." , err ) )
return fmt . Sprintf ( "Error retrieving server configuration: %s." , err . Error ( ) )
2021-06-17 17:04:21 +00:00
}
voterCount := 0
for _ , s := range conf . Servers {
if s . Voter {
voterCount ++
}
}
if voterCount == 1 {
2021-07-11 22:44:19 +00:00
nonHAWarning := "Only one server node found. Vault is not running in high availability mode."
SpotWarn ( ctx , raftQuorumTestName , nonHAWarning )
2021-06-17 17:04:21 +00:00
return nonHAWarning
}
var warnMsg string
if voterCount % 2 == 0 {
2021-07-11 22:44:19 +00:00
warnMsg = fmt . Sprintf ( "%d voters found. Please ensure that Vault has access to an odd number of voter nodes." , voterCount )
SpotWarn ( ctx , raftQuorumTestName , warnMsg )
2021-06-17 17:04:21 +00:00
return warnMsg
}
if voterCount > 7 {
2021-07-11 22:44:19 +00:00
warnMsg = fmt . Sprintf ( "Very large cluster detected: %d voters found. " , voterCount )
SpotWarn ( ctx , raftQuorumTestName , warnMsg )
2021-06-17 17:04:21 +00:00
return warnMsg
}
2021-07-11 22:44:19 +00:00
okMsg := fmt . Sprintf ( "Voter quorum exists: %d voters." , voterCount )
SpotOk ( ctx , raftQuorumTestName , okMsg )
2021-06-17 17:04:21 +00:00
return okMsg
}