Regression fix of eth2_network_simulation on Windows. (#1900)

* Concentrate all sensitive writeFile/createPath calls in one place.
Fix eth2_network_simulation for Windows.

* Remove artifacts.

* fix import

Co-authored-by: Jacek Sieka <jacek@status.im>
This commit is contained in:
Eugene Kabanov 2020-10-27 13:04:17 +02:00 committed by GitHub
parent c82ff24b5c
commit eee01a32d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 130 additions and 117 deletions

View File

@ -6,7 +6,8 @@ import
serialization, chronicles, snappy,
eth/db/[kvstore, kvstore_sqlite3],
./spec/[datatypes, digest, crypto, state_transition, signatures],
./ssz/[ssz_serialization, merkleization]
./ssz/[ssz_serialization, merkleization],
filepath
type
DbSeq*[T] = object
@ -202,7 +203,7 @@ proc init*(T: type BeaconChainDB,
# of the database-backed one (i.e. tracking of deposits and validators)
T(backend: kvStore MemStoreRef.init(), preset: preset)
else:
let s = createPath(dir, 0o750)
let s = secureCreatePath(dir)
doAssert s.isOk # TODO Handle this in a better way
let sqliteStore = SqStoreRef.init(dir, "nbc", Keyspaces).expect(

View File

@ -32,9 +32,8 @@ import
nimbus_binary_common, network_metadata,
mainchain_monitor, version, ssz/[merkleization], merkle_minimal,
sync_protocol, request_manager, keystore_management, interop, statusbar,
sync_manager, validator_duties,
validator_slashing_protection,
./eth2_processor
sync_manager, validator_duties, filepath,
validator_slashing_protection, ./eth2_processor
const
hasPrompt = not defined(withoutPrompt)
@ -1179,12 +1178,12 @@ programMain:
swap(mnemonic, walletRes.get.mnemonic)
walletPath = walletRes.get.walletPath
let vres = createPath(config.outValidatorsDir, 0o750)
let vres = secureCreatePath(config.outValidatorsDir)
if vres.isErr():
fatal "Could not create directory", path = config.outValidatorsDir
quit QuitFailure
let sres = createPath(config.outSecretsDir, 0o750)
let sres = secureCreatePath(config.outSecretsDir)
if sres.isErr():
fatal "Could not create directory", path = config.outSecretsDir
quit QuitFailure

View File

@ -7,7 +7,7 @@ import
stew/io2, unicodedb/properties, normalize,
json_serialization, web3/[ethtypes, confutils_defs],
spec/[crypto, keystore, digest, datatypes, network],
network_metadata
network_metadata, filepath
export
defaultEth2TcpPort, enabledLogLevel, ValidIpAddress,
@ -434,13 +434,13 @@ func dumpDirOutgoing*(conf: BeaconNodeConf|ValidatorClientConf): string =
proc createDumpDirs*(conf: BeaconNodeConf) =
if conf.dumpEnabled:
let resInv = createPath(conf.dumpDirInvalid, 0o750)
let resInv = secureCreatePath(conf.dumpDirInvalid)
if resInv.isErr():
warn "Could not create dump directory", path = conf.dumpDirInvalid
let resInc = createPath(conf.dumpDirIncoming, 0o750)
let resInc = secureCreatePath(conf.dumpDirIncoming)
if resInc.isErr():
warn "Could not create dump directory", path = conf.dumpDirIncoming
let resOut = createPath(conf.dumpDirOutgoing, 0o750)
let resOut = secureCreatePath(conf.dumpDirOutgoing)
if resOut.isErr():
warn "Could not create dump directory", path = conf.dumpDirOutgoing

View File

@ -2,7 +2,7 @@ import
os, sequtils, strutils, options, json, terminal, random,
chronos, chronicles, confutils, stint, json_serialization,
../beacon_chain/network_metadata,
web3, web3/confutils_defs, eth/keys, stew/io2,
web3, web3/confutils_defs, eth/keys, stew/io2, filepath,
spec/[datatypes, crypto, presets], ssz/merkleization, keystore_management
# Compiled version of /scripts/depositContract.v.py in this repo
@ -178,12 +178,12 @@ proc main() {.async.} =
mnemonic = generateMnemonic(rng[])
runtimePreset = getRuntimePresetForNetwork(cfg.eth2Network)
let vres = createPath(string cfg.outValidatorsDir, 0o750)
let vres = secureCreatePath(string cfg.outValidatorsDir)
if vres.isErr():
warn "Could not create validators folder",
path = string cfg.outValidatorsDir, err = ioErrorMsg(vres.error)
let sres = createPath(string cfg.outSecretsDir, 0o750)
let sres = secureCreatePath(string cfg.outSecretsDir)
if sres.isErr():
warn "Could not create secrets folder",
path = string cfg.outSecretsDir, err = ioErrorMsg(sres.error)

33
beacon_chain/filepath.nim Normal file
View File

@ -0,0 +1,33 @@
import chronicles
import stew/io2
export io2
when defined(windows):
import stew/[windows/acl]
proc secureCreatePath*(path: string): IoResult[void] =
when defined(windows):
let sres = createFoldersUserOnlySecurityDescriptor()
if sres.isErr():
error "Could not allocate security descriptor", path = path,
errorMsg = ioErrorMsg(sres.error), errorCode = $sres.error
err(sres.error)
else:
var sd = sres.get()
createPath(path, 0o750, secDescriptor = sd.getDescriptor())
else:
createPath(path, 0o750)
proc secureWriteFile*[T: byte|char](path: string,
data: openArray[T]): IoResult[void] =
when defined(windows):
let sres = createFilesUserOnlySecurityDescriptor()
if sres.isErr():
error "Could not allocate security descriptor", path = path,
errorMsg = ioErrorMsg(sres.error), errorCode = $sres.error
err(sres.error)
else:
var sd = sres.get()
writeFile(path, data, 0o600, secDescriptor = sd.getDescriptor())
else:
writeFile(path, data, 0o600)

View File

@ -5,7 +5,7 @@ import
spec/[datatypes, digest, crypto, keystore],
stew/[byteutils, io2], libp2p/crypto/crypto as lcrypto,
nimcrypto/utils as ncrutils,
conf, ssz/merkleization, network_metadata
conf, ssz/merkleization, network_metadata, filepath
export
keystore
@ -71,7 +71,7 @@ proc checkAndCreateDataDir*(dataDir: string): bool =
else:
true
else:
let res = createPath(dataDir, 0o750)
let res = secureCreatePath(dataDir)
if res.isErr():
fatal "Could not create data folder", data_dir = dataDir,
errorMsg = ioErrorMsg(res.error), errorCode = $res.error
@ -93,20 +93,13 @@ proc checkAndCreateDataDir*(dataDir: string): bool =
else:
true
else:
let sres = createCurrentUserOnlySecurityDescriptor()
if sres.isErr():
fatal "Could not allocate security descriptor", data_dir = dataDir,
errorMsg = ioErrorMsg(sres.error), errorCode = $sres.error
let res = secureCreatePath(dataDir)
if res.isErr():
fatal "Could not create data folder", data_dir = dataDir,
errorMsg = ioErrorMsg(res.error), errorCode = $res.error
false
else:
var sd = sres.get()
let res = createPath(dataDir, 0o750, secDescriptor = sd.getDescriptor())
if res.isErr():
fatal "Could not create data folder", data_dir = dataDir,
errorMsg = ioErrorMsg(res.error), errorCode = $res.error
false
else:
true
true
else:
fatal "Unsupported operation system"
return false
@ -373,18 +366,7 @@ proc saveNetKeystore*(rng: var BrHmacDrbgContext, keyStorePath: string,
error "Could not serialize network key storage", key_path = keyStorePath
return err(FailedToCreateKeystoreFile)
let res =
when defined(windows):
let sres = createCurrentUserOnlySecurityDescriptor()
if sres.isErr():
error "Could not allocate security descriptor", key_path = keyStorePath
return err(FailedToCreateKeystoreFile)
var sd = sres.get()
writeFile(keyStorePath, encodedStorage, 0o600,
secDescriptor = sd.getDescriptor())
else:
writeFile(keyStorePath, encodedStorage, 0o600)
let res = secureWriteFile(keyStorePath, encodedStorage)
if res.isOk():
ok()
else:
@ -416,48 +398,22 @@ proc saveKeystore(rng: var BrHmacDrbgContext,
error "Could not serialize keystorage", key_path = keystoreFile
return err(FailedToCreateKeystoreFile)
when defined(windows):
let csres = createCurrentUserOnlySecurityDescriptor()
if csres.isErr():
error "Could not allocate security descriptor", key_path = keystoreFile
return err(FailedToCreateKeystoreFile)
var sd = csres.get()
let vres = secureCreatePath(validatorDir)
if vres.isErr():
return err(FailedToCreateValidatorDir)
let vres = createPath(validatorDir, 0o750,
secDescriptor = sd.getDescriptor())
if vres.isErr():
return err(FailedToCreateValidatorDir)
let sres = secureCreatePath(secretsDir)
if sres.isErr():
return err(FailedToCreateSecretsDir)
let sres = createPath(secretsDir, 0o750,
secDescriptor = sd.getDescriptor())
if sres.isErr():
return err(FailedToCreateSecretsDir)
let swres = secureWriteFile(secretsDir / keyName, password.str)
if swres.isErr():
return err(FailedToCreateSecretFile)
let swres = writeFile(secretsDir / keyName, password.str, 0o600,
secDescriptor = sd.getDescriptor())
if swres.isErr():
return err(FailedToCreateSecretFile)
let kwres = secureWriteFile(keystoreFile, encodedStorage)
if kwres.isErr():
return err(FailedToCreateKeystoreFile)
let kwres = writeFile(keystoreFile, encodedStorage, 0o600,
secDescriptor = sd.getDescriptor())
if kwres.isErr():
return err(FailedToCreateKeystoreFile)
else:
let vres = createPath(validatorDir, 0o750)
if vres.isErr():
return err(FailedToCreateValidatorDir)
let sres = createPath(secretsDir, 0o750)
if sres.isErr():
return err(FailedToCreateSecretsDir)
let swres = writeFile(secretsDir / keyName, password.str, 0o600)
if swres.isErr():
return err(FailedToCreateSecretFile)
let kwres = writeFile(keystoreFile, encodedStorage, 0o600)
if kwres.isErr():
return err(FailedToCreateKeystoreFile)
ok()
proc generateDeposits*(preset: RuntimePreset,
@ -498,26 +454,13 @@ proc saveWallet*(wallet: Wallet, outWalletPath: string): Result[void, string] =
except SerializationError:
return err("Could not serialize wallet")
when defined(windows):
let sres = createCurrentUserOnlySecurityDescriptor()
if sres.isErr():
error "Could not allocate security descriptor"
return err("Could not create security descriptor")
var sd = sres.get()
let pres = createPath(walletDir, 0o750, secDescriptor = sd.getDescriptor())
if pres.isErr():
return err("Could not create wallet directory [" & walletDir & "]")
let wres = writeFile(outWalletPath, encodedWallet, 0o600,
secDescriptor = sd.getDescriptor())
if wres.isErr():
return err("Could not write wallet to file [" & outWalletPath & "]")
else:
let pres = createPath(walletDir, 0o750)
if pres.isErr():
return err("Could not create wallet directory [" & walletDir & "]")
let wres = writeFile(outWalletPath, encodedWallet, 0o600)
if wres.isErr():
return err("Could not write wallet to file [" & outWalletPath & "]")
let pres = secureCreatePath(walletDir)
if pres.isErr():
return err("Could not create wallet directory [" & walletDir & "]")
let wres = secureWriteFile(outWalletPath, encodedWallet)
if wres.isErr():
return err("Could not write wallet to file [" & outWalletPath & "]")
ok()
proc saveWallet*(wallet: WalletPathPair): Result[void, string] =

View File

@ -17,7 +17,7 @@ import
stew/io2,
# Local modules
spec/[datatypes, crypto, helpers], eth2_network, time
spec/[datatypes, crypto, helpers], eth2_network, time, filepath
proc setupStdoutLogging*(logLevel: string) =
when compiles(defaultChroniclesStream.output.writer):
@ -37,7 +37,7 @@ proc setupLogging*(logLevel: string, logFile: Option[OutFile]) =
let
logFile = logFile.get.string
logFileDir = splitFile(logFile).dir
let lres = createPath(logFileDir, 0o750)
let lres = secureCreatePath(logFileDir)
if lres.isErr():
error "Failed to create directory for log file",
path = logFileDir, err = ioErrorMsg(lres.error)

34
scripts/copyfile.sh Normal file
View File

@ -0,0 +1,34 @@
#!/bin/bash
# Copyright (c) 2018-2019 Status Research & Development GmbH. Licensed under
# either of:
# - Apache License, version 2.0
# - MIT license
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
if [[ $OS = "Windows_NT" ]]; then
# Copy file.
cp -a $1 $2
if [ -f "$1" ]; then
DST_FILE=$2
if [ -d "$2" ]; then
SRC_NAME="$(basename -- $1)"
DST_FILE=$(realpath ${2})/$SRC_NAME
fi
# Single file was copied, so we setting file permissions only.
icacls $DST_FILE /inheritance:r /grant:r $USERDOMAIN\\$USERNAME:\(F\);
else
if [ -d "$1" ]; then
SRC_NAME="$(basename -- $1)"
DST_DIR=$(realpath ${2})/$SRC_NAME
DST_FILES=$(realpath ${DST_DIR})/\*
# Directory was copied, so we update destination directory permissions.
icacls $DST_DIR /inheritance:r /grant:r $USERDOMAIN\\$USERNAME:\(OI\)\(CI\)\(F\);
# And update permissions for all files inside of destination directory.
icacls $DST_FILES /inheritance:r /grant:r $USERDOMAIN\\$USERNAME:\(F\);
fi
fi
else
cp -a $1 $2;
fi

View File

@ -12,10 +12,9 @@ then
if [ ! -d "$1" ]; then
# Create full path.
mkdir -p $1;
# Remove all inherited aces from path $1 ACL.
icacls $1 /inheritance:r &> /dev/null;
# Grant full access rights to current user only in $1 ACL.
icacls $1 /grant:r $USERDOMAIN\\$USERNAME:\(OI\)\(CI\)F &> /dev/null;
# Remove all inherited aces from path $1 ACL and grant full access rights
# to current user only in $1 ACL.
icacls $1 /inheritance:r /grant:r $USERDOMAIN\\$USERNAME:\(OI\)\(CI\)\(F\)&>/dev/null;
fi
else
# Create full path with 0750 permissions.

View File

@ -42,6 +42,8 @@ cd "$GIT_ROOT"
NODE_DATA_DIR="${SIMULATION_DIR}/node-$NODE_ID"
NODE_VALIDATORS_DIR=$NODE_DATA_DIR/validators/
NODE_SECRETS_DIR=$NODE_DATA_DIR/secrets/
MAKEDIR=$GIT_ROOT/scripts/makedir.sh
COPYFILE=$GIT_ROOT/scripts/copyfile.sh
PORT=$(( BASE_P2P_PORT + NODE_ID ))
@ -50,13 +52,13 @@ if [ "${NAT:-}" == "1" ]; then
NAT_ARG="--nat:any"
fi
mkdir -m 0700 -p "$NODE_DATA_DIR"
"$MAKEDIR" "$NODE_DATA_DIR"
rm -rf "$NODE_VALIDATORS_DIR"
mkdir -m 0700 "$NODE_VALIDATORS_DIR"
"$MAKEDIR" "$NODE_VALIDATORS_DIR"
rm -rf "$NODE_SECRETS_DIR"
mkdir -m 0700 "$NODE_SECRETS_DIR"
"$MAKEDIR" "$NODE_SECRETS_DIR"
VALIDATORS_PER_NODE=$(( NUM_VALIDATORS / (TOTAL_NODES - 1) ))
if [ "${USE_BN_VC_VALIDATOR_SPLIT:-}" == "yes" ]; then
@ -69,14 +71,14 @@ fi
if [[ $NODE_ID -lt $BOOTSTRAP_NODE ]]; then
pushd "$VALIDATORS_DIR" >/dev/null
for VALIDATOR in $(ls | tail -n +$(( ($VALIDATORS_PER_NODE * $NODE_ID) + 1 )) | head -n $VALIDATORS_PER_NODE); do
cp -a "$VALIDATOR" "$NODE_VALIDATORS_DIR"
cp -a "$SECRETS_DIR/$VALIDATOR" "$NODE_SECRETS_DIR"
"$COPYFILE" "$VALIDATOR" "$NODE_VALIDATORS_DIR"
"$COPYFILE" "$SECRETS_DIR/$VALIDATOR" "$NODE_SECRETS_DIR"
done
popd >/dev/null
fi
rm -rf "$NODE_DATA_DIR/dump"
mkdir -m 0700 "$NODE_DATA_DIR/dump"
"$MAKEDIR" "$NODE_DATA_DIR/dump"
SNAPSHOT_ARG=""
if [ -f "${SNAPSHOT_FILE}" ]; then

View File

@ -18,12 +18,14 @@ cd "$GIT_ROOT"
NODE_DATA_DIR="${SIMULATION_DIR}/validator-$NODE_ID"
NODE_VALIDATORS_DIR=$NODE_DATA_DIR/validators/
NODE_SECRETS_DIR=$NODE_DATA_DIR/secrets/
MAKEDIR=$GIT_ROOT/scripts/makedir.sh
COPYFILE=$GIT_ROOT/scripts/copyfile.sh
rm -rf "$NODE_VALIDATORS_DIR"
mkdir -p "$NODE_VALIDATORS_DIR"
"$MAKEDIR" "$NODE_VALIDATORS_DIR"
rm -rf "$NODE_SECRETS_DIR"
mkdir -p "$NODE_SECRETS_DIR"
"$MAKEDIR" "$NODE_SECRETS_DIR"
# we will split the keys for this instance in half between the BN and the VC
# and the validators for the VCs will be from the second half of all validators
@ -34,8 +36,8 @@ if [[ $NODE_ID -lt $TOTAL_NODES ]]; then
pushd "$VALIDATORS_DIR" >/dev/null
for VALIDATOR in $(ls | tail -n +$(( $VALIDATOR_OFFSET + ($VALIDATORS_PER_NODE * $NODE_ID) + 1 )) | head -n $VALIDATORS_PER_NODE); do
cp -a "$VALIDATOR" "$NODE_VALIDATORS_DIR"
cp -a "$SECRETS_DIR/$VALIDATOR" "$NODE_SECRETS_DIR"
"$COPYFILE" "$VALIDATOR" "$NODE_VALIDATORS_DIR"
"$COPYFILE" "$SECRETS_DIR/$VALIDATOR" "$NODE_SECRETS_DIR"
done
popd >/dev/null
fi

2
vendor/nim-stew vendored

@ -1 +1 @@
Subproject commit 7018fb0b5ec9bdf7795d4834a15f8967dd5910a4
Subproject commit bc3b4cf2de880260adeec8b082778730f878d56e