forked from p15670423/monkey
Fixed, improved and tested configuration import and export.
This commit is contained in:
parent
8b86e40259
commit
500f270aa9
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from json.decoder import JSONDecodeError
|
||||||
|
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import request
|
from flask import request
|
||||||
|
@ -35,8 +36,11 @@ class ConfigurationImport(flask_restful.Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
request_contents = json.loads(request.data)
|
request_contents = json.loads(request.data)
|
||||||
try:
|
try:
|
||||||
decrypt_config(request_contents["config"], request_contents["password"])
|
try:
|
||||||
ConfigurationImport.import_config(request_contents["config"])
|
config = json.loads(request_contents["config"])
|
||||||
|
except JSONDecodeError:
|
||||||
|
config = decrypt_config(request_contents["config"], request_contents["password"])
|
||||||
|
ConfigurationImport.import_config(config)
|
||||||
return ResponseContents().form_response()
|
return ResponseContents().form_response()
|
||||||
except InvalidCredentialsError:
|
except InvalidCredentialsError:
|
||||||
return ResponseContents(
|
return ResponseContents(
|
||||||
|
|
|
@ -31,12 +31,7 @@ def decrypt_config(cyphertext: Union[str, dict], password: str) -> Dict:
|
||||||
if not password:
|
if not password:
|
||||||
raise NoCredentialsError
|
raise NoCredentialsError
|
||||||
|
|
||||||
try:
|
cyphertext = base64.b64decode(cyphertext)
|
||||||
cyphertext = base64.b64decode(cyphertext)
|
|
||||||
except TypeError:
|
|
||||||
logger.info("Configuration doesn't require decryption.")
|
|
||||||
return cyphertext
|
|
||||||
|
|
||||||
ciphertext_config_stream = io.BytesIO(cyphertext)
|
ciphertext_config_stream = io.BytesIO(cyphertext)
|
||||||
dec_plaintext_config_stream = io.BytesIO()
|
dec_plaintext_config_stream = io.BytesIO()
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,14 @@ const ConfigImportModal = (props: Props) => {
|
||||||
const configImportEndpoint = '/api/configuration/import';
|
const configImportEndpoint = '/api/configuration/import';
|
||||||
|
|
||||||
const [uploadStatus, setUploadStatus] = useState(UploadStatuses.clean);
|
const [uploadStatus, setUploadStatus] = useState(UploadStatuses.clean);
|
||||||
const [configContents, setConfigContents] = useState('');
|
const [configContents, setConfigContents] = useState(null);
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [errorMessage, setErrorMessage] = useState('');
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
const authComponent = new AuthComponent({});
|
const authComponent = new AuthComponent({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (configContents !== '') {
|
if (configContents !== null) {
|
||||||
sendConfigToServer();
|
sendConfigToServer();
|
||||||
}
|
}
|
||||||
}, [configContents])
|
}, [configContents])
|
||||||
|
@ -54,7 +54,6 @@ const ConfigImportModal = (props: Props) => {
|
||||||
} else {
|
} else {
|
||||||
setUploadStatus(UploadStatuses.success);
|
setUploadStatus(UploadStatuses.success);
|
||||||
}
|
}
|
||||||
console.log(res['import_status']);
|
|
||||||
return res['import_status'];
|
return res['import_status'];
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -66,7 +65,7 @@ const ConfigImportModal = (props: Props) => {
|
||||||
function resetState() {
|
function resetState() {
|
||||||
setUploadStatus(UploadStatuses.clean);
|
setUploadStatus(UploadStatuses.clean);
|
||||||
setPassword('');
|
setPassword('');
|
||||||
setConfigContents('');
|
setConfigContents(null);
|
||||||
setErrorMessage('');
|
setErrorMessage('');
|
||||||
setShowPassword(false);
|
setShowPassword(false);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +73,7 @@ const ConfigImportModal = (props: Props) => {
|
||||||
function uploadFile(event) {
|
function uploadFile(event) {
|
||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
reader.onload = (event) => {
|
reader.onload = (event) => {
|
||||||
setConfigContents(JSON.stringify(event.target.result))
|
setConfigContents(event.target.result);
|
||||||
};
|
};
|
||||||
reader.readAsText(event.target.files[0]);
|
reader.readAsText(event.target.files[0]);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from tests.unit_tests.monkey_island.cc.services.utils.cyphertexts_for_encryption
|
||||||
MALFORMED_CYPHER_TEXT_TOO_SHORT,
|
MALFORMED_CYPHER_TEXT_TOO_SHORT,
|
||||||
)
|
)
|
||||||
|
|
||||||
from common.utils.exceptions import InvalidCredentialsError
|
from common.utils.exceptions import InvalidCredentialsError, NoCredentialsError
|
||||||
from monkey_island.cc.services.utils.config_encryption import decrypt_config, encrypt_config
|
from monkey_island.cc.services.utils.config_encryption import decrypt_config, encrypt_config
|
||||||
|
|
||||||
MONKEY_CONFIGS_DIR_PATH = "monkey_configs"
|
MONKEY_CONFIGS_DIR_PATH = "monkey_configs"
|
||||||
|
@ -43,5 +43,7 @@ def test_encrypt_decrypt_config__malformed():
|
||||||
decrypt_config(MALFORMED_CYPHER_TEXT_CORRUPTED, PASSWORD)
|
decrypt_config(MALFORMED_CYPHER_TEXT_CORRUPTED, PASSWORD)
|
||||||
|
|
||||||
|
|
||||||
def test_decrypt_config__unencrypted(plaintext_config):
|
def test_decrypt_config__no_password(plaintext_config):
|
||||||
assert plaintext_config == decrypt_config(plaintext_config, PASSWORD)
|
encrypted_config = encrypt_config(plaintext_config, PASSWORD)
|
||||||
|
with pytest.raises(NoCredentialsError):
|
||||||
|
decrypt_config(encrypted_config, "")
|
||||||
|
|
Loading…
Reference in New Issue