diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py
index 4b887d94b..e480d2cd5 100644
--- a/monkey/monkey_island/cc/app.py
+++ b/monkey/monkey_island/cc/app.py
@@ -5,7 +5,7 @@ import flask_restful
from flask import Flask, send_from_directory, Response
from werkzeug.exceptions import NotFound
-from monkey_island.cc.auth import init_jwt
+from monkey_island.cc.resources.auth.auth import init_jwt
from monkey_island.cc.database import mongo, database
from monkey_island.cc.environment.environment_singleton import env
from monkey_island.cc.resources.client_run import ClientRun
diff --git a/monkey/monkey_island/cc/environment/__init__.py b/monkey/monkey_island/cc/environment/__init__.py
index 62a702d73..adcb8aed0 100644
--- a/monkey/monkey_island/cc/environment/__init__.py
+++ b/monkey/monkey_island/cc/environment/__init__.py
@@ -5,7 +5,6 @@ from datetime import timedelta
__author__ = 'itay.mizeretz'
-from typing import Dict
from common.utils.exceptions import InvalidRegistrationCredentials
from monkey_island.cc.environment.environment_config import EnvironmentConfig
@@ -25,7 +24,7 @@ class Environment(object, metaclass=ABCMeta):
_testing = False
def __init__(self):
- self._config = None
+ self._config = EnvironmentConfig("", "", UserCreds())
self._testing = False # Assume env is not for unit testing.
@property
@@ -40,6 +39,9 @@ class Environment(object, metaclass=ABCMeta):
def try_add_user(self, credentials: UserCreds):
if self._credentials_required:
if credentials:
+ if self._is_registered():
+ raise InvalidRegistrationCredentials("User has already been registered. "
+ "Reset credentials or login.")
self._config.add_user(credentials)
else:
raise InvalidRegistrationCredentials("Missing part of credentials.")
diff --git a/monkey/monkey_island/cc/environment/aws.py b/monkey/monkey_island/cc/environment/aws.py
index 96b74556d..b42fa910e 100644
--- a/monkey/monkey_island/cc/environment/aws.py
+++ b/monkey/monkey_island/cc/environment/aws.py
@@ -1,5 +1,4 @@
-import monkey_island.cc.auth
-from monkey_island.cc.auth_user import User
+from monkey_island.cc.resources.auth.auth_user import User
from monkey_island.cc.environment import Environment
from common.cloud.aws.aws_instance import AwsInstance
diff --git a/monkey/monkey_island/cc/environment/environment_config.py b/monkey/monkey_island/cc/environment/environment_config.py
index 20d70ef9e..4a50fb7cc 100644
--- a/monkey/monkey_island/cc/environment/environment_config.py
+++ b/monkey/monkey_island/cc/environment/environment_config.py
@@ -4,9 +4,10 @@ import json
import os
from typing import List, Dict
-from monkey_island.cc.auth_user import User
+from monkey_island.cc.resources.auth.auth_user import User
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
from monkey_island.cc.environment.user_creds import UserCreds
+from monkey_island.cc.resources.auth.user_store import UserStore
class EnvironmentConfig:
@@ -60,6 +61,8 @@ class EnvironmentConfig:
def add_user(self, credentials: UserCreds):
self.user_creds = credentials
+ self.save_to_file()
+ UserStore.set_users(self.get_users())
def get_users(self) -> List[User]:
auth_user = self.user_creds.to_auth_user()
diff --git a/monkey/monkey_island/cc/environment/password.py b/monkey/monkey_island/cc/environment/password.py
index e181feb7c..8cfd495d2 100644
--- a/monkey/monkey_island/cc/environment/password.py
+++ b/monkey/monkey_island/cc/environment/password.py
@@ -1,5 +1,4 @@
from monkey_island.cc.environment import Environment
-import monkey_island.cc.auth
__author__ = 'itay.mizeretz'
@@ -10,6 +9,6 @@ class PasswordEnvironment(Environment):
def get_auth_users(self):
if self._is_registered():
- return self._config.get_users
+ return self._config.get_users()
else:
return []
diff --git a/monkey/monkey_island/cc/environment/standard.py b/monkey/monkey_island/cc/environment/standard.py
index 8f18824db..08851c94a 100644
--- a/monkey/monkey_island/cc/environment/standard.py
+++ b/monkey/monkey_island/cc/environment/standard.py
@@ -1,4 +1,4 @@
-from monkey_island.cc.auth_user import User
+from monkey_island.cc.resources.auth.auth_user import User
from monkey_island.cc.environment import Environment
__author__ = 'itay.mizeretz'
diff --git a/monkey/monkey_island/cc/environment/test__init__.py b/monkey/monkey_island/cc/environment/test__init__.py
index ddca7e535..3115023a5 100644
--- a/monkey/monkey_island/cc/environment/test__init__.py
+++ b/monkey/monkey_island/cc/environment/test__init__.py
@@ -2,8 +2,10 @@ import json
import os
from typing import Dict
from unittest import TestCase
+from unittest.mock import patch, MagicMock
-from monkey_island.cc.environment import Environment, EnvironmentConfig
+from common.utils.exceptions import InvalidRegistrationCredentials
+from monkey_island.cc.environment import Environment, EnvironmentConfig, UserCreds
def get_server_config_file_path_test_version():
@@ -57,6 +59,21 @@ class TestEnvironment(TestCase):
"4f2e9b3ca9f484f521d0ce464345cc1aec96779149c14"
}
+ @patch.object(target=EnvironmentConfig, attribute="save_to_file", new=MagicMock())
+ def test_try_add_user(self):
+ env = TestEnvironment.EnvironmentWithCredentials()
+ credentials = UserCreds(username="test", password_hash="1231234")
+ env.try_add_user(credentials)
+
+ credentials = UserCreds(username="test")
+ with self.assertRaises(InvalidRegistrationCredentials):
+ env.try_add_user(credentials)
+
+ env = TestEnvironment.EnvironmentNoCredentials()
+ credentials = UserCreds(username="test", password_hash="1231234")
+ with self.assertRaises(InvalidRegistrationCredentials):
+ env.try_add_user(credentials)
+
def test_needs_registration(self):
env = TestEnvironment.EnvironmentWithCredentials()
self._test_bool_env_method("needs_registration", env, TestEnvironment.CONFIG_WITH_CREDENTIALS, False)
diff --git a/monkey/monkey_island/cc/environment/test_aws.py b/monkey/monkey_island/cc/environment/test_aws.py
index 5cd37501a..65f8c3e58 100644
--- a/monkey/monkey_island/cc/environment/test_aws.py
+++ b/monkey/monkey_island/cc/environment/test_aws.py
@@ -1,4 +1,4 @@
-from monkey_island.cc.auth_user import User
+from monkey_island.cc.resources.auth.auth_user import User
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
from monkey_island.cc.environment.aws import AwsEnvironment
diff --git a/monkey/monkey_island/cc/environment/user_creds.py b/monkey/monkey_island/cc/environment/user_creds.py
index d60c61720..7d6ca4962 100644
--- a/monkey/monkey_island/cc/environment/user_creds.py
+++ b/monkey/monkey_island/cc/environment/user_creds.py
@@ -3,7 +3,7 @@ from __future__ import annotations
import json
from typing import Dict
-from monkey_island.cc.auth_user import User
+from monkey_island.cc.resources.auth.auth_user import User
class UserCreds:
diff --git a/monkey/monkey_island/cc/resources/attack/attack_config.py b/monkey/monkey_island/cc/resources/attack/attack_config.py
index 021663521..129297b19 100644
--- a/monkey/monkey_island/cc/resources/attack/attack_config.py
+++ b/monkey/monkey_island/cc/resources/attack/attack_config.py
@@ -1,7 +1,7 @@
import flask_restful
from flask import jsonify, request, json, current_app
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.attack.attack_config import AttackConfig
__author__ = "VakarisZ"
diff --git a/monkey/monkey_island/cc/resources/attack/attack_report.py b/monkey/monkey_island/cc/resources/attack/attack_report.py
index dc63f6747..aa7a28a09 100644
--- a/monkey/monkey_island/cc/resources/attack/attack_report.py
+++ b/monkey/monkey_island/cc/resources/attack/attack_report.py
@@ -1,5 +1,5 @@
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.attack.attack_report import AttackReportService
from monkey_island.cc.services.attack.attack_schema import SCHEMA
from flask import json, current_app
diff --git a/monkey/monkey_island/cc/resources/auth/__init__.py b/monkey/monkey_island/cc/resources/auth/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/monkey/monkey_island/cc/auth.py b/monkey/monkey_island/cc/resources/auth/auth.py
similarity index 79%
rename from monkey/monkey_island/cc/auth.py
rename to monkey/monkey_island/cc/resources/auth/auth.py
index 0bbb385b0..c582f8706 100644
--- a/monkey/monkey_island/cc/auth.py
+++ b/monkey/monkey_island/cc/resources/auth/auth.py
@@ -5,23 +5,22 @@ from flask_jwt import JWT, _jwt_required, JWTError
from werkzeug.security import safe_str_cmp
from monkey_island.cc.environment.environment_singleton import env
+from monkey_island.cc.resources.auth.user_store import UserStore
__author__ = 'itay.mizeretz'
def init_jwt(app):
- users = env.get_auth_users()
- username_table = {u.username: u for u in users}
- userid_table = {u.id: u for u in users}
+ UserStore.set_users(env.get_auth_users())
def authenticate(username, secret):
- user = username_table.get(username, None)
+ user = UserStore.username_table.get(username, None)
if user and safe_str_cmp(user.secret.encode('utf-8'), secret.encode('utf-8')):
return user
def identity(payload):
user_id = payload['identity']
- return userid_table.get(user_id, None)
+ return UserStore.userid_table.get(user_id, None)
JWT(app, authenticate, identity)
diff --git a/monkey/monkey_island/cc/auth_user.py b/monkey/monkey_island/cc/resources/auth/auth_user.py
similarity index 100%
rename from monkey/monkey_island/cc/auth_user.py
rename to monkey/monkey_island/cc/resources/auth/auth_user.py
diff --git a/monkey/monkey_island/cc/resources/auth/user_store.py b/monkey/monkey_island/cc/resources/auth/user_store.py
new file mode 100644
index 000000000..7cb43e222
--- /dev/null
+++ b/monkey/monkey_island/cc/resources/auth/user_store.py
@@ -0,0 +1,15 @@
+from typing import List
+
+from monkey_island.cc.resources.auth.auth_user import User
+
+
+class UserStore:
+ users = []
+ username_table = {}
+ userid_table = {}
+
+ @staticmethod
+ def set_users(users: List[User]):
+ UserStore.users = users
+ UserStore.username_table = {u.username: u for u in UserStore.users}
+ UserStore.userid_table = {u.id: u for u in UserStore.users}
diff --git a/monkey/monkey_island/cc/resources/island_configuration.py b/monkey/monkey_island/cc/resources/island_configuration.py
index 28ef32c46..81f922263 100644
--- a/monkey/monkey_island/cc/resources/island_configuration.py
+++ b/monkey/monkey_island/cc/resources/island_configuration.py
@@ -3,7 +3,7 @@ import json
import flask_restful
from flask import request, jsonify, abort
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.config import ConfigService
diff --git a/monkey/monkey_island/cc/resources/island_logs.py b/monkey/monkey_island/cc/resources/island_logs.py
index 724087e52..5ef64789b 100644
--- a/monkey/monkey_island/cc/resources/island_logs.py
+++ b/monkey/monkey_island/cc/resources/island_logs.py
@@ -2,7 +2,7 @@ import logging
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.island_logs import IslandLogService
__author__ = "Maor.Rayzin"
diff --git a/monkey/monkey_island/cc/resources/log.py b/monkey/monkey_island/cc/resources/log.py
index 920890648..b7b405ddf 100644
--- a/monkey/monkey_island/cc/resources/log.py
+++ b/monkey/monkey_island/cc/resources/log.py
@@ -4,7 +4,7 @@ import flask_restful
from bson import ObjectId
from flask import request
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.database import mongo
from monkey_island.cc.resources.test.utils.telem_store import TestTelemStore
from monkey_island.cc.services.log import LogService
diff --git a/monkey/monkey_island/cc/resources/monkey_configuration.py b/monkey/monkey_island/cc/resources/monkey_configuration.py
index 1c067892f..3877ec9ee 100644
--- a/monkey/monkey_island/cc/resources/monkey_configuration.py
+++ b/monkey/monkey_island/cc/resources/monkey_configuration.py
@@ -3,7 +3,7 @@ import json
import flask_restful
from flask import request, jsonify, abort
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.config import ConfigService
__author__ = 'Barak'
diff --git a/monkey/monkey_island/cc/resources/netmap.py b/monkey/monkey_island/cc/resources/netmap.py
index 3b7e471d8..221a8c60a 100644
--- a/monkey/monkey_island/cc/resources/netmap.py
+++ b/monkey/monkey_island/cc/resources/netmap.py
@@ -1,6 +1,6 @@
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.edge import EdgeService
from monkey_island.cc.services.node import NodeService
from monkey_island.cc.database import mongo
diff --git a/monkey/monkey_island/cc/resources/node.py b/monkey/monkey_island/cc/resources/node.py
index e4c2761c9..a38af4b48 100644
--- a/monkey/monkey_island/cc/resources/node.py
+++ b/monkey/monkey_island/cc/resources/node.py
@@ -1,7 +1,7 @@
from flask import request
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.node import NodeService
__author__ = 'Barak'
diff --git a/monkey/monkey_island/cc/resources/node_states.py b/monkey/monkey_island/cc/resources/node_states.py
index bb5a978b6..3a4e674cc 100644
--- a/monkey/monkey_island/cc/resources/node_states.py
+++ b/monkey/monkey_island/cc/resources/node_states.py
@@ -1,6 +1,6 @@
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.utils.node_states import NodeStates as NodeStateList
diff --git a/monkey/monkey_island/cc/resources/pba_file_upload.py b/monkey/monkey_island/cc/resources/pba_file_upload.py
index 3a636459c..2d1954c31 100644
--- a/monkey/monkey_island/cc/resources/pba_file_upload.py
+++ b/monkey/monkey_island/cc/resources/pba_file_upload.py
@@ -2,7 +2,7 @@ import flask_restful
from flask import request, send_from_directory, Response
from monkey_island.cc.services.config import ConfigService
from monkey_island.cc.services.post_breach_files import PBA_WINDOWS_FILENAME_PATH, PBA_LINUX_FILENAME_PATH, UPLOADS_DIR
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
import os
from werkzeug.utils import secure_filename
import logging
diff --git a/monkey/monkey_island/cc/resources/registration.py b/monkey/monkey_island/cc/resources/registration.py
index 0e55b697a..237972ee6 100644
--- a/monkey/monkey_island/cc/resources/registration.py
+++ b/monkey/monkey_island/cc/resources/registration.py
@@ -14,7 +14,7 @@ class Registration(flask_restful.Resource):
credentials = UserCreds.get_from_json(request.data)
try:
env.try_add_user(credentials)
- return make_response({"error": ""}, 300)
+ return make_response({"error": ""}, 200)
except InvalidRegistrationCredentials as e:
- return make_response({"error": e}, 400)
+ return make_response({"error": str(e)}, 400)
diff --git a/monkey/monkey_island/cc/resources/remote_run.py b/monkey/monkey_island/cc/resources/remote_run.py
index 98d3694bf..1d9cdf4d6 100644
--- a/monkey/monkey_island/cc/resources/remote_run.py
+++ b/monkey/monkey_island/cc/resources/remote_run.py
@@ -4,7 +4,7 @@ from botocore.exceptions import NoCredentialsError, ClientError
from flask import request, jsonify, make_response
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
from common.cloud.aws.aws_service import AwsService
diff --git a/monkey/monkey_island/cc/resources/reporting/report.py b/monkey/monkey_island/cc/resources/reporting/report.py
index 961e745a8..6197b1e0c 100644
--- a/monkey/monkey_island/cc/resources/reporting/report.py
+++ b/monkey/monkey_island/cc/resources/reporting/report.py
@@ -3,7 +3,7 @@ import http.client
import flask_restful
from flask import jsonify
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.reporting.report import ReportService
from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService
diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py
index 5b319072b..18521a377 100644
--- a/monkey/monkey_island/cc/resources/root.py
+++ b/monkey/monkey_island/cc/resources/root.py
@@ -4,7 +4,7 @@ import threading
import flask_restful
from flask import request, make_response, jsonify
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.database import mongo
from monkey_island.cc.services.database import Database
from monkey_island.cc.services.infection_lifecycle import InfectionLifecycle
diff --git a/monkey/monkey_island/cc/resources/telemetry.py b/monkey/monkey_island/cc/resources/telemetry.py
index f6e833eeb..a8d7c2fbd 100644
--- a/monkey/monkey_island/cc/resources/telemetry.py
+++ b/monkey/monkey_island/cc/resources/telemetry.py
@@ -6,7 +6,7 @@ import dateutil
import flask_restful
from flask import request
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.database import mongo
from monkey_island.cc.resources.test.utils.telem_store import TestTelemStore
from monkey_island.cc.services.node import NodeService
diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py
index 6333f2feb..cb35fcf82 100644
--- a/monkey/monkey_island/cc/resources/telemetry_feed.py
+++ b/monkey/monkey_island/cc/resources/telemetry_feed.py
@@ -6,7 +6,7 @@ import flask_restful
from flask import request
import flask_pymongo
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.database import mongo
from monkey_island.cc.services.node import NodeService
diff --git a/monkey/monkey_island/cc/resources/test/clear_caches.py b/monkey/monkey_island/cc/resources/test/clear_caches.py
index f17193821..525841803 100644
--- a/monkey/monkey_island/cc/resources/test/clear_caches.py
+++ b/monkey/monkey_island/cc/resources/test/clear_caches.py
@@ -2,7 +2,7 @@ import logging
import flask_restful
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.attack.attack_report import AttackReportService
from monkey_island.cc.services.reporting.report import ReportService
diff --git a/monkey/monkey_island/cc/resources/test/log_test.py b/monkey/monkey_island/cc/resources/test/log_test.py
index f0f9af936..60222deac 100644
--- a/monkey/monkey_island/cc/resources/test/log_test.py
+++ b/monkey/monkey_island/cc/resources/test/log_test.py
@@ -2,7 +2,7 @@ from bson import json_util
import flask_restful
from flask import request
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.database import mongo, database
diff --git a/monkey/monkey_island/cc/resources/test/monkey_test.py b/monkey/monkey_island/cc/resources/test/monkey_test.py
index 100624780..900fde6ae 100644
--- a/monkey/monkey_island/cc/resources/test/monkey_test.py
+++ b/monkey/monkey_island/cc/resources/test/monkey_test.py
@@ -2,7 +2,7 @@ from bson import json_util
import flask_restful
from flask import request
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.database import mongo
diff --git a/monkey/monkey_island/cc/resources/zero_trust/finding_event.py b/monkey/monkey_island/cc/resources/zero_trust/finding_event.py
index 16c545241..44f686235 100644
--- a/monkey/monkey_island/cc/resources/zero_trust/finding_event.py
+++ b/monkey/monkey_island/cc/resources/zero_trust/finding_event.py
@@ -1,7 +1,7 @@
import flask_restful
import json
-from monkey_island.cc.auth import jwt_required
+from monkey_island.cc.resources.auth.auth import jwt_required
from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService
diff --git a/monkey/monkey_island/cc/ui/src/components/Main.js b/monkey/monkey_island/cc/ui/src/components/Main.js
index 4e8c0b1a0..07f9638d6 100644
--- a/monkey/monkey_island/cc/ui/src/components/Main.js
+++ b/monkey/monkey_island/cc/ui/src/components/Main.js
@@ -1,9 +1,9 @@
import React from 'react';
import {BrowserRouter as Router, NavLink, Redirect, Route, Switch} from 'react-router-dom';
import {Col, Grid, Row} from 'react-bootstrap';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck'
-import { faUndo } from '@fortawesome/free-solid-svg-icons/faUndo'
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
+import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
+import {faUndo} from '@fortawesome/free-solid-svg-icons/faUndo'
import RunServerPage from 'components/pages/RunServerPage';
import ConfigurePage from 'components/pages/ConfigurePage';
@@ -15,6 +15,7 @@ import ReportPage from 'components/pages/ReportPage';
import LicensePage from 'components/pages/LicensePage';
import AuthComponent from 'components/AuthComponent';
import LoginPageComponent from 'components/pages/LoginPage';
+import RegisterPageComponent from 'components/pages/RegisterPage';
import Notifier from 'react-desktop-notification';
import NotFoundPage from 'components/pages/NotFoundPage';
@@ -43,6 +44,15 @@ class AppComponent extends AuthComponent {
});
}
+ if (!res){
+ this.auth.needsRegistration()
+ .then(result => {
+ this.setState({
+ needsRegistration: result
+ });
+ })
+ }
+
if (res) {
this.authFetch('/api')
.then(res => res.json())
@@ -70,10 +80,16 @@ class AppComponent extends AuthComponent {
case true:
return page_component;
case false:
- return