diff --git a/monkey/common/utils/exceptions.py b/monkey/common/utils/exceptions.py index 5103b297e..4b27cd04d 100644 --- a/monkey/common/utils/exceptions.py +++ b/monkey/common/utils/exceptions.py @@ -24,3 +24,7 @@ class AlreadyRegisteredError(RegistrationNotNeededError): class RulePathCreatorNotFound(Exception): """ Raise to indicate that ScoutSuite rule doesn't have a path creator""" + + +class InvalidAWSKeys(Exception): + """ Raise to indicate that AWS API keys are invalid""" diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 8ed7189f3..38ce7f23b 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -47,6 +47,8 @@ from monkey_island.cc.resources.test.monkey_test import MonkeyTest from monkey_island.cc.resources.version_update import VersionUpdate from monkey_island.cc.resources.zero_trust.finding_event import \ ZeroTrustFindingEvent +from monkey_island.cc.resources.zero_trust.scoutsuite_auth.aws_keys import AWSKeys +from monkey_island.cc.resources.zero_trust.scoutsuite_auth.scoutsuite_auth import ScoutSuiteAuth from monkey_island.cc.services.database import Database from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService from monkey_island.cc.services.representations import output_json @@ -146,6 +148,8 @@ def init_api_resources(api): api.add_resource(VersionUpdate, '/api/version-update', '/api/version-update/') api.add_resource(RemotePortCheck, '/api/monkey_control/check_remote_port/') api.add_resource(StartedOnIsland, '/api/monkey_control/started_on_island') + api.add_resource(ScoutSuiteAuth, '/api/scoutsuite_auth/') + api.add_resource(AWSKeys, '/api/aws_keys') api.add_resource(MonkeyTest, '/api/test/monkey') api.add_resource(ClearCaches, '/api/test/clear_caches') diff --git a/monkey/monkey_island/cc/resources/zero_trust/scoutsuite_auth/aws_keys.py b/monkey/monkey_island/cc/resources/zero_trust/scoutsuite_auth/aws_keys.py new file mode 100644 index 000000000..53e757f11 --- /dev/null +++ b/monkey/monkey_island/cc/resources/zero_trust/scoutsuite_auth/aws_keys.py @@ -0,0 +1,11 @@ +import flask_restful + +from monkey_island.cc.resources.auth.auth import jwt_required +from monkey_island.cc.services.zero_trust.scoutsuite.scoutsuite_auth_service import get_aws_keys + + +class AWSKeys(flask_restful.Resource): + + @jwt_required + def get(self): + return get_aws_keys() diff --git a/monkey/monkey_island/cc/resources/zero_trust/scoutsuite_auth/scoutsuite_auth.py b/monkey/monkey_island/cc/resources/zero_trust/scoutsuite_auth/scoutsuite_auth.py new file mode 100644 index 000000000..9a07d436a --- /dev/null +++ b/monkey/monkey_island/cc/resources/zero_trust/scoutsuite_auth/scoutsuite_auth.py @@ -0,0 +1,34 @@ +import json + +import flask_restful +from flask import request + +from common.cloud.scoutsuite_consts import PROVIDERS +from common.utils.exceptions import InvalidAWSKeys +from monkey_island.cc.resources.auth.auth import jwt_required +from monkey_island.cc.services.zero_trust.scoutsuite.scoutsuite_auth_service import is_cloud_authentication_setup, \ + set_aws_keys + + +class ScoutSuiteAuth(flask_restful.Resource): + + @jwt_required + def get(self, provider: PROVIDERS): + if provider == PROVIDERS.AWS.value: + is_setup, message = is_cloud_authentication_setup(provider) + return {'is_setup': is_setup, 'message': message} + else: + return {'is_setup': False, 'message': ''} + + @jwt_required + def post(self, provider: PROVIDERS): + key_info = json.loads(request.data) + error_msg = '' + if provider == PROVIDERS.AWS.value: + try: + set_aws_keys(access_key_id=key_info['accessKeyId'], + secret_access_key=key_info['secretAccessKey'], + session_token=key_info['sessionToken']) + except InvalidAWSKeys as e: + error_msg = str(e) + return {'error_msg': error_msg} diff --git a/monkey/monkey_island/cc/ui/src/components/pages/LoginPage.js b/monkey/monkey_island/cc/ui/src/components/pages/LoginPage.js index cbe3867ee..961c1899c 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/LoginPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/LoginPage.js @@ -69,7 +69,7 @@ class LoginPageComponent extends React.Component {
this.updateUsername(evt)} type='text' placeholder='Username'/> this.updatePassword(evt)} type='password' placeholder='Password'/> - { diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js b/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js index 3b8188221..093dba950 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js @@ -92,7 +92,7 @@ class RegisterPageComponent extends React.Component { this.updateUsername(evt)} type='text' placeholder='Username'/> this.updatePassword(evt)} type='password' placeholder='Password'/> - diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js index fa724d6f6..ddf7ef6cc 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js @@ -7,7 +7,6 @@ import InlineSelection from '../../ui-components/inline-selection/InlineSelectio import {cloneDeep} from 'lodash'; import {faCloud, faExpandArrowsAlt} from '@fortawesome/free-solid-svg-icons'; import RunOnIslandButton from './RunOnIslandButton'; -import AWSSetup from './scoutsuite-setup/AWSSetup'; import CloudOptions from './scoutsuite-setup/CloudOptions'; function RunOptions(props) { diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSSetup.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSCLISetup.js similarity index 71% rename from monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSSetup.js rename to monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSCLISetup.js index 6fe85936e..69ab4903f 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSSetup.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSCLISetup.js @@ -1,16 +1,17 @@ import {Button} from 'react-bootstrap'; import React from 'react'; -import InlineSelection from '../../../ui-components/inline-selection/InlineSelection'; -import CloudOptions from './CloudOptions'; -import {COLUMN_SIZES} from '../../../ui-components/inline-selection/utils'; -import '../../../../styles/components/scoutsuite/AWSSetup.scss'; +import InlineSelection from '../../../../ui-components/inline-selection/InlineSelection'; +import {COLUMN_SIZES} from '../../../../ui-components/inline-selection/utils'; +import '../../../../../styles/components/scoutsuite/AWSSetup.scss'; +import AWSSetupOptions from './AWSSetupOptions'; -export default function AWSSetup(props) { + +export default function AWSCLISetup(props) { return InlineSelection(getContents, { ...props, collumnSize: COLUMN_SIZES.LARGE, onBackButtonClick: () => { - props.setComponent(CloudOptions, props) + props.setComponent(AWSSetupOptions, props); } }) } @@ -33,9 +34,11 @@ const getContents = (props) => {
  • 2. Run aws configure. It's important to configure credentials, which allows ScoutSuite to get information about your cloud configuration. The most trivial way to do so is to - provide .
  • diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSKeySetup.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSKeySetup.js new file mode 100644 index 000000000..3643ba89c --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSKeySetup.js @@ -0,0 +1,176 @@ +import React, {useEffect, useState} from 'react'; +import InlineSelection from '../../../../ui-components/inline-selection/InlineSelection'; +import {COLUMN_SIZES} from '../../../../ui-components/inline-selection/utils'; +import AWSSetupOptions from './AWSSetupOptions'; +import {Button, Col, Form, Row} from 'react-bootstrap'; +import AuthComponent from '../../../../AuthComponent'; +import '../../../../../styles/components/scoutsuite/AWSSetup.scss'; +import {PROVIDERS} from '../ProvidersEnum'; +import classNames from 'classnames'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown'; +import {faChevronUp} from '@fortawesome/free-solid-svg-icons/faChevronUp'; +import {faQuestion} from '@fortawesome/free-solid-svg-icons'; +import Collapse from '@kunukn/react-collapse/dist/Collapse.umd'; +import keySetupForAnyUserImage from '../../../../../images/aws_keys_tutorial-any-user.png'; +import keySetupForCurrentUserImage from '../../../../../images/aws_keys_tutorial-current-user.png'; +import ImageModal from '../../../../ui-components/ImageModal'; + + +export default function AWSCLISetup(props) { + return InlineSelection(getContents, { + ...props, + collumnSize: COLUMN_SIZES.LARGE, + onBackButtonClick: () => { + props.setComponent(AWSSetupOptions, props); + } + }) +} + +const authComponent = new AuthComponent({}) + +const getContents = (props) => { + + const [accessKeyId, setAccessKeyId] = useState(''); + const [secretAccessKey, setSecretAccessKey] = useState(''); + const [sessionToken, setSessionToken] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [successMessage, setSuccessMessage] = useState(''); + const [docCollapseOpen, setDocCollapseOpen] = useState(false); + + function submitKeys(event) { + event.preventDefault(); + setSuccessMessage(''); + setErrorMessage(''); + authComponent.authFetch( + '/api/scoutsuite_auth/' + PROVIDERS.AWS, + { + 'method': 'POST', + 'body': JSON.stringify({ + 'accessKeyId': accessKeyId, + 'secretAccessKey': secretAccessKey, + 'sessionToken': sessionToken + }) + }) + .then(res => res.json()) + .then(res => { + if (res['error_msg'] === '') { + setSuccessMessage('AWS keys saved!'); + } else { + setErrorMessage(res['error_msg']); + } + }); + } + + useEffect(() => { + authComponent.authFetch('/api/aws_keys') + .then(res => res.json()) + .then(res => { + setAccessKeyId(res['access_key_id']); + setSecretAccessKey(res['secret_access_key']); + setSessionToken(res['session_token']); + }); + }, [props]); + + + // TODO separate into standalone component + function getKeyCreationDocsContent() { + return ( +
    +
    Tips
    +

    Consider creating a new user account just for this activity. Assign only ReadOnlyAccess and  + SecurityAudit policies.

    + +
    Keys for custom user
    +

    1. Open the IAM console at https://console.aws.amazon.com/iam/ .

    +

    2. In the navigation pane, choose Users.

    +

    3. Choose the name of the user whose access keys you want to create, and then choose the Security credentials + tab.

    +

    4. In the Access keys section, choose Create access key.

    +

    To view the new access key pair, choose Show. Your credentials will look something like this:

    +

    Access key ID: AKIAIOSFODNN7EXAMPLE

    +

    Secret access key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

    + + + + + + +
    Keys for current user
    +

    1. Click on your username in the upper right corner.

    +

    2. Click on "My security credentials".

    +

    3. In the Access keys section, choose Create access key.

    +

    To view the new access key pair, choose Show. Your credentials will look something like this:

    +

    Access key ID: AKIAIOSFODNN7EXAMPLE

    +

    Secret access key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

    + + + + + +
    ); + } + + function getKeyCreationDocs() { + return ( +
    + + +
    ); + } + + return ( +
    + {getKeyCreationDocs()} + + setAccessKeyId(evt.target.value)} + type='text' + placeholder='Access key ID' + value={accessKeyId}/> + setSecretAccessKey(evt.target.value)} + type='password' + placeholder='Secret access key' + value={secretAccessKey}/> + setSessionToken(evt.target.value)} + type='text' + placeholder='Session token (optional, only for temp. keys)' + value={sessionToken}/> + { + errorMessage ? +
    {errorMessage}
    + : + '' + } + { + successMessage ? +
    {successMessage}  + Go back and  + to start AWS scan!
    + : + '' + } + + + + + + +
    + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSSetupOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSSetupOptions.js new file mode 100644 index 000000000..a66a893d8 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/AWSConfiguration/AWSSetupOptions.js @@ -0,0 +1,40 @@ +import React from 'react'; +import InlineSelection from '../../../../ui-components/inline-selection/InlineSelection'; +import NextSelectionButton from '../../../../ui-components/inline-selection/NextSelectionButton'; +import {faKey, faTerminal} from '@fortawesome/free-solid-svg-icons'; +import AWSCLISetup from './AWSCLISetup'; +import CloudOptions from '../CloudOptions'; +import AWSKeySetup from './AWSKeySetup'; + + +const AWSSetupOptions = (props) => { + return InlineSelection(getContents, { + ...props, + onBackButtonClick: () => { + props.setComponent(CloudOptions, props); + } + }) +} + +const getContents = (props) => { + return ( + <> + { + props.setComponent(AWSKeySetup, + {setComponent: props.setComponent}) + }}/> + { + props.setComponent(AWSCLISetup, + {setComponent: props.setComponent}) + }}/> + + ) +} + +export default AWSSetupOptions; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/CloudOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/CloudOptions.js index 1605a0eaa..aa4dedd2e 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/CloudOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/scoutsuite-setup/CloudOptions.js @@ -1,8 +1,10 @@ -import React from 'react'; +import React, {useEffect, useState} from 'react'; import InlineSelection from '../../../ui-components/inline-selection/InlineSelection'; import NextSelectionButton from '../../../ui-components/inline-selection/NextSelectionButton'; -import {faCloud} from '@fortawesome/free-solid-svg-icons'; -import AWSSetup from './AWSSetup'; +import {faCheck, faCloud, faSync} from '@fortawesome/free-solid-svg-icons'; +import AWSSetupOptions from './AWSConfiguration/AWSSetupOptions'; +import {PROVIDERS} from './ProvidersEnum'; +import AuthComponent from '../../../AuthComponent'; const CloudOptions = (props) => { @@ -14,14 +16,38 @@ const CloudOptions = (props) => { }) } +const authComponent = new AuthComponent({}) + const getContents = (props) => { + + const [description, setDescription] = useState("Loading..."); + const [iconType, setIconType] = useState('spinning-icon'); + const [icon, setIcon] = useState(faSync); + + useEffect(() => { + authComponent.authFetch('/api/scoutsuite_auth/' + PROVIDERS.AWS) + .then(res => res.json()) + .then(res => { + if(res.is_setup){ + setDescription(res.message + 'Click next to change the configuration.'); + setIconType('icon-success'); + setIcon(faCheck); + } else { + setDescription('Setup Amazon Web Services infrastructure scan.'); + setIconType('') + setIcon(faCloud); + } + }); + }, [props]); + return ( <> { - props.setComponent(AWSSetup, + props.setComponent(AWSSetupOptions, {setComponent: props.setComponent}) }}/> diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/ImageModal.js b/monkey/monkey_island/cc/ui/src/components/ui-components/ImageModal.js new file mode 100644 index 000000000..12632e811 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/ImageModal.js @@ -0,0 +1,33 @@ +import React, {useState} from 'react'; +import PropTypes from 'prop-types'; +import {Button, Image, Modal} from 'react-bootstrap'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faSearchPlus} from '@fortawesome/free-solid-svg-icons'; + + +const ImageModal = (props) => { + + const [isModalOpen, setIsModalOpen] = useState(false); + + return ( +
    + + setIsModalOpen(false)}> + + + + +
    + ); +} + +export default ImageModal; + +ImageModal.propTypes = { + image: PropTypes.element +} diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js index 51bf341bd..502fbf6b1 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js @@ -18,8 +18,8 @@ export default function InlineSelection(WrappedComponent, props) { ) } -function renderBackButton(props){ - if(props.onBackButtonClick !== undefined){ +function renderBackButton(props) { + if (props.onBackButtonClick !== undefined) { return (); } } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js index 7a7c47087..174dce254 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js @@ -6,7 +6,8 @@ import {faAngleRight} from '@fortawesome/free-solid-svg-icons'; export default function nextSelectionButton(props) { let description = props.description !== undefined ? (

    {props.description}

    ) : '' - let icon = props.icon !== undefined ? () : '' + let iconType = props.iconType !== undefined ? props.iconType : '' + let icon = props.icon !== undefined ? () : '' return ( @@ -24,6 +25,7 @@ export default function nextSelectionButton(props) { nextSelectionButton.propTypes = { title: PropTypes.string, + iconType: PropTypes.string, icon: FontAwesomeIcon, description: PropTypes.string, onButtonClick: PropTypes.func diff --git a/monkey/monkey_island/cc/ui/src/images/aws_keys_tutorial-any-user.png b/monkey/monkey_island/cc/ui/src/images/aws_keys_tutorial-any-user.png new file mode 100644 index 000000000..c0dfb4111 Binary files /dev/null and b/monkey/monkey_island/cc/ui/src/images/aws_keys_tutorial-any-user.png differ diff --git a/monkey/monkey_island/cc/ui/src/images/aws_keys_tutorial-current-user.png b/monkey/monkey_island/cc/ui/src/images/aws_keys_tutorial-current-user.png new file mode 100644 index 000000000..b1b3a997f Binary files /dev/null and b/monkey/monkey_island/cc/ui/src/images/aws_keys_tutorial-current-user.png differ diff --git a/monkey/monkey_island/cc/ui/src/styles/Main.scss b/monkey/monkey_island/cc/ui/src/styles/Main.scss index 602c62b3d..400af4054 100644 --- a/monkey/monkey_island/cc/ui/src/styles/Main.scss +++ b/monkey/monkey_island/cc/ui/src/styles/Main.scss @@ -3,6 +3,7 @@ @import '../../node_modules/bootstrap/scss/bootstrap'; // Imports that require variables +@import 'components/Buttons'; @import 'pages/report/ReportPage.scss'; @import 'pages/report/AttackReport.scss'; @import 'pages/ConfigurationPage'; @@ -13,11 +14,12 @@ @import 'components/AdvancedMultiSelect'; @import 'components/particle-component/ParticleBackground'; @import 'components/scoutsuite/ResourceDropdown'; +@import 'components/ImageModal'; +@import 'components/Icons'; @import 'components/inline-selection/InlineSelection'; @import 'components/inline-selection/NextSelectionButton'; @import 'components/inline-selection/BackButton'; @import 'components/inline-selection/CommandDisplay'; -@import 'components/Icons'; // Define custom elements after bootstrap import diff --git a/monkey/monkey_island/cc/ui/src/styles/components/Icons.scss b/monkey/monkey_island/cc/ui/src/styles/components/Icons.scss index ed75d8a9d..36c9082b8 100644 --- a/monkey/monkey_island/cc/ui/src/styles/components/Icons.scss +++ b/monkey/monkey_island/cc/ui/src/styles/components/Icons.scss @@ -3,6 +3,14 @@ display: inline-block; } +.icon-success { + color: $success +} + +.icon-failed { + color: $danger; +} + @keyframes spin-animation { 0% { transform: rotate(0deg); diff --git a/monkey/monkey_island/cc/ui/src/styles/components/ImageModal.scss b/monkey/monkey_island/cc/ui/src/styles/components/ImageModal.scss new file mode 100644 index 000000000..bfe630b5f --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/styles/components/ImageModal.scss @@ -0,0 +1,49 @@ +.image-modal .image-modal-thumbnail { + position: relative; + padding: 7px; +} + +.image-modal .image-modal-thumbnail:focus { + background-color: white; + border-color: white; + box-shadow: 0 2px 6px #ccc; +} + +.image-modal .image-modal-thumbnail:hover { + background-color: white; + border-color: white; + box-shadow: 0 2px 6px #ccc; +} + +.image-modal .image-modal-thumbnail-icon { + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + position: absolute; + min-width: 40px; + min-height: 40px; +} + +.image-modal:hover .image-modal-thumbnail-icon { + color: $monkey-yellow; +} + +.image-modal-screen { + padding: 0; +} + +.image-modal-screen .modal-dialog { + margin: 0; + top: 0; + width: 100%; + padding: 30px; + max-width: none; + max-height: none; +} + +.image-modal-screen .modal-dialog .modal-content { + width: fit-content; + margin: auto; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/AWSSetup.scss b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/AWSSetup.scss index c1546ac81..9d8b793aa 100644 --- a/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/AWSSetup.scss +++ b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/AWSSetup.scss @@ -1,17 +1,74 @@ -.aws-scoutsuite-configuration a{ +.aws-scoutsuite-configuration a { display: inline-block; padding: 0 0 3px 0; } -.aws-scoutsuite-configuration ol{ +.aws-scoutsuite-configuration ol { padding-left: 15px; margin-bottom: 30px; } -.aws-scoutsuite-configuration ol.nested-ol{ +.aws-scoutsuite-configuration ol.nested-ol { margin-bottom: 0; } -.aws-scoutsuite-configuration li{ +.aws-scoutsuite-configuration li { margin-bottom: 5px; } + +.monkey-submit-button { + margin-bottom: 15px; +} + +.aws-scoutsuite-key-configuration .collapse-item { + padding: 0; + margin-bottom: 15px; +} + +.aws-scoutsuite-key-configuration .collapse-item .btn-collapse .question-icon { + display: inline-block; + margin-right: 7px; + margin-bottom: 1px; +} + +.aws-scoutsuite-key-configuration .collapse-item .btn-collapse p { + display: inline-block; + margin-bottom: 0; + font-size: 1.2em; + margin-left: 5px +} + +.aws-scoutsuite-key-configuration .key-creation-tutorial { + padding-bottom: 10px; +} + +.aws-scoutsuite-key-configuration .key-creation-tutorial p { + margin-bottom: 2px; + font-weight: 400; +} + +.aws-scoutsuite-key-configuration .key-creation-tutorial h5 { + margin-top: 15px; + font-weight: 600; +} + +.aws-scoutsuite-key-configuration .key-creation-tutorial p:first-child { + margin-top: 15px; +} + +.aws-scoutsuite-key-configuration .image-modal { + margin-top: 5px; +} + +.aws-scoutsuite-key-configuration .key-creation-tutorial img { + max-width: 100%; + max-height: 100%; + border: 1px solid black; +} + +.link-in-success-message { + padding: 0 !important; + vertical-align: initial !important; +} + + diff --git a/monkey/monkey_island/cc/ui/src/styles/pages/AuthPage.scss b/monkey/monkey_island/cc/ui/src/styles/pages/AuthPage.scss index 8b1b10502..e3ecbd0e6 100644 --- a/monkey/monkey_island/cc/ui/src/styles/pages/AuthPage.scss +++ b/monkey/monkey_island/cc/ui/src/styles/pages/AuthPage.scss @@ -15,23 +15,6 @@ margin-top: 20px; } -#auth-button { - border-color: #3f3f3f; - font-size: 1.3em; - width: 100%; - background-color: #3f3f3f; - color: $monkey-yellow; -} - -#auth-button:hover { - border-color: $monkey-yellow; - font-size: 1.3em; - font-weight: bold; - width: 100%; - background-color: $monkey-yellow; - color: #000000; -} - .monkey-detective { max-height: 500px; }