Merge pull request #225 from VakarisZ/deployment_scripts

Deployment scripts
This commit is contained in:
Daniel Goldberg 2018-12-10 13:22:05 +02:00 committed by GitHub
commit 09538de4b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 464 additions and 2 deletions

View File

@ -44,7 +44,8 @@ Check out the [Setup](https://github.com/guardicore/monkey/wiki/setup) page in t
Building the Monkey from source
-------------------------------
If you want to build the monkey from source, see [Setup](https://github.com/guardicore/monkey/wiki/Setup#compile-it-yourself)
To deploy development version of monkey you should refer to readme in the [deployment scripts](deployment_scripts) folder.
If you only want to build the monkey from source, see [Setup](https://github.com/guardicore/monkey/wiki/Setup#compile-it-yourself)
and follow the instructions at the readme files under [infection_monkey](infection_monkey) and [monkey_island](monkey_island).

View File

@ -0,0 +1,21 @@
# Files used to deploy development version of infection monkey
On windows:<br>
Before running the script you must have git installed.<br>
Cd to scripts directory and use the scripts.<br>
First argument is an empty directory (script can create one) and second is branch you want to clone.
Example usages:<br>
./run_script.bat (Sets up monkey in current directory under .\infection_monkey)<br>
./run_script.bat "C:\test" (Sets up monkey in C:\test)<br>
powershell -ExecutionPolicy ByPass -Command ". .\deploy_windows.ps1; Deploy-Windows -monkey_home C:\test" (Same as above)<br>
./run_script.bat "" "master"(Sets up master branch instead of develop in current dir)
Don't forget to add python to PATH or do so while installing it via this script.<br>
On Linux:<br>
You must have root permissions, but don't run the script as root.<br>
Launch deploy_linux.sh from scripts directory.<br>
First argument is an empty directory (script can create one) and second is branch you want to clone.
Example usages:<br>
./deploy_linux.sh (deploys under ./infection_monkey)<br>
./deploy_linux.sh "/home/test/monkey" (deploys under /home/test/monkey)<br>
./deploy_linux.sh "" "master" (deploys master branch in script directory)<br>
./deploy_linux.sh "/home/user/new" "master" (if directory "new" is not found creates it and clones master branch into it)<br>

19
deployment_scripts/config Normal file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Absolute monkey's path
MONKEY_FOLDER_NAME="infection_monkey"
# Url of public git repository that contains monkey's source code
MONKEY_GIT_URL="https://github.com/guardicore/monkey"
# Monkey binaries
LINUX_32_BINARY_URL="https://github.com/guardicore/monkey/releases/download/1.6/monkey-linux-32"
LINUX_32_BINARY_NAME="monkey-linux-32"
LINUX_64_BINARY_URL="https://github.com/guardicore/monkey/releases/download/1.6/monkey-linux-64"
LINUX_64_BINARY_NAME="monkey-linux-64"
WINDOWS_32_BINARY_URL="https://github.com/guardicore/monkey/releases/download/1.6/monkey-windows-32.exe"
WINDOWS_32_BINARY_NAME="monkey-windows-32.exe"
WINDOWS_64_BINARY_URL="https://github.com/guardicore/monkey/releases/download/1.6/monkey-windows-64.exe"
WINDOWS_64_BINARY_NAME="monkey-windows-64.exe"
# Mongo url's
MONGO_DEBIAN_URL="https://downloads.mongodb.org/linux/mongodb-linux-x86_64-debian81-latest.tgz"
MONGO_UBUNTU_URL="https://downloads.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-latest.tgz"

View File

@ -0,0 +1,48 @@
# Absolute monkey's path
$MONKEY_FOLDER_NAME = "infection_monkey"
# Url of public git repository that contains monkey's source code
$MONKEY_GIT_URL = "https://github.com/guardicore/monkey"
# Link to the latest python download or install it manually
$PYTHON_URL = "https://www.python.org/ftp/python/2.7.13/python-2.7.13.amd64.msi"
# Monkey binaries
$LINUX_32_BINARY_URL = "https://github.com/guardicore/monkey/releases/download/1.6/monkey-linux-32"
$LINUX_32_BINARY_PATH = "monkey-linux-32"
$LINUX_64_BINARY_URL = "https://github.com/guardicore/monkey/releases/download/1.6/monkey-linux-64"
$LINUX_64_BINARY_PATH = "monkey-linux-64"
$WINDOWS_32_BINARY_URL = "https://github.com/guardicore/monkey/releases/download/1.6/monkey-windows-32.exe"
$WINDOWS_32_BINARY_PATH = "monkey-windows-32.exe"
$WINDOWS_64_BINARY_URL = "https://github.com/guardicore/monkey/releases/download/1.6/monkey-windows-64.exe"
$WINDOWS_64_BINARY_PATH = "monkey-windows-64.exe"
$SAMBA_32_BINARY_URL = "https://github.com/VakarisZ/tempBinaries/raw/master/sc_monkey_runner32.so"
$SAMBA_32_BINARY_NAME= "sc_monkey_runner32.so"
$SAMBA_64_BINARY_URL = "https://github.com/VakarisZ/tempBinaries/raw/master/sc_monkey_runner64.so"
$SAMBA_64_BINARY_NAME = "sc_monkey_runner64.so"
# Other directories and paths ( most likely you dont need to configure)
$MONKEY_ISLAND_DIR = "\monkey\monkey_island"
$MONKEY_DIR = "\monkey\infection_monkey"
$SAMBA_BINARIES_DIR = Join-Path -Path $MONKEY_DIR -ChildPath "\monkey_utils\sambacry_monkey_runner"
$PYTHON_DLL = "C:\Windows\System32\python27.dll"
$MK32_DLL = "mk32.dll"
$MK64_DLL = "mk64.dll"
$TEMP_PYTHON_INSTALLER = ".\python.msi"
$TEMP_MONGODB_ZIP = ".\mongodb.zip"
$TEMP_OPEN_SSL_ZIP = ".\openssl.zip"
$TEMP_CPP_INSTALLER = "cpp.exe"
$TEMP_NPM_INSTALLER = "node.msi"
$TEMP_PYWIN32_INSTALLER = "pywin32.exe"
$TEMP_UPX_ZIP = "upx.zip"
$TEMP_VC_FOR_PYTHON27_INSTALLER = "vcforpython.msi"
$UPX_FOLDER = "upx394w"
# Other url's
$VC_FOR_PYTHON27_URL = "https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi"
$MONGODB_URL = "https://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-latest.zip"
$OPEN_SSL_URL = "https://indy.fulgan.com/SSL/Archive/openssl-1.0.2l-i386-win32.zip"
$CPP_URL = "https://go.microsoft.com/fwlink/?LinkId=746572"
$NPM_URL = "https://nodejs.org/dist/v10.13.0/node-v10.13.0-x64.msi"
$PYWIN32_URL = "https://github.com/mhammond/pywin32/releases/download/b224/pywin32-224.win-amd64-py2.7.exe"
$UPX_URL = "https://github.com/upx/upx/releases/download/v3.94/upx394w.zip"
$MK32_DLL_URL = "https://github.com/guardicore/mimikatz/releases/download/1.1.0/mk32.dll"
$MK64_DLL_URL = "https://github.com/guardicore/mimikatz/releases/download/1.1.0/mk64.dll"

View File

@ -0,0 +1,146 @@
#!/bin/bash
source config
# Setup monkey either in dir required or current dir
monkey_home=${1:-`pwd`}
if [[ $monkey_home == `pwd` ]]; then
monkey_home="$monkey_home/$MONKEY_FOLDER_NAME"
fi
# We can set main paths after we know the home dir
ISLAND_PATH="$monkey_home/monkey/monkey_island"
MONKEY_COMMON_PATH="$monkey_home/monkey/common/"
MONGO_PATH="$ISLAND_PATH/bin/mongodb"
MONGO_BIN_PATH="$MONGO_PATH/bin"
ISLAND_DB_PATH="$ISLAND_PATH/db"
ISLAND_BINARIES_PATH="$ISLAND_PATH/cc/binaries"
handle_error () {
echo "Fix the errors above and rerun the script"
exit 1
}
log_message () {
echo -e "\n\n-------------------------------------------"
echo -e "DEPLOYMENT SCRIPT: $1"
echo -e "-------------------------------------------\n"
}
sudo -v
if [[ $? != 0 ]]; then
echo "You need root permissions for some of this script operations. Quiting."
exit 1
fi
if [[ ! -d ${monkey_home} ]]; then
mkdir -p ${monkey_home}
fi
git --version &>/dev/null
git_available=$?
if [[ ${git_available} != 0 ]]; then
echo "Please install git and re-run this script"
exit 1
fi
log_message "Cloning files from git"
branch=${2:-"develop"}
if [[ ! -d "$monkey_home/monkey" ]]; then # If not already cloned
git clone --single-branch -b $branch ${MONKEY_GIT_URL} ${monkey_home} 2>&1 || handle_error
chmod 774 -R ${monkey_home}
fi
# Create folders
log_message "Creating island dirs under $ISLAND_PATH"
mkdir -p ${MONGO_BIN_PATH}
mkdir -p ${ISLAND_DB_PATH}
mkdir -p ${ISLAND_BINARIES_PATH} || handle_error
python_version=`python --version 2>&1`
if [[ ${python_version} == *"command not found"* ]] || [[ ${python_version} != *"Python 2.7"* ]]; then
echo "Python 2.7 is not found or is not a default interpreter for 'python' command..."
exit 1
fi
log_message "Installing island requirements"
requirements="$ISLAND_PATH/requirements.txt"
python -m pip install --user -r ${requirements} || handle_error
# Download binaries
log_message "Downloading binaries"
wget -c -N -P ${ISLAND_BINARIES_PATH} ${LINUX_32_BINARY_URL}
wget -c -N -P ${ISLAND_BINARIES_PATH} ${LINUX_64_BINARY_URL}
wget -c -N -P ${ISLAND_BINARIES_PATH} ${WINDOWS_32_BINARY_URL}
wget -c -N -P ${ISLAND_BINARIES_PATH} ${WINDOWS_64_BINARY_URL}
# Allow them to be executed
chmod a+x "$ISLAND_BINARIES_PATH/$LINUX_32_BINARY_NAME"
chmod a+x "$ISLAND_BINARIES_PATH/$LINUX_64_BINARY_NAME"
chmod a+x "$ISLAND_BINARIES_PATH/$WINDOWS_32_BINARY_NAME"
chmod a+x "$ISLAND_BINARIES_PATH/$WINDOWS_64_BINARY_NAME"
# Get machine type/kernel version
kernel=`uname -m`
linux_dist=`lsb_release -a 2> /dev/null`
# If a user haven't installed mongo manually check if we can install it with our script
if [[ ! -f "$MONGO_BIN_PATH/mongod" ]] && { [[ ${kernel} != "x86_64" ]] || \
{ [[ ${linux_dist} != *"Debian"* ]] && [[ ${linux_dist} != *"Ubuntu"* ]]; }; }; then
echo "Script does not support your operating system for mongodb installation.
Reference monkey island readme and install it manually"
exit 1
fi
# Download mongo
if [[ ! -f "$MONGO_BIN_PATH/mongod" ]]; then
log_message "Downloading mongodb"
if [[ ${linux_dist} == *"Debian"* ]]; then
wget -c -N -O "/tmp/mongo.tgz" ${MONGO_DEBIAN_URL}
elif [[ ${linux_dist} == *"Ubuntu"* ]]; then
wget -c -N -O "/tmp/mongo.tgz" ${MONGO_UBUNTU_URL}
fi
tar --strip 2 --wildcards -C ${MONGO_BIN_PATH} -zxvf /tmp/mongo.tgz mongo*/bin/* || handle_error
else
log_message "Mongo db already installed"
fi
log_message "Installing openssl"
sudo apt-get install openssl
# Generate SSL certificate
log_message "Generating certificate"
cd ${ISLAND_PATH} || handle_error
openssl genrsa -out cc/server.key 1024 || handle_error
openssl req -new -key cc/server.key -out cc/server.csr \
-subj "/C=GB/ST=London/L=London/O=Global Security/OU=Monkey Department/CN=monkey.com" || handle_error
openssl x509 -req -days 366 -in cc/server.csr -signkey cc/server.key -out cc/server.crt || handle_error
chmod +x ${ISLAND_PATH}/linux/create_certificate.sh || handle_error
${ISLAND_PATH}/linux/create_certificate.sh || handle_error
# Install npm
log_message "Installing npm"
sudo apt-get install npm
log_message "Generating front end"
cd "$ISLAND_PATH/cc/ui" || handle_error
npm update
npm run dist
# Monkey setup
log_message "Installing monkey requirements"
sudo apt-get install python-pip python-dev libffi-dev upx libssl-dev libc++1
cd ${monkey_home}/monkey/infection_monkey || handle_error
python -m pip install --user -r requirements.txt || handle_error
# Build samba
log_message "Building samba binaries"
sudo apt-get install gcc-multilib
cd ${monkey_home}/monkey/infection_monkey/monkey_utils/sambacry_monkey_runner
chmod +x ./build.sh || handle_error
./build.sh
chmod +x ${monkey_home}/monkey/infection_monkey/build_linux.sh
log_message "Deployment script finished."
exit 0

View File

@ -0,0 +1,215 @@
function Deploy-Windows([String] $monkey_home = (Get-Item -Path ".\").FullName, [String] $branch = "develop"){
# Import the config variables
. ./config.ps1
"Config variables from config.ps1 imported"
# If we want monkey in current dir we need to create an empty folder for source files
if ( (Join-Path $monkey_home '') -eq (Join-Path (Get-Item -Path ".\").FullName '') ){
$monkey_home = Join-Path -Path $monkey_home -ChildPath $MONKEY_FOLDER_NAME
}
# Set variables for script execution
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webClient = New-Object System.Net.WebClient
# We check if git is installed
try
{
git | Out-Null -ErrorAction Stop
"Git requirement satisfied"
}
catch [System.Management.Automation.CommandNotFoundException]
{
"Please install git before running this script or add it to path and restart cmd"
return
}
# Download the monkey
$output = cmd.exe /c "git clone --single-branch -b $branch $MONKEY_GIT_URL $monkey_home 2>&1"
$binDir = (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\bin")
if ( $output -like "*already exists and is not an empty directory.*"){
"Assuming you already have the source directory. If not, make sure to set an empty directory as monkey's home directory."
} elseif ($output -like "fatal:*"){
"Error while cloning monkey from the repository:"
$output
return
} else {
"Monkey cloned from the repository"
# Create bin directory
New-Item -ItemType directory -path $binDir
"Bin directory added"
}
# We check if python is installed
try
{
$version = cmd.exe /c '"python" --version 2>&1'
if ( $version -like 'Python 2.7.*' ) {
"Python 2.7.* was found, installing dependancies"
} else {
throw System.Management.Automation.CommandNotFoundException
}
}
catch [System.Management.Automation.CommandNotFoundException]
{
"Downloading python 2.7 ..."
$webClient.DownloadFile($PYTHON_URL, $TEMP_PYTHON_INSTALLER)
Start-Process -Wait $TEMP_PYTHON_INSTALLER -ErrorAction Stop
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
Remove-Item $TEMP_PYTHON_INSTALLER
# Check if installed correctly
$version = cmd.exe /c '"python" --version 2>&1'
if ( $version -like '* is not recognized*' ) {
"Python is not found in PATH. Add it manually or reinstall python."
return
}
}
# Set python home dir
$PYTHON_PATH = Split-Path -Path (Get-Command python | Select-Object -ExpandProperty Source)
# Get vcforpython27 before installing requirements
"Downloading Visual C++ Compiler for Python 2.7 ..."
$webClient.DownloadFile($VC_FOR_PYTHON27_URL, $TEMP_VC_FOR_PYTHON27_INSTALLER)
Start-Process -Wait $TEMP_VC_FOR_PYTHON27_INSTALLER -ErrorAction Stop
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
Remove-Item $TEMP_VC_FOR_PYTHON27_INSTALLER
# Install requirements for island
$islandRequirements = Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\requirements.txt" -ErrorAction Stop
"Upgrading pip..."
$output = cmd.exe /c 'python -m pip install --user --upgrade pip 2>&1'
$output
if ( $output -like '*No module named pip*' ) {
"Make sure pip module is installed and re-run this script."
return
}
& python -m pip install --user -r $islandRequirements
# Install requirements for monkey
$monkeyRequirements = Join-Path -Path $monkey_home -ChildPath $MONKEY_DIR | Join-Path -ChildPath "\requirements.txt"
& python -m pip install --user -r $monkeyRequirements
# Download mongodb
if(!(Test-Path -Path (Join-Path -Path $binDir -ChildPath "mongodb") )){
"Downloading mongodb ..."
$webClient.DownloadFile($MONGODB_URL, $TEMP_MONGODB_ZIP)
"Unzipping mongodb"
Expand-Archive $TEMP_MONGODB_ZIP -DestinationPath $binDir
# Get unzipped folder's name
$mongodb_folder = Get-ChildItem -Path $binDir | Where-Object -FilterScript {($_.Name -like "mongodb*")} | Select-Object -ExpandProperty Name
# Move all files from extracted folder to mongodb folder
New-Item -ItemType directory -Path (Join-Path -Path $binDir -ChildPath "mongodb")
New-Item -ItemType directory -Path (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "db")
"Moving extracted files"
Move-Item -Path (Join-Path -Path $binDir -ChildPath $mongodb_folder | Join-Path -ChildPath "\bin\*") -Destination (Join-Path -Path $binDir -ChildPath "mongodb\")
"Removing zip file"
Remove-Item $TEMP_MONGODB_ZIP
Remove-Item (Join-Path -Path $binDir -ChildPath $mongodb_folder) -Recurse
}
# Download OpenSSL
"Downloading OpenSSL ..."
$webClient.DownloadFile($OPEN_SSL_URL, $TEMP_OPEN_SSL_ZIP)
"Unzipping OpenSSl"
Expand-Archive $TEMP_OPEN_SSL_ZIP -DestinationPath (Join-Path -Path $binDir -ChildPath "openssl") -ErrorAction SilentlyContinue
"Removing zip file"
Remove-Item $TEMP_OPEN_SSL_ZIP
# Download and install C++ redistributable
"Downloading C++ redistributable ..."
$webClient.DownloadFile($CPP_URL, $TEMP_CPP_INSTALLER)
Start-Process -Wait $TEMP_CPP_INSTALLER -ErrorAction Stop
Remove-Item $TEMP_CPP_INSTALLER
# Generate ssl certificate
"Generating ssl certificate"
Push-Location -Path (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR)
. .\windows\create_certificate.bat
Pop-Location
# Adding binaries
"Adding binaries"
$binaries = (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\cc\binaries")
New-Item -ItemType directory -path $binaries -ErrorAction SilentlyContinue
$webClient.DownloadFile($LINUX_32_BINARY_URL, (Join-Path -Path $binaries -ChildPath $LINUX_32_BINARY_PATH))
$webClient.DownloadFile($LINUX_64_BINARY_URL, (Join-Path -Path $binaries -ChildPath $LINUX_64_BINARY_PATH))
$webClient.DownloadFile($WINDOWS_32_BINARY_URL, (Join-Path -Path $binaries -ChildPath $WINDOWS_32_BINARY_PATH))
$webClient.DownloadFile($WINDOWS_64_BINARY_URL, (Join-Path -Path $binaries -ChildPath $WINDOWS_64_BINARY_PATH))
# Check if NPM installed
"Installing npm"
try
{
$version = cmd.exe /c '"npm" --version 2>&1'
if ( $version -like "*is not recognized*"){
throw System.Management.Automation.CommandNotFoundException
} else {
"Npm already installed"
}
}
catch [System.Management.Automation.CommandNotFoundException]
{
"Downloading npm ..."
$webClient.DownloadFile($NPM_URL, $TEMP_NPM_INSTALLER)
Start-Process -Wait $TEMP_NPM_INSTALLER
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
Remove-Item $TEMP_NPM_INSTALLER
}
"Updating npm"
Push-Location -Path (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\cc\ui")
& npm update
& npm run dist
Pop-Location
# Install pywin32
"Downloading pywin32"
$webClient.DownloadFile($PYWIN32_URL, $TEMP_PYWIN32_INSTALLER)
Start-Process -Wait $TEMP_PYWIN32_INSTALLER -ErrorAction Stop
Remove-Item $TEMP_PYWIN32_INSTALLER
# Create infection_monkey/bin directory if not already present
$binDir = (Join-Path -Path $monkey_home -ChildPath $MONKEY_DIR | Join-Path -ChildPath "\bin")
New-Item -ItemType directory -path $binaries -ErrorAction SilentlyContinue
# Download upx
if(!(Test-Path -Path (Join-Path -Path $binDir -ChildPath "upx.exe") )){
"Downloading upx ..."
$webClient.DownloadFile($UPX_URL, $TEMP_UPX_ZIP)
"Unzipping upx"
Expand-Archive $TEMP_UPX_ZIP -DestinationPath $binDir -ErrorAction SilentlyContinue
Move-Item -Path (Join-Path -Path $binDir -ChildPath $UPX_FOLDER | Join-Path -ChildPath "upx.exe") -Destination $binDir
# Remove unnecessary files
Remove-Item -Recurse -Force (Join-Path -Path $binDir -ChildPath $UPX_FOLDER)
"Removing zip file"
Remove-Item $TEMP_UPX_ZIP
}
# Download mimikatz binaries
$mk32_path = Join-Path -Path $binDir -ChildPath $MK32_DLL
if(!(Test-Path -Path $mk32_path )){
"Downloading mimikatz 32 binary"
$webClient.DownloadFile($MK32_DLL_URL, $mk32_path)
}
$mk64_path = Join-Path -Path $binDir -ChildPath $MK64_DLL
if(!(Test-Path -Path $mk64_path )){
"Downloading mimikatz 64 binary"
$webClient.DownloadFile($MK64_DLL_URL, $mk64_path)
}
# Download sambacry binaries
$samba_path = Join-Path -Path $monkey_home -ChildPath $SAMBA_BINARIES_DIR
$samba32_path = Join-Path -Path $samba_path -ChildPath $SAMBA_32_BINARY_NAME
if(!(Test-Path -Path $samba32_path )){
"Downloading sambacry 32 binary"
$webClient.DownloadFile($SAMBA_32_BINARY_URL, $samba32_path)
}
$samba64_path = Join-Path -Path $samba_path -ChildPath $SAMBA_64_BINARY_NAME
if(!(Test-Path -Path $samba64_path )){
"Downloading sambacry 64 binary"
$webClient.DownloadFile($SAMBA_64_BINARY_URL, $samba64_path)
}
"Script finished"
}

View File

@ -0,0 +1,8 @@
SET command=. .\deploy_windows.ps1; Deploy-Windows
if NOT "%~1" == "" (
SET "command=%command% -monkey_home %~1"
)
if NOT "%~2" == "" (
SET "command=%command% -branch %~2"
)
powershell -ExecutionPolicy ByPass -Command %command%

View File

@ -1,4 +1,5 @@
How to build a monkey binary from scratch.
To get development versions of Monkey Island and Monkey look into deployment scripts folder.
If you only want to monkey from scratch you may refer to the instructions below.
The monkey is composed of three separate parts.
* The Infection Monkey itself - PyInstaller compressed python archives

View File

@ -1,3 +1,6 @@
To get development versions of Monkey Island and Monkey look into deployment scripts folder.
If you only want to run the software from source you may refer to the instructions below.
How to set up the Monkey Island server:
---------------- On Windows ----------------: