mirror of https://github.com/MISP/MISP
Merge branch '2.4' into tools
commit
ceacaf56d1
|
@ -53,6 +53,9 @@ tools/mkdocs
|
|||
!/app/files/scripts/mispzmq/mispzmqtest.py
|
||||
/app/files/scripts/tmp/*
|
||||
!/app/files/scripts/tmp/empty
|
||||
/app/files/scripts/stix2/*
|
||||
!/app/files/scripts/stix2/misp2stix2*.py
|
||||
!/app/files/scripts/stix2/stix2misp*.py
|
||||
!/app/files/empty
|
||||
/app/files/terms/*
|
||||
!/app/files/terms/empty
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
url = https://github.com/MISP/misp-vagrant.git
|
||||
[submodule "cti-python-stix2"]
|
||||
path = cti-python-stix2
|
||||
url = https://github.com/oasis-open/cti-python-stix2
|
||||
url = https://github.com/MISP/cti-python-stix2
|
||||
[submodule "app/files/noticelists"]
|
||||
path = app/files/noticelists
|
||||
url = https://github.com/MISP/misp-noticelist
|
||||
|
@ -37,3 +37,12 @@
|
|||
path = Plugin/DebugKit
|
||||
url = https://github.com/cakephp/debug_kit.git
|
||||
branch = 2.2
|
||||
[submodule "INSTALL/Crypt_GPG"]
|
||||
path = INSTALL/dependencies/Crypt_GPG
|
||||
url = https://github.com/pear/Crypt_GPG
|
||||
[submodule "INSTALL/Console_CommandLine"]
|
||||
path = INSTALL/dependencies/Console_CommandLine
|
||||
url = https://github.com/pear/Console_CommandLine
|
||||
[submodule "INSTALL/dependencies/Net_GeoIP"]
|
||||
path = INSTALL/dependencies/Net_GeoIP
|
||||
url = https://github.com/pear/Net_GeoIP
|
||||
|
|
16
.travis.yml
16
.travis.yml
|
@ -4,6 +4,7 @@ php:
|
|||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
- nightly
|
||||
|
||||
services:
|
||||
|
@ -34,6 +35,7 @@ install:
|
|||
- sudo pip3.6 install --upgrade pip setuptools requests
|
||||
- hash -r
|
||||
- sudo pip3.6 install --upgrade -r requirements.txt
|
||||
- sudo pip3.6 install pipenv
|
||||
- phpenv rehash
|
||||
- pushd app
|
||||
- composer install
|
||||
|
@ -110,20 +112,18 @@ script:
|
|||
- ./curl_tests.sh $AUTH
|
||||
- popd
|
||||
- pushd PyMISP
|
||||
- sudo pip3.6 install nose python-dateutil
|
||||
- sudo pip3.6 install git+https://github.com/kbandla/pydeep.git
|
||||
- sudo pip3.6 install -e .[fileobjects,neo,openioc,virustotal]
|
||||
- pipenv install -d
|
||||
- pushd tests
|
||||
- git clone https://github.com/viper-framework/viper-test-files.git
|
||||
- popd
|
||||
- python3.6 tests/test.py
|
||||
- python3.6 tests/test_mispevent.py
|
||||
- python3.6 tests/test_offline.py
|
||||
- python3.6 tests/testlive_comprehensive.py
|
||||
- pipenv run python tests/test.py
|
||||
- pipenv run python tests/test_mispevent.py
|
||||
- pipenv run python tests/test_offline.py
|
||||
- pipenv run python tests/testlive_comprehensive.py
|
||||
- popd
|
||||
- cp PyMISP/tests/keys.py PyMISP/examples/events/
|
||||
- pushd PyMISP/examples/events/
|
||||
- python3.6 ./create_massive_dummy_events.py -l 5 -a 30
|
||||
- pipenv run python ./create_massive_dummy_events.py -l 5 -a 30
|
||||
- popd
|
||||
- pushd app/files/feed-metadata
|
||||
- jsonschema -i defaults.json schema.json
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,695 @@
|
|||
#!/usr/bin/env bash
|
||||
############################################################
|
||||
###### #
|
||||
##### Please AutoGenerated... ##
|
||||
#### Do NOT was ###
|
||||
### Manually It ####
|
||||
## Change this Script... #####
|
||||
# ######
|
||||
############################################################
|
||||
############################################################
|
||||
#INSTALLATION INSTRUCTIONS #
|
||||
##########################################################
|
||||
#------------------------- for Debian Flavored Linux Distributions
|
||||
#
|
||||
#-------------------------------------------------------|
|
||||
# 0/ Quick MISP Instance on Debian Based Linux - Status |
|
||||
#-------------------------------------------------------|
|
||||
#
|
||||
# 20190208: Kali Linux tested and working.
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------|
|
||||
# 1/ For Kali, download and run Installer Script |
|
||||
#-------------------------------------------------------|
|
||||
#
|
||||
# To install MISP on Kali copy paste the following to your r00t shell:
|
||||
# # wget -O /tmp/misp-kali.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.debian.sh && bash /tmp/misp-kali.sh
|
||||
# /!\ Please read the installer script before randomly doing the above.
|
||||
# The script is tested on a plain vanilla Kali Linux Boot CD and installs quite a few dependencies.
|
||||
#
|
||||
#
|
||||
#---------------------------------------------------------------------------------------------|
|
||||
# 2/ For other Debian based Linux distributions, download script and run as unprivileged user |
|
||||
#---------------------------------------------------------------------------------------------|
|
||||
#
|
||||
# $ wget -O ~/INSTALL.debian.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.debian.sh && bash ~/INSTALL.debian.sh -C
|
||||
#
|
||||
#
|
||||
#----------------------------------------------------------|
|
||||
# 3/ The following script has been partially autogenerated |
|
||||
#----------------------------------------------------------|
|
||||
#
|
||||
# To generate this script yourself, the following steps need to be taken.
|
||||
# $ git clone https://github.com/SteveClement/xsnippet.git
|
||||
# Make sure xsnippet resides somewhere in your $PATH - It is a shell script so a simple, copy to somewhere sane is enough.
|
||||
# $ git clone https://github.com/MISP/MISP.git
|
||||
# $ cd MISP/INSTALL ; ./INSTALL.debian.tpl.sh
|
||||
#
|
||||
##
|
||||
###
|
||||
####----------------\
|
||||
## Developer Note |
|
||||
####--------------------------------------------------------------------------------------------------|
|
||||
## In theory the order does not matter as everything is a self-contained function. |
|
||||
# That said, ideally leave the order as is and do NOT change the lines as they are place-holders. |
|
||||
# Script files that do NOT have a #_name.sh are scripts that have NO functions. This is by design. |
|
||||
#-----------------------------------------------------------------------------------------------------|
|
||||
#
|
||||
# ToC #
|
||||
#
|
||||
#### BEGIN AUTOMATED SECTION ####
|
||||
#
|
||||
## 0_global-vars.sh ##
|
||||
## 0_support-functions.sh ##
|
||||
## 0_apt-upgrade.sh ##
|
||||
## 0_sudoKeeper.sh ##
|
||||
## 0_installCoreDeps.sh ##
|
||||
## 0_installDepsPhp73.sh ##
|
||||
## 0_installDepsPhp72.sh ##
|
||||
## 1_prepareDB.sh ##
|
||||
## 1_apacheConfig.sh ##
|
||||
## 1_mispCoreInstall.sh ##
|
||||
## 1_installCake.sh ##
|
||||
## 2_permissions.sh ##
|
||||
## 2_configMISP.sh ##
|
||||
## 2_core-cake.sh ##
|
||||
## 2_gnupg.sh ##
|
||||
## 2_logRotation.sh ##
|
||||
## 2_backgroundWorkers.sh ##
|
||||
## 3_misp-modules.sh ##
|
||||
## 4_misp-dashboard.sh ##
|
||||
## 4_misp-dashboard-cake.sh ##
|
||||
## 5_mail_to_misp.sh ##
|
||||
## 6_ssdeep.sh ##
|
||||
## 6_viper.sh ##
|
||||
|
||||
# No functions scripts:
|
||||
## apt-upgrade.sh ##
|
||||
## postfix.sh ##
|
||||
## interfaces.sh ##
|
||||
#
|
||||
### END AUTOMATED SECTION ###
|
||||
|
||||
# This function will generate the main installer.
|
||||
# It is a helper function for the maintainers for the installer.
|
||||
|
||||
colors () {
|
||||
# Some colors for easier debug and better UX (not colorblind compatible, PR welcome)
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
LBLUE='\033[1;34m'
|
||||
YELLOW='\033[0;33m'
|
||||
HIDDEN='\e[8m'
|
||||
NC='\033[0m'
|
||||
}
|
||||
|
||||
generateInstaller () {
|
||||
if [ ! -f $(which xsnippet) ]; then
|
||||
echo 'xsnippet is NOT installed. Clone the repository below and copy the xsnippet shell script somehwere in your $PATH'
|
||||
echo "git clone https://github.com/SteveClement/xsnippet.git"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $(echo $0 |grep -e '^\.\/') != "./INSTALL.debian.tpl.sh" ]]; then
|
||||
echo -e "${RED}iAmError!${NC}"
|
||||
echo -e "To generate the installer call it with './INSTALL.debian.tpl.sh' otherwise things will break."
|
||||
echo -e "You called: ${RED}$0${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir installer ; cd installer
|
||||
cp ../INSTALL.debian.tpl.sh .
|
||||
|
||||
# Pull code snippets out of Main Install Documents
|
||||
for f in `echo INSTALL.ubuntu1804.md xINSTALL.debian9.md INSTALL.kali.md xINSTALL.debian_testing.md xINSTALL.tsurugi.md xINSTALL.debian9-postgresql.md xINSTALL.ubuntu1804.with.webmin.md`; do
|
||||
xsnippet . ../../docs/${f}
|
||||
done
|
||||
|
||||
# Pull out code snippets from generic Install Documents
|
||||
for f in `echo globalVariables.md mail_to_misp-debian.md MISP_CAKE_init.md misp-dashboard-debian.md misp-modules-debian.md gnupg.md ssdeep-debian.md sudo_etckeeper.md supportFunctions.md viper-debian.md`; do
|
||||
xsnippet . ../../docs/generic/${f}
|
||||
done
|
||||
|
||||
# TODO: Fix the below.
|
||||
# $ for f in `echo ls [0-9]_*`; do
|
||||
# $ perl -pe 's/## ${f} ##/`cat ${f}`/ge' -i INSTALL.debian.sh
|
||||
# $ done
|
||||
#
|
||||
# Temporary copy/paste holder
|
||||
perl -pe 's/^## 0_global-vars.sh ##/`cat 0_global-vars.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 0_apt-upgrade.sh ##/`cat 0_apt-upgrade.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 0_sudoKeeper.sh ##/`cat 0_sudoKeeper.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 0_installCoreDeps.sh ##/`cat 0_installCoreDeps.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 0_installDepsPhp73.sh ##/`cat 0_installDepsPhp73.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 0_installDepsPhp72.sh ##/`cat 0_installDepsPhp72.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 1_prepareDB.sh ##/`cat 1_prepareDB.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 1_apacheConfig.sh ##/`cat 1_apacheConfig.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 1_mispCoreInstall.sh ##/`cat 1_mispCoreInstall.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 1_installCake.sh ##/`cat 1_installCake.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 2_permissions.sh ##/`cat 2_permissions.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 2_configMISP.sh ##/`cat 2_configMISP.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 0_support-functions.sh ##/`cat 0_support-functions.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 2_gnupg.sh ##/`cat 2_gnupg.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 2_logRotation.sh ##/`cat 2_logRotation.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 2_backgroundWorkers.sh ##/`cat 2_backgroundWorkers.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 2_core-cake.sh ##/`cat 2_core-cake.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 3_misp-modules.sh ##/`cat 3_misp-modules.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 4_misp-dashboard-cake.sh ##/`cat 4_misp-dashboard-cake.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 4_misp-dashboard.sh ##/`cat 4_misp-dashboard.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 5_mail_to_misp.sh ##/`cat 5_mail_to_misp.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 6_viper.sh ##/`cat 6_viper.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
perl -pe 's/^## 6_ssdeep.sh ##/`cat 6_ssdeep.sh`/ge' -i INSTALL.debian.tpl.sh
|
||||
|
||||
cp INSTALL.debian.tpl.sh ../INSTALL.debian.sh
|
||||
cd ..
|
||||
rm -rf installer
|
||||
echo -e "${LBLUE}Generated INSTALL.debian.sh${NC}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Simple debug function with message
|
||||
|
||||
# Make sure no alias exists
|
||||
if [[ $(type -t debug) == "alias" ]]; then unalias debug; fi
|
||||
debug () {
|
||||
echo -e "${RED}Next step:${NC} ${GREEN}$1${NC}" > /dev/tty
|
||||
if [ ! -z $DEBUG ]; then
|
||||
NO_PROGRESS=1
|
||||
echo -e "${RED}Debug Mode${NC}, press ${LBLUE}enter${NC} to continue..." > /dev/tty
|
||||
exec 3>&1
|
||||
read
|
||||
else
|
||||
# [Set up conditional redirection](https://stackoverflow.com/questions/8756535/conditional-redirection-in-bash)
|
||||
#exec 3>&1 &>/dev/null
|
||||
:
|
||||
fi
|
||||
}
|
||||
|
||||
installMISPubuntuSupported () {
|
||||
space
|
||||
echo "Proceeding with the installation of MISP core"
|
||||
space
|
||||
|
||||
# Set Base URL - functionLocation('generic/supportFunctions.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && setBaseURL
|
||||
progress 4
|
||||
|
||||
# Check if sudo is installed and etckeeper - functionLocation('generic/sudo_etckeeper.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && checkSudoKeeper 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Set locale if not set - functionLocation('generic/supportFunctions.md')
|
||||
checkLocale
|
||||
|
||||
# Upgrade system to make sure we install the latest packages - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && aptUpgrade 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# TODO: Double check how the user is added and subsequently used during the install.
|
||||
# TODO: Work on possibility to install as user X and install MISP for user Y
|
||||
# TODO: Check if logout needed. (run SUDO_USER in installer)
|
||||
# <snippet-begin add-user.sh>
|
||||
# TODO: Double check how to properly handle postfix
|
||||
# <snippet-begin postfix.sh>
|
||||
|
||||
# Pull in all possible MISP Environment variables - functionLocation('generic/globalVariables.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && MISPvars
|
||||
progress 4
|
||||
|
||||
# Check if MISP user is installed and we do not run as root - functionLocation('generic/supportFunctions.md')
|
||||
checkID
|
||||
progress 4
|
||||
|
||||
# Starting friendly UI spinner
|
||||
#spin &
|
||||
#SPIN_PID=$!
|
||||
#disown
|
||||
#trap "kill -9 $SPIN_PID" `seq 0 15`
|
||||
|
||||
# Install Core Dependencies - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && installCoreDeps
|
||||
progress 4
|
||||
|
||||
# Install PHP 7.2 Dependencies - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && installDepsPhp72
|
||||
progress 4
|
||||
|
||||
# Install Core MISP - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && installCore
|
||||
progress 4
|
||||
|
||||
# Install PHP Cake - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && installCake
|
||||
progress 4
|
||||
|
||||
# Make sure permissions are sane - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && permissions 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# TODO: Mysql install functions, make it upgrade safe, double check
|
||||
# Setup Databse - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && prepareDB 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Roll Apache Config - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && apacheConfig 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Setup log logrotate - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && logRotation 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Generate MISP Config files - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && configMISP 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Generate GnuPG key - functionLocation('generic/gnupg.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && setupGnuPG 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Setup and start background workers - functionLocation('INSTALL.ubuntu1804.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && backgroundWorkers 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Run cake CLI for the core installation - functionLocation('generic/MISP_CAKE_init.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && coreCAKE 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Update Galaxies, Template Objects, Warning Lists, Notice Lists, Taxonomies - functionLocation('generic/MISP_CAKE_init.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && updateGOWNT 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Disable spinner
|
||||
#(kill $SPIN_PID 2>&1) >/dev/null
|
||||
|
||||
# Check if /usr/local/src is writeable by target install user - functionLocation('generic/supportFunctions.md')
|
||||
[[ -n $CORE ]] || [[ -n $ALL ]] && checkUsrLocalSrc
|
||||
progress 4
|
||||
|
||||
## Resume spinner
|
||||
#spin &
|
||||
#SPIN_PID=$!
|
||||
#disown
|
||||
#trap "kill -9 $SPIN_PID" `seq 0 15`
|
||||
|
||||
# Install misp-modules - functionLocation('generic/misp-modules-debian.md')
|
||||
[[ -n $MODULES ]] || [[ -n $ALL ]] && mispmodules
|
||||
progress 4
|
||||
|
||||
# Install Viper - functionLocation('generic/viper-debian.md')
|
||||
[[ -n $VIPER ]] || [[ -n $ALL ]] && viper
|
||||
progress 4
|
||||
|
||||
# Install ssdeep - functionLocation('generic/ssdeep-debian.md')
|
||||
[[ -n $SSDEEP ]] || [[ -n $ALL ]] && ssdeep
|
||||
progress 4
|
||||
|
||||
# Install misp-dashboard - functionLocation('generic/misp-dashboard-debian.md')
|
||||
[[ -n $DASHBOARD ]] || [[ -n $ALL ]] && mispDashboard ; dashboardCAKE 2> /dev/null > /dev/null
|
||||
progress 4
|
||||
|
||||
# Install Mail2MISP - functionLocation('generic/mail_to_misp-debian.md')
|
||||
[[ -n $MAIL2 ]] || [[ -n $ALL ]] && mail2misp
|
||||
progress 100
|
||||
|
||||
# Run final script to inform the User what happened - functionLocation('generic/supportFunctions.md')
|
||||
theEnd
|
||||
}
|
||||
|
||||
# Main Kalin Install function
|
||||
installMISPonKali () {
|
||||
# Kali might have a bug on installs where libc6 is not up to date, this forces bash and libc to update - functionLocation('')
|
||||
kaliUpgrade 2> /dev/null > /dev/null
|
||||
|
||||
# Set locale if not set - functionLocation('generic/supportFunctions.md')
|
||||
checkLocale
|
||||
|
||||
# Set Base URL - functionLocation('generic/supportFunctions.md')
|
||||
setBaseURL
|
||||
|
||||
# Install PHP 7.3 Dependencies - functionLocation('generic/supportFunctions.md')
|
||||
installDepsPhp73 2> /dev/null > /dev/null
|
||||
|
||||
# Set custom Kali only variables and tweaks
|
||||
space
|
||||
# The following disables sleep on kali/gnome
|
||||
### FIXME: Disabling for now, maybe source of some issues.
|
||||
##disableSleep 2> /dev/null > /dev/null
|
||||
##debug "Sleeping 3 seconds to make sure the disable sleep does not confuse the execution of the script."
|
||||
##sleep 3
|
||||
|
||||
# Kali specific dependencies - functionLocation('generic/supportFunctions.md')
|
||||
debug "Installing dependencies"
|
||||
installDeps
|
||||
|
||||
# Install Core Dependencies - functionLocation('INSTALL.ubuntu1804.md')
|
||||
installCoreDeps
|
||||
|
||||
debug "Enabling redis and gnupg modules"
|
||||
phpenmod -v 7.3 redis
|
||||
phpenmod -v 7.3 gnupg
|
||||
|
||||
debug "Apache2 ops: dismod: status php7.2 - dissite: 000-default enmod: ssl rewrite headers php7.3 ensite: default-ssl"
|
||||
a2dismod status 2> /dev/null > /dev/null
|
||||
a2dismod php7.2 2> /dev/null > /dev/null
|
||||
a2enmod ssl rewrite headers php7.3 2> /dev/null > /dev/null
|
||||
a2dissite 000-default 2> /dev/null > /dev/null
|
||||
a2ensite default-ssl 2> /dev/null > /dev/null
|
||||
|
||||
debug "Restarting mysql.service"
|
||||
systemctl restart mysql.service 2> /dev/null > /dev/null
|
||||
|
||||
debug "Fixing redis rc script on Kali"
|
||||
fixRedis 2> /dev/null > /dev/null
|
||||
|
||||
debug "git clone, submodule update everything"
|
||||
mkdir $PATH_TO_MISP
|
||||
chown www-data:www-data $PATH_TO_MISP
|
||||
cd $PATH_TO_MISP
|
||||
$SUDO_WWW git clone https://github.com/MISP/MISP.git $PATH_TO_MISP
|
||||
|
||||
$SUDO_WWW git config core.filemode false
|
||||
|
||||
cd $PATH_TO_MISP
|
||||
$SUDO_WWW git submodule update --init --recursive 2> /dev/null > /dev/null
|
||||
# Make git ignore filesystem permission differences for submodules
|
||||
$SUDO_WWW git submodule foreach --recursive git config core.filemode false
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts
|
||||
$SUDO_WWW git clone https://github.com/CybOXProject/python-cybox.git 2> /dev/null > /dev/null
|
||||
$SUDO_WWW git clone https://github.com/STIXProject/python-stix.git 2> /dev/null > /dev/null
|
||||
$SUDO_WWW git clone https://github.com/CybOXProject/mixbox.git 2> /dev/null > /dev/null
|
||||
$SUDO_WWW git clone https://github.com/MAECProject/python-maec.git 2> /dev/null > /dev/null
|
||||
|
||||
|
||||
mkdir /var/www/.cache/
|
||||
|
||||
MISP_USER_HOME=$(sudo -Hiu $MISP_USER env | grep HOME |cut -f 2 -d=)
|
||||
mkdir $MISP_USER_HOME/.cache
|
||||
chown $MISP_USER:$MISP_USER $MISP_USER_HOME/.cache
|
||||
chown www-data:www-data /var/www/.cache
|
||||
|
||||
debug "Generating rc.local"
|
||||
genRCLOCAL
|
||||
|
||||
debug "Setting up main MISP virtualenv"
|
||||
# Needs virtualenv
|
||||
sudo -u www-data virtualenv -p python3 ${PATH_TO_MISP}/venv
|
||||
|
||||
debug "Installing MISP dashboard"
|
||||
mispDashboard
|
||||
|
||||
debug "Installing python-cybox"
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-cybox
|
||||
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install . 2> /dev/null > /dev/null
|
||||
|
||||
debug "Installing python-stix"
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-stix
|
||||
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install . 2> /dev/null > /dev/null
|
||||
|
||||
debug "Install maec"
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-maec
|
||||
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install . 2> /dev/null > /dev/null
|
||||
|
||||
# install STIX2.0 library to support STIX 2.0 export
|
||||
debug "Installing cti-python-stix2"
|
||||
cd ${PATH_TO_MISP}/cti-python-stix2
|
||||
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install -I . 2> /dev/null > /dev/null
|
||||
|
||||
debug "Installing mixbox"
|
||||
cd $PATH_TO_MISP/app/files/scripts/mixbox
|
||||
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install . 2> /dev/null > /dev/null
|
||||
|
||||
# install PyMISP
|
||||
debug "Installing PyMISP"
|
||||
cd $PATH_TO_MISP/PyMISP
|
||||
sudo -H -u www-data ${PATH_TO_MISP}/venv/bin/pip install . 2> /dev/null > /dev/null
|
||||
|
||||
# install pydeep
|
||||
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install git+https://github.com/kbandla/pydeep.git 2> /dev/null > /dev/null
|
||||
|
||||
# install lief
|
||||
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install https://github.com/lief-project/packages/raw/lief-master-latest/pylief-0.9.0.dev.zip 2> /dev/null > /dev/null
|
||||
|
||||
# install python-magic
|
||||
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install python-magic 2> /dev/null > /dev/null
|
||||
|
||||
# Install Crypt_GPG and Console_CommandLine
|
||||
debug "Installing pear Console_CommandLine"
|
||||
pear install ${PATH_TO_MISP}/INSTALL/dependencies/Console_CommandLine/package.xml
|
||||
debug "Installing pear Crypt_GPG"
|
||||
pear install ${PATH_TO_MISP}/INSTALL/dependencies/Crypt_GPG/package.xml
|
||||
|
||||
|
||||
debug "Installing composer with php 7.3 updates"
|
||||
composer73
|
||||
|
||||
$SUDO_WWW cp -fa $PATH_TO_MISP/INSTALL/setup/config.php $PATH_TO_MISP/app/Plugin/CakeResque/Config/config.php
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP
|
||||
chmod -R 750 $PATH_TO_MISP
|
||||
chmod -R g+ws $PATH_TO_MISP/app/tmp
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files/scripts/tmp
|
||||
|
||||
debug "Setting up database"
|
||||
if [ ! -e /var/lib/mysql/misp/users.ibd ]; then
|
||||
echo "
|
||||
set timeout 10
|
||||
spawn mysql_secure_installation
|
||||
expect \"Enter current password for root (enter for none):\"
|
||||
send -- \"\r\"
|
||||
expect \"Set root password?\"
|
||||
send -- \"y\r\"
|
||||
expect \"New password:\"
|
||||
send -- \"${DBPASSWORD_ADMIN}\r\"
|
||||
expect \"Re-enter new password:\"
|
||||
send -- \"${DBPASSWORD_ADMIN}\r\"
|
||||
expect \"Remove anonymous users?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Disallow root login remotely?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Remove test database and access to it?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Reload privilege tables now?\"
|
||||
send -- \"y\r\"
|
||||
expect eof" | expect -f -
|
||||
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "create database $DBNAME;"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant usage on *.* to $DBNAME@localhost identified by '$DBPASSWORD_MISP';"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant all privileges on $DBNAME.* to '$DBUSER_MISP'@'localhost';"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "flush privileges;"
|
||||
|
||||
enableServices
|
||||
|
||||
$SUDO_WWW cat $PATH_TO_MISP/INSTALL/MYSQL.sql | mysql -u $DBUSER_MISP -p$DBPASSWORD_MISP $DBNAME
|
||||
|
||||
echo "<?php
|
||||
class DATABASE_CONFIG {
|
||||
public \$default = array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
//'datasource' => 'Database/Postgres',
|
||||
'persistent' => false,
|
||||
'host' => '$DBHOST',
|
||||
'login' => '$DBUSER_MISP',
|
||||
'port' => 3306, // MySQL & MariaDB
|
||||
//'port' => 5432, // PostgreSQL
|
||||
'password' => '$DBPASSWORD_MISP',
|
||||
'database' => '$DBNAME',
|
||||
'prefix' => '',
|
||||
'encoding' => 'utf8',
|
||||
);
|
||||
}" | $SUDO_WWW tee $PATH_TO_MISP/app/Config/database.php 2> /dev/null > /dev/null
|
||||
else
|
||||
echo "There might be a database already existing here: /var/lib/mysql/misp/users.ibd"
|
||||
echo "Skipping any creations…"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
debug "Generating Certificate"
|
||||
openssl req -newkey rsa:4096 -days 365 -nodes -x509 \
|
||||
-subj "/C=${OPENSSL_C}/ST=${OPENSSL_ST}/L=${OPENSSL_L}/O=${OPENSSL_O}/OU=${OPENSSL_OU}/CN=${OPENSSL_CN}/emailAddress=${OPENSSL_EMAILADDRESS}" \
|
||||
-keyout /etc/ssl/private/misp.local.key -out /etc/ssl/private/misp.local.crt
|
||||
|
||||
debug "Generating Apache Conf"
|
||||
genApacheConf
|
||||
|
||||
echo "127.0.0.1 misp.local" | tee -a /etc/hosts
|
||||
|
||||
debug "Disabling site default-ssl, enabling misp-ssl"
|
||||
a2dissite default-ssl
|
||||
a2ensite misp-ssl
|
||||
|
||||
for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit
|
||||
do
|
||||
sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI
|
||||
done
|
||||
|
||||
debug "Restarting Apache2"
|
||||
systemctl restart apache2
|
||||
|
||||
debug "Setting up logrotate"
|
||||
cp $PATH_TO_MISP/INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
chmod 0640 /etc/logrotate.d/misp
|
||||
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/bootstrap.default.php $PATH_TO_MISP/app/Config/bootstrap.php
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/core.default.php $PATH_TO_MISP/app/Config/core.php
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/config.default.php $PATH_TO_MISP/app/Config/config.php
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP/app/Config
|
||||
chmod -R 750 $PATH_TO_MISP/app/Config
|
||||
|
||||
debug "Setting up GnuPG"
|
||||
setupGnuPG 2> /dev/null > /dev/null
|
||||
|
||||
debug "Starting workers"
|
||||
chmod +x $PATH_TO_MISP/app/Console/worker/start.sh
|
||||
$SUDO_WWW $PATH_TO_MISP/app/Console/worker/start.sh
|
||||
|
||||
debug "Running Core Cake commands"
|
||||
coreCAKE 2> /dev/null > /dev/null
|
||||
dashboardCAKE 2> /dev/null > /dev/null
|
||||
|
||||
debug "Update: Galaxies, Template Objects, Warning Lists, Notice Lists, Taxonomies"
|
||||
updateGOWNT 2> /dev/null > /dev/null
|
||||
|
||||
gitPullAllRCLOCAL
|
||||
|
||||
checkUsrLocalSrc
|
||||
|
||||
debug "Installing misp-modules"
|
||||
mispmodules
|
||||
|
||||
debug "Installing Viper"
|
||||
viper
|
||||
|
||||
debug "Installing ssdeep"
|
||||
ssdeep
|
||||
phpenmod -v 7.3 ssdeep
|
||||
|
||||
debug "Setting permissions"
|
||||
permissions
|
||||
|
||||
debug "Running Then End!"
|
||||
theEnd
|
||||
}
|
||||
# End installMISPonKali ()
|
||||
|
||||
## End Function Section ##
|
||||
|
||||
colors
|
||||
debug "Checking if we are run as the installer template"
|
||||
if [[ "$0" == "./INSTALL.debian.tpl.sh" || "$(echo $0 |grep -o -e 'INSTALL.debian.tpl.sh')" == "INSTALL.debian.tpl.sh" ]]; then
|
||||
generateInstaller
|
||||
fi
|
||||
|
||||
space
|
||||
debug "Setting MISP variables"
|
||||
MISPvars
|
||||
debug "Checking Linux distribution and flavour..."
|
||||
checkFlavour
|
||||
|
||||
debug "Checking for parameters or Unattended Kali Install"
|
||||
if [[ $# == 0 && $0 != "/tmp/misp-kali.sh" ]]; then
|
||||
usage
|
||||
exit
|
||||
else
|
||||
debug "Setting install options with given parameters."
|
||||
# The setOpt/checkOpt function lives in generic/supportFunctions.md
|
||||
setOpt $@
|
||||
checkOpt core && echo "${LBLUE}MISP${NC} ${GREEN}core${NC} selected"
|
||||
checkOpt viper && echo "${GREEN}Viper${NC} selected"
|
||||
checkOpt modules && echo "${LBLUE}MISP${NC} ${GREEN}modules${NC} selected"
|
||||
checkOpt dashboard && echo "${LBLUE}MISP${NC} ${GREEN}dashboard${NC} selected"
|
||||
checkOpt mail2 && echo "${GREEN}Mail 2${NC} ${LBLUE}MISP${NC} selected"
|
||||
checkOpt all && echo "${GREEN}All options${NC} selected"
|
||||
checkOpt pre && echo "${GREEN}Pre-flight checks${NC} selected"
|
||||
checkOpt unattended && echo "${GREEN}unattended${NC} install selected"
|
||||
checkOpt upgrade && echo "${GREEN}upgrade${NC} install selected"
|
||||
checkOpt force && echo "${GREEN}force${NC} install selected"
|
||||
|
||||
# Check if at least core is selected if no other options that do not require core are set
|
||||
if [[ "$CORE" != "1" && "$ALL" != "1" && "$UPGRADE" != "1" && "$PRE" != "1" && "$0" != "/tmp/misp-kali.sh" ]]; then
|
||||
space
|
||||
usage
|
||||
echo "You need to at least select core, or -A to install everything."
|
||||
echo "$0 -c # Is the minima for install options"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add upgrade option to do upgrade pre flight
|
||||
[[ -n $PRE ]] && preInstall
|
||||
|
||||
[[ -n $UPGRADE ]] && upgrade
|
||||
|
||||
# If Ubuntu is detected, figure out which release it is and run the according scripts
|
||||
if [ "${FLAVOUR}" == "ubuntu" ]; then
|
||||
RELEASE=$(lsb_release -s -r| tr [A-Z] [a-z])
|
||||
if [ "${RELEASE}" == "18.04" ]; then
|
||||
echo "Install on Ubuntu 18.04 LTS fully supported."
|
||||
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
|
||||
installMISPubuntuSupported && exit || exit
|
||||
fi
|
||||
if [ "${RELEASE}" == "18.10" ]; then
|
||||
echo "Install on Ubuntu 18.10 partially supported, bye."
|
||||
installMISPubuntuSupported && exit || exit
|
||||
fi
|
||||
if [ "${RELEASE}" == "19.04" ]; then
|
||||
echo "Install on Ubuntu 19.04 not supported, bye"
|
||||
exit 1
|
||||
fi
|
||||
if [ "${RELEASE}" == "19.10" ]; then
|
||||
echo "Install on Ubuntu 19.10 not supported, bye"
|
||||
exit 1
|
||||
fi
|
||||
echo "Installation done!"
|
||||
exit
|
||||
fi
|
||||
|
||||
# If Debian is detected, figure out which release it is and run the according scripts
|
||||
if [ "${FLAVOUR}" == "debian" ]; then
|
||||
CODE=$(lsb_release -s -c| tr [A-Z] [a-z])
|
||||
if [ "${CODE}" == "buster" ]; then
|
||||
echo "Install on Debian testing fully supported."
|
||||
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
|
||||
installDepsPhp73
|
||||
fi
|
||||
if [ "${CODE}" == "sid" ]; then
|
||||
echo "Install on Debian unstable not fully supported."
|
||||
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
|
||||
installDepsPhp73
|
||||
fi
|
||||
if [ "${CODE}" == "stretch" ]; then
|
||||
echo "Install on Debian stable fully supported."
|
||||
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
|
||||
installDepsPhp72
|
||||
fi
|
||||
echo "Installation done!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If Tsurugi is detected, figure out which release it is and run the according scripts
|
||||
if [ "${FLAVOUR}" == "tsurugi" ]; then
|
||||
CODE=$(lsb_release -s -c| tr [A-Z] [a-z])
|
||||
if [ "${CODE}" == "bamboo" ]; then
|
||||
echo "Install on Tsurugi Lab partially supported."
|
||||
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
|
||||
fi
|
||||
if [ "${CODE}" == "soy sauce" ]; then
|
||||
echo "Install on Tsurugi Acquire partially supported."
|
||||
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
|
||||
fi
|
||||
echo "Installation done!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If Kali Linux is detected, run the acccording scripts
|
||||
if [ "${FLAVOUR}" == "kali" ]; then
|
||||
KALI=1
|
||||
kaliOnRootR0ckz
|
||||
installMISPonKali
|
||||
echo "Installation done!"
|
||||
exit
|
||||
fi
|
|
@ -1 +0,0 @@
|
|||
../docs/INSTALL.debian9.md
|
|
@ -1,592 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
#INSTALLATION INSTRUCTIONS
|
||||
#------------------------- for Kali Linux
|
||||
#
|
||||
#0/ Quick MISP Instance on Kali Linux - Status
|
||||
#---------------------------------------------
|
||||
#
|
||||
#1/ Prepare Kali with a MISP User
|
||||
#--------------------------------
|
||||
# To install MISP on Kali copy paste this in your r00t shell:
|
||||
# wget -O /tmp/misp-kali.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.kali.txt && bash /tmp/misp-kali.sh
|
||||
# /!\ Please read the installer script before randomly doing the above.
|
||||
# The script is tested on a plain vanilla Kali Linux Boot CD and installs quite a few dependencies.
|
||||
|
||||
MISP_USER='misp'
|
||||
MISP_PASSWORD='Password1234'
|
||||
|
||||
function kaliOnRootR0ckz() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
elif [[ $(id misp >/dev/null; echo $?) -ne 0 ]]; then
|
||||
useradd -s /bin/bash -m -G adm,cdrom,sudo,dip,plugdev,www-data misp
|
||||
echo $MISP_USER:$MISP_PASSWORD | chpasswd
|
||||
else
|
||||
echo "User ${MISP_USER} exists, skipping creation"
|
||||
fi
|
||||
}
|
||||
|
||||
function installMISPonKali() {
|
||||
# MISP configuration variables
|
||||
PATH_TO_MISP='/var/www/MISP'
|
||||
MISP_BASEURL='https://misp.local'
|
||||
MISP_LIVE='1'
|
||||
CAKE="$PATH_TO_MISP/app/Console/cake"
|
||||
|
||||
# Database configuration
|
||||
DBHOST='localhost'
|
||||
DBNAME='misp'
|
||||
DBUSER_ADMIN='root'
|
||||
DBPASSWORD_ADMIN="$(openssl rand -hex 32)"
|
||||
DBUSER_MISP='misp'
|
||||
DBPASSWORD_MISP="$(openssl rand -hex 32)"
|
||||
|
||||
# Webserver configuration
|
||||
FQDN='misp.local'
|
||||
|
||||
# OpenSSL configuration
|
||||
OPENSSL_CN=$FQDN
|
||||
OPENSSL_C='LU'
|
||||
OPENSSL_ST='State'
|
||||
OPENSSL_L='Location'
|
||||
OPENSSL_O='Organization'
|
||||
OPENSSL_OU='Organizational Unit'
|
||||
OPENSSL_EMAILADDRESS='info@localhost'
|
||||
|
||||
# GPG configuration
|
||||
GPG_REAL_NAME='Autogenerated Key'
|
||||
GPG_COMMENT='WARNING: MISP AutoGenerated Key consider this Key VOID!'
|
||||
GPG_EMAIL_ADDRESS='admin@admin.test'
|
||||
GPG_KEY_LENGTH='2048'
|
||||
GPG_PASSPHRASE='Password1234'
|
||||
|
||||
# php.ini configuration
|
||||
upload_max_filesize=50M
|
||||
post_max_size=50M
|
||||
max_execution_time=300
|
||||
memory_limit=512M
|
||||
PHP_INI=/etc/php/7.2/apache2/php.ini
|
||||
|
||||
# apt config
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# sudo config to run $LUSER commands
|
||||
SUDO="sudo -u ${MISP_USER}"
|
||||
SUDO_WWW="sudo -u www-data"
|
||||
|
||||
echo "Admin (${DBUSER_ADMIN}) DB Password: ${DBPASSWORD_ADMIN}"
|
||||
echo "User (${DBUSER_MISP}) DB Password: ${DBPASSWORD_MISP}"
|
||||
|
||||
echo "-----------------------------------------------------------------------"
|
||||
echo "Disabling sleep etc…"
|
||||
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0
|
||||
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-timeout 0
|
||||
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing'
|
||||
xset s 0 0
|
||||
xset dpms 0 0
|
||||
xset s off
|
||||
apt update
|
||||
apt install -qy etckeeper
|
||||
# Skip dist-upgrade for now, pulls in 500+ updated packages
|
||||
#sudo apt -y dist-upgrade
|
||||
git config --global user.email "root@kali.lan"
|
||||
git config --global user.name "Root User"
|
||||
apt install -qy postfix
|
||||
|
||||
apt install -qy \
|
||||
curl gcc git gnupg-agent make openssl redis-server neovim zip libyara-dev python3-yara python3-redis python3-zmq \
|
||||
mariadb-client \
|
||||
mariadb-server \
|
||||
apache2 apache2-doc apache2-utils \
|
||||
libapache2-mod-php7.2 php7.2 php7.2-cli php7.2-mbstring php-pear php7.2-dev php7.2-json php7.2-xml php7.2-mysql php7.2-opcache php7.2-readline \
|
||||
python3-dev python3-pip libpq5 libjpeg-dev libfuzzy-dev ruby asciidoctor \
|
||||
libxml2-dev libxslt1-dev zlib1g-dev python3-setuptools expect
|
||||
|
||||
modprobe tpm-rng
|
||||
echo tpm-rng >> /etc/modules
|
||||
apt install -qy rng-tools # This might fail on TPM grounds, enable the security chip in your BIOS
|
||||
service rng-tools start
|
||||
|
||||
systemctl restart mariadb.service
|
||||
|
||||
a2dismod status
|
||||
a2enmod ssl rewrite headers
|
||||
a2dissite 000-default
|
||||
a2ensite default-ssl
|
||||
|
||||
pear channel-update pear.php.net
|
||||
pear install Crypt_GPG
|
||||
pecl channel-update pecl.php.net
|
||||
|
||||
yes '' |pecl install redis
|
||||
|
||||
echo "extension=redis.so" | tee /etc/php/7.2/mods-available/redis.ini
|
||||
|
||||
phpenmod redis
|
||||
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.6 2
|
||||
|
||||
mkdir $PATH_TO_MISP
|
||||
chown www-data:www-data $PATH_TO_MISP
|
||||
cd $PATH_TO_MISP
|
||||
$SUDO_WWW git clone https://github.com/MISP/MISP.git $PATH_TO_MISP
|
||||
|
||||
$SUDO_WWW git config core.filemode false
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts
|
||||
$SUDO_WWW git clone https://github.com/CybOXProject/python-cybox.git
|
||||
$SUDO_WWW git clone https://github.com/STIXProject/python-stix.git
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-cybox
|
||||
pip3 install .
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-stix
|
||||
pip3 install .
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts/
|
||||
$SUDO_WWW git clone https://github.com/CybOXProject/mixbox.git
|
||||
cd $PATH_TO_MISP/app/files/scripts/mixbox
|
||||
pip3 install .
|
||||
|
||||
cd $PATH_TO_MISP
|
||||
$SUDO_WWW git submodule update --init --recursive
|
||||
# Make git ignore filesystem permission differences for submodules
|
||||
$SUDO_WWW git submodule foreach --recursive git config core.filemode false
|
||||
|
||||
# install PyMISP
|
||||
cd $PATH_TO_MISP/PyMISP
|
||||
pip3 install .
|
||||
|
||||
cd $PATH_TO_MISP/app
|
||||
mkdir /var/www/.composer ; chown www-data:www-data /var/www/.composer
|
||||
$SUDO_WWW php composer.phar require kamisama/cake-resque:4.1.2
|
||||
$SUDO_WWW php composer.phar config vendor-dir Vendor
|
||||
$SUDO_WWW php composer.phar install
|
||||
|
||||
$SUDO_WWW cp -fa $PATH_TO_MISP/INSTALL/setup/config.php $PATH_TO_MISP/app/Plugin/CakeResque/Config/config.php
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP
|
||||
chmod -R 750 $PATH_TO_MISP
|
||||
chmod -R g+ws $PATH_TO_MISP/app/tmp
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files/scripts/tmp
|
||||
|
||||
if [ ! -e /var/lib/mysql/misp/users.ibd ]; then
|
||||
echo "
|
||||
set timeout 10
|
||||
spawn mysql_secure_installation
|
||||
expect \"Enter current password for root (enter for none):\"
|
||||
send -- \"\r\"
|
||||
expect \"Set root password?\"
|
||||
send -- \"y\r\"
|
||||
expect \"New password:\"
|
||||
send -- \"${DBPASSWORD_ADMIN}\r\"
|
||||
expect \"Re-enter new password:\"
|
||||
send -- \"${DBPASSWORD_ADMIN}\r\"
|
||||
expect \"Remove anonymous users?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Disallow root login remotely?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Remove test database and access to it?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Reload privilege tables now?\"
|
||||
send -- \"y\r\"
|
||||
expect eof" | expect -f -
|
||||
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "create database $DBNAME;"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant usage on *.* to $DBNAME@localhost identified by '$DBPASSWORD_MISP';"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant all privileges on $DBNAME.* to '$DBUSER_MISP'@'localhost';"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "flush privileges;"
|
||||
|
||||
update-rc.d mysql enable
|
||||
update-rc.d apache2 enable
|
||||
update-rc.d redis-server enable
|
||||
|
||||
$SUDO_WWW cat $PATH_TO_MISP/INSTALL/MYSQL.sql | mysql -u $DBUSER_MISP -p$DBPASSWORD_MISP $DBNAME
|
||||
|
||||
echo "<?php
|
||||
class DATABASE_CONFIG {
|
||||
public \$default = array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
//'datasource' => 'Database/Postgres',
|
||||
'persistent' => false,
|
||||
'host' => '$DBHOST',
|
||||
'login' => '$DBUSER_MISP',
|
||||
'port' => 3306, // MySQL & MariaDB
|
||||
//'port' => 5432, // PostgreSQL
|
||||
'password' => '$DBPASSWORD_MISP',
|
||||
'database' => '$DBNAME',
|
||||
'prefix' => '',
|
||||
'encoding' => 'utf8',
|
||||
);
|
||||
}" | $SUDO_WWW tee $PATH_TO_MISP/app/Config/database.php
|
||||
else
|
||||
echo "There might be a database already existing here: /var/lib/mysql/misp/users.ibd"
|
||||
echo "Skipping any creations…"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
openssl req -newkey rsa:4096 -days 365 -nodes -x509 \
|
||||
-subj "/C=${OPENSSL_C}/ST=${OPENSSL_ST}/L=${OPENSSL_L}/O=${OPENSSL_O}/OU=${OPENSSL_OU}/CN=${OPENSSL_CN}/emailAddress=${OPENSSL_EMAILADDRESS}" \
|
||||
-keyout /etc/ssl/private/misp.local.key -out /etc/ssl/private/misp.local.crt
|
||||
|
||||
if [ ! -e /etc/rc.local ]
|
||||
then
|
||||
echo '#!/bin/sh -e' | tee -a /etc/rc.local
|
||||
echo 'exit 0' | tee -a /etc/rc.local
|
||||
chmod u+x /etc/rc.local
|
||||
fi
|
||||
|
||||
cd /var/www
|
||||
mkdir misp-dashboard
|
||||
chown www-data:www-data misp-dashboard
|
||||
$SUDO_WWW git clone https://github.com/MISP/misp-dashboard.git
|
||||
cd misp-dashboard
|
||||
/var/www/misp-dashboard/install_dependencies.sh
|
||||
sed -i "s/^host\ =\ localhost/host\ =\ 0.0.0.0/g" /var/www/misp-dashboard/config/config.cfg
|
||||
sed -i -e '$i \sudo -u www-data bash /var/www/misp-dashboard/start_all.sh\n' /etc/rc.local
|
||||
sed -i -e '$i \sudo -u misp /usr/local/src/viper/viper-web -p 8888 -H 0.0.0.0 &\n' /etc/rc.local
|
||||
sed -i -e '$i \git_dirs="/usr/local/src/misp-modules/ /var/www/misp-dashboard /usr/local/src/faup /usr/local/src/mail_to_misp /usr/local/src/misp-modules /usr/local/src/viper /var/www/misp-dashboard"\n' /etc/rc.local
|
||||
sed -i -e '$i \for d in $git_dirs; do\n' /etc/rc.local
|
||||
sed -i -e '$i \ echo "Updating ${d}"\n' /etc/rc.local
|
||||
sed -i -e '$i \ cd $d && sudo git pull &\n' /etc/rc.local
|
||||
sed -i -e '$i \done\n' /etc/rc.local
|
||||
$SUDO_WWW bash /var/www/misp-dashboard/start_all.sh
|
||||
|
||||
apt install libapache2-mod-wsgi-py3 -y
|
||||
|
||||
echo "<VirtualHost _default_:80>
|
||||
ServerAdmin admin@localhost.lu
|
||||
ServerName misp.local
|
||||
|
||||
Redirect permanent / https://misp.local
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost _default_:443>
|
||||
ServerAdmin admin@localhost.lu
|
||||
ServerName misp.local
|
||||
DocumentRoot $PATH_TO_MISP/app/webroot
|
||||
|
||||
<Directory $PATH_TO_MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Require all granted
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
# SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
</VirtualHost>" | tee /etc/apache2/sites-available/misp-ssl.conf
|
||||
|
||||
echo "127.0.0.1 misp.local" | tee -a /etc/hosts
|
||||
|
||||
echo "<VirtualHost *:8001>
|
||||
ServerAdmin admin@misp.local
|
||||
ServerName misp.local
|
||||
|
||||
DocumentRoot /var/www/misp-dashboard
|
||||
|
||||
WSGIDaemonProcess misp-dashboard \
|
||||
user=misp group=misp \
|
||||
python-home=/var/www/misp-dashboard/DASHENV \
|
||||
processes=1 \
|
||||
threads=15 \
|
||||
maximum-requests=5000 \
|
||||
listen-backlog=100 \
|
||||
queue-timeout=45 \
|
||||
socket-timeout=60 \
|
||||
connect-timeout=15 \
|
||||
request-timeout=60 \
|
||||
inactivity-timeout=0 \
|
||||
deadlock-timeout=60 \
|
||||
graceful-timeout=15 \
|
||||
eviction-timeout=0 \
|
||||
shutdown-timeout=5 \
|
||||
send-buffer-size=0 \
|
||||
receive-buffer-size=0 \
|
||||
header-buffer-size=0 \
|
||||
response-buffer-size=0 \
|
||||
server-metrics=Off
|
||||
|
||||
WSGIScriptAlias / /var/www/misp-dashboard/misp-dashboard.wsgi
|
||||
|
||||
<Directory /var/www/misp-dashboard>
|
||||
WSGIProcessGroup misp-dashboard
|
||||
WSGIApplicationGroup %{GLOBAL}
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
LogLevel info
|
||||
ErrorLog /var/log/apache2/misp-dashboard.local_error.log
|
||||
CustomLog /var/log/apache2/misp-dashboard.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>" | tee /etc/apache2/sites-available/misp-dashboard.conf
|
||||
|
||||
a2dissite default-ssl
|
||||
a2ensite misp-ssl
|
||||
a2ensite misp-dashboard
|
||||
|
||||
for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit
|
||||
do
|
||||
sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI
|
||||
done
|
||||
|
||||
systemctl restart apache2
|
||||
|
||||
cp $PATH_TO_MISP/INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
chmod 0640 /etc/logrotate.d/misp
|
||||
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/bootstrap.default.php $PATH_TO_MISP/app/Config/bootstrap.php
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/core.default.php $PATH_TO_MISP/app/Config/core.php
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/config.default.php $PATH_TO_MISP/app/Config/config.php
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP/app/Config
|
||||
chmod -R 750 $PATH_TO_MISP/app/Config
|
||||
$CAKE Live $MISP_LIVE
|
||||
$CAKE Baseurl $MISP_BASEURL
|
||||
|
||||
echo "%echo Generating a default key
|
||||
Key-Type: default
|
||||
Key-Length: $GPG_KEY_LENGTH
|
||||
Subkey-Type: default
|
||||
Name-Real: $GPG_REAL_NAME
|
||||
Name-Comment: $GPG_COMMENT
|
||||
Name-Email: $GPG_EMAIL_ADDRESS
|
||||
Expire-Date: 0
|
||||
Passphrase: $GPG_PASSPHRASE
|
||||
# Do a commit here, so that we can later print "done"
|
||||
%commit
|
||||
%echo done" > /tmp/gen-key-script
|
||||
|
||||
$SUDO_WWW gpg --homedir $PATH_TO_MISP/.gnupg --batch --gen-key /tmp/gen-key-script
|
||||
|
||||
$SUDO_WWW sh -c "gpg --homedir $PATH_TO_MISP/.gnupg --export --armor $GPG_EMAIL_ADDRESS" | $SUDO_WWW tee $PATH_TO_MISP/app/webroot/gpg.asc
|
||||
|
||||
chmod +x $PATH_TO_MISP/app/Console/worker/start.sh
|
||||
|
||||
$CAKE userInit -q
|
||||
|
||||
AUTH_KEY=$(mysql -u $DBUSER_MISP -p$DBPASSWORD_MISP misp -e "SELECT authkey FROM users;" | tail -1)
|
||||
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_event_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_object_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_object_reference_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_attribute_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_sighting_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_user_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_organisation_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_port" 50000
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_host" "localhost"
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_port" 6379
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_database" 1
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_namespace" "mispq"
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_include_attachments" false
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_tag_notifications_enable" false
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" false
|
||||
$CAKE Admin setSetting "GnuPG.email" "admin@admin.test"
|
||||
$CAKE Admin setSetting "GnuPG.homedir" "/var/www/MISP/.gnupg"
|
||||
$CAKE Admin setSetting "GnuPG.password" "Password1234"
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_services_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_hover_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_timeout" 300
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_hover_timeout" 150
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_cve_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_dns_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_services_port" 6666
|
||||
$CAKE Admin setSetting "Plugin.Import_services_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Import_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Import_services_port" 6666
|
||||
$CAKE Admin setSetting "Plugin.Import_timeout" 300
|
||||
$CAKE Admin setSetting "Plugin.Import_ocr_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Import_csvimport_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Export_services_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Export_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Export_services_port" 6666
|
||||
$CAKE Admin setSetting "Plugin.Export_timeout" 300
|
||||
$CAKE Admin setSetting "Plugin.Export_pdfexport_enabled" true
|
||||
$CAKE Admin setSetting "MISP.host_org_id" 1
|
||||
$CAKE Admin setSetting "MISP.email" "info@admin.test"
|
||||
$CAKE Admin setSetting "MISP.disable_emailing" false
|
||||
$CAKE Admin setSetting "MISP.contact" "info@admin.test"
|
||||
$CAKE Admin setSetting "MISP.disablerestalert" true
|
||||
$CAKE Admin setSetting "MISP.showCorrelationsOnIndex" true
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_enable" false
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
|
||||
$CAKE Admin setSetting "Plugin.Cortex_timeout" 120
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_timeout" 120
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_authkey" ""
|
||||
$CAKE Admin setSetting "Plugin.Cortex_ssl_verify_peer" false
|
||||
$CAKE Admin setSetting "Plugin.Cortex_ssl_verify_host" false
|
||||
$CAKE Admin setSetting "Plugin.Cortex_ssl_allow_self_signed" true
|
||||
$CAKE Admin setSetting "Plugin.Sightings_policy" 0
|
||||
$CAKE Admin setSetting "Plugin.Sightings_anonymise" false
|
||||
$CAKE Admin setSetting "Plugin.Sightings_range" 365
|
||||
$CAKE Admin setSetting "Plugin.CustomAuth_disable_logout" false
|
||||
$CAKE Admin setSetting "Plugin.RPZ_policy" "DROP"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_walled_garden" "127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_serial" "\$date00"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_refresh" "2h"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_retry" "30m"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_expiry" "30d"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_minimum_ttl" "1h"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_ttl" "1w"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_ns" "localhost."
|
||||
$CAKE Admin setSetting "Plugin.RPZ_ns_alt" ""
|
||||
$CAKE Admin setSetting "Plugin.RPZ_email" "root.localhost"
|
||||
$CAKE Admin setSetting "MISP.language" "eng"
|
||||
$CAKE Admin setSetting "MISP.proposals_block_attributes" false
|
||||
$CAKE Admin setSetting "MISP.redis_host" "127.0.0.1"
|
||||
$CAKE Admin setSetting "MISP.redis_port" 6379
|
||||
$CAKE Admin setSetting "MISP.redis_database" 13
|
||||
$CAKE Admin setSetting "MISP.redis_password" ""
|
||||
$CAKE Admin setSetting "MISP.ssdeep_correlation_threshold" 40
|
||||
$CAKE Admin setSetting "MISP.extended_alert_subject" false
|
||||
$CAKE Admin setSetting "MISP.default_event_threat_level" 4
|
||||
$CAKE Admin setSetting "MISP.newUserText" "Dear new MISP user,\\n\\nWe would hereby like to welcome you to the \$org MISP community.\\n\\n Use the credentials below to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nPassword: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
|
||||
$CAKE Admin setSetting "MISP.passwordResetText" "Dear MISP user,\\n\\nA password reset has been triggered for your account. Use the below provided temporary password to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nYour temporary password: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
|
||||
$CAKE Admin setSetting "MISP.enableEventBlacklisting" true
|
||||
$CAKE Admin setSetting "MISP.enableOrgBlacklisting" true
|
||||
$CAKE Admin setSetting "MISP.log_client_ip" false
|
||||
$CAKE Admin setSetting "MISP.log_auth" false
|
||||
$CAKE Admin setSetting "MISP.disableUserSelfManagement" false
|
||||
$CAKE Admin setSetting "MISP.block_event_alert" false
|
||||
$CAKE Admin setSetting "MISP.block_event_alert_tag" "no-alerts=\"true\""
|
||||
$CAKE Admin setSetting "MISP.block_old_event_alert" false
|
||||
$CAKE Admin setSetting "MISP.block_old_event_alert_age" ""
|
||||
$CAKE Admin setSetting "MISP.incoming_tags_disabled_by_default" false
|
||||
$CAKE Admin setSetting "MISP.footermidleft" "This is an autogenerated install"
|
||||
$CAKE Admin setSetting "MISP.footermidright" "Please configure accordingly and do not use in production"
|
||||
$CAKE Admin setSetting "MISP.welcome_text_top" "Autogenerated install, please configure and harden accordingly"
|
||||
$CAKE Admin setSetting "MISP.welcome_text_bottom" "Welcome to MISP on Kali"
|
||||
$CAKE Admin setSetting "Security.password_policy_length" 12
|
||||
$CAKE Admin setSetting "Security.password_policy_complexity" '/^((?=.*\d)|(?=.*\W+))(?![\n])(?=.*[A-Z])(?=.*[a-z]).*$|.{16,}/'
|
||||
$CAKE Admin setSetting "Session.autoRegenerate" 0
|
||||
$CAKE Admin setSetting "Session.timeout" 600
|
||||
$CAKE Admin setSetting "Session.cookie_timeout" 3600
|
||||
$CAKE Live $MISP_LIVE
|
||||
$CAKE Admin updateGalaxies
|
||||
$CAKE Admin updateTaxonomies
|
||||
#$CAKE Admin updateWarningLists
|
||||
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/warninglists/update
|
||||
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/noticelists/update
|
||||
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/objectTemplates/update
|
||||
sed -i -e '$i \echo never > /sys/kernel/mm/transparent_hugepage/enabled\n' /etc/rc.local
|
||||
sed -i -e '$i \echo 1024 > /proc/sys/net/core/somaxconn\n' /etc/rc.local
|
||||
sed -i -e '$i \sysctl vm.overcommit_memory=1\n' /etc/rc.local
|
||||
sed -i -e '$i \sudo -u www-data bash /var/www/MISP/app/Console/worker/start.sh\n' /etc/rc.local
|
||||
sed -i -e '$i \sudo -u www-data misp-modules -l 0.0.0.0 -s &\n' /etc/rc.local
|
||||
$SUDO_WWW bash $PATH_TO_MISP/app/Console/worker/start.sh
|
||||
cd /usr/local/src/
|
||||
git clone https://github.com/MISP/misp-modules.git
|
||||
cd misp-modules
|
||||
# pip3 install
|
||||
pip3 install -I -r REQUIREMENTS
|
||||
pip3 install -I .
|
||||
pip3 install maec lief python-magic wand yara
|
||||
pip3 install git+https://github.com/kbandla/pydeep.git
|
||||
pip3 install stix2
|
||||
gem install pygments.rb
|
||||
gem install asciidoctor-pdf --pre
|
||||
$SUDO_WWW misp-modules -l 0.0.0.0 -s &
|
||||
cd /usr/local/src/
|
||||
apt-get install -y libssl-dev swig python3-ssdeep p7zip-full unrar-free sqlite python3-pyclamd exiftool radare2
|
||||
pip3 install SQLAlchemy PrettyTable python-magic
|
||||
git clone https://github.com/viper-framework/viper.git
|
||||
chown -R $MISP_USER:$MISP_USER viper
|
||||
cd viper
|
||||
$SUDO git submodule update --init --recursive
|
||||
pip3 install -r requirements.txt
|
||||
pip3 uninstall yara -y
|
||||
$SUDO /usr/local/src/viper/viper-cli -h > /dev/null
|
||||
$SUDO /usr/local/src/viper/viper-web -p 8888 -H 0.0.0.0 &
|
||||
echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/src/viper:/var/www/MISP/app/Console"' |tee /etc/environment
|
||||
echo ". /etc/environment" >> /home/${MISP_USER}/.profile
|
||||
$SUDO sed -i "s/^misp_url\ =/misp_url\ =\ http:\/\/localhost/g" /home/${MISP_USER}/.viper/viper.conf
|
||||
$SUDO sed -i "s/^misp_key\ =/misp_key\ =\ $AUTH_KEY/g" /home/${MISP_USER}/.viper/viper.conf
|
||||
|
||||
while [ "$(sqlite3 /home/${MISP_USER}/.viper/admin.db 'UPDATE auth_user SET password="pbkdf2_sha256$100000$iXgEJh8hz7Cf$vfdDAwLX8tko1t0M1TLTtGlxERkNnltUnMhbv56wK/U="'; echo $?)" -ne "0" ]; do
|
||||
# FIXME This might lead to a race condition, the while loop is sub-par
|
||||
chown $MISP_USER:$MISP_USER /home/${MISP_USER}/.viper/admin.db
|
||||
echo "Updating viper-web admin password, giving process time to start-up, sleeping 5, 4, 3,…"
|
||||
sleep 6
|
||||
done
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP
|
||||
chmod -R 750 $PATH_TO_MISP
|
||||
chmod -R g+ws $PATH_TO_MISP/app/tmp
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files/scripts/tmp
|
||||
|
||||
# TODO: fix faup
|
||||
cd /usr/local/src/
|
||||
apt-get install -y cmake
|
||||
git clone https://github.com/MISP/mail_to_misp.git
|
||||
git clone git://github.com/stricaud/faup.git faup
|
||||
chown -R ${MISP_USER}:${MISP_USER} faup mail_to_misp
|
||||
cd faup
|
||||
$SUDO mkdir -p build
|
||||
cd build
|
||||
$SUDO cmake .. && $SUDO make
|
||||
make install
|
||||
ldconfig
|
||||
cd ../../
|
||||
cd mail_to_misp
|
||||
pip3 install -r requirements.txt
|
||||
$SUDO cp mail_to_misp_config.py-example mail_to_misp_config.py
|
||||
sed -i "s/^misp_url\ =\ 'YOUR_MISP_URL'/misp_url\ =\ 'http:\/\/localhost'/g" /usr/local/src/mail_to_misp/mail_to_misp_config.py
|
||||
sed -i "s/^misp_key\ =\ 'YOUR_KEY_HERE'/misp_key\ =\ '$AUTH_KEY'/g" /usr/local/src/mail_to_misp/mail_to_misp_config.py
|
||||
echo ""
|
||||
echo "Admin (root) DB Password: $DBPASSWORD_ADMIN" > /home/${MISP_USER}/mysql.txt
|
||||
echo "User (misp) DB Password: $DBPASSWORD_MISP" >> /home/${MISP_USER}/mysql.txt
|
||||
echo "Authkey: $AUTH_KEY" > /home/${MISP_USER}/MISP-authkey.txt
|
||||
|
||||
clear
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "MISP Installed, access here: https://misp.local"
|
||||
echo "User: admin@admin.test"
|
||||
echo "Password: admin"
|
||||
echo "MISP Dashboard, access here: http://misp.local:8001"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
cat /home/${MISP_USER}/mysql.txt
|
||||
cat /home/${MISP_USER}/MISP-authkey.txt
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "The LOCAL system credentials:"
|
||||
echo "User: ${MISP_USER}"
|
||||
echo "Password: ${MISP_PASSWORD}"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "viper-web installed, access here: http://misp.local:8888"
|
||||
echo "viper-cli configured with your MISP Site Admin Auth Key"
|
||||
echo "User: admin"
|
||||
echo "Password: Password1234"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "To enable outgoing mails via postfix set a permissive SMTP server for the domains you want to contact:"
|
||||
echo ""
|
||||
echo "sudo postconf -e 'relayhost = example.com'"
|
||||
echo "sudo postfix reload"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "Enjoy using MISP. For any issues see here: https://github.com/MISP/MISP/issues"
|
||||
su - misp
|
||||
}
|
||||
|
||||
kaliOnRootR0ckz
|
||||
installMISPonKali
|
|
@ -0,0 +1 @@
|
|||
INSTALL.debian.sh
|
|
@ -1 +0,0 @@
|
|||
../docs/INSTALL.ubuntu1804.with.webmin.md
|
|
@ -904,7 +904,7 @@ CREATE TABLE IF NOT EXISTS `tags` (
|
|||
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`colour` varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`exportable` tinyint(1) NOT NULL,
|
||||
`org_id` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`org_id` int(11) NOT NULL DEFAULT 0,
|
||||
`user_id` int(11) NOT NULL DEFAULT 0,
|
||||
`hide_tag` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,22 @@
|
|||
<VirtualHost *:443>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Require all granted
|
||||
</Directory>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
# SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
</VirtualHost>
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
<VirtualHost *:80>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
<IfModule !mod_php5.c>
|
||||
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
|
||||
DirectoryIndex /index.php index.php
|
||||
<FilesMatch \.php$>
|
||||
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
<IfModule !mod_php5.c>
|
||||
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
|
||||
DirectoryIndex /index.php index.php
|
||||
<FilesMatch \.php$>
|
||||
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/httpd/misp.local_error.log
|
||||
CustomLog /var/log/httpd/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/httpd/misp.local_error.log
|
||||
CustomLog /var/log/httpd/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
</VirtualHost>
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<VirtualHost *:80>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
|
||||
Redirect permanent / https://127.0.0.1
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/httpd/misp.local_error.log
|
||||
CustomLog /var/log/httpd/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost *:443>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
<IfModule !mod_php5.c>
|
||||
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
|
||||
DirectoryIndex /index.php index.php
|
||||
<FilesMatch \.php$>
|
||||
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/pki/tls/certs/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/pki/tls/private/misp.local.key
|
||||
SSLCertificateChainFile /etc/pki/tls/certs/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/httpd/misp.local_error.log
|
||||
CustomLog /var/log/httpd/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
</VirtualHost>
|
|
@ -1,18 +1,18 @@
|
|||
<VirtualHost *:80>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
ServerAdmin me@me.local
|
||||
ServerName misp.local
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
</VirtualHost>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 40fca1d3dabbbb23e13b333bd5c615ca19d7d73f
|
|
@ -0,0 +1 @@
|
|||
Subproject commit bf07ab51207446ed33ea0075083df9bbc2358617
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5ccc654f03086febbec95e3358b7bae80ca9af6f
|
|
@ -0,0 +1 @@
|
|||
../docs/generic
|
|
@ -0,0 +1,5 @@
|
|||
# MISP logos
|
||||
|
||||
MISP logos are licensed under [CC-BY](https://creativecommons.org/licenses/by/4.0/).
|
||||
|
||||
If you are using the MISP logo, don't hesitate to contact us if you have any question.
|
|
@ -0,0 +1,167 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="67.622406mm"
|
||||
height="49.558979mm"
|
||||
viewBox="0 0 67.622406 49.558979"
|
||||
version="1.1"
|
||||
id="svg108"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="misp-logo.svg">
|
||||
<defs
|
||||
id="defs102">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath312-7">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 0,0 H 595.276 V 841.89 H 0 Z"
|
||||
id="path314-0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath1086">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 0,0 H 595.276 V 841.89 H 0 Z"
|
||||
id="path1088" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="-155.06677"
|
||||
inkscape:cy="96.511905"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1025"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata105">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-6.2542725,-124.80979)">
|
||||
<g
|
||||
id="g1076"
|
||||
transform="matrix(0.35277777,0,0,-0.35277777,6.2542725,151.16434)"
|
||||
inkscape:export-filename="/home/adulau/misp.png"
|
||||
inkscape:export-xdpi="100"
|
||||
inkscape:export-ydpi="100">
|
||||
<path
|
||||
d="M 0,0 H 14.014 L 22.629,-14.129 31.245,0 H 45.258 V -40.204 H 31.875 v 19.93 l -9.246,-14.302 h -0.23 l -9.247,14.302 v -19.93 H 0 Z"
|
||||
style="fill:#5f6062;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path1078"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
d="m 24.567932,151.16434 h 4.741334 v 14.18308 h -4.741334 z"
|
||||
style="fill:#5f6062;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28222224"
|
||||
id="path1080"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="/home/adulau/misp.png"
|
||||
inkscape:export-xdpi="100"
|
||||
inkscape:export-ydpi="100" />
|
||||
<g
|
||||
id="g1082"
|
||||
transform="matrix(0.35277777,0,0,-0.35277777,-74.454256,298.51394)"
|
||||
inkscape:export-filename="/home/adulau/misp.png"
|
||||
inkscape:export-xdpi="100"
|
||||
inkscape:export-ydpi="100">
|
||||
<g
|
||||
id="g1084"
|
||||
clip-path="url(#clipPath1086)">
|
||||
<g
|
||||
id="g1090"
|
||||
transform="translate(297.5875,384.2569)">
|
||||
<path
|
||||
d="m 0,0 7.18,8.558 c 4.365,-3.332 9.361,-4.71 14.071,-4.71 2.412,0 3.446,0.631 3.446,1.723 v 0.115 c 0,1.148 -1.263,1.78 -5.571,2.642 C 10.108,10.166 2.183,12.75 2.183,21.25 v 0.115 c 0,7.639 5.973,13.555 17.058,13.555 7.753,0 13.497,-1.838 18.149,-5.514 l -6.547,-9.074 c -3.791,2.756 -8.328,3.962 -12.062,3.962 -2.009,0 -2.928,-0.689 -2.928,-1.665 v -0.115 c 0,-1.091 1.09,-1.781 5.34,-2.585 10.282,-1.895 17.173,-4.882 17.173,-12.98 V 6.834 C 38.366,-1.608 31.417,-6.777 20.619,-6.777 12.464,-6.777 5.112,-4.48 0,0"
|
||||
style="fill:#5f6062;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path1092"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g1094"
|
||||
transform="translate(340.0289,418.4302)">
|
||||
<path
|
||||
d="m 0,0 h 18.091 c 10.683,0 17.977,-4.767 17.977,-14.301 v -0.115 c 0,-9.707 -7.409,-14.876 -18.264,-14.876 H 13.439 V -40.204 H 0 Z m 17.058,-19.7 c 3.446,0 5.743,1.551 5.743,4.422 v 0.115 c 0,2.929 -2.125,4.423 -5.686,4.423 h -3.676 v -8.96 z"
|
||||
style="fill:#5f6062;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path1096"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:3.38666677px;line-height:0%;font-family:sans-serif;-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#5f6062;fill-opacity:1;stroke:none;stroke-width:0.28222224"
|
||||
x="7.8113232"
|
||||
y="172.66331"
|
||||
id="text4094"
|
||||
inkscape:export-filename="/home/adulau/misp.png"
|
||||
inkscape:export-xdpi="100"
|
||||
inkscape:export-ydpi="100"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4096"
|
||||
x="7.8113232"
|
||||
y="172.66331"
|
||||
style="font-size:7.90222216px;line-height:1.25;font-family:sans-serif;stroke-width:0.28222224">Threat Sharing</tspan></text>
|
||||
<g
|
||||
id="g308"
|
||||
transform="matrix(0.17650827,0,0,-0.17650827,-4.3435815,225.27546)">
|
||||
<g
|
||||
id="g310-5"
|
||||
clip-path="url(#clipPath312-7)">
|
||||
<g
|
||||
id="g316"
|
||||
transform="translate(385.579,529.5928)">
|
||||
<path
|
||||
d="m 0,0 h -5.184 v -56.985 c 0,-8.879 -5.16,-16.902 -15.523,-16.902 h -101.465 v -2.709 c 0,-7.851 8.922,-15.763 18.084,-15.763 h 77.581 l 29.678,-17.449 -4.31,17.449 H 0 c 9.156,0 13.287,7.906 13.287,15.763 v 63.068 C 13.287,-5.683 9.156,0 0,0"
|
||||
style="fill:#2fa1db;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path318"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g320-4"
|
||||
transform="translate(349.7253,569.1839)">
|
||||
<path
|
||||
d="m 0,0 h -117.85 c -10.369,0 -22.301,-9.211 -22.301,-18.09 v -71.424 c 0,-8.177 10.11,-14.082 19.807,-14.987 l -6.311,-23.958 40.441,23.786 H 0 c 10.363,0 19.937,6.286 19.937,15.159 v 57.786 13.638 C 19.937,-9.211 10.363,0 0,0 m -99.871,-60.292 c -5.88,0 -10.645,4.766 -10.645,10.646 0,5.88 4.765,10.646 10.645,10.646 5.874,0 10.646,-4.766 10.646,-10.646 0,-5.88 -4.772,-10.646 -10.646,-10.646 m 39.764,0 c -5.88,0 -10.646,4.766 -10.646,10.646 0,5.88 4.766,10.646 10.646,10.646 5.88,0 10.646,-4.766 10.646,-10.646 0,-5.88 -4.766,-10.646 -10.646,-10.646 m 39.77,0 c -5.881,0 -10.652,4.766 -10.652,10.646 0,5.88 4.771,10.646 10.652,10.646 5.868,0 10.645,-4.766 10.645,-10.646 0,-5.88 -4.777,-10.646 -10.645,-10.646"
|
||||
style="fill:#2fa1db;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path322-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.1 KiB |
|
@ -1,341 +0,0 @@
|
|||
INSTALLATION INSTRUCTIONS
|
||||
------------------------- for Ubuntu 16.04-server
|
||||
|
||||
1/ Minimal Ubuntu install
|
||||
-------------------------
|
||||
|
||||
# Install a minimal Ubuntu 16.04-server system with the software:
|
||||
- OpenSSH server
|
||||
|
||||
# Make sure your system is up2date:
|
||||
sudo apt-get update
|
||||
sudo apt-get upgrade
|
||||
|
||||
# install postfix, there will be some questions.
|
||||
sudo apt-get install postfix
|
||||
# Postfix Configuration: Satellite system
|
||||
# change the relay server later with:
|
||||
sudo postconf -e 'relayhost = example.com'
|
||||
sudo postfix reload
|
||||
|
||||
|
||||
2/ Install LAMP & dependencies
|
||||
------------------------------
|
||||
Once the system is installed you can perform the following steps:
|
||||
|
||||
# Install the dependencies: (some might already be installed)
|
||||
sudo apt-get install curl gcc git gnupg-agent make python python3 openssl redis-server sudo vim zip
|
||||
|
||||
# Install MariaDB (a MySQL fork/alternative)
|
||||
sudo apt-get install mariadb-client mariadb-server
|
||||
|
||||
# Secure the MariaDB installation (especially by setting a strong root password)
|
||||
sudo mysql_secure_installation
|
||||
|
||||
# Install Apache2
|
||||
sudo apt-get install apache2 apache2-doc apache2-utils
|
||||
|
||||
# Enable modules, settings, and default of SSL in Apache
|
||||
sudo a2dismod status
|
||||
sudo a2enmod ssl
|
||||
sudo a2enmod rewrite
|
||||
sudo a2enmod headers
|
||||
sudo a2dissite 000-default
|
||||
sudo a2ensite default-ssl
|
||||
|
||||
# Install PHP and dependencies
|
||||
sudo apt-get install libapache2-mod-php php php-cli php-crypt-gpg php-dev php-json php-mysql php-opcache php-readline php-redis php-xml
|
||||
|
||||
# Apply all changes
|
||||
sudo systemctl restart apache2
|
||||
|
||||
3/ MISP code
|
||||
------------
|
||||
# Download MISP using git in the /var/www/ directory.
|
||||
sudo mkdir /var/www/MISP
|
||||
sudo chown www-data:www-data /var/www/MISP
|
||||
cd /var/www/MISP
|
||||
sudo -u www-data git clone https://github.com/MISP/MISP.git /var/www/MISP
|
||||
sudo -u www-data git checkout tags/$(git describe --tags `git rev-list --tags --max-count=1`)
|
||||
# if the last shortcut doesn't work, specify the latest version manually
|
||||
# example: git checkout tags/v2.4.XY
|
||||
# the message regarding a "detached HEAD state" is expected behaviour
|
||||
# (you only have to create a new branch, if you want to change stuff and do a pull request for example)
|
||||
|
||||
# Make git ignore filesystem permission differences
|
||||
sudo -u www-data git config core.filemode false
|
||||
|
||||
# install Mitre's STIX and its dependencies by running the following commands:
|
||||
sudo apt-get install python3-dev python3-pip libxml2-dev libxslt1-dev zlib1g-dev python-setuptools
|
||||
cd /var/www/MISP/app/files/scripts
|
||||
sudo -u www-data git clone https://github.com/CybOXProject/python-cybox.git
|
||||
sudo -u www-data git clone https://github.com/STIXProject/python-stix.git
|
||||
cd /var/www/MISP/app/files/scripts/python-cybox
|
||||
sudo python3 setup.py install
|
||||
cd /var/www/MISP/app/files/scripts/python-stix
|
||||
sudo python3 setup.py install
|
||||
|
||||
# install mixbox to accommodate the new STIX dependencies:
|
||||
cd /var/www/MISP/app/files/scripts/
|
||||
sudo -u www-data git clone https://github.com/CybOXProject/mixbox.git
|
||||
cd /var/www/MISP/app/files/scripts/mixbox
|
||||
sudo python3 setup.py install
|
||||
|
||||
# install PyMISP
|
||||
cd /var/www/MISP/PyMISP
|
||||
sudo python3 setup.py install
|
||||
|
||||
# install support for STIX 2.0
|
||||
sudo pip3 install stix2
|
||||
|
||||
4/ CakePHP
|
||||
-----------
|
||||
# CakePHP is included as a submodule of MISP, execute the following commands to let git fetch it:
|
||||
cd /var/www/MISP
|
||||
sudo -u www-data git submodule init
|
||||
sudo -u www-data git submodule update
|
||||
# Make git ignore filesystem permission differences for submodules
|
||||
sudo -u www-data git submodule foreach git config core.filemode false
|
||||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /var/www/MISP/app
|
||||
sudo -u www-data php composer.phar require kamisama/cake-resque:4.1.2
|
||||
sudo -u www-data php composer.phar config vendor-dir Vendor
|
||||
sudo -u www-data php composer.phar install
|
||||
|
||||
# Enable CakeResque with php-redis
|
||||
sudo phpenmod redis
|
||||
|
||||
# To use the scheduler worker for scheduled tasks, do the following:
|
||||
sudo -u www-data cp -fa /var/www/MISP/INSTALL/setup/config.php /var/www/MISP/app/Plugin/CakeResque/Config/config.php
|
||||
|
||||
# If you have multiple MISP instances on the same system, don't forget to have a different Redis per MISP instance for the CakeResque workers
|
||||
# The default Redis port can be updated in Plugin/CakeResque/Config/config.php
|
||||
|
||||
5/ Set the permissions
|
||||
----------------------
|
||||
|
||||
# Check if the permissions are set correctly using the following commands:
|
||||
sudo chown -R www-data:www-data /var/www/MISP
|
||||
sudo chmod -R 750 /var/www/MISP
|
||||
sudo chmod -R g+ws /var/www/MISP/app/tmp
|
||||
sudo chmod -R g+ws /var/www/MISP/app/files
|
||||
sudo chmod -R g+ws /var/www/MISP/app/files/scripts/tmp
|
||||
|
||||
|
||||
6/ Create a database and user
|
||||
-----------------------------
|
||||
# Enter the mysql shell
|
||||
sudo mysql -u root -p
|
||||
|
||||
MariaDB [(none)]> create database misp;
|
||||
MariaDB [(none)]> grant usage on *.* to misp@localhost identified by 'XXXXdbpasswordhereXXXXX';
|
||||
MariaDB [(none)]> grant all privileges on misp.* to misp@localhost;
|
||||
MariaDB [(none)]> flush privileges;
|
||||
MariaDB [(none)]> exit
|
||||
|
||||
# Import the empty MISP database from MYSQL.sql
|
||||
sudo -u www-data sh -c "mysql -u misp -p misp < /var/www/MISP/INSTALL/MYSQL.sql"
|
||||
# enter the password you've set in line 129 when prompted
|
||||
|
||||
|
||||
7/ Apache configuration
|
||||
-----------------------
|
||||
# Now configure your Apache webserver with the DocumentRoot /var/www/MISP/app/webroot/
|
||||
|
||||
# If the apache version is 2.2:
|
||||
sudo cp /var/www/MISP/INSTALL/apache.22.misp.ssl /etc/apache2/sites-available/misp-ssl.conf
|
||||
|
||||
# If the apache version is 2.4:
|
||||
sudo cp /var/www/MISP/INSTALL/apache.24.misp.ssl /etc/apache2/sites-available/misp-ssl.conf
|
||||
|
||||
# Be aware that the configuration files for apache 2.4 and up have changed.
|
||||
# The configuration file has to have the .conf extension in the sites-available directory
|
||||
# For more information, visit http://httpd.apache.org/docs/2.4/upgrading.html
|
||||
|
||||
# If a valid SSL certificate is not already created for the server, create a self-signed certificate:
|
||||
sudo openssl req -newkey rsa:4096 -days 365 -nodes -x509 \
|
||||
-subj "/C=<Country>/ST=<State>/L=<Locality>/O=<Organization>/OU=<Organizational Unit Name>/CN=<QDN.here>/emailAddress=admin@<your.FQDN.here>" \
|
||||
-keyout /etc/ssl/private/misp.local.key -out /etc/ssl/private/misp.local.crt
|
||||
|
||||
# Please find a sample conf file for an SSL enabled conf file in-line below (alternatively use one of the samples provided in /var/www/MISP/INSTALL
|
||||
|
||||
# Also remember to verify the SSLCertificateChainFile property in your config file - this is usually commented out for the self-generated certificate in the sample configurations, such as the one pasted below.
|
||||
|
||||
# Otherwise, copy the SSLCertificateFile, SSLCertificateKeyFile, and SSLCertificateChainFile to /etc/ssl/private/. (Modify path and config to fit your environment)
|
||||
|
||||
============================================= Begin sample working SSL config for MISP
|
||||
<VirtualHost <IP, FQDN, or *>:80>
|
||||
ServerName <your.FQDN.here>
|
||||
|
||||
Redirect permanent / https://<your.FQDN.here>
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost <IP, FQDN, or *>:443>
|
||||
ServerAdmin admin@<your.FQDN.here>
|
||||
ServerName <your.FQDN.here>
|
||||
DocumentRoot /var/www/MISP/app/webroot
|
||||
<Directory /var/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
# SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
============================================= End sample working SSL config for MISP
|
||||
|
||||
# activate new vhost
|
||||
sudo a2dissite default-ssl
|
||||
sudo a2ensite misp-ssl
|
||||
|
||||
# Restart apache
|
||||
sudo systemctl restart apache2
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
sudo cp /var/www/MISP/INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
|
||||
sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php
|
||||
sudo -u www-data cp -a /var/www/MISP/app/Config/database.default.php /var/www/MISP/app/Config/database.php
|
||||
sudo -u www-data cp -a /var/www/MISP/app/Config/core.default.php /var/www/MISP/app/Config/core.php
|
||||
sudo -u www-data cp -a /var/www/MISP/app/Config/config.default.php /var/www/MISP/app/Config/config.php
|
||||
|
||||
# Configure the fields in the newly created files:
|
||||
sudo -u www-data vim /var/www/MISP/app/Config/database.php
|
||||
# DATABASE_CONFIG has to be filled
|
||||
# With the default values provided in section 6, this would look like:
|
||||
# class DATABASE_CONFIG {
|
||||
# public $default = array(
|
||||
# 'datasource' => 'Database/Mysql',
|
||||
# 'persistent' => false,
|
||||
# 'host' => 'localhost',
|
||||
# 'login' => 'misp', // grant usage on *.* to misp@localhost
|
||||
# 'port' => 3306,
|
||||
# 'password' => 'XXXXdbpasswordhereXXXXX', // identified by 'XXXXdbpasswordhereXXXXX';
|
||||
# 'database' => 'misp', // create database misp;
|
||||
# 'prefix' => '',
|
||||
# 'encoding' => 'utf8',
|
||||
# );
|
||||
#}
|
||||
|
||||
# Important! Change the salt key in /var/www/MISP/app/Config/config.php
|
||||
# The salt key must be a string at least 32 bytes long.
|
||||
# The admin user account will be generated on the first login, make sure that the salt is changed before you create that user
|
||||
# If you forget to do this step, and you are still dealing with a fresh installation, just alter the salt,
|
||||
# you can reset the admin password with the following command
|
||||
/var/www/MISP/app/Console/cake Password admin@admin.test Password1234
|
||||
|
||||
# Change baseurl
|
||||
/var/www/MISP/app/Console/cake Baseurl https://<your.FQDN.here>
|
||||
# alternatively, you can leave this field empty if you would like to use relative pathing in MISP.
|
||||
# This however is highly advised against.
|
||||
|
||||
# and make sure the file permissions are still OK
|
||||
sudo chown -R www-data:www-data /var/www/MISP/app/Config
|
||||
sudo chmod -R 750 /var/www/MISP/app/Config
|
||||
|
||||
# Generate a GPG encryption key.
|
||||
sudo -u www-data mkdir /var/www/MISP/.gnupg
|
||||
sudo chmod 700 /var/www/MISP/.gnupg
|
||||
sudo -u www-data gpg --homedir /var/www/MISP/.gnupg --gen-key
|
||||
# The email address should match the one set in the config.php / set in the configuration menu in the administration menu configuration file
|
||||
|
||||
# NOTE: if entropy is not high enough, you can install rng-tools and then run rngd -r /dev/urandom do fix it quickly
|
||||
|
||||
# And export the public key to the webroot
|
||||
sudo -u www-data sh -c "gpg --homedir /var/www/MISP/.gnupg --export --armor YOUR-KEYS-EMAIL-HERE > /var/www/MISP/app/webroot/gpg.asc"
|
||||
|
||||
# To make the background workers start on boot
|
||||
sudo chmod +x /var/www/MISP/app/Console/worker/start.sh
|
||||
sudo vim /etc/rc.local
|
||||
# Add the following line before the last line (exit 0). Make sure that you replace www-data with your apache user:
|
||||
sudo -u www-data bash /var/www/MISP/app/Console/worker/start.sh
|
||||
|
||||
# Now log in using the webinterface:
|
||||
# The default user/pass = admin@admin.test/admin
|
||||
|
||||
# Using the server settings tool in the admin interface (Administration -> Server Settings), set MISP up to your preference
|
||||
# It is especially vital that no critical issues remain!
|
||||
# start the workers by navigating to the workers tab and clicking restart all workers
|
||||
|
||||
# Don't forget to change the email, password and authentication key after installation.
|
||||
|
||||
# Once done, have a look at the diagnostics
|
||||
|
||||
# If any of the directories that MISP uses to store files is not writeable to the apache user, change the permissions
|
||||
# you can do this by running the following commands:
|
||||
|
||||
sudo chmod -R 750 /var/www/MISP/<directory path with an indicated issue>
|
||||
sudo chown -R www-data:www-data /var/www/MISP/<directory path with an indicated issue>
|
||||
|
||||
# Make sure that the STIX libraries and GnuPG work as intended, if not, refer to INSTALL.txt's paragraphs dealing with these two items
|
||||
|
||||
# If anything goes wrong, make sure that you check MISP's logs for errors:
|
||||
# /var/www/MISP/app/tmp/logs/error.log
|
||||
# /var/www/MISP/app/tmp/logs/resque-worker-error.log
|
||||
# /var/www/MISP/app/tmp/logs/resque-scheduler-error.log
|
||||
# /var/www/MISP/app/tmp/logs/resque-2015-01-01.log // where the actual date is the current date
|
||||
|
||||
|
||||
Recommended actions
|
||||
-------------------
|
||||
- By default CakePHP exposes its name and version in email headers. Apply a patch to remove this behavior.
|
||||
|
||||
- You should really harden your OS
|
||||
- You should really harden the configuration of Apache
|
||||
- You should really harden the configuration of MySQL/MariaDB
|
||||
- Keep your software up2date (OS, MISP, CakePHP and everything else)
|
||||
- Log and audit
|
||||
|
||||
|
||||
Optional features
|
||||
-----------------
|
||||
# MISP has a new pub/sub feature, using ZeroMQ. To enable it, simply run the following command
|
||||
sudo pip install pyzmq
|
||||
# ZeroMQ depends on the Python client for Redis
|
||||
sudo pip install redis
|
||||
|
||||
# For the experimental ssdeep correlations, run the following installation:
|
||||
# installing ssdeep
|
||||
wget http://downloads.sourceforge.net/project/ssdeep/ssdeep-2.13/ssdeep-2.13.tar.gz
|
||||
tar zxvf ssdeep-2.13.tar.gz
|
||||
cd ssdeep-2.13
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
ssdeep -h # test
|
||||
|
||||
#installing ssdeep_php
|
||||
sudo pecl install ssdeep
|
||||
|
||||
# You should add "extension=ssdeep.so" to mods-available - Check /etc/php for your current version
|
||||
echo "extension=ssdeep.so" | sudo tee /etc/php/7.2/mods-available/ssdeep.ini
|
||||
sudo phpenmod ssdeep
|
||||
sudo service apache2 restart
|
||||
|
||||
Optional features: misp-modules
|
||||
-------------------------------
|
||||
# If you want to add the misp modules functionality, follow the setup procedure described in misp-modules:
|
||||
# https://github.com/MISP/misp-modules#how-to-install-and-start-misp-modules
|
||||
# Then the enrichment, export and import modules can be enabled in MISP via the settings.
|
|
@ -0,0 +1 @@
|
|||
../../docs/archive/INSTALL.ubuntu1604.md
|
|
@ -1 +1 @@
|
|||
../../docs/old-2_3to2_4-UPGRADE.md
|
||||
../../docs/archive/old-2_3to2_4-UPGRADE.md
|
|
@ -1,490 +0,0 @@
|
|||
INSTALLATION INSTRUCTIONS
|
||||
------------------------- for FreeBSD 11.2-amd64
|
||||
|
||||
0/ WIP /!\ You are warned, this does not work yet! /!\
|
||||
|
||||
NOT working: pydeep, lief, py-yara, MAEC
|
||||
|
||||
1/ Minimal FreeBSD install
|
||||
--------------------------
|
||||
|
||||
# Install standard FreeBSD-amd64 with:
|
||||
- sshd
|
||||
- ntpd
|
||||
- ports
|
||||
|
||||
# System Hardening
|
||||
|
||||
- Clean /tmp
|
||||
- Disable Syslogd network socket
|
||||
- Disable Sendmail service
|
||||
|
||||
# Install pkg and point to latest
|
||||
|
||||
Install pkg by typing:
|
||||
```
|
||||
$ su -
|
||||
# pkg
|
||||
```
|
||||
|
||||
# Install sudo
|
||||
|
||||
pkg install sudo
|
||||
|
||||
# Install bash
|
||||
|
||||
sudo pkg install bash
|
||||
|
||||
Make sure users in group wheel can sudo, uncomment in /usr/local/etc/sudoers :
|
||||
```
|
||||
%wheel ALL=(ALL) ALL
|
||||
```
|
||||
|
||||
# Update system
|
||||
```
|
||||
sudo freebsd-update fetch install
|
||||
```
|
||||
|
||||
# Make python3 default
|
||||
|
||||
echo "DEFAULT_VERSIONS= python=3.6 python2=2.7 python3=3.6" >> /etc/make.conf
|
||||
sudo ln -s /usr/local/bin/python3 /usr/local/bin/python
|
||||
|
||||
# Install postfix
|
||||
```
|
||||
sudo pkg install postfix
|
||||
|
||||
# Optional but useful, add a local misp user
|
||||
sudo pw user add misp -s /usr/local/bin/bash -G wheel,www
|
||||
sudo mkdir /home/misp ; sudo chown misp:misp /home/misp
|
||||
sudo passwd misp
|
||||
```
|
||||
|
||||
# FAMP
|
||||
## Install misc dependencies
|
||||
```
|
||||
sudo pkg install curl git python3 vim m4 help2man gmake automake libtool
|
||||
```
|
||||
|
||||
/!\ N.B: MariaDB 10.3 currently segfaults on 11.2: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=229219
|
||||
|
||||
```
|
||||
sudo pkg install apache24 \
|
||||
logrotate \
|
||||
gnupg \
|
||||
mariadb102-server mariadb102-client \
|
||||
php72 \
|
||||
php72-mysqli \
|
||||
php72-xml \
|
||||
php72-openssl \
|
||||
php72-pcntl \
|
||||
php72-mbstring \
|
||||
php72-pdo_mysql \
|
||||
php72-phar \
|
||||
php72-json \
|
||||
php72-filter \
|
||||
php72-dom \
|
||||
php72-opcache \
|
||||
php72-session \
|
||||
mod_php72
|
||||
|
||||
sudo cp -p /usr/local/etc/php.ini-development /usr/local/etc/php.ini
|
||||
|
||||
sudo sysrc apache24_enable="yes"
|
||||
sudo sysrc mysql_enable="yes"
|
||||
sudo sysrc mysql_args="--bind-address=127.0.0.1"
|
||||
sudo service apache24 start
|
||||
sudo service mysql-server start
|
||||
sudo /usr/local/bin/mysql_secure_installation
|
||||
```
|
||||
|
||||
```
|
||||
sudo vi /usr/local/etc/apache24/Includes/php.conf
|
||||
```
|
||||
|
||||
Add:
|
||||
```
|
||||
<IfModule dir_module>
|
||||
DirectoryIndex index.php index.html
|
||||
|
||||
<FilesMatch "\.php$">
|
||||
SetHandler application/x-httpd-php
|
||||
</FilesMatch>
|
||||
|
||||
<FilesMatch "\.phps$">
|
||||
SetHandler application/x-httpd-php-source
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
```
|
||||
|
||||
|
||||
## Redis need to be installed via ports
|
||||
|
||||
```
|
||||
cd /usr/ports/databases/redis
|
||||
sudo make install clean
|
||||
sudo sysrc redis_enable="yes"
|
||||
```
|
||||
|
||||
### php-redis
|
||||
```
|
||||
cd /use/ports/databases/pecl-redis
|
||||
sudo make install clean
|
||||
```
|
||||
|
||||
## Maybe needed, had to add the path for php CLI to work…
|
||||
add this: PATH=$PATH:/usr/local/bin
|
||||
to: /usr/local/etc/apache24/envvars.d/php.env
|
||||
|
||||
|
||||
```
|
||||
sudo service apache24 restart
|
||||
```
|
||||
|
||||
3/ MISP code
|
||||
------------
|
||||
|
||||
# Download MISP using git in the /usr/local/www/ directory.
|
||||
sudo mkdir /usr/local/www/MISP
|
||||
sudo chown www:www /usr/local/www/MISP
|
||||
cd /usr/local/www/MISP
|
||||
sudo -u www git clone https://github.com/MISP/MISP.git /usr/local/www/MISP
|
||||
|
||||
# Make git ignore filesystem permission differences
|
||||
sudo -u www git config core.filemode false
|
||||
|
||||
# install Mitre's STIX and its dependencies by running the following commands:
|
||||
##sudo apt-get install python-dev zlib1g-dev python-setuptools
|
||||
sudo pkg install py27-pip py36-pip libxml2 libxslt
|
||||
|
||||
cd /usr/local/www/MISP/app/files/scripts
|
||||
sudo -u www git clone https://github.com/CybOXProject/python-cybox.git
|
||||
sudo -u www git clone https://github.com/STIXProject/python-stix.git
|
||||
cd /usr/local/www/MISP/app/files/scripts/python-cybox
|
||||
sudo python3 setup.py install
|
||||
cd /usr/local/www/MISP/app/files/scripts/python-stix
|
||||
sudo python3 setup.py install
|
||||
|
||||
# install mixbox to accommodate the new STIX dependencies:
|
||||
cd /usr/local/www/MISP/app/files/scripts/
|
||||
sudo -u www git clone https://github.com/CybOXProject/mixbox.git
|
||||
cd /usr/local/www/MISP/app/files/scripts/mixbox
|
||||
sudo python3 setup.py install
|
||||
|
||||
|
||||
|
||||
4/ CakePHP
|
||||
-----------
|
||||
# CakePHP is included as a submodule of MISP, execute the following commands to let git fetch it:
|
||||
cd /usr/local/www/MISP
|
||||
sudo -u www git submodule update --init --recursive
|
||||
# Make git ignore filesystem permission differences for submodules
|
||||
sudo -u www git submodule foreach --recursive git config core.filemode false
|
||||
|
||||
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
|
||||
cd /usr/local/www/MISP/app
|
||||
sudo -u www php composer.phar require kamisama/cake-resque:4.1.2
|
||||
sudo -u www php composer.phar config vendor-dir Vendor
|
||||
sudo -u www php composer.phar install
|
||||
|
||||
# To use the scheduler worker for scheduled tasks, do the following:
|
||||
sudo -u www cp -fa /usr/local/www/MISP/INSTALL/setup/config.php /usr/local/www/MISP/app/Plugin/CakeResque/Config/config.php
|
||||
|
||||
5/ Set the permissions
|
||||
----------------------
|
||||
|
||||
# Check if the permissions are set correctly using the following commands:
|
||||
sudo chown -R www:www /usr/local/www/MISP
|
||||
sudo chmod -R 750 /usr/local/www/MISP
|
||||
sudo chmod -R g+ws /usr/local/www/MISP/app/tmp
|
||||
sudo chmod -R g+ws /usr/local/www/MISP/app/files
|
||||
sudo chmod -R g+ws /usr/local/www/MISP/app/files/scripts/tmp
|
||||
|
||||
6/ Create a database and user
|
||||
-----------------------------
|
||||
# Enter the mysql shell
|
||||
sudo mysql -u root -p
|
||||
|
||||
MariaDB [(none)]> create database misp;
|
||||
MariaDB [(none)]> grant usage on *.* to misp@localhost identified by 'XXXXdbpasswordhereXXXXX';
|
||||
MariaDB [(none)]> grant all privileges on misp.* to misp@localhost;
|
||||
MariaDB [(none)]> flush privileges;
|
||||
MariaDB [(none)]> exit
|
||||
|
||||
# Import the empty MISP database from MYSQL.sql
|
||||
sudo -u www sh -c "mysql -u misp -p misp < /usr/local/www/MISP/INSTALL/MYSQL.sql"
|
||||
# enter the password you set previously
|
||||
|
||||
|
||||
7/ Apache configuration
|
||||
-----------------------
|
||||
```
|
||||
# Now configure your Apache webserver with the DocumentRoot /usr/local/www/MISP/app/webroot/
|
||||
|
||||
#2.4
|
||||
sudo mkdir /usr/local/etc/apache24/sites-available/ /usr/local/etc/apache24/sites-enabled/
|
||||
|
||||
# If the apache version is 2.4:
|
||||
sudo cp /usr/local/www/MISP/INSTALL/apache.24.misp.ssl /usr/local/etc/apache24/sites-available/misp-ssl.conf
|
||||
|
||||
# Be aware that the configuration files for apache 2.4 and up have changed.
|
||||
# The configuration file has to have the .conf extension in the sites-available directory
|
||||
# For more information, visit http://httpd.apache.org/docs/2.4/upgrading.html
|
||||
|
||||
sudo mkdir /etc/ssl/private/
|
||||
# If a valid SSL certificate is not already created for the server, create a self-signed certificate: (Make sure to fill the <…>)
|
||||
sudo openssl req -newkey rsa:4096 -days 365 -nodes -x509 \
|
||||
-subj "/C=<Country>/ST=<State>/L=<Locality>/O=<Organization>/OU=<Organizational Unit Name>/CN=<QDN.here>/emailAddress=admin@<your.FQDN.here>" \
|
||||
-keyout /etc/ssl/private/misp.local.key -out /etc/ssl/private/misp.local.crt
|
||||
|
||||
sudo chmod 750 /etc/ssl/private/
|
||||
sudo chmod 640 /etc/ssl/private/*
|
||||
|
||||
# Otherwise, copy the SSLCertificateFile, SSLCertificateKeyFile, and SSLCertificateChainFile to /etc/ssl/private/. (Modify path and config to fit your environment)
|
||||
|
||||
sudo mkdir /var/log/apache24/
|
||||
```
|
||||
|
||||
Now edit: /usr/local/etc/apache24/sites-available/misp-ssl.conf to reflect the below.
|
||||
Make sure the ssl fqdn will reflect what you entered as a CN in the SSL-Cert.
|
||||
You might see this: "AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message"
|
||||
Edit:
|
||||
|
||||
```
|
||||
============================================= Begin sample working SSL config for MISP
|
||||
<VirtualHost <IP, FQDN, or *>:80>
|
||||
ServerName <your.FQDN.here>
|
||||
|
||||
Redirect permanent / https://<your.FQDN.here>
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache24/misp.local_error.log
|
||||
CustomLog /var/log/apache24/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost <IP, FQDN, or *>:443>
|
||||
ServerAdmin admin@<your.FQDN.here>
|
||||
ServerName <your.FQDN.here>
|
||||
DocumentRoot /usr/local/www/MISP/app/webroot
|
||||
<Directory /usr/local/www/MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
# SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache24/misp.local_error.log
|
||||
CustomLog /var/log/apache24/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
============================================= End sample working SSL config for MISP
|
||||
```
|
||||
|
||||
```
|
||||
# activate new vhost
|
||||
cd /usr/local/etc/apache24/sites-enabled/
|
||||
sudo ln -s ../sites-available/misp-ssl.conf
|
||||
echo "Include etc/apache24/sites-enabled/*.conf" >> /usr/local/etc/apache24/httpd.conf
|
||||
echo "IncludeOptional etc/apache24/sites-enabled/*.conf" >> /usr/local/etc/apache24/httpd.conf
|
||||
|
||||
sudo vi /usr/local/etc/apache24/httpd.conf
|
||||
/!\ Enable mod_rewrite in httpd.conf /!\
|
||||
LoadModule rewrite_module libexec/apache24/mod_rewrite.so
|
||||
LoadModule ssl_module libexec/apache24/mod_ssl.so
|
||||
Listen 443
|
||||
|
||||
# Restart apache
|
||||
sudo service apache24 restart
|
||||
```
|
||||
|
||||
8/ Log rotation
|
||||
---------------
|
||||
# MISP saves the stdout and stderr of its workers in /usr/local/www/MISP/app/tmp/logs
|
||||
# To rotate these logs install the supplied logrotate script:
|
||||
|
||||
sudo cp /usr/local/www/MISP/INSTALL/misp.logrotate /usr/local/etc/logrotate.d/misp
|
||||
chmod 0640 /usr/local/etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
---------------------
|
||||
# There are 4 sample configuration files in /usr/local/www/MISP/app/Config that need to be copied
|
||||
sudo -u www cp -a /usr/local/www/MISP/app/Config/bootstrap.default.php /usr/local/www/MISP/app/Config/bootstrap.php
|
||||
sudo -u www cp -a /usr/local/www/MISP/app/Config/database.default.php /usr/local/www/MISP/app/Config/database.php
|
||||
sudo -u www cp -a /usr/local/www/MISP/app/Config/core.default.php /usr/local/www/MISP/app/Config/core.php
|
||||
sudo -u www cp -a /usr/local/www/MISP/app/Config/config.default.php /usr/local/www/MISP/app/Config/config.php
|
||||
|
||||
# Configure the fields in the newly created files:
|
||||
sudo -u www vim /usr/local/www/MISP/app/Config/database.php
|
||||
# DATABASE_CONFIG has to be filled
|
||||
# With the default values provided in section 6, this would look like:
|
||||
# class DATABASE_CONFIG {
|
||||
# public $default = array(
|
||||
# 'datasource' => 'Database/Mysql',
|
||||
# 'persistent' => false,
|
||||
# 'host' => 'localhost',
|
||||
# 'login' => 'misp', // grant usage on *.* to misp@localhost
|
||||
# 'port' => 3306,
|
||||
# 'password' => 'XXXXdbpasswordhereXXXXX', // identified by 'XXXXdbpasswordhereXXXXX';
|
||||
# 'database' => 'misp', // create database misp;
|
||||
# 'prefix' => '',
|
||||
# 'encoding' => 'utf8',
|
||||
# );
|
||||
#}
|
||||
|
||||
# Important! Change the salt key in /usr/local/www/MISP/app/Config/config.php
|
||||
# The salt key must be a string at least 32 bytes long.
|
||||
# The admin user account will be generated on the first login, make sure that the salt is changed before you create that user
|
||||
# If you forget to do this step, and you are still dealing with a fresh installation, just alter the salt,
|
||||
# delete the user from mysql and log in again using the default admin credentials (admin@admin.test / admin)
|
||||
|
||||
# Change base url in config.php
|
||||
sudo -u www vim /usr/local/www/MISP/app/Config/config.php
|
||||
# example: 'baseurl' => 'https://<your.FQDN.here>',
|
||||
# alternatively, you can leave this field empty if you would like to use relative pathing in MISP
|
||||
# 'baseurl' => '',
|
||||
|
||||
# and make sure the file permissions are still OK
|
||||
sudo chown -R www:www /usr/local/www/MISP/app/Config
|
||||
sudo chmod -R 750 /usr/local/www/MISP/app/Config
|
||||
|
||||
# Generate a GPG encryption key.
|
||||
sudo -u www mkdir /usr/local/www/MISP/.gnupg
|
||||
sudo chmod 700 /usr/local/www/MISP/.gnupg
|
||||
##### sudo -u www gpg --homedir /usr/local/www/MISP/.gnupg --gen-key <- Broken
|
||||
# The email address should match the one set in the config.php / set in the configuration menu in the administration menu configuration file
|
||||
|
||||
# And export the public key to the webroot
|
||||
sudo -u www sh -c "gpg --homedir /usr/local/www/MISP/.gnupg --export --armor YOUR-KEYS-EMAIL-HERE > /usr/local/www/MISP/app/webroot/gpg.asc"
|
||||
|
||||
# To make the background workers start on boot
|
||||
sudo chmod +x /usr/local/www/MISP/app/Console/worker/start.sh
|
||||
sudo vim /etc/rc.local
|
||||
# Add the following line before the last line (exit 0). Make sure that you replace www with your apache user:
|
||||
sudo -u www bash /usr/local/www/MISP/app/Console/worker/start.sh
|
||||
|
||||
# Now log in using the webinterface:
|
||||
# The default user/pass = admin@admin.test/admin
|
||||
|
||||
# Using the server settings tool in the admin interface (Administration -> Server Settings), set MISP up to your preference
|
||||
# It is especially vital that no critical issues remain!
|
||||
# start the workers by navigating to the workers tab and clicking restart all workers
|
||||
|
||||
# Don't forget to change the email, password and authentication key after installation.
|
||||
|
||||
# Once done, have a look at the diagnostics
|
||||
|
||||
# If any of the directories that MISP uses to store files is not writeable to the apache user, change the permissions
|
||||
# you can do this by running the following commands:
|
||||
|
||||
sudo chmod -R 750 /usr/local/www/MISP/<directory path with an indicated issue>
|
||||
sudo chown -R www:www /usr/local/www/MISP/<directory path with an indicated issue>
|
||||
|
||||
# Make sure that the STIX libraries and GnuPG work as intended, if not, refer to INSTALL.txt's paragraphs dealing with these two items
|
||||
|
||||
# If anything goes wrong, make sure that you check MISP's logs for errors:
|
||||
# /usr/local/www/MISP/app/tmp/logs/error.log
|
||||
# /usr/local/www/MISP/app/tmp/logs/resque-worker-error.log
|
||||
# /usr/local/www/MISP/app/tmp/logs/resque-scheduler-error.log
|
||||
# /usr/local/www/MISP/app/tmp/logs/resque-2015-01-01.log // where the actual date is the current date
|
||||
|
||||
set PATH_TO_MISP='/usr/local/www/MISP'
|
||||
set MISP_BASEURL=''
|
||||
set MISP_LIVE='1'
|
||||
set FQDN='localhost'
|
||||
|
||||
|
||||
# Enable Enrichment set better timeouts
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Enrichment_services_enable" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Enrichment_hover_enable" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Enrichment_timeout" 300
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Enrichment_hover_timeout" 150
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Enrichment_cve_enabled" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Enrichment_dns_enabled" true
|
||||
|
||||
# Enable Import modules set better timout
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Import_services_enable" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Import_timeout" 300
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Import_ocr_enabled" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Import_csvimport_enabled" true
|
||||
|
||||
# Enable Export modules set better timout
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Export_services_enable" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Export_timeout" 300
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Plugin.Export_pdfexport_enabled" true
|
||||
|
||||
sudo $PATH_TO_MISP/app/Console/cake Live $MISP_LIVE
|
||||
|
||||
|
||||
# Enable installer org and tune some configurables
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.host_org_id" 1
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.email" "info@admin.test"
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.disable_emailing" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.contact" "info@admin.test"
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.disablerestalert" true
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.showCorrelationsOnIndex" true
|
||||
|
||||
# Force defaults to make MISP Server Settings less RED
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.language" "eng"
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.proposals_block_attributes" false
|
||||
## Redis block
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.redis_host" "127.0.0.1"
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.redis_port" 6379
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.redis_database" 13
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "MISP.redis_password" ""
|
||||
|
||||
# Tune global time outs
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Session.autoRegenerate" 0
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Session.timeout" 600
|
||||
sudo $PATH_TO_MISP/app/Console/cake Admin setSetting "Session.cookie_timeout" 3600
|
||||
|
||||
|
||||
Recommended actions
|
||||
-------------------
|
||||
- By default CakePHP exposes its name and version in email headers. Apply a patch to remove this behavior.
|
||||
|
||||
- You should really harden your OS
|
||||
- You should really harden the configuration of Apache
|
||||
- You should really harden the configuration of MySQL/MariaDB
|
||||
- Keep your software up2date (OS, MISP, CakePHP and everything else)
|
||||
- Log and audit
|
||||
|
||||
10/ MISP modulesß
|
||||
|
||||
sudo pkg install yara
|
||||
sudo mkdir /usr/local/src/
|
||||
cd /usr/local/src/
|
||||
sudo git clone https://github.com/MISP/misp-modules.git
|
||||
cd misp-modules
|
||||
# pip3 install
|
||||
sudo pip-3.6 install -I -r REQUIREMENTS
|
||||
sudo pip-3.6 install -I .
|
||||
##sudo pip-3.6 install lief
|
||||
sudo pip-3.6 install maec
|
||||
sudo pip-3.6 install pymisp python-magic wand yara
|
||||
##sudo pip-3.6 install git+https://github.com/kbandla/pydeep.git
|
||||
|
||||
# pip2 install
|
||||
sudo pip-2.7 install pymisp python-magic wand yara
|
||||
##sudo pip-2.7 install git+https://github.com/kbandla/pydeep.git
|
||||
##sudo pip-2.7 install lief
|
||||
# install STIX2.0 library to support STIX 2.0 export:
|
||||
sudo pip-3.6 install stix2
|
||||
|
||||
Add this to rc.local:
|
||||
|
||||
```
|
||||
sudo -u www misp-modules -l 0.0.0.0 -s &
|
||||
```
|
||||
|
||||
Optional features
|
||||
-------------------
|
||||
# MISP has a new pub/sub feature, using ZeroMQ. To enable it, simply run the following command
|
||||
sudo pkg install libzmq4
|
||||
# ZeroMQ depends on the Python client for Redis
|
|
@ -0,0 +1 @@
|
|||
../../docs/archive/xINSTALL.FreeBSD.md
|
|
@ -0,0 +1 @@
|
|||
../docs/xINSTALL.debian9.md
|
|
@ -0,0 +1,620 @@
|
|||
#!/usr/bin/env bash
|
||||
#INSTALLATION INSTRUCTIONS
|
||||
#------------------------- for Tsurugi Linux
|
||||
#
|
||||
#0/ Quick MISP Instance on Tsurugi Linux - Status
|
||||
#---------------------------------------------
|
||||
#
|
||||
#1/ Prepare Tsurugi with a MISP User
|
||||
#--------------------------------
|
||||
# You will need a working OpenSSH server, reconfigure as follows:
|
||||
# sudo update-rc.d -f ssh remove
|
||||
# sudo update-rc.d -f ssh defaults
|
||||
# sudo dpkg-reconfigure openssh-server
|
||||
# sudo systemctl restart ssh
|
||||
# If you installed tsurugi the locale is a little all over the place. I assume en_US to be default unless you know what you're doing.
|
||||
# sudo sed -i 's/ja_JP/en_US/g' /etc/default/locale
|
||||
# sudo sed -i 's/ja_JP.UTF/# ja_JP.UTF/g' /etc/locale.gen
|
||||
# sudo dpkg-reconfigure locales
|
||||
# To install MISP on Tsurugi copy paste this in your r00t shell:
|
||||
# wget -O /tmp/misp-tsurugi.sh https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/INSTALL.tsurugi.txt && bash /tmp/misp-tsurugi.sh
|
||||
# /!\ Please read the installer script before randomly doing the above.
|
||||
# The script is tested on a plain vanilla Tsurugi Linux Boot CD and installs quite a few dependencies.
|
||||
|
||||
MISP_USER='misp'
|
||||
MISP_PASSWORD='Password1234'
|
||||
|
||||
function tsurugiOnRootR0ckz() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
elif [[ $(id $MISP_USER >/dev/null; echo $?) -ne 0 ]]; then
|
||||
useradd -s /bin/bash -m -G adm,cdrom,sudo,dip,plugdev,www-data $MISP_USER
|
||||
echo $MISP_USER:$MISP_PASSWORD | chpasswd
|
||||
else
|
||||
echo "User ${MISP_USER} exists, skipping creation"
|
||||
adduser $MISP_USER www-data
|
||||
fi
|
||||
}
|
||||
|
||||
function installMISPonTsurugi() {
|
||||
# MISP configuration variables
|
||||
PATH_TO_MISP='/var/www/MISP'
|
||||
MISP_BASEURL='https://misp.local'
|
||||
MISP_LIVE='1'
|
||||
CAKE="$PATH_TO_MISP/app/Console/cake"
|
||||
|
||||
# Database configuration
|
||||
DBHOST='localhost'
|
||||
DBNAME='misp'
|
||||
DBUSER_ADMIN='root'
|
||||
DBPASSWORD_ADMIN="$(openssl rand -hex 32)"
|
||||
DBUSER_MISP='misp'
|
||||
DBPASSWORD_MISP="$(openssl rand -hex 32)"
|
||||
|
||||
# Webserver configuration
|
||||
FQDN='misp.local'
|
||||
|
||||
# OpenSSL configuration
|
||||
OPENSSL_CN=$FQDN
|
||||
OPENSSL_C='LU'
|
||||
OPENSSL_ST='State'
|
||||
OPENSSL_L='Location'
|
||||
OPENSSL_O='Organization'
|
||||
OPENSSL_OU='Organizational Unit'
|
||||
OPENSSL_EMAILADDRESS='info@localhost'
|
||||
|
||||
# GPG configuration
|
||||
GPG_REAL_NAME='Autogenerated Key'
|
||||
GPG_COMMENT='WARNING: MISP AutoGenerated Key consider this Key VOID!'
|
||||
GPG_EMAIL_ADDRESS='admin@admin.test'
|
||||
GPG_KEY_LENGTH='2048'
|
||||
GPG_PASSPHRASE='Password1234'
|
||||
|
||||
# php.ini configuration
|
||||
upload_max_filesize=50M
|
||||
post_max_size=50M
|
||||
max_execution_time=300
|
||||
memory_limit=512M
|
||||
PHP_INI=/etc/php/7.0/apache2/php.ini
|
||||
|
||||
# apt config
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# sudo config to run $LUSER commands
|
||||
SUDO="sudo -H -u ${MISP_USER}"
|
||||
SUDO_WWW="sudo -H -u www-data"
|
||||
|
||||
echo "Admin (${DBUSER_ADMIN}) DB Password: ${DBPASSWORD_ADMIN}"
|
||||
echo "User (${DBUSER_MISP}) DB Password: ${DBPASSWORD_MISP}"
|
||||
|
||||
echo "-----------------------------------------------------------------------"
|
||||
echo "Disabling sleep etc…"
|
||||
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0
|
||||
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-timeout 0
|
||||
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing'
|
||||
xset s 0 0
|
||||
xset dpms 0 0
|
||||
xset s off
|
||||
apt update
|
||||
apt install -qy etckeeper
|
||||
# Skip dist-upgrade for now, pulls in 500+ updated packages
|
||||
#sudo apt -y dist-upgrade
|
||||
git config --global user.email "root@tsurugi.lan"
|
||||
git config --global user.name "Root User"
|
||||
apt install -qy postfix
|
||||
|
||||
apt install -qy \
|
||||
curl gcc git gnupg-agent make openssl redis-server zip libyara-dev python3-yara python3-redis python3-zmq \
|
||||
mariadb-client \
|
||||
mariadb-server \
|
||||
apache2 apache2-doc apache2-utils \
|
||||
libapache2-mod-php7.0 php7.0 php7.0-cli php7.0-mbstring php-pear php7.0-dev php7.0-json php7.0-xml php7.0-mysql php7.0-opcache php7.0-readline \
|
||||
python3-dev python3-pip libpq5 libjpeg-dev libfuzzy-dev ruby asciidoctor \
|
||||
libxml2-dev libxslt1-dev zlib1g-dev python3-setuptools expect
|
||||
|
||||
apt install -qy haveged
|
||||
systemctl restart haveged
|
||||
|
||||
systemctl restart mysql.service
|
||||
|
||||
a2dismod status
|
||||
a2enmod ssl rewrite headers
|
||||
a2dissite 000-default
|
||||
a2ensite default-ssl
|
||||
|
||||
pear channel-update pear.php.net
|
||||
pear install Crypt_GPG
|
||||
pecl channel-update pecl.php.net
|
||||
|
||||
yes '' |pecl install redis
|
||||
|
||||
echo "extension=redis.so" | tee /etc/php/7.0/mods-available/redis.ini
|
||||
|
||||
phpenmod redis
|
||||
|
||||
# You can make Python 3 default, if you wish to.
|
||||
#update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
|
||||
#update-alternatives --install /usr/bin/python python /usr/bin/python3.5 2
|
||||
|
||||
mkdir $PATH_TO_MISP
|
||||
chown www-data:www-data $PATH_TO_MISP
|
||||
cd $PATH_TO_MISP
|
||||
$SUDO_WWW git clone https://github.com/MISP/MISP.git $PATH_TO_MISP
|
||||
|
||||
$SUDO_WWW git config core.filemode false
|
||||
|
||||
cp -p /etc/lsb-release /etc/lsb-release.tmp
|
||||
sudo sed -i 's/TSURUGI/Ubuntu/g' /etc/lsb-release
|
||||
sudo sed -i 's/bamboo/xenial/g' /etc/lsb-release
|
||||
sudo add-apt-repository ppa:jonathonf/python-3.6 -y
|
||||
sudo apt-get update
|
||||
sudo apt-get install python3.6 python3.6-dev -y
|
||||
mv /etc/lsb-release.tmp /etc/lsb-release
|
||||
$SUDO_WWW virtualenv -p python3.6 $PATH_TO_MISP/venv
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts
|
||||
$SUDO_WWW git clone https://github.com/CybOXProject/python-cybox.git
|
||||
$SUDO_WWW git clone https://github.com/STIXProject/python-stix.git
|
||||
$SUDO_WWW git clone https://github.com/CybOXProject/mixbox.git
|
||||
|
||||
mkdir /var/www/.cache
|
||||
chown www-data:www-data /var/www/.cache
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-stix
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install .
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts/python-cybox
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install .
|
||||
|
||||
cd $PATH_TO_MISP/app/files/scripts/mixbox
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install .
|
||||
|
||||
cd $PATH_TO_MISP
|
||||
$SUDO_WWW git submodule update --init --recursive
|
||||
# Make git ignore filesystem permission differences for submodules
|
||||
$SUDO_WWW git submodule foreach --recursive git config core.filemode false
|
||||
|
||||
# install PyMISP
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install enum34
|
||||
cd $PATH_TO_MISP/PyMISP
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install .
|
||||
|
||||
cd $PATH_TO_MISP/app
|
||||
mkdir /var/www/.composer ; chown www-data:www-data /var/www/.composer
|
||||
$SUDO_WWW php composer.phar require kamisama/cake-resque:4.1.2
|
||||
$SUDO_WWW php composer.phar config vendor-dir Vendor
|
||||
$SUDO_WWW php composer.phar install
|
||||
|
||||
$SUDO_WWW cp -fa $PATH_TO_MISP/INSTALL/setup/config.php $PATH_TO_MISP/app/Plugin/CakeResque/Config/config.php
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP
|
||||
chmod -R 750 $PATH_TO_MISP
|
||||
chmod -R g+ws $PATH_TO_MISP/app/tmp
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files/scripts/tmp
|
||||
|
||||
if [ ! -e /var/lib/mysql/misp/users.ibd ]; then
|
||||
echo "
|
||||
set timeout 10
|
||||
spawn mysql_secure_installation
|
||||
expect \"Enter current password for root (enter for none):\"
|
||||
send -- \"\r\"
|
||||
expect \"Set root password?\"
|
||||
send -- \"y\r\"
|
||||
expect \"New password:\"
|
||||
send -- \"${DBPASSWORD_ADMIN}\r\"
|
||||
expect \"Re-enter new password:\"
|
||||
send -- \"${DBPASSWORD_ADMIN}\r\"
|
||||
expect \"Remove anonymous users?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Disallow root login remotely?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Remove test database and access to it?\"
|
||||
send -- \"y\r\"
|
||||
expect \"Reload privilege tables now?\"
|
||||
send -- \"y\r\"
|
||||
expect eof" | expect -f -
|
||||
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "create database $DBNAME;"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant usage on *.* to $DBNAME@localhost identified by '$DBPASSWORD_MISP';"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "grant all privileges on $DBNAME.* to '$DBUSER_MISP'@'localhost';"
|
||||
mysql -u $DBUSER_ADMIN -p$DBPASSWORD_ADMIN -e "flush privileges;"
|
||||
|
||||
update-rc.d mysql enable
|
||||
update-rc.d apache2 enable
|
||||
update-rc.d redis-server enable
|
||||
|
||||
$SUDO_WWW cat $PATH_TO_MISP/INSTALL/MYSQL.sql | mysql -u $DBUSER_MISP -p$DBPASSWORD_MISP $DBNAME
|
||||
|
||||
echo "<?php
|
||||
class DATABASE_CONFIG {
|
||||
public \$default = array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
//'datasource' => 'Database/Postgres',
|
||||
'persistent' => false,
|
||||
'host' => '$DBHOST',
|
||||
'login' => '$DBUSER_MISP',
|
||||
'port' => 3306, // MySQL & MariaDB
|
||||
//'port' => 5432, // PostgreSQL
|
||||
'password' => '$DBPASSWORD_MISP',
|
||||
'database' => '$DBNAME',
|
||||
'prefix' => '',
|
||||
'encoding' => 'utf8',
|
||||
);
|
||||
}" | $SUDO_WWW tee $PATH_TO_MISP/app/Config/database.php
|
||||
else
|
||||
echo "There might be a database already existing here: /var/lib/mysql/misp/users.ibd"
|
||||
echo "Skipping any creations…"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
openssl req -newkey rsa:4096 -days 365 -nodes -x509 \
|
||||
-subj "/C=${OPENSSL_C}/ST=${OPENSSL_ST}/L=${OPENSSL_L}/O=${OPENSSL_O}/OU=${OPENSSL_OU}/CN=${OPENSSL_CN}/emailAddress=${OPENSSL_EMAILADDRESS}" \
|
||||
-keyout /etc/ssl/private/misp.local.key -out /etc/ssl/private/misp.local.crt
|
||||
|
||||
if [ ! -e /etc/rc.local ]
|
||||
then
|
||||
echo '#!/bin/sh -e' | tee -a /etc/rc.local
|
||||
echo 'exit 0' | tee -a /etc/rc.local
|
||||
chmod u+x /etc/rc.local
|
||||
fi
|
||||
|
||||
cd /var/www
|
||||
mkdir misp-dashboard
|
||||
chown www-data:www-data misp-dashboard
|
||||
$SUDO_WWW git clone https://github.com/MISP/misp-dashboard.git
|
||||
cd misp-dashboard
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install zmq
|
||||
/var/www/misp-dashboard/install_dependencies.sh
|
||||
sed -i "s/^host\ =\ localhost/host\ =\ 0.0.0.0/g" /var/www/misp-dashboard/config/config.cfg
|
||||
sed -i -e '$i \sudo -u www-data bash /var/www/misp-dashboard/start_all.sh\n' /etc/rc.local
|
||||
sed -i -e '$i \sudo -u misp /usr/local/src/viper/viper-web -p 8888 -H 0.0.0.0 &\n' /etc/rc.local
|
||||
sed -i -e '$i \git_dirs="/usr/local/src/misp-modules/ /var/www/misp-dashboard /usr/local/src/faup /usr/local/src/mail_to_misp /usr/local/src/misp-modules /usr/local/src/viper /var/www/misp-dashboard"\n' /etc/rc.local
|
||||
sed -i -e '$i \for d in $git_dirs; do\n' /etc/rc.local
|
||||
sed -i -e '$i \ echo "Updating ${d}"\n' /etc/rc.local
|
||||
sed -i -e '$i \ cd $d && sudo git pull &\n' /etc/rc.local
|
||||
sed -i -e '$i \done\n' /etc/rc.local
|
||||
$SUDO_WWW bash /var/www/misp-dashboard/start_all.sh
|
||||
|
||||
apt install libapache2-mod-wsgi-py3 -y
|
||||
|
||||
echo "<VirtualHost _default_:80>
|
||||
ServerAdmin admin@localhost.lu
|
||||
ServerName misp.local
|
||||
|
||||
Redirect permanent / https://misp.local
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost _default_:443>
|
||||
ServerAdmin admin@localhost.lu
|
||||
ServerName misp.local
|
||||
DocumentRoot $PATH_TO_MISP/app/webroot
|
||||
|
||||
<Directory $PATH_TO_MISP/app/webroot>
|
||||
Options -Indexes
|
||||
AllowOverride all
|
||||
Require all granted
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/ssl/private/misp.local.crt
|
||||
SSLCertificateKeyFile /etc/ssl/private/misp.local.key
|
||||
# SSLCertificateChainFile /etc/ssl/private/misp-chain.crt
|
||||
|
||||
LogLevel warn
|
||||
ErrorLog /var/log/apache2/misp.local_error.log
|
||||
CustomLog /var/log/apache2/misp.local_access.log combined
|
||||
ServerSignature Off
|
||||
Header set X-Content-Type-Options nosniff
|
||||
Header set X-Frame-Options DENY
|
||||
</VirtualHost>" | tee /etc/apache2/sites-available/misp-ssl.conf
|
||||
|
||||
echo "127.0.0.1 misp.local" | tee -a /etc/hosts
|
||||
|
||||
echo "<VirtualHost *:8001>
|
||||
ServerAdmin admin@misp.local
|
||||
ServerName misp.local
|
||||
|
||||
DocumentRoot /var/www/misp-dashboard
|
||||
|
||||
WSGIDaemonProcess misp-dashboard \
|
||||
user=misp group=misp \
|
||||
python-home=/var/www/misp-dashboard/DASHENV \
|
||||
processes=1 \
|
||||
threads=15 \
|
||||
maximum-requests=5000 \
|
||||
listen-backlog=100 \
|
||||
queue-timeout=45 \
|
||||
socket-timeout=60 \
|
||||
connect-timeout=15 \
|
||||
request-timeout=60 \
|
||||
inactivity-timeout=0 \
|
||||
deadlock-timeout=60 \
|
||||
graceful-timeout=15 \
|
||||
shutdown-timeout=5 \
|
||||
send-buffer-size=0 \
|
||||
receive-buffer-size=0 \
|
||||
header-buffer-size=0
|
||||
|
||||
WSGIScriptAlias / /var/www/misp-dashboard/misp-dashboard.wsgi
|
||||
|
||||
<Directory /var/www/misp-dashboard>
|
||||
WSGIProcessGroup misp-dashboard
|
||||
WSGIApplicationGroup %{GLOBAL}
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
LogLevel info
|
||||
ErrorLog /var/log/apache2/misp-dashboard.local_error.log
|
||||
CustomLog /var/log/apache2/misp-dashboard.local_access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>" | tee /etc/apache2/sites-available/misp-dashboard.conf
|
||||
|
||||
a2dissite default-ssl
|
||||
a2ensite misp-ssl
|
||||
a2ensite misp-dashboard
|
||||
|
||||
for key in upload_max_filesize post_max_size max_execution_time max_input_time memory_limit
|
||||
do
|
||||
sed -i "s/^\($key\).*/\1 = $(eval echo \${$key})/" $PHP_INI
|
||||
done
|
||||
|
||||
systemctl restart apache2
|
||||
|
||||
cp $PATH_TO_MISP/INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
chmod 0640 /etc/logrotate.d/misp
|
||||
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/bootstrap.default.php $PATH_TO_MISP/app/Config/bootstrap.php
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/core.default.php $PATH_TO_MISP/app/Config/core.php
|
||||
$SUDO_WWW cp -a $PATH_TO_MISP/app/Config/config.default.php $PATH_TO_MISP/app/Config/config.php
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP/app/Config
|
||||
chmod -R 750 $PATH_TO_MISP/app/Config
|
||||
$CAKE Live $MISP_LIVE
|
||||
$CAKE Baseurl $MISP_BASEURL
|
||||
|
||||
echo "%echo Generating a default key
|
||||
Key-Type: 1
|
||||
Key-Length: $GPG_KEY_LENGTH
|
||||
Subkey-Type: 1
|
||||
Name-Real: $GPG_REAL_NAME
|
||||
Name-Comment: $GPG_COMMENT
|
||||
Name-Email: $GPG_EMAIL_ADDRESS
|
||||
Expire-Date: 0
|
||||
Passphrase: $GPG_PASSPHRASE
|
||||
# Do a commit here, so that we can later print "done"
|
||||
%commit
|
||||
%echo done" > /tmp/gen-key-script
|
||||
|
||||
$SUDO_WWW gpg --homedir $PATH_TO_MISP/.gnupg --batch --gen-key /tmp/gen-key-script
|
||||
|
||||
$SUDO_WWW sh -c "gpg --homedir $PATH_TO_MISP/.gnupg --export --armor $GPG_EMAIL_ADDRESS" | $SUDO_WWW tee $PATH_TO_MISP/app/webroot/gpg.asc
|
||||
|
||||
chmod +x $PATH_TO_MISP/app/Console/worker/start.sh
|
||||
|
||||
$CAKE userInit -q
|
||||
|
||||
AUTH_KEY=$(mysql -u $DBUSER_MISP -p$DBPASSWORD_MISP misp -e "SELECT authkey FROM users;" | tail -1)
|
||||
|
||||
$CAKE Admin setSetting "MISP.python_bin" "${PATH_TO_MISP}/venv/bin/python"
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_event_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_object_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_object_reference_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_attribute_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_sighting_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_user_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_organisation_notifications_enable" true
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_port" 50000
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_host" "localhost"
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_port" 6379
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_database" 1
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_redis_namespace" "mispq"
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_include_attachments" false
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_tag_notifications_enable" false
|
||||
$CAKE Admin setSetting "Plugin.ZeroMQ_audit_notifications_enable" false
|
||||
$CAKE Admin setSetting "GnuPG.email" "admin@admin.test"
|
||||
$CAKE Admin setSetting "GnuPG.homedir" "/var/www/MISP/.gnupg"
|
||||
$CAKE Admin setSetting "GnuPG.password" "Password1234"
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_services_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_hover_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_timeout" 300
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_hover_timeout" 150
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_cve_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_dns_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Enrichment_services_port" 6666
|
||||
$CAKE Admin setSetting "Plugin.Import_services_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Import_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Import_services_port" 6666
|
||||
$CAKE Admin setSetting "Plugin.Import_timeout" 300
|
||||
$CAKE Admin setSetting "Plugin.Import_ocr_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Import_csvimport_enabled" true
|
||||
$CAKE Admin setSetting "Plugin.Export_services_enable" true
|
||||
$CAKE Admin setSetting "Plugin.Export_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Export_services_port" 6666
|
||||
$CAKE Admin setSetting "Plugin.Export_timeout" 300
|
||||
$CAKE Admin setSetting "Plugin.Export_pdfexport_enabled" true
|
||||
$CAKE Admin setSetting "MISP.host_org_id" 1
|
||||
$CAKE Admin setSetting "MISP.email" "info@admin.test"
|
||||
$CAKE Admin setSetting "MISP.disable_emailing" false
|
||||
$CAKE Admin setSetting "MISP.contact" "info@admin.test"
|
||||
$CAKE Admin setSetting "MISP.disablerestalert" true
|
||||
$CAKE Admin setSetting "MISP.showCorrelationsOnIndex" true
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_enable" false
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
|
||||
$CAKE Admin setSetting "Plugin.Cortex_timeout" 120
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_url" "http://127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_port" 9000
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_timeout" 120
|
||||
$CAKE Admin setSetting "Plugin.Cortex_services_authkey" ""
|
||||
$CAKE Admin setSetting "Plugin.Cortex_ssl_verify_peer" false
|
||||
$CAKE Admin setSetting "Plugin.Cortex_ssl_verify_host" false
|
||||
$CAKE Admin setSetting "Plugin.Cortex_ssl_allow_self_signed" true
|
||||
$CAKE Admin setSetting "Plugin.Sightings_policy" 0
|
||||
$CAKE Admin setSetting "Plugin.Sightings_anonymise" false
|
||||
$CAKE Admin setSetting "Plugin.Sightings_range" 365
|
||||
$CAKE Admin setSetting "Plugin.CustomAuth_disable_logout" false
|
||||
$CAKE Admin setSetting "Plugin.RPZ_policy" "DROP"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_walled_garden" "127.0.0.1"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_serial" "\$date00"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_refresh" "2h"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_retry" "30m"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_expiry" "30d"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_minimum_ttl" "1h"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_ttl" "1w"
|
||||
$CAKE Admin setSetting "Plugin.RPZ_ns" "localhost."
|
||||
$CAKE Admin setSetting "Plugin.RPZ_ns_alt" ""
|
||||
$CAKE Admin setSetting "Plugin.RPZ_email" "root.localhost"
|
||||
$CAKE Admin setSetting "MISP.language" "eng"
|
||||
$CAKE Admin setSetting "MISP.proposals_block_attributes" false
|
||||
$CAKE Admin setSetting "MISP.redis_host" "127.0.0.1"
|
||||
$CAKE Admin setSetting "MISP.redis_port" 6379
|
||||
$CAKE Admin setSetting "MISP.redis_database" 13
|
||||
$CAKE Admin setSetting "MISP.redis_password" ""
|
||||
$CAKE Admin setSetting "MISP.ssdeep_correlation_threshold" 40
|
||||
$CAKE Admin setSetting "MISP.extended_alert_subject" false
|
||||
$CAKE Admin setSetting "MISP.default_event_threat_level" 4
|
||||
$CAKE Admin setSetting "MISP.newUserText" "Dear new MISP user,\\n\\nWe would hereby like to welcome you to the \$org MISP community.\\n\\n Use the credentials below to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nPassword: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
|
||||
$CAKE Admin setSetting "MISP.passwordResetText" "Dear MISP user,\\n\\nA password reset has been triggered for your account. Use the below provided temporary password to log into MISP at \$misp, where you will be prompted to manually change your password to something of your own choice.\\n\\nUsername: \$username\\nYour temporary password: \$password\\n\\nIf you have any questions, don't hesitate to contact us at: \$contact.\\n\\nBest regards,\\nYour \$org MISP support team"
|
||||
$CAKE Admin setSetting "MISP.enableEventBlacklisting" true
|
||||
$CAKE Admin setSetting "MISP.enableOrgBlacklisting" true
|
||||
$CAKE Admin setSetting "MISP.log_client_ip" false
|
||||
$CAKE Admin setSetting "MISP.log_auth" false
|
||||
$CAKE Admin setSetting "MISP.disableUserSelfManagement" false
|
||||
$CAKE Admin setSetting "MISP.block_event_alert" false
|
||||
$CAKE Admin setSetting "MISP.block_event_alert_tag" "no-alerts=\"true\""
|
||||
$CAKE Admin setSetting "MISP.block_old_event_alert" false
|
||||
$CAKE Admin setSetting "MISP.block_old_event_alert_age" ""
|
||||
$CAKE Admin setSetting "MISP.incoming_tags_disabled_by_default" false
|
||||
$CAKE Admin setSetting "MISP.footermidleft" "This is an autogenerated install"
|
||||
$CAKE Admin setSetting "MISP.footermidright" "Please configure accordingly and do not use in production"
|
||||
$CAKE Admin setSetting "MISP.welcome_text_top" "Autogenerated install, please configure and harden accordingly"
|
||||
$CAKE Admin setSetting "MISP.welcome_text_bottom" "Welcome to MISP on Tsurugi"
|
||||
$CAKE Admin setSetting "Security.password_policy_length" 12
|
||||
$CAKE Admin setSetting "Security.password_policy_complexity" '/^((?=.*\d)|(?=.*\W+))(?![\n])(?=.*[A-Z])(?=.*[a-z]).*$|.{16,}/'
|
||||
$CAKE Admin setSetting "Session.autoRegenerate" 0
|
||||
$CAKE Admin setSetting "Session.timeout" 600
|
||||
$CAKE Admin setSetting "Session.cookie_timeout" 3600
|
||||
$CAKE Live $MISP_LIVE
|
||||
$CAKE Admin updateGalaxies
|
||||
$CAKE Admin updateTaxonomies
|
||||
#$CAKE Admin updateWarningLists
|
||||
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/warninglists/update
|
||||
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/noticelists/update
|
||||
curl --header "Authorization: $AUTH_KEY" --header "Accept: application/json" --header "Content-Type: application/json" -k -X POST https://127.0.0.1/objectTemplates/update
|
||||
sed -i -e '$i \echo never > /sys/kernel/mm/transparent_hugepage/enabled\n' /etc/rc.local
|
||||
sed -i -e '$i \echo 1024 > /proc/sys/net/core/somaxconn\n' /etc/rc.local
|
||||
sed -i -e '$i \sysctl vm.overcommit_memory=1\n' /etc/rc.local
|
||||
sed -i -e '$i \sudo -u www-data bash /var/www/MISP/app/Console/worker/start.sh\n' /etc/rc.local
|
||||
sed -i -e '$i \sudo -u www-data /var/www/MISP/venv/bin/misp-modules -l 127.0.0.1 -s > /tmp/misp-modules_rc.local.log 2> /dev/null &\n' /etc/rc.local
|
||||
$SUDO_WWW bash $PATH_TO_MISP/app/Console/worker/start.sh
|
||||
cd /usr/local/src/
|
||||
git clone https://github.com/MISP/misp-modules.git
|
||||
cd misp-modules
|
||||
# pip3 install
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -I -r REQUIREMENTS
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install -I .
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install maec python-magic wand lief yara-python
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install git+https://github.com/kbandla/pydeep.git
|
||||
$SUDO_WWW $PATH_TO_MISP/venv/bin/pip install stix2
|
||||
gem install pygments.rb
|
||||
gem install asciidoctor-pdf --pre
|
||||
$SUDO_WWW misp-modules -l 0.0.0.0 -s &
|
||||
cd /usr/local/src/
|
||||
apt-get install -y libssl-dev swig python3-ssdeep p7zip-full unrar-free sqlite python3-pyclamd exiftool radare2
|
||||
pip3 install SQLAlchemy PrettyTable python-magic
|
||||
git clone https://github.com/viper-framework/viper.git
|
||||
chown -R $MISP_USER:$MISP_USER viper
|
||||
cd viper
|
||||
virtualenv -p python3.6 venv
|
||||
$SUDO git submodule update --init --recursive
|
||||
# There is a bug with yara-python, removing for the time being
|
||||
sed -i 's/yara-python==3.7.0//g' requirements-modules.txt
|
||||
./venv/bin/pip install scrapy
|
||||
./venv/bin/pip install -r requirements.txt
|
||||
./venv/bin/pip uninstall yara -y
|
||||
sed -i '1 s/^.*$/\#!\/usr\/local\/src\/viper\/venv\/bin\/python/' viper-cli
|
||||
sed -i '1 s/^.*$/\#!\/usr\/local\/src\/viper\/venv\/bin\/python/' viper-web
|
||||
$SUDO /usr/local/src/viper/viper-cli -h > /dev/null
|
||||
$SUDO /usr/local/src/viper/viper-web -p 8888 -H 0.0.0.0 &
|
||||
echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/src/viper:/var/www/MISP/app/Console"' |tee /etc/environment
|
||||
echo ". /etc/environment" >> /home/${MISP_USER}/.profile
|
||||
$SUDO sed -i "s/^misp_url\ =/misp_url\ =\ http:\/\/localhost/g" /home/${MISP_USER}/.viper/viper.conf
|
||||
$SUDO sed -i "s/^misp_key\ =/misp_key\ =\ $AUTH_KEY/g" /home/${MISP_USER}/.viper/viper.conf
|
||||
|
||||
while [ "$(sqlite3 /home/${MISP_USER}/.viper/admin.db 'UPDATE auth_user SET password="pbkdf2_sha256$100000$iXgEJh8hz7Cf$vfdDAwLX8tko1t0M1TLTtGlxERkNnltUnMhbv56wK/U="'; echo $?)" -ne "0" ]; do
|
||||
# FIXME This might lead to a race condition, the while loop is sub-par
|
||||
chown $MISP_USER:$MISP_USER /home/${MISP_USER}/.viper/admin.db
|
||||
echo "Updating viper-web admin password, giving process time to start-up, sleeping 5, 4, 3,…"
|
||||
sleep 6
|
||||
done
|
||||
|
||||
chown -R www-data:www-data $PATH_TO_MISP
|
||||
chmod -R 750 $PATH_TO_MISP
|
||||
chmod -R g+ws $PATH_TO_MISP/app/tmp
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files
|
||||
chmod -R g+ws $PATH_TO_MISP/app/files/scripts/tmp
|
||||
|
||||
# TODO: fix faup
|
||||
cd /usr/local/src/
|
||||
apt-get install -y cmake
|
||||
git clone https://github.com/MISP/mail_to_misp.git
|
||||
git clone git://github.com/stricaud/faup.git faup
|
||||
chown -R ${MISP_USER}:${MISP_USER} faup mail_to_misp
|
||||
cd faup
|
||||
$SUDO mkdir -p build
|
||||
cd build
|
||||
$SUDO cmake .. && $SUDO make
|
||||
make install
|
||||
ldconfig
|
||||
cd ../../
|
||||
cd mail_to_misp
|
||||
pip3 install -r requirements.txt
|
||||
$SUDO cp mail_to_misp_config.py-example mail_to_misp_config.py
|
||||
sed -i "s/^misp_url\ =\ 'YOUR_MISP_URL'/misp_url\ =\ 'http:\/\/localhost'/g" /usr/local/src/mail_to_misp/mail_to_misp_config.py
|
||||
sed -i "s/^misp_key\ =\ 'YOUR_KEY_HERE'/misp_key\ =\ '$AUTH_KEY'/g" /usr/local/src/mail_to_misp/mail_to_misp_config.py
|
||||
echo ""
|
||||
echo "Admin (root) DB Password: $DBPASSWORD_ADMIN" > /home/${MISP_USER}/mysql.txt
|
||||
echo "User (misp) DB Password: $DBPASSWORD_MISP" >> /home/${MISP_USER}/mysql.txt
|
||||
echo "Authkey: $AUTH_KEY" > /home/${MISP_USER}/MISP-authkey.txt
|
||||
|
||||
clear
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "MISP Installed, access here: https://misp.local"
|
||||
echo "User: admin@admin.test"
|
||||
echo "Password: admin"
|
||||
echo "MISP Dashboard, access here: http://misp.local:8001"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
cat /home/${MISP_USER}/mysql.txt
|
||||
cat /home/${MISP_USER}/MISP-authkey.txt
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "The LOCAL system credentials:"
|
||||
echo "User: ${MISP_USER}"
|
||||
echo "Password: ${MISP_PASSWORD}"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "viper-web installed, access here: http://misp.local:8888"
|
||||
echo "viper-cli configured with your MISP Site Admin Auth Key"
|
||||
echo "User: admin"
|
||||
echo "Password: Password1234"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "To enable outgoing mails via postfix set a permissive SMTP server for the domains you want to contact:"
|
||||
echo ""
|
||||
echo "sudo postconf -e 'relayhost = example.com'"
|
||||
echo "sudo postfix reload"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "Enjoy using MISP. For any issues see here: https://github.com/MISP/MISP/issues"
|
||||
su - misp
|
||||
}
|
||||
|
||||
tsurugiOnRootR0ckz
|
||||
installMISPonTsurugi
|
|
@ -0,0 +1 @@
|
|||
../docs/xINSTALL.ubuntu1804.with.webmin.md
|
2
PyMISP
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit cb2dbbd481f587e4a4c77f7f8bfa0a536fc9105c
|
||||
Subproject commit 634ecc3ac308d01ebf5f5fbb9aace7746a2b8707
|
33
README.md
33
README.md
|
@ -31,33 +31,34 @@ MISP - Malware Information Sharing Platform and Threat Sharing
|
|||
|
||||
</table>
|
||||
|
||||
MISP, is an open source software solution for collecting, storing, distributing and sharing cyber security indicators and threat about cyber security incidents analysis and malware analysis. MISP is designed by and for incident analysts, security and ICT professionals or malware reverser to support their day-to-day operations to share structured informations efficiently.
|
||||
MISP is an open source software solution for collecting, storing, distributing and sharing cyber security indicators and threats about cyber security incidents analysis and malware analysis. MISP is designed by and for incident analysts, security and ICT professionals or malware reversers to support their day-to-day operations to share structured information efficiently.
|
||||
|
||||
The objective of MISP is to foster the sharing of structured information within the security community and abroad. MISP provides functionalities to support the exchange of information but also the consumption of the information by Network Intrusion Detection System (NIDS), LIDS but also log analysis tools, SIEMs.
|
||||
The objective of MISP is to foster the sharing of structured information within the security community and abroad. MISP provides functionalities to support the exchange of information but also the consumption of said information by Network Intrusion Detection Systems (NIDS), LIDS but also log analysis tools, SIEMs.
|
||||
|
||||
MISP, Malware Information Sharing Platform and Threat Sharing, core functionalities are:
|
||||
|
||||
- An **efficient IOC and indicators** database allowing to store technical and non-technical information about malware samples, incidents, attackers and intelligence.
|
||||
- Automatic **correlation** finding relationships between attributes and indicators from malware, attacks campaigns or analysis. attacks campaigns or analysis. Correlation engine includes correlation between attributes and more advanced correlations like Fuzzy hashing correlation (e.g. ssdeep) or CIDR block matching. Correlation can be also enabled or event disabled per attribute.
|
||||
- Automatic **correlation** finding relationships between attributes and indicators from malware, attack campaigns or analysis. The correlation engine includes correlation between attributes and more advanced correlations like Fuzzy hashing correlation (e.g. ssdeep) or CIDR block matching. Correlation can also be enabled or event disabled per attribute.
|
||||
- A **flexible data model** where complex [objects](https://www.misp-project.org/objects.html) can be expressed and **linked together to express threat intelligence, incidents or connected elements**.
|
||||
- Built-in **sharing functionality** to ease data sharing using different model of distributions. MISP can synchronize automatically events and attributes among different MISP. Advanced filtering functionalities can be used to meet each organization sharing policy including a **flexible sharing group** capacity and an attribute level distribution mechanisms.
|
||||
- An **intuitive user-interface** for end-users to create, update and collaborate on events and attributes/indicators. A **graphical interface** to navigate seamlessly between events and their correlations. Advanced filtering functionalities and [warning list](https://github.com/MISP/misp-warninglists) to help the analysts to contribute events and attributes.
|
||||
- Built-in **sharing functionality** to ease data sharing using different model of distributions. MISP can automatically synchronize events and attributes among different MISP instances. Advanced filtering functionalities can be used to meet each organization's sharing policy including a **flexible sharing group** capacity and an attribute level distribution mechanisms.
|
||||
- An **intuitive user-interface** for end-users to create, update and collaborate on events and attributes/indicators. A **graphical interface** to navigate seamlessly between events and their correlations. An **event graph** functionality to create and view relationships between objects and attributes. Advanced filtering functionalities and [warning lists](https://github.com/MISP/misp-warninglists) to help the analysts to contribute events and attributes and limit the risk of false-positives.
|
||||
- **storing data** in a structured format (allowing automated use of the database for various purposes) with an extensive support of cyber security indicators along fraud indicators as in the financial sector.
|
||||
- **export**: generating IDS, OpenIOC, plain text, CSV, MISP XML or JSON output to integrate with other systems (network IDS, host IDS, custom tools), STIX (XML and JSON), NIDS export (Suricata, Snort and Bro) or RPZ zone. Many other formats easily added via the [misp-modules](https://github.com/MISP/misp-modules).
|
||||
- **import**: bulk-import, batch-import, import from OpenIOC, GFI sandbox, ThreatConnect CSV. Many other formats easily added via the [misp-modules](https://github.com/MISP/misp-modules).
|
||||
- **export**: generating IDS, OpenIOC, plain text, CSV, MISP XML or JSON output to integrate with other systems (network IDS, host IDS, custom tools), Cache format (used for forensic tools), STIX (XML and JSON) 1 and 2, NIDS export (Suricata, Snort and Bro/Zeek) or RPZ zone. Many other formats can be easily added via the [misp-modules](https://github.com/MISP/misp-modules).
|
||||
- **import**: bulk-import, batch-import, import from OpenIOC, GFI sandbox, ThreatConnect CSV, MISP standard format or STIX 1.1/2.0. Many other formats easily added via the [misp-modules](https://github.com/MISP/misp-modules).
|
||||
- Flexible **free text import** tool to ease the integration of unstructured reports into MISP.
|
||||
- A gentle system to **collaborate** on events and attributes allowing MISP users to propose changes or updates to attributes/indicators.
|
||||
- **data-sharing**: automatically exchange and synchronization with other parties and trust-groups using MISP.
|
||||
- **data-sharing**: automatically exchange and synchronize with other parties and trust-groups using MISP.
|
||||
- **delegating of sharing**: allows a simple pseudo-anonymous mechanism to delegate publication of event/indicators to another organization.
|
||||
- Flexible **API** to integrate MISP with your own solutions. MISP is bundled with [PyMISP](https://github.com/MISP/PyMISP) which is a flexible Python Library to fetch, add or update events attributes, handle malware samples or search for attributes.
|
||||
- Flexible **API** to integrate MISP with your own solutions. MISP is bundled with [PyMISP](https://github.com/MISP/PyMISP) which is a flexible Python Library to fetch, add or update events attributes, handle malware samples or search for attributes. An exhaustive restSearch API to easily search for indicators in MISP and exports those in all the format supported by MISP.
|
||||
- **Adjustable taxonomy** to classify and tag events following your own classification schemes or [existing classification](https://github.com/MISP/misp-taxonomies). The taxonomy can be local to your MISP but also shareable among MISP instances.
|
||||
- **Intelligence vocabularies** called MISP galaxy and bundled with existing [threat actors, malware, RAT, ransomware or MITRE ATT&CK](https://www.misp-project.org/galaxy.html) which can be easily linked with events in MISP.
|
||||
- **Intelligence vocabularies** called MISP galaxy and bundled with existing [threat actors, malware, RAT, ransomware or MITRE ATT&CK](https://www.misp-project.org/galaxy.html) which can be easily linked with events and attributes in MISP.
|
||||
- **Expansion modules in Python** to expand MISP with your own services or activate already available [misp-modules](https://github.com/MISP/misp-modules).
|
||||
- **Sighting support** to get observations from organizations concerning shared indicators and attributes. Sighting [can be contributed](https://www.circl.lu/doc/misp/automation/index.html#sightings-api) via MISP user-interface, API as MISP document or STIX sighting documents.
|
||||
- **STIX support**: export data in the STIX format (XML and JSON). Additional STIX import and export is supported by [MISP-STIX-Converter](https://github.com/MISP/MISP-STIX-Converter) or [MISP-Taxii-Server](https://github.com/MISP/MISP-Taxii-Server).
|
||||
- **Integrated encryption and signing of the notifications** via GnuPG and/or S/MIME depending of the user preferences.
|
||||
- **STIX support**: import and export data in the STIX version 1 and version 2 format.
|
||||
- **Integrated encryption and signing of the notifications** via GnuPG and/or S/MIME depending on the user's preferences.
|
||||
- **Real-time** publish-subscribe channel within MISP to automatically get all changes (e.g. new events, indicators, sightings or tagging) in ZMQ (e.g. [misp-dashboard](https://github.com/MISP/misp-dashboard)) or ElasticSearch logging.
|
||||
|
||||
Exchanging info results in *faster detection* of targeted attacks and improves the detection ratio while reducing the false positives. We also avoid reversing similar malware as we know very fast that others team or organizations who already analyzed a specific malware.
|
||||
Exchanging info results in *faster detection* of targeted attacks and improves the detection ratio while reducing the false positives. We also avoid reversing similar malware as we know very fast that other teams or organizations have already analyzed a specific malware.
|
||||
|
||||
![MISP 2.4 overview](https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/screenshots/misp-panorama.png)
|
||||
|
||||
|
@ -77,7 +78,7 @@ Documentation
|
|||
|
||||
[MISP user-guide (MISP-book)](https://github.com/MISP/misp-book) is available [online](https://www.circl.lu/doc/misp/) or as [PDF](https://www.circl.lu/doc/misp/book.pdf) or as [EPUB](https://www.circl.lu/doc/misp/book.epub) or as [MOBI/Kindle](https://www.circl.lu/doc/misp/book.mobi).
|
||||
|
||||
For installation guide see [INSTALL](https://github.com/MISP/MISP/tree/2.4/INSTALL) or the [download section](https://www.misp-project.org/download/).
|
||||
For the installation guide see the [INSTALL](https://github.com/MISP/MISP/tree/2.4/INSTALL) or [download section](https://www.misp-project.org/download/).
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
@ -106,8 +107,8 @@ This software is licensed under [GNU Affero General Public License version 3](ht
|
|||
* Copyright (C) 2012 Christophe Vandeplas
|
||||
* Copyright (C) 2012 Belgian Defence
|
||||
* Copyright (C) 2012 NATO / NCIRC
|
||||
* Copyright (C) 2013-2018 Andras Iklody
|
||||
* Copyright (C) 2015-2018 CIRCL - Computer Incident Response Center Luxembourg
|
||||
* Copyright (C) 2013-2019 Andras Iklody
|
||||
* Copyright (C) 2015-2019 CIRCL - Computer Incident Response Center Luxembourg
|
||||
* Copyright (C) 2016 Andreas Ziegler
|
||||
|
||||
For more information, [the list of authors and contributors](AUTHORS) is available.
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"major":2, "minor":4, "hotfix":96}
|
||||
{"major":2, "minor":4, "hotfix":102}
|
||||
|
|
|
@ -134,6 +134,7 @@ $config = array(
|
|||
'apacheEnv' => 'REMOTE_USER', // If proxy variable = HTTP_REMOTE_USER
|
||||
'ldapServer' => 'ldap://example.com', // FQDN or IP
|
||||
'ldapProtocol' => 3,
|
||||
'ldapNetworkTimeout' => -1, // use -1 for unlimited network timeout
|
||||
'ldapReaderUser' => 'cn=userWithReadAccess,ou=users,dc=example,dc=com', // DN ou RDN LDAP with reader user right
|
||||
'ldapReaderPassword' => 'UserPassword', // the LDAP reader user password
|
||||
'ldapDN' => 'dc=example,dc=com',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
App::uses('AppShell', 'Console/Command');
|
||||
class AdminShell extends AppShell
|
||||
{
|
||||
public $uses = array('Event', 'Post', 'Attribute', 'Job', 'User', 'Task', 'Whitelist', 'Server', 'Organisation', 'AdminSetting', 'Galaxy', 'Taxonomy', 'Warninglist', 'Noticelist', 'ObjectTemplate');
|
||||
public $uses = array('Event', 'Post', 'Attribute', 'Job', 'User', 'Task', 'Whitelist', 'Server', 'Organisation', 'AdminSetting', 'Galaxy', 'Taxonomy', 'Warninglist', 'Noticelist', 'ObjectTemplate', 'Bruteforce');
|
||||
|
||||
public function jobGenerateCorrelation() {
|
||||
$jobId = $this->args[0];
|
||||
|
@ -146,15 +146,26 @@ class AdminShell extends AppShell
|
|||
}
|
||||
|
||||
public function setSetting() {
|
||||
$setting = !isset($this->args[0]) ? null : $this->args[0];
|
||||
$setting_name = !isset($this->args[0]) ? null : $this->args[0];
|
||||
$value = !isset($this->args[1]) ? null : $this->args[1];
|
||||
if ($value === 'false') $value = 0;
|
||||
if ($value === 'true') $value = 1;
|
||||
if (empty($setting) || $value === null) {
|
||||
$cli_user = array('id' => 0, 'email' => 'SYSTEM', 'Organisation' => array('name' => 'SYSTEM'));
|
||||
if (empty($setting_name) || $value === null) {
|
||||
echo 'Invalid parameters. Usage: ' . APP . 'Console/cake Admin setSetting [setting_name] [setting_value]';
|
||||
} else {
|
||||
$this->Server->serverSettingsSaveValue($setting, $value);
|
||||
$setting = $this->Server->getSettingData($setting_name);
|
||||
if (empty($setting)) {
|
||||
echo 'Invalid setting. Please make sure that the setting that you are attempting to change exists.';
|
||||
}
|
||||
$result = $this->Server->serverSettingsEditValue($cli_user, $setting, $value);
|
||||
if ($result === true) {
|
||||
echo 'Setting changed.';
|
||||
} else {
|
||||
echo $result;
|
||||
}
|
||||
}
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
public function setDatabaseVersion() {
|
||||
|
@ -173,6 +184,12 @@ class AdminShell extends AppShell
|
|||
}
|
||||
}
|
||||
|
||||
public function updateDatabase() {
|
||||
echo 'Executing all updates to bring the database up to date with the current version.' . PHP_EOL;
|
||||
$this->Server->runUpdates(true);
|
||||
echo 'All updates completed.' . PHP_EOL;
|
||||
}
|
||||
|
||||
public function getAuthkey() {
|
||||
if (empty($this->args[0])) {
|
||||
echo 'Invalid parameters. Usage: ' . APP . 'Console/cake Admin getAuthkey [user_email]' . PHP_EOL;
|
||||
|
@ -190,4 +207,18 @@ class AdminShell extends AppShell
|
|||
}
|
||||
}
|
||||
|
||||
public function clearBruteforce()
|
||||
{
|
||||
$conditions = array('Bruteforce.username !=' => '');
|
||||
if (!empty($this->args[0])) {
|
||||
$conditions = array('Bruteforce.username' => $this->args[0]);
|
||||
}
|
||||
$result = $this->Bruteforce->deleteAll($conditions, false, false);
|
||||
$target = empty($this->args[0]) ? 'all users' : $this->args[0];
|
||||
if ($result) {
|
||||
echo 'Brutefoce entries for ' . $target . ' deleted.' . PHP_EOL;
|
||||
} else {
|
||||
echo 'Something went wrong, could not delete bruteforce entries for ' . $target . '.' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -558,12 +558,24 @@ class EventShell extends AppShell
|
|||
$this->Job->save($data);
|
||||
$jobId = $this->Job->id;
|
||||
}
|
||||
$job = $this->Job->read(null, $jobId);
|
||||
$options = array(
|
||||
'user' => $user,
|
||||
'event_id' => $eventId,
|
||||
'modules' => $modules
|
||||
);
|
||||
$result = $this->Event->enrichment($options);
|
||||
$job['Job']['progress'] = 100;
|
||||
$job['Job']['date_modified'] = date("y-m-d H:i:s");
|
||||
if ($result) {
|
||||
$job['Job']['message'] = 'Added ' . $result . ' attribute' . ($result > 1 ? 's.' : '.');
|
||||
} else {
|
||||
$job['Job']['message'] = 'Enrichment finished, but no attributes added.';
|
||||
}
|
||||
$this->Job->save($job);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->create();
|
||||
$log->createLogEntry($user, 'enrichment', 'Event', $eventId, 'Event (' . $eventId . '): enriched.', 'enriched () => (1)');
|
||||
}
|
||||
|
||||
public function processfreetext() {
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Populate023Shell extends AppShell {
|
||||
|
||||
public $tasks = array('Roles', 'RoleToAroAco', 'RoleId', 'Users');
|
||||
|
||||
public function main() {
|
||||
// perform tasks
|
||||
sleep(30);
|
||||
$this->Roles->execute();
|
||||
$this->RoleId->execute('2');
|
||||
$this->RoleToAroAco->execute();
|
||||
// on user data
|
||||
$this->Users->execute();
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ class ServerShell extends AppShell
|
|||
|
||||
public function pull() {
|
||||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['pull'] . PHP_EOL);
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['pull'] . PHP_EOL);
|
||||
}
|
||||
$userId = $this->args[0];
|
||||
$user = $this->User->getAuthUser($userId);
|
||||
|
@ -56,7 +56,7 @@ class ServerShell extends AppShell
|
|||
|
||||
public function push() {
|
||||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['push'] . PHP_EOL);
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['push'] . PHP_EOL);
|
||||
}
|
||||
$userId = $this->args[0];
|
||||
$user = $this->User->getAuthUser($userId);
|
||||
|
@ -103,7 +103,7 @@ class ServerShell extends AppShell
|
|||
|
||||
public function fetchFeed() {
|
||||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['fetchFeed'] . PHP_EOL);
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['fetchFeed'] . PHP_EOL);
|
||||
}
|
||||
$userId = $this->args[0];
|
||||
$user = $this->User->getAuthUser($userId);
|
||||
|
@ -129,31 +129,107 @@ class ServerShell extends AppShell
|
|||
$jobId = $this->Job->id;
|
||||
}
|
||||
$this->Job->read(null, $jobId);
|
||||
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user, $jobId);
|
||||
$this->Job->id = $jobId;
|
||||
if (!$result) {
|
||||
$message = 'Job Failed.';
|
||||
$this->Job->save(array(
|
||||
'id' => $jobId,
|
||||
'message' => $message,
|
||||
'progress' => 0,
|
||||
'status' => 3
|
||||
$outcome = array(
|
||||
'id' => $jobId,
|
||||
'message' => 'Job done.',
|
||||
'progress' => 100,
|
||||
'status' => 4
|
||||
);
|
||||
if ($feedId == 'all') {
|
||||
$feedIds = $this->Feed->find('list', array(
|
||||
'fields' => array('Feed.id', 'Feed.id'),
|
||||
'conditions' => array('Feed.enabled' => 1)
|
||||
));
|
||||
$feedIds = array_values($feedIds);
|
||||
$successes = 0;
|
||||
$fails = 0;
|
||||
foreach ($feedIds as $k => $feedId) {
|
||||
$jobStatus = array(
|
||||
'id' => $jobId,
|
||||
'message' => 'Fetching feed: ' . $feedId,
|
||||
'progress' => 100 * $k / count($feedIds),
|
||||
'status' => 0
|
||||
);
|
||||
$this->Job->id = $jobId;
|
||||
$this->Job->save($jobStatus);
|
||||
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user);
|
||||
if ($result) {
|
||||
$successes++;
|
||||
} else {
|
||||
$fails++;
|
||||
}
|
||||
}
|
||||
$outcome['message'] = 'Job done. ' . $successes . ' feeds pulled successfuly, ' . $fails . ' feeds could not be pulled.';
|
||||
} else {
|
||||
$message = 'Job done.';
|
||||
$this->Job->save(array(
|
||||
'id' => $jobId,
|
||||
'message' => $message,
|
||||
'progress' => 100,
|
||||
'status' => 4
|
||||
$temp = $this->Feed->find('first', array(
|
||||
'fields' => array('Feed.id', 'Feed.id'),
|
||||
'conditions' => array('Feed.enabled' => 1, 'Feed.id' => $feedId)
|
||||
));
|
||||
if (!empty($temp)) {
|
||||
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user, $jobId);
|
||||
if (!$result) {
|
||||
$outcome['progress'] = 0;
|
||||
$outcome['status'] = 3;
|
||||
$outcome['message'] = 'Job failed.';
|
||||
}
|
||||
}
|
||||
}
|
||||
echo $message . PHP_EOL;
|
||||
$this->Job->id = $jobId;
|
||||
$this->Job->save($outcome);
|
||||
echo $outcome['message'] . PHP_EOL;
|
||||
}
|
||||
|
||||
public function cacheServer() {
|
||||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['cacheServer'] . PHP_EOL);
|
||||
}
|
||||
$userId = $this->args[0];
|
||||
$user = $this->User->getAuthUser($userId);
|
||||
if (empty($user)) die('Invalid user.' . PHP_EOL);
|
||||
$scope = $this->args[1];
|
||||
if (!empty($this->args[2])) {
|
||||
$jobId = $this->args[2];
|
||||
} else {
|
||||
$this->Job->create();
|
||||
$data = array(
|
||||
'worker' => 'default',
|
||||
'job_type' => 'cache_servers',
|
||||
'job_input' => 'Server: ' . $id,
|
||||
'status' => 0,
|
||||
'retries' => 0,
|
||||
'org' => $user['Organisation']['name'],
|
||||
'message' => 'Starting server caching.',
|
||||
);
|
||||
$this->Job->save($data);
|
||||
$jobId = $this->Job->id;
|
||||
}
|
||||
$this->Job->read(null, $jobId);
|
||||
$result = $this->Server->cacheServerInitiator($user, $scope, $jobId);
|
||||
$this->Job->id = $jobId;
|
||||
if ($result !== true) {
|
||||
$message = 'Job Failed. Reason: ';
|
||||
$this->Job->save(array(
|
||||
'id' => $jobId,
|
||||
'message' => $message . $result,
|
||||
'progress' => 0,
|
||||
'status' => 3
|
||||
));
|
||||
} else {
|
||||
$message = 'Job done.';
|
||||
$this->Job->save(array(
|
||||
'id' => $jobId,
|
||||
'message' => $message,
|
||||
'progress' => 100,
|
||||
'status' => 4
|
||||
));
|
||||
}
|
||||
echo $message . PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
public function cacheFeed() {
|
||||
if (empty($this->args[0]) || empty($this->args[1])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['cacheFeed'] . PHP_EOL);
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['cacheFeed'] . PHP_EOL);
|
||||
}
|
||||
$userId = $this->args[0];
|
||||
$user = $this->User->getAuthUser($userId);
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
App::uses('UsersController', 'Controller');
|
||||
|
||||
class RoleIdTask extends Shell {
|
||||
|
||||
public $uses = array('User');
|
||||
|
||||
public $Users;
|
||||
|
||||
public function execute($fk = '1') {
|
||||
$this->Users = new UsersController();
|
||||
$this->Users->constructClasses();
|
||||
$this->Users->setRoleId($fk);
|
||||
//$this->Users->generateAllForRoleId($fk); // TODO
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
App::uses('RolesController', 'Controller');
|
||||
|
||||
class RoleToAroAcoTask extends Shell {
|
||||
|
||||
public $uses = array('Role');
|
||||
|
||||
public $Roles;
|
||||
|
||||
public function execute() {
|
||||
$this->Roles = new RolesController();
|
||||
$this->Roles->constructClasses();
|
||||
|
||||
$roles = $this->Role->find('all');
|
||||
foreach ($roles as $role) {
|
||||
$this->Roles->saveAcl(array('model' => 'Role', 'foreign_key' => $role['Role']['id']), $role['Role']['perm_add'], $role['Role']['perm_modify'], $role['Role']['perm_publish'], $role['Role']['perm_admin'], $role['Role']['perm_sync'], $role['Role']['perm_auth'], $role['Role']['perm_audit']);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
App::uses('RolesController', 'Controller');
|
||||
|
||||
class RolesTask extends Shell {
|
||||
|
||||
public $uses = array('Role');
|
||||
|
||||
public $Roles;
|
||||
|
||||
public function execute() {
|
||||
$this->Roles = new RolesController();
|
||||
$this->Roles->constructClasses();
|
||||
|
||||
$roles = ClassRegistry::init('Role');
|
||||
$roles->create();
|
||||
$roles->save(array('Role' => array('name' => 'admin', 'perm_add' => 1, 'perm_modify' => 1, 'perm_publish' => 1, 'perm_full' => 1, 'perm_sync' => 1, 'perm_audit' => 1, 'perm_auth' => 1)));
|
||||
$roles->create();
|
||||
$roles->save(array('Role' => array('name' => 'org_admin', 'perm_add' => 1, 'perm_modify' => 1, 'perm_publish' => 0, 'perm_full' => 0, 'perm_sync' => 1, 'perm_audit' => 1, 'perm_auth' => 1)));
|
||||
$roles->create();
|
||||
$roles->save(array('Role' => array('name' => 'User', 'perm_add' => 1, 'perm_modify' => 1, 'perm_publish' => 0, 'perm_full' => 0, 'perm_sync' => 1, 'perm_audit' => 1, 'perm_auth' => 0)));
|
||||
$roles->create();
|
||||
$roles->save(array('Role' => array('name' => 'Sync', 'perm_add' => 1, 'perm_modify' => 1, 'perm_publish' => 1, 'perm_full' => 0, 'perm_sync' => 1, 'perm_audit' => 1, 'perm_auth' => 1)));
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
App::uses('UsersController', 'Controller');
|
||||
|
||||
class UsersTask extends Shell {
|
||||
|
||||
public $uses = array('User');
|
||||
|
||||
public $Users;
|
||||
|
||||
public function execute() {
|
||||
$this->Users = new UsersController();
|
||||
$this->Users->constructClasses();
|
||||
|
||||
$users = ClassRegistry::init('User');
|
||||
// perform clean
|
||||
$users->checkAndCorrectPgps();
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
class Populate023Shell extends AppShell {
|
||||
|
||||
public $tasks = array('Roles', 'RoleToAroAco', 'RoleId', 'Users');
|
||||
|
||||
public function main() {
|
||||
// perform tasks
|
||||
sleep(30);
|
||||
$this->Roles->execute();
|
||||
$this->RoleId->execute('2');
|
||||
$this->RoleToAroAco->execute();
|
||||
// on user data
|
||||
$this->Users->execute();
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# degrate 0.2.3 to 0.2.2
|
||||
|
||||
# step into project and ..
|
||||
PRJCT=/var/www/MISP/app
|
||||
cd ${PRJCT}
|
||||
|
||||
# update Schema, remove Users.role_id
|
||||
./Console/cake schema update -s 0.2.2
|
||||
|
||||
exit 0;
|
|
@ -1,38 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# migrate 0.2.2 to 0.2.3
|
||||
|
||||
# DataBase migrate, Audit and Access Control granulation
|
||||
|
||||
# step into project and ..
|
||||
PRJCT=../../../app
|
||||
cd ${PRJCT}
|
||||
|
||||
# create ACL tables
|
||||
./Console/cake schema create DbAcl
|
||||
# populate ACL acos
|
||||
./Console/cake acl create aco root controllers
|
||||
./Console/cake AclExtras.AclExtras aco_sync
|
||||
|
||||
# create Correlation table
|
||||
./Console/cake schema create DbCorrelation
|
||||
|
||||
# create Regexp table
|
||||
./Console/cake schema create DbRegexp
|
||||
|
||||
# create Whitelist table
|
||||
./Console/cake schema create DbWhitelist
|
||||
|
||||
# update Schema, add Users.role_id
|
||||
./Console/cake schema update -s 0.2.2.1
|
||||
|
||||
# create Log table
|
||||
./Console/cake schema create DbLog
|
||||
|
||||
# create Roles, populate ACL aros and Users.role_id
|
||||
./Console/cake schema create DbRole
|
||||
|
||||
# populate 0.2.3
|
||||
./Console/cake populate0_2_3
|
||||
|
||||
exit 0;
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# migrate 0.2.1.1 to 0.2.2
|
||||
|
||||
# Servers.lastpushedid and Servers.lastpulledid
|
||||
|
||||
# step into project and ..
|
||||
PRJCT=/var/www/MISP/app
|
||||
cd ${PRJCT}
|
||||
|
||||
# update Schema, add Users.role_id
|
||||
./Console/cake schema update -s 0.2.2
|
||||
|
||||
exit 0
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
USER=noud
|
||||
CY_HOME=../../../../MISP
|
||||
|
||||
chown -R ${USER}:www-data ${CY_HOME}
|
||||
chmod -R 750 ${CY_HOME}
|
||||
chmod -R g+s ${CY_HOME}
|
||||
cd ${CY_HOME}/app/
|
||||
chmod -R g+w tmp
|
||||
chmod -R g+w files
|
||||
|
||||
# GnuPG
|
||||
chmod -R ug+rwx ${CY_HOME}/.gnupg
|
||||
|
||||
exit 0
|
|
@ -46,13 +46,13 @@ class AppController extends Controller
|
|||
|
||||
public $helpers = array('Utility', 'OrgImg');
|
||||
|
||||
private $__queryVersion = '46';
|
||||
public $pyMispVersion = '2.4.96';
|
||||
public $phpmin = '5.6.5';
|
||||
private $__queryVersion = '60';
|
||||
public $pyMispVersion = '2.4.102';
|
||||
public $phpmin = '7.0.16';
|
||||
public $phprec = '7.0.16';
|
||||
|
||||
public $baseurl = '';
|
||||
public $sql_dump = false;
|
||||
public $sql_dump = false;
|
||||
|
||||
// Used for _isAutomation(), a check that returns true if the controller & action combo matches an action that is a non-xml and non-json automation method
|
||||
// This is used to allow authentication via headers for methods not covered by _isRest() - as that only checks for JSON and XML formats
|
||||
|
@ -90,7 +90,7 @@ class AppController extends Controller
|
|||
'ACL',
|
||||
'RestResponse',
|
||||
'Flash'
|
||||
//,'DebugKit.Toolbar'
|
||||
//,'DebugKit.Toolbar'
|
||||
);
|
||||
|
||||
private function __isApiFunction($controller, $action)
|
||||
|
@ -103,9 +103,24 @@ class AppController extends Controller
|
|||
|
||||
public function beforeFilter()
|
||||
{
|
||||
if (!empty($this->params['named']['sql'])) {
|
||||
$this->sql_dump = 1;
|
||||
}
|
||||
if (Configure::read('Security.allow_cors')) {
|
||||
// Add CORS headers
|
||||
$this->response->cors($this->request,
|
||||
explode(',', Configure::read('Security.cors_origins')),
|
||||
['*'],
|
||||
['Origin', 'Content-Type', 'Authorization', 'Accept']);
|
||||
|
||||
if ($this->request->is('options')) {
|
||||
// Stop here!
|
||||
// CORS only needs the headers
|
||||
$this->response->send();
|
||||
$this->_stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->params['named']['sql'])) {
|
||||
$this->sql_dump = 1;
|
||||
}
|
||||
// check for a supported datasource configuration
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
if (!isset($dataSourceConfig['encoding'])) {
|
||||
|
@ -333,6 +348,9 @@ class AppController extends Controller
|
|||
}
|
||||
} else {
|
||||
if (!($this->params['controller'] === 'users' && $this->params['action'] === 'login')) {
|
||||
if (!$this->request->is('ajax')) {
|
||||
$this->Session->write('pre_login_requested_url', $this->here);
|
||||
}
|
||||
$this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => false));
|
||||
}
|
||||
}
|
||||
|
@ -360,20 +378,20 @@ class AppController extends Controller
|
|||
|
||||
if ($this->Session->check(AuthComponent::$sessionKey)) {
|
||||
if ($this->action !== 'checkIfLoggedIn' || $this->request->params['controller'] !== 'users') {
|
||||
$this->User->id = $this->Auth->user('id');
|
||||
if (!$this->User->exists()) {
|
||||
$message = __('Something went wrong. Your user account that you are authenticated with doesn\'t exist anymore.');
|
||||
if ($this->_isRest) {
|
||||
$this->RestResponse->throwException(
|
||||
401,
|
||||
$message
|
||||
);
|
||||
} else {
|
||||
$this->Flash->info($message);
|
||||
}
|
||||
$this->Auth->logout();
|
||||
$this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => false));
|
||||
}
|
||||
$this->User->id = $this->Auth->user('id');
|
||||
if (!$this->User->exists()) {
|
||||
$message = __('Something went wrong. Your user account that you are authenticated with doesn\'t exist anymore.');
|
||||
if ($this->_isRest) {
|
||||
$this->RestResponse->throwException(
|
||||
401,
|
||||
$message
|
||||
);
|
||||
} else {
|
||||
$this->Flash->info($message);
|
||||
}
|
||||
$this->Auth->logout();
|
||||
$this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => false));
|
||||
}
|
||||
if (!empty(Configure::read('MISP.terms_file')) && !$this->Auth->user('termsaccepted') && (!in_array($this->request->here, array($base_dir.'/users/terms', $base_dir.'/users/logout', $base_dir.'/users/login', $base_dir.'/users/downloadTerms')))) {
|
||||
//if ($this->_isRest()) throw new MethodNotAllowedException('You have not accepted the terms of use yet, please log in via the web interface and accept them.');
|
||||
if (!$this->_isRest()) {
|
||||
|
@ -407,6 +425,7 @@ class AppController extends Controller
|
|||
$this->set('me', $this->Auth->user());
|
||||
$this->set('isAdmin', $role['perm_admin']);
|
||||
$this->set('isSiteAdmin', $role['perm_site_admin']);
|
||||
$this->set('hostOrgUser', $this->Auth->user('org_id') == Configure::read('MISP.host_org_id'));
|
||||
$this->set('isAclAdd', $role['perm_add']);
|
||||
$this->set('isAclModify', $role['perm_modify']);
|
||||
$this->set('isAclModifyOrg', $role['perm_modify_org']);
|
||||
|
@ -454,13 +473,13 @@ class AppController extends Controller
|
|||
$this->ACL->checkAccess($this->Auth->user(), Inflector::variable($this->request->params['controller']), $this->action);
|
||||
}
|
||||
|
||||
public function afterFilter()
|
||||
{
|
||||
if (Configure::read('debug') > 1 && !empty($this->sql_dump) && $this->_isRest()) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
echo json_encode($this->Log->getDataSource()->getLog(false, false), JSON_PRETTY_PRINT);
|
||||
}
|
||||
}
|
||||
public function afterFilter()
|
||||
{
|
||||
if (Configure::read('debug') > 1 && !empty($this->sql_dump) && $this->_isRest()) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
echo json_encode($this->Log->getDataSource()->getLog(false, false), JSON_PRETTY_PRINT);
|
||||
}
|
||||
}
|
||||
|
||||
public function queryACL($debugType='findMissingFunctionNames', $content = false)
|
||||
{
|
||||
|
@ -505,14 +524,14 @@ class AppController extends Controller
|
|||
return $this->request->header('Accept') === 'application/json' || $this->RequestHandler->prefers() === 'json';
|
||||
}
|
||||
|
||||
protected function _isCsv($data=false)
|
||||
{
|
||||
if ($this->params['ext'] === 'csv' || $this->request->header('Accept') === 'application/csv' || $this->RequestHandler->prefers() === 'csv') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
protected function _isCsv($data=false)
|
||||
{
|
||||
if ($this->params['ext'] === 'csv' || $this->request->header('Accept') === 'application/csv' || $this->RequestHandler->prefers() === 'csv') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function _isRest()
|
||||
{
|
||||
|
@ -583,7 +602,7 @@ class AppController extends Controller
|
|||
);
|
||||
return false;
|
||||
}
|
||||
$key = 'json';
|
||||
$key = 'json';
|
||||
} else {
|
||||
if (!$this->Auth->user('id')) {
|
||||
$exception = $this->RestResponse->throwException(
|
||||
|
@ -627,21 +646,37 @@ class AppController extends Controller
|
|||
$data[$p] = str_replace(';', ':', $data[$p]);
|
||||
}
|
||||
if (isset($options['named_params'][$p])) {
|
||||
$data[$p] = $options['named_params'][$p];
|
||||
$data[$p] = str_replace(';', ':', $options['named_params'][$p]);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($data as $k => $v) {
|
||||
if (!is_array($data[$k])) {
|
||||
$data[$k] = trim($data[$k]);
|
||||
if (strpos($data[$k], '||')) {
|
||||
$data[$k] = explode('||', $data[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($options['additional_delimiters'])) {
|
||||
if (!is_array($options['additional_delimiters'])) {
|
||||
$options['additional_delimiters'] = array($options['additional_delimiters']);
|
||||
}
|
||||
foreach ($data as $k => $v) {
|
||||
$found = false;
|
||||
foreach ($options['additional_delimiters'] as $delim) {
|
||||
if (strpos($v, $delim) !== false) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
if ($found) {
|
||||
$data[$k] = explode($options['additional_delimiters'][0], str_replace($options['additional_delimiters'], $options['additional_delimiters'][0], $v));
|
||||
foreach ($data[$k] as $k2 => $value) {
|
||||
$data[$k][$k2] = trim($data[$k][$k2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($options['additional_delimiters'])) {
|
||||
if (!is_array($options['additional_delimiters'])) {
|
||||
$options['additional_delimiters'] = array($options['additional_delimiters']);
|
||||
}
|
||||
foreach ($data as $k => $v) {
|
||||
$data[$k] = explode($options['additional_delimiters'][0], str_replace($options['additional_delimiters'], $options['additional_delimiters'][0], $v));
|
||||
foreach ($data[$k] as $k2 => $value) {
|
||||
$data[$k][$k2] = trim($data[$k][$k2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,14 +59,17 @@ class AttributesController extends AppController
|
|||
{
|
||||
$this->Attribute->recursive = -1;
|
||||
if (!$this->_isRest()) {
|
||||
$this->paginate['recursive'] = -1;
|
||||
$this->paginate['contain'] = array(
|
||||
'Event' => array(
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.info', 'Event.user_id')
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.info', 'Event.user_id', 'Event.date'),
|
||||
'Orgc' => array('fields' => array('Orgc.id', 'Orgc.name')),
|
||||
'Org' => array('fields' => array('Org.id', 'Org.name'))
|
||||
),
|
||||
'AttributeTag' => array('Tag'),
|
||||
'Object' => array(
|
||||
'fields' => array('Object.id', 'Object.distribution', 'Object.sharing_group_id')
|
||||
),
|
||||
'AttributeTag'
|
||||
)
|
||||
);
|
||||
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
|
||||
}
|
||||
|
@ -77,28 +80,6 @@ class AttributesController extends AppController
|
|||
}
|
||||
$org_ids = array();
|
||||
$tag_ids = array();
|
||||
foreach ($attributes as $k => $attribute) {
|
||||
if (empty($attribute['Event']['id'])) {
|
||||
unset($attribute[$k]);
|
||||
continue;
|
||||
}
|
||||
if ($attribute['Attribute']['type'] == 'attachment' && preg_match('/.*\.(jpg|png|jpeg|gif)$/i', $attribute['Attribute']['value'])) {
|
||||
$attributes[$k]['Attribute']['image'] = $this->Attribute->base64EncodeAttachment($attribute['Attribute']);
|
||||
}
|
||||
if (!in_array($attribute['Event']['orgc_id'], $org_ids)) {
|
||||
$org_ids[] = $attribute['Event']['orgc_id'];
|
||||
}
|
||||
if (!in_array($attribute['Event']['org_id'], $org_ids)) {
|
||||
$org_ids[] = $attribute['Event']['org_id'];
|
||||
}
|
||||
if (!empty($attribute['AttributeTag'])) {
|
||||
foreach ($attribute['AttributeTag'] as $k => $v) {
|
||||
if (!in_array($v['tag_id'], $tag_ids)) {
|
||||
$tag_ids[] = $v['tag_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$orgs = $this->Attribute->Event->Orgc->find('list', array(
|
||||
'conditions' => array('Orgc.id' => $org_ids),
|
||||
'fields' => array('Orgc.id', 'Orgc.name')
|
||||
|
@ -110,21 +91,16 @@ class AttributesController extends AppController
|
|||
'fields' => array('Tag.id', 'Tag.name', 'Tag.colour')
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($attributes as $k => $attribute) {
|
||||
$attributes[$k]['Event']['Orgc'] = array('id' => $attribute['Event']['orgc_id'], 'name' => $orgs[$attribute['Event']['orgc_id']]);
|
||||
$attributes[$k]['Event']['Org'] = array('id' => $attribute['Event']['org_id'], 'name' => $orgs[$attribute['Event']['org_id']]);
|
||||
if (!empty($attribute['AttributeTag'])) {
|
||||
foreach ($attribute['AttributeTag'] as $kat => $at) {
|
||||
foreach ($tags as $ktag => $tag) {
|
||||
if ($tag['Tag']['id'] == $at['tag_id']) {
|
||||
$attributes[$k]['AttributeTag'][$kat]['Tag'] = $tag['Tag'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->_isRest()) {
|
||||
$temp = $this->__searchUI($attributes);
|
||||
$this->loadModel('Galaxy');
|
||||
$this->set('mitreAttackGalaxyId', $this->Galaxy->getMitreAttackGalaxyId());
|
||||
$attributes = $temp[0];
|
||||
$sightingsData = $temp[1];
|
||||
$this->set('sightingsData', $sightingsData);
|
||||
}
|
||||
$this->set('orgs', $orgs);
|
||||
$this->set('shortDist', $this->Attribute->shortDist);
|
||||
$this->set('attributes', $attributes);
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
|
@ -190,9 +166,10 @@ class AttributesController extends AppController
|
|||
} else {
|
||||
$values = explode("\n", $this->request->data['Attribute']['value']);
|
||||
}
|
||||
$temp = $this->request->data['Attribute'];
|
||||
foreach ($values as $value) {
|
||||
$this->request->data['Attribute']['value'] = $value;
|
||||
$attributes[] = $this->request->data['Attribute'];
|
||||
$temp['value'] = $value;
|
||||
$attributes[] = $temp;
|
||||
}
|
||||
} else {
|
||||
$attributes = $this->request->data['Attribute'];
|
||||
|
@ -318,18 +295,19 @@ class AttributesController extends AppController
|
|||
if (empty($fails)) {
|
||||
$message = 'Attributes saved.';
|
||||
} else {
|
||||
if (count($attributes) > 1) {
|
||||
if ($attributeCount > 1) {
|
||||
$failKeys = array_keys($fails);
|
||||
foreach ($failKeys as $k => $v) {
|
||||
$v = explode('_', $v);
|
||||
$failKeys[$k] = intval($v[1]) + 1;
|
||||
$failKeys[$k] = intval($v[1]);
|
||||
}
|
||||
$message = 'Attributes saved, however, attributes ' . implode(', ', $failKeys) . ' could not be saved.';
|
||||
$failed = 1;
|
||||
$message = sprintf('Attributes saved, however, %s attributes could not be saved. Click %s for more info', count($fails), '$flashErrorMessage');
|
||||
} else {
|
||||
if (!empty($fails["attribute_0"])) {
|
||||
foreach ($fails["attribute_0"] as $k => $v) {
|
||||
$failed = 1;
|
||||
$message = '$this->Flash->info [' . $k . ']: ' . $v[0];
|
||||
$message = $k . ': ' . $v[0];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -338,6 +316,25 @@ class AttributesController extends AppController
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!empty($failKeys)) {
|
||||
$flashErrorMessage = array();
|
||||
$original_values = trim($this->request->data['Attribute']['value']);
|
||||
$original_values = explode("\n", $original_values);
|
||||
foreach ($original_values as $k => $original_value) {
|
||||
$original_value = trim($original_value);
|
||||
if (in_array($k, $failKeys)) {
|
||||
$reason = '';
|
||||
foreach ($fails["attribute_" . $k] as $failKey => $failData) {
|
||||
$reason = $failKey . ': ' . $failData[0];
|
||||
}
|
||||
$flashErrorMessage[] = '<span class="red bold">' . h($original_value) . '</span> (' . h($reason) . ')';
|
||||
} else {
|
||||
$flashErrorMessage[] = '<span class="green bold">' . h($original_value) . '</span>';
|
||||
}
|
||||
}
|
||||
$flashErrorMessage = implode('<br />', $flashErrorMessage);
|
||||
$this->Session->write('flashErrorMessage', $flashErrorMessage);
|
||||
}
|
||||
if ($this->request->is('ajax')) {
|
||||
$this->autoRender = false;
|
||||
$errors = ($attributeCount > 1) ? $message : $this->Attribute->validationErrors;
|
||||
|
@ -483,7 +480,10 @@ class AttributesController extends AppController
|
|||
$this->loadModel('Event');
|
||||
$this->Event->id = $this->request->data['Attribute']['event_id'];
|
||||
$this->Event->recursive = -1;
|
||||
$this->Event->read();
|
||||
$event = $this->Event->read();
|
||||
if (empty($event)) {
|
||||
throw new NotFoundException(__('Invalid Event.'));
|
||||
}
|
||||
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc_id'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
|
||||
throw new UnauthorizedException(__('You do not have permission to do that.'));
|
||||
}
|
||||
|
@ -648,6 +648,9 @@ class AttributesController extends AppController
|
|||
$this->set('sharingGroups', $sgs);
|
||||
|
||||
$events = $this->Event->findById($eventId);
|
||||
if (empty($events)) {
|
||||
throw new NotFoundException(__('Invalid Event.'));
|
||||
}
|
||||
$this->set('currentDist', $events['Event']['distribution']);
|
||||
$this->set('published', $events['Event']['published']);
|
||||
}
|
||||
|
@ -877,8 +880,13 @@ class AttributesController extends AppController
|
|||
|| $this->userRole['perm_modify_org'])) {
|
||||
// Allow the edit
|
||||
} else {
|
||||
$this->Flash->error(__('Invalid attribute.'));
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index'));
|
||||
$message = __('Invalid attribute.');
|
||||
if ($this->_isRest()) {
|
||||
throw new MethodNotAllowedException($message);
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->_isRest()) {
|
||||
|
@ -980,10 +988,14 @@ class AttributesController extends AppController
|
|||
$this->redirect(array('controller' => 'events', 'action' => 'view', $eventId));
|
||||
}
|
||||
} else {
|
||||
if (!CakeSession::read('Message.flash')) {
|
||||
$this->Flash->error(__('The attribute could not be saved. Please, try again.'));
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Attributes', 'edit', false, $this->Attribute->validationErrors);
|
||||
} else {
|
||||
$this->request->data = $this->Attribute->read(null, $id);
|
||||
if (!CakeSession::read('Message.flash')) {
|
||||
$this->Flash->error(__('The attribute could not be saved. Please, try again.'));
|
||||
} else {
|
||||
$this->request->data = $this->Attribute->read(null, $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1454,12 +1466,11 @@ class AttributesController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
public function editSelected($id)
|
||||
public function editSelected($id, $selectedAttributeIds = "[]")
|
||||
{
|
||||
if (!$this->request->is('ajax')) {
|
||||
throw new MethodNotAllowedException(__('This method can only be accessed via AJAX.'));
|
||||
}
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
$event = $this->Attribute->Event->find('first', array(
|
||||
'conditions' => array('id' => $id),
|
||||
|
@ -1480,7 +1491,18 @@ class AttributesController extends AppController
|
|||
'recursive' => -1,
|
||||
));
|
||||
|
||||
if ($this->request->data['Attribute']['to_ids'] == 2 && $this->request->data['Attribute']['distribution'] == 6 && $this->request->data['Attribute']['comment'] == null) {
|
||||
$tags_ids_remove = json_decode($this->request->data['Attribute']['tags_ids_remove']);
|
||||
$tags_ids_add = json_decode($this->request->data['Attribute']['tags_ids_add']);
|
||||
$clusters_ids_remove = json_decode($this->request->data['Attribute']['clusters_ids_remove']);
|
||||
$clusters_ids_add = json_decode($this->request->data['Attribute']['clusters_ids_add']);
|
||||
$changeInTagOrCluster = ($tags_ids_remove !== null && count($tags_ids_remove) > 0)
|
||||
|| ($tags_ids_add === null || count($tags_ids_add) > 0)
|
||||
|| ($clusters_ids_remove === null || count($clusters_ids_remove) > 0)
|
||||
|| ($clusters_ids_add === null || count($clusters_ids_add) > 0);
|
||||
|
||||
$changeInAttribute = ($this->request->data['Attribute']['to_ids'] != 2) || ($this->request->data['Attribute']['distribution'] != 6) || ($this->request->data['Attribute']['comment'] != null);
|
||||
|
||||
if (!$changeInAttribute && !$changeInTagOrCluster) {
|
||||
$this->autoRender = false;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
@ -1518,29 +1540,158 @@ class AttributesController extends AppController
|
|||
$attributes[$key]['Attribute']['timestamp'] = $timestamp;
|
||||
}
|
||||
|
||||
if ($this->Attribute->saveMany($attributes)) {
|
||||
if (!$this->_isRest()) {
|
||||
$this->Attribute->Event->insertLock($this->Auth->user(), $id);
|
||||
if ($changeInAttribute) {
|
||||
if ($this->Attribute->saveMany($attributes)) {
|
||||
if (!$this->_isRest()) {
|
||||
$this->Attribute->Event->insertLock($this->Auth->user(), $id);
|
||||
}
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$event['Event']['published'] = 0;
|
||||
$this->Attribute->Event->save($event, array('fieldList' => array('published', 'timestamp', 'info', 'id')));
|
||||
$this->autoRender = false;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
|
||||
} else {
|
||||
$this->autoRender = false;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'validationErrors' => $this->Attribute->validationErrors)), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$event['Event']['published'] = 0;
|
||||
$this->Attribute->Event->save($event, array('fieldList' => array('published', 'timestamp', 'info', 'id')));
|
||||
$this->autoRender = false;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
|
||||
} else {
|
||||
$this->autoRender = false;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'validationErrors' => $this->Attribute->validationErrors)), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
||||
// apply changes in tag/cluster
|
||||
foreach ($attributes as $key => $attribute) {
|
||||
foreach ($tags_ids_remove as $t => $tag_id) {
|
||||
$this->removeTag($attributes[$key]['Attribute']['id'], $tag_id);
|
||||
}
|
||||
foreach ($tags_ids_add as $t => $tag_id) {
|
||||
$this->addTag($attributes[$key]['Attribute']['id'], $tag_id);
|
||||
}
|
||||
$this->Galaxy = ClassRegistry::init('Galaxy');
|
||||
foreach ($clusters_ids_remove as $c => $cluster_id) {
|
||||
$this->Galaxy->detachCluster($this->Auth->user(), 'attribute', $attributes[$key]['Attribute']['id'], $cluster_id);
|
||||
}
|
||||
foreach ($clusters_ids_add as $c => $cluster_id) {
|
||||
$this->Galaxy->attachCluster($this->Auth->user(), 'attribute', $attributes[$key]['Attribute']['id'], $cluster_id);
|
||||
}
|
||||
}
|
||||
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true)), 'status' => 200, 'type' => 'json'));
|
||||
|
||||
} else {
|
||||
if (!isset($id)) {
|
||||
throw new MethodNotAllowedException(__('No event ID provided.'));
|
||||
}
|
||||
$selectedAttributeIds = json_decode($selectedAttributeIds);
|
||||
if ($selectedAttributeIds === null) {
|
||||
$selectedAttributeIds = array();
|
||||
}
|
||||
|
||||
// tags to remove
|
||||
$tags = $this->Attribute->AttributeTag->getAttributesTags($this->Auth->user(), $id, $selectedAttributeIds);
|
||||
$tagItemsRemove = array();
|
||||
foreach ($tags as $k => $tag) {
|
||||
$tagName = $tag['name'];
|
||||
$tagItemsRemove[] = array(
|
||||
'name' => $tagName,
|
||||
'value' => $tag['id'],
|
||||
'template' => array(
|
||||
'name' => array(
|
||||
'name' => $tagName,
|
||||
'label' => array(
|
||||
'background' => isset($tag['colour']) ? $tag['colour'] : '#ffffff'
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
unset($tags);
|
||||
|
||||
// clusters to remove
|
||||
$clusters = $this->Attribute->AttributeTag->getAttributesClusters($this->Auth->user(), $id, $selectedAttributeIds);
|
||||
$clusterItemsRemove = array();
|
||||
foreach ($clusters as $k => $cluster) {
|
||||
$name = $cluster['value'];
|
||||
$optionName = $cluster['value'];
|
||||
$synom = $cluster['synonyms_string'] !== '' ? ' (' . $cluster['synonyms_string'] . ')' : '';
|
||||
$optionName .= $synom;
|
||||
|
||||
$temp = array(
|
||||
'name' => $optionName,
|
||||
'value' => $cluster['id'],
|
||||
'template' => array(
|
||||
'name' => $name,
|
||||
'infoExtra' => $cluster['description']
|
||||
)
|
||||
);
|
||||
if ($cluster['synonyms_string'] !== '') {
|
||||
$temp['infoContextual'] = __('Synonyms: ') . $cluster['synonyms_string'];
|
||||
}
|
||||
$clusterItemsRemove[] = $temp;
|
||||
}
|
||||
unset($clusters);
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
|
||||
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
|
||||
$conditions = array('Tag.hide_tag' => 0);
|
||||
}
|
||||
$allTags = $this->Attribute->AttributeTag->Tag->find('all', array('conditions' => $conditions, 'recursive' => -1));
|
||||
$tags = array();
|
||||
foreach ($allTags as $i => $tag) {
|
||||
$tags[$tag['Tag']['id']] = $tag['Tag'];
|
||||
}
|
||||
unset($allTags);
|
||||
$tagItemsAdd = array();
|
||||
foreach ($tags as $k => $tag) {
|
||||
$tagName = $tag['name'];
|
||||
$tagItemsAdd[] = array(
|
||||
'name' => $tagName,
|
||||
'value' => $tag['id'],
|
||||
'template' => array(
|
||||
'name' => array(
|
||||
'name' => $tagName,
|
||||
'label' => array(
|
||||
'background' => isset($tag['colour']) ? $tag['colour'] : '#ffffff'
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
// clusters to add
|
||||
$this->GalaxyCluster = ClassRegistry::init('GalaxyCluster');
|
||||
$clusters = $this->GalaxyCluster->find('all', array(
|
||||
'fields' => array('value', 'id'),
|
||||
'recursive' => -1
|
||||
));
|
||||
$clusterItemsAdd = array();
|
||||
foreach ($clusters as $k => $cluster) {
|
||||
$clusterItemsAdd[] = array(
|
||||
'name' => $cluster['GalaxyCluster']['value'],
|
||||
'value' => $cluster['GalaxyCluster']['id']
|
||||
);
|
||||
}
|
||||
unset($clusters);
|
||||
|
||||
$this->layout = 'ajax';
|
||||
$this->set('id', $id);
|
||||
$this->set('sgs', $this->Attribute->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', true));
|
||||
$this->set('distributionLevels', $this->Attribute->distributionLevels);
|
||||
$this->set('distributionDescriptions', $this->Attribute->distributionDescriptions);
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('tagItemsRemove', $tagItemsRemove);
|
||||
$this->set('tagItemsAdd', $tagItemsAdd);
|
||||
$this->set('clusterItemsAdd', $clusterItemsAdd);
|
||||
$this->set('clusterItemsRemove', $clusterItemsRemove);
|
||||
$this->set('options', array( // set chosen (select picker) options
|
||||
'multiple' => -1,
|
||||
'disabledSubmitButton' => true,
|
||||
'flag_redraw_chosen' => true,
|
||||
'select_options' => array(
|
||||
'additionalData' => array(
|
||||
'event_id' => $id,
|
||||
),
|
||||
),
|
||||
));
|
||||
$this->render('ajax/attributeEditMassForm');
|
||||
}
|
||||
}
|
||||
|
@ -1566,87 +1717,159 @@ class AttributesController extends AppController
|
|||
|
||||
public function search($continue = false)
|
||||
{
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
|
||||
if ($this->request->is('post')) {
|
||||
if (isset($this->request->data['Attribute'])) {
|
||||
$this->request->data = $this->request->data['Attribute'];
|
||||
}
|
||||
$checkForEmpty = array('value', 'tags', 'uuid', 'org', 'type', 'category');
|
||||
foreach ($checkForEmpty as $field) {
|
||||
if (empty($this->request->data[$field]) || $this->request->data[$field] === 'ALL') {
|
||||
unset($this->request->data[$field]);
|
||||
}
|
||||
}
|
||||
if (empty($this->request->data['to_ids'])) {
|
||||
unset($this->request->data['to_ids']);
|
||||
$this->request->data['ignore'] = 1;
|
||||
}
|
||||
$paramArray = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'event_timestamp', 'threat_level_id', 'includeEventTags');
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
'paramArray' => $paramArray,
|
||||
'ordered_url_params' => compact($paramArray),
|
||||
'additional_delimiters' => PHP_EOL
|
||||
);
|
||||
$exception = false;
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
unset($filterData);
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
}
|
||||
$this->Session->write('search_attributes_filters', json_encode($filters));
|
||||
} else if ($continue === 'results') {
|
||||
$filters = $this->Session->read('search_attributes_filters');
|
||||
if (empty($filters)) {
|
||||
$filters = array();
|
||||
} else {
|
||||
$filters = json_decode($filters, true);
|
||||
}
|
||||
} else {
|
||||
$types = array('' => array('ALL' => 'ALL'), 'types' => array());
|
||||
$types['types'] = array_merge($types['types'], $this->_arrayToValuesIndexArray(array_keys($this->Attribute->typeDefinitions)));
|
||||
ksort($types['types']);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
$categories['categories'] = array_merge(array('ALL' => 'ALL'), $this->_arrayToValuesIndexArray(array_keys($this->Attribute->categoryDefinitions)));
|
||||
$this->set('categories', $categories);
|
||||
$this->Session->write('search_attributes_filters', null);
|
||||
}
|
||||
if (isset($filters)) {
|
||||
$params = $this->Attribute->restSearch($this->Auth->user(), 'json', $filters, true);
|
||||
$this->paginate = $params;
|
||||
if (empty($this->paginate['limit'])) {
|
||||
$this->paginate['limit'] = 60;
|
||||
}
|
||||
if (empty($this->paginate['page'])) {
|
||||
$this->paginate['page'] = 1;
|
||||
}
|
||||
$this->paginate['recursive'] = -1;
|
||||
$this->paginate['contain'] = array(
|
||||
'Event' => array(
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.info', 'Event.user_id'),
|
||||
'Orgc' => array('fields' => array('Orgc.id', 'Orgc.name')),
|
||||
'Org' => array('fields' => array('Org.id', 'Org.name'))
|
||||
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
|
||||
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
|
||||
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
|
||||
$this->set('shortDist', $this->Attribute->shortDist);
|
||||
if ($this->request->is('post') || !empty($this->request->params['named']['tags'])) {
|
||||
if (isset($this->request->data['Attribute'])) {
|
||||
$this->request->data = $this->request->data['Attribute'];
|
||||
}
|
||||
$checkForEmpty = array('value', 'tags', 'uuid', 'org', 'type', 'category');
|
||||
foreach ($checkForEmpty as $field) {
|
||||
if (empty($this->request->data[$field]) || $this->request->data[$field] === 'ALL') {
|
||||
unset($this->request->data[$field]);
|
||||
}
|
||||
}
|
||||
if (empty($this->request->data['to_ids'])) {
|
||||
unset($this->request->data['to_ids']);
|
||||
$this->request->data['ignore'] = 1;
|
||||
}
|
||||
$paramArray = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'event_timestamp', 'threat_level_id', 'includeEventTags');
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
'paramArray' => $paramArray,
|
||||
'ordered_url_params' => compact($paramArray),
|
||||
'additional_delimiters' => PHP_EOL
|
||||
);
|
||||
$exception = false;
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
unset($filterData);
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
}
|
||||
$this->Session->write('search_attributes_filters', json_encode($filters));
|
||||
} elseif ($continue === 'results') {
|
||||
$filters = $this->Session->read('search_attributes_filters');
|
||||
if (empty($filters)) {
|
||||
$filters = array();
|
||||
} else {
|
||||
$filters = json_decode($filters, true);
|
||||
}
|
||||
} else {
|
||||
$types = array('' => array('ALL' => 'ALL'), 'types' => array());
|
||||
$types['types'] = array_merge($types['types'], $this->_arrayToValuesIndexArray(array_keys($this->Attribute->typeDefinitions)));
|
||||
ksort($types['types']);
|
||||
$this->set('types', $types);
|
||||
// combobox for categories
|
||||
$categories['categories'] = array_merge(array('ALL' => 'ALL'), $this->_arrayToValuesIndexArray(array_keys($this->Attribute->categoryDefinitions)));
|
||||
$this->set('categories', $categories);
|
||||
$this->Session->write('search_attributes_filters', null);
|
||||
}
|
||||
if (isset($filters)) {
|
||||
$params = $this->Attribute->restSearch($this->Auth->user(), 'json', $filters, true);
|
||||
if (!isset($params['conditions']['Attribute.deleted'])) {
|
||||
$params['conditions']['Attribute.deleted'] = 0;
|
||||
}
|
||||
$this->paginate = $params;
|
||||
if (empty($this->paginate['limit'])) {
|
||||
$this->paginate['limit'] = 60;
|
||||
}
|
||||
if (empty($this->paginate['page'])) {
|
||||
$this->paginate['page'] = 1;
|
||||
}
|
||||
$this->paginate['recursive'] = -1;
|
||||
$this->paginate['contain'] = array(
|
||||
'Event' => array(
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.info', 'Event.user_id', 'Event.date'),
|
||||
'Orgc' => array('fields' => array('Orgc.id', 'Orgc.name')),
|
||||
'Org' => array('fields' => array('Org.id', 'Org.name'))
|
||||
),
|
||||
'AttributeTag' => array('Tag'),
|
||||
'Object' => array(
|
||||
'AttributeTag' => array('Tag'),
|
||||
'Object' => array(
|
||||
'fields' => array('Object.id', 'Object.distribution', 'Object.sharing_group_id')
|
||||
)
|
||||
);
|
||||
$attributes = $this->paginate();
|
||||
$this->set('filters', $filters);
|
||||
$this->set('attributes', $attributes);
|
||||
$this->set('isSearch', 1);
|
||||
$this->render('index');
|
||||
}
|
||||
);
|
||||
$attributes = $this->paginate();
|
||||
if (!$this->_isRest()) {
|
||||
$temp = $this->__searchUI($attributes);
|
||||
$this->loadModel('Galaxy');
|
||||
$this->set('mitreAttackGalaxyId', $this->Galaxy->getMitreAttackGalaxyId());
|
||||
$attributes = $temp[0];
|
||||
$sightingsData = $temp[1];
|
||||
$this->set('sightingsData', $sightingsData);
|
||||
} else {
|
||||
return $this->RestResponse->viewData($attributes, $this->response->type());
|
||||
}
|
||||
if (isset($filters['tags']) && !empty($filters['tags'])) {
|
||||
// if the tag is passed by ID - show its name in the view
|
||||
$this->loadModel('Tag');
|
||||
if (!is_array($filters['tags'])) {
|
||||
$filters['tags'] = array($filters['tags']);
|
||||
}
|
||||
foreach ($filters['tags'] as $k => &$v) {
|
||||
if (!is_numeric($v))
|
||||
continue;
|
||||
$tag = $this->Tag->find('first', [
|
||||
'conditions' => ['Tag.id' => $v],
|
||||
'fields' => ['name'],
|
||||
'recursive' => -1
|
||||
]);
|
||||
if (!empty($tag)) {
|
||||
$v = $tag['Tag']['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->set('filters', $filters);
|
||||
$this->set('attributes', $attributes);
|
||||
$this->set('isSearch', 1);
|
||||
$this->render('index');
|
||||
}
|
||||
if (isset($attributeTags)) {
|
||||
$this->set('attributeTags', $attributeTags);
|
||||
}
|
||||
}
|
||||
|
||||
private function __searchUI($attributes)
|
||||
{
|
||||
$sightingsData = array();
|
||||
$sgids = $this->Attribute->Event->cacheSgids($this->Auth->user(), true);
|
||||
$this->Feed = ClassRegistry::init('Feed');
|
||||
if (!empty($options['overrideLimit'])) {
|
||||
$overrideLimit = true;
|
||||
} else {
|
||||
$overrideLimit = false;
|
||||
}
|
||||
$this->loadModel('GalaxyCluster');
|
||||
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name', 'GalaxyCluster.id')));
|
||||
$this->loadModel('Sighting');
|
||||
foreach ($attributes as $k => $attribute) {
|
||||
$attributes[$k]['Attribute']['AttributeTag'] = $attributes[$k]['AttributeTag'];
|
||||
$attributes[$k]['Attribute'] = $this->Attribute->Event->massageTags($attributes[$k]['Attribute'], 'Attribute');
|
||||
unset($attributes[$k]['AttributeTag']);
|
||||
foreach ($attributes[$k]['Attribute']['AttributeTag'] as $k2 => $attributeTag) {
|
||||
if (in_array($attributeTag['Tag']['name'], $cluster_names)) {
|
||||
unset($attributes[$k]['Attribute']['AttributeTag'][$k2]);
|
||||
}
|
||||
}
|
||||
$sightingsData = array_merge(
|
||||
$sightingsData,
|
||||
$this->Sighting->attachToEvent($attribute, $this->Auth->user(), $attributes[$k]['Attribute']['id'], $extraConditions = false)
|
||||
);
|
||||
$correlations = $this->Attribute->Event->getRelatedAttributes($this->Auth->user(), $attributes[$k]['Attribute']['id'], false, false, 'attribute');
|
||||
if (!empty($correlations)) {
|
||||
$attributes[$k]['Attribute']['RelatedAttribute'] = $correlations[$attributes[$k]['Attribute']['id']];
|
||||
}
|
||||
$temp = $this->Feed->attachFeedCorrelations(array($attributes[$k]['Attribute']), $this->Auth->user, $attributes[$k]['Event'], $overrideLimit);
|
||||
if (!empty($temp)) {
|
||||
$attributes[$k]['Attribute'] = $temp[0];
|
||||
}
|
||||
}
|
||||
$sightingsData = $this->Attribute->Event->getSightingData(array('Sighting' => $sightingsData));
|
||||
return array($attributes, $sightingsData);
|
||||
}
|
||||
|
||||
// If the checkbox for the alternate search is ticked, then this method is called to return the data to be represented
|
||||
// This alternate view will show a list of events with matching search results and the percentage of those matched attributes being marked as to_ids
|
||||
// events are sorted based on relevance (as in the percentage of matches being flagged as indicators for IDS)
|
||||
|
@ -1714,35 +1937,48 @@ class AttributesController extends AppController
|
|||
$this->set('fails', $this->Attribute->checkComposites());
|
||||
}
|
||||
|
||||
public function restSearch($returnFormat = 'json', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false, $includeEventUuid = false, $event_timestamp = false, $threat_level_id = false) {
|
||||
$paramArray = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'event_timestamp', 'threat_level_id', 'includeEventTags');
|
||||
public function restSearch(
|
||||
$returnFormat = false, $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false,
|
||||
$to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false,
|
||||
$timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false, $includeEventUuid = false, $event_timestamp = false,
|
||||
$threat_level_id = false
|
||||
)
|
||||
{
|
||||
$paramArray = array(
|
||||
'value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp',
|
||||
'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'event_timestamp', 'threat_level_id', 'includeEventTags',
|
||||
'includeProposals', 'returnFormat', 'published', 'limit', 'page', 'requested_attributes', 'includeContext', 'headerless'
|
||||
);
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
'paramArray' => $paramArray,
|
||||
'ordered_url_params' => compact($paramArray)
|
||||
);
|
||||
$validFormats = $this->Attribute->validFormats;
|
||||
$validFormats = $this->Attribute->validFormats;
|
||||
$exception = false;
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
unset($filterData);
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
return $exception;
|
||||
}
|
||||
$list = array();
|
||||
$user = $this->_getApiAuthUser($returnFormat, $exception);
|
||||
if ($user === false) {
|
||||
return $exception;
|
||||
return $exception;
|
||||
}
|
||||
if (isset($filters['returnFormat'])) {
|
||||
$returnFormat = $filters['returnFormat'];
|
||||
$returnFormat = $filters['returnFormat'];
|
||||
} else {
|
||||
$returnFormat = 'json';
|
||||
}
|
||||
if ($returnFormat === 'download') {
|
||||
$returnFormat = 'json';
|
||||
}
|
||||
$final = $this->Attribute->restSearch($user, $returnFormat, $filters);
|
||||
if ($returnFormat === 'download') {
|
||||
$returnFormat = 'json';
|
||||
}
|
||||
$elementCounter = 0;
|
||||
$final = $this->Attribute->restSearch($user, $returnFormat, $filters, false, false, $elementCounter);
|
||||
$responseType = $validFormats[$returnFormat][0];
|
||||
return $this->RestResponse->viewData($final, $responseType, false, true);
|
||||
return $this->RestResponse->viewData($final, $responseType, false, true, false, array('X-Result-Count' => $elementCounter, 'X-Export-Module-Used' => $returnFormat, 'X-Response-Format' => $responseType));
|
||||
}
|
||||
|
||||
// returns an XML with attributes that belong to an event. The type of attributes to be returned can be restricted by type using the 3rd parameter.
|
||||
|
@ -2632,7 +2868,7 @@ class AttributesController extends AppController
|
|||
$this->redirect('/pages/display/administration');
|
||||
}
|
||||
|
||||
public function hoverEnrichment($id)
|
||||
public function hoverEnrichment($id, $persistent = false)
|
||||
{
|
||||
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id), 'flatten' => 1));
|
||||
if (empty($attribute)) {
|
||||
|
@ -2665,6 +2901,9 @@ class AttributesController extends AppController
|
|||
throw new MethodNotAllowedException(__('No valid enrichment options found for this attribute.'));
|
||||
}
|
||||
$data = array('module' => $type, $attribute[0]['Attribute']['type'] => $attribute[0]['Attribute']['value']);
|
||||
if ($persistent) {
|
||||
$data['persistent'] = 1;
|
||||
}
|
||||
if (!empty($options)) {
|
||||
$data['config'] = $options;
|
||||
}
|
||||
|
@ -2672,11 +2911,11 @@ class AttributesController extends AppController
|
|||
$result = $this->Module->queryModuleServer('/query', $data, true);
|
||||
if ($result) {
|
||||
if (!is_array($result)) {
|
||||
$resultArray[] = array($type => $result);
|
||||
$resultArray[$type][] = array($type => $result);
|
||||
}
|
||||
} else {
|
||||
// TODO: i18n?
|
||||
$resultArray[] = array($type => 'Enrichment service not reachable.');
|
||||
$resultArray[$type][] = array($type => 'Enrichment service not reachable.');
|
||||
continue;
|
||||
}
|
||||
if (!empty($result['results'])) {
|
||||
|
@ -2689,11 +2928,11 @@ class AttributesController extends AppController
|
|||
}
|
||||
$tempArray[$k] = $v;
|
||||
}
|
||||
$resultArray[] = array($type => $tempArray);
|
||||
$resultArray[$type][] = array($type => $tempArray);
|
||||
} elseif ($r['values'] == null) {
|
||||
$resultArray[] = array($type => 'No result');
|
||||
$resultArray[$type][] = array($type => 'No result');
|
||||
} else {
|
||||
$resultArray[] = array($type => $r['values']);
|
||||
$resultArray[$type][] = array($type => $r['values']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2772,15 +3011,52 @@ class AttributesController extends AppController
|
|||
$tag_id = $this->request->data['tag'];
|
||||
}
|
||||
if (!is_numeric($tag_id)) {
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
|
||||
if (empty($tag)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200, 'type' => 'json'));
|
||||
if (preg_match('/^collection_[0-9]+$/i', $tag_id)) {
|
||||
$tagChoice = explode('_', $tag_id)[1];
|
||||
$this->loadModel('TagCollection');
|
||||
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $tagChoice)));
|
||||
if (empty($tagCollection)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$tag_id_list = array();
|
||||
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
|
||||
$tag_id_list[] = $tagCollectionTag['tag_id'];
|
||||
}
|
||||
} else {
|
||||
// try to parse json array
|
||||
$tag_ids = json_decode($tag_id);
|
||||
if ($tag_ids !== null) { // can decode json
|
||||
$tag_id_list = array();
|
||||
foreach ($tag_ids as $tag_id) {
|
||||
if (preg_match('/^collection_[0-9]+$/i', $tag_id)) {
|
||||
$tagChoice = explode('_', $tag_id)[1];
|
||||
$this->loadModel('TagCollection');
|
||||
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $tagChoice)));
|
||||
if (empty($tagCollection)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
|
||||
$tag_id_list[] = $tagCollectionTag['tag_id'];
|
||||
}
|
||||
} else {
|
||||
$tag_id_list[] = $tag_id;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
|
||||
if (empty($tag)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
}
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
if (!isset($idList)) {
|
||||
$idList = array($id);
|
||||
}
|
||||
if (empty($tag_id_list)) {
|
||||
$tag_id_list = array($tag_id);
|
||||
}
|
||||
$success = 0;
|
||||
$fails = 0;
|
||||
foreach ($idList as $id) {
|
||||
|
@ -2789,11 +3065,14 @@ class AttributesController extends AppController
|
|||
throw new NotFoundException(__('Invalid attribute'));
|
||||
}
|
||||
$this->Attribute->read();
|
||||
if (!$this->_isSiteAdmin() && $this->Attribute->data['Event']['orgc_id'] !== $this->Auth->user('org_id')) {
|
||||
$fails++;
|
||||
continue;
|
||||
}
|
||||
if ($this->Attribute->data['Attribute']['deleted']) {
|
||||
throw new NotFoundException(__('Invalid attribute'));
|
||||
}
|
||||
$eventId = $this->Attribute->data['Attribute']['event_id'];
|
||||
|
||||
$this->Attribute->Event->recursive = -1;
|
||||
$event = $this->Attribute->Event->read(array(), $eventId);
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
|
||||
|
@ -2805,40 +3084,44 @@ class AttributesController extends AppController
|
|||
$this->Attribute->Event->insertLock($this->Auth->user(), $eventId);
|
||||
}
|
||||
$this->Attribute->recursive = -1;
|
||||
$this->Attribute->AttributeTag->Tag->id = $tag_id;
|
||||
if (!$this->Attribute->AttributeTag->Tag->exists()) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
$found = $this->Attribute->AttributeTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'attribute_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
$this->autoRender = false;
|
||||
if (!empty($found)) {
|
||||
$fails++;
|
||||
continue;
|
||||
}
|
||||
$this->Attribute->AttributeTag->create();
|
||||
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId))) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->Event->save($event);
|
||||
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->save($this->Attribute->data);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to attribute (' . $id . ')', 'Attribute (' . $id . ') tagged as Tag (' . $tag_id . ')');
|
||||
$success++;
|
||||
} else {
|
||||
$fails++;
|
||||
|
||||
foreach ($tag_id_list as $tag_id) {
|
||||
$this->Attribute->AttributeTag->Tag->id = $tag_id;
|
||||
if (!$this->Attribute->AttributeTag->Tag->exists()) {
|
||||
$fails++;
|
||||
continue;
|
||||
}
|
||||
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
$found = $this->Attribute->AttributeTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'attribute_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
$this->autoRender = false;
|
||||
if (!empty($found)) {
|
||||
$fails++;
|
||||
continue;
|
||||
}
|
||||
$this->Attribute->AttributeTag->create();
|
||||
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId))) {
|
||||
$event['Event']['published'] = 0;
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->Event->save($event);
|
||||
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
|
||||
$this->Attribute->save($this->Attribute->data);
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to attribute (' . $id . ')', 'Attribute (' . $id . ') tagged as Tag (' . $tag_id . ')');
|
||||
$success++;
|
||||
} else {
|
||||
$fails++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($fails == 0) {
|
||||
|
@ -2952,7 +3235,7 @@ class AttributesController extends AppController
|
|||
|
||||
public function toggleCorrelation($id)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && Configure.read('MISP.allow_disabling_correlation')) {
|
||||
if (!$this->_isSiteAdmin() && Configure::read('MISP.allow_disabling_correlation')) {
|
||||
throw new MethodNotAllowedException(__('Disabling the correlation is not permitted on this instance.'));
|
||||
}
|
||||
$this->Attribute->id = $id;
|
||||
|
@ -3001,6 +3284,12 @@ class AttributesController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
public function toggleToIDS($id)
|
||||
{
|
||||
return $this->fetchEditForm($id, 'to_ids');
|
||||
}
|
||||
|
||||
|
||||
public function checkAttachments()
|
||||
{
|
||||
$attributes = $this->Attribute->find(
|
||||
|
@ -3025,19 +3314,18 @@ class AttributesController extends AppController
|
|||
return new CakeResponse(array('body'=>$counter, 'status'=>200));
|
||||
}
|
||||
|
||||
public function exportSearch($type = false)
|
||||
{
|
||||
if (empty($type)) {
|
||||
$exports = array_keys($this->Attribute->validFormats);
|
||||
$this->set('exports', $exports);
|
||||
$this->render('ajax/exportSearch');
|
||||
} else {
|
||||
$filters = $this->Session->read('search_attributes_filters');
|
||||
$filters = json_decode($filters, true);
|
||||
$final = $this->Attribute->restSearch($this->Auth->user(), $type, $filters);
|
||||
$responseType = $this->Attribute->validFormats[$type][0];
|
||||
return $this->RestResponse->viewData($final, $responseType, false, true, 'search.' . $type . '.' . $responseType);
|
||||
}
|
||||
}
|
||||
|
||||
public function exportSearch($type = false)
|
||||
{
|
||||
if (empty($type)) {
|
||||
$exports = array_keys($this->Attribute->validFormats);
|
||||
$this->set('exports', $exports);
|
||||
$this->render('ajax/exportSearch');
|
||||
} else {
|
||||
$filters = $this->Session->read('search_attributes_filters');
|
||||
$filters = json_decode($filters, true);
|
||||
$final = $this->Attribute->restSearch($this->Auth->user(), $type, $filters);
|
||||
$responseType = $this->Attribute->validFormats[$type][0];
|
||||
return $this->RestResponse->viewData($final, $responseType, false, true, 'search.' . $type . '.' . $responseType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ class ACLComponent extends Component
|
|||
'edit' => array('perm_add'),
|
||||
'editField' => array('perm_add'),
|
||||
'editSelected' => array('perm_add'),
|
||||
'exportSearch' => array('*'),
|
||||
'exportSearch' => array('*'),
|
||||
'fetchEditForm' => array('perm_add'),
|
||||
'fetchViewValue' => array('*'),
|
||||
'generateCorrelation' => array(),
|
||||
|
@ -105,6 +105,7 @@ class ACLComponent extends Component
|
|||
'enrichEvent' => array('perm_add'),
|
||||
'export' => array('*'),
|
||||
'exportChoice' => array('*'),
|
||||
'exportModule' => array('*'),
|
||||
'filterEventIdsForPush' => array('perm_sync'),
|
||||
'filterEventIndex' => array('*'),
|
||||
'freeTextImport' => array('perm_add'),
|
||||
|
@ -117,10 +118,12 @@ class ACLComponent extends Component
|
|||
'getReferenceData' => array('*'),
|
||||
'getReferences' => array('*'),
|
||||
'getObjectTemplate' => array('*'),
|
||||
'viewMitreAttackMatrix' => array('*'),
|
||||
'hids' => array('*'),
|
||||
'index' => array('*'),
|
||||
'importChoice' => array('*'),
|
||||
'importModule' => array('*'),
|
||||
'massDelete' => array('perm_site_admin'),
|
||||
'merge' => array('perm_modify'),
|
||||
'nids' => array('*'),
|
||||
'proposalEventIndex' => array('*'),
|
||||
'publish' => array('perm_publish'),
|
||||
|
@ -136,18 +139,17 @@ class ACLComponent extends Component
|
|||
'stix2' => array('*'),
|
||||
'strposarray' => array(),
|
||||
'toggleCorrelation' => array('perm_add'),
|
||||
'unpublish' => array('perm_modify'),
|
||||
'updateGraph' => array('*'),
|
||||
'upload_analysis_file' => array('perm_add'),
|
||||
'upload_sample' => array('AND' => array('perm_auth', 'perm_add')),
|
||||
'upload_stix' => array('perm_add'),
|
||||
'view' => array('*'),
|
||||
'viewEventAttributes' => array('*'),
|
||||
'viewEventGraph' => array('*'),
|
||||
'viewGraph' => array('*'),
|
||||
'xml' => array('*'),
|
||||
'merge' => array('perm_modify'),
|
||||
'importChoice' => array('*'),
|
||||
'importModule' => array('*'),
|
||||
'exportModule' => array('*')
|
||||
'viewGalaxyMatrix' => array('*'),
|
||||
'xml' => array('*')
|
||||
),
|
||||
'favouriteTags' => array(
|
||||
'index' => array('*'),
|
||||
|
@ -157,7 +159,7 @@ class ACLComponent extends Component
|
|||
'feeds' => array(
|
||||
'add' => array(),
|
||||
'cacheFeeds' => array(),
|
||||
'compareFeeds' => array(),
|
||||
'compareFeeds' => array('*'),
|
||||
'delete' => array(),
|
||||
'disable' => array(),
|
||||
'edit' => array(),
|
||||
|
@ -167,11 +169,11 @@ class ACLComponent extends Component
|
|||
'fetchSelectedFromFreetextIndex' => array(),
|
||||
'getEvent' => array(),
|
||||
'importFeeds' => array(),
|
||||
'index' => array(),
|
||||
'previewEvent' => array(),
|
||||
'previewIndex' => array(),
|
||||
'index' => array('*'),
|
||||
'previewEvent' => array('*'),
|
||||
'previewIndex' => array('*'),
|
||||
'toggleSelected' => array('perm_site_admin'),
|
||||
'view' => array(),
|
||||
'view' => array('*'),
|
||||
),
|
||||
'galaxies' => array(
|
||||
'attachCluster' => array('perm_tagger'),
|
||||
|
@ -180,13 +182,14 @@ class ACLComponent extends Component
|
|||
'selectGalaxy' => array('perm_tagger'),
|
||||
'selectGalaxyNamespace' => array('perm_tagger'),
|
||||
'selectCluster' => array('perm_tagger'),
|
||||
'showGalaxies' => array('*'),
|
||||
'update' => array(),
|
||||
'view' => array('*'),
|
||||
'viewGraph' => array('*')
|
||||
),
|
||||
'galaxyClusters' => array(
|
||||
'attachToEvent' => array('perm_tagger'),
|
||||
'delete' => array('perm_site_admin'),
|
||||
'delete' => array('perm_site_admin'),
|
||||
'detach' => array('perm_tagger'),
|
||||
'index' => array('*'),
|
||||
'view' => array('*')
|
||||
|
@ -252,6 +255,7 @@ class ACLComponent extends Component
|
|||
'delete' => array('perm_object_template'),
|
||||
'getToggleField' => array(),
|
||||
'objectChoice' => array('*'),
|
||||
'objectMetaChoice' => array('perm_add'),
|
||||
'view' => array('*'),
|
||||
'viewElements' => array('*'),
|
||||
'index' => array('*'),
|
||||
|
@ -308,13 +312,14 @@ class ACLComponent extends Component
|
|||
),
|
||||
'servers' => array(
|
||||
'add' => array(),
|
||||
'cache' => array('perm_site_admin'),
|
||||
'checkout' => array(),
|
||||
'delete' => array(),
|
||||
'deleteFile' => array(),
|
||||
'edit' => array(),
|
||||
'fetchServersForSG' => array('*'),
|
||||
'filterEventIndex' => array(),
|
||||
'getApiInfo' => array('*'),
|
||||
'getApiInfo' => array('*'),
|
||||
'getGit' => array(),
|
||||
'getInstanceUUID' => array('perm_sync'),
|
||||
'getPyMISPVersion' => array('*'),
|
||||
|
@ -372,12 +377,25 @@ class ACLComponent extends Component
|
|||
),
|
||||
'sightings' => array(
|
||||
'add' => array('perm_sighting'),
|
||||
'restSearch' => array('perm_sighting'),
|
||||
'advanced' => array('perm_sighting'),
|
||||
'delete' => array('perm_sighting'),
|
||||
'index' => array('*'),
|
||||
'listSightings' => array('perm_sighting'),
|
||||
'quickDelete' => array('perm_sighting'),
|
||||
'viewSightings' => array('perm_sighting')
|
||||
'viewSightings' => array('perm_sighting'),
|
||||
'quickAdd' => array('perm_sighting')
|
||||
),
|
||||
'tagCollections' => array(
|
||||
'add' => array('perm_tag_editor'),
|
||||
'addTag' => array('perm_tag_editor'),
|
||||
'delete' => array('perm_tag_editor'),
|
||||
'edit' => array('perm_tag_editor'),
|
||||
'getRow' => array('perm_tag_editor'),
|
||||
'import' => array('perm_tag_editor'),
|
||||
'index' => array('*'),
|
||||
'removeTag' => array('perm_tag_editor'),
|
||||
'view' => array('*')
|
||||
),
|
||||
'tags' => array(
|
||||
'add' => array('perm_tag_editor'),
|
||||
|
@ -387,10 +405,12 @@ class ACLComponent extends Component
|
|||
'index' => array('*'),
|
||||
'quickAdd' => array('perm_tag_editor'),
|
||||
'removeTagFromObject' => array('perm_tagger'),
|
||||
'search' => array('*'),
|
||||
'selectTag' => array('perm_tagger'),
|
||||
'selectTaxonomy' => array('perm_tagger'),
|
||||
'showEventTag' => array('*'),
|
||||
'showAttributeTag' => array('*'),
|
||||
'showTagControllerTag' => array('*'),
|
||||
'tagStatistics' => array('*'),
|
||||
'view' => array('*'),
|
||||
'viewGraph' => array('*'),
|
||||
|
@ -472,7 +492,7 @@ class ACLComponent extends Component
|
|||
'view' => array('*'),
|
||||
),
|
||||
'warninglists' => array(
|
||||
'checkValue' => array('perm_auth'),
|
||||
'checkValue' => array('perm_auth'),
|
||||
'delete' => array(),
|
||||
'enableWarninglist' => array(),
|
||||
'getToggleField' => array(),
|
||||
|
@ -547,9 +567,9 @@ class ACLComponent extends Component
|
|||
|
||||
private function __error($code, $message, $soft = false)
|
||||
{
|
||||
if ($soft) {
|
||||
return $code;
|
||||
}
|
||||
if ($soft) {
|
||||
return $code;
|
||||
}
|
||||
switch ($code) {
|
||||
case 404:
|
||||
throw new NotFoundException($message);
|
||||
|
|
|
@ -51,7 +51,9 @@ class ApacheAuthenticate extends BaseAuthenticate
|
|||
$ldaprdn = Configure::read('ApacheSecureAuth.ldapReaderUser'); // DN ou RDN LDAP
|
||||
$ldappass = Configure::read('ApacheSecureAuth.ldapReaderPassword');
|
||||
$ldapSearchFilter = Configure::read('ApacheSecureAuth.ldapSearchFilter');
|
||||
|
||||
// LDAP connection
|
||||
ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, Configure::read('ApacheSecureAuth.ldapNetworkTimeout', -1));
|
||||
$ldapconn = ldap_connect(Configure::read('ApacheSecureAuth.ldapServer'))
|
||||
or die('LDAP server connection failed');
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ class BlackListComponent extends Component
|
|||
|
||||
public function index($rest = false, $filters = array())
|
||||
{
|
||||
if (!empty($filters)) {
|
||||
$this->controller->paginate['conditions'] = $filters;
|
||||
}
|
||||
if (!empty($filters)) {
|
||||
$this->controller->paginate['conditions'] = $filters;
|
||||
}
|
||||
if ($this->controller->response->type() === 'application/json' || $this->controller->response->type() == 'application/xml' || $rest) {
|
||||
$blackList = $this->controller->paginate();
|
||||
$blacklist= array();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,7 @@ class EventBlacklistsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'EventBlacklist.created' => 'DESC'
|
||||
),
|
||||
|
@ -27,13 +27,13 @@ class EventBlacklistsController extends AppController
|
|||
|
||||
public function index()
|
||||
{
|
||||
$params = array();
|
||||
$validParams = array('event_uuid', 'comment');
|
||||
foreach ($validParams as $validParam) {
|
||||
if (!empty($this->params['named'][$validParam])) {
|
||||
$params[$validParam] = $this->params['named'][$validParam];
|
||||
}
|
||||
}
|
||||
$params = array();
|
||||
$validParams = array('event_uuid', 'comment');
|
||||
foreach ($validParams as $validParam) {
|
||||
if (!empty($this->params['named'][$validParam])) {
|
||||
$params[$validParam] = $this->params['named'][$validParam];
|
||||
}
|
||||
}
|
||||
$this->BlackList->index($this->_isRest(), $params);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class EventDelegationsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'EventDelegations.id' => 'DESC'
|
||||
),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,7 @@ class FavouriteTagsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'FavouriteTag.id' => 'DESC'
|
||||
),
|
||||
|
|
|
@ -4,7 +4,7 @@ App::uses('Xml', 'Utility');
|
|||
|
||||
class FeedsController extends AppController
|
||||
{
|
||||
public $components = array('Security' ,'RequestHandler'); // XXX ACL component
|
||||
public $components = array('Security' ,'RequestHandler'); // XXX ACL component
|
||||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
|
@ -22,14 +22,17 @@ class FeedsController extends AppController
|
|||
public function beforeFilter()
|
||||
{
|
||||
parent::beforeFilter();
|
||||
$this->Security->unlockedActions = array('previewIndex');
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$this->Security->unlockedActions[] = 'previewIndex';
|
||||
if (!$this->_isSiteAdmin() && $this->Auth->user('org_id') != Configure::read('MISP.host_org_id')) {
|
||||
throw new MethodNotAllowedException(__('You don\'t have the required privileges to do that.'));
|
||||
}
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
|
||||
throw NotAllowedException('You don\'t have access to this feature.');
|
||||
}
|
||||
$this->Feed->load_default_feeds();
|
||||
$scope = isset($this->passedArgs['scope']) ? $this->passedArgs['scope'] : 'all';
|
||||
if ($scope !== 'all') {
|
||||
|
@ -77,6 +80,9 @@ class FeedsController extends AppController
|
|||
|
||||
public function view($feedId)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
|
||||
throw NotAllowedException('You don\'t have access to this feature.');
|
||||
}
|
||||
$feed = $this->Feed->find('first', array(
|
||||
'conditions' => array('Feed.id' => $feedId),
|
||||
'recursive' => -1,
|
||||
|
@ -127,6 +133,9 @@ class FeedsController extends AppController
|
|||
$tags = $this->Event->EventTag->Tag->find('list', array('fields' => array('Tag.name'), 'order' => array('lower(Tag.name) asc')));
|
||||
$tags[0] = 'None';
|
||||
$this->set('tags', $tags);
|
||||
if (empty($this->request->data['Feed']['fixed_event'])) {
|
||||
$this->request->data['Feed']['fixed_event'] = 1;
|
||||
}
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->_isRest()) {
|
||||
if (empty($this->request->data['Feed'])) {
|
||||
|
@ -150,6 +159,9 @@ class FeedsController extends AppController
|
|||
$this->request->data['Feed']['sharing_group_id'] = 0;
|
||||
}
|
||||
$this->request->data['Feed']['default'] = 0;
|
||||
if (!isset($this->request->data['Feed']['source_format'])) {
|
||||
$this->request->data['Feed']['source_format'] = 'freetext';
|
||||
}
|
||||
if ($this->request->data['Feed']['source_format'] == 'freetext') {
|
||||
if ($this->request->data['Feed']['fixed_event'] == 1) {
|
||||
if (!empty($this->request->data['Feed']['target_event']) && is_numeric($this->request->data['Feed']['target_event'])) {
|
||||
|
@ -390,10 +402,10 @@ class FeedsController extends AppController
|
|||
$message = __('Fetching the feed has successfuly completed.');
|
||||
if ($this->Feed->data['Feed']['source_format'] == 'misp') {
|
||||
if (isset($result['add'])) {
|
||||
$message['result'] .= ' Downloaded ' . count($result['add']) . ' new event(s).';
|
||||
$message .= ' Downloaded ' . count($result['add']) . ' new event(s).';
|
||||
}
|
||||
if (isset($result['edit'])) {
|
||||
$message['result'] .= ' Updated ' . count($result['edit']) . ' event(s).';
|
||||
$message .= ' Updated ' . count($result['edit']) . ' event(s).';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -497,6 +509,9 @@ class FeedsController extends AppController
|
|||
|
||||
public function previewIndex($feedId)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
|
||||
throw NotAllowedException('You don\'t have access to this feature.');
|
||||
}
|
||||
$this->Feed->id = $feedId;
|
||||
if (!$this->Feed->exists()) {
|
||||
throw new NotFoundException(__('Invalid feed.'));
|
||||
|
@ -535,6 +550,27 @@ class FeedsController extends AppController
|
|||
$this->Flash->info($events);
|
||||
$this->redirect(array('controller' => 'feeds', 'action' => 'index'));
|
||||
}
|
||||
if (!empty($this->params['named']['searchall'])) {
|
||||
foreach ($events as $uuid => $event) {
|
||||
$found = false;
|
||||
if (strpos(strtolower($event['info']), strtolower($this->params['named']['searchall'])) !== false) {
|
||||
$found = true;
|
||||
}
|
||||
if (strpos(strtolower($event['Orgc']['name']), strtolower($this->params['named']['searchall'])) !== false) {
|
||||
$found = true;
|
||||
}
|
||||
if (!empty($event['Tag'])) {
|
||||
foreach ($event['Tag'] as $tag) {
|
||||
if (strpos(strtolower($tag['name']), strtolower($this->params['named']['searchall'])) !== false) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
unset($events[$uuid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($filterParams as $k => $filter) {
|
||||
if (!empty($filter)) {
|
||||
$filterParams[$k] = json_decode($filter);
|
||||
|
@ -677,6 +713,9 @@ class FeedsController extends AppController
|
|||
|
||||
public function previewEvent($feedId, $eventUuid, $all = false)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
|
||||
throw NotAllowedException('You don\'t have access to this feature.');
|
||||
}
|
||||
$this->Feed->id = $feedId;
|
||||
if (!$this->Feed->exists()) {
|
||||
throw new NotFoundException(__('Invalid feed.'));
|
||||
|
@ -836,6 +875,9 @@ class FeedsController extends AppController
|
|||
|
||||
public function compareFeeds($id = false)
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->Auth->user('org_id') == Configure::read('MISP.host_org_id')) {
|
||||
throw NotAllowedException('You don\'t have access to this feature.');
|
||||
}
|
||||
$feeds = $this->Feed->compareFeeds($id);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($feeds, $this->response->type());
|
||||
|
|
|
@ -7,7 +7,7 @@ class GalaxiesController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'contain' => array(
|
||||
|
||||
),
|
||||
|
@ -35,8 +35,8 @@ class GalaxiesController extends AppController
|
|||
if (!empty($this->params['named']['force'])) {
|
||||
$force = 1;
|
||||
} else {
|
||||
$force = 0;
|
||||
}
|
||||
$force = 0;
|
||||
}
|
||||
$result = $this->Galaxy->update($force);
|
||||
$message = 'Galaxies updated.';
|
||||
if ($this->_isRest()) {
|
||||
|
@ -79,36 +79,46 @@ class GalaxiesController extends AppController
|
|||
|
||||
public function selectGalaxy($target_id, $target_type='event', $namespace='misp')
|
||||
{
|
||||
$expectedDescription = 'ATT&CK Tactic';
|
||||
$mitreAttackGalaxyId = $this->Galaxy->getMitreAttackGalaxyId();
|
||||
$conditions = $namespace == '0' ? array() : array('namespace' => $namespace);
|
||||
if ($namespace == 'mitre-attack' || $namespace == '0') {
|
||||
$conditions[] = array('description !=' => $expectedDescription);
|
||||
$conditions2 = array('namespace' => 'mitre-attack');
|
||||
$conditions2[] = array('description' => $expectedDescription);
|
||||
|
||||
$tacticGalaxies = $this->Galaxy->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions2,
|
||||
));
|
||||
}
|
||||
$galaxies = $this->Galaxy->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions,
|
||||
'order' => array('name asc')
|
||||
));
|
||||
if (!empty($tacticGalaxies)) {
|
||||
array_unshift($galaxies, array('Galaxy' => array(
|
||||
'id' => '-1',
|
||||
'uuid' => '-1',
|
||||
'name' => $expectedDescription,
|
||||
'type' => '-1',
|
||||
'icon' => '/img/mitre-attack-icon.ico',
|
||||
'namespace' => 'mitre-attack'
|
||||
)));
|
||||
|
||||
$items = array();
|
||||
$items[] = array(
|
||||
'name' => __('All clusters'),
|
||||
'value' => "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/0'
|
||||
);
|
||||
foreach ($galaxies as $galaxy) {
|
||||
if (!isset($galaxy['Galaxy']['kill_chain_order'])) {
|
||||
$items[] = array(
|
||||
'name' => h($galaxy['Galaxy']['name']),
|
||||
'value' => "/galaxies/selectCluster/" . $target_id . '/' . $target_type . '/' . $galaxy['Galaxy']['id'],
|
||||
'template' => array(
|
||||
'preIcon' => 'fa-' . $galaxy['Galaxy']['icon'],
|
||||
'name' => $galaxy['Galaxy']['name'],
|
||||
'infoExtra' => $galaxy['Galaxy']['description'],
|
||||
)
|
||||
);
|
||||
} else { // should use matrix instead
|
||||
$param = array(
|
||||
'name' => $galaxy['Galaxy']['name'],
|
||||
'functionName' => "getMatrixPopup('" . $target_type . "', '" . $target_id . "', " . $galaxy['Galaxy']['id'] . ")",
|
||||
'isPill' => true,
|
||||
'isMatrix' => true
|
||||
);
|
||||
if ($galaxy['Galaxy']['id'] == $mitreAttackGalaxyId) {
|
||||
$param['img'] = "/img/mitre-attack-icon.ico";
|
||||
}
|
||||
$items[] = $param;
|
||||
}
|
||||
}
|
||||
$this->set('galaxies', $galaxies);
|
||||
$this->set('target_id', $target_id);
|
||||
$this->set('target_type', $target_type);
|
||||
$this->render('ajax/galaxy_choice');
|
||||
|
||||
$this->set('items', $items);
|
||||
$this->render('/Elements/generic_picker');
|
||||
}
|
||||
|
||||
public function selectGalaxyNamespace($target_id, $target_type='event')
|
||||
|
@ -116,12 +126,27 @@ class GalaxiesController extends AppController
|
|||
$namespaces = $this->Galaxy->find('list', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('namespace', 'namespace'),
|
||||
'group' => array('namespace')
|
||||
'group' => array('namespace'),
|
||||
'order' => array('namespace asc')
|
||||
));
|
||||
$this->set('namespaces', $namespaces);
|
||||
$this->set('target_id', $target_id);
|
||||
$this->set('target_type', $target_type);
|
||||
$this->render('ajax/galaxy_namespace_choice');
|
||||
|
||||
$items = array();
|
||||
$items[] = array(
|
||||
'name' => __('All namespaces'),
|
||||
'value' => "/galaxies/selectGalaxy/" . $target_id . '/' . $target_type . '/0'
|
||||
);
|
||||
foreach ($namespaces as $namespace) {
|
||||
$items[] = array(
|
||||
'name' => $namespace,
|
||||
'value' => "/galaxies/selectGalaxy/" . $target_id . '/' . $target_type . '/' . $namespace
|
||||
);
|
||||
}
|
||||
|
||||
$this->set('items', $items);
|
||||
$this->set('options', array( // set chosen (select picker) options
|
||||
'multiple' => 0,
|
||||
));
|
||||
$this->render('/Elements/generic_picker');
|
||||
}
|
||||
|
||||
public function selectCluster($target_id, $target_type = 'event', $selectGalaxy = false)
|
||||
|
@ -132,60 +157,116 @@ class GalaxiesController extends AppController
|
|||
}
|
||||
$data = $this->Galaxy->GalaxyCluster->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'fields' => array('value', 'description', 'source', 'type'),
|
||||
'contain' => array(
|
||||
'GalaxyElement' => array(
|
||||
'conditions' => array('GalaxyElement.key' => 'synonyms')
|
||||
)
|
||||
),
|
||||
'fields' => array('value', 'description', 'source', 'type', 'id'),
|
||||
'order' => array('value asc'),
|
||||
'recursive' => -1
|
||||
));
|
||||
$clusters = array();
|
||||
$lookup_table = array();
|
||||
foreach ($data as $k => $cluster) {
|
||||
$temp = $this->Galaxy->GalaxyCluster->GalaxyElement->find('all', array(
|
||||
'conditions' => array(
|
||||
'GalaxyElement.galaxy_cluster_id' => $cluster['GalaxyCluster']['id'],
|
||||
'GalaxyElement.key' => 'synonyms'
|
||||
),
|
||||
'recursive' => -1
|
||||
));
|
||||
$cluster['GalaxyCluster']['synonyms_string'] = array();
|
||||
foreach ($cluster['GalaxyElement'] as $element) {
|
||||
$cluster['GalaxyCluster']['synonyms_string'][] = $element['value'];
|
||||
if (isset($lookup_table[$cluster['GalaxyCluster']['type']][$element['value']])) {
|
||||
$lookup_table[$cluster['GalaxyCluster']['type']][$element['value']][] = $cluster['GalaxyCluster']['id'];
|
||||
} else {
|
||||
$lookup_table[$cluster['GalaxyCluster']['type']][$element['value']] = array($cluster['GalaxyCluster']['id']);
|
||||
}
|
||||
foreach ($temp as $element) {
|
||||
$cluster['GalaxyCluster']['synonyms_string'][] = $element['GalaxyElement']['value'];
|
||||
$cluster['GalaxyElement'][] = $element['GalaxyElement'];
|
||||
}
|
||||
unset($temp);
|
||||
$cluster['GalaxyCluster']['synonyms_string'] = implode(', ', $cluster['GalaxyCluster']['synonyms_string']);
|
||||
unset($cluster['GalaxyElement']);
|
||||
$clusters[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']] = $cluster['GalaxyCluster'];
|
||||
if (isset($lookup_table[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']])) {
|
||||
$lookup_table[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']][] = $cluster['GalaxyCluster']['id'];
|
||||
} else {
|
||||
$lookup_table[$cluster['GalaxyCluster']['type']][$cluster['GalaxyCluster']['value']] = array($cluster['GalaxyCluster']['id']);
|
||||
}
|
||||
}
|
||||
ksort($clusters);
|
||||
$this->set('clusters', $clusters);
|
||||
$this->set('target_id', $target_id);
|
||||
$this->set('target_type', $target_type);
|
||||
$this->set('lookup_table', $lookup_table);
|
||||
$this->render('ajax/cluster_choice');
|
||||
|
||||
$items = array();
|
||||
foreach ($clusters as $namespace => $cluster_data) {
|
||||
foreach ($cluster_data as $k => $cluster) {
|
||||
$name = $cluster['value'];
|
||||
$optionName = $cluster['value'];
|
||||
if ($cluster['synonyms_string'] !== '') {
|
||||
$synom = __('Synonyms: ') . $cluster['synonyms_string'];
|
||||
$optionName .= $cluster['synonyms_string'] !== '' ? ' (' . $cluster['synonyms_string'] . ')' : '';
|
||||
} else {
|
||||
$synom = '';
|
||||
}
|
||||
$itemParam = array(
|
||||
'name' => $optionName,
|
||||
'value' => $cluster['id'],
|
||||
'template' => array(
|
||||
'name' => $name,
|
||||
'infoExtra' => $cluster['description'],
|
||||
)
|
||||
);
|
||||
if ($cluster['synonyms_string'] !== '') {
|
||||
$itemParam['template']['infoContextual'] = $synom;
|
||||
}
|
||||
$items[] = $itemParam;
|
||||
unset($cluster_data[$k]);
|
||||
}
|
||||
}
|
||||
$onClickForm = 'quickSubmitGalaxyForm';
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($items, $this->response->type());
|
||||
} else {
|
||||
$this->set('items', $items);
|
||||
$this->set('options', array( // set chosen (select picker) options
|
||||
'functionName' => $onClickForm,
|
||||
'multiple' => '-1',
|
||||
'select_options' => array(
|
||||
'additionalData' => array(
|
||||
'target_id' => $target_id,
|
||||
'target_type' => $target_type,
|
||||
)
|
||||
),
|
||||
));
|
||||
$this->render('ajax/cluster_choice');
|
||||
}
|
||||
}
|
||||
|
||||
public function attachCluster($target_id, $target_type = 'event')
|
||||
{
|
||||
$cluster_id = $this->request->data['Galaxy']['target_id'];
|
||||
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id);
|
||||
$this->Flash->info($result);
|
||||
$this->redirect($this->referer());
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result, 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
|
||||
public function attachMultipleClusters($target_id, $target_type = 'event')
|
||||
{
|
||||
$cluster_ids = json_decode($this->request->data['Galaxy']['target_ids'], true);
|
||||
$result = "";
|
||||
foreach ($cluster_ids as $cluster_id) {
|
||||
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id);
|
||||
if ($target_id === 'selected') {
|
||||
$target_id_list = json_decode($this->request->data['Galaxy']['attribute_ids']);
|
||||
} else {
|
||||
$target_id_list = array($target_id);
|
||||
}
|
||||
$cluster_ids = $this->request->data['Galaxy']['target_ids'];
|
||||
if (!empty($cluster_ids)) {
|
||||
$cluster_ids = json_decode($cluster_ids, true);
|
||||
if ($cluster_ids === null) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'error' => __('Failed to parse request.'))), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'error' => __('No clusters picked.'))), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$result = "";
|
||||
if (!is_array($cluster_ids)) { // in case we only want to attach 1
|
||||
$cluster_ids = array($cluster_ids);
|
||||
}
|
||||
foreach ($cluster_ids as $cluster_id) {
|
||||
foreach ($target_id_list as $target_id) {
|
||||
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id);
|
||||
}
|
||||
}
|
||||
if ($this->request->is('ajax')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result, 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
|
||||
} else {
|
||||
$this->Flash->info($result);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
$this->Flash->info($result);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
public function viewGraph($id)
|
||||
|
@ -204,4 +285,34 @@ class GalaxiesController extends AppController
|
|||
$this->set('galaxy_id', $cluster['Galaxy']['id']);
|
||||
$this->render('/Events/view_graph');
|
||||
}
|
||||
|
||||
public function showGalaxies($id, $scope = 'event')
|
||||
{
|
||||
$this->layout = 'ajax';
|
||||
$this->set('scope', $scope);
|
||||
if ($scope == 'event') {
|
||||
$this->loadModel('Event');
|
||||
$object = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id, 'metadata' => 1));
|
||||
if (empty($object)) {
|
||||
throw new MethodNotAllowedException('Invalid event.');
|
||||
}
|
||||
$this->set('object', $object[0]);
|
||||
|
||||
} elseif ($scope == 'attribute') {
|
||||
$this->loadModel('Attribute');
|
||||
$object = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id), 'flatten' => 1));
|
||||
if (empty($object)) {
|
||||
throw new MethodNotAllowedException('Invalid attribute.');
|
||||
}
|
||||
$object[0] = $this->Attribute->Event->massageTags($object[0], 'Attribute');
|
||||
} elseif ($scope == 'tag_collection') {
|
||||
$this->loadModel('TagCollection');
|
||||
$object = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $id)));
|
||||
if (empty($object)) {
|
||||
throw new MethodNotAllowedException('Invalid Tag Collection.');
|
||||
}
|
||||
}
|
||||
$this->set('object', $object[0]);
|
||||
$this->render('/Events/ajax/ajaxGalaxies');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class GalaxyClustersController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'recursive' => -1,
|
||||
'order' => array(
|
||||
'GalaxyCluster.value' => 'ASC'
|
||||
|
@ -115,14 +115,14 @@ class GalaxyClustersController extends AppController
|
|||
|
||||
public function view($id)
|
||||
{
|
||||
$conditions = array('GalaxyCluster.id' => $id);
|
||||
if (Validation::uuid($id)) {
|
||||
$conditions = array('GalaxyCluster.uuid' => $id);
|
||||
}
|
||||
$contain = array('Galaxy');
|
||||
if ($this->_isRest()) {
|
||||
$contain[] = 'GalaxyElement';
|
||||
}
|
||||
$conditions = array('GalaxyCluster.id' => $id);
|
||||
if (Validation::uuid($id)) {
|
||||
$conditions = array('GalaxyCluster.uuid' => $id);
|
||||
}
|
||||
$contain = array('Galaxy');
|
||||
if ($this->_isRest()) {
|
||||
$contain[] = 'GalaxyElement';
|
||||
}
|
||||
$cluster = $this->GalaxyCluster->find('first', array(
|
||||
'recursive' => -1,
|
||||
'contain' => $contain,
|
||||
|
@ -143,16 +143,18 @@ class GalaxyClustersController extends AppController
|
|||
$cluster['GalaxyCluster']['tag_count'] = count($tag['EventTag']);
|
||||
$cluster['GalaxyCluster']['tag_id'] = $tag['Tag']['id'];
|
||||
}
|
||||
} else {
|
||||
throw new NotFoundException('Cluster not found.');
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$cluster['GalaxyCluster']['Galaxy'] = $cluster['Galaxy'];
|
||||
$cluster['GalaxyCluster']['GalaxyElement'] = $cluster['GalaxyElement'];
|
||||
return $this->RestResponse->viewData(array('GalaxyCluster' => $cluster['GalaxyCluster']), $this->response->type());
|
||||
} else {
|
||||
$this->set('id', $id);
|
||||
$this->set('galaxy_id', $cluster['Galaxy']['id']);
|
||||
$this->set('cluster', $cluster);
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$cluster['GalaxyCluster']['Galaxy'] = $cluster['Galaxy'];
|
||||
$cluster['GalaxyCluster']['GalaxyElement'] = $cluster['GalaxyElement'];
|
||||
return $this->RestResponse->viewData(array('GalaxyCluster' => $cluster['GalaxyCluster']), $this->response->type());
|
||||
} else {
|
||||
$this->set('id', $id);
|
||||
$this->set('galaxy_id', $cluster['Galaxy']['id']);
|
||||
$this->set('cluster', $cluster);
|
||||
}
|
||||
}
|
||||
|
||||
public function attachToEvent($event_id, $tag_name)
|
||||
|
@ -222,20 +224,40 @@ class GalaxyClustersController extends AppController
|
|||
$event_id = $attribute['Attribute']['event_id'];
|
||||
} elseif ($target_type == 'event') {
|
||||
$event_id = $target_id;
|
||||
} elseif ($target_type === 'tag_collection') {
|
||||
// pass
|
||||
} else {
|
||||
throw new MethodNotAllowedException('Invalid options');
|
||||
}
|
||||
$this->Event->id = $event_id;
|
||||
$this->Event->recursive = -1;
|
||||
$event = $this->Event->read(array(), $event_id);
|
||||
if (empty($event)) {
|
||||
throw new MethodNotAllowedException('Invalid Event.');
|
||||
}
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
|
||||
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
|
||||
|
||||
if ($target_type === 'tag_collection') {
|
||||
$tag_collection = $this->GalaxyCluster->Tag->TagCollectionTag->TagCollection->fetchTagCollection($this->Auth->user(), array(
|
||||
'conditions' => array('TagCollection.id' => $target_id),
|
||||
'contain' => array('Organisation', 'TagCollectionTag' => array('Tag'))
|
||||
));
|
||||
if (empty($tag_collection)) {
|
||||
throw new MethodNotAllowedException('Invalid Tag Collection');
|
||||
}
|
||||
$tag_collection = $tag_collection[0];
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if (!$this->userRole['perm_tag_editor'] || $this->Auth->user('org_id') !== $tag_collection['TagCollection']['org_id']) {
|
||||
throw new MethodNotAllowedException('Invalid Tag Collection');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Event->id = $event_id;
|
||||
$this->Event->recursive = -1;
|
||||
$event = $this->Event->read(array(), $event_id);
|
||||
if (empty($event)) {
|
||||
throw new MethodNotAllowedException('Invalid Event.');
|
||||
}
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
|
||||
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
|
||||
throw new MethodNotAllowedException('Invalid Event.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($target_type == 'attribute') {
|
||||
$existingTargetTag = $this->Event->Attribute->AttributeTag->find('first', array(
|
||||
'conditions' => array('AttributeTag.tag_id' => $tag_id, 'AttributeTag.attribute_id' => $target_id),
|
||||
|
@ -248,6 +270,12 @@ class GalaxyClustersController extends AppController
|
|||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
} elseif ($target_type == 'tag_collection') {
|
||||
$existingTargetTag = $this->GalaxyCluster->Tag->TagCollectionTag->find('first', array(
|
||||
'conditions' => array('TagCollectionTag.tag_id' => $tag_id, 'TagCollectionTag.tag_collection_id' => $target_id),
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag')
|
||||
));
|
||||
}
|
||||
|
||||
if (empty($existingTargetTag)) {
|
||||
|
@ -261,6 +289,8 @@ class GalaxyClustersController extends AppController
|
|||
$result = $this->Event->EventTag->delete($existingTargetTag['EventTag']['id']);
|
||||
} elseif ($target_type == 'attribute') {
|
||||
$result = $this->Event->Attribute->AttributeTag->delete($existingTargetTag['AttributeTag']['id']);
|
||||
} elseif ($target_type == 'tag_collection') {
|
||||
$result = $this->GalaxyCluster->Tag->TagCollectionTag->delete($existingTargetTag['TagCollectionTag']['id']);
|
||||
}
|
||||
if ($result) {
|
||||
$event['Event']['published'] = 0;
|
||||
|
@ -286,43 +316,44 @@ class GalaxyClustersController extends AppController
|
|||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
public function delete($id) {
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$result = false;
|
||||
$galaxy_cluster = $this->GalaxyCluster->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('GalaxyCluster.id' => $id)
|
||||
));
|
||||
if (!empty($galaxy_cluster)) {
|
||||
$result = $this->GalaxyCluster->delete($id, true);
|
||||
$galaxy_id = $galaxy_cluster['GalaxyCluster']['galaxy_id'];
|
||||
}
|
||||
if ($result) {
|
||||
$message = 'Galaxy cluster successfuly deleted.';
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('GalaxyCluster', 'delete', $id, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(array('controller' => 'galaxies', 'action' => 'view', $galaxy_id));
|
||||
}
|
||||
} else {
|
||||
$message = 'Galaxy cluster could not be deleted.';
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('GalaxyCluster', 'delete', $id, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
$this->redirect(array('controller' => 'taxonomies', 'action' => 'index'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->request->is('ajax')) {
|
||||
$this->set('id', $id);
|
||||
$this->render('ajax/galaxy_cluster_delete_confirmation');
|
||||
} else {
|
||||
throw new MethodNotAllowedException('This function can only be reached via AJAX.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public function delete($id)
|
||||
{
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$result = false;
|
||||
$galaxy_cluster = $this->GalaxyCluster->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('GalaxyCluster.id' => $id)
|
||||
));
|
||||
if (!empty($galaxy_cluster)) {
|
||||
$result = $this->GalaxyCluster->delete($id, true);
|
||||
$galaxy_id = $galaxy_cluster['GalaxyCluster']['galaxy_id'];
|
||||
}
|
||||
if ($result) {
|
||||
$message = 'Galaxy cluster successfuly deleted.';
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('GalaxyCluster', 'delete', $id, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(array('controller' => 'galaxies', 'action' => 'view', $galaxy_id));
|
||||
}
|
||||
} else {
|
||||
$message = 'Galaxy cluster could not be deleted.';
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('GalaxyCluster', 'delete', $id, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
$this->redirect(array('controller' => 'taxonomies', 'action' => 'index'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->request->is('ajax')) {
|
||||
$this->set('id', $id);
|
||||
$this->render('ajax/galaxy_cluster_delete_confirmation');
|
||||
} else {
|
||||
throw new MethodNotAllowedException('This function can only be reached via AJAX.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class GalaxyElementsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 20,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'recursive' => -1,
|
||||
'order' => array(
|
||||
'GalaxyElement.key' => 'ASC'
|
||||
|
|
|
@ -29,98 +29,120 @@ class LogsController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
private function __resolveSpecial($data, $type, $fields) {
|
||||
if (!is_array($data)) {
|
||||
$data = array($data);
|
||||
}
|
||||
foreach ($data as $k => $element) {
|
||||
if (!is_numeric($data)) {
|
||||
$this->loadModel($type);
|
||||
$params = array(
|
||||
'conditions' => array(),
|
||||
'recursive' => -1,
|
||||
'fields' => array($type . '.id')
|
||||
);
|
||||
foreach ($fields as $field) {
|
||||
$params['conditions']['OR'][$type . '.' . $field] = $element;
|
||||
}
|
||||
$records = $this->$type->find('all', $params);
|
||||
if (empty($records)) {
|
||||
$data[$k] = -1;
|
||||
} else {
|
||||
$temp = array();
|
||||
foreach ($records as $record) {
|
||||
$temp[] = $record[$type]['id'];
|
||||
}
|
||||
$data = array_merge($data, $temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
private function __resolveSpecial($data, $type, $fields)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
$data = array($data);
|
||||
}
|
||||
foreach ($data as $k => $element) {
|
||||
if (!is_numeric($data)) {
|
||||
$this->loadModel($type);
|
||||
$params = array(
|
||||
'conditions' => array(),
|
||||
'recursive' => -1,
|
||||
'fields' => array($type . '.id')
|
||||
);
|
||||
foreach ($fields as $field) {
|
||||
$params['conditions']['OR'][$type . '.' . $field] = $element;
|
||||
}
|
||||
$records = $this->$type->find('all', $params);
|
||||
if (empty($records)) {
|
||||
$data[$k] = -1;
|
||||
} else {
|
||||
$temp = array();
|
||||
foreach ($records as $record) {
|
||||
$temp[] = $record[$type]['id'];
|
||||
}
|
||||
$data = array_merge($data, $temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function admin_index()
|
||||
{
|
||||
if ($this->_isRest()) {
|
||||
$paramArray = array('id', 'title', 'created', 'model', 'model_id', 'action', 'user_id', 'change', 'email', 'org', 'description', 'ip');
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
'paramArray' => $paramArray,
|
||||
'ordered_url_params' => compact($paramArray)
|
||||
);
|
||||
$exception = false;
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
unset($filterData);
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
}
|
||||
$conditions = array();
|
||||
foreach ($filters as $filter => $data) {
|
||||
$data = array('OR' => $data);
|
||||
$conditions = $this->Log->generic_add_filter($conditions, $data, 'Log.' . $filter);
|
||||
}
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$orgRestriction = $this->Auth->user('Organisation')['name'];
|
||||
$conditions['AND']['Log.org'] = $orgRestriction;
|
||||
}
|
||||
$params = array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1
|
||||
);
|
||||
if (isset($filters['limit'])) {
|
||||
$params['limit'] = $filters['limit'];
|
||||
}
|
||||
if (isset($filters['page'])) {
|
||||
$params['page'] = $filters['page'];
|
||||
}
|
||||
$log_entries = $this->Log->find('all', $params);
|
||||
return $this->RestResponse->viewData($log_entries, 'json');
|
||||
} else {
|
||||
if (!$this->userRole['perm_audit']) {
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index', 'admin' => false));
|
||||
}
|
||||
$this->set('isSearch', 0);
|
||||
$this->recursive = 0;
|
||||
$validFilters = $this->Log->logMeta;
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$orgRestriction = $this->Auth->user('Organisation')['name'];
|
||||
$conditions['Log.org'] = $orgRestriction;
|
||||
$this->paginate = array(
|
||||
'limit' => 60,
|
||||
'conditions' => $conditions,
|
||||
'order' => array('Log.id' => 'DESC')
|
||||
);
|
||||
} else {
|
||||
$validFilters = array_merge_recursive($validFilters, $this->Log->logMetaAdmin);
|
||||
}
|
||||
if (isset($this->params['named']['filter']) && in_array($this->params['named']['filter'], array_keys($validFilters))) {
|
||||
$this->paginate['conditions']['Log.action'] = $validFilters[$this->params['named']['filter']]['values'];
|
||||
}
|
||||
$this->set('validFilters', $validFilters);
|
||||
$this->set('filter', isset($this->params['named']['filter']) ? $this->params['named']['filter'] : false);
|
||||
$this->set('list', $this->paginate());
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$paramArray = array('id', 'title', 'created', 'model', 'model_id', 'action', 'user_id', 'change', 'email', 'org', 'description', 'ip');
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
'paramArray' => $paramArray,
|
||||
'ordered_url_params' => compact($paramArray)
|
||||
);
|
||||
$exception = false;
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
unset($filterData);
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
}
|
||||
$conditions = array();
|
||||
foreach ($filters as $filter => $data) {
|
||||
if ($filter === 'created') {
|
||||
$tempData = $data;
|
||||
if (!is_array($data)) {
|
||||
$tempData = array($data);
|
||||
}
|
||||
foreach ($tempData as $k => $v) {
|
||||
$tempData[$k] = $this->Log->resolveTimeDelta($v);
|
||||
}
|
||||
if (count($tempData) == 1) {
|
||||
$conditions['AND']['created >='] = date("Y-m-d H:i:s", $tempData[0]);
|
||||
} else {
|
||||
if ($tempData[0] < $tempData[1]) {
|
||||
$temp = $tempData[1];
|
||||
$tempData[1] = $tempData[0];
|
||||
$tempData[0] = $temp;
|
||||
}
|
||||
$conditions['AND'][] = array('created <= ' => date("Y-m-d H:i:s", $tempData[0]));
|
||||
$conditions['AND'][] = array('created >= ' => date("Y-m-d H:i:s", $tempData[1]));
|
||||
}
|
||||
} else {
|
||||
$data = array('OR' => $data);
|
||||
$conditions = $this->Log->generic_add_filter($conditions, $data, 'Log.' . $filter);
|
||||
}
|
||||
}
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$orgRestriction = $this->Auth->user('Organisation')['name'];
|
||||
$conditions['AND']['Log.org'] = $orgRestriction;
|
||||
}
|
||||
$params = array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1
|
||||
);
|
||||
if (isset($filters['limit'])) {
|
||||
$params['limit'] = $filters['limit'];
|
||||
}
|
||||
if (isset($filters['page'])) {
|
||||
$params['page'] = $filters['page'];
|
||||
}
|
||||
$log_entries = $this->Log->find('all', $params);
|
||||
return $this->RestResponse->viewData($log_entries, 'json');
|
||||
} else {
|
||||
if (!$this->userRole['perm_audit']) {
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index', 'admin' => false));
|
||||
}
|
||||
$this->set('isSearch', 0);
|
||||
$this->recursive = 0;
|
||||
$validFilters = $this->Log->logMeta;
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$orgRestriction = $this->Auth->user('Organisation')['name'];
|
||||
$conditions['Log.org'] = $orgRestriction;
|
||||
$this->paginate = array(
|
||||
'limit' => 60,
|
||||
'conditions' => $conditions,
|
||||
'order' => array('Log.id' => 'DESC')
|
||||
);
|
||||
} else {
|
||||
$validFilters = array_merge_recursive($validFilters, $this->Log->logMetaAdmin);
|
||||
}
|
||||
if (isset($this->params['named']['filter']) && in_array($this->params['named']['filter'], array_keys($validFilters))) {
|
||||
$this->paginate['conditions']['Log.action'] = $validFilters[$this->params['named']['filter']]['values'];
|
||||
}
|
||||
$this->set('validFilters', $validFilters);
|
||||
$this->set('filter', isset($this->params['named']['filter']) ? $this->params['named']['filter'] : false);
|
||||
$this->set('list', $this->paginate());
|
||||
}
|
||||
}
|
||||
|
||||
// Shows a minimalistic history for the currently selected event
|
||||
|
|
|
@ -7,7 +7,7 @@ class NewsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 5,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'News.id' => 'DESC'
|
||||
),
|
||||
|
@ -31,10 +31,10 @@ class NewsController extends AppController
|
|||
}
|
||||
}
|
||||
$this->User->id = $this->Auth->user('id');
|
||||
//if ($this->User->exists()) {
|
||||
$this->User->saveField('newsread', time());
|
||||
$this->set('newsItems', $newsItems);
|
||||
//}
|
||||
//if ($this->User->exists()) {
|
||||
$this->User->saveField('newsread', time());
|
||||
$this->set('newsItems', $newsItems);
|
||||
//}
|
||||
}
|
||||
|
||||
public function add()
|
||||
|
|
|
@ -162,6 +162,7 @@ class ObjectReferencesController extends AppController
|
|||
$relationships[$v['ObjectRelationship']['name']] = $v['ObjectRelationship']['name'];
|
||||
}
|
||||
$relationships['custom'] = 'custom';
|
||||
ksort($relationships);
|
||||
$this->set('relationships', $relationships);
|
||||
$this->set('event', $event);
|
||||
$this->set('objectId', $objectId);
|
||||
|
|
|
@ -17,36 +17,91 @@ class ObjectTemplatesController extends AppController
|
|||
'recursive' => -1
|
||||
);
|
||||
|
||||
public function objectChoice($event_id)
|
||||
{
|
||||
$this->ObjectTemplate->populateIfEmpty($this->Auth->user());
|
||||
$templates_raw = $this->ObjectTemplate->find('all', array(
|
||||
public function objectMetaChoice($event_id) {
|
||||
$metas = $this->ObjectTemplate->find('list', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('ObjectTemplate.active' => 1),
|
||||
'fields' => array('meta-category', 'meta-category'),
|
||||
'group' => array('ObjectTemplate.meta-category'),
|
||||
'order' => array('ObjectTemplate.meta-category asc')
|
||||
));
|
||||
|
||||
$items = array();
|
||||
$items[] = array(
|
||||
'name' => __('All Objects'),
|
||||
'value' => "/ObjectTemplates/objectChoice/" . h($event_id) . "/" . "0"
|
||||
);
|
||||
foreach($metas as $meta) {
|
||||
$items[] = array(
|
||||
'name' => $meta,
|
||||
'value' => "/ObjectTemplates/objectChoice/" . h($event_id) . "/" . h($meta)
|
||||
);
|
||||
}
|
||||
|
||||
$this->set('items', $items);
|
||||
$this->set('options', array(
|
||||
'multiple' => 0,
|
||||
));
|
||||
$this->render('/Elements/generic_picker');
|
||||
}
|
||||
|
||||
public function objectChoice($event_id, $category=false)
|
||||
{
|
||||
$this->ObjectTemplate->populateIfEmpty($this->Auth->user());
|
||||
$conditions = array('ObjectTemplate.active' => 1);
|
||||
if ($category !== false && $category !== "0") {
|
||||
$conditions['meta-category'] = $category;
|
||||
}
|
||||
$templates_raw = $this->ObjectTemplate->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions,
|
||||
'fields' => array('id', 'meta-category', 'name', 'description', 'org_id'),
|
||||
'contain' => array('Organisation.name'),
|
||||
'sort' => array('ObjectTemplate.name asc')
|
||||
'order' => array('ObjectTemplate.name asc')
|
||||
));
|
||||
$templates = array('all' => array());
|
||||
foreach ($templates_raw as $k => $template) {
|
||||
unset($template['ObjectTemplate']['meta-category']);
|
||||
$template['ObjectTemplate']['org_name'] = $template['Organisation']['name'];
|
||||
$templates[$templates_raw[$k]['ObjectTemplate']['meta-category']][] = $template['ObjectTemplate'];
|
||||
$templates['all'][] = $template['ObjectTemplate'];
|
||||
|
||||
$items = array();
|
||||
foreach($templates_raw as $template) {
|
||||
$template = $template['ObjectTemplate'];
|
||||
$items[] = array(
|
||||
'name' => $template['name'],
|
||||
'value' => $template['id'],
|
||||
'template' => array(
|
||||
'name' => $template['name'],
|
||||
'infoExtra' => $template['description'],
|
||||
'infoContextual' => $template['meta-category']
|
||||
)
|
||||
);
|
||||
}
|
||||
foreach ($templates as $category => $template_list) {
|
||||
$templates[$category] = Hash::sort($templates[$category], '{n}.name');
|
||||
}
|
||||
$template_categories = array_keys($templates);
|
||||
$this->layout = false;
|
||||
$this->set('template_categories', $template_categories);
|
||||
$this->set('eventId', $event_id);
|
||||
$this->set('templates', $templates);
|
||||
$this->render('ajax/object_choice');
|
||||
|
||||
$fun = 'redirectAddObject';
|
||||
$this->set('items', $items);
|
||||
$this->set('options', array(
|
||||
'functionName' => $fun,
|
||||
'multiple' => 0,
|
||||
'select_options' => array(
|
||||
'additionalData' => array('event_id' => $event_id),
|
||||
),
|
||||
));
|
||||
$this->render('/Elements/generic_picker');
|
||||
}
|
||||
|
||||
public function view($id)
|
||||
{
|
||||
if (Validation::uuid($id)) {
|
||||
$temp = $this->ObjectTemplate->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('ObjectTemplate.uuid' => $id),
|
||||
'fields' => array('ObjectTemplate.id', 'ObjectTemplate.uuid'),
|
||||
'order' => array('ObjectTemplate.version desc')
|
||||
));
|
||||
if (empty($temp)) {
|
||||
throw new NotFoundException(__('Invalid object template'));
|
||||
}
|
||||
$id = $temp['ObjectTemplate']['id'];
|
||||
} elseif (!is_numeric($id)) {
|
||||
throw new NotFoundException(__('Invalid object template id.'));
|
||||
}
|
||||
$params = array(
|
||||
'recursive' => -1,
|
||||
'contain' => array(
|
||||
|
|
|
@ -42,7 +42,7 @@ class ObjectsController extends AppController
|
|||
)
|
||||
));
|
||||
$event = $this->MispObject->Event->find('first', $eventFindParams);
|
||||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
$sharing_groups = array();
|
||||
|
@ -140,7 +140,7 @@ class ObjectsController extends AppController
|
|||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
$event = $this->MispObject->Event->find('first', $eventFindParams);
|
||||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
throw new NotFoundException(__('Invalid event.'));
|
||||
}
|
||||
$eventId = $event['Event']['id'];
|
||||
|
@ -194,6 +194,7 @@ class ObjectsController extends AppController
|
|||
$error = 'Could not save the object as no attributes were set.';
|
||||
} else {
|
||||
foreach ($object['Attribute'] as $k => $attribute) {
|
||||
unset($object['Attribute'][$k]['id']);
|
||||
$object['Attribute'][$k]['event_id'] = $eventId;
|
||||
$this->MispObject->Event->Attribute->set($attribute);
|
||||
if (!$this->MispObject->Event->Attribute->validates()) {
|
||||
|
@ -220,6 +221,7 @@ class ObjectsController extends AppController
|
|||
$error = $this->MispObject->ObjectTemplate->checkTemplateConformity($template, $object);
|
||||
}
|
||||
if ($error === true) {
|
||||
unset($object['Object']['id']);
|
||||
$result = $this->MispObject->saveObject($object, $eventId, $template, $this->Auth->user(), $errorBehaviour = 'halt');
|
||||
if (is_numeric($result)) {
|
||||
$this->MispObject->Event->unpublishEvent($eventId);
|
||||
|
@ -234,6 +236,10 @@ class ObjectsController extends AppController
|
|||
'conditions' => array('Object.id' => $result),
|
||||
'contain' => array('Attribute')
|
||||
));
|
||||
if (!empty($object)) {
|
||||
$object['Object']['Attribute'] = $object['Attribute'];
|
||||
unset($object['Attribute']);
|
||||
}
|
||||
return $this->RestResponse->viewData($object, $this->response->type());
|
||||
} else {
|
||||
return $this->RestResponse->saveFailResponse('Objects', 'add', false, $error, $this->response->type());
|
||||
|
@ -324,7 +330,7 @@ class ObjectsController extends AppController
|
|||
);
|
||||
|
||||
$event = $this->MispObject->Event->find('first', $eventFindParams);
|
||||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
|
||||
throw new NotFoundException(__('Invalid object.'));
|
||||
}
|
||||
if (!$this->_isRest()) {
|
||||
|
@ -370,6 +376,10 @@ class ObjectsController extends AppController
|
|||
'conditions' => array('Object.id' => $id),
|
||||
'contain' => array('Attribute')
|
||||
));
|
||||
if (!empty($objectToSave)) {
|
||||
$objectToSave['Object']['Attribute'] = $objectToSave['Attribute'];
|
||||
unset($objectToSave['Attribute']);
|
||||
}
|
||||
$this->MispObject->Event->unpublishEvent($object['Object']['event_id']);
|
||||
return $this->RestResponse->viewData($objectToSave, $this->response->type());
|
||||
} else {
|
||||
|
|
|
@ -19,7 +19,7 @@ class OrgBlacklistsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'OrgBlacklist.created' => 'DESC'
|
||||
),
|
||||
|
|
|
@ -15,10 +15,10 @@ class OrganisationsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => 'LOWER(Organisation.name)'
|
||||
//'order' => array(
|
||||
// 'Organisation.name' => 'ASC'
|
||||
// 'Organisation.name' => 'ASC'
|
||||
//),
|
||||
);
|
||||
|
||||
|
@ -171,8 +171,8 @@ class OrganisationsController extends AppController
|
|||
} else {
|
||||
$temp['Organisation'][$field] = $existingOrg['Organisation'][$field];
|
||||
}
|
||||
$this->request->data = $temp;
|
||||
}
|
||||
$this->request->data = $temp;
|
||||
}
|
||||
$this->request->data['Organisation']['id'] = $id;
|
||||
if ($this->Organisation->save($this->request->data)) {
|
||||
|
|
|
@ -4,7 +4,7 @@ App::uses('Xml', 'Utility');
|
|||
|
||||
class ServersController extends AppController
|
||||
{
|
||||
public $components = array('Security' ,'RequestHandler'); // XXX ACL component
|
||||
public $components = array('Security' ,'RequestHandler'); // XXX ACL component
|
||||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
|
@ -31,7 +31,7 @@ class ServersController extends AppController
|
|||
public function beforeFilter()
|
||||
{
|
||||
parent::beforeFilter();
|
||||
$this->Security->unlockedActions[] = 'getApiInfo';
|
||||
$this->Security->unlockedActions[] = 'getApiInfo';
|
||||
// permit reuse of CSRF tokens on some pages.
|
||||
switch ($this->request->params['action']) {
|
||||
case 'push':
|
||||
|
@ -51,27 +51,37 @@ class ServersController extends AppController
|
|||
$this->paginate['conditions'] = array('Server.org_id LIKE' => $this->Auth->user('org_id'));
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$params = array(
|
||||
'recursive' => -1,
|
||||
'contain' => array(
|
||||
'Organisation' => array('Organisation.id', 'Organisation.name', 'Organisation.uuid', 'Organisation.nationality', 'Organisation.sector', 'Organisation.type'),
|
||||
'RemoteOrg' => array('RemoteOrg.id', 'RemoteOrg.name', 'RemoteOrg.uuid', 'RemoteOrg.nationality', 'RemoteOrg.sector', 'RemoteOrg.type'),
|
||||
)
|
||||
);
|
||||
$servers = $this->Server->find('all', $params);
|
||||
return $this->RestResponse->viewData($servers, $this->response->type());
|
||||
} else {
|
||||
$this->set('servers', $this->paginate());
|
||||
$collection = array();
|
||||
$collection['orgs'] = $this->Server->Organisation->find('list', array(
|
||||
'fields' => array('id', 'name'),
|
||||
));
|
||||
$this->loadModel('Tag');
|
||||
$collection['tags'] = $this->Tag->find('list', array(
|
||||
'fields' => array('id', 'name'),
|
||||
));
|
||||
$this->set('collection', $collection);
|
||||
}
|
||||
$params = array(
|
||||
'recursive' => -1,
|
||||
'contain' => array(
|
||||
'User' => array(
|
||||
'fields' => array('User.id', 'User.org_id', 'User.email'),
|
||||
),
|
||||
'Organisation' => array(
|
||||
'fields' => array('Organisation.id', 'Organisation.name', 'Organisation.uuid', 'Organisation.nationality', 'Organisation.sector', 'Organisation.type'),
|
||||
),
|
||||
'RemoteOrg' => array(
|
||||
'fields' => array('RemoteOrg.id', 'RemoteOrg.name', 'RemoteOrg.uuid', 'RemoteOrg.nationality', 'RemoteOrg.sector', 'RemoteOrg.type'),
|
||||
),
|
||||
),
|
||||
);
|
||||
$servers = $this->Server->find('all', $params);
|
||||
$servers = $this->Server->attachServerCacheTimestamps($servers);
|
||||
return $this->RestResponse->viewData($servers, $this->response->type());
|
||||
} else {
|
||||
$servers = $this->paginate();
|
||||
$servers = $this->Server->attachServerCacheTimestamps($servers);
|
||||
$this->set('servers', $servers);
|
||||
$collection = array();
|
||||
$collection['orgs'] = $this->Server->Organisation->find('list', array(
|
||||
'fields' => array('id', 'name'),
|
||||
));
|
||||
$this->loadModel('Tag');
|
||||
$collection['tags'] = $this->Tag->find('list', array(
|
||||
'fields' => array('id', 'name'),
|
||||
));
|
||||
$this->set('collection', $collection);
|
||||
}
|
||||
}
|
||||
|
||||
public function previewIndex($id)
|
||||
|
@ -236,6 +246,7 @@ class ServersController extends AppController
|
|||
$defaults = array(
|
||||
'push' => 0,
|
||||
'pull' => 0,
|
||||
'caching_enabled' => 0,
|
||||
'json' => '[]',
|
||||
'push_rules' => '[]',
|
||||
'pull_rules' => '[]',
|
||||
|
@ -422,7 +433,7 @@ class ServersController extends AppController
|
|||
}
|
||||
if (!$fail) {
|
||||
// say what fields are to be updated
|
||||
$fieldList = array('id', 'url', 'push', 'pull', 'unpublish_event', 'publish_without_email', 'remote_org_id', 'name' ,'self_signed', 'cert_file', 'client_cert_file', 'push_rules', 'pull_rules', 'internal', 'skip_proxy');
|
||||
$fieldList = array('id', 'url', 'push', 'pull', 'caching_enabled', 'unpublish_event', 'publish_without_email', 'remote_org_id', 'name' ,'self_signed', 'cert_file', 'client_cert_file', 'push_rules', 'pull_rules', 'internal', 'skip_proxy');
|
||||
$this->request->data['Server']['id'] = $id;
|
||||
if (isset($this->request->data['Server']['authkey']) && "" != $this->request->data['Server']['authkey']) {
|
||||
$fieldList[] = 'authkey';
|
||||
|
@ -563,6 +574,7 @@ class ServersController extends AppController
|
|||
}
|
||||
$this->set('allTags', $allTags);
|
||||
$this->set('server', $s);
|
||||
$this->set('id', $id);
|
||||
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
|
||||
}
|
||||
}
|
||||
|
@ -591,9 +603,9 @@ class ServersController extends AppController
|
|||
/**
|
||||
* Pull one or more events with attributes from a remote instance.
|
||||
* Set $technique to
|
||||
* full - download everything
|
||||
* incremental - only new events
|
||||
* <int> - specific id of the event to pull
|
||||
* full - download everything
|
||||
* incremental - only new events
|
||||
* <int> - specific id of the event to pull
|
||||
*/
|
||||
public function pull($id = null, $technique='full')
|
||||
{
|
||||
|
@ -602,66 +614,66 @@ class ServersController extends AppController
|
|||
throw new NotFoundException(__('Invalid server'));
|
||||
}
|
||||
$s = $this->Server->read(null, $id);
|
||||
$error = false;
|
||||
$error = false;
|
||||
if (!$this->_isSiteAdmin() && !($s['Server']['org_id'] == $this->Auth->user('org_id') && $this->_isAdmin())) {
|
||||
throw new MethodNotAllowedException(__('You are not authorised to do that.'));
|
||||
throw new MethodNotAllowedException(__('You are not authorised to do that.'));
|
||||
}
|
||||
$this->Server->id = $id;
|
||||
if (!$this->Server->exists()) {
|
||||
throw new NotFoundException(__('Invalid server'));
|
||||
}
|
||||
if (false == $this->Server->data['Server']['pull'] && ($technique == 'full' || $technique == 'incremental')) {
|
||||
$error = __('Pull setting not enabled for this server.');
|
||||
$error = __('Pull setting not enabled for this server.');
|
||||
}
|
||||
if (empty($error)) {
|
||||
if (!Configure::read('MISP.background_jobs')) {
|
||||
$result = $this->Server->pull($this->Auth->user(), $id, $technique, $s);
|
||||
if (is_array($result)) {
|
||||
$success = sprintf(__('Pull completed. %s events pulled, %s events could not be pulled, %s proposals pulled.', count($result[0]), count($result[1]), count($result[2])));
|
||||
} else {
|
||||
$error = $result;
|
||||
}
|
||||
$this->set('successes', $result[0]);
|
||||
$this->set('fails', $result[1]);
|
||||
$this->set('pulledProposals', $result[2]);
|
||||
} else {
|
||||
$this->loadModel('Job');
|
||||
$this->Job->create();
|
||||
$data = array(
|
||||
'worker' => 'default',
|
||||
'job_type' => 'pull',
|
||||
'job_input' => 'Server: ' . $id,
|
||||
'status' => 0,
|
||||
'retries' => 0,
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'message' => 'Pulling.',
|
||||
);
|
||||
$this->Job->save($data);
|
||||
$jobId = $this->Job->id;
|
||||
$process_id = CakeResque::enqueue(
|
||||
'default',
|
||||
'ServerShell',
|
||||
array('pull', $this->Auth->user('id'), $id, $technique, $jobId)
|
||||
);
|
||||
$this->Job->saveField('process_id', $process_id);
|
||||
$success = sprintf(__('Pull queued for background execution. Job ID: %s'), $jobId);
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
if (!empty($error)) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'pull', false, $error, $this->response->type());
|
||||
} else {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'pull', $success, $this->response->type());
|
||||
}
|
||||
} else {
|
||||
if (!empty($error)) {
|
||||
$this->Flash->error($error);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
} else {
|
||||
$this->Flash->success($success);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
}
|
||||
if (empty($error)) {
|
||||
if (!Configure::read('MISP.background_jobs')) {
|
||||
$result = $this->Server->pull($this->Auth->user(), $id, $technique, $s);
|
||||
if (is_array($result)) {
|
||||
$success = sprintf(__('Pull completed. %s events pulled, %s events could not be pulled, %s proposals pulled.', count($result[0]), count($result[1]), count($result[2])));
|
||||
} else {
|
||||
$error = $result;
|
||||
}
|
||||
$this->set('successes', $result[0]);
|
||||
$this->set('fails', $result[1]);
|
||||
$this->set('pulledProposals', $result[2]);
|
||||
} else {
|
||||
$this->loadModel('Job');
|
||||
$this->Job->create();
|
||||
$data = array(
|
||||
'worker' => 'default',
|
||||
'job_type' => 'pull',
|
||||
'job_input' => 'Server: ' . $id,
|
||||
'status' => 0,
|
||||
'retries' => 0,
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'message' => 'Pulling.',
|
||||
);
|
||||
$this->Job->save($data);
|
||||
$jobId = $this->Job->id;
|
||||
$process_id = CakeResque::enqueue(
|
||||
'default',
|
||||
'ServerShell',
|
||||
array('pull', $this->Auth->user('id'), $id, $technique, $jobId)
|
||||
);
|
||||
$this->Job->saveField('process_id', $process_id);
|
||||
$success = sprintf(__('Pull queued for background execution. Job ID: %s'), $jobId);
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
if (!empty($error)) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'pull', false, $error, $this->response->type());
|
||||
} else {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'pull', $success, $this->response->type());
|
||||
}
|
||||
} else {
|
||||
if (!empty($error)) {
|
||||
$this->Flash->error($error);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
} else {
|
||||
$this->Flash->success($success);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function push($id = null, $technique=false)
|
||||
|
@ -681,24 +693,24 @@ class ServersController extends AppController
|
|||
$HttpSocket = $syncTool->setupHttpSocket($server);
|
||||
$result = $this->Server->push($id, $technique, false, $HttpSocket, $this->Auth->user());
|
||||
if ($result === false) {
|
||||
$error = __('The remote server is too outdated to initiate a push towards it. Please notify the hosting organisation of the remote instance.');
|
||||
} else if (!is_array($result)) {
|
||||
$error = $result;
|
||||
}
|
||||
if (!empty($error)) {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'push', false, $error, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->info($error);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'push', array(sprintf(__('Push complete. %s events pushed, %s events could not be pushed.', $result[0], $result[1]))), $this->response->type());
|
||||
} else {
|
||||
$this->set('successes', $result[0]);
|
||||
$this->set('fails', $result[1]);
|
||||
}
|
||||
$error = __('The remote server is too outdated to initiate a push towards it. Please notify the hosting organisation of the remote instance.');
|
||||
} elseif (!is_array($result)) {
|
||||
$error = $result;
|
||||
}
|
||||
if (!empty($error)) {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'push', false, $error, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->info($error);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'push', array(sprintf(__('Push complete. %s events pushed, %s events could not be pushed.', $result[0], $result[1]))), $this->response->type());
|
||||
} else {
|
||||
$this->set('successes', $result[0]);
|
||||
$this->set('fails', $result[1]);
|
||||
}
|
||||
} else {
|
||||
$this->loadModel('Job');
|
||||
$this->Job->create();
|
||||
|
@ -719,10 +731,10 @@ class ServersController extends AppController
|
|||
array('push', $this->Auth->user('id'), $id, $jobId)
|
||||
);
|
||||
$this->Job->saveField('process_id', $process_id);
|
||||
$message = sprintf(__('Push queued for background execution. Job ID: %s'), $jobId);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'push', $message, $this->response->type());
|
||||
}
|
||||
$message = sprintf(__('Push queued for background execution. Job ID: %s'), $jobId);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'push', $message, $this->response->type());
|
||||
}
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
@ -751,7 +763,7 @@ class ServersController extends AppController
|
|||
}
|
||||
$file = new File($server['Server'][$subm]['name']);
|
||||
$ext = $file->ext();
|
||||
if (($ext != 'pem') || !$server['Server'][$subm]['size'] > 0) {
|
||||
if (!$server['Server'][$subm]['size'] > 0) {
|
||||
$this->Flash->error('Incorrect extension or empty file.');
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
@ -821,6 +833,11 @@ class ServersController extends AppController
|
|||
return $this->Server->loadAvailableLanguages();
|
||||
}
|
||||
|
||||
private function __loadTagCollections()
|
||||
{
|
||||
return $this->Server->loadTagCollections($this->Auth->user());
|
||||
}
|
||||
|
||||
private function __loadLocalOrgs()
|
||||
{
|
||||
$this->loadModel('Organisation');
|
||||
|
@ -852,10 +869,11 @@ class ServersController extends AppController
|
|||
$zmqErrors = array(0 => 'OK', 1 => 'not enabled (so not tested)', 2 => 'Python ZeroMQ library not installed correctly.', 3 => 'ZeroMQ script not running.');
|
||||
$stixOperational = array(0 => 'Some of the libraries related to STIX are not installed. Make sure that all libraries listed below are correctly installed.', 1 => 'OK');
|
||||
$stixVersion = array(0 => 'Incorrect STIX version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$stix2Version = array(0 => 'Incorrect STIX2 version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$cyboxVersion = array(0 => 'Incorrect CyBox version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$mixboxVersion = array(0 => 'Incorrect mixbox version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$maecVersion = array(0 => 'Incorrect maec version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$pymispVersion = array(0 => 'Incorrect pymisp version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$pymispVersion = array(0 => 'Incorrect PyMISP version installed, found $current, expecting $expected', 1 => 'OK');
|
||||
$sessionErrors = array(0 => 'OK', 1 => 'High', 2 => 'Alternative setting used', 3 => 'Test failed');
|
||||
$moduleErrors = array(0 => 'OK', 1 => 'System not enabled', 2 => 'No modules found');
|
||||
|
||||
|
@ -975,7 +993,7 @@ class ServersController extends AppController
|
|||
}
|
||||
|
||||
// check if the STIX and Cybox libraries are working and the correct version using the test script stixtest.py
|
||||
$stix = $this->Server->stixDiagnostics($diagnostic_errors, $stixVersion, $cyboxVersion, $mixboxVersion, $maecVersion, $pymispVersion);
|
||||
$stix = $this->Server->stixDiagnostics($diagnostic_errors, $stixVersion, $cyboxVersion, $mixboxVersion, $maecVersion, $stix2Version, $pymispVersion);
|
||||
|
||||
// if GnuPG is set up in the settings, try to encrypt a test message
|
||||
$gpgStatus = $this->Server->gpgDiagnostics($diagnostic_errors);
|
||||
|
@ -996,7 +1014,7 @@ class ServersController extends AppController
|
|||
$sessionStatus = $this->Server->sessionDiagnostics($diagnostic_errors, $sessionCount);
|
||||
$this->set('sessionCount', $sessionCount);
|
||||
|
||||
$additionalViewVars = array('gpgStatus', 'sessionErrors', 'proxyStatus', 'sessionStatus', 'zmqStatus', 'stixVersion', 'cyboxVersion', 'mixboxVersion', 'maecVersion', 'pymispVersion', 'moduleStatus', 'gpgErrors', 'proxyErrors', 'zmqErrors', 'stixOperational', 'stix', 'moduleErrors', 'moduleTypes');
|
||||
$additionalViewVars = array('gpgStatus', 'sessionErrors', 'proxyStatus', 'sessionStatus', 'zmqStatus', 'stixVersion', 'cyboxVersion', 'mixboxVersion', 'maecVersion', 'stix2Version', 'pymispVersion', 'moduleStatus', 'gpgErrors', 'proxyErrors', 'zmqErrors', 'stixOperational', 'stix', 'moduleErrors', 'moduleTypes');
|
||||
}
|
||||
// check whether the files are writeable
|
||||
$writeableDirs = $this->Server->writeableDirsDiagnostics($diagnostic_errors);
|
||||
|
@ -1119,67 +1137,39 @@ class ServersController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
public function serverSettingsEdit($setting, $id = false, $forceSave = false)
|
||||
public function serverSettingsEdit($setting_name, $id = false, $forceSave = false)
|
||||
{
|
||||
// invalidate config.php from php opcode cache
|
||||
if (function_exists('opcache_reset')) {
|
||||
opcache_reset();
|
||||
}
|
||||
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
if (!isset($setting) || !isset($id)) {
|
||||
if (!isset($setting_name) || !isset($id)) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
$this->set('id', $id);
|
||||
if (strpos($setting, 'Plugin.Enrichment') !== false || strpos($setting, 'Plugin.Import') !== false || strpos($setting, 'Plugin.Export') !== false || strpos($setting, 'Plugin.Cortex') !== false) {
|
||||
$serverSettings = $this->Server->getCurrentServerSettings();
|
||||
} else {
|
||||
$serverSettings = $this->Server->serverSettings;
|
||||
}
|
||||
$relevantSettings = (array_intersect_key(Configure::read(), $serverSettings));
|
||||
$found = null;
|
||||
foreach ($serverSettings as $k => $s) {
|
||||
if (isset($s['branch'])) {
|
||||
foreach ($s as $ek => $es) {
|
||||
if ($ek != 'branch') {
|
||||
if ($setting == $k . '.' . $ek) {
|
||||
$found = $es;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($setting == $k) {
|
||||
$found = $s;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
$setting = $this->Server->getSettingData($setting_name);
|
||||
if ($this->request->is('get')) {
|
||||
if ($found != null) {
|
||||
$value = Configure::read($setting);
|
||||
if ($setting != null) {
|
||||
$value = Configure::read($setting['name']);
|
||||
if ($value) {
|
||||
$found['value'] = $value;
|
||||
$setting['value'] = $value;
|
||||
}
|
||||
$found['setting'] = $setting;
|
||||
$setting['setting'] = $setting['name'];
|
||||
}
|
||||
if (isset($found['optionsSource']) && !empty($found['optionsSource'])) {
|
||||
$found['options'] = $this->{'__load' . $found['optionsSource']}();
|
||||
if (isset($setting['optionsSource']) && !empty($setting['optionsSource'])) {
|
||||
$setting['options'] = $this->{'__load' . $setting['optionsSource']}();
|
||||
}
|
||||
$subGroup = 'general';
|
||||
$subGroup = explode('.', $setting);
|
||||
$subGroup = explode('.', $setting['name']);
|
||||
if ($subGroup[0] === 'Plugin') {
|
||||
$subGroup = explode('_', $subGroup[1])[0];
|
||||
} else {
|
||||
$subGroup = 'general';
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData(array($setting => $found['value']));
|
||||
return $this->RestResponse->viewData(array($setting['name'] => $setting['value']));
|
||||
} else {
|
||||
$this->set('subGroup', $subGroup);
|
||||
$this->set('setting', $found);
|
||||
$this->set('setting', $setting);
|
||||
$this->render('ajax/server_settings_edit');
|
||||
}
|
||||
}
|
||||
|
@ -1211,7 +1201,7 @@ class ServersController extends AppController
|
|||
'action' => 'serverSettingsEdit',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Server setting issue',
|
||||
'change' => 'There was an issue witch changing ' . $setting . ' to ' . $this->request->data['Server']['value'] . '. The error message returned is: app/Config.config.php is not writeable to the apache user. No changes were made.',
|
||||
'change' => 'There was an issue witch changing ' . $setting['name'] . ' to ' . $this->request->data['Server']['value'] . '. The error message returned is: app/Config.config.php is not writeable to the apache user. No changes were made.',
|
||||
));
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, 'app/Config.config.php is not writeable to the apache user.', $this->response->type());
|
||||
|
@ -1219,92 +1209,19 @@ class ServersController extends AppController
|
|||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'app/Config.config.php is not writeable to the apache user.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($found['beforeHook'])) {
|
||||
$beforeResult = call_user_func_array(array($this->Server, $found['beforeHook']), array($setting, $this->request->data['Server']['value']));
|
||||
if ($beforeResult !== true) {
|
||||
$this->Log->create();
|
||||
$result = $this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'serverSettingsEdit',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Server setting issue',
|
||||
'change' => 'There was an issue witch changing ' . $setting . ' to ' . $this->request->data['Server']['value'] . '. The error message returned is: ' . $beforeResult . 'No changes were made.',
|
||||
));
|
||||
if ($this->_isRest) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, $beforeResult, $this->response->type());
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $beforeResult)), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->request->data['Server']['value'] = trim($this->request->data['Server']['value']);
|
||||
if ($found['type'] == 'boolean') {
|
||||
$this->request->data['Server']['value'] = ($this->request->data['Server']['value'] ? true : false);
|
||||
}
|
||||
if ($found['type'] == 'numeric') {
|
||||
$this->request->data['Server']['value'] = intval($this->request->data['Server']['value']);
|
||||
}
|
||||
if (!empty($leafValue['test'])) {
|
||||
$testResult = $this->Server->{$found['test']}($this->request->data['Server']['value']);
|
||||
} else {
|
||||
$testResult = true; # No test defined for this setting: cannot fail
|
||||
}
|
||||
if (!$forceSave && $testResult !== true) {
|
||||
if ($testResult === false) {
|
||||
$errorMessage = $found['errorMessage'];
|
||||
} else {
|
||||
$errorMessage = $testResult;
|
||||
}
|
||||
if ($this->_isRest) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, $errorMessage, $this->response->type());
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $errorMessage)), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
} else {
|
||||
$oldValue = Configure::read($setting);
|
||||
$this->Server->serverSettingsSaveValue($setting, $this->request->data['Server']['value']);
|
||||
$this->Log->create();
|
||||
$result = $this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'serverSettingsEdit',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Server setting changed',
|
||||
'change' => $setting . ' (' . $oldValue . ') => (' . $this->request->data['Server']['value'] . ')',
|
||||
));
|
||||
// execute after hook
|
||||
if (isset($found['afterHook'])) {
|
||||
$afterResult = call_user_func_array(array($this->Server, $found['afterHook']), array($setting, $this->request->data['Server']['value']));
|
||||
if ($afterResult !== true) {
|
||||
$this->Log->create();
|
||||
$result = $this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'serverSettingsEdit',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Server setting issue',
|
||||
'change' => 'There was an issue after setting a new setting. The error message returned is: ' . $afterResult,
|
||||
));
|
||||
if ($this->_isRest) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, $afterResult, $this->response->type());
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $afterResult)), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->_isRest) {
|
||||
$result = $this->Server->serverSettingsEditValue($this->Auth->user(), $setting, $this->request->data['Server']['value'], $forceSave);
|
||||
if ($result === true) {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Servers', 'serverSettingsEdit', false, $this->response->type(), 'Field updated');
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Field updated.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
} else {
|
||||
if ($this->_isRest) {
|
||||
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, $result, $this->response->type());
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $result)), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1614,17 +1531,18 @@ class ServersController extends AppController
|
|||
|
||||
public function rest()
|
||||
{
|
||||
$allValidApis = $this->RestResponse->getAllApis($this->Auth->user(), $this);
|
||||
$allValidApis = $this->RestResponse->getAllApis($this->Auth->user());
|
||||
$allValidApisFieldsContraint = $this->RestResponse->getAllApisFieldsConstraint($this->Auth->user());
|
||||
if ($this->request->is('post')) {
|
||||
$request = $this->request->data;
|
||||
if (!empty($request['Server'])) {
|
||||
$request = $this->request->data['Server'];
|
||||
}
|
||||
$curl = '';
|
||||
$python = '';
|
||||
$curl = '';
|
||||
$python = '';
|
||||
$result = $this->__doRestQuery($request, $curl, $python);
|
||||
$this->set('curl', $curl);
|
||||
$this->set('python', $python);
|
||||
$this->set('curl', $curl);
|
||||
$this->set('python', $python);
|
||||
if (!$result) {
|
||||
$this->Flash->error('Something went wrong. Make sure you set the http method, body (when sending POST requests) and URL correctly.');
|
||||
} else {
|
||||
|
@ -1636,7 +1554,14 @@ class ServersController extends AppController
|
|||
'Accept: application/json' . PHP_EOL .
|
||||
'Content-Type: application/json';
|
||||
$this->set('header', $header);
|
||||
$this->set('allValidApis', $allValidApis);
|
||||
$this->set('allValidApis', $allValidApis);
|
||||
// formating for optgroup
|
||||
$allValidApisFormated = array();
|
||||
foreach ($allValidApis as $endpoint_url => $endpoint_data) {
|
||||
$allValidApisFormated[$endpoint_data['controller']][] = array('url' => $endpoint_url, 'action' => $endpoint_data['action']);
|
||||
}
|
||||
$this->set('allValidApisFormated', $allValidApisFormated);
|
||||
$this->set('allValidApisFieldsContraint', $allValidApisFieldsContraint);
|
||||
}
|
||||
|
||||
private function __doRestQuery($request, &$curl = false, &$python = false)
|
||||
|
@ -1644,20 +1569,20 @@ class ServersController extends AppController
|
|||
App::uses('SyncTool', 'Tools');
|
||||
$params = array();
|
||||
if (!empty($request['url'])) {
|
||||
if (empty($request['use_full_path'])) {
|
||||
$path = preg_replace('#^(://|[^/?])+#', '', $request['url']);
|
||||
$url = Configure::read('MISP.baseurl') . $path;
|
||||
unset($request['url']);
|
||||
} else {
|
||||
$url = $request['url'];
|
||||
}
|
||||
if (empty($request['use_full_path'])) {
|
||||
$path = preg_replace('#^(://|[^/?])+#', '', $request['url']);
|
||||
$url = Configure::read('MISP.baseurl') . $path;
|
||||
unset($request['url']);
|
||||
} else {
|
||||
$url = $request['url'];
|
||||
}
|
||||
} else {
|
||||
throw new InvalidArgumentException('Url not set.');
|
||||
}
|
||||
if (!empty($request['skip_ssl_validation'])) {
|
||||
$params['ssl_verify_peer'] = false;
|
||||
}
|
||||
$params['timeout'] = 300;
|
||||
if (!empty($request['skip_ssl_validation'])) {
|
||||
$params['ssl_verify_peer'] = false;
|
||||
}
|
||||
$params['timeout'] = 300;
|
||||
App::uses('HttpSocket', 'Network/Http');
|
||||
$HttpSocket = new HttpSocket($params);
|
||||
$view_data = array();
|
||||
|
@ -1678,24 +1603,24 @@ class ServersController extends AppController
|
|||
!empty($request['method']) &&
|
||||
$request['method'] === 'GET'
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('get', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('get', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->get($url, false, array('header' => $request['header']));
|
||||
} elseif (
|
||||
!empty($request['method']) &&
|
||||
$request['method'] === 'POST' &&
|
||||
!empty($request['body'])
|
||||
) {
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('post', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
if ($curl !== false) {
|
||||
$curl = $this->__generateCurlQuery('post', $request, $url);
|
||||
}
|
||||
if ($python !== false) {
|
||||
$python = $this->__generatePythonScript($request, $url);
|
||||
}
|
||||
$response = $HttpSocket->post($url, $request['body'], array('header' => $request['header']));
|
||||
} else {
|
||||
return false;
|
||||
|
@ -1716,28 +1641,28 @@ class ServersController extends AppController
|
|||
return $view_data;
|
||||
}
|
||||
|
||||
private function __generatePythonScript($request, $url)
|
||||
{
|
||||
$slashCounter = 0;
|
||||
$baseurl = '';
|
||||
$relative = '';
|
||||
$verifyCert = ($url[4] === 's') ? 'True' : 'False';
|
||||
for ($i = 0; $i < strlen($url); $i++) {
|
||||
//foreach ($url as $url[$i]) {
|
||||
if ($url[$i] === '/') {
|
||||
$slashCounter += 1;
|
||||
if ($slashCounter == 3) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($slashCounter < 3) {
|
||||
$baseurl .= $url[$i];
|
||||
} else {
|
||||
$relative .= $url[$i];
|
||||
}
|
||||
}
|
||||
$python_script =
|
||||
sprintf(
|
||||
private function __generatePythonScript($request, $url)
|
||||
{
|
||||
$slashCounter = 0;
|
||||
$baseurl = '';
|
||||
$relative = '';
|
||||
$verifyCert = ($url[4] === 's') ? 'True' : 'False';
|
||||
for ($i = 0; $i < strlen($url); $i++) {
|
||||
//foreach ($url as $url[$i]) {
|
||||
if ($url[$i] === '/') {
|
||||
$slashCounter += 1;
|
||||
if ($slashCounter == 3) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($slashCounter < 3) {
|
||||
$baseurl .= $url[$i];
|
||||
} else {
|
||||
$relative .= $url[$i];
|
||||
}
|
||||
}
|
||||
$python_script =
|
||||
sprintf(
|
||||
'misp_url = \'%s\'
|
||||
misp_key = \'%s\'
|
||||
misp_verifycert = %s
|
||||
|
@ -1749,63 +1674,102 @@ from pymisp import PyMISP
|
|||
misp = PyMISP(misp_url, misp_key, misp_verifycert)
|
||||
misp.direct_call(relative_path, body)
|
||||
',
|
||||
$baseurl,
|
||||
$request['header']['Authorization'],
|
||||
$verifyCert,
|
||||
$relative,
|
||||
(empty($request['body']) ? 'Null' : '\'' . $request['body'] . '\'')
|
||||
);
|
||||
return $python_script;
|
||||
}
|
||||
$baseurl,
|
||||
$request['header']['Authorization'],
|
||||
$verifyCert,
|
||||
$relative,
|
||||
(empty($request['body']) ? 'Null' : '\'' . $request['body'] . '\'')
|
||||
);
|
||||
return $python_script;
|
||||
}
|
||||
|
||||
private function __generateCurlQuery($type, $request, $url)
|
||||
{
|
||||
if ($type === 'get') {
|
||||
$curl = sprintf(
|
||||
'curl \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s %s',
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
} else {
|
||||
$curl = sprintf(
|
||||
'curl \%s -d \'%s\' \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s -X POST %s',
|
||||
PHP_EOL,
|
||||
json_encode(json_decode($request['body']), true),
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
}
|
||||
return $curl;
|
||||
}
|
||||
|
||||
public function getApiInfo() {
|
||||
$relative_path = $this->request->data['url'];
|
||||
$result = $this->RestResponse->getApiInfo($relative_path);
|
||||
if ($this->_isRest()) {
|
||||
return $result;
|
||||
} else {
|
||||
$result = json_decode($result, true);
|
||||
if (empty($result)) {
|
||||
return $this->RestResponse->viewData(' ', $this->response->type());
|
||||
}
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->set('api_info', $result);
|
||||
$this->render('ajax/get_api_info');
|
||||
}
|
||||
}
|
||||
private function __generateCurlQuery($type, $request, $url)
|
||||
{
|
||||
if ($type === 'get') {
|
||||
$curl = sprintf(
|
||||
'curl \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s %s',
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
} else {
|
||||
$curl = sprintf(
|
||||
'curl \%s -d \'%s\' \%s -H "Authorization: %s" \%s -H "Accept: %s" \%s -H "Content-type: %s" \%s -X POST %s',
|
||||
PHP_EOL,
|
||||
json_encode(json_decode($request['body']), true),
|
||||
PHP_EOL,
|
||||
$request['header']['Authorization'],
|
||||
PHP_EOL,
|
||||
$request['header']['Accept'],
|
||||
PHP_EOL,
|
||||
$request['header']['Content-Type'],
|
||||
PHP_EOL,
|
||||
$url
|
||||
);
|
||||
}
|
||||
return $curl;
|
||||
}
|
||||
|
||||
public function getApiInfo()
|
||||
{
|
||||
$relative_path = $this->request->data['url'];
|
||||
$result = $this->RestResponse->getApiInfo($relative_path);
|
||||
if ($this->_isRest()) {
|
||||
return $result;
|
||||
} else {
|
||||
$result = json_decode($result, true);
|
||||
if (empty($result)) {
|
||||
return $this->RestResponse->viewData(' ', $this->response->type());
|
||||
}
|
||||
$this->layout = false;
|
||||
$this->autoRender = false;
|
||||
$this->set('api_info', $result);
|
||||
$this->render('ajax/get_api_info');
|
||||
}
|
||||
}
|
||||
|
||||
public function cache($id = 'all')
|
||||
{
|
||||
if (Configure::read('MISP.background_jobs')) {
|
||||
$this->loadModel('Job');
|
||||
$this->Job->create();
|
||||
$data = array(
|
||||
'worker' => 'default',
|
||||
'job_type' => 'cache_servers',
|
||||
'job_input' => intval($id) ? $id : 'all',
|
||||
'status' => 0,
|
||||
'retries' => 0,
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'message' => __('Starting server caching.'),
|
||||
);
|
||||
$this->Job->save($data);
|
||||
$jobId = $this->Job->id;
|
||||
$process_id = CakeResque::enqueue(
|
||||
'default',
|
||||
'ServerShell',
|
||||
array('cacheServer', $this->Auth->user('id'), $id, $jobId),
|
||||
true
|
||||
);
|
||||
$this->Job->saveField('process_id', $process_id);
|
||||
$message = 'Server caching job initiated.';
|
||||
} else {
|
||||
$result = $this->Server->cacheServerInitiator($this->Auth->user(), $id);
|
||||
if (!$result) {
|
||||
$this->Flash->error(__('Caching the servers has failed.'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
$message = __('Caching the servers has successfully completed.');
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Server', 'cache', false, $this->response->type(), $message);
|
||||
} else {
|
||||
$this->Flash->info($message);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -347,7 +347,7 @@ class ShadowAttributesController extends AppController
|
|||
if (!$this->_isRest() && (isset($this->request->data['ShadowAttribute']['batch_import']) && $this->request->data['ShadowAttribute']['batch_import'] == 1)) {
|
||||
// make array from value field
|
||||
$attributes = explode("\n", $this->request->data['ShadowAttribute']['value']);
|
||||
$fails = ""; // will be used to keep a list of the lines that failed or succeeded
|
||||
$fails = ""; // will be used to keep a list of the lines that failed or succeeded
|
||||
$successes = "";
|
||||
// TODO loopholes
|
||||
// the value null value thing
|
||||
|
@ -824,7 +824,7 @@ class ShadowAttributesController extends AppController
|
|||
$id = $temp['Attribute']['id'];
|
||||
}
|
||||
|
||||
$existingAttribute = $this->ShadowAttribute->Event->Attribute->fetchAttributes($this->Auth->user(), array('Attriute.id' => $id));
|
||||
$existingAttribute = $this->ShadowAttribute->Event->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id)));
|
||||
if (empty($existingAttribute)) {
|
||||
throw new NotFoundException(__('Invalid attribute.'));
|
||||
}
|
||||
|
@ -833,6 +833,7 @@ class ShadowAttributesController extends AppController
|
|||
if (empty($existingAttribute)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('false' => true, 'errors' => 'Invalid Attribute.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$existingAttribute = $existingAttribute[0];
|
||||
$this->ShadowAttribute->create();
|
||||
$sa = array(
|
||||
'old_id' => $existingAttribute['Attribute']['id'],
|
||||
|
@ -861,6 +862,7 @@ class ShadowAttributesController extends AppController
|
|||
if (empty($existingAttribute)) {
|
||||
throw new NotFoundException(__('Invalid Attribute'));
|
||||
}
|
||||
$existingAttribute = $existingAttribute[0];
|
||||
$this->set('id', $id);
|
||||
$this->set('event_id', $existingAttribute['Attribute']['event_id']);
|
||||
$this->render('ajax/deletionProposalConfirmationForm');
|
||||
|
|
|
@ -17,7 +17,7 @@ class SharingGroupsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'SharingGroup.name' => 'ASC'
|
||||
),
|
||||
|
|
|
@ -12,7 +12,7 @@ class SightingsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array('Sighting.date_sighting' => 'DESC'),
|
||||
);
|
||||
|
||||
|
@ -83,9 +83,22 @@ class SightingsController extends AppController
|
|||
}
|
||||
} else {
|
||||
if ($error) {
|
||||
return $this->RestResponse->saveFailResponse('Sighting', 'add', $id, $error);
|
||||
$error_message = __('Could not add the Sighting. Reason: ') . $error;
|
||||
if ($this->_isRest() || $this->response->type() === 'application/json') {
|
||||
$this->set('message', $error_message);
|
||||
$this->set('_serialize', array('message'));
|
||||
} else {
|
||||
$this->Flash->error($error_message);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
} else {
|
||||
return $this->RestResponse->saveSuccessResponse('Sighting', 'add', $id, false, $result . ' ' . $this->Sighting->type[$type] . (($result == 1) ? '' : 's') . ' successfuly added.');
|
||||
if ($this->_isRest() || $this->response->type() === 'application/json') {
|
||||
$this->set('message', __('Sighting added'));
|
||||
$this->set('_serialize', array('message'));
|
||||
} else {
|
||||
$this->Flash->success(__('Sighting added'));
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -133,6 +146,50 @@ class SightingsController extends AppController
|
|||
$this->render('/Sightings/ajax/advanced');
|
||||
}
|
||||
|
||||
public function quickAdd($id=false, $type=1, $onvalue=false)
|
||||
{
|
||||
if (!$this->userRole['perm_modify_org']) {
|
||||
throw new MethodNotAllowedException(__('You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.'));
|
||||
}
|
||||
if (!$this->request->is('post')) {
|
||||
$this->loadModel('Attribute');
|
||||
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id, 'Attribute.deleted' => 0), 'flatten' => 1));
|
||||
if (empty($attribute)) {
|
||||
throw new MethodNotAllowedException(__('Attribute not found'));
|
||||
} else {
|
||||
$attribute = $attribute[0]['Attribute'];
|
||||
if (!$onvalue) {
|
||||
$this->set('id', $attribute['id']);
|
||||
$this->set('tosight', $attribute['id']);
|
||||
} else {
|
||||
$this->set('id', '');
|
||||
$this->set('tosight', $attribute['value']);
|
||||
}
|
||||
$this->set('value', $attribute['value']);
|
||||
$this->set('event_id', $attribute['event_id']);
|
||||
$this->set('sighting_type', $type);
|
||||
$this->set('onvalue', $onvalue);
|
||||
$this->render('ajax/quickAddConfirmationForm');
|
||||
}
|
||||
} else {
|
||||
if (!isset($id)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => __('Invalid request.'))), 'status' => 200, 'type' => 'json'));
|
||||
} else {
|
||||
if ($onvalue) {
|
||||
$result = $this->Sighting->add();
|
||||
} else {
|
||||
$result = $this->Sighting->add($id);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => __('Sighting added.'))), 'status' => 200, 'type' => 'json'));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => __('Sighting could not be added'))), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function quickDelete($id, $rawId, $context)
|
||||
{
|
||||
if (!$this->userRole['perm_modify_org']) {
|
||||
|
@ -220,6 +277,42 @@ class SightingsController extends AppController
|
|||
return $this->RestResponse->viewData($sightings);
|
||||
}
|
||||
|
||||
public function restSearch($context = false)
|
||||
{
|
||||
$allowedContext = array(false, 'event', 'attribute');
|
||||
$paramArray = array('returnFormat', 'id', 'type', 'from', 'to', 'last', 'org_id', 'source', 'includeAttribute', 'includeEvent');
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
'paramArray' => $paramArray,
|
||||
'ordered_url_params' => compact($paramArray)
|
||||
);
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
|
||||
// validate context
|
||||
if (!in_array($context, $allowedContext, true)) {
|
||||
throw new MethodNotAllowedException(_('Invalid context.'));
|
||||
}
|
||||
// ensure that an id is provided if context is set
|
||||
if ($context !== false && !isset($filters['id'])) {
|
||||
throw new MethodNotAllowedException(_('An id must be provided if the context is set.'));
|
||||
}
|
||||
$filters['context'] = $context;
|
||||
|
||||
if (isset($filters['returnFormat'])) {
|
||||
$returnFormat = $filters['returnFormat'];
|
||||
}
|
||||
if ($returnFormat === 'download') {
|
||||
$returnFormat = 'json';
|
||||
}
|
||||
|
||||
$sightings = $this->Sighting->restSearch($this->Auth->user(), $returnFormat, $filters);
|
||||
|
||||
$validFormats = $this->Sighting->validFormats;
|
||||
$responseType = $validFormats[$returnFormat][0];
|
||||
return $this->RestResponse->viewData($sightings, $responseType, false, true);
|
||||
}
|
||||
|
||||
public function listSightings($id, $context = 'attribute', $org_id = false)
|
||||
{
|
||||
$this->loadModel('Event');
|
||||
|
|
|
@ -0,0 +1,500 @@
|
|||
<?php
|
||||
|
||||
App::uses('AppController', 'Controller');
|
||||
|
||||
class TagCollectionsController extends AppController
|
||||
{
|
||||
public $components = array(
|
||||
'Security',
|
||||
'AdminCrud',
|
||||
'RequestHandler'
|
||||
);
|
||||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'order' => array(
|
||||
'TagCollection.name' => 'ASC'
|
||||
),
|
||||
'recursive' => -1,
|
||||
'contain' => array(
|
||||
'TagCollectionTag' => array(
|
||||
'Tag'
|
||||
),
|
||||
'Organisation' => array(
|
||||
'fields' => array(
|
||||
'Organisation.id',
|
||||
'Organisation.name',
|
||||
'Organisation.uuid'
|
||||
)
|
||||
),
|
||||
'User' => array(
|
||||
'fields' => array(
|
||||
'User.email',
|
||||
'User.id'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$this->TagCollection->create();
|
||||
if (!isset($this->request->data['TagCollection'])) {
|
||||
$this->request->data = array('TagCollection' => $this->request->data);
|
||||
}
|
||||
$this->request->data['TagCollection']['org_id'] = $this->Auth->user('org_id');
|
||||
$this->request->data['TagCollection']['user_id'] = $this->Auth->user('id');
|
||||
if ($this->TagCollection->save($this->request->data)) {
|
||||
if ($this->_isRest()) {
|
||||
$tagCollection = $this->TagCollection->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('TagCollection.id' => $this->TagCollection->id)
|
||||
));
|
||||
return $this->RestResponse->viewData($tagCollection, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->success(__('The tag collection has been saved'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
} else {
|
||||
$message = json_encode($this->TagCollection->validationErrors);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('TagCollection', 'add', false, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error(__('The tag collection could not be added. Reason: ') . $message);
|
||||
}
|
||||
}
|
||||
} elseif ($this->_isRest()) {
|
||||
return $this->RestResponse->describe('TagCollection', 'add', false, $this->response->type());
|
||||
}
|
||||
$this->set('action', 'add');
|
||||
}
|
||||
|
||||
public function import()
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
if (isset($this->request->data['TagCollection']['json'])) {
|
||||
$data = json_decode($this->request->data['TagCollection']['json'], true);
|
||||
} else {
|
||||
$data = $this->request->data;
|
||||
}
|
||||
$results = $this->TagCollection->import($data, $this->Auth->user());
|
||||
if ($results['successes'] > 0) {
|
||||
$flashType = 'success';
|
||||
$message = sprintf(
|
||||
__('%s new tag collections added.'),
|
||||
$results['successes']
|
||||
);
|
||||
} else {
|
||||
$flashType = 'info';
|
||||
$message = 'No new tag_collections to add.';
|
||||
}
|
||||
if ($results['fails']) {
|
||||
$message .= sprintf(
|
||||
' %s tag collections could not be added (possibly because they already exist)',
|
||||
$results['fails']
|
||||
);
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('TagCollections', 'import', false, $this->response->type(), $message);
|
||||
} else {
|
||||
$this->Flash->{$flashType}($message);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function view($id)
|
||||
{
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array(
|
||||
'OR' => array(
|
||||
'TagCollection.all_orgs' => 1,
|
||||
'TagCollection.org_id' => $this->Auth->user('org_id')
|
||||
)
|
||||
);
|
||||
$this->paginate['conditions'] = $conditions;
|
||||
}
|
||||
$conditions['TagCollection.id'] = $id;
|
||||
$params = array(
|
||||
'recursive' => -1,
|
||||
'contain' => array('TagCollectionTag' => array('Tag'), 'Organisation' => array('fields' => array('id', 'name', 'uuid')), 'User' => array('fields' => array('User.id', 'User.email')))
|
||||
);
|
||||
if (!empty($conditions)) {
|
||||
$params['conditions'] = $conditions;
|
||||
}
|
||||
$collection = $this->TagCollection->find('first', $params);
|
||||
if (empty($collection)) {
|
||||
throw new NotFoundException('Invalid Tag Collection');
|
||||
}
|
||||
$collection = $this->TagCollection->cullBlockedTags($this->Auth->user(), $collection);
|
||||
$this->loadModel('Event');
|
||||
$collection = $this->Event->massageTags($collection, 'TagCollection', false, true);
|
||||
if (!$this->_isSiteAdmin() && $collection['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
|
||||
unset($collection['User']);
|
||||
unset($collection['TagCollection']['user_id']);
|
||||
}
|
||||
if (!empty($collection['TagCollectionTag'])) {
|
||||
foreach ($collection['TagCollectionTag'] as $k => $tct) {
|
||||
$collection['TagCollectionTag'][$k]['Tag'] = array(
|
||||
'id' => $tct['Tag']['id'],
|
||||
'name' => $tct['Tag']['name'],
|
||||
'colour' => $tct['Tag']['colour']
|
||||
);
|
||||
}
|
||||
}
|
||||
return $this->RestResponse->viewData($collection, $this->response->type());
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
$this->TagCollection->id = $id;
|
||||
if (!$this->TagCollection->exists()) {
|
||||
throw new NotFoundException(__('Invalid Tag Collection'));
|
||||
}
|
||||
$tagCollection = $this->TagCollection->find('first', array(
|
||||
'conditions' => array('TagCollection.id' => $id),
|
||||
'recursive' => -1
|
||||
));
|
||||
if (!$this->_isSiteAdmin() && $tagCollection['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
|
||||
throw new MethodNotAllowedException(__('You don\'t have editing rights on this Tag Collection.'));
|
||||
}
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
if (!isset($this->request->data['TagCollection'])) {
|
||||
$this->request->data = array('TagCollection' => $this->request->data);
|
||||
}
|
||||
$this->request->data['TagCollection']['id'] = $tagCollection['TagCollection']['id'];
|
||||
$this->request->data['TagCollection']['uuid'] = $tagCollection['TagCollection']['uuid'];
|
||||
if ($this->TagCollection->save($this->request->data)) {
|
||||
if ($this->_isRest()) {
|
||||
$tagCollection = $this->TagCollection->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('TagCollection.id' => $this->TagCollection->id)
|
||||
));
|
||||
return $this->RestResponse->viewData($tagCollection, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->success(__('The tag collection has been saved'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
} else {
|
||||
$message = json_encode($this->TagCollection->validationErrors);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('TagCollection', 'add', false, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error(__('The tag collection could not be added. Reason: ') . $message);
|
||||
}
|
||||
}
|
||||
} elseif ($this->_isRest()) {
|
||||
return $this->RestResponse->describe('TagCollection', 'add', false, $this->response->type());
|
||||
} else {
|
||||
$this->request->data = $tagCollection;
|
||||
}
|
||||
$this->set('action', 'edit');
|
||||
$this->render('add');
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $id)));
|
||||
if (empty($tagCollection)) {
|
||||
throw new NotFoundException(__('Invalid tag collection.'));
|
||||
}
|
||||
$tagCollection = $tagCollection[0];
|
||||
if ($this->TagCollection->checkAccess($this->Auth->user(), $tagCollection, 'write')) {
|
||||
$result = $this->TagCollection->delete($id);
|
||||
if ($result) {
|
||||
$message = __('Tag collection deleted.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('TagCollections', 'delete', false, $this->response->type(), $message);
|
||||
} else {
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
} else {
|
||||
$message = __('Tag collection could not be deleted.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('TagCollections', 'delete', false, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new NotFoundException(__('You are not allowed to delete that.'));
|
||||
}
|
||||
}
|
||||
|
||||
public function addTag($id = false, $tag_id = false)
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$rearrangeRules = array(
|
||||
'request' => false,
|
||||
'TagCollection' => false,
|
||||
'tag_id' => 'tag',
|
||||
'tag_collection_id' => 'tag_collection',
|
||||
'id' => 'tag_collection'
|
||||
);
|
||||
$RearrangeTool = new RequestRearrangeTool();
|
||||
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
|
||||
if ($id === false) {
|
||||
$id = $this->request->data['tag_collection'];
|
||||
}
|
||||
if ($tag_id === false) {
|
||||
$tag_id = $this->request->data['tag'];
|
||||
}
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
|
||||
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
|
||||
}
|
||||
if (!is_numeric($tag_id)) {
|
||||
$tag_ids = json_decode($tag_id);
|
||||
$tag_lookups = array();
|
||||
foreach ($tag_ids as $temp) {
|
||||
if (is_numeric($temp)) {
|
||||
$tag_lookups['OR']['Tag.id'][] = $temp;
|
||||
} else {
|
||||
$tag_lookups['OR']['LOWER(Tag.name) LIKE'][] = strtolower(trim($tag_id));
|
||||
}
|
||||
}
|
||||
if ($tag_ids !== null && is_array($tag_ids)) { // can decode json
|
||||
$tag_ids = $this->TagCollection->TagCollectionTag->Tag->find('list', array(
|
||||
'conditions' => array(
|
||||
'AND' => array(
|
||||
$conditions,
|
||||
$tag_lookups
|
||||
)
|
||||
),
|
||||
'fields' => array('Tag.id', 'Tag.id')
|
||||
));
|
||||
$tag_id_list = array_values($tag_ids);
|
||||
if (empty($tag_id_list)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag(s).')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
} else {
|
||||
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
|
||||
if (empty($tag)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
$tag_id = $tag['Tag']['id'];
|
||||
}
|
||||
}
|
||||
$tagCollection = $this->TagCollection->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('TagCollection.id' => $id)
|
||||
));
|
||||
if (empty($tagCollection)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid tag collection.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $tagCollection['TagCollection']['org_id'])) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
$this->autoRender = false;
|
||||
$error = false;
|
||||
$success = false;
|
||||
if (empty($tag_id_list)) {
|
||||
$tag_id_list = array($tag_id);
|
||||
}
|
||||
|
||||
foreach ($tag_id_list as $tag_id) {
|
||||
$this->TagCollection->TagCollectionTag->Tag->id = $tag_id;
|
||||
if (!$this->TagCollection->TagCollectionTag->Tag->exists()) {
|
||||
$error = __('Invalid Tag.');
|
||||
continue;
|
||||
}
|
||||
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array(
|
||||
'conditions' => array('Tag.id' => $tag_id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('Tag.name')
|
||||
));
|
||||
$found = $this->TagCollection->TagCollectionTag->find('first', array(
|
||||
'conditions' => array(
|
||||
'tag_collection_id' => $id,
|
||||
'tag_id' => $tag_id
|
||||
),
|
||||
'recursive' => -1,
|
||||
));
|
||||
if (!empty($found)) {
|
||||
$error = __('Tag is already attached to this event.');
|
||||
continue;
|
||||
}
|
||||
$this->TagCollection->TagCollectionTag->create();
|
||||
if ($this->TagCollection->TagCollectionTag->save(array('tag_collection_id' => $id, 'tag_id' => $tag_id))) {
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'TagCollection', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to collection (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
|
||||
$success = __('Tag(s) added.');
|
||||
} else {
|
||||
$fail = __('Tag(s) could not be added.');
|
||||
}
|
||||
}
|
||||
if ($success) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $success)), 'status'=>200, 'type' => 'json'));
|
||||
} elseif (empty($fail)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => __('All tags are already present, nothing to add.'), 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $fail)), 'status'=>200, 'type' => 'json'));
|
||||
}
|
||||
}
|
||||
|
||||
public function removeTag($id = false, $tag_id = false)
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
$this->set('id', $id);
|
||||
$this->set('tag_id', $tag_id);
|
||||
$this->set('model', 'tag_collection');
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/Attributes/ajax/tagRemoveConfirmation');
|
||||
} else {
|
||||
$rearrangeRules = array(
|
||||
'request' => false,
|
||||
'TagCollection' => false,
|
||||
'tag_id' => 'tag',
|
||||
'tag_collection_id' => 'tag_collection',
|
||||
'id' => 'tag_collection'
|
||||
);
|
||||
$RearrangeTool = new RequestRearrangeTool();
|
||||
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
|
||||
if ($id === false) {
|
||||
$id = $this->request->data['tag_collection'];
|
||||
}
|
||||
if ($tag_id === false) {
|
||||
$tag_id = $this->request->data['tag'];
|
||||
}
|
||||
$tagCollection = $this->TagCollection->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array(
|
||||
'TagCollection.id' => $id
|
||||
),
|
||||
'contain' => array(
|
||||
'TagCollectionTag' => array(
|
||||
'Tag'
|
||||
)
|
||||
)
|
||||
));
|
||||
if (empty($tagCollection)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Invalid tag collection.'))), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
$found = false;
|
||||
if (!$this->_isSiteAdmin() && $this->Auth->user('org_id') !== $tagCollection['TagCollection']['org_id']) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Insufficient privileges to remove the tag from the collection.'))), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
foreach ($tagCollection['TagCollectionTag'] as $TagCollectionTag) {
|
||||
if ((is_numeric($tag_id) && $TagCollectionTag['Tag']['id'] == $tag_id) || $TagCollectionTag['Tag']['name'] === $tag_id) {
|
||||
$found = true;
|
||||
$tag = $TagCollectionTag;
|
||||
$result = $this->TagCollection->TagCollectionTag->delete($TagCollectionTag['id']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Invalid tag or tag not associated with the collection.'))), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
||||
if (!$result) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Failed to remove tag from the collection.'))), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($this->Auth->user(), 'tag', 'TagCollection', $id, 'Removed tag (' . $tag['Tag']['id'] . ') "' . $tag['Tag']['name'] . '" from tag collection (' . $id . ')', 'Tag collection (' . $id . ') - untagged Tag (' . $tag_id . ')');
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag removed.')), 'status' => 200));
|
||||
}
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
//$this->Auth->user('Role')['perm_site_admin']);
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array(
|
||||
'OR' => array(
|
||||
'TagCollection.all_orgs' => 1,
|
||||
'TagCollection.org_id' => $this->Auth->user('org_id')
|
||||
)
|
||||
);
|
||||
$this->paginate['conditions'] = $conditions;
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$params = array(
|
||||
'recursive' => -1,
|
||||
'contain' => array(
|
||||
'TagCollectionTag' => array(
|
||||
'Tag'
|
||||
),
|
||||
'Organisation' => array(
|
||||
'fields' => array(
|
||||
'Organisation.id',
|
||||
'Organisation.name',
|
||||
'Organisation.uuid'
|
||||
)
|
||||
),
|
||||
'User' => array(
|
||||
'fields' => array(
|
||||
'User.email',
|
||||
'User.id'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!empty($conditions)) {
|
||||
$params['conditions'] = $conditions;
|
||||
}
|
||||
$namedParams = array('limit', 'page');
|
||||
foreach ($namedParams as $namedParam) {
|
||||
if (!empty($this->params['named'][$namedParam])) {
|
||||
$params['limit'] = $this->params['named'][$namedParam];
|
||||
}
|
||||
}
|
||||
$list = $this->TagCollection->find('all', $params);
|
||||
} else {
|
||||
$list = $this->paginate();
|
||||
}
|
||||
$this->loadModel('Event');
|
||||
foreach ($list as $k => $tag_collection) {
|
||||
$list[$k] = $this->TagCollection->cullBlockedTags($this->Auth->user(), $tag_collection);
|
||||
$list[$k] = $this->Event->massageTags($list[$k], 'TagCollection', false, true);
|
||||
if (!$this->_isSiteAdmin() && $list[$k]['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
|
||||
unset($list[$k]['User']);
|
||||
unset($list[$k]['TagCollection']['user_id']);
|
||||
}
|
||||
if (!empty($list[$k]['TagCollectionTag'])) {
|
||||
foreach ($list[$k]['TagCollectionTag'] as $k2 => $tct) {
|
||||
$list[$k]['TagCollectionTag'][$k2]['Tag'] = array(
|
||||
'id' => $tct['Tag']['id'],
|
||||
'name' => $tct['Tag']['name'],
|
||||
'colour' => $tct['Tag']['colour']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($list, $this->response->type());
|
||||
} else {
|
||||
$this->set('list', $list);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRow($id)
|
||||
{
|
||||
$params = array(
|
||||
'recursive' => -1,
|
||||
'contain' => array('TagCollectionTag' => array('Tag'), 'User', 'Organisation'),
|
||||
'conditions' => array('TagCollection.id' => $id)
|
||||
);
|
||||
$item = $this->TagCollection->find('first', $params);
|
||||
if (empty($item)) {
|
||||
throw new NotFoundException('Invalid tag collection.');
|
||||
}
|
||||
if (!$this->_isSiteAdmin() && $item['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
|
||||
unset($item['User']);
|
||||
unset($item['TagCollection']['user_id']);
|
||||
}
|
||||
$this->loadModel('Event');
|
||||
$item = $this->Event->massageTags($item, 'TagCollection', false, true);
|
||||
$this->layout = false;
|
||||
$this->set('item', $item);
|
||||
}
|
||||
}
|
|
@ -293,7 +293,7 @@ class TagsController extends AppController
|
|||
if ($this->Tag->save($this->request->data)) {
|
||||
if ($this->_isRest()) {
|
||||
$tag = $this->Tag->find('first', array(
|
||||
'contidions' => array(
|
||||
'conditions' => array(
|
||||
'Tag.id' => $id
|
||||
),
|
||||
'recursive' => -1
|
||||
|
@ -500,6 +500,13 @@ class TagsController extends AppController
|
|||
'contain' => array('Tag'),
|
||||
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
|
||||
));
|
||||
$this->loadModel('GalaxyCluster');
|
||||
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name', 'GalaxyCluster.id')));
|
||||
foreach ($attributeTags as $k => $attributeTag) {
|
||||
if (in_array($attributeTag['Tag']['name'], $cluster_names)) {
|
||||
unset($attributeTags[$k]);
|
||||
}
|
||||
}
|
||||
$event = $this->Tag->AttributeTag->Attribute->Event->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'),
|
||||
|
@ -512,6 +519,39 @@ class TagsController extends AppController
|
|||
$this->render('/Attributes/ajax/ajaxAttributeTags');
|
||||
}
|
||||
|
||||
public function showTagControllerTag($id)
|
||||
{
|
||||
$this->loadModel('TagCollection');
|
||||
$tagCollection = $this->TagCollection->find('first', array(
|
||||
'recursive' => -1,
|
||||
'contain' => array('TagCollection'),
|
||||
'conditions' => array('TagCollection.id' => $id)
|
||||
));
|
||||
if (empty($tagCollection) || (!$this->_isSiteAdmin() && $tagCollection['org_id'] !== $this->Auth->user('org_id'))) {
|
||||
throw new MethodNotAllowedException('Invalid tag_collection.');
|
||||
}
|
||||
$this->loadModel('GalaxyCluster');
|
||||
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.id', 'GalaxyCluster.tag_name')));
|
||||
$this->helpers[] = 'TextColour';
|
||||
$tags = $this->TagCollection->TagCollectionTag->find('all', array(
|
||||
'conditions' => array(
|
||||
'tag_collection_id' => $id,
|
||||
'Tag.name !=' => $cluster_names
|
||||
),
|
||||
'contain' => array('Tag'),
|
||||
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
|
||||
));
|
||||
$this->set('tags', $tags);
|
||||
$event = $this->Tag->EventTag->Event->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'),
|
||||
'conditions' => array('Event.id' => $id)
|
||||
));
|
||||
$this->set('event', $event);
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/Events/ajax/ajaxTags');
|
||||
}
|
||||
|
||||
public function viewTag($id)
|
||||
{
|
||||
$tag = $this->Tag->find('first', array(
|
||||
|
@ -527,109 +567,206 @@ class TagsController extends AppController
|
|||
}
|
||||
|
||||
|
||||
public function selectTaxonomy($id, $attributeTag = false)
|
||||
public function selectTaxonomy($id, $scope = 'event')
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
|
||||
throw new NotFoundException('You don\'t have permission to do that.');
|
||||
}
|
||||
|
||||
$items = array();
|
||||
$favourites = $this->Tag->FavouriteTag->find('count', array('conditions' => array('FavouriteTag.user_id' => $this->Auth->user('id'))));
|
||||
if ($favourites) {
|
||||
$items[] = array(
|
||||
'name' => __('Favourite Tags'),
|
||||
'value' => "/tags/selectTag/" . h($id) . "/favourites/" . h($scope)
|
||||
);
|
||||
}
|
||||
if ($scope !== 'tag_collection') {
|
||||
$items[] = array(
|
||||
'name' => __('Tag Collections'),
|
||||
'value' => "/tags/selectTag/" . h($id) . "/collections/" . h($scope)
|
||||
);
|
||||
}
|
||||
$items[] = array(
|
||||
'name' => __('All Tags'),
|
||||
'value' => "/tags/selectTag/" . h($id) . "/all/" . h($scope)
|
||||
);
|
||||
|
||||
$this->loadModel('Taxonomy');
|
||||
$options = $this->Taxonomy->find('list', array('conditions' => array('enabled' => true), 'fields' => array('namespace'), 'order' => array('Taxonomy.namespace ASC')));
|
||||
foreach ($options as $k => $option) {
|
||||
$tags = $this->Taxonomy->getTaxonomyTags($k, false, true);
|
||||
if (empty($tags)) {
|
||||
unset($options[$k]);
|
||||
if (!empty($tags)) {
|
||||
$items[] = array(
|
||||
'name' => __('Taxonomy Library') . ":" . h($option),
|
||||
'value' => "/tags/selectTag/" . h($id) . "/" . h($k) . "/" . h($scope)
|
||||
);
|
||||
}
|
||||
}
|
||||
if ($attributeTag !== false) {
|
||||
$this->set('attributeTag', true);
|
||||
}
|
||||
$this->set('object_id', $id);
|
||||
$this->set('options', $options);
|
||||
$this->set('favourites', $favourites);
|
||||
$this->render('ajax/taxonomy_choice');
|
||||
$this->set('items', $items);
|
||||
$this->set('options', array( // set chosen (select picker) options
|
||||
'select_options' => array(
|
||||
'multiple' => 0,
|
||||
),
|
||||
));
|
||||
$this->render('/Elements/generic_picker');
|
||||
}
|
||||
|
||||
public function selectTag($id, $taxonomy_id, $attributeTag = false, $filterData = '')
|
||||
public function selectTag($id, $taxonomy_id, $scope = 'event', $filterData = '')
|
||||
{
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
|
||||
throw new NotFoundException('You don\'t have permission to do that.');
|
||||
}
|
||||
$this->loadModel('Taxonomy');
|
||||
$expanded = array();
|
||||
if ($taxonomy_id === '0') {
|
||||
$options = $this->Taxonomy->getAllTaxonomyTags(true);
|
||||
$expanded = $options;
|
||||
} elseif ($taxonomy_id === 'favourites') {
|
||||
$conditions = array('FavouriteTag.user_id' => $this->Auth->user('id'));
|
||||
$tags = $this->Tag->FavouriteTag->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag.name')
|
||||
));
|
||||
foreach ($tags as $tag) {
|
||||
$options[$tag['FavouriteTag']['tag_id']] = $tag['Tag']['name'];
|
||||
$expanded = $options;
|
||||
}
|
||||
} elseif ($taxonomy_id === 'all') {
|
||||
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
|
||||
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
|
||||
$conditions['Tag.hide_tag'] = 0;
|
||||
$options = $this->Tag->find('list', array('fields' => array('Tag.name'), 'conditions' => $conditions));
|
||||
$expanded = $options;
|
||||
} else {
|
||||
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
|
||||
$options = array();
|
||||
foreach ($taxonomies['entries'] as $entry) {
|
||||
if (!empty($entry['existing_tag']['Tag'])) {
|
||||
$options[$entry['existing_tag']['Tag']['id']] = $entry['existing_tag']['Tag']['name'];
|
||||
$expanded[$entry['existing_tag']['Tag']['id']] = $entry['expanded'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unset all tags that this user cannot use for tagging, determined by the org restriction on tags
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$banned_tags = $this->Tag->find('list', array(
|
||||
'conditions' => array(
|
||||
'NOT' => array(
|
||||
'Tag.org_id' => array(
|
||||
0,
|
||||
$this->Auth->user('org_id')
|
||||
),
|
||||
'Tag.user_id' => array(
|
||||
0,
|
||||
$this->Auth->user('id')
|
||||
)
|
||||
)
|
||||
),
|
||||
'fields' => array('Tag.id')
|
||||
));
|
||||
foreach ($banned_tags as $banned_tag) {
|
||||
unset($options[$banned_tag]);
|
||||
unset($expanded[$banned_tag]);
|
||||
}
|
||||
}
|
||||
$hidden_tags = $this->Tag->find('list', array(
|
||||
'conditions' => array('Tag.hide_tag' => 1),
|
||||
$banned_tags = $this->Tag->find('list', array(
|
||||
'conditions' => array(
|
||||
'NOT' => array(
|
||||
'Tag.org_id' => array(
|
||||
0,
|
||||
$this->Auth->user('org_id')
|
||||
),
|
||||
'Tag.user_id' => array(
|
||||
0,
|
||||
$this->Auth->user('id')
|
||||
)
|
||||
)
|
||||
),
|
||||
'fields' => array('Tag.id')
|
||||
));
|
||||
foreach ($hidden_tags as $hidden_tag) {
|
||||
unset($options[$hidden_tag]);
|
||||
unset($expanded[$hidden_tag]);
|
||||
}
|
||||
if ($attributeTag !== false && $attributeTag !== "false") {
|
||||
$this->set('attributeTag', true);
|
||||
}
|
||||
$this->set('object_id', $id);
|
||||
foreach ($options as $k => $v) {
|
||||
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
|
||||
unset($options[$k]);
|
||||
$this->set('taxonomy_id', $taxonomy_id);
|
||||
if ($taxonomy_id === 'collections') {
|
||||
$this->loadModel('TagCollection');
|
||||
$tagCollections = $this->TagCollection->fetchTagCollection($this->Auth->user());
|
||||
$tags = array();
|
||||
$inludedTagListString = array();
|
||||
$expanded = array();
|
||||
foreach ($tagCollections as &$tagCollection) {
|
||||
$tags[$tagCollection['TagCollection']['id']] = $tagCollection['TagCollection'];
|
||||
$expanded[$tagCollection['TagCollection']['id']] = empty($tagCollection['TagCollection']['description']) ? $tagCollection['TagCollection']['name'] : $tagCollection['TagCollection']['description'];
|
||||
if (!empty($tagCollection['TagCollectionTag'])) {
|
||||
$tagList = array();
|
||||
foreach ($tagCollection['TagCollectionTag'] as $k => $tce) {
|
||||
if (in_array($tce['tag_id'], $banned_tags)) {
|
||||
unset($tagCollection['TagCollectionTag'][$k]);
|
||||
} else {
|
||||
$tagList[] = $tce['Tag']['name'];
|
||||
}
|
||||
$tagCollection['TagCollectionTag'] = array_values($tagCollection['TagCollectionTag']);
|
||||
}
|
||||
$tagList = implode(', ', $tagList);
|
||||
$inludedTagListString[$tagCollection['TagCollection']['id']] = $tagList;
|
||||
$expanded[$tagCollection['TagCollection']['id']] .= sprintf(' (%s)', $tagList);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($taxonomy_id === '0') {
|
||||
$tags = $this->Taxonomy->getAllTaxonomyTags(true);
|
||||
$expanded = $tags;
|
||||
} elseif ($taxonomy_id === 'favourites') {
|
||||
$tags = array();
|
||||
$conditions = array('FavouriteTag.user_id' => $this->Auth->user('id'));
|
||||
$favTags = $this->Tag->FavouriteTag->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1,
|
||||
'contain' => array('Tag'),
|
||||
'order' => array('Tag.name asc')
|
||||
));
|
||||
foreach ($favTags as $favTag) {
|
||||
$tags[$favTag['FavouriteTag']['tag_id']] = $favTag['Tag'];
|
||||
$expanded = $tags;
|
||||
}
|
||||
} elseif ($taxonomy_id === 'all') {
|
||||
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
|
||||
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
|
||||
$conditions['Tag.hide_tag'] = 0;
|
||||
$allTags = $this->Tag->find('all', array('conditions' => $conditions, 'recursive' => -1, 'order' => array('name asc')));
|
||||
$allTags = $this->Tag->EventTag->Event->massageTags(array('EventTag' => $allTags), 'Event', false);
|
||||
$allTags = $allTags['EventTag'];
|
||||
$tags = array();
|
||||
foreach ($allTags as $i => $tag) {
|
||||
if (!empty($tag['Tag'])) {
|
||||
$tags[$tag['Tag']['id']] = $tag['Tag'];
|
||||
}
|
||||
}
|
||||
unset($allTags);
|
||||
$expanded = $tags;
|
||||
} else {
|
||||
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
|
||||
$tags = array();
|
||||
if (!empty($taxonomies['entries'])) {
|
||||
foreach ($taxonomies['entries'] as $entry) {
|
||||
if (!empty($entry['existing_tag']['Tag'])) {
|
||||
$tags[$entry['existing_tag']['Tag']['id']] = $entry['existing_tag']['Tag'];
|
||||
$expanded[$entry['existing_tag']['Tag']['id']] = $entry['expanded'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unset all tags that this user cannot use for tagging, determined by the org restriction on tags
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
foreach ($banned_tags as $banned_tag) {
|
||||
unset($tags[$banned_tag]);
|
||||
unset($expanded[$banned_tag]);
|
||||
}
|
||||
}
|
||||
$hidden_tags = $this->Tag->find('list', array(
|
||||
'conditions' => array('Tag.hide_tag' => 1),
|
||||
'fields' => array('Tag.id')
|
||||
));
|
||||
foreach ($hidden_tags as $hidden_tag) {
|
||||
unset($tags[$hidden_tag]);
|
||||
unset($expanded[$hidden_tag]);
|
||||
}
|
||||
}
|
||||
$this->set('options', $options);
|
||||
$this->set('expanded', $expanded);
|
||||
$this->set('custom', $taxonomy_id == 0 ? true : false);
|
||||
$this->set('filterData', $filterData);
|
||||
|
||||
$this->set('scope', $scope);
|
||||
$this->set('object_id', $id);
|
||||
|
||||
if ($scope === 'attribute') {
|
||||
$onClickForm = 'quickSubmitAttributeTagForm';
|
||||
} elseif ($scope === 'tag_collection') {
|
||||
$onClickForm = 'quickSubmitTagCollectionTagForm';
|
||||
} else {
|
||||
$onClickForm = 'quickSubmitTagForm';
|
||||
}
|
||||
|
||||
$items = array();
|
||||
foreach ($tags as $k => $tag) {
|
||||
$tagName = $tag['name'];
|
||||
$choice_id = $k;
|
||||
if ($taxonomy_id === 'collections') {
|
||||
$choice_id = 'collection_' . $choice_id;
|
||||
}
|
||||
|
||||
$itemParam = array(
|
||||
'name' => $tagName,
|
||||
'value' => $choice_id,
|
||||
'template' => array(
|
||||
'name' => array(
|
||||
'name' => $tagName,
|
||||
'label' => array(
|
||||
'background' => isset($tag['colour']) ? $tag['colour'] : '#ffffff'
|
||||
)
|
||||
),
|
||||
'infoExtra' => $expanded[$tag['id']]
|
||||
)
|
||||
);
|
||||
if ($taxonomy_id === 'collections') {
|
||||
$itemParam['template']['infoContextual'] = __('Includes: ') . $inludedTagListString[$tag['id']];
|
||||
}
|
||||
$items[] = $itemParam;
|
||||
}
|
||||
$this->set('items', $items);
|
||||
$this->set('options', array( // set chosen (select picker) options
|
||||
'functionName' => $onClickForm,
|
||||
'multiple' => -1,
|
||||
'select_options' => array(
|
||||
'additionalData' => array(
|
||||
'id' => $id
|
||||
),
|
||||
),
|
||||
));
|
||||
$this->render('ajax/select_tag');
|
||||
}
|
||||
|
||||
|
@ -804,6 +941,18 @@ class TagsController extends AppController
|
|||
}
|
||||
$result = $this->$objectType->$connectorObject->save($data);
|
||||
if ($result) {
|
||||
$tempObject = $this->$objectType->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array($objectType . '.id' => $object[$objectType]['id'])
|
||||
));
|
||||
$date = new DateTime();
|
||||
$tempObject[$objectType]['timestamp'] = $date->getTimestamp();
|
||||
$this->$objectType->save($tempObject);
|
||||
if ($objectType === 'Attribute') {
|
||||
$this->$objectType->Event->unpublishEvent($object['Event']['id']);
|
||||
} else if ($objectType === 'Event') {
|
||||
$this->Event->unpublishEvent($object['Event']['id']);
|
||||
}
|
||||
$message = 'Tag ' . $existingTag['Tag']['name'] . '(' . $existingTag['Tag']['id'] . ') successfully attached to ' . $objectType . '(' . $object[$objectType]['id'] . ').';
|
||||
return $this->RestResponse->saveSuccessResponse('Tags', 'attachTagToObject', false, $this->response->type(), $message);
|
||||
} else {
|
||||
|
@ -885,4 +1034,55 @@ class TagsController extends AppController
|
|||
$this->set('id', $id);
|
||||
$this->render('/Events/view_graph');
|
||||
}
|
||||
|
||||
public function search($tag = false)
|
||||
{
|
||||
if (isset($this->request->data['Tag'])) {
|
||||
$this->request->data = $this->request->data['Tag'];
|
||||
}
|
||||
if (!empty($this->request->data['tag'])) {
|
||||
$tag = $this->request->data['tag'];
|
||||
} else if (!empty($this->request->data)) {
|
||||
$tag = $this->request->data;
|
||||
}
|
||||
if (!is_array($tag)) {
|
||||
$tag = array($tag);
|
||||
}
|
||||
foreach ($tag as $k => $t) {
|
||||
$tag[$k] = strtolower($t);
|
||||
}
|
||||
$this->loadModel('GalaxyCluster');
|
||||
$conditions = array('OR' => array('LOWER(GalaxyCluster.value) LIKE' => $t, array('GalaxyElement.key' => 'synonyms', 'OR' => array())));
|
||||
foreach ($tag as $k => $t) {
|
||||
$conditions['OR'][0]['OR'][] = array('LOWER(GalaxyElement.value) LIKE' => $t);
|
||||
}
|
||||
$elements = $this->GalaxyCluster->GalaxyElement->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions,
|
||||
'contain' => array('GalaxyCluster.tag_name')
|
||||
));
|
||||
foreach ($elements as $element) {
|
||||
$tag[] = strtolower($element['GalaxyCluster']['tag_name']);
|
||||
}
|
||||
$conditions = array();
|
||||
foreach ($tag as $k => $t) {
|
||||
$conditions['OR'][] = array('LOWER(Tag.name) LIKE' => $t);
|
||||
}
|
||||
$tags = $this->Tag->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1
|
||||
));
|
||||
$this->loadModel('Taxonomy');
|
||||
foreach ($tags as $k => $t) {
|
||||
$taxonomy = $this->Taxonomy->getTaxonomyForTag($t['Tag']['name'], true);
|
||||
if (!empty($taxonomy)) {
|
||||
$tags[$k]['Taxonomy'] = $taxonomy['Taxonomy'];
|
||||
}
|
||||
$cluster = $this->GalaxyCluster->getCluster($t['Tag']['name']);
|
||||
if (!empty($cluster)) {
|
||||
$tags[$k]['GalaxyCluster'] = $cluster['GalaxyCluster'];
|
||||
}
|
||||
}
|
||||
return $this->RestResponse->viewData($tags, $this->response->type());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class TaxonomiesController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'contain' => array(
|
||||
'TaxonomyPredicate' => array(
|
||||
'fields' => array('TaxonomyPredicate.id'),
|
||||
|
@ -119,6 +119,7 @@ class TaxonomiesController extends AppController
|
|||
'recursive' => -1,
|
||||
'conditions' => array('Taxonomy.id' => $id),
|
||||
));
|
||||
$this->Taxonomy->disableTags($id);
|
||||
$taxonomy['Taxonomy']['enabled'] = 0;
|
||||
$this->Taxonomy->save($taxonomy);
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
|
|
|
@ -1065,7 +1065,11 @@ class UsersController extends AppController
|
|||
public function routeafterlogin()
|
||||
{
|
||||
// Events list
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index'));
|
||||
$url = $this->Session->consume('pre_login_requested_url');
|
||||
if (empty($url)) {
|
||||
$url = array('controller' => 'events', 'action' => 'index');
|
||||
}
|
||||
$this->redirect($url);
|
||||
}
|
||||
|
||||
public function logout()
|
||||
|
@ -1375,70 +1379,110 @@ class UsersController extends AppController
|
|||
$this->set('user', $user);
|
||||
}
|
||||
|
||||
public function admin_email()
|
||||
public function admin_email($isPreview=false)
|
||||
{
|
||||
if (!$this->_isAdmin()) {
|
||||
throw new MethodNotAllowedException();
|
||||
}
|
||||
// User has filled in his contact form, send out the email.
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array('org_id' => $this->Auth->user('org_id'));
|
||||
}
|
||||
if ($this->request->data['User']['recipient'] != 1) {
|
||||
$conditions['id'] = $this->request->data['User']['recipientEmailList'];
|
||||
}
|
||||
$conditions['AND'][] = array('User.disabled' => 0);
|
||||
$users = $this->User->find('all', array('recursive' => -1, 'order' => array('email ASC'), 'conditions' => $conditions));
|
||||
$this->request->data['User']['message'] = $this->User->adminMessageResolve($this->request->data['User']['message']);
|
||||
$failures = '';
|
||||
foreach ($users as $user) {
|
||||
$password = $this->User->generateRandomPassword();
|
||||
$body = str_replace('$password', $password, $this->request->data['User']['message']);
|
||||
$body = str_replace('$username', $user['User']['email'], $body);
|
||||
$result = $this->User->sendEmail($user, $body, false, $this->request->data['User']['subject']);
|
||||
// if sending successful and action was a password change, update the user's password.
|
||||
if ($result && $this->request->data['User']['action'] != '0') {
|
||||
$this->User->id = $user['User']['id'];
|
||||
$this->User->saveField('password', $password);
|
||||
$this->User->saveField('change_pw', '1');
|
||||
}
|
||||
if (!$result) {
|
||||
if ($failures != '') {
|
||||
$failures .= ', ';
|
||||
}
|
||||
$failures .= $user['User']['email'];
|
||||
}
|
||||
}
|
||||
if ($failures != '') {
|
||||
$this->Flash->success(__('E-mails sent, but failed to deliver the messages to the following recipients: ' . $failures));
|
||||
} else {
|
||||
$this->Flash->success(__('E-mails sent.'));
|
||||
}
|
||||
}
|
||||
$isPostOrPut = $this->request->is('post') || $this->request->is('put');
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array('org_id' => $this->Auth->user('org_id'));
|
||||
}
|
||||
$conditions['User.disabled'] = 0;
|
||||
$temp = $this->User->find('all', array('recursive' => -1, 'fields' => array('id', 'email'), 'order' => array('email ASC'), 'conditions' => $conditions));
|
||||
$emails = array();
|
||||
// save all the emails of the users and set it for the dropdown list in the form
|
||||
foreach ($temp as $user) {
|
||||
$emails[$user['User']['id']] = $user['User']['email'];
|
||||
|
||||
// harvest parameters
|
||||
if ($isPostOrPut) {
|
||||
$recipient = $this->request->data['User']['recipient'];
|
||||
} else {
|
||||
$recipient = isset($this->request->query['recipient']) ? $this->request->query['recipient'] : null;
|
||||
}
|
||||
$this->set('users', $temp);
|
||||
$this->set('recipientEmail', $emails);
|
||||
$this->set('org', Configure::read('MISP.org'));
|
||||
$textsToFetch = array('newUserText', 'passwordResetText');
|
||||
$this->loadModel('Server');
|
||||
foreach ($textsToFetch as $text) {
|
||||
${$text} = Configure::read('MISP.' . $text);
|
||||
if (!${$text}) {
|
||||
${$text} = $this->Server->serverSettings['MISP'][$text]['value'];
|
||||
if ($isPostOrPut) {
|
||||
$recipientEmailList = $this->request->data['User']['recipientEmailList'];
|
||||
} else {
|
||||
$recipientEmailList = isset($this->request->query['recipientEmailList']) ? $this->request->query['recipientEmailList'] : null;
|
||||
}
|
||||
if ($isPostOrPut) {
|
||||
$orgNameList = $this->request->data['User']['orgNameList'];
|
||||
} else {
|
||||
$orgNameList = isset($this->request->query['orgNameList']) ? $this->request->query['orgNameList'] : null;
|
||||
}
|
||||
|
||||
if (!is_null($recipient) && $recipient == 0) {
|
||||
if (is_null($recipientEmailList)) {
|
||||
throw new NotFoundException(__('Recipient email not provided'));
|
||||
}
|
||||
$conditions['id'] = $recipientEmailList;
|
||||
} elseif (!is_null($recipient) && $recipient == 2) {
|
||||
if (is_null($orgNameList)) {
|
||||
throw new NotFoundException(__('Recipient organisation not provided'));
|
||||
}
|
||||
$conditions['org_id'] = $orgNameList;
|
||||
}
|
||||
$conditions['AND'][] = array('User.disabled' => 0);
|
||||
|
||||
// Allow to mimic real form post
|
||||
if ($isPreview) {
|
||||
$users = $this->User->find('list', array('recursive' => -1, 'order' => array('email ASC'), 'conditions' => $conditions, 'fields' => array('email')));
|
||||
$this->set('emails', $users);
|
||||
$this->set('emailsCount', count($users));
|
||||
$this->render('ajax/emailConfirmTemplate');
|
||||
} else {
|
||||
$users = $this->User->find('all', array('recursive' => -1, 'order' => array('email ASC'), 'conditions' => $conditions));
|
||||
// User has filled in his contact form, send out the email.
|
||||
if ($isPostOrPut) {
|
||||
$this->request->data['User']['message'] = $this->User->adminMessageResolve($this->request->data['User']['message']);
|
||||
$failures = '';
|
||||
foreach ($users as $user) {
|
||||
$password = $this->User->generateRandomPassword();
|
||||
$body = str_replace('$password', $password, $this->request->data['User']['message']);
|
||||
$body = str_replace('$username', $user['User']['email'], $body);
|
||||
$result = $this->User->sendEmail($user, $body, false, $this->request->data['User']['subject']);
|
||||
// if sending successful and action was a password change, update the user's password.
|
||||
if ($result && $this->request->data['User']['action'] != '0') {
|
||||
$this->User->id = $user['User']['id'];
|
||||
$this->User->saveField('password', $password);
|
||||
$this->User->saveField('change_pw', '1');
|
||||
}
|
||||
if (!$result) {
|
||||
if ($failures != '') {
|
||||
$failures .= ', ';
|
||||
}
|
||||
$failures .= $user['User']['email'];
|
||||
}
|
||||
}
|
||||
if ($failures != '') {
|
||||
$this->Flash->success(__('E-mails sent, but failed to deliver the messages to the following recipients: ' . $failures));
|
||||
} else {
|
||||
$this->Flash->success(__('E-mails sent.'));
|
||||
}
|
||||
}
|
||||
$conditions = array();
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions = array('org_id' => $this->Auth->user('org_id'));
|
||||
}
|
||||
$conditions['User.disabled'] = 0;
|
||||
$temp = $this->User->find('all', array('recursive' => -1, 'fields' => array('id', 'email', 'Organisation.name'), 'order' => array('email ASC'), 'conditions' => $conditions, 'contain' => array('Organisation')));
|
||||
$emails = array();
|
||||
$orgName = array();
|
||||
// save all the emails of the users and set it for the dropdown list in the form
|
||||
foreach ($temp as $user) {
|
||||
$emails[$user['User']['id']] = $user['User']['email'];
|
||||
$orgName[$user['Organisation']['id']] = $user['Organisation']['name'];
|
||||
}
|
||||
|
||||
$this->set('users', $temp);
|
||||
$this->set('recipientEmail', $emails);
|
||||
$this->set('orgName', $orgName);
|
||||
$this->set('org', Configure::read('MISP.org'));
|
||||
$textsToFetch = array('newUserText', 'passwordResetText');
|
||||
$this->loadModel('Server');
|
||||
foreach ($textsToFetch as $text) {
|
||||
${$text} = Configure::read('MISP.' . $text);
|
||||
if (!${$text}) {
|
||||
${$text} = $this->Server->serverSettings['MISP'][$text]['value'];
|
||||
}
|
||||
$this->set($text, ${$text});
|
||||
}
|
||||
$this->set($text, ${$text});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1521,12 +1565,16 @@ class UsersController extends AppController
|
|||
// set all of the data up for the heatmaps
|
||||
$params = array(
|
||||
'fields' => array('name'),
|
||||
'recursive' => -1
|
||||
'recursive' => -1,
|
||||
'conditions' => array()
|
||||
);
|
||||
if (!$this->_isSiteAdmin() && !empty(Configure::read('Security.hide_organisation_index_from_users'))) {
|
||||
$params['conditions'] = array('Organisation.id' => $this->Auth->user('org_id'));
|
||||
}
|
||||
$orgs = $this->User->Organisation->find('all', $params);
|
||||
$local_orgs_params = $params;
|
||||
$local_orgs_params['conditions']['Organisation.local'] = 1;
|
||||
$local_orgs = $this->User->Organisation->find('all', $local_orgs_params);
|
||||
$this->loadModel('Log');
|
||||
$year = date('Y');
|
||||
$month = date('n');
|
||||
|
@ -1552,7 +1600,10 @@ class UsersController extends AppController
|
|||
$stats['proposal_count'] = $this->User->Event->ShadowAttribute->find('count', array('recursive' => -1));
|
||||
|
||||
$stats['user_count'] = $this->User->find('count', array('recursive' => -1));
|
||||
$stats['user_count_pgp'] = $this->User->find('count', array('recursive' => -1, 'conditions' => array('User.gpgkey !=' => '')));
|
||||
$stats['org_count'] = count($orgs);
|
||||
$stats['local_org_count'] = count($local_orgs);
|
||||
$stats['average_user_per_org'] = round($stats['user_count'] / $stats['local_org_count'], 1);
|
||||
|
||||
$this->loadModel('Thread');
|
||||
$stats['thread_count'] = $this->Thread->find('count', array('conditions' => array('Thread.post_count >' => 0), 'recursive' => -1));
|
||||
|
@ -1808,23 +1859,68 @@ class UsersController extends AppController
|
|||
{
|
||||
$this->loadModel('Event');
|
||||
$this->loadModel('Galaxy');
|
||||
$attackTacticData = $this->Galaxy->getMitreAttackMatrix();
|
||||
$attackTactic = $attackTacticData['attackTactic'];
|
||||
$attackTags = $attackTacticData['attackTags'];
|
||||
$killChainOrders = $attackTacticData['killChain'];
|
||||
$instanceUUID = $attackTacticData['instance-uuid'];
|
||||
|
||||
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores(0, $attackTags);
|
||||
$scoresDataEvent = $this->Event->EventTag->getTagScores(0, $attackTags);
|
||||
$galaxy_id = $this->Galaxy->getMitreAttackGalaxyId();
|
||||
$matrixData = $this->Galaxy->getMatrix($galaxy_id);
|
||||
|
||||
$tabs = $matrixData['tabs'];
|
||||
$matrixTags = $matrixData['matrixTags'];
|
||||
$killChainOrders = $matrixData['killChain'];
|
||||
$instanceUUID = $matrixData['instance-uuid'];
|
||||
|
||||
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores(0, $matrixTags);
|
||||
$scoresDataEvent = $this->Event->EventTag->getTagScores(0, $matrixTags);
|
||||
$scoresData = array();
|
||||
foreach (array_keys($scoresDataAttr['scores'] + $scoresDataEvent['scores']) as $key) {
|
||||
$scoresData[$key] = (isset($scoresDataAttr['scores'][$key]) ? $scoresDataAttr['scores'][$key] : 0) + (isset($scoresDataEvent['scores'][$key]) ? $scoresDataEvent['scores'][$key] : 0);
|
||||
}
|
||||
$maxScore = max($scoresDataAttr['maxScore'], $scoresDataEvent['maxScore']);
|
||||
$scores = $scoresData;
|
||||
// FIXME: temporary fix: add the score of deprecated mitre galaxies to the new one (for the stats)
|
||||
if ($matrixData['galaxy']['id'] == $galaxy_id) {
|
||||
$mergedScore = array();
|
||||
foreach ($scoresData as $tag => $v) {
|
||||
$predicateValue = explode(':', $tag, 2)[1];
|
||||
$predicateValue = explode('=', $predicateValue, 2);
|
||||
$predicate = $predicateValue[0];
|
||||
$clusterValue = $predicateValue[1];
|
||||
$mappedTag = '';
|
||||
$mappingWithoutExternalId = array();
|
||||
if ($predicate == 'mitre-attack-pattern') {
|
||||
$mappedTag = $tag;
|
||||
$name = explode(" ", $tag);
|
||||
$name = join(" ", array_slice($name, 0, -2)); // remove " - external_id"
|
||||
$mappingWithoutExternalId[$name] = $tag;
|
||||
} else {
|
||||
$name = explode(" ", $clusterValue);
|
||||
$name = join(" ", array_slice($name, 0, -2)); // remove " - external_id"
|
||||
if (isset($mappingWithoutExternalId[$name])) {
|
||||
$mappedTag = $mappingWithoutExternalId[$name];
|
||||
} else {
|
||||
$adjustedTagName = $this->Galaxy->GalaxyCluster->find('list', array(
|
||||
'group' => array('GalaxyCluster.id', 'GalaxyCluster.tag_name'),
|
||||
'conditions' => array('GalaxyCluster.tag_name LIKE' => 'misp-galaxy:mitre-attack-pattern=' . $name . '% T%'),
|
||||
'fields' => array('GalaxyCluster.tag_name')
|
||||
));
|
||||
$adjustedTagName = array_values($adjustedTagName)[0];
|
||||
$mappingWithoutExternalId[$name] = $adjustedTagName;
|
||||
$mappedTag = $mappingWithoutExternalId[$name];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($mergedScore[$mappedTag])) {
|
||||
$mergedScore[$mappedTag] += $v;
|
||||
} else {
|
||||
$mergedScore[$mappedTag] = $v;
|
||||
}
|
||||
}
|
||||
$scores = $mergedScore;
|
||||
$maxScore = max(array_values($mergedScore));
|
||||
}
|
||||
// end FIXME
|
||||
|
||||
if ($this->_isRest()) {
|
||||
$json = array('matrix' => $attackTactic, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
|
||||
$json = array('matrix' => $tabs, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
|
||||
return $this->RestResponse->viewData($json, $this->response->type());
|
||||
} else {
|
||||
App::uses('ColourGradientTool', 'Tools');
|
||||
|
@ -1832,12 +1928,17 @@ class UsersController extends AppController
|
|||
$colours = $gradientTool->createGradientFromValues($scores);
|
||||
|
||||
$this->set('target_type', 'attribute');
|
||||
$this->set('killChainOrders', $killChainOrders);
|
||||
$this->set('attackTactic', $attackTactic);
|
||||
$this->set('columnOrders', $killChainOrders);
|
||||
$this->set('tabs', $tabs);
|
||||
$this->set('scores', $scores);
|
||||
$this->set('maxScore', $maxScore);
|
||||
$this->set('colours', $colours);
|
||||
if (!empty($colours)) {
|
||||
$this->set('colours', $colours['mapping']);
|
||||
$this->set('interpolation', $colours['interpolation']);
|
||||
}
|
||||
$this->set('pickingMode', false);
|
||||
$this->set('defaultTabName', "mitre-attack");
|
||||
$this->set('removeTrailling', 2);
|
||||
|
||||
$this->render('statistics_attackmatrix');
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class WarninglistsController extends AppController
|
|||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'contain' => array(
|
||||
'WarninglistType'
|
||||
),
|
||||
|
@ -117,45 +117,45 @@ class WarninglistsController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* toggle warninglists on or offset
|
||||
* Simply POST an ID or a list of IDs to toggle the current state
|
||||
* To control what state the warninglists should have after execution instead of just blindly toggling them, simply pass the enabled flag
|
||||
* Example:
|
||||
* {"id": [5, 8], "enabled": 1}
|
||||
/*
|
||||
* toggle warninglists on or offset
|
||||
* Simply POST an ID or a list of IDs to toggle the current state
|
||||
* To control what state the warninglists should have after execution instead of just blindly toggling them, simply pass the enabled flag
|
||||
* Example:
|
||||
* {"id": [5, 8], "enabled": 1}
|
||||
* Alternatively search by a substring in the warninglist's named, such as:
|
||||
* {"name": ["%alexa%", "%iana%"], "enabled": 1}
|
||||
*/
|
||||
*/
|
||||
public function toggleEnable()
|
||||
{
|
||||
if (!$this->request->is('post')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'This function only accepts POST requests.')), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
if (isset($this->request->data['Warninglist']['data'])) {
|
||||
$id = $this->request->data['Warninglist']['data'];
|
||||
} else {
|
||||
if (!empty($this->request->data['id'])) {
|
||||
$id = $this->request->data['id'];
|
||||
} else if (!empty($this->request->data['name'])) {
|
||||
if (!is_array($this->request->data['name'])) {
|
||||
$names = array($this->request->data['name']);
|
||||
} else {
|
||||
$names = $this->request->data['name'];
|
||||
}
|
||||
$conditions = array();
|
||||
foreach ($names as $k => $name) {
|
||||
$conditions['OR'][] = array('LOWER(Warninglist.name) LIKE' => strtolower($name));
|
||||
}
|
||||
$id = $this->Warninglist->find('list', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1,
|
||||
'fields' => array('Warninglist.id', 'Warninglist.id')
|
||||
));
|
||||
}
|
||||
}
|
||||
if (isset($this->request->data['enabled'])) {
|
||||
$enabled = $this->request->data['enabled'];
|
||||
}
|
||||
if (!$this->request->is('post')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'This function only accepts POST requests.')), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
if (isset($this->request->data['Warninglist']['data'])) {
|
||||
$id = $this->request->data['Warninglist']['data'];
|
||||
} else {
|
||||
if (!empty($this->request->data['id'])) {
|
||||
$id = $this->request->data['id'];
|
||||
} elseif (!empty($this->request->data['name'])) {
|
||||
if (!is_array($this->request->data['name'])) {
|
||||
$names = array($this->request->data['name']);
|
||||
} else {
|
||||
$names = $this->request->data['name'];
|
||||
}
|
||||
$conditions = array();
|
||||
foreach ($names as $k => $name) {
|
||||
$conditions['OR'][] = array('LOWER(Warninglist.name) LIKE' => strtolower($name));
|
||||
}
|
||||
$id = $this->Warninglist->find('list', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1,
|
||||
'fields' => array('Warninglist.id', 'Warninglist.id')
|
||||
));
|
||||
}
|
||||
}
|
||||
if (isset($this->request->data['enabled'])) {
|
||||
$enabled = $this->request->data['enabled'];
|
||||
}
|
||||
if (empty($id)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Warninglist not found.')), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
@ -163,28 +163,28 @@ class WarninglistsController extends AppController
|
|||
if (empty($currentState)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Warninglist(s) not found.')), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
$success = 0;
|
||||
foreach ($currentState as $warningList) {
|
||||
if (isset($enabled)) {
|
||||
$warningList['Warninglist']['enabled'] = $enabled;
|
||||
$message = $enabled ? 'enabled' : 'disabled';
|
||||
} else {
|
||||
if ($warningList['Warninglist']['enabled']) {
|
||||
$warningList['Warninglist']['enabled'] = 0;
|
||||
$message = 'disabled';
|
||||
} else {
|
||||
$warningList['Warninglist']['enabled'] = 1;
|
||||
$message = 'enabled';
|
||||
}
|
||||
if (!isset($enabled) && count($currentState) > 1) {
|
||||
$message = 'toggled';
|
||||
}
|
||||
}
|
||||
if ($this->Warninglist->save($warningList)) {
|
||||
$success += 1;
|
||||
}
|
||||
$this->Warninglist->regenerateWarninglistCaches($warningList['Warninglist']['id']);
|
||||
}
|
||||
$success = 0;
|
||||
foreach ($currentState as $warningList) {
|
||||
if (isset($enabled)) {
|
||||
$warningList['Warninglist']['enabled'] = $enabled;
|
||||
$message = $enabled ? 'enabled' : 'disabled';
|
||||
} else {
|
||||
if ($warningList['Warninglist']['enabled']) {
|
||||
$warningList['Warninglist']['enabled'] = 0;
|
||||
$message = 'disabled';
|
||||
} else {
|
||||
$warningList['Warninglist']['enabled'] = 1;
|
||||
$message = 'enabled';
|
||||
}
|
||||
if (!isset($enabled) && count($currentState) > 1) {
|
||||
$message = 'toggled';
|
||||
}
|
||||
}
|
||||
if ($this->Warninglist->save($warningList)) {
|
||||
$success += 1;
|
||||
}
|
||||
$this->Warninglist->regenerateWarninglistCaches($warningList['Warninglist']['id']);
|
||||
}
|
||||
if ($success) {
|
||||
$this->Warninglist->regenerateWarninglistCaches($id);
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $success . ' warninglist(s) ' . $message)), 'status' => 200, 'type' => 'json'));
|
||||
|
@ -259,30 +259,34 @@ class WarninglistsController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
public function checkValue() {
|
||||
if ($this->request->is('post')) {
|
||||
$warninglists = $this->Warninglist->getWarninglists(array());
|
||||
if (empty($this->request->data)) {
|
||||
throw new NotFoundException('No valid data received.');
|
||||
}
|
||||
$data = $this->request->data;
|
||||
if (!is_array($data)) {
|
||||
$data = array($data);
|
||||
}
|
||||
$hits = array();
|
||||
foreach ($data as $dataPoint) {
|
||||
foreach ($warninglists as $warninglist) {
|
||||
$listValues = $this->Warninglist->getWarninglistEntries($warninglist['Warninglist']['id']);
|
||||
$listValues = array_combine($listValues, $listValues);
|
||||
$result = $this->Warninglist->quickCheckValue($listValues, $dataPoint, $warninglist['Warninglist']['type']);
|
||||
if ($result) {
|
||||
$hits[$dataPoint][] = array('id' => $warninglist['Warninglist']['id'], 'name' => $warninglist['Warninglist']['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->RestResponse->viewData($hits, $this->response->type());
|
||||
public function checkValue()
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$warninglists = $this->Warninglist->getWarninglists(array());
|
||||
if (empty($this->request->data)) {
|
||||
throw new NotFoundException('No valid data received.');
|
||||
}
|
||||
$data = $this->request->data;
|
||||
if (!is_array($data)) {
|
||||
$data = array($data);
|
||||
}
|
||||
if (array_key_exists('[]', $data)) {
|
||||
$data = $data['[]'];
|
||||
}
|
||||
$hits = array();
|
||||
foreach ($data as $dataPoint) {
|
||||
foreach ($warninglists as $warninglist) {
|
||||
$listValues = $this->Warninglist->getWarninglistEntries($warninglist['Warninglist']['id']);
|
||||
$listValues = array_combine($listValues, $listValues);
|
||||
$result = $this->Warninglist->quickCheckValue($listValues, $dataPoint, $warninglist['Warninglist']['type']);
|
||||
if ($result) {
|
||||
$hits[$dataPoint][] = array('id' => $warninglist['Warninglist']['id'], 'name' => $warninglist['Warninglist']['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->RestResponse->viewData($hits, $this->response->type());
|
||||
} else {
|
||||
return $this->RestResponse->describe('Warninglists', 'checkValue', false, $this->response->type());
|
||||
return $this->RestResponse->describe('Warninglists', 'checkValue', false, $this->response->type());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ class BroExport
|
|||
'sha512/224' => array('brotype' => 'FILE_HASH'),
|
||||
'sha512/256' => array('brotype' => 'FILE_HASH'),
|
||||
'tlsh' => array('brotype' => 'FILE_HASH'),
|
||||
'cdhash' => array('brotype' => 'FILE_HASH'),
|
||||
'filename|authentihash' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
|
||||
'filename|ssdeep' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
|
||||
'filename|imphash' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
|
||||
|
@ -133,7 +134,22 @@ class BroExport
|
|||
|
||||
private $whitelist = null;
|
||||
|
||||
public function export($items, $orgs, $valueField, $whitelist, $instanceString)
|
||||
public function handler($data, $options = array())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return "\n";
|
||||
}
|
||||
|
||||
public function separator()
|
||||
{
|
||||
return "\n";
|
||||
}
|
||||
|
||||
public function export($items, $orgs, $valueField, $whitelist = array(), $instanceString)
|
||||
{
|
||||
$intel = array();
|
||||
//For bro format organisation
|
||||
|
@ -155,10 +171,10 @@ class BroExport
|
|||
return $intel;
|
||||
}
|
||||
|
||||
private function __generateRule($attribute, $ruleFormat, $valueField, $whitelist)
|
||||
private function __generateRule($attribute, $ruleFormat, $valueField, $whitelist = array())
|
||||
{
|
||||
if (isset($this->mapping[$attribute['type']])) {
|
||||
if (! $this->checkWhitelist($attribute['value'], $whitelist)) {
|
||||
if (empty($whitelist) || !$this->checkWhitelist($attribute['value'], $whitelist)) {
|
||||
$brotype = $this->mapping[$attribute['type']]['brotype'];
|
||||
if (isset($this->mapping[$attribute['type']]['alternate'])) {
|
||||
if (preg_match($this->mapping[$attribute['type']]['alternate'][0], $attribute['value'])) {
|
||||
|
|
|
@ -15,12 +15,20 @@ class CacheExport
|
|||
throw new MethodNotAllowedException('Invalid hashing algo');
|
||||
}
|
||||
if ($options['scope'] === 'Attribute') {
|
||||
return hash($hash_type, $data['Attribute']['value']);
|
||||
$temp = hash($hash_type, $data['Attribute']['value']);
|
||||
if (!empty($options['filters']['includeEventUuid'])) {
|
||||
$temp .= ',' . $data['Event']['uuid'];
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
if ($options['scope'] === 'Event') {
|
||||
$result = array();
|
||||
foreach ($data['Attribute'] as $attribute) {
|
||||
$result[] = hash($hash_type, $data['Attribute']['value']);
|
||||
$temp = hash($hash_type, $data['Attribute']['value']);
|
||||
if (!empty($options['filters']['includeEventUuid'])) {
|
||||
$temp .= ',' . $data['Event']['uuid'];
|
||||
}
|
||||
$result[] = $temp;
|
||||
}
|
||||
return implode($this->separator(), $result);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ class CsvExport
|
|||
$lines = $this->__attributesHandler($data, $options);
|
||||
} else if($options['scope'] === 'Event') {
|
||||
$lines = $this->__eventsHandler($data, $options);
|
||||
} else if($options['scope'] === 'Sighting') {
|
||||
$lines = $this->__sightingsHandler($data, $options);
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
@ -29,8 +31,6 @@ class CsvExport
|
|||
'Event' => array('fields' => array('Event.*'), 'EventTag' => 'Tag', 'Org.name', 'Orgc.name', 'ThreatLevel')
|
||||
));
|
||||
unset($params['fields']);
|
||||
$params['includeEventUuid'] = 0;
|
||||
$params['includeEventTags'] = 0;
|
||||
$params['withAttachments'] = 0;
|
||||
return $params;
|
||||
}
|
||||
|
@ -46,6 +46,32 @@ class CsvExport
|
|||
return $this->__addLine($attribute, $options);
|
||||
}
|
||||
|
||||
private function __sightingsHandler($sighting, $options)
|
||||
{
|
||||
$lines = '';
|
||||
if (isset($sighting['Sighting']['Event'])) {
|
||||
foreach($sighting['Sighting']['Event'] as $k => $event_val) {
|
||||
$new_key = 'event_' . $k;
|
||||
// in case we have an array, e.g. orc => name
|
||||
if (is_array($event_val)) {
|
||||
$v2 = reset($event_val);
|
||||
$k2 = key($event_val);
|
||||
$new_key .= '_' . $k2;
|
||||
$event_val = $v2;
|
||||
}
|
||||
$sighting['Sighting'][$new_key] = $event_val;
|
||||
}
|
||||
}
|
||||
if (isset($sighting['Sighting']['Attribute'])) {
|
||||
foreach($sighting['Sighting']['Attribute'] as $k => $attribute_val) {
|
||||
$new_key = 'attribute_' . $k;
|
||||
$sighting['Sighting'][$new_key] = $attribute_val;
|
||||
}
|
||||
}
|
||||
$lines .= $this->__addLine($sighting['Sighting'], $options);
|
||||
return $lines;
|
||||
}
|
||||
|
||||
private function __eventsHandler($event, $options)
|
||||
{
|
||||
$lines = '';
|
||||
|
|
|
@ -9,8 +9,10 @@ class JsonExport
|
|||
{
|
||||
if ($options['scope'] === 'Attribute') {
|
||||
return $this->__attributeHandler($data, $options);
|
||||
} else {
|
||||
} else if($options['scope'] === 'Event') {
|
||||
return $this->__eventHandler($data, $options);
|
||||
} else if($options['scope'] === 'Sighting') {
|
||||
return $this->__sightingsHandler($data, $options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +49,11 @@ class JsonExport
|
|||
return json_encode($attribute);
|
||||
}
|
||||
|
||||
private function __sightingsHandler($sighting, $options = array())
|
||||
{
|
||||
return json_encode($sighting);
|
||||
}
|
||||
|
||||
public function header($options = array())
|
||||
{
|
||||
if ($options['scope'] === 'Attribute') {
|
||||
|
|
|
@ -14,12 +14,14 @@ class Stix1Export extends StixExport
|
|||
$this->__baseurl = escapeshellarg(Configure::read('MISP.baseurl'));
|
||||
$this->__org = escapeshellarg(Configure::read('MISP.org'));
|
||||
$framing_file = $this->__scripts_dir . 'misp_framing.py ';
|
||||
return 'python3 ' . $framing_file . $this->__return_type . ' ' . $this->__baseurl . ' ' . $this->__org . ' xml' . $this->__end_of_cmd;
|
||||
$my_server = ClassRegistry::init('Server');
|
||||
return $my_server->getPythonVersion() . ' ' . $framing_file . $this->__return_type . ' ' . $this->__baseurl . ' ' . $this->__org . ' xml' . $this->__end_of_cmd;
|
||||
}
|
||||
|
||||
protected function __parse_misp_events($filename)
|
||||
{
|
||||
$scriptFile = $this->__scripts_dir . $this->__script_name;
|
||||
return shell_exec('python3 ' . $scriptFile . ' ' . $filename . ' xml ' . $this->__baseurl . ' ' . $this->__org . $this->__end_of_cmd);
|
||||
$my_server = ClassRegistry::init('Server');
|
||||
return shell_exec($my_server->getPythonVersion() . ' ' . $scriptFile . ' ' . $filename . ' xml ' . $this->__baseurl . ' ' . $this->__org . $this->__end_of_cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,15 @@ class Stix2Export extends StixExport
|
|||
protected function initiate_framing_params()
|
||||
{
|
||||
$framing_file = $this->__scripts_dir . 'misp_framing.py ';
|
||||
return 'python3 ' . $framing_file . $this->__return_type . ' ' . escapeshellarg(CakeText::uuid()) . $this->__end_of_cmd;
|
||||
$my_server = ClassRegistry::init('Server');
|
||||
return $my_server->getPythonVersion() . ' ' . $framing_file . $this->__return_type . ' ' . escapeshellarg(CakeText::uuid()) . $this->__end_of_cmd;
|
||||
}
|
||||
|
||||
protected function __parse_misp_events($filename)
|
||||
{
|
||||
$scriptFile = $this->__scripts_dir . $this->__script_name;
|
||||
$filename = $this->__scripts_dir . 'tmp/' . $filename;
|
||||
return shell_exec('python3 ' . $scriptFile . ' ' . $filename . $this->__end_of_cmd);
|
||||
$my_server = ClassRegistry::init('Server');
|
||||
return shell_exec($my_server->getPythonVersion() . ' ' . $scriptFile . ' ' . $filename . $this->__end_of_cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ class StixExport
|
|||
{
|
||||
$attributes_count = count($data['Attribute']);
|
||||
foreach ($data['Object'] as $_object) {
|
||||
$attributes_count += count($_object['Attribute']);
|
||||
if (isset($_object['Attribute'])) {
|
||||
$attributes_count += count($_object['Attribute']);
|
||||
}
|
||||
}
|
||||
App::uses('JSONConverterTool', 'Tools');
|
||||
$converter = new JSONConverterTool();
|
||||
|
|
|
@ -9,8 +9,10 @@ class XmlExport
|
|||
{
|
||||
if ($options['scope'] === 'Attribute') {
|
||||
return $this->__attributeHandler($data, $options);
|
||||
} else {
|
||||
} else if($options['scope'] === 'Event') {
|
||||
return $this->__eventHandler($data, $options);
|
||||
} else if($options['scope'] === 'Sighting') {
|
||||
return $this->__sightingsHandler($data, $options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +52,12 @@ class XmlExport
|
|||
return substr($xmlString, strpos($xmlString, "\n") + 1);
|
||||
}
|
||||
|
||||
private function __sightingsHandler($sighting, $options = array()) {
|
||||
$xmlObject = Xml::fromArray(array('Sighting' => $sighting['Sighting']), array('format' => 'tags'));
|
||||
$xmlString = $xmlObject->asXML();
|
||||
return substr($xmlString, strpos($xmlString, "\n") + 1);
|
||||
}
|
||||
|
||||
public function header($options = array())
|
||||
{
|
||||
return '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>';
|
||||
|
|
|
@ -77,18 +77,25 @@ class AWSS3Client
|
|||
}
|
||||
|
||||
public function deleteDirectory($prefix) {
|
||||
$keys = $s3->listObjects([
|
||||
$keys = $this->__client->listObjectsV2([
|
||||
'Bucket' => $this->__settings['bucket_name'],
|
||||
'Prefix' => $prefix
|
||||
]) ->getPath('Contents/*/Key');
|
||||
|
||||
$s3->deleteObjects([
|
||||
'Bucket' => $bucket,
|
||||
'Delete' => [
|
||||
'Objects' => array_map(function ($key) {
|
||||
return ['Key' => $key];
|
||||
}, $keys)
|
||||
],
|
||||
]);
|
||||
|
||||
$toDelete = array_map(
|
||||
function ($key) {
|
||||
return ['Key' => $key['Key']];
|
||||
},
|
||||
is_array($keys['Contents'])?$keys['Contents']:[]
|
||||
);
|
||||
|
||||
if (sizeof($toDelete) != 0) {
|
||||
$this->__client->deleteObjects([
|
||||
'Bucket' => $this->__settings['bucket_name'],
|
||||
'Delete' => [
|
||||
'Objects' => $toDelete
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,113 @@
|
|||
<?php
|
||||
class ColourGradientTool
|
||||
{
|
||||
public function createGradient($step)
|
||||
{
|
||||
$stepHex = dechex($step);
|
||||
$minHex = 0x0000FF;
|
||||
$maxHex = 0xFF0000;
|
||||
$intervalHex = ($maxHex-$minHex) / $stepHex;
|
||||
$colours = array();
|
||||
for ($i=$minHex; $i<$maxHex; $i+=$intervalHex) {
|
||||
$colours[] = $i;
|
||||
}
|
||||
return $colours;
|
||||
}
|
||||
|
||||
// source: https://graphicdesign.stackexchange.com/a/83867
|
||||
// $values of the form array(item1: val1, item2: val2, ...)
|
||||
public function createGradientFromValues($items)
|
||||
{
|
||||
$starColor = '#0000FF';
|
||||
$endColor = '#FF0000';
|
||||
|
||||
if (count($items) == 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$maxColorHex = 0x0000FF;
|
||||
$minColorHex = 0xE0E0FF;
|
||||
|
||||
$vals = array_values($items);
|
||||
$maxDec = max($vals);
|
||||
$minDec = min($vals);
|
||||
|
||||
if ($maxDec == $minDec) {
|
||||
$intervalHex = 0x0;
|
||||
} else {
|
||||
$intervalHex = ($maxColorHex - $minColorHex)/($maxDec-$minDec);
|
||||
}
|
||||
|
||||
$interpolation = $this->interpolateColors($starColor, $endColor, $maxDec+1, true);
|
||||
$coloursMapping = array();
|
||||
foreach ($items as $name => $val) {
|
||||
$ratio = ($val-$minDec)*($intervalHex);
|
||||
$colour = $maxDec == $minDec ? $maxColorHex : $ratio + $minColorHex;
|
||||
$coloursMapping[$name] = '#' . str_pad(dechex($colour), 6, '0', STR_PAD_LEFT);
|
||||
$color = $interpolation[$val];
|
||||
$coloursMapping[$name] = '#' . str_pad(dechex($color[0]), 2, '0', STR_PAD_LEFT) . str_pad(dechex($color[1]), 2, '0', STR_PAD_LEFT) . str_pad(dechex($color[2]), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
return array('mapping' => $coloursMapping, 'interpolation' => $interpolation);
|
||||
}
|
||||
|
||||
private function hue2rgb($p, $q, $t) {
|
||||
if ($t < 0) $t += 1;
|
||||
if ($t > 1) $t -= 1;
|
||||
if ($t < 1/6) return $p + ($q - $p) * 6 * $t;
|
||||
if ($t < 1/2) return $q;
|
||||
if ($t < 2/3) return $p + ($q - $p) * (2/3 - $t) * 6;
|
||||
return $p;
|
||||
}
|
||||
|
||||
private function hsl2rgb($color) {
|
||||
$l = $color[2];
|
||||
if ($color[1] == 0) {
|
||||
$l = round($l*255);
|
||||
return array($l, $l, $l);
|
||||
} else {
|
||||
$s = $color[1];
|
||||
$q = ($l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s);
|
||||
$p = 2 * $l - $q;
|
||||
$r = $this->hue2rgb($p, $q, $color[0] + 1/3);
|
||||
$g = $this->hue2rgb($p, $q, $color[0]);
|
||||
$b = $this->hue2rgb($p, $q, $color[0] - 1/3);
|
||||
return array(round($r*255), round($g*255), round($b*255));
|
||||
}
|
||||
return $coloursMapping;
|
||||
}
|
||||
|
||||
private function rgb2hsl($color) {
|
||||
$r = $color[0]/255;
|
||||
$g = $color[1]/255;
|
||||
$b = $color[2]/255;
|
||||
$arrRGB = array($r, $g, $b);
|
||||
|
||||
$max = max($arrRGB);
|
||||
$min = min($arrRGB);
|
||||
$h = ($max - $min) / 2;
|
||||
$s = $h;
|
||||
$l = $h;
|
||||
|
||||
if ($max == $min) {
|
||||
$s = 0; // achromatic
|
||||
$h = 0;
|
||||
} else {
|
||||
$d = $max - $min;
|
||||
$s = ($l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min) );
|
||||
if ($max == $r) {
|
||||
$h = ($g - $b) / $d + ($g < $b ? 6 : 0);
|
||||
} elseif ($max == $g) {
|
||||
$h = ($b - $r) / $d + 2;
|
||||
} elseif ($max == $b) {
|
||||
$h = ($r - $g) / $d + 4;
|
||||
}
|
||||
$h = $h / 6;
|
||||
return array($h, $s, $l);
|
||||
}
|
||||
}
|
||||
|
||||
private function interpolateColor($color1, $color2, $factor, $useHSL=false) {
|
||||
if ($useHSL) {
|
||||
$hsl1 = $this->rgb2hsl($color1);
|
||||
$hsl2 = $this->rgb2hsl($color2);
|
||||
for ($i=0; $i<3; $i++) {
|
||||
$hsl1[$i] += $factor*($hsl2[$i] - $hsl1[$i]);
|
||||
}
|
||||
$result = $this->hsl2rgb($hsl1);
|
||||
} else {
|
||||
$result = $color1;
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$result[$i] = round($result[$i] + $factor * ($color2[$i] - $color1[$i]));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function interpolateColors($hexColor1, $hexColor2, $steps, $useHSL=false) {
|
||||
$stepFactor = 1 / ($steps - 1);
|
||||
$interpolatedColorArray = array();
|
||||
$color1 = sscanf($hexColor1, "#%02x%02x%02x");
|
||||
$color2 = sscanf($hexColor2, "#%02x%02x%02x");
|
||||
|
||||
for($i = 0; $i < $steps; $i++) {
|
||||
$interpolatedColorArray[$i] = $this->interpolateColor($color1, $color2, $stepFactor * $i, $useHSL);
|
||||
}
|
||||
|
||||
return $interpolatedColorArray;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ class ComplexTypeTool
|
|||
|
||||
private $__hexHashTypes = array(
|
||||
32 => array('single' => array('md5', 'imphash', 'x509-fingerprint-md5'), 'composite' => array('filename|md5', 'filename|imphash')),
|
||||
40 => array('single' => array('sha1', 'pehash', 'x509-fingerprint-sha1'), 'composite' => array('filename|sha1', 'filename|pehash')),
|
||||
40 => array('single' => array('sha1', 'pehash', 'x509-fingerprint-sha1', 'cdhash'), 'composite' => array('filename|sha1', 'filename|pehash')),
|
||||
56 => array('single' => array('sha224', 'sha512/224'), 'composite' => array('filename|sha224', 'filename|sha512/224')),
|
||||
64 => array('single' => array('sha256', 'authentihash', 'sha512/256', 'x509-fingerprint-sha256'), 'composite' => array('filename|sha256', 'filename|authentihash', 'filename|sha512/256')),
|
||||
96 => array('single' => array('sha384'), 'composite' => array('filename|sha384')),
|
||||
|
@ -228,7 +228,7 @@ class ComplexTypeTool
|
|||
);
|
||||
|
||||
// algorithms to run through in order
|
||||
private $__checks = array('Hashes', 'Email', 'IP', 'DomainOrFilename', 'SimpleRegex', 'AS');
|
||||
private $__checks = array('Hashes', 'Email', 'IP', 'DomainOrFilename', 'SimpleRegex', 'AS', 'BTC');
|
||||
|
||||
private function __resolveType($raw_input)
|
||||
{
|
||||
|
@ -247,6 +247,14 @@ class ComplexTypeTool
|
|||
return false;
|
||||
}
|
||||
|
||||
private function __checkForBTC($input)
|
||||
{
|
||||
if (preg_match("#^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$#i", $input['raw'])) {
|
||||
return array('types' => array('btc'), 'categories' => array('Financial fraud'), 'to_ids' => true, 'default_type' => 'btc', 'value' => $input['raw']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function __checkForEmail($input)
|
||||
{
|
||||
// quick filter for an @ to see if we should validate a potential e-mail address
|
||||
|
@ -288,7 +296,11 @@ class ComplexTypeTool
|
|||
// check for hashes
|
||||
foreach ($this->__hexHashTypes as $k => $v) {
|
||||
if (strlen($input['raw']) == $k && preg_match("#[0-9a-f]{" . $k . "}$#i", $input['raw'])) {
|
||||
return array('types' => $v['single'], 'to_ids' => true, 'default_type' => $v['single'][0], 'value' => $input['raw']);
|
||||
$types = $v['single'];
|
||||
if (!empty($this->__checkForBTC($input))) {
|
||||
$types[] = 'btc';
|
||||
}
|
||||
return array('types' => $types, 'to_ids' => true, 'default_type' => $v['single'][0], 'value' => $input['raw']);
|
||||
}
|
||||
}
|
||||
// ssdeep has a different pattern
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:37\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:21\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: Czech\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:37\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:22\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: Danish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -5461,11 +5461,11 @@ msgstr "EventGraph Sletning"
|
|||
|
||||
#: View/EventGraph/ajax/eventGraph_delete_form.ctp:8
|
||||
msgid "Are you sure you want to delete eventGraph #%s? The eventGraph will be permanently deleted and unrecoverable."
|
||||
msgstr ""
|
||||
msgstr "Er du sikker på du vil slette eventGraph #%s? EventGraph vil være permanent slettede og uoprettelig."
|
||||
|
||||
#: View/Events/add.ctp:3
|
||||
msgid "The event created %s, but not synchronised to other MISP instances until it is published."
|
||||
msgstr ""
|
||||
msgstr "Begivenheden oprettet %s, men synkroniseret ikke til andre forekomster af MISP, indtil det er offentliggjort."
|
||||
|
||||
#: View/Events/add.ctp:3
|
||||
msgid "will be restricted to your organisation"
|
||||
|
@ -5895,7 +5895,8 @@ msgstr "Inkluder events der ikke er publicerede."
|
|||
#: View/Events/automation.ctp:208;275
|
||||
msgid "You can also chain several tag commands together with the '&&' operator. Please be aware the colons (:) cannot be used in the tag search.\n"
|
||||
" Use semicolons instead (the search will automatically search for colons instead). For example, to include tag1 and tag2 but exclude tag3 you would use"
|
||||
msgstr ""
|
||||
msgstr "Du kan også sammenkæde flere tagkommandoer med &&-operatoren. Vær opmærksom på, at kolon (:) ikke kan benyttes i tag-søgning.\n"
|
||||
" Benyt i stedet somikolon (søgningen vil automatisk søge efter koloner i stedet). For f.eks. at medtage tag1 og tag2, men udelukke tag3, skal du benytte"
|
||||
|
||||
#: View/Events/automation.ctp:211
|
||||
msgid "Bro IDS export"
|
||||
|
@ -6951,7 +6952,7 @@ msgstr "Skift pivotgraf"
|
|||
|
||||
#: View/Events/view.ctp:360
|
||||
msgid "Pivots"
|
||||
msgstr ""
|
||||
msgstr "Pivots"
|
||||
|
||||
#: View/Events/view.ctp:363
|
||||
msgid "Toggle galaxies"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:35\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:23\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: German\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -61,7 +61,7 @@ msgstr "Sie haben keine Berechtigung dieses Event anzuzeigen."
|
|||
|
||||
#: Controller/AttributesController.php:472
|
||||
msgid "Attribute not an attachment or malware-sample"
|
||||
msgstr "Attribut ist keine Anlage oder Malware-Sample"
|
||||
msgstr "Attribut ist kein Anhang oder Malware-Sample"
|
||||
|
||||
#: Controller/AttributesController.php:504;677
|
||||
#: Controller/ShadowAttributesController.php:548
|
||||
|
@ -220,7 +220,7 @@ msgstr "Ungültiges Event-ID-Format."
|
|||
#: Controller/AttributesController.php:2645
|
||||
#: Controller/ShadowAttributesController.php:1254
|
||||
msgid "All done. "
|
||||
msgstr "Alles erledigt. "
|
||||
msgstr "Fertig. "
|
||||
|
||||
#: Controller/AttributesController.php:2677;2724
|
||||
#: Controller/ShadowAttributesController.php:1062
|
||||
|
@ -1819,19 +1819,19 @@ msgstr "Einstellung des Bereichs für Sightings für das generieren von Graphen.
|
|||
|
||||
#: Model/Server.php:1465
|
||||
msgid "Enable this functionality if you would like to handle the authentication via an external tool and authenticate with MISP using a custom header."
|
||||
msgstr ""
|
||||
msgstr "Aktivieren Sie diese Funktion, falls Sie die Authentifizierung mit MISP durch ein externes Tool und custom Header handhaben möchten."
|
||||
|
||||
#: Model/Server.php:1475
|
||||
msgid "Set the header that MISP should look for here. If left empty it will default to the Authorization header."
|
||||
msgstr ""
|
||||
msgstr "Stellen Sie hier die Kopfzeile ein, nach der MISP hier suchen soll. Ohne weitere Angabe wird als Default nach der Authorisierungskopfzeile gesucht."
|
||||
|
||||
#: Model/Server.php:1484
|
||||
msgid "Use a header namespace for the auth header - default setting is enabled"
|
||||
msgstr ""
|
||||
msgstr "Verwenden Sie einen Namespace (Namensbereich) für den Authentifizierungsheader - Standardeinstellung ist aktiviert"
|
||||
|
||||
#: Model/Server.php:1493
|
||||
msgid "The default header namespace for the auth header - default setting is HTTP_"
|
||||
msgstr ""
|
||||
msgstr "Der Standard Namespace für den Authentifizierungsheader - Standardeinstellung ist HTTP"
|
||||
|
||||
#: Model/Server.php:1502
|
||||
msgid "If this setting is enabled then the only way to authenticate will be using the custom header. Altnertatively you can run in mixed mode that will log users in via the header if found, otherwise users will be redirected to the normal login page."
|
||||
|
@ -1847,7 +1847,7 @@ msgstr ""
|
|||
|
||||
#: Model/Server.php:1529
|
||||
msgid "Disable the logout button for users authenticate with the external auth mechanism."
|
||||
msgstr ""
|
||||
msgstr "Deaktivieren Sie den Logout-Button für User, die sich extern authentifizieren."
|
||||
|
||||
#: Model/Server.php:1537
|
||||
msgid "Enable/disable the enrichment services"
|
||||
|
@ -3909,7 +3909,7 @@ msgstr ""
|
|||
|
||||
#: View/Elements/side_menu.ctp:533
|
||||
msgid "Update Galaxies"
|
||||
msgstr ""
|
||||
msgstr "Galaxien aktualisieren"
|
||||
|
||||
#: View/Elements/side_menu.ctp:533
|
||||
msgid "Are you sure you want to reimport all galaxies from the submodule?"
|
||||
|
@ -3943,7 +3943,7 @@ msgstr ""
|
|||
#: View/Layouts/default.ctp:84
|
||||
#: View/Layouts/graph.ctp:84
|
||||
msgid "Loading"
|
||||
msgstr ""
|
||||
msgstr "Lädt"
|
||||
|
||||
#: View/Elements/view_event_distribution_graph.ctp:17
|
||||
msgid "Elements having lower distribution level than the event"
|
||||
|
@ -12487,7 +12487,7 @@ msgstr ""
|
|||
#: View/Users/admin_add.ctp:88
|
||||
#: View/Users/admin_edit.ctp:78
|
||||
msgid "Disable this user account"
|
||||
msgstr ""
|
||||
msgstr "Diesen Useraccount deaktivieren"
|
||||
|
||||
#: View/Users/admin_add.ctp:90
|
||||
msgid "Send credentials automatically"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 14:03\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:22\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:37\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:24\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: Italian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:37\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:25\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: Japanese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:37\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:25\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: Korean\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -609,35 +609,35 @@ msgstr "다운로드에 실패했습니다."
|
|||
|
||||
#: Controller/FeedsController.php:561
|
||||
msgid "Feed could not be fetched. The HTTP error code returned was: "
|
||||
msgstr ""
|
||||
msgstr "피드를 가져올 수 없습니다. 리턴된 HTTP 오류 코드는 다음과 같습니다: "
|
||||
|
||||
#: Controller/FeedsController.php:600;651
|
||||
msgid "Invalid feed type."
|
||||
msgstr ""
|
||||
msgstr "잘못된 피드 유형입니다."
|
||||
|
||||
#: Controller/FeedsController.php:714
|
||||
msgid "This event is blocked by the Feed filters."
|
||||
msgstr ""
|
||||
msgstr "이 이벤트는 피드 필터에 의해 차단되어 있습니다."
|
||||
|
||||
#: Controller/FeedsController.php:716
|
||||
msgid "Could not download the selected Event"
|
||||
msgstr ""
|
||||
msgstr "선택한 이벤트를 다운로드 할 수 없습니다"
|
||||
|
||||
#: Controller/FeedsController.php:752;756
|
||||
msgid "Invalid Feed."
|
||||
msgstr ""
|
||||
msgstr "잘못된 피드입니다."
|
||||
|
||||
#: Controller/FeedsController.php:777
|
||||
msgid "Only POST requests are allowed."
|
||||
msgstr ""
|
||||
msgstr "POST 요청 만 허용되어 있습니다."
|
||||
|
||||
#: Controller/FeedsController.php:781
|
||||
msgid "Feed not found."
|
||||
msgstr ""
|
||||
msgstr "피드가 없습니다."
|
||||
|
||||
#: Controller/FeedsController.php:790
|
||||
msgid "Data pulled."
|
||||
msgstr ""
|
||||
msgstr "데이터를 가져왔습니다."
|
||||
|
||||
#: Controller/FeedsController.php:792
|
||||
msgid "Could not pull the selected data. Reason: %s"
|
||||
|
@ -645,27 +645,27 @@ msgstr ""
|
|||
|
||||
#: Controller/FeedsController.php:809
|
||||
msgid "Starting feed caching."
|
||||
msgstr ""
|
||||
msgstr "피드 캐싱 시작."
|
||||
|
||||
#: Controller/FeedsController.php:824
|
||||
msgid "Caching the feeds has failed."
|
||||
msgstr ""
|
||||
msgstr "피드를 캐싱에 실패 했습니다."
|
||||
|
||||
#: Controller/FeedsController.php:827
|
||||
msgid "Caching the feeds has successfully completed."
|
||||
msgstr ""
|
||||
msgstr "피드 캐싱을 성공적으로 완료 했습니다."
|
||||
|
||||
#: Controller/FeedsController.php:858
|
||||
msgid "Invalid feed list received."
|
||||
msgstr ""
|
||||
msgstr "잘못 된 피드 리스트를 받았습니다."
|
||||
|
||||
#: Controller/JobsController.php:156
|
||||
msgid "All completed jobs have been purged"
|
||||
msgstr ""
|
||||
msgstr "모든 완료 된 작업이 제거 되었습니다."
|
||||
|
||||
#: Controller/JobsController.php:159
|
||||
msgid "All jobs have been purged"
|
||||
msgstr ""
|
||||
msgstr "모든 작업이 제거 되었습니다."
|
||||
|
||||
#: Controller/ObjectReferencesController.php:37
|
||||
msgid "Invalid object"
|
||||
|
@ -677,19 +677,19 @@ msgstr "올바르지 않은 객체 참조"
|
|||
|
||||
#: Controller/ObjectTemplatesController.php:88
|
||||
msgid "ObjectTemplate deleted"
|
||||
msgstr ""
|
||||
msgstr "오브젝트템플릿이 삭제 되었습니다."
|
||||
|
||||
#: Controller/ObjectsController.php:29
|
||||
msgid "This action can only be reached via POST requests"
|
||||
msgstr ""
|
||||
msgstr "이 행위는 POST 요청을 통해 서만 이용할 수 있습니다."
|
||||
|
||||
#: Controller/ObjectsController.php:69;82
|
||||
msgid "Invalid sharing group."
|
||||
msgstr ""
|
||||
msgstr "잘못 된 공유 그룹입니다."
|
||||
|
||||
#: Controller/ObjectsController.php:103
|
||||
msgid "You don't have permissions to create objects."
|
||||
msgstr ""
|
||||
msgstr "오브젝트를 생성할 수있는 권한이 없습니다."
|
||||
|
||||
#: Controller/ObjectsController.php:131
|
||||
#: Model/Template.php:25
|
||||
|
@ -698,7 +698,7 @@ msgstr "올바르지 않은 양식입니다."
|
|||
|
||||
#: Controller/ObjectsController.php:303
|
||||
msgid "You don't have permissions to edit objects."
|
||||
msgstr ""
|
||||
msgstr "오브젝트를 수정할 수있는 권한이 없습니다."
|
||||
|
||||
#: Controller/ObjectsController.php:317;328;427
|
||||
msgid "Invalid object."
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: misp\n"
|
||||
"PO-Revision-Date: 2018-10-15 23:37\n"
|
||||
"PO-Revision-Date: 2019-01-22 21:26\n"
|
||||
"Last-Translator: SteveClement <steve@localhost.lu>\n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue