diff --git a/.github/workflows/malcolm-iso-build-docker-wrap-push-ghcr.yml b/.github/workflows/malcolm-iso-build-docker-wrap-push-ghcr.yml index a33321072..9f68aaaa8 100644 --- a/.github/workflows/malcolm-iso-build-docker-wrap-push-ghcr.yml +++ b/.github/workflows/malcolm-iso-build-docker-wrap-push-ghcr.yml @@ -70,12 +70,12 @@ jobs: virt-what \ xorriso \ xz-utils - git clone --depth=1 --single-branch --recurse-submodules --shallow-submodules --branch='debian/1%20210407' 'https://salsa.debian.org/live-team/live-build.git' /tmp/live-build + git clone --depth=1 --single-branch --recurse-submodules --shallow-submodules --branch='debian/1%20230131' 'https://salsa.debian.org/live-team/live-build.git' /tmp/live-build cd /tmp/live-build dpkg-buildpackage -b -uc -us cd /tmp sudo dpkg -i /tmp/live-build*.deb - rm -rf /tmp/live-build + sudo rm -rf /tmp/live-build /tmp/live-build*.deb - name: Checkout uses: actions/checkout@v3 @@ -92,7 +92,7 @@ jobs: - name: Extract Malcolm version shell: bash - run: echo "mversion=$(grep -P "^\s+image:\s*malcolm" docker-compose.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" >> $GITHUB_OUTPUT + run: echo "mversion=$(grep -P "^\s+image:.*/malcolm/" docker-compose.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" >> $GITHUB_OUTPUT id: extract_malcolm_version - name: Build image diff --git a/.github/workflows/sensor-iso-build-docker-wrap-push-ghcr.yml b/.github/workflows/sensor-iso-build-docker-wrap-push-ghcr.yml index 2fe46a799..3cfe30c26 100644 --- a/.github/workflows/sensor-iso-build-docker-wrap-push-ghcr.yml +++ b/.github/workflows/sensor-iso-build-docker-wrap-push-ghcr.yml @@ -66,10 +66,12 @@ jobs: squashfs-tools \ virt-what \ xorriso - git clone --depth=1 --single-branch --recurse-submodules --shallow-submodules --branch='debian/1%20210407' 'https://salsa.debian.org/live-team/live-build.git' /tmp/live-build - cd /tmp/live-build - dpkg-buildpackage -b -uc -us - sudo dpkg -i /tmp/live-build*.deb + git clone --depth=1 --single-branch --recurse-submodules --shallow-submodules --branch='debian/1%20230131' 'https://salsa.debian.org/live-team/live-build.git' /tmp/live-build + cd /tmp/live-build + dpkg-buildpackage -b -uc -us + cd /tmp + sudo dpkg -i /tmp/live-build*.deb + sudo rm -rf /tmp/live-build /tmp/live-build*.deb - name: Checkout uses: actions/checkout@v3 @@ -86,7 +88,7 @@ jobs: - name: Extract Malcolm version shell: bash - run: echo "mversion=$(grep -P "^\s+image:\s*malcolm" docker-compose.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" >> $GITHUB_OUTPUT + run: echo "mversion=$(grep -P "^\s+image:.*/malcolm/" docker-compose.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" >> $GITHUB_OUTPUT id: extract_malcolm_version - name: Build image diff --git a/Dockerfiles/api.Dockerfile b/Dockerfiles/api.Dockerfile index 4b181663b..edf8f67f7 100644 --- a/Dockerfiles/api.Dockerfile +++ b/Dockerfiles/api.Dockerfile @@ -1,4 +1,4 @@ -FROM python:3-slim-bullseye as builder +FROM python:3-slim-bookworm as builder ENV DEBIAN_FRONTEND noninteractive ENV TERM xterm @@ -8,8 +8,8 @@ ENV PYTHONUNBUFFERED 1 RUN apt-get update -q \ && apt-get -y -q upgrade \ && apt-get install -y gcc \ - && python3 -m pip install --upgrade pip \ - && python3 -m pip install flake8 + && python3 -m pip install --break-system-packages --no-cache-dir --upgrade pip \ + && python3 -m pip install --break-system-packages --no-cache-dir flake8 COPY ./api /usr/src/app/ COPY scripts/malcolm_utils.py /usr/src/app/ @@ -18,7 +18,7 @@ WORKDIR /usr/src/app RUN python3 -m pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt \ && flake8 --ignore=E203,E501,F401,W503 -FROM python:3-slim-bullseye +FROM python:3-slim-bookworm # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -79,7 +79,7 @@ COPY --from=ghcr.io/mmguero-dev/gostatic --chmod=755 /goStatic /usr/bin/goStatic RUN apt-get -q update \ && apt-get -y -q --no-install-recommends upgrade \ - && apt-get -y -q --no-install-recommends install curl netcat rsync tini \ + && apt-get -y -q --no-install-recommends install curl netcat-openbsd rsync tini \ && python3 -m pip install --upgrade pip \ && python3 -m pip install --no-cache /wheels/* \ && groupadd --gid ${DEFAULT_GID} ${PGROUP} \ diff --git a/Dockerfiles/arkime.Dockerfile b/Dockerfiles/arkime.Dockerfile index 7b3850acf..393c74e32 100644 --- a/Dockerfiles/arkime.Dockerfile +++ b/Dockerfiles/arkime.Dockerfile @@ -1,10 +1,10 @@ -FROM debian:11-slim AS build +FROM debian:12-slim AS build # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. ENV DEBIAN_FRONTEND noninteractive -ENV ARKIME_VERSION "v4.3.2" +ENV ARKIME_VERSION "v4.4.0" ENV ARKIME_DIR "/opt/arkime" ENV ARKIME_URL "https://github.com/arkime/arkime.git" ENV ARKIME_LOCALELASTICSEARCH no @@ -33,6 +33,7 @@ RUN apt-get -q update && \ libkrb5-dev \ libmaxminddb-dev \ libpcap0.8-dev \ + libpcre3-dev \ libssl-dev \ libtool \ libwww-perl \ @@ -49,7 +50,7 @@ RUN apt-get -q update && \ swig \ wget \ zlib1g-dev && \ - pip3 install --no-cache-dir beautifulsoup4 && \ + python3 -m pip install --break-system-packages --no-cache-dir beautifulsoup4 meson && \ cd /opt && \ git clone --recurse-submodules --branch="$ARKIME_VERSION" "$ARKIME_URL" "./arkime-"$ARKIME_VERSION && \ cd "./arkime-"$ARKIME_VERSION && \ @@ -61,7 +62,7 @@ RUN apt-get -q update && \ python3 /opt/bs4_remove_div.py -i ./viewer/vueapp/src/components/users/Users.vue -o ./viewer/vueapp/src/components/users/Users.new -c "new-user-form" && \ mv -vf ./viewer/vueapp/src/components/users/Users.new ./viewer/vueapp/src/components/users/Users.vue && \ sed -i 's/v-if.*password.*"/v-if="false"/g' ./viewer/vueapp/src/components/settings/Settings.vue && \ - rm -rf ./viewer/vueapp/src/components/upload ./capture/plugins/suricata* && \ + rm -rf ./capture/plugins/suricata* && \ sed -i "s/^\(ARKIME_LOCALELASTICSEARCH=\).*/\1"$ARKIME_LOCALELASTICSEARCH"/" ./release/Configure && \ sed -i "s/^\(ARKIME_INET=\).*/\1"$ARKIME_INET"/" ./release/Configure && \ ./easybutton-build.sh && \ @@ -71,7 +72,7 @@ RUN apt-get -q update && \ rm -f ${ARKIME_DIR}/wiseService/source.* ${ARKIME_DIR}/etc/*.systemd.service && \ bash -c "file ${ARKIME_DIR}/bin/* ${ARKIME_DIR}/node-v*/bin/* | grep 'ELF 64-bit' | sed 's/:.*//' | xargs -l -r strip -v --strip-unneeded" -FROM debian:11-slim +FROM debian:12-slim LABEL maintainer="malcolm@inl.gov" LABEL org.opencontainers.image.authors='malcolm@inl.gov' @@ -133,7 +134,7 @@ ENV PCAP_MONITOR_HOST $PCAP_MONITOR_HOST COPY --from=build $ARKIME_DIR $ARKIME_DIR -RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.list && \ +RUN sed -i "s/main$/main contrib non-free/g" /etc/apt/sources.list.d/debian.sources && \ apt-get -q update && \ apt-get -y -q --no-install-recommends upgrade && \ apt-get install -q -y --no-install-recommends \ @@ -148,14 +149,14 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l libkrb5-3 \ libmaxminddb0 \ libpcap0.8 \ - libssl1.0 \ + libpcre3 \ + libssl3 \ libtool \ libwww-perl \ libyaml-0-2 \ libzmq5 \ procps \ psmisc \ - python \ python3 \ python3-pip \ python3-setuptools \ @@ -164,15 +165,15 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l rsync \ sudo \ supervisor \ + tini \ vim-tiny \ wget \ - tini \ tar gzip unzip cpio bzip2 lzma xz-utils p7zip-full unrar zlib1g && \ - pip3 install --no-cache-dir beautifulsoup4 pyzmq watchdog && \ + python3 -m pip install --break-system-packages --no-cache-dir beautifulsoup4 pyzmq watchdog && \ ln -sfr $ARKIME_DIR/bin/npm /usr/local/bin/npm && \ ln -sfr $ARKIME_DIR/bin/node /usr/local/bin/node && \ ln -sfr $ARKIME_DIR/bin/npx /usr/local/bin/npx && \ - apt-get -q -y --purge remove gcc gcc-10 cpp cpp-10 libssl-dev && \ + apt-get -q -y --purge remove gcc gcc-12 cpp cpp-12 libssl-dev && \ apt-get -q -y autoremove && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* @@ -206,7 +207,7 @@ RUN [ ${#MAXMIND_GEOIP_DB_LICENSE_KEY} -gt 1 ] && for DB in ASN Country City; do rm -f "GeoLite2-$DB*"; \ done; \ curl -s -S -L -o $ARKIME_DIR/etc/ipv4-address-space.csv "https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.csv" && \ - curl -s -S -L -o $ARKIME_DIR/etc/oui.txt "https://raw.githubusercontent.com/wireshark/wireshark/master/manuf" + curl -s -S -L -o $ARKIME_DIR/etc/oui.txt "https://gitlab.com/wireshark/wireshark/raw/release-4.0/manuf" RUN groupadd --gid $DEFAULT_GID $PGROUP && \ useradd -M --uid $DEFAULT_UID --gid $DEFAULT_GID --home $ARKIME_DIR $PUSER && \ diff --git a/Dockerfiles/dashboards-helper.Dockerfile b/Dockerfiles/dashboards-helper.Dockerfile index 4953e5aa6..d6b1b44d5 100644 --- a/Dockerfiles/dashboards-helper.Dockerfile +++ b/Dockerfiles/dashboards-helper.Dockerfile @@ -47,10 +47,10 @@ ENV DASHBOARDS_URL $DASHBOARDS_URL ENV DASHBOARDS_DARKMODE $DASHBOARDS_DARKMODE ENV PATH="/data:${PATH}" -ENV SUPERCRONIC_VERSION "0.2.25" +ENV SUPERCRONIC_VERSION "0.2.26" ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" ENV SUPERCRONIC "supercronic-linux-amd64" -ENV SUPERCRONIC_SHA1SUM "642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" ENV SUPERCRONIC_CRONTAB "/etc/crontab" ENV ECS_RELEASES_URL "https://api.github.com/repos/elastic/ecs/releases/latest" diff --git a/Dockerfiles/dashboards.Dockerfile b/Dockerfiles/dashboards.Dockerfile index 9ab901727..b97bf8b73 100644 --- a/Dockerfiles/dashboards.Dockerfile +++ b/Dockerfiles/dashboards.Dockerfile @@ -128,8 +128,8 @@ RUN yum upgrade -y && \ /usr/share/opensearch-dashboards/bin/opensearch-dashboards-plugin install file:///tmp/kbnSankeyVis.zip --allow-root && \ cd /tmp && \ # unzip transformVis.zip opensearch-dashboards/transformVis/opensearch_dashboards.json opensearch-dashboards/transformVis/package.json && \ - # sed -i "s/2\.7\.0/2\.8\.0/g" opensearch-dashboards/transformVis/opensearch_dashboards.json && \ - # sed -i "s/2\.7\.0/2\.8\.0/g" opensearch-dashboards/transformVis/package.json && \ + # sed -i "s/2\.9\.0/2\.9\.0/g" opensearch-dashboards/transformVis/opensearch_dashboards.json && \ + # sed -i "s/2\.9\.0/2\.9\.0/g" opensearch-dashboards/transformVis/package.json && \ # zip transformVis.zip opensearch-dashboards/transformVis/opensearch_dashboards.json opensearch-dashboards/transformVis/package.json && \ cd /usr/share/opensearch-dashboards/plugins && \ /usr/share/opensearch-dashboards/bin/opensearch-dashboards-plugin install file:///tmp/transformVis.zip --allow-root && \ diff --git a/Dockerfiles/file-monitor.Dockerfile b/Dockerfiles/file-monitor.Dockerfile index 8f0fa94b5..c596525a1 100644 --- a/Dockerfiles/file-monitor.Dockerfile +++ b/Dockerfiles/file-monitor.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -91,15 +91,15 @@ ENV EXTRACTED_FILE_HTTP_SERVER_ENCRYPT $EXTRACTED_FILE_HTTP_SERVER_ENCRYPT ENV EXTRACTED_FILE_HTTP_SERVER_KEY $EXTRACTED_FILE_HTTP_SERVER_KEY ENV EXTRACTED_FILE_HTTP_SERVER_PORT $EXTRACTED_FILE_HTTP_SERVER_PORT -ENV SUPERCRONIC_VERSION "0.2.25" +ENV SUPERCRONIC_VERSION "0.2.26" ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" ENV SUPERCRONIC "supercronic-linux-amd64" -ENV SUPERCRONIC_SHA1SUM "642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" ENV SUPERCRONIC_CRONTAB "/etc/crontab" COPY --chmod=755 shared/bin/yara_rules_setup.sh /usr/local/bin/ -RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.list && \ +RUN sed -i "s/main$/main contrib non-free/g" /etc/apt/sources.list.d/debian.sources && \ apt-get -q update && \ apt-get -y -q --no-install-recommends upgrade && \ apt-get install --no-install-recommends -y -q \ @@ -112,13 +112,13 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l gcc \ git \ jq \ - libclamunrar9 \ + libclamunrar11 \ libjansson-dev \ libjansson4 \ libmagic-dev \ libmagic1 \ libssl-dev \ - libssl1.1 \ + libssl3 \ libtool \ make \ pkg-config \ @@ -135,7 +135,7 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l python3-requests \ python3-zmq \ rsync && \ - pip3 install clamd supervisor yara-python python-magic psutil pycryptodome watchdog && \ + python3 -m pip install --break-system-packages --no-cache-dir clamd supervisor yara-python python-magic psutil pycryptodome watchdog && \ curl -fsSLO "$SUPERCRONIC_URL" && \ echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ chmod +x "$SUPERCRONIC" && \ @@ -167,9 +167,9 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l automake \ build-essential \ gcc \ - gcc-8 \ + gcc-12 \ libc6-dev \ - libgcc-8-dev \ + libgcc-12-dev \ libjansson-dev \ libmagic-dev \ libssl-dev \ diff --git a/Dockerfiles/file-upload.Dockerfile b/Dockerfiles/file-upload.Dockerfile index 5d0a8ddef..d39d1a20d 100644 --- a/Dockerfiles/file-upload.Dockerfile +++ b/Dockerfiles/file-upload.Dockerfile @@ -1,27 +1,21 @@ -FROM debian:11-slim AS build +FROM debian:12-slim AS npmget # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. ENV DEBIAN_FRONTEND noninteractive -ENV JQUERY_FILE_UPLOAD_VERSION v9.19.1 -ENV JQUERY_FILE_UPLOAD_URL "https://github.com/blueimp/jQuery-File-Upload/archive/${JQUERY_FILE_UPLOAD_VERSION}.tar.gz" - RUN apt-get -q update && \ apt-get -y -q --no-install-recommends upgrade && \ - apt-get -y -q --allow-downgrades --allow-remove-essential --allow-change-held-packages install --no-install-recommends npm node-encoding git ca-certificates curl wget && \ - npm install -g bower && \ - mkdir -p /jQuery-File-Upload && \ - curl -sSL "$JQUERY_FILE_UPLOAD_URL" | tar xzvf - -C /jQuery-File-Upload --strip-components 1 && \ - cd /jQuery-File-Upload && \ - bower --allow-root install bootstrap && \ - bower --allow-root install jquery && \ - bower --allow-root install blueimp-gallery && \ - bower --allow-root install bootstrap-tagsinput && \ - rm -rf /jQuery-File-Upload/*.html /jQuery-File-Upload/test/ /jQuery-File-Upload/server/gae-go/ \ - /jQuery-File-Upload/server/gae-python/ - -FROM debian:11-slim AS runtime + apt-get -y -q --allow-downgrades --allow-remove-essential --allow-change-held-packages install --no-install-recommends npm node-encoding git ca-certificates && \ + npm install -g \ + filepond \ + filepond-plugin-file-validate-size \ + filepond-plugin-file-validate-type \ + filepond-plugin-file-metadata \ + filepond-plugin-file-rename \ + @jcubic/tagger + +FROM debian:12-slim AS runtime LABEL maintainer="malcolm@inl.gov" LABEL org.opencontainers.image.authors='malcolm@inl.gov' @@ -46,59 +40,89 @@ ENV PUSER_PRIV_DROP false ENV DEBIAN_FRONTEND noninteractive ENV TERM xterm -ARG PHP_VERSION=7.4 +ARG PHP_VERSION=8.2 ENV PHP_VERSION $PHP_VERSION -ARG SITE_NAME="Capture File and Log Archive Upload" -ENV SITE_NAME $SITE_NAME +ARG FILEPOND_SERVER_BRANCH=master +ENV FILEPOND_SERVER_BRANCH $FILEPOND_SERVER_BRANCH + +ARG STALE_UPLOAD_DELETE_MIN=360 +ENV STALE_UPLOAD_DELETE_MIN $STALE_UPLOAD_DELETE_MIN + +ENV SUPERCRONIC_VERSION "0.2.26" +ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" +ENV SUPERCRONIC "supercronic-linux-amd64" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" +ENV SUPERCRONIC_CRONTAB "/etc/crontab" -COPY --from=build /jQuery-File-Upload/ /var/www/upload/ +COPY --from=npmget /usr/local/lib/node_modules/filepond /var/www/upload/filepond +COPY --from=npmget /usr/local/lib/node_modules/filepond-plugin-file-validate-size /var/www/upload/filepond-plugin-file-validate-size +COPY --from=npmget /usr/local/lib/node_modules/filepond-plugin-file-validate-type /var/www/upload/filepond-plugin-file-validate-type +COPY --from=npmget /usr/local/lib/node_modules/filepond-plugin-file-metadata /var/www/upload/filepond-plugin-file-metadata +COPY --from=npmget /usr/local/lib/node_modules/filepond-plugin-file-rename /var/www/upload/filepond-plugin-file-rename +COPY --from=npmget /usr/local/lib/node_modules/@jcubic /var/www/upload/@jcubic RUN apt-get -q update && \ apt-get -y -q --no-install-recommends upgrade && \ apt-get -y -q --allow-downgrades --allow-remove-essential --allow-change-held-packages install --no-install-recommends \ - wget \ ca-certificates \ - openssh-server \ - supervisor \ - vim-tiny \ + curl \ + file \ less \ + nginx-light \ + openssh-server \ php$PHP_VERSION \ - php$PHP_VERSION-fpm \ php$PHP_VERSION-apcu \ - nginx-light \ + php$PHP_VERSION-fpm \ rsync \ - tini && \ + supervisor \ + tini \ + vim-tiny && \ + curl -fsSLO "$SUPERCRONIC_URL" && \ + echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ + chmod +x "$SUPERCRONIC" && \ + mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \ + ln -sr "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic && \ + mkdir -p /var/www/upload/server/php \ + /tmp/filepond-server && \ + cd /tmp && \ + curl -sSL "https://github.com/pqina/filepond-server-php/archive/${FILEPOND_SERVER_BRANCH}.tar.gz" | tar xzvf - -C ./filepond-server --strip-components 1 && \ + rsync -a --include="*/" --include="*.php" --exclude="*" ./filepond-server/ /var/www/upload/server/php/ && \ apt-get clean -y -q && \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/* /var/cache/* /tmp/* /var/tmp/* COPY --chmod=755 shared/bin/docker-uid-gid-setup.sh /usr/local/bin/ COPY --chmod=755 shared/bin/service_check_passthrough.sh /usr/local/bin/ COPY --from=ghcr.io/mmguero-dev/gostatic --chmod=755 /goStatic /usr/bin/goStatic COPY --chmod=755 file-upload/docker-entrypoint.sh /docker-entrypoint.sh ADD docs/images/logo/Malcolm_banner.png /var/www/upload/Malcolm_banner.png -ADD file-upload/jquery-file-upload/bootstrap.min.css /var/www/upload/bower_components/bootstrap/dist/css/bootstrap.min.css -ADD file-upload/jquery-file-upload/index.html /var/www/upload/index.html -ADD file-upload/jquery-file-upload/index.php /var/www/upload/server/php/index.php ADD file-upload/nginx/sites-available/default /etc/nginx/sites-available/default ADD file-upload/php/php.ini /etc/php/$PHP_VERSION/fpm/php.ini +ADD file-upload/php/*.php /var/www/upload/server/php/ +ADD file-upload/site/index.html /var/www/upload/index.html ADD file-upload/sshd_config /tmp/sshd_config ADD file-upload/supervisord.conf /supervisord.conf -RUN mkdir -p /var/run/sshd /var/www/upload/server/php/chroot /run/php && \ - mv /var/www/upload/server/php/files /var/www/upload/server/php/chroot && \ +RUN mkdir -p /run/php \ + /var/run/sshd \ + /var/www/upload/server/php/chroot/files && \ ln -s /var/www/upload/server/php/chroot/files /var/www/upload/server/php/files && \ ln -sr /var/www/upload /var/www/upload/upload && \ perl -i -pl -e 's/^#?(\s*PermitRootLogin\s+)[\w\-]+$/$1no/i;' \ - -e 's/^#?(\s*PasswordAuthentication\s+)\w+$/$1no/i' /etc/ssh/sshd_config && \ - chmod a+x /docker-entrypoint.sh && \ + -e 's/^#?(\s*PasswordAuthentication\s+)\w+$/$1no/i' /etc/ssh/sshd_config && \ cat /tmp/sshd_config >>/etc/ssh/sshd_config && \ + echo "0/10 * * * * find /var/www/upload/server/php/chroot/files -mindepth 3 -type f -mmin +\$STALE_UPLOAD_DELETE_MIN -delete" > ${SUPERCRONIC_CRONTAB} && \ + echo "5 * * * * find /var/www/upload/server/php/chroot/files -mindepth 2 -type d -empty -mmin +\$STALE_UPLOAD_DELETE_MIN -delete" >> ${SUPERCRONIC_CRONTAB} && \ chmod 775 /var/www/upload/server/php/chroot/files && \ - chmod 755 /var /var/www /var/www/upload /var/www/upload/server /var/www/upload/server/php \ + chmod 755 /var \ + /var/www \ + /var/www/upload \ + /var/www/upload/server \ + /var/www/upload/server/php \ /var/www/upload/server/php/chroot && \ echo "Put your files into /files. Don't use subdirectories." \ >/var/www/upload/server/php/chroot/README.txt && \ - rm -rf /var/lib/apt/lists/* /var/cache/* /tmp/* /var/tmp/* /var/www/upload/server/php/chroot/files/.gitignore /tmp/sshd_config + rm -rf /var/lib/apt/lists/* /var/cache/* /tmp/* /var/tmp/* VOLUME [ "/var/www/upload/server/php/chroot/files" ] EXPOSE 22 80 @@ -112,7 +136,6 @@ ENTRYPOINT ["/usr/bin/tini", \ CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf", "-u", "root", "-n"] - # to be populated at build-time: ARG BUILD_DATE ARG MALCOLM_VERSION diff --git a/Dockerfiles/filebeat.Dockerfile b/Dockerfiles/filebeat.Dockerfile index b52dc85af..c77d29c50 100644 --- a/Dockerfiles/filebeat.Dockerfile +++ b/Dockerfiles/filebeat.Dockerfile @@ -1,4 +1,4 @@ -FROM docker.elastic.co/beats/filebeat-oss:8.8.2 +FROM docker.elastic.co/beats/filebeat-oss:8.9.0 # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -59,10 +59,10 @@ ARG FILEBEAT_TCP_PARSE_TARGET_FIELD="" ARG FILEBEAT_TCP_PARSE_DROP_FIELD="" ARG FILEBEAT_TCP_TAG="_malcolm_beats" -ENV SUPERCRONIC_VERSION "0.2.25" +ENV SUPERCRONIC_VERSION "0.2.26" ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" ENV SUPERCRONIC "supercronic-linux-amd64" -ENV SUPERCRONIC_SHA1SUM "642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" ENV SUPERCRONIC_CRONTAB "/etc/crontab" ENV TINI_VERSION v0.19.0 @@ -93,7 +93,7 @@ RUN apt-get -q update && \ unar \ unzip \ xz-utils && \ - python3 -m pip install patool entrypoint2 pyunpack python-magic ordered-set supervisor watchdog && \ + python3 -m pip install --no-cache-dir patool entrypoint2 pyunpack python-magic ordered-set supervisor watchdog && \ curl -fsSLO "$SUPERCRONIC_URL" && \ echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ chmod +x "$SUPERCRONIC" && \ diff --git a/Dockerfiles/freq.Dockerfile b/Dockerfiles/freq.Dockerfile index e11bdb862..2034e3203 100644 --- a/Dockerfiles/freq.Dockerfile +++ b/Dockerfiles/freq.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -40,7 +40,7 @@ RUN apt-get -q update && \ python3-pip \ rsync \ tini && \ - pip3 install supervisor six && \ + pip3 install --break-system-packages supervisor six && \ cd /opt && \ mkdir -p ./freq_server && \ curl -sSL "$FREQ_URL" | tar xzvf - -C ./freq_server --strip-components 1 && \ diff --git a/Dockerfiles/logstash.Dockerfile b/Dockerfiles/logstash.Dockerfile index ddd84f7ea..7c6ab795a 100644 --- a/Dockerfiles/logstash.Dockerfile +++ b/Dockerfiles/logstash.Dockerfile @@ -1,4 +1,4 @@ -FROM opensearchproject/logstash-oss-with-opensearch-output-plugin:8.6.1 +FROM docker.elastic.co/logstash/logstash-oss:8.9.0 LABEL maintainer="malcolm@inl.gov" LABEL org.opencontainers.image.authors='malcolm@inl.gov' @@ -66,13 +66,14 @@ RUN set -x && \ echo "gem 'deep_merge'" >> /usr/share/logstash/Gemfile && \ echo "gem 'fuzzy-string-match'" >> /usr/share/logstash/Gemfile && \ echo "gem 'stringex'" >> /usr/share/logstash/Gemfile && \ + echo "gem 'psych'" >> /usr/share/logstash/Gemfile && \ /usr/share/logstash/bin/ruby -S bundle install && \ logstash-plugin install --preserve logstash-filter-translate logstash-filter-cidr logstash-filter-dns \ logstash-filter-json logstash-filter-prune logstash-filter-http \ logstash-filter-grok logstash-filter-geoip logstash-filter-uuid \ logstash-filter-kv logstash-filter-mutate logstash-filter-dissect \ logstash-filter-fingerprint logstash-filter-useragent \ - logstash-input-beats logstash-output-elasticsearch && \ + logstash-input-beats logstash-output-elasticsearch logstash-output-opensearch && \ apt-get -y -q --allow-downgrades --allow-remove-essential --allow-change-held-packages autoremove && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/bin/jruby \ diff --git a/Dockerfiles/netbox.Dockerfile b/Dockerfiles/netbox.Dockerfile index f7485d881..64e1b6256 100644 --- a/Dockerfiles/netbox.Dockerfile +++ b/Dockerfiles/netbox.Dockerfile @@ -1,4 +1,4 @@ -FROM netboxcommunity/netbox:v3.5.4 +FROM netboxcommunity/netbox:v3.5.7 # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -22,65 +22,81 @@ ENV PUSER "boxer" ENV PGROUP "boxer" ENV PUSER_PRIV_DROP true -ENV SUPERCRONIC_VERSION "0.2.25" +ENV SUPERCRONIC_VERSION "0.2.26" ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" ENV SUPERCRONIC "supercronic-linux-amd64" -ENV SUPERCRONIC_SHA1SUM "642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" ENV SUPERCRONIC_CRONTAB "/etc/crontab" +ENV YQ_VERSION "4.33.3" +ENV YQ_URL "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_amd64" + ENV NETBOX_DEVICETYPE_LIBRARY_URL "https://codeload.github.com/netbox-community/devicetype-library/tar.gz/master" ARG NETBOX_DEVICETYPE_LIBRARY_PATH="/opt/netbox-devicetype-library" ARG NETBOX_DEFAULT_SITE=Malcolm ARG NETBOX_CRON=true +ARG NETBOX_PRELOAD_PATH="/opt/netbox-preload" +ENV NETBOX_PATH /opt/netbox ENV BASE_PATH netbox ENV NETBOX_DEVICETYPE_LIBRARY_PATH $NETBOX_DEVICETYPE_LIBRARY_PATH ENV NETBOX_DEFAULT_SITE $NETBOX_DEFAULT_SITE ENV NETBOX_CRON $NETBOX_CRON +ENV NETBOX_PRELOAD_PATH $NETBOX_PRELOAD_PATH + +ADD netbox/patch/* /tmp/netbox-patches/ RUN apt-get -q update && \ apt-get -y -q --no-install-recommends upgrade && \ apt-get install -q -y --no-install-recommends \ + git \ jq \ + patch \ procps \ psmisc \ rsync \ supervisor \ tini && \ - /opt/netbox/venv/bin/python -m pip install psycopg2 pynetbox python-slugify randomcolor && \ - curl -fsSLO "$SUPERCRONIC_URL" && \ + "${NETBOX_PATH}/venv/bin/python" -m pip install --break-system-packages --no-cache-dir 'git+https://github.com/mmguero-dev/netbox-initializers' psycopg2 pynetbox python-slugify randomcolor && \ + cd "${NETBOX_PATH}" && \ + bash -c 'for i in /tmp/netbox-patches/*; do patch -p 1 -r - --no-backup-if-mismatch < $i || true; done' && \ + curl -fsSLO "${SUPERCRONIC_URL}" && \ echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ - chmod +x "$SUPERCRONIC" && \ - mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \ + chmod +x "${SUPERCRONIC}" && \ + mv "${SUPERCRONIC}" "/usr/local/bin/${SUPERCRONIC}" && \ ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic && \ touch "${SUPERCRONIC_CRONTAB}" && \ - apt-get -q -y autoremove && \ + curl -fsSL -o /usr/bin/yq "${YQ_URL}" && \ + chmod 755 /usr/bin/yq && \ + apt-get -q -y --purge remove patch git && \ + apt-get -q -y --purge autoremove && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ groupadd --gid ${DEFAULT_GID} ${PUSER} && \ useradd -m --uid ${DEFAULT_UID} --gid ${DEFAULT_GID} ${PUSER} && \ usermod -a -G tty ${PUSER} && \ mkdir -p /opt/unit "${NETBOX_DEVICETYPE_LIBRARY_PATH}" && \ - chown -R $PUSER:root /etc/netbox /opt/unit /opt/netbox && \ + chown -R $PUSER:root /etc/netbox /opt/unit "${NETBOX_PATH}" && \ cd "$(dirname "${NETBOX_DEVICETYPE_LIBRARY_PATH}")" && \ - curl -sSL "$NETBOX_DEVICETYPE_LIBRARY_URL" | tar xzvf - -C ./"$(basename "${NETBOX_DEVICETYPE_LIBRARY_PATH}")" --strip-components 1 && \ - mkdir -p /opt/netbox/netbox/$BASE_PATH && \ - mv /opt/netbox/netbox/static /opt/netbox/netbox/$BASE_PATH/static && \ + curl -sSL "${NETBOX_DEVICETYPE_LIBRARY_URL}" | tar xzf - -C ./"$(basename "${NETBOX_DEVICETYPE_LIBRARY_PATH}")" --strip-components 1 && \ + mkdir -p "${NETBOX_PATH}/netbox/${BASE_PATH}" && \ + mv "${NETBOX_PATH}/netbox/static" "${NETBOX_PATH}/netbox/${BASE_PATH}/static" && \ jq '. += { "settings": { "http": { "discard_unsafe_fields": false } } }' /etc/unit/nginx-unit.json | jq 'del(.listeners."[::]:8080")' | jq 'del(.listeners."[::]:8081")' | jq ".routes.main[0].match.uri = \"/${BASE_PATH}/static/*\"" > /etc/unit/nginx-unit-new.json && \ mv /etc/unit/nginx-unit-new.json /etc/unit/nginx-unit.json && \ chmod 644 /etc/unit/nginx-unit.json && \ - tr -cd '\11\12\15\40-\176' < /opt/netbox/netbox/netbox/configuration.py > /opt/netbox/netbox/netbox/configuration_ascii.py && \ - mv /opt/netbox/netbox/netbox/configuration_ascii.py /opt/netbox/netbox/netbox/configuration.py && \ - sed -i "s/\('CENSUS_REPORTING_ENABLED',[[:space:]]*\)True/\1False/" /opt/netbox/netbox/netbox/settings.py && \ - sed -i -E 's@^([[:space:]]*\-\-(state|tmp))([[:space:]])@\1dir\3@g' /opt/netbox/launch-netbox.sh + tr -cd '\11\12\15\40-\176' < "${NETBOX_PATH}/netbox/${BASE_PATH}/configuration.py" > "${NETBOX_PATH}/netbox/${BASE_PATH}/configuration_ascii.py" && \ + mv "${NETBOX_PATH}/netbox/${BASE_PATH}/configuration_ascii.py" "${NETBOX_PATH}/netbox/${BASE_PATH}/configuration.py" && \ + sed -i "s/\('CENSUS_REPORTING_ENABLED',[[:space:]]*\)True/\1False/" "${NETBOX_PATH}/netbox/${BASE_PATH}/settings.py" && \ + sed -i -E 's@^([[:space:]]*\-\-(state|tmp))([[:space:]])@\1dir\3@g' "${NETBOX_PATH}/launch-netbox.sh" COPY --chmod=755 shared/bin/docker-uid-gid-setup.sh /usr/local/bin/ COPY --chmod=755 shared/bin/service_check_passthrough.sh /usr/local/bin/ COPY --from=ghcr.io/mmguero-dev/gostatic --chmod=755 /goStatic /usr/bin/goStatic COPY --chmod=755 netbox/scripts/* /usr/local/bin/ +COPY --chmod=644 scripts/malcolm_utils.py /usr/local/bin/ COPY --chmod=644 netbox/supervisord.conf /etc/supervisord.conf -COPY --chmod=644 netbox/*-defaults.json /etc/ +COPY --chmod=644 netbox/preload/*.yml $NETBOX_PRELOAD_PATH/ EXPOSE 9001 diff --git a/Dockerfiles/pcap-capture.Dockerfile b/Dockerfiles/pcap-capture.Dockerfile index 8254959cb..6244eaad9 100644 --- a/Dockerfiles/pcap-capture.Dockerfile +++ b/Dockerfiles/pcap-capture.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" diff --git a/Dockerfiles/pcap-monitor.Dockerfile b/Dockerfiles/pcap-monitor.Dockerfile index b445677f6..f5e1fc84e 100644 --- a/Dockerfiles/pcap-monitor.Dockerfile +++ b/Dockerfiles/pcap-monitor.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -52,7 +52,6 @@ RUN apt-get -q update && \ libzmq5 \ procps \ psmisc \ - python \ python3-pip \ python3-setuptools \ python3-wheel \ @@ -62,7 +61,7 @@ RUN apt-get -q update && \ vim-tiny && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ - pip3 install --no-cache-dir opensearch-py pyzmq python-magic requests watchdog && \ + python3 -m pip install --break-system-packages --no-cache-dir opensearch-py pyzmq python-magic requests watchdog && \ groupadd --gid ${DEFAULT_GID} ${PGROUP} && \ useradd -M --uid ${DEFAULT_UID} --gid ${DEFAULT_GID} ${PUSER} diff --git a/Dockerfiles/postgresql.Dockerfile b/Dockerfiles/postgresql.Dockerfile index ea4e14f69..757d13684 100644 --- a/Dockerfiles/postgresql.Dockerfile +++ b/Dockerfiles/postgresql.Dockerfile @@ -1,4 +1,4 @@ -FROM postgres:14-alpine +FROM postgres:15-alpine # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. LABEL maintainer="malcolm@inl.gov" @@ -44,7 +44,7 @@ ENTRYPOINT ["/sbin/tini", \ "--", \ "/usr/bin/docker-uid-gid-setup.sh", \ "/usr/local/bin/service_check_passthrough.sh", \ - "-s", "netbox"] + "-s", "netbox-postgres"] CMD ["/usr/bin/docker-entrypoint.sh", "postgres"] diff --git a/Dockerfiles/redis.Dockerfile b/Dockerfiles/redis.Dockerfile index a25c17c72..6585f2ea2 100644 --- a/Dockerfiles/redis.Dockerfile +++ b/Dockerfiles/redis.Dockerfile @@ -35,7 +35,7 @@ ENTRYPOINT ["/sbin/tini", \ "--", \ "/usr/local/bin/docker-uid-gid-setup.sh", \ "/usr/local/bin/service_check_passthrough.sh", \ - "-s", "netbox"] + "-s", "netbox-redis"] # to be populated at build-time: ARG BUILD_DATE diff --git a/Dockerfiles/suricata.Dockerfile b/Dockerfiles/suricata.Dockerfile index 5e4d4ab0f..9d8b1e249 100644 --- a/Dockerfiles/suricata.Dockerfile +++ b/Dockerfiles/suricata.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim LABEL maintainer="malcolm@inl.gov" LABEL org.opencontainers.image.authors='malcolm@inl.gov' @@ -28,10 +28,10 @@ ENV PGROUP "suricata" ENV PUSER_PRIV_DROP false ENV PUSER_RLIMIT_UNLOCK true -ENV SUPERCRONIC_VERSION "0.2.25" +ENV SUPERCRONIC_VERSION "0.2.26" ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" ENV SUPERCRONIC "supercronic-linux-amd64" -ENV SUPERCRONIC_SHA1SUM "642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" ENV SUPERCRONIC_CRONTAB "/etc/crontab" ENV YQ_VERSION "4.33.3" @@ -49,14 +49,9 @@ ENV SURICATA_UPDATE_DIR "$SURICATA_MANAGED_DIR/update" ENV SURICATA_UPDATE_SOURCES_DIR "$SURICATA_UPDATE_DIR/sources" ENV SURICATA_UPDATE_CACHE_DIR "$SURICATA_UPDATE_DIR/cache" -RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.list && \ - echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list && \ +RUN sed -i "s/main$/main contrib non-free/g" /etc/apt/sources.list.d/debian.sources && \ apt-get -q update && \ apt-get -y -q --no-install-recommends upgrade && \ - apt-get install -q -y -t bullseye-backports --no-install-recommends \ - libhtp2 \ - suricata \ - suricata-update && \ apt-get install -q -y --no-install-recommends \ bc \ curl \ @@ -73,6 +68,7 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l libgeoip1 \ libhiredis0.14 \ libhtp2 \ + libhtp2 \ libhyperscan5 \ libjansson4 \ liblua5.1-0 \ @@ -98,10 +94,12 @@ RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.l python3-zmq \ rsync \ supervisor \ - vim-tiny \ + suricata \ + suricata-update \ tini \ + vim-tiny \ zlib1g && \ - pip3 install --no-cache-dir watchdog && \ + python3 -m pip install --break-system-packages --no-cache-dir watchdog && \ curl -fsSLO "$SUPERCRONIC_URL" && \ echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ chmod +x "$SUPERCRONIC" && \ diff --git a/Dockerfiles/zeek.Dockerfile b/Dockerfiles/zeek.Dockerfile index 3ba9394da..137589e86 100644 --- a/Dockerfiles/zeek.Dockerfile +++ b/Dockerfiles/zeek.Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. @@ -37,10 +37,10 @@ ARG ZEEK_VERSION=5.2.2-0 ENV ZEEK_LTS $ZEEK_LTS ENV ZEEK_VERSION $ZEEK_VERSION -ENV SUPERCRONIC_VERSION "0.2.25" +ENV SUPERCRONIC_VERSION "0.2.26" ENV SUPERCRONIC_URL "https://github.com/aptible/supercronic/releases/download/v$SUPERCRONIC_VERSION/supercronic-linux-amd64" ENV SUPERCRONIC "supercronic-linux-amd64" -ENV SUPERCRONIC_SHA1SUM "642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49" +ENV SUPERCRONIC_SHA1SUM "7a79496cf8ad899b99a719355d4db27422396735" ENV SUPERCRONIC_CRONTAB "/etc/crontab" # for build @@ -109,21 +109,21 @@ RUN export DEBARCH=$(dpkg --print-architecture) && \ tini \ vim-tiny \ zlib1g-dev && \ - pip3 install --no-cache-dir pymisp stix2 taxii2-client dateparser && \ + python3 -m pip install --break-system-packages --no-cache-dir pymisp stix2 taxii2-client dateparser && \ mkdir -p /tmp/zeek-packages && \ cd /tmp/zeek-packages && \ if [ -n "${ZEEK_LTS}" ]; then ZEEK_LTS="-lts"; fi && export ZEEK_LTS && \ curl -sSL --remote-name-all \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/libbroker${ZEEK_LTS}-dev_${ZEEK_VERSION}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}-core-dev_${ZEEK_VERSION}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}-core_${ZEEK_VERSION}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}-spicy-dev_${ZEEK_VERSION}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}_${ZEEK_VERSION}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeekctl${ZEEK_LTS}_${ZEEK_VERSION}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-client_${ZEEK_VERSION}_all.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-zkg_${ZEEK_VERSION}_all.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-btest_${ZEEK_VERSION}_all.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-btest-data_${ZEEK_VERSION}_all.deb" && \ + "https://download.zeek.org/binary-packages/Debian_12/amd64/libbroker${ZEEK_LTS}-dev_${ZEEK_VERSION}_amd64.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/amd64/zeek${ZEEK_LTS}-core-dev_${ZEEK_VERSION}_amd64.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/amd64/zeek${ZEEK_LTS}-core_${ZEEK_VERSION}_amd64.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/amd64/zeek${ZEEK_LTS}-spicy-dev_${ZEEK_VERSION}_amd64.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/amd64/zeek${ZEEK_LTS}_${ZEEK_VERSION}_amd64.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/amd64/zeekctl${ZEEK_LTS}_${ZEEK_VERSION}_amd64.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/all/zeek${ZEEK_LTS}-client_${ZEEK_VERSION}_all.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/all/zeek${ZEEK_LTS}-zkg_${ZEEK_VERSION}_all.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/all/zeek${ZEEK_LTS}-btest_${ZEEK_VERSION}_all.deb" \ + "https://download.zeek.org/binary-packages/Debian_12/all/zeek${ZEEK_LTS}-btest-data_${ZEEK_VERSION}_all.deb" && \ dpkg -i ./*.deb && \ curl -fsSLO "$SUPERCRONIC_URL" && \ echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - && \ diff --git a/api/requirements.txt b/api/requirements.txt index a46da061d..e2919f390 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -1,7 +1,7 @@ pytz==2021.3 Flask==2.3.2 gunicorn==20.1.0 -opensearch-py==2.2.0 +opensearch-py==2.3.0 requests==2.31.0 regex==2022.3.2 dateparser==1.1.1 \ No newline at end of file diff --git a/arkime/etc/config.ini b/arkime/etc/config.ini index c4d057fb5..0aff4df59 100644 --- a/arkime/etc/config.ini +++ b/arkime/etc/config.ini @@ -49,6 +49,7 @@ pluginsDir=/opt/arkime/plugins plugins=wise.so viewerPlugins=wise.js spiDataMaxIndices=7 +uploadCommand= packetThreads=2 pcapWriteMethod=simple pcapWriteSize=262143 diff --git a/arkime/patch/remove_upload.patch b/arkime/patch/remove_upload.patch deleted file mode 100644 index 4c17cc35c..000000000 --- a/arkime/patch/remove_upload.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/viewer/vueapp/src/router/index.js b/viewer/vueapp/src/router/index.js -index 104506cf..0850f2cd 100644 ---- a/viewer/vueapp/src/router/index.js -+++ b/viewer/vueapp/src/router/index.js -@@ -12,7 +12,6 @@ import Spiview from '@/components/spiview/Spiview'; - import Spigraph from '@/components/spigraph/Spigraph'; - import Connections from '@/components/connections/Connections'; - import Settings from '@/components/settings/Settings'; --import Upload from '@/components/upload/Upload'; - import Hunt from '@/components/hunt/Hunt'; - import Moloch404 from '@/components/utils/404'; - -@@ -92,11 +91,6 @@ const router = new Router({ - name: 'Settings', - component: Settings - }, -- { -- path: '/upload', -- name: 'Upload', -- component: Upload -- }, - { - path: '/hunt', - name: 'Hunt', diff --git a/arkime/scripts/arkime_update_geo.sh b/arkime/scripts/arkime_update_geo.sh index 5e26566a2..64be5973e 100755 --- a/arkime/scripts/arkime_update_geo.sh +++ b/arkime/scripts/arkime_update_geo.sh @@ -8,7 +8,7 @@ wget -nv --no-check-certificate -O ipv4-address-space.csv_new https://www.iana.o mv -f ipv4-address-space.csv_new ipv4-address-space.csv || \ rm -f ipv4-address-space.csv_new -wget -nv -O oui.txt_new https://raw.githubusercontent.com/wireshark/wireshark/master/manuf && \ +wget -nv -O oui.txt_new https://gitlab.com/wireshark/wireshark/raw/release-4.0/manuf && \ mv -f oui.txt_new oui.txt || \ rm -f oui.txt_new diff --git a/config/netbox-common.env.example b/config/netbox-common.env.example index a8e81103a..882cc64ae 100644 --- a/config/netbox-common.env.example +++ b/config/netbox-common.env.example @@ -7,5 +7,4 @@ NETBOX_DEFAULT_SITE=Malcolm NETBOX_DISABLED=true NETBOX_POSTGRES_DISABLED=true NETBOX_REDIS_DISABLED=true -NETBOX_REDIS_CACHE_DISABLED=true NETBOX_CRON=true diff --git a/config/upload.env.example b/config/upload.env.example deleted file mode 100644 index ebc4e3d25..000000000 --- a/config/upload.env.example +++ /dev/null @@ -1 +0,0 @@ -SITE_NAME=Capture File and Log Archive Upload \ No newline at end of file diff --git a/dashboards/dashboards/29a1b290-eb98-11e9-a384-0fcf32210194.json b/dashboards/dashboards/29a1b290-eb98-11e9-a384-0fcf32210194.json index 965fadb4e..9940028e3 100644 --- a/dashboards/dashboards/29a1b290-eb98-11e9-a384-0fcf32210194.json +++ b/dashboards/dashboards/29a1b290-eb98-11e9-a384-0fcf32210194.json @@ -368,7 +368,6 @@ "destination.ip", "event.action", "event.result", - "network.is_orig", "zeek.cip.direction", "zeek.cip.cip_sequence_count", "zeek.cip.class_id", @@ -457,7 +456,6 @@ "destination.ip", "event.action", "event.result", - "network.is_orig", "zeek.enip.options", "zeek.enip.sender_context", "zeek.enip.session_handle", @@ -500,7 +498,6 @@ "columns": [ "source.ip", "destination.ip", - "network.is_orig", "zeek.cip_io.connection_id", "zeek.cip_io.sequence_number", "zeek.cip_io.data_length", diff --git a/dashboards/dashboards/2bec1490-eb94-11e9-a384-0fcf32210194.json b/dashboards/dashboards/2bec1490-eb94-11e9-a384-0fcf32210194.json index fbca23fdf..2f218e86c 100644 --- a/dashboards/dashboards/2bec1490-eb94-11e9-a384-0fcf32210194.json +++ b/dashboards/dashboards/2bec1490-eb94-11e9-a384-0fcf32210194.json @@ -435,7 +435,6 @@ "columns": [ "source.ip", "destination.ip", - "network.is_orig", "zeek.bacnet.bvlc_function", "zeek.bacnet.pdu_type", "zeek.bacnet.pdu_service", @@ -478,7 +477,6 @@ "columns": [ "source.ip", "destination.ip", - "network.is_orig", "zeek.bacnet_property.pdu_service", "zeek.bacnet_property.object_type", "zeek.bacnet.instance_number", @@ -522,7 +520,6 @@ "columns": [ "source.ip", "destination.ip", - "network.is_orig", "zeek.bacnet_discovery.pdu_service", "zeek.bacnet_discovery.object_type", "zeek.bacnet.instance_number", diff --git a/dashboards/dashboards/e76d05c0-eb9f-11e9-a384-0fcf32210194.json b/dashboards/dashboards/e76d05c0-eb9f-11e9-a384-0fcf32210194.json index 8e9e8ec31..523c02acd 100644 --- a/dashboards/dashboards/e76d05c0-eb9f-11e9-a384-0fcf32210194.json +++ b/dashboards/dashboards/e76d05c0-eb9f-11e9-a384-0fcf32210194.json @@ -359,7 +359,6 @@ "source.port", "destination.ip", "destination.port", - "network.is_orig", "event.action", "event.result", "zeek.s7comm.pdu_reference", @@ -400,7 +399,6 @@ "source.port", "destination.ip", "destination.port", - "network.is_orig", "event.action", "event.result", "zeek.uid" diff --git a/docker-compose-standalone.yml b/docker-compose-standalone.yml index 7a0a1fff9..de1f0ae49 100644 --- a/docker-compose-standalone.yml +++ b/docker-compose-standalone.yml @@ -4,7 +4,7 @@ version: '3.7' services: opensearch: - image: ghcr.io/idaholab/malcolm/opensearch:23.07.1 + image: ghcr.io/idaholab/malcolm/opensearch:23.08.0 restart: "no" stdin_open: false tty: true @@ -37,7 +37,7 @@ services: retries: 3 start_period: 180s dashboards-helper: - image: ghcr.io/idaholab/malcolm/dashboards-helper:23.07.1 + image: ghcr.io/idaholab/malcolm/dashboards-helper:23.08.0 restart: "no" stdin_open: false tty: true @@ -64,7 +64,7 @@ services: retries: 3 start_period: 30s dashboards: - image: ghcr.io/idaholab/malcolm/dashboards:23.07.1 + image: ghcr.io/idaholab/malcolm/dashboards:23.08.0 restart: "no" stdin_open: false tty: true @@ -90,7 +90,7 @@ services: retries: 3 start_period: 210s logstash: - image: ghcr.io/idaholab/malcolm/logstash-oss:23.07.1 + image: ghcr.io/idaholab/malcolm/logstash-oss:23.08.0 restart: "no" stdin_open: false tty: true @@ -132,7 +132,7 @@ services: retries: 3 start_period: 600s filebeat: - image: ghcr.io/idaholab/malcolm/filebeat-oss:23.07.1 + image: ghcr.io/idaholab/malcolm/filebeat-oss:23.08.0 restart: "no" stdin_open: false tty: true @@ -167,7 +167,7 @@ services: retries: 3 start_period: 60s arkime: - image: ghcr.io/idaholab/malcolm/arkime:23.07.1 + image: ghcr.io/idaholab/malcolm/arkime:23.08.0 restart: "no" stdin_open: false tty: true @@ -203,7 +203,7 @@ services: retries: 3 start_period: 210s zeek: - image: ghcr.io/idaholab/malcolm/zeek:23.07.1 + image: ghcr.io/idaholab/malcolm/zeek:23.08.0 restart: "no" stdin_open: false tty: true @@ -241,7 +241,7 @@ services: retries: 3 start_period: 60s zeek-live: - image: ghcr.io/idaholab/malcolm/zeek:23.07.1 + image: ghcr.io/idaholab/malcolm/zeek:23.08.0 restart: "no" stdin_open: false tty: true @@ -269,7 +269,7 @@ services: - ./zeek-logs/extract_files:/zeek/extract_files - ./zeek/intel:/opt/zeek/share/zeek/site/intel suricata: - image: ghcr.io/idaholab/malcolm/suricata:23.07.1 + image: ghcr.io/idaholab/malcolm/suricata:23.08.0 restart: "no" stdin_open: false tty: true @@ -305,7 +305,7 @@ services: retries: 3 start_period: 120s suricata-live: - image: ghcr.io/idaholab/malcolm/suricata:23.07.1 + image: ghcr.io/idaholab/malcolm/suricata:23.08.0 restart: "no" stdin_open: false tty: true @@ -331,7 +331,7 @@ services: - ./suricata-logs:/var/log/suricata - ./suricata/rules:/opt/suricata/rules:ro file-monitor: - image: ghcr.io/idaholab/malcolm/file-monitor:23.07.1 + image: ghcr.io/idaholab/malcolm/file-monitor:23.08.0 restart: "no" stdin_open: false tty: true @@ -357,7 +357,7 @@ services: retries: 3 start_period: 60s pcap-capture: - image: ghcr.io/idaholab/malcolm/pcap-capture:23.07.1 + image: ghcr.io/idaholab/malcolm/pcap-capture:23.08.0 restart: "no" stdin_open: false tty: true @@ -379,7 +379,7 @@ services: - ./nginx/ca-trust:/var/local/ca-trust:ro - ./pcap/upload:/pcap pcap-monitor: - image: ghcr.io/idaholab/malcolm/pcap-monitor:23.07.1 + image: ghcr.io/idaholab/malcolm/pcap-monitor:23.08.0 restart: "no" stdin_open: false tty: true @@ -405,7 +405,7 @@ services: retries: 3 start_period: 90s upload: - image: ghcr.io/idaholab/malcolm/file-upload:23.07.1 + image: ghcr.io/idaholab/malcolm/file-upload:23.08.0 restart: "no" stdin_open: false tty: true @@ -416,7 +416,6 @@ services: - ./config/process.env - ./config/ssl.env - ./config/auth.env - - ./config/upload.env environment: VIRTUAL_HOST : 'upload.malcolm.local' depends_on: @@ -427,13 +426,13 @@ services: - ./nginx/ca-trust:/var/local/ca-trust:ro - ./pcap/upload:/var/www/upload/server/php/chroot/files healthcheck: - test: ["CMD", "wget", "-qO-", "http://localhost"] + test: ["CMD", "curl", "--silent", "--fail", "http://localhost"] interval: 30s timeout: 15s retries: 3 start_period: 60s htadmin: - image: ghcr.io/idaholab/malcolm/htadmin:23.07.1 + image: ghcr.io/idaholab/malcolm/htadmin:23.08.0 restart: "no" stdin_open: false tty: true @@ -458,7 +457,7 @@ services: retries: 3 start_period: 60s freq: - image: ghcr.io/idaholab/malcolm/freq:23.07.1 + image: ghcr.io/idaholab/malcolm/freq:23.08.0 restart: "no" stdin_open: false tty: true @@ -480,7 +479,7 @@ services: retries: 3 start_period: 60s netbox: - image: ghcr.io/idaholab/malcolm/netbox:23.07.1 + image: ghcr.io/idaholab/malcolm/netbox:23.08.0 restart: "no" stdin_open: false tty: true @@ -504,6 +503,7 @@ services: - ./netbox/config:/etc/netbox/config:ro - ./netbox/media:/opt/netbox/netbox/media:rw - ./net-map.json:/usr/local/share/net-map.json:ro + - ./netbox/preload:/opt/netbox-preload/configmap:ro healthcheck: test: ["CMD", "curl", "--silent", "http://localhost:8080/netbox/api/" ] interval: 60s @@ -511,7 +511,7 @@ services: retries: 3 start_period: 120s netbox-postgres: - image: ghcr.io/idaholab/malcolm/postgresql:23.07.1 + image: ghcr.io/idaholab/malcolm/postgresql:23.08.0 restart: "no" stdin_open: false tty: true @@ -535,7 +535,7 @@ services: retries: 3 start_period: 45s netbox-redis: - image: ghcr.io/idaholab/malcolm/redis:23.07.1 + image: ghcr.io/idaholab/malcolm/redis:23.08.0 restart: "no" stdin_open: false tty: true @@ -563,7 +563,7 @@ services: retries: 3 start_period: 45s netbox-redis-cache: - image: ghcr.io/idaholab/malcolm/redis:23.07.1 + image: ghcr.io/idaholab/malcolm/redis:23.08.0 restart: "no" stdin_open: false tty: true @@ -590,7 +590,7 @@ services: retries: 3 start_period: 45s api: - image: ghcr.io/idaholab/malcolm/api:23.07.1 + image: ghcr.io/idaholab/malcolm/api:23.08.0 command: gunicorn --bind 0:5000 manage:app restart: "no" stdin_open: false @@ -614,7 +614,7 @@ services: retries: 3 start_period: 60s nginx-proxy: - image: ghcr.io/idaholab/malcolm/nginx-proxy:23.07.1 + image: ghcr.io/idaholab/malcolm/nginx-proxy:23.08.0 restart: "no" stdin_open: false tty: true diff --git a/docker-compose.yml b/docker-compose.yml index 817a26cb5..9b1538ded 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: build: context: . dockerfile: Dockerfiles/opensearch.Dockerfile - image: ghcr.io/idaholab/malcolm/opensearch:23.07.1 + image: ghcr.io/idaholab/malcolm/opensearch:23.08.0 restart: "no" stdin_open: false tty: true @@ -43,7 +43,7 @@ services: build: context: . dockerfile: Dockerfiles/dashboards-helper.Dockerfile - image: ghcr.io/idaholab/malcolm/dashboards-helper:23.07.1 + image: ghcr.io/idaholab/malcolm/dashboards-helper:23.08.0 restart: "no" stdin_open: false tty: true @@ -73,7 +73,7 @@ services: build: context: . dockerfile: Dockerfiles/dashboards.Dockerfile - image: ghcr.io/idaholab/malcolm/dashboards:23.07.1 + image: ghcr.io/idaholab/malcolm/dashboards:23.08.0 restart: "no" stdin_open: false tty: true @@ -102,7 +102,7 @@ services: build: context: . dockerfile: Dockerfiles/logstash.Dockerfile - image: ghcr.io/idaholab/malcolm/logstash-oss:23.07.1 + image: ghcr.io/idaholab/malcolm/logstash-oss:23.08.0 restart: "no" stdin_open: false tty: true @@ -151,7 +151,7 @@ services: build: context: . dockerfile: Dockerfiles/filebeat.Dockerfile - image: ghcr.io/idaholab/malcolm/filebeat-oss:23.07.1 + image: ghcr.io/idaholab/malcolm/filebeat-oss:23.08.0 restart: "no" stdin_open: false tty: true @@ -189,7 +189,7 @@ services: build: context: . dockerfile: Dockerfiles/arkime.Dockerfile - image: ghcr.io/idaholab/malcolm/arkime:23.07.1 + image: ghcr.io/idaholab/malcolm/arkime:23.08.0 restart: "no" stdin_open: false tty: true @@ -231,7 +231,7 @@ services: build: context: . dockerfile: Dockerfiles/zeek.Dockerfile - image: ghcr.io/idaholab/malcolm/zeek:23.07.1 + image: ghcr.io/idaholab/malcolm/zeek:23.08.0 restart: "no" stdin_open: false tty: true @@ -273,7 +273,7 @@ services: build: context: . dockerfile: Dockerfiles/zeek.Dockerfile - image: ghcr.io/idaholab/malcolm/zeek:23.07.1 + image: ghcr.io/idaholab/malcolm/zeek:23.08.0 restart: "no" stdin_open: false tty: true @@ -305,7 +305,7 @@ services: build: context: . dockerfile: Dockerfiles/suricata.Dockerfile - image: ghcr.io/idaholab/malcolm/suricata:23.07.1 + image: ghcr.io/idaholab/malcolm/suricata:23.08.0 restart: "no" stdin_open: false tty: true @@ -344,7 +344,7 @@ services: build: context: . dockerfile: Dockerfiles/suricata.Dockerfile - image: ghcr.io/idaholab/malcolm/suricata:23.07.1 + image: ghcr.io/idaholab/malcolm/suricata:23.08.0 restart: "no" stdin_open: false tty: true @@ -373,7 +373,7 @@ services: build: context: . dockerfile: Dockerfiles/file-monitor.Dockerfile - image: ghcr.io/idaholab/malcolm/file-monitor:23.07.1 + image: ghcr.io/idaholab/malcolm/file-monitor:23.08.0 restart: "no" stdin_open: false tty: true @@ -402,7 +402,7 @@ services: build: context: . dockerfile: Dockerfiles/pcap-capture.Dockerfile - image: ghcr.io/idaholab/malcolm/pcap-capture:23.07.1 + image: ghcr.io/idaholab/malcolm/pcap-capture:23.08.0 restart: "no" stdin_open: false tty: true @@ -427,7 +427,7 @@ services: build: context: . dockerfile: Dockerfiles/pcap-monitor.Dockerfile - image: ghcr.io/idaholab/malcolm/pcap-monitor:23.07.1 + image: ghcr.io/idaholab/malcolm/pcap-monitor:23.08.0 restart: "no" stdin_open: false tty: true @@ -456,7 +456,7 @@ services: build: context: . dockerfile: Dockerfiles/file-upload.Dockerfile - image: ghcr.io/idaholab/malcolm/file-upload:23.07.1 + image: ghcr.io/idaholab/malcolm/file-upload:23.08.0 restart: "no" stdin_open: false tty: true @@ -467,7 +467,6 @@ services: - ./config/process.env - ./config/ssl.env - ./config/auth.env - - ./config/upload.env environment: VIRTUAL_HOST : 'upload.malcolm.local' depends_on: @@ -478,13 +477,13 @@ services: - ./nginx/ca-trust:/var/local/ca-trust:ro - ./pcap/upload:/var/www/upload/server/php/chroot/files healthcheck: - test: ["CMD", "wget", "-qO-", "http://localhost"] + test: ["CMD", "curl", "--silent", "--fail", "http://localhost"] interval: 30s timeout: 15s retries: 3 start_period: 60s htadmin: - image: ghcr.io/idaholab/malcolm/htadmin:23.07.1 + image: ghcr.io/idaholab/malcolm/htadmin:23.08.0 build: context: . dockerfile: Dockerfiles/htadmin.Dockerfile @@ -512,7 +511,7 @@ services: retries: 3 start_period: 60s freq: - image: ghcr.io/idaholab/malcolm/freq:23.07.1 + image: ghcr.io/idaholab/malcolm/freq:23.08.0 build: context: . dockerfile: Dockerfiles/freq.Dockerfile @@ -537,7 +536,7 @@ services: retries: 3 start_period: 60s netbox: - image: ghcr.io/idaholab/malcolm/netbox:23.07.1 + image: ghcr.io/idaholab/malcolm/netbox:23.08.0 build: context: . dockerfile: Dockerfiles/netbox.Dockerfile @@ -564,7 +563,7 @@ services: - ./netbox/config:/etc/netbox/config:ro - ./netbox/media:/opt/netbox/netbox/media:rw - ./net-map.json:/usr/local/share/net-map.json:ro - - ./netbox/service-template-defaults.json:/etc/service-template-defaults.json:ro + - ./netbox/preload:/opt/netbox-preload/configmap:ro healthcheck: test: ["CMD", "curl", "--silent", "http://localhost:8080/netbox/api/" ] interval: 60s @@ -572,7 +571,7 @@ services: retries: 3 start_period: 120s netbox-postgres: - image: ghcr.io/idaholab/malcolm/postgresql:23.07.1 + image: ghcr.io/idaholab/malcolm/postgresql:23.08.0 build: context: . dockerfile: Dockerfiles/postgresql.Dockerfile @@ -599,7 +598,7 @@ services: retries: 3 start_period: 45s netbox-redis: - image: ghcr.io/idaholab/malcolm/redis:23.07.1 + image: ghcr.io/idaholab/malcolm/redis:23.08.0 build: context: . dockerfile: Dockerfiles/redis.Dockerfile @@ -630,7 +629,7 @@ services: retries: 3 start_period: 45s netbox-redis-cache: - image: ghcr.io/idaholab/malcolm/redis:23.07.1 + image: ghcr.io/idaholab/malcolm/redis:23.08.0 build: context: . dockerfile: Dockerfiles/redis.Dockerfile @@ -660,7 +659,7 @@ services: retries: 3 start_period: 45s api: - image: ghcr.io/idaholab/malcolm/api:23.07.1 + image: ghcr.io/idaholab/malcolm/api:23.08.0 build: context: . dockerfile: Dockerfiles/api.Dockerfile @@ -690,7 +689,7 @@ services: build: context: . dockerfile: Dockerfiles/nginx.Dockerfile - image: ghcr.io/idaholab/malcolm/nginx-proxy:23.07.1 + image: ghcr.io/idaholab/malcolm/nginx-proxy:23.08.0 restart: "no" stdin_open: false tty: true diff --git a/docs/README.md b/docs/README.md index c929dde23..cee5df17e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -41,7 +41,7 @@ Malcolm can also easily be deployed locally on an ordinary consumer workstation - [Stopping and restarting Malcolm](running.md#StopAndRestart) - [Clearing Malcolm's data](running.md#Wipe) - [Temporary read-only interface](running.md#ReadOnlyUI) -* [Capture file and log archive upload](upload.md#Upload) +* [Network traffic artifact upload](upload.md#Upload) - [Tagging](upload.md#Tagging) - [Processing uploaded PCAPs with Zeek and Suricata](upload.md#UploadPCAPProcessors) * [Live analysis](live-analysis.md#LiveAnalysis) @@ -89,6 +89,7 @@ Malcolm can also easily be deployed locally on an ordinary consumer workstation * [Via passively-gathered network traffic metadata](asset-interaction-analysis.md#NetBoxPopPassive) * [Via active discovery](asset-interaction-analysis.md#NetBoxPopActive) + [Compare NetBox inventory with database of known vulnerabilities](asset-interaction-analysis.md#NetBoxVuln) + + [Preloading NetBox inventory](asset-interaction-analysis.md#NetBoxPreload) + [Backup and restore](asset-interaction-analysis.md#NetBoxBackup) - [CyberChef](cyberchef.md#CyberChef) - [API](api.md#API) @@ -104,6 +105,7 @@ Malcolm can also easily be deployed locally on an ordinary consumer workstation - [Deployment Example](kubernetes.md#Example) - [Future Enhancements](kubernetes.md#Future) - [Deploying Malcolm on Amazon Elastic Kubernetes Service (EKS)](kubernetes-eks.md#KubernetesEKS) + - [Deploying Malcolm on Microsoft Azure Kubernetes Service (AKS)](kubernetes-azure.md#KubernetesAzure) * [Deploying Malcolm in Other Third-Party Environments](third-party-envs.md#ThirdPartyEnv) * [Hardening](hardening.md#Hardening) - [Compliance Exceptions](hardening.md#ComplianceExceptions) diff --git a/docs/asset-interaction-analysis.md b/docs/asset-interaction-analysis.md index e536b67a8..dced1e2ce 100644 --- a/docs/asset-interaction-analysis.md +++ b/docs/asset-interaction-analysis.md @@ -7,6 +7,7 @@ - [Via passively-gathered network traffic metadata](#NetBoxPopPassive) - [Via active discovery](#NetBoxPopActive) * [Compare NetBox inventory with database of known vulnerabilities](#NetBoxVuln) +* [Preloading NetBox inventory](#NetBoxPreload) * [Backup and restore](#NetBoxBackup) Malcolm provides an instance of [NetBox](https://netbox.dev/), an open-source "solution for modeling and documenting modern networks." The NetBox web interface is available at at **https://localhost/netbox/** if connecting locally. @@ -112,6 +113,12 @@ See [idaholab/Malcolm#136](https://github.com/idaholab/Malcolm/issues/136). See [idaholab/Malcolm#134](https://github.com/idaholab/Malcolm/issues/134). +## Preloading NetBox inventory + +YML files in [`./netbox/preload`]({{ site.github.repository_url }}/tree/{{ site.github.build_revision }}/netbox/preload/) under the Malcolm installation directory will be preloaded upon startup using the third-party [netbox-initializers](https://github.com/tobiasge/netbox-initializers) plugin. Examples illustrating the format of these YML files can be found at its [GitHub repository](https://github.com/tobiasge/netbox-initializers/tree/main/src/netbox_initializers/initializers/yaml). + +[workflow files] + ## Backup and Restore The NetBox database may be backed up and restored using `./scripts/netbox-backup` and `./scripts/netbox-restore`, respectively. While Malcolm is running, run the following command from within the Malcolm installation directory to backup the entire NetBox database: diff --git a/docs/contributing-pcap.md b/docs/contributing-pcap.md index 3f5397d3c..591e9027a 100644 --- a/docs/contributing-pcap.md +++ b/docs/contributing-pcap.md @@ -1,6 +1,6 @@ # PCAP processors -When a PCAP is uploaded (either through Malcolm's [upload web interface](upload.md#Upload) or just copied manually into the `./pcap/upload/` directory), the `pcap-monitor` container has a script that picks up those PCAP files and publishes to a [ZeroMQ](https://zeromq.org/) topic that can be subscribed to by any other process that wants to analyze that PCAP. In Malcolm (at the time of the [v23.07.1 release]({{ site.github.repository_url }}/releases/tag/v23.07.1)), there are three such ZeroMQ topics: the `zeek`, `suricata` and `arkime` containers. These actually share the [same script]({{ site.github.repository_url }}/blob/{{ site.github.build_revision }}/shared/bin/pcap_processor.py) to run the PCAP through Zeek, Suricata, and Arkime, respectively. For an example to follow, the `zeek` container is the less complicated of the two. To integrate a new PCAP processing tool into Malcolm (named `cooltool` for this example) the process would entail: +When a PCAP is uploaded (either through Malcolm's [upload web interface](upload.md#Upload) or just copied manually into the `./pcap/upload` directory), the `pcap-monitor` container has a script that picks up those PCAP files and publishes to a [ZeroMQ](https://zeromq.org/) topic that can be subscribed to by any other process that wants to analyze that PCAP. In Malcolm (at the time of the [v23.08.0 release]({{ site.github.repository_url }}/releases/tag/v23.08.0)), there are three such ZeroMQ topics: the `zeek`, `suricata` and `arkime` containers. These actually share the [same script]({{ site.github.repository_url }}/blob/{{ site.github.build_revision }}/shared/bin/pcap_processor.py) to run the PCAP through Zeek, Suricata, and Arkime, respectively. For an example to follow, the `zeek` container is the less complicated of the two. To integrate a new PCAP processing tool into Malcolm (named `cooltool` for this example) the process would entail: 1. Define the service as instructed in the [Adding a new service](contributing-new-image.md#NewImage) section * Note how the existing `zeek` and `arkime` services use [bind mounts](contributing-local-modifications.md#Bind) to access the local `./pcap` directory diff --git a/docs/development.md b/docs/development.md index 5993f641f..37da486d6 100644 --- a/docs/development.md +++ b/docs/development.md @@ -52,24 +52,24 @@ $ ./scripts/build.sh Then, go take a walk or something since it will be a while. When you are done, you can run `docker images` and see if you have fresh images for: * `ghcr.io/idaholab/malcolm/api` (based on `python:3-slim`) -* `ghcr.io/idaholab/malcolm/arkime` (based on `debian:11-slim`) +* `ghcr.io/idaholab/malcolm/arkime` (based on `debian:12-slim`) * `ghcr.io/idaholab/malcolm/dashboards-helper` (based on `alpine:3.18`) * `ghcr.io/idaholab/malcolm/dashboards` (based on `opensearchproject/opensearch-dashboards`) -* `ghcr.io/idaholab/malcolm/file-monitor` (based on `debian:11-slim`) -* `ghcr.io/idaholab/malcolm/file-upload` (based on `debian:11-slim`) +* `ghcr.io/idaholab/malcolm/file-monitor` (based on `debian:12-slim`) +* `ghcr.io/idaholab/malcolm/file-upload` (based on `debian:12-slim`) * `ghcr.io/idaholab/malcolm/filebeat-oss` (based on `docker.elastic.co/beats/filebeat-oss`) -* `ghcr.io/idaholab/malcolm/freq` (based on `debian:11-slim`) +* `ghcr.io/idaholab/malcolm/freq` (based on `debian:12-slim`) * `ghcr.io/idaholab/malcolm/htadmin` (based on `debian:11-slim`) * `ghcr.io/idaholab/malcolm/logstash-oss` (based on `opensearchproject/logstash-oss-with-opensearch-output-plugin`) * `ghcr.io/idaholab/malcolm/netbox` (based on `netboxcommunity/netbox:latest`) * `ghcr.io/idaholab/malcolm/nginx-proxy` (based on `alpine:3.18`) * `ghcr.io/idaholab/malcolm/opensearch` (based on `opensearchproject/opensearch`) -* `ghcr.io/idaholab/malcolm/pcap-capture` (based on `debian:11-slim`) -* `ghcr.io/idaholab/malcolm/pcap-monitor` (based on `debian:11-slim`) +* `ghcr.io/idaholab/malcolm/pcap-capture` (based on `debian:12-slim`) +* `ghcr.io/idaholab/malcolm/pcap-monitor` (based on `debian:12-slim`) * `ghcr.io/idaholab/malcolm/postgresql` (based on `postgres:14-alpine`) * `ghcr.io/idaholab/malcolm/redis` (based on `redis:7-alpine`) -* `ghcr.io/idaholab/malcolm/suricata` (based on `debian:11-slim`) -* `ghcr.io/idaholab/malcolm/zeek` (based on `debian:11-slim`) +* `ghcr.io/idaholab/malcolm/suricata` (based on `debian:12-slim`) +* `ghcr.io/idaholab/malcolm/zeek` (based on `debian:12-slim`) Alternately, if you have forked Malcolm on GitHub, [workflow files]({{ site.github.repository_url }}/tree/{{ site.github.build_revision }}/.github/workflows/) are provided that contain instructions for GitHub to build the docker images, as well as [sensor](live-analysis.md#Hedgehog) and [Malcolm](malcolm-iso.md#ISO) installer ISOs. The resulting images are named according to the pattern `ghcr.io/owner/malcolm/image:branch` (e.g., if you have forked Malcolm with the GitHub user `romeogdetlevjr`, the `Arkime` container built for the `main` would be named `ghcr.io/romeogdetlevjr/malcolm/arkime:main`). To run your local instance of Malcolm using these images instead of the official ones, you willll need to edit your `docker-compose.yml` file(s) and replace the `image:` tags according to this new pattern, or use the bash helper script `./shared/bin/github_image_helper.sh` to pull and re-tag the images. diff --git a/docs/download.md b/docs/download.md index acd66e703..d47efd58a 100644 --- a/docs/download.md +++ b/docs/download.md @@ -16,7 +16,7 @@ While official downloads of the Malcolm installer ISO are not provided, an **uno | ISO | SHA256 | |---|---| -| [malcolm-23.07.1.iso](/iso/malcolm-23.07.1.iso) (4.6GiB) | [`f6a244079ea016269454ad4d19b20672952417a88599fa7536bf476056f619f6`](/iso/malcolm-23.07.1.iso.sha256.txt) | +| [malcolm-23.08.0.iso](/iso/malcolm-23.08.0.iso) (4.6GiB) | [`54c3298e4e4a16430f698a07a7b3d44529d2684b85f8903a2b224963474711bc`](/iso/malcolm-23.08.0.iso.sha256.txt) | ## Hedgehog Linux @@ -26,7 +26,7 @@ While official downloads of the Malcolm installer ISO are not provided, an **uno | ISO | SHA256 | |---|---| -| [hedgehog-23.07.1.iso](/iso/hedgehog-23.07.1.iso) (2.3GiB) | [`4e92f2df34884b381885256ab74535bd9c3e38b7b6e14e2403524651fed759a3`](/iso/hedgehog-23.07.1.iso.sha256.txt) | +| [hedgehog-23.08.0.iso](/iso/hedgehog-23.08.0.iso) (2.3GiB) | [`944bed2e7e56377ee6f720f8d126415455d34b89cd6b4402caf786897b216fa3`](/iso/hedgehog-23.08.0.iso.sha256.txt) | ## Warning diff --git a/docs/hedgehog-iso-build.md b/docs/hedgehog-iso-build.md index ee7ad904b..cba7600e1 100644 --- a/docs/hedgehog-iso-build.md +++ b/docs/hedgehog-iso-build.md @@ -5,7 +5,7 @@ Official downloads of the Hedgehog Linux installer ISO are not provided: however * [Vagrant](https://www.vagrantup.com/) - [`vagrant-reload`](https://github.com/aidanns/vagrant-reload) plugin - [`vagrant-sshfs`](https://github.com/dustymabe/vagrant-sshfs) plugin - - [`bento/debian-11`](https://app.vagrantup.com/bento/boxes/debian-11) Vagrant box + - [`bento/debian-12`](https://app.vagrantup.com/bento/boxes/debian-12) Vagrant box The build should work with either the [VirtualBox](https://www.virtualbox.org/) provider or the [libvirt](https://libvirt.org/) provider: @@ -13,7 +13,7 @@ The build should work with either the [VirtualBox](https://www.virtualbox.org/) - [`vagrant-vbguest`](https://github.com/dotless-de/vagrant-vbguest) plugin * [libvirt](https://libvirt.org/) - [`vagrant-libvirt`](https://github.com/vagrant-libvirt/vagrant-libvirt) provider plugin - - [`vagrant-mutate`](https://github.com/sciurus/vagrant-mutate) plugin to convert [`bento/debian-11`](https://app.vagrantup.com/bento/boxes/debian-11) Vagrant box to `libvirt` format + - [`vagrant-mutate`](https://github.com/sciurus/vagrant-mutate) plugin to convert [`bento/debian-12`](https://app.vagrantup.com/bento/boxes/debian-12) Vagrant box to `libvirt` format To perform a clean build the Hedgehog Linux installer ISO, navigate to your local [Malcolm]({{ site.github.repository_url }}/) working copy and run: @@ -29,7 +29,7 @@ Building the ISO may take 90 minutes or more depending on your system. As the bu ``` … -Finished, created "/sensor-build/hedgehog-23.07.1.iso" +Finished, created "/sensor-build/hedgehog-23.08.0.iso" … ``` diff --git a/docs/images/screenshots/malcolm_upload.png b/docs/images/screenshots/malcolm_upload.png index f56b4c79f..62e54eb2d 100644 Binary files a/docs/images/screenshots/malcolm_upload.png and b/docs/images/screenshots/malcolm_upload.png differ diff --git a/docs/kubernetes-azure.md b/docs/kubernetes-azure.md new file mode 100644 index 000000000..76a3f7329 --- /dev/null +++ b/docs/kubernetes-azure.md @@ -0,0 +1,22 @@ +# Deploying Malcolm on Microsoft Azure Kubernetes Service (AKS) + +* [Deploying Malcolm on Microsoft Azure Kubernetes Service (AKS)](#KubernetesAzure) + - [Prerequisites](#Prerequisites) + - [Procedure](#Procedure) +* [Attribution](#AzureAttribution) + +This document outlines the process of setting up a cluster on Microsoft [Azure Kubernetes Service (AKS)](https://azure.microsoft.com/en-us/products/kubernetes-service) using [Azure](https://azure.microsoft.com/en-us/) in preparation for [**Deploying Malcolm with Kubernetes**](kubernetes.md). + +This is a work-in-progress document that is still a bit rough around the edges. Any feedback is welcome in the [relevant issue](https://github.com/idaholab/Malcolm/issues/231) on GitHub. + +This document assumes good working knowledge of Azure and Azure Kubernetes Service (AKS). Good documentation resources can be found in the [Azure documentation](https://learn.microsoft.com/en-us/azure/), the [AKS documentation](https://learn.microsoft.com/en-us/azure/aks/), [Kubernetes core concepts for Azure Kubernetes Service (AKS)](https://learn.microsoft.com/en-us/azure/aks/concepts-clusters-workloads), and the [AKS Workshop](https://www.microsoft.com/azure/partners/news/article/azure-kubernetes-service-workshop). + +## Prerequisites + +* [az cli](https://learn.microsoft.com/en-us/cli/azure/) - the Azure Command Line Interface with functioning access to the Azure infrastructure + +## Procedure + +## Attribution + +Microsoft Azure, the Microsoft Azure logo, Azure, and any other Microsoft Azure Marks used in these materials are trademarks of Microsoft Corporation or its affiliates in the United States and/or other countries. The information about providers and services contained in this document is for instructional purposes and does not constitute endorsement or recommendation. diff --git a/docs/kubernetes.md b/docs/kubernetes.md index 263e30e66..308bc5ae5 100644 --- a/docs/kubernetes.md +++ b/docs/kubernetes.md @@ -15,6 +15,7 @@ - [Horizontal Scaling](#FutureScaleOut) - [Helm Chart](#FutureHelmChart) * [Deploying Malcolm on Amazon Elastic Kubernetes Service (EKS)](kubernetes-eks.md#KubernetesEKS) +* [Deploying Malcolm on Microsoft Azure Kubernetes Service (AKS)](kubernetes-azure.md#KubernetesAzure) This document assumes good working knowledge of Kubernetes (K8s). The comprehensive [Kubernetes documentation](https://kubernetes.io/docs/home/) is a good place to go for more information about Kubernetes. @@ -274,28 +275,28 @@ agent2 | agent2 | 192.168.56.12 | agent2 | k3s | 6000m | agent1 | agent1 | 192.168.56.11 | agent1 | k3s | 6000m | 861.34m | 14.36% | 19.55Gi | 9.29Gi | 61.28Gi | 11 | Pod Name | State | Pod IP | Pod Kind | Worker Node | CPU Usage | Memory Usage | Container Name:Restarts | Container Image | -api-deployment-6f4686cf59-bn286 | Running | 10.42.2.14 | ReplicaSet | agent1 | 0.11m | 59.62Mi | api-container:0 | api:23.07.1 | -file-monitor-deployment-855646bd75-vk7st | Running | 10.42.2.16 | ReplicaSet | agent1 | 8.47m | 1.46Gi | file-monitor-container:0 | file-monitor:23.07.1 | -zeek-live-deployment-64b69d4b6f-947vr | Running | 10.42.2.17 | ReplicaSet | agent1 | 0.02m | 12.44Mi | zeek-live-container:0 | zeek:23.07.1 | -dashboards-helper-deployment-69dc54f6b6-ln4sq | Running | 10.42.2.15 | ReplicaSet | agent1 | 10.77m | 38.43Mi | dashboards-helper-container:0 | dashboards-helper:23.07.1 | -upload-deployment-586568844b-4jnk9 | Running | 10.42.2.18 | ReplicaSet | agent1 | 0.15m | 29.78Mi | upload-container:0 | file-upload:23.07.1 | -filebeat-deployment-6ff8bc444f-t7h49 | Running | 10.42.2.20 | ReplicaSet | agent1 | 2.84m | 70.71Mi | filebeat-container:0 | filebeat-oss:23.07.1 | -zeek-offline-deployment-844f4865bd-g2sdm | Running | 10.42.2.21 | ReplicaSet | agent1 | 0.17m | 41.92Mi | zeek-offline-container:0 | zeek:23.07.1 | -logstash-deployment-6fbc9fdcd5-hwx8s | Running | 10.42.2.22 | ReplicaSet | agent1 | 85.55m | 2.91Gi | logstash-container:0 | logstash-oss:23.07.1 | -netbox-deployment-cdcff4977-hbbw5 | Running | 10.42.2.23 | ReplicaSet | agent1 | 807.64m | 702.86Mi | netbox-container:0 | netbox:23.07.1 | -suricata-offline-deployment-6ccdb89478-z5696 | Running | 10.42.2.19 | ReplicaSet | agent1 | 0.22m | 34.88Mi | suricata-offline-container:0 | suricata:23.07.1 | -dashboards-deployment-69b5465db-vz88g | Running | 10.42.1.14 | ReplicaSet | agent2 | 0.94m | 100.12Mi | dashboards-container:0 | dashboards:23.07.1 | -netbox-redis-cache-deployment-5f77d47b8b-z7t2z | Running | 10.42.1.15 | ReplicaSet | agent2 | 3.57m | 7.36Mi | netbox-redis-cache-container:0 | redis:23.07.1 | -suricata-live-deployment-6494c77759-9rlnt | Running | 10.42.1.16 | ReplicaSet | agent2 | 0.02m | 9.69Mi | suricata-live-container:0 | suricata:23.07.1 | -freq-deployment-cfd84fd97-dnngf | Running | 10.42.1.17 | ReplicaSet | agent2 | 0.2m | 26.36Mi | freq-container:0 | freq:23.07.1 | -arkime-deployment-56999cdd66-s98pp | Running | 10.42.1.18 | ReplicaSet | agent2 | 4.15m | 113.07Mi | arkime-container:0 | arkime:23.07.1 | -pcap-monitor-deployment-594ff674c4-fsm7m | Running | 10.42.1.19 | ReplicaSet | agent2 | 1.24m | 48.44Mi | pcap-monitor-container:0 | pcap-monitor:23.07.1 | -pcap-capture-deployment-7c8bf6957-jzpzn | Running | 10.42.1.20 | ReplicaSet | agent2 | 0.02m | 9.64Mi | pcap-capture-container:0 | pcap-capture:23.07.1 | -netbox-postgres-deployment-5879b8dffc-kkt56 | Running | 10.42.1.21 | ReplicaSet | agent2 | 70.91m | 33.02Mi | netbox-postgres-container:0 | postgresql:23.07.1 | -htadmin-deployment-6fc46888b9-sq6ln | Running | 10.42.1.23 | ReplicaSet | agent2 | 0.14m | 30.53Mi | htadmin-container:0 | htadmin:23.07.1 | -netbox-redis-deployment-5bcd8f6c96-j5xpf | Running | 10.42.1.24 | ReplicaSet | agent2 | 1.46m | 7.34Mi | netbox-redis-container:0 | redis:23.07.1 | -nginx-proxy-deployment-69fcc4968d-f68tq | Running | 10.42.1.22 | ReplicaSet | agent2 | 0.31m | 22.63Mi | nginx-proxy-container:0 | nginx-proxy:23.07.1 | -opensearch-deployment-75498799f6-4zmwd | Running | 10.42.1.25 | ReplicaSet | agent2 | 89.8m | 11.03Gi | opensearch-container:0 | opensearch:23.07.1 | +api-deployment-6f4686cf59-bn286 | Running | 10.42.2.14 | ReplicaSet | agent1 | 0.11m | 59.62Mi | api-container:0 | api:23.08.0 | +file-monitor-deployment-855646bd75-vk7st | Running | 10.42.2.16 | ReplicaSet | agent1 | 8.47m | 1.46Gi | file-monitor-container:0 | file-monitor:23.08.0 | +zeek-live-deployment-64b69d4b6f-947vr | Running | 10.42.2.17 | ReplicaSet | agent1 | 0.02m | 12.44Mi | zeek-live-container:0 | zeek:23.08.0 | +dashboards-helper-deployment-69dc54f6b6-ln4sq | Running | 10.42.2.15 | ReplicaSet | agent1 | 10.77m | 38.43Mi | dashboards-helper-container:0 | dashboards-helper:23.08.0 | +upload-deployment-586568844b-4jnk9 | Running | 10.42.2.18 | ReplicaSet | agent1 | 0.15m | 29.78Mi | upload-container:0 | file-upload:23.08.0 | +filebeat-deployment-6ff8bc444f-t7h49 | Running | 10.42.2.20 | ReplicaSet | agent1 | 2.84m | 70.71Mi | filebeat-container:0 | filebeat-oss:23.08.0 | +zeek-offline-deployment-844f4865bd-g2sdm | Running | 10.42.2.21 | ReplicaSet | agent1 | 0.17m | 41.92Mi | zeek-offline-container:0 | zeek:23.08.0 | +logstash-deployment-6fbc9fdcd5-hwx8s | Running | 10.42.2.22 | ReplicaSet | agent1 | 85.55m | 2.91Gi | logstash-container:0 | logstash-oss:23.08.0 | +netbox-deployment-cdcff4977-hbbw5 | Running | 10.42.2.23 | ReplicaSet | agent1 | 807.64m | 702.86Mi | netbox-container:0 | netbox:23.08.0 | +suricata-offline-deployment-6ccdb89478-z5696 | Running | 10.42.2.19 | ReplicaSet | agent1 | 0.22m | 34.88Mi | suricata-offline-container:0 | suricata:23.08.0 | +dashboards-deployment-69b5465db-vz88g | Running | 10.42.1.14 | ReplicaSet | agent2 | 0.94m | 100.12Mi | dashboards-container:0 | dashboards:23.08.0 | +netbox-redis-cache-deployment-5f77d47b8b-z7t2z | Running | 10.42.1.15 | ReplicaSet | agent2 | 3.57m | 7.36Mi | netbox-redis-cache-container:0 | redis:23.08.0 | +suricata-live-deployment-6494c77759-9rlnt | Running | 10.42.1.16 | ReplicaSet | agent2 | 0.02m | 9.69Mi | suricata-live-container:0 | suricata:23.08.0 | +freq-deployment-cfd84fd97-dnngf | Running | 10.42.1.17 | ReplicaSet | agent2 | 0.2m | 26.36Mi | freq-container:0 | freq:23.08.0 | +arkime-deployment-56999cdd66-s98pp | Running | 10.42.1.18 | ReplicaSet | agent2 | 4.15m | 113.07Mi | arkime-container:0 | arkime:23.08.0 | +pcap-monitor-deployment-594ff674c4-fsm7m | Running | 10.42.1.19 | ReplicaSet | agent2 | 1.24m | 48.44Mi | pcap-monitor-container:0 | pcap-monitor:23.08.0 | +pcap-capture-deployment-7c8bf6957-jzpzn | Running | 10.42.1.20 | ReplicaSet | agent2 | 0.02m | 9.64Mi | pcap-capture-container:0 | pcap-capture:23.08.0 | +netbox-postgres-deployment-5879b8dffc-kkt56 | Running | 10.42.1.21 | ReplicaSet | agent2 | 70.91m | 33.02Mi | netbox-postgres-container:0 | postgresql:23.08.0 | +htadmin-deployment-6fc46888b9-sq6ln | Running | 10.42.1.23 | ReplicaSet | agent2 | 0.14m | 30.53Mi | htadmin-container:0 | htadmin:23.08.0 | +netbox-redis-deployment-5bcd8f6c96-j5xpf | Running | 10.42.1.24 | ReplicaSet | agent2 | 1.46m | 7.34Mi | netbox-redis-container:0 | redis:23.08.0 | +nginx-proxy-deployment-69fcc4968d-f68tq | Running | 10.42.1.22 | ReplicaSet | agent2 | 0.31m | 22.63Mi | nginx-proxy-container:0 | nginx-proxy:23.08.0 | +opensearch-deployment-75498799f6-4zmwd | Running | 10.42.1.25 | ReplicaSet | agent2 | 89.8m | 11.03Gi | opensearch-container:0 | opensearch:23.08.0 | ``` The other control scripts (`stop`, `restart`, `logs`, etc.) work in a similar manner as in a Docker-based deployment. One notable difference is the `wipe` script: data on PersistentVolume storage cannot be deleted by `wipe`. It must be deleted manually on the storage media underlying the PersistentVolumes. @@ -551,28 +552,28 @@ agent1 | agent1 | 192.168.56.11 | agent1 | k3s | 6000m | agent2 | agent2 | 192.168.56.12 | agent2 | k3s | 6000m | 552.71m | 9.21% | 19.55Gi | 13.27Gi | 61.28Gi | 12 | Pod Name | State | Pod IP | Pod Kind | Worker Node | CPU Usage | Memory Usage | Container Name:Restarts | Container Image | -netbox-redis-cache-deployment-5f77d47b8b-jr9nt | Running | 10.42.2.6 | ReplicaSet | agent2 | 1.89m | 7.24Mi | netbox-redis-cache-container:0 | redis:23.07.1 | -netbox-redis-deployment-5bcd8f6c96-bkzmh | Running | 10.42.2.5 | ReplicaSet | agent2 | 1.62m | 7.52Mi | netbox-redis-container:0 | redis:23.07.1 | -dashboards-helper-deployment-69dc54f6b6-ks7ps | Running | 10.42.2.4 | ReplicaSet | agent2 | 12.95m | 40.75Mi | dashboards-helper-container:0 | dashboards-helper:23.07.1 | -freq-deployment-cfd84fd97-5bwp6 | Running | 10.42.2.8 | ReplicaSet | agent2 | 0.11m | 26.33Mi | freq-container:0 | freq:23.07.1 | -pcap-capture-deployment-7c8bf6957-hkvkn | Running | 10.42.2.12 | ReplicaSet | agent2 | 0.02m | 9.21Mi | pcap-capture-container:0 | pcap-capture:23.07.1 | -nginx-proxy-deployment-69fcc4968d-m57rz | Running | 10.42.2.10 | ReplicaSet | agent2 | 0.91m | 22.72Mi | nginx-proxy-container:0 | nginx-proxy:23.07.1 | -htadmin-deployment-6fc46888b9-vpt7l | Running | 10.42.2.7 | ReplicaSet | agent2 | 0.16m | 30.21Mi | htadmin-container:0 | htadmin:23.07.1 | -opensearch-deployment-75498799f6-5v92w | Running | 10.42.2.13 | ReplicaSet | agent2 | 139.2m | 10.86Gi | opensearch-container:0 | opensearch:23.07.1 | -zeek-live-deployment-64b69d4b6f-fcb6n | Running | 10.42.2.9 | ReplicaSet | agent2 | 0.02m | 109.55Mi | zeek-live-container:0 | zeek:23.07.1 | -dashboards-deployment-69b5465db-kgsqk | Running | 10.42.2.3 | ReplicaSet | agent2 | 14.98m | 108.85Mi | dashboards-container:0 | dashboards:23.07.1 | -arkime-deployment-56999cdd66-xxpw9 | Running | 10.42.2.11 | ReplicaSet | agent2 | 208.95m | 78.42Mi | arkime-container:0 | arkime:23.07.1 | -api-deployment-6f4686cf59-xt9md | Running | 10.42.1.3 | ReplicaSet | agent1 | 0.14m | 56.88Mi | api-container:0 | api:23.07.1 | -netbox-postgres-deployment-5879b8dffc-lb4qm | Running | 10.42.1.6 | ReplicaSet | agent1 | 141.2m | 48.02Mi | netbox-postgres-container:0 | postgresql:23.07.1 | -pcap-monitor-deployment-594ff674c4-fwq7g | Running | 10.42.1.12 | ReplicaSet | agent1 | 3.93m | 46.44Mi | pcap-monitor-container:0 | pcap-monitor:23.07.1 | -suricata-offline-deployment-6ccdb89478-j5fgj | Running | 10.42.1.10 | ReplicaSet | agent1 | 10.42m | 35.12Mi | suricata-offline-container:0 | suricata:23.07.1 | -suricata-live-deployment-6494c77759-rpt48 | Running | 10.42.1.8 | ReplicaSet | agent1 | 0.01m | 9.62Mi | suricata-live-container:0 | suricata:23.07.1 | -netbox-deployment-cdcff4977-7ns2q | Running | 10.42.1.7 | ReplicaSet | agent1 | 830.47m | 530.7Mi | netbox-container:0 | netbox:23.07.1 | -zeek-offline-deployment-844f4865bd-7x68b | Running | 10.42.1.9 | ReplicaSet | agent1 | 1.44m | 43.66Mi | zeek-offline-container:0 | zeek:23.07.1 | -filebeat-deployment-6ff8bc444f-pdgzj | Running | 10.42.1.11 | ReplicaSet | agent1 | 0.78m | 75.25Mi | filebeat-container:0 | filebeat-oss:23.07.1 | -file-monitor-deployment-855646bd75-nbngq | Running | 10.42.1.4 | ReplicaSet | agent1 | 1.69m | 1.46Gi | file-monitor-container:0 | file-monitor:23.07.1 | -upload-deployment-586568844b-9s7f5 | Running | 10.42.1.13 | ReplicaSet | agent1 | 0.14m | 29.62Mi | upload-container:0 | file-upload:23.07.1 | -logstash-deployment-6fbc9fdcd5-2hhx8 | Running | 10.42.1.5 | ReplicaSet | agent1 | 3236.29m | 357.36Mi | logstash-container:0 | logstash-oss:23.07.1 | +netbox-redis-cache-deployment-5f77d47b8b-jr9nt | Running | 10.42.2.6 | ReplicaSet | agent2 | 1.89m | 7.24Mi | netbox-redis-cache-container:0 | redis:23.08.0 | +netbox-redis-deployment-5bcd8f6c96-bkzmh | Running | 10.42.2.5 | ReplicaSet | agent2 | 1.62m | 7.52Mi | netbox-redis-container:0 | redis:23.08.0 | +dashboards-helper-deployment-69dc54f6b6-ks7ps | Running | 10.42.2.4 | ReplicaSet | agent2 | 12.95m | 40.75Mi | dashboards-helper-container:0 | dashboards-helper:23.08.0 | +freq-deployment-cfd84fd97-5bwp6 | Running | 10.42.2.8 | ReplicaSet | agent2 | 0.11m | 26.33Mi | freq-container:0 | freq:23.08.0 | +pcap-capture-deployment-7c8bf6957-hkvkn | Running | 10.42.2.12 | ReplicaSet | agent2 | 0.02m | 9.21Mi | pcap-capture-container:0 | pcap-capture:23.08.0 | +nginx-proxy-deployment-69fcc4968d-m57rz | Running | 10.42.2.10 | ReplicaSet | agent2 | 0.91m | 22.72Mi | nginx-proxy-container:0 | nginx-proxy:23.08.0 | +htadmin-deployment-6fc46888b9-vpt7l | Running | 10.42.2.7 | ReplicaSet | agent2 | 0.16m | 30.21Mi | htadmin-container:0 | htadmin:23.08.0 | +opensearch-deployment-75498799f6-5v92w | Running | 10.42.2.13 | ReplicaSet | agent2 | 139.2m | 10.86Gi | opensearch-container:0 | opensearch:23.08.0 | +zeek-live-deployment-64b69d4b6f-fcb6n | Running | 10.42.2.9 | ReplicaSet | agent2 | 0.02m | 109.55Mi | zeek-live-container:0 | zeek:23.08.0 | +dashboards-deployment-69b5465db-kgsqk | Running | 10.42.2.3 | ReplicaSet | agent2 | 14.98m | 108.85Mi | dashboards-container:0 | dashboards:23.08.0 | +arkime-deployment-56999cdd66-xxpw9 | Running | 10.42.2.11 | ReplicaSet | agent2 | 208.95m | 78.42Mi | arkime-container:0 | arkime:23.08.0 | +api-deployment-6f4686cf59-xt9md | Running | 10.42.1.3 | ReplicaSet | agent1 | 0.14m | 56.88Mi | api-container:0 | api:23.08.0 | +netbox-postgres-deployment-5879b8dffc-lb4qm | Running | 10.42.1.6 | ReplicaSet | agent1 | 141.2m | 48.02Mi | netbox-postgres-container:0 | postgresql:23.08.0 | +pcap-monitor-deployment-594ff674c4-fwq7g | Running | 10.42.1.12 | ReplicaSet | agent1 | 3.93m | 46.44Mi | pcap-monitor-container:0 | pcap-monitor:23.08.0 | +suricata-offline-deployment-6ccdb89478-j5fgj | Running | 10.42.1.10 | ReplicaSet | agent1 | 10.42m | 35.12Mi | suricata-offline-container:0 | suricata:23.08.0 | +suricata-live-deployment-6494c77759-rpt48 | Running | 10.42.1.8 | ReplicaSet | agent1 | 0.01m | 9.62Mi | suricata-live-container:0 | suricata:23.08.0 | +netbox-deployment-cdcff4977-7ns2q | Running | 10.42.1.7 | ReplicaSet | agent1 | 830.47m | 530.7Mi | netbox-container:0 | netbox:23.08.0 | +zeek-offline-deployment-844f4865bd-7x68b | Running | 10.42.1.9 | ReplicaSet | agent1 | 1.44m | 43.66Mi | zeek-offline-container:0 | zeek:23.08.0 | +filebeat-deployment-6ff8bc444f-pdgzj | Running | 10.42.1.11 | ReplicaSet | agent1 | 0.78m | 75.25Mi | filebeat-container:0 | filebeat-oss:23.08.0 | +file-monitor-deployment-855646bd75-nbngq | Running | 10.42.1.4 | ReplicaSet | agent1 | 1.69m | 1.46Gi | file-monitor-container:0 | file-monitor:23.08.0 | +upload-deployment-586568844b-9s7f5 | Running | 10.42.1.13 | ReplicaSet | agent1 | 0.14m | 29.62Mi | upload-container:0 | file-upload:23.08.0 | +logstash-deployment-6fbc9fdcd5-2hhx8 | Running | 10.42.1.5 | ReplicaSet | agent1 | 3236.29m | 357.36Mi | logstash-container:0 | logstash-oss:23.08.0 | ``` View container logs for the Malcolm deployment with `./scripts/logs` (if **[stern](https://github.com/stern/stern)** present in `$PATH`): diff --git a/docs/malcolm-config.md b/docs/malcolm-config.md index 77989cd73..a99202165 100644 --- a/docs/malcolm-config.md +++ b/docs/malcolm-config.md @@ -67,7 +67,7 @@ Although the configuration script automates many of the following configuration - `SURICATA_ROTATED_PCAP` - if set to `true`, Suricata can analyze PCAP files captured by `netsniff-ng` or `tcpdump` (see `PCAP_ENABLE_NETSNIFF` and `PCAP_ENABLE_TCPDUMP`, as well as `SURICATA_AUTO_ANALYZE_PCAP_FILES`); if `SURICATA_LIVE_CAPTURE` is `true`, this should be `false`; otherwise Suricata will see duplicate traffic - `SURICATA_…` - the [`suricata` container entrypoint script]({{ site.github.repository_url }}/blob/{{ site.github.build_revision }}/shared/bin/suricata_config_populate.py) can use **many** more environment variables to tweak [suricata.yaml](https://github.com/OISF/suricata/blob/master/suricata.yaml.in); in that script, `DEFAULT_VARS` defines those variables (albeit without the `SURICATA_` prefix you must add to each for use) Note that for some variables (e.g., something with a sequence like `HOME_NET`) Suricata wants values to be quoted. To accomplish that in the `suricata.env` file, use outer single quotes with inner double quotes, like this: + `SURICATA_HOME_NET='"[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]"'` -* **`upload-common.env`** and **`upload.env`** - settings for dealing with PCAP files [uploaded](upload.md#Upload) to Malcolm for analysis +* **`upload-common.env`** - settings for dealing with PCAP files [uploaded](upload.md#Upload) to Malcolm for analysis - `AUTO_TAG` – if set to `true`, Malcolm will automatically create Arkime sessions and Zeek logs with tags based on the filename, as described in [Tagging](upload.md#Tagging) (default `true`) * **`zeek.env`**, **`zeek-secret.env`**, **`zeek-live.env`** and **`zeek-offline.env`** - settings for [Zeek](https://www.zeek.org/index.html) and for scanning [extracted files](file-scanning.md#ZeekFileExtraction) Zeek observes in network traffic - `EXTRACTED_FILE_CAPA_VERBOSE` – if set to `true`, all Capa rule hits will be logged; otherwise (`false`) only [MITRE ATT&CK® technique](https://attack.mitre.org/techniques) classifications will be logged diff --git a/docs/malcolm-hedgehog-e2e-iso-install.md b/docs/malcolm-hedgehog-e2e-iso-install.md index ded84b0a9..5ea807a38 100644 --- a/docs/malcolm-hedgehog-e2e-iso-install.md +++ b/docs/malcolm-hedgehog-e2e-iso-install.md @@ -189,26 +189,28 @@ The [configuration and tuning](malcolm-config.md#ConfigAndTuning) wizard's quest - Malcolm will [map MAC addresses](https://standards.ieee.org/products-programs/regauth/) to hardware manufacturer when possible. Users probably want to answer **Y** to this question. * **Perform string randomness scoring on some fields?** - If enabled, domain names observed in network traffic (from DNS queries and SSL server names) will be assigned entropy scores as calculated by [`freq`](https://github.com/MarkBaggett/freq). Users probably want to answer **Y** to this question. -* **Expose OpenSearch port to external hosts?** - - Answer **Y** in order for Malcolm's firewall to allow connections from a remote log forwarder (such as Hedgehog Linux) to TCP port 9200 so that Arkime sessions can be written to Malcolm's OpenSearch database. -* **Expose Logstash port to external hosts?** - - Answer **Y** in order for Malcolm's firewall to allow connections from a remote log forwarder (such as Hedgehog Linux) to TCP port 5044 so that Zeek and Suricata logs can be ingested by Malcolm's Logstash instance. -* **Expose Filebeat TCP port to external hosts?** - - Answer **Y** in order for Malcolm's firewall to allow connections from a remote log forwarder (such as Hedgehog Linux for resource utilization metrics or other forwarders for other [third-Party logs](third-party-logs.md#ThirdPartyLogs)) to TCP port 5045. -* **Use default field values for Filebeat TCP listener?** - - Answer **Y** to use the defaults and skip the next five questions about the Filebeat TCP listener. -* **Select log format for messages sent to Filebeat TCP listener** - - Possible choices include `json` and `raw`; users probably want to choose `json`. -* **Source field to parse for messages sent to Filebeat TCP listener** - - The default choice (and the one Hedgehog Linux will be sending) is `message`. -* **Target field under which to store decoded JSON fields for messages sent to Filebeat TCP listener** - - The default choice (and the one that corresponds to Malcolm's dashboards built for the resource utilization metrics sent by Hedgehog Linux) is `miscbeat`. -* **Field to drop from events sent to Filebeat TCP listener** - - Users most likely want this to be the default, `message`, to match the field name specified above. -* **Tag to apply to messages sent to Filebeat TCP listener** - - The default is `_malcolm_beats`, which is used by Malcolm to recognize and parse metrics sent from Hedgehog Linux. -* **Expose SFTP server (for PCAP upload) to external hosts?** - - Users should answer **N** unless they plan to use SFTP/SCP to [upload](upload.md#Upload) PCAP files to Malcolm; answering **Y** will expose TCP port 8022 in Malcolm's firewall for SFTP/SCP connections +* **Should Malcolm accept logs and metrics from a Hedgehog Linux sensor or other forwarder?** + - Answer **yes** or **no** in order for Malcolm's firewall to allow or block connections for OpenSearch, Logstash, and Filebeat TCP, bypassing the following several questions in this list. Answer **customize** to proceed to answer the following related questions individually. + - **Expose OpenSearch port to external hosts?** + + Answer **Y** in order for Malcolm's firewall to allow connections from a remote log forwarder (such as Hedgehog Linux) to TCP port 9200 so that Arkime sessions can be written to Malcolm's OpenSearch database. + - **Expose Logstash port to external hosts?** + + Answer **Y** in order for Malcolm's firewall to allow connections from a remote log forwarder (such as Hedgehog Linux) to TCP port 5044 so that Zeek and Suricata logs can be ingested by Malcolm's Logstash instance. + - **Expose Filebeat TCP port to external hosts?** + + Answer **Y** in order for Malcolm's firewall to allow connections from a remote log forwarder (such as Hedgehog Linux for resource utilization metrics or other forwarders for other [third-Party logs](third-party-logs.md#ThirdPartyLogs)) to TCP port 5045. + - **Use default field values for Filebeat TCP listener?** + + Answer **Y** to use the defaults and skip the next five questions about the Filebeat TCP listener. + - **Select log format for messages sent to Filebeat TCP listener** + + Possible choices include `json` and `raw`; users probably want to choose `json`. + - **Source field to parse for messages sent to Filebeat TCP listener** + + The default choice (and the one Hedgehog Linux will be sending) is `message`. + - **Target field under which to store decoded JSON fields for messages sent to Filebeat TCP listener** + + The default choice (and the one that corresponds to Malcolm's dashboards built for the resource utilization metrics sent by Hedgehog Linux) is `miscbeat`. + - **Field to drop from events sent to Filebeat TCP listener** + + Users most likely want this to be the default, `message`, to match the field name specified above. + - **Tag to apply to messages sent to Filebeat TCP listener** + + The default is `_malcolm_beats`, which is used by Malcolm to recognize and parse metrics sent from Hedgehog Linux. + - **Expose SFTP server (for PCAP upload) to external hosts?** + + Users should answer **N** unless they plan to use SFTP/SCP to [upload](upload.md#Upload) PCAP files to Malcolm; answering **Y** will expose TCP port 8022 in Malcolm's firewall for SFTP/SCP connections * **Enable file extraction with Zeek?** - Answer **Y** to indicate that Zeek should [extract files](file-scanning.md#ZeekFileExtraction) transfered in observed network traffic. * **Select file extraction behavior** diff --git a/docs/malcolm-iso.md b/docs/malcolm-iso.md index 79ecbb1c1..2d5d9666b 100644 --- a/docs/malcolm-iso.md +++ b/docs/malcolm-iso.md @@ -17,7 +17,7 @@ Official downloads of the Malcolm installer ISO are not provided: however, it ca * [Vagrant](https://www.vagrantup.com/) - [`vagrant-reload`](https://github.com/aidanns/vagrant-reload) plugin - [`vagrant-sshfs`](https://github.com/dustymabe/vagrant-sshfs) plugin - - [`bento/debian-11`](https://app.vagrantup.com/bento/boxes/debian-11) Vagrant box + - [`bento/debian-12`](https://app.vagrantup.com/bento/boxes/debian-12) Vagrant box The build should work with either the [VirtualBox](https://www.virtualbox.org/) provider or the [libvirt](https://libvirt.org/) provider: @@ -25,7 +25,7 @@ The build should work with either the [VirtualBox](https://www.virtualbox.org/) - [`vagrant-vbguest`](https://github.com/dotless-de/vagrant-vbguest) plugin * [libvirt](https://libvirt.org/) - [`vagrant-libvirt`](https://github.com/vagrant-libvirt/vagrant-libvirt) provider plugin - - [`vagrant-mutate`](https://github.com/sciurus/vagrant-mutate) plugin to convert [`bento/debian-11`](https://app.vagrantup.com/bento/boxes/debian-11) Vagrant box to `libvirt` format + - [`vagrant-mutate`](https://github.com/sciurus/vagrant-mutate) plugin to convert [`bento/debian-12`](https://app.vagrantup.com/bento/boxes/debian-12) Vagrant box to `libvirt` format To perform a clean build of the Malcolm installer ISO, navigate to the local Malcolm working copy and run: @@ -41,7 +41,7 @@ Building the ISO may take 30 minutes or more depending on the system. As the bui ``` … -Finished, created "/malcolm-build/malcolm-iso/malcolm-23.07.1.iso" +Finished, created "/malcolm-build/malcolm-iso/malcolm-23.08.0.iso" … ``` diff --git a/docs/quickstart.md b/docs/quickstart.md index 64b5b30a4..40a6634c7 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -54,25 +54,25 @@ You can then observe the images have been retrieved by running `docker images`: ``` $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE -ghcr.io/idaholab/malcolm/api 23.07.1 xxxxxxxxxxxx 3 days ago 158MB -ghcr.io/idaholab/malcolm/arkime 23.07.1 xxxxxxxxxxxx 3 days ago 816MB -ghcr.io/idaholab/malcolm/dashboards 23.07.1 xxxxxxxxxxxx 3 days ago 1.02GB -ghcr.io/idaholab/malcolm/dashboards-helper 23.07.1 xxxxxxxxxxxx 3 days ago 184MB -ghcr.io/idaholab/malcolm/file-monitor 23.07.1 xxxxxxxxxxxx 3 days ago 588MB -ghcr.io/idaholab/malcolm/file-upload 23.07.1 xxxxxxxxxxxx 3 days ago 259MB -ghcr.io/idaholab/malcolm/filebeat-oss 23.07.1 xxxxxxxxxxxx 3 days ago 624MB -ghcr.io/idaholab/malcolm/freq 23.07.1 xxxxxxxxxxxx 3 days ago 132MB -ghcr.io/idaholab/malcolm/htadmin 23.07.1 xxxxxxxxxxxx 3 days ago 242MB -ghcr.io/idaholab/malcolm/logstash-oss 23.07.1 xxxxxxxxxxxx 3 days ago 1.35GB -ghcr.io/idaholab/malcolm/netbox 23.07.1 xxxxxxxxxxxx 3 days ago 1.01GB -ghcr.io/idaholab/malcolm/nginx-proxy 23.07.1 xxxxxxxxxxxx 3 days ago 121MB -ghcr.io/idaholab/malcolm/opensearch 23.07.1 xxxxxxxxxxxx 3 days ago 1.17GB -ghcr.io/idaholab/malcolm/pcap-capture 23.07.1 xxxxxxxxxxxx 3 days ago 121MB -ghcr.io/idaholab/malcolm/pcap-monitor 23.07.1 xxxxxxxxxxxx 3 days ago 213MB -ghcr.io/idaholab/malcolm/postgresql 23.07.1 xxxxxxxxxxxx 3 days ago 268MB -ghcr.io/idaholab/malcolm/redis 23.07.1 xxxxxxxxxxxx 3 days ago 34.2MB -ghcr.io/idaholab/malcolm/suricata 23.07.1 xxxxxxxxxxxx 3 days ago 278MB -ghcr.io/idaholab/malcolm/zeek 23.07.1 xxxxxxxxxxxx 3 days ago 1GB +ghcr.io/idaholab/malcolm/api 23.08.0 xxxxxxxxxxxx 3 days ago 158MB +ghcr.io/idaholab/malcolm/arkime 23.08.0 xxxxxxxxxxxx 3 days ago 816MB +ghcr.io/idaholab/malcolm/dashboards 23.08.0 xxxxxxxxxxxx 3 days ago 1.02GB +ghcr.io/idaholab/malcolm/dashboards-helper 23.08.0 xxxxxxxxxxxx 3 days ago 184MB +ghcr.io/idaholab/malcolm/file-monitor 23.08.0 xxxxxxxxxxxx 3 days ago 588MB +ghcr.io/idaholab/malcolm/file-upload 23.08.0 xxxxxxxxxxxx 3 days ago 259MB +ghcr.io/idaholab/malcolm/filebeat-oss 23.08.0 xxxxxxxxxxxx 3 days ago 624MB +ghcr.io/idaholab/malcolm/freq 23.08.0 xxxxxxxxxxxx 3 days ago 132MB +ghcr.io/idaholab/malcolm/htadmin 23.08.0 xxxxxxxxxxxx 3 days ago 242MB +ghcr.io/idaholab/malcolm/logstash-oss 23.08.0 xxxxxxxxxxxx 3 days ago 1.35GB +ghcr.io/idaholab/malcolm/netbox 23.08.0 xxxxxxxxxxxx 3 days ago 1.01GB +ghcr.io/idaholab/malcolm/nginx-proxy 23.08.0 xxxxxxxxxxxx 3 days ago 121MB +ghcr.io/idaholab/malcolm/opensearch 23.08.0 xxxxxxxxxxxx 3 days ago 1.17GB +ghcr.io/idaholab/malcolm/pcap-capture 23.08.0 xxxxxxxxxxxx 3 days ago 121MB +ghcr.io/idaholab/malcolm/pcap-monitor 23.08.0 xxxxxxxxxxxx 3 days ago 213MB +ghcr.io/idaholab/malcolm/postgresql 23.08.0 xxxxxxxxxxxx 3 days ago 268MB +ghcr.io/idaholab/malcolm/redis 23.08.0 xxxxxxxxxxxx 3 days ago 34.2MB +ghcr.io/idaholab/malcolm/suricata 23.08.0 xxxxxxxxxxxx 3 days ago 278MB +ghcr.io/idaholab/malcolm/zeek 23.08.0 xxxxxxxxxxxx 3 days ago 1GB ``` ### Import from pre-packaged tarballs @@ -90,7 +90,7 @@ A few minutes after starting Malcolm (probably 5 or so for Logstash to be comple * [Arkime](https://arkime.com/): **https://localhost** * [OpenSearch Dashboards](https://opensearch.org/docs/latest/dashboards/index/): **https://localhost/dashboards/** -* [Capture File and Log Archive Upload (Web)](upload.md#Upload): **https://localhost/upload/** -* [Capture File and Log Archive Upload (SFTP)](upload.md#Upload): `sftp://@127.0.0.1:8022/files` +* [Network Traffic Artifact Upload (Web)](upload.md#Upload): **https://localhost/upload/** +* [Network Traffic Artifact Upload (SFTP)](upload.md#Upload): `sftp://@127.0.0.1:8022/files` * [NetBox](asset-interaction-analysis.md#AssetInteractionAnalysis): **https://localhost/netbox/** * [Account Management](authsetup.md#AuthBasicAccountManagement): **https://localhost/auth/** \ No newline at end of file diff --git a/docs/slides/Network Traffic Analysis with Malcolm.odp b/docs/slides/Network Traffic Analysis with Malcolm.odp index cc332a0c6..d01655d82 100644 Binary files a/docs/slides/Network Traffic Analysis with Malcolm.odp and b/docs/slides/Network Traffic Analysis with Malcolm.odp differ diff --git a/docs/slides/Network Traffic Analysis with Malcolm.pdf b/docs/slides/Network Traffic Analysis with Malcolm.pdf index cd864d9dd..97ccc114d 100644 Binary files a/docs/slides/Network Traffic Analysis with Malcolm.pdf and b/docs/slides/Network Traffic Analysis with Malcolm.pdf differ diff --git a/docs/ubuntu-install-example.md b/docs/ubuntu-install-example.md index 162b000bd..91be88741 100644 --- a/docs/ubuntu-install-example.md +++ b/docs/ubuntu-install-example.md @@ -148,23 +148,20 @@ Perform hardware vendor OUI lookups for MAC addresses? (Y/n): y Perform string randomness scoring on some fields? (Y/n): y -Expose OpenSearch port to external hosts? (y/N): n - -Expose Logstash port to external hosts? (y/N): n - -Expose Filebeat TCP port to external hosts? (y/N): y - -Use default field values for Filebeat TCP listener? (Y/n): y - -Expose SFTP server (for PCAP upload) to external hosts? (y/N): n +1: no +2: yes +3: customize +Should Malcolm accept logs and metrics from a Hedgehog Linux sensor or other forwarder? (no): 1 Enable file extraction with Zeek? (y/N): y + 1: none 2: known 3: mapped 4: all 5: interesting Select file extraction behavior (none): 5 + 1: quarantined 2: all 3: none @@ -256,25 +253,25 @@ Pulling zeek ... done user@host:~/Malcolm$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE -ghcr.io/idaholab/malcolm/api 23.07.1 xxxxxxxxxxxx 3 days ago 158MB -ghcr.io/idaholab/malcolm/arkime 23.07.1 xxxxxxxxxxxx 3 days ago 816MB -ghcr.io/idaholab/malcolm/dashboards 23.07.1 xxxxxxxxxxxx 3 days ago 1.02GB -ghcr.io/idaholab/malcolm/dashboards-helper 23.07.1 xxxxxxxxxxxx 3 days ago 184MB -ghcr.io/idaholab/malcolm/file-monitor 23.07.1 xxxxxxxxxxxx 3 days ago 588MB -ghcr.io/idaholab/malcolm/file-upload 23.07.1 xxxxxxxxxxxx 3 days ago 259MB -ghcr.io/idaholab/malcolm/filebeat-oss 23.07.1 xxxxxxxxxxxx 3 days ago 624MB -ghcr.io/idaholab/malcolm/freq 23.07.1 xxxxxxxxxxxx 3 days ago 132MB -ghcr.io/idaholab/malcolm/htadmin 23.07.1 xxxxxxxxxxxx 3 days ago 242MB -ghcr.io/idaholab/malcolm/logstash-oss 23.07.1 xxxxxxxxxxxx 3 days ago 1.35GB -ghcr.io/idaholab/malcolm/netbox 23.07.1 xxxxxxxxxxxx 3 days ago 1.01GB -ghcr.io/idaholab/malcolm/nginx-proxy 23.07.1 xxxxxxxxxxxx 3 days ago 121MB -ghcr.io/idaholab/malcolm/opensearch 23.07.1 xxxxxxxxxxxx 3 days ago 1.17GB -ghcr.io/idaholab/malcolm/pcap-capture 23.07.1 xxxxxxxxxxxx 3 days ago 121MB -ghcr.io/idaholab/malcolm/pcap-monitor 23.07.1 xxxxxxxxxxxx 3 days ago 213MB -ghcr.io/idaholab/malcolm/postgresql 23.07.1 xxxxxxxxxxxx 3 days ago 268MB -ghcr.io/idaholab/malcolm/redis 23.07.1 xxxxxxxxxxxx 3 days ago 34.2MB -ghcr.io/idaholab/malcolm/suricata 23.07.1 xxxxxxxxxxxx 3 days ago 278MB -ghcr.io/idaholab/malcolm/zeek 23.07.1 xxxxxxxxxxxx 3 days ago 1GB +ghcr.io/idaholab/malcolm/api 23.08.0 xxxxxxxxxxxx 3 days ago 158MB +ghcr.io/idaholab/malcolm/arkime 23.08.0 xxxxxxxxxxxx 3 days ago 816MB +ghcr.io/idaholab/malcolm/dashboards 23.08.0 xxxxxxxxxxxx 3 days ago 1.02GB +ghcr.io/idaholab/malcolm/dashboards-helper 23.08.0 xxxxxxxxxxxx 3 days ago 184MB +ghcr.io/idaholab/malcolm/file-monitor 23.08.0 xxxxxxxxxxxx 3 days ago 588MB +ghcr.io/idaholab/malcolm/file-upload 23.08.0 xxxxxxxxxxxx 3 days ago 259MB +ghcr.io/idaholab/malcolm/filebeat-oss 23.08.0 xxxxxxxxxxxx 3 days ago 624MB +ghcr.io/idaholab/malcolm/freq 23.08.0 xxxxxxxxxxxx 3 days ago 132MB +ghcr.io/idaholab/malcolm/htadmin 23.08.0 xxxxxxxxxxxx 3 days ago 242MB +ghcr.io/idaholab/malcolm/logstash-oss 23.08.0 xxxxxxxxxxxx 3 days ago 1.35GB +ghcr.io/idaholab/malcolm/netbox 23.08.0 xxxxxxxxxxxx 3 days ago 1.01GB +ghcr.io/idaholab/malcolm/nginx-proxy 23.08.0 xxxxxxxxxxxx 3 days ago 121MB +ghcr.io/idaholab/malcolm/opensearch 23.08.0 xxxxxxxxxxxx 3 days ago 1.17GB +ghcr.io/idaholab/malcolm/pcap-capture 23.08.0 xxxxxxxxxxxx 3 days ago 121MB +ghcr.io/idaholab/malcolm/pcap-monitor 23.08.0 xxxxxxxxxxxx 3 days ago 213MB +ghcr.io/idaholab/malcolm/postgresql 23.08.0 xxxxxxxxxxxx 3 days ago 268MB +ghcr.io/idaholab/malcolm/redis 23.08.0 xxxxxxxxxxxx 3 days ago 34.2MB +ghcr.io/idaholab/malcolm/suricata 23.08.0 xxxxxxxxxxxx 3 days ago 278MB +ghcr.io/idaholab/malcolm/zeek 23.08.0 xxxxxxxxxxxx 3 days ago 1GB ``` Finally, start Malcolm. When Malcolm starts it will stream informational and debug messages to the console until it has completed initializing. diff --git a/docs/upload.md b/docs/upload.md index d9fc007eb..4c3b8bb6f 100644 --- a/docs/upload.md +++ b/docs/upload.md @@ -1,12 +1,12 @@ -# Capture file and log archive upload +# Network traffic artifact upload -* [Capture file and log archive upload](#Upload) +* [Network traffic artifact upload](#Upload) - [Tagging](#Tagging) - [Processing uploaded PCAPs with Zeek and Suricata](#UploadPCAPProcessors) Malcolm serves a web browser-based upload form for uploading PCAP files and Zeek logs at **https://localhost/upload/** if connecting locally. -![Capture File and Log Archive Upload](./images/screenshots/malcolm_upload.png) +![Network traffic artifact upload](./images/screenshots/malcolm_upload.png) Additionally, there is a writable `files` directory on an SFTP server served on port 8022 (e.g., `sftp://USERNAME@localhost:8022/files/` if connecting locally). @@ -24,7 +24,3 @@ Files uploaded via these methods are monitored and moved automatically to other In addition to being processed for uploading, Malcolm events will be tagged according to the components of the filenames of the PCAP files or Zeek log archives files from which the events were parsed. For example, records created from a PCAP file named `ACME_Scada_VLAN10.pcap` would be tagged with `ACME`, `Scada`, and `VLAN10`. Tags are extracted from filenames by splitting on the characters `,` (comma), `-` (dash), and `_` (underscore). These tags are viewable and searchable (via the `tags` field) in Arkime and OpenSearch Dashboards. This behavior can be changed by modifying the `AUTO_TAG` [environment variable in `upload-common.env`](malcolm-config.md#MalcolmConfigEnvVars). Tags may also be specified manually with the [browser-based upload form](#Upload). - -## Processing uploaded PCAPs with Zeek and Suricata - -The **Analyze with Zeek** and **Analyze with Suricata** checkboxes may be used when uploading PCAP files to cause them to be analyzed by Zeek and Suricata, respectively. This is functionally equivalent to the `ZEEK_AUTO_ANALYZE_PCAP_FILES` and `SURICATA_AUTO_ANALYZE_PCAP_FILES` environment variables [described above](malcolm-config.md#MalcolmConfigEnvVars), only on a per-upload basis. Zeek can also automatically carve out files from file transfers; see [Automatic file extraction and scanning](file-scanning.md#ZeekFileExtraction) for more details. diff --git a/file-upload/docker-entrypoint.sh b/file-upload/docker-entrypoint.sh index 95685445f..85dacd97f 100755 --- a/file-upload/docker-entrypoint.sh +++ b/file-upload/docker-entrypoint.sh @@ -2,18 +2,14 @@ # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. - -if [[ -z $SITE_NAME || -z $MALCOLM_USERNAME || -z $MALCOLM_PASSWORD ]] -then - echo "Please set the site name, username and (openssl-encrypted then base64-encoded) password by adding the following arguments to docker run/create:" - echo " -e SITE_NAME='...'" +if [[ -z $MALCOLM_USERNAME || -z $MALCOLM_PASSWORD ]]; then + echo "Please set the SSH username and (openssl-encrypted then base64-encoded) password by adding the following arguments to docker run/create:" echo " -e MALCOLM_USERNAME='...'" echo " -e MALCOLM_PASSWORD='...'" exit 1 fi -if ! getent passwd "$MALCOLM_USERNAME" >/dev/null -then +if ! getent passwd "$MALCOLM_USERNAME" >/dev/null; then # Make sure every container gets its own SSH host keys the first time around rm -f /etc/ssh/ssh_host_* dpkg-reconfigure openssh-server @@ -21,10 +17,11 @@ then useradd -g $PGROUP -d /var/www/upload/server/php/chroot -s /sbin/nologin "$MALCOLM_USERNAME" usermod --password "$(echo -n "$MALCOLM_PASSWORD" | base64 -d)" "$MALCOLM_USERNAME" chown :$PGROUP /var/www/upload/server/php/chroot/files + chown :$PGROUP /var/www/upload/server/php/chroot/files/{tmp,variants} 2>/dev/null || true + chown :$PGROUP /var/www/upload/server/php/chroot/files/tmp/spool 2>/dev/null || true chmod 775 /var/www/upload/server/php/chroot/files - - # This will break if $SITE_NAME contains a slash... - sed -i 's/%SITE_NAME%/'"$SITE_NAME"'/g' /var/www/upload/index.html + chmod 775 /var/www/upload/server/php/chroot/files/{tmp,variants} 2>/dev/null || true + chmod 775 /var/www/upload/server/php/chroot/files/tmp/spool 2>/dev/null || true else echo "skipping one-time setup tasks" 1>&2 diff --git a/file-upload/jquery-file-upload/bootstrap.min.css b/file-upload/jquery-file-upload/bootstrap.min.css deleted file mode 100644 index 523da07bf..000000000 --- a/file-upload/jquery-file-upload/bootstrap.min.css +++ /dev/null @@ -1,12 +0,0 @@ -/*! - * Bootswatch v4.4.1 - * Homepage: https://bootswatch.com - * Copyright 2012-2020 Thomas Park - * Licensed under MIT - * Based on Bootstrap -*//*! - * Bootstrap v4.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 The Bootstrap Authors - * Copyright 2011-2019 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */:root{--blue: #007bff;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #ee5f5b;--orange: #fd7e14;--yellow: #f89406;--green: #62c462;--teal: #20c997;--cyan: #5bc0de;--white: #fff;--gray: #7A8288;--gray-dark: #3A3F44;--primary: #3A3F44;--secondary: #7A8288;--success: #62c462;--info: #5bc0de;--warning: #f89406;--danger: #ee5f5b;--light: #e9ecef;--dark: #272B30;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-size:0.9375rem;font-weight:400;line-height:1.5;color:#aaa;text-align:left;background-color:#272B30}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#fff;text-decoration:none;background-color:transparent}a:hover{color:#d9d9d9;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:0.75rem;padding-bottom:0.75rem;color:#7A8288;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:0.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{padding:0;border-style:none}input[type="radio"],input[type="checkbox"]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:none}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:0.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:2.34375rem}h2,.h2{font-size:1.875rem}h3,.h3{font-size:1.640625rem}h4,.h4{font-size:1.40625rem}h5,.h5{font-size:1.171875rem}h6,.h6{font-size:0.9375rem}.lead{font-size:1.171875rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,0.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:0.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:0.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.171875rem}.blockquote-footer{display:block;font-size:80%;color:#7A8288}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:0.25rem;background-color:#272B30;border:1px solid #dee2e6;border-radius:0.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:0.5rem;line-height:1}.figure-caption{font-size:90%;color:#7A8288}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:0.2rem 0.4rem;font-size:87.5%;color:#fff;background-color:#272B30;border-radius:0.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:inherit}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid,.container-sm,.container-md,.container-lg,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container,.container-sm{max-width:540px}}@media (min-width: 768px){.container,.container-sm,.container-md{max-width:720px}}@media (min-width: 992px){.container,.container-sm,.container-md,.container-lg{max-width:960px}}@media (min-width: 1200px){.container,.container-sm,.container-md,.container-lg,.container-xl{max-width:1140px}}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width: 576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width: 768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width: 992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width: 1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.table{width:100%;margin-bottom:1rem;color:#fff}.table th,.table td{padding:0.75rem;vertical-align:top;border-top:1px solid rgba(0,0,0,0.6)}.table thead th{vertical-align:bottom;border-bottom:2px solid rgba(0,0,0,0.6)}.table tbody+tbody{border-top:2px solid rgba(0,0,0,0.6)}.table-sm th,.table-sm td{padding:0.3rem}.table-bordered{border:1px solid rgba(0,0,0,0.6)}.table-bordered th,.table-bordered td{border:1px solid rgba(0,0,0,0.6)}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,0.05)}.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,0.075)}.table-primary,.table-primary>th,.table-primary>td{background-color:#c8c9cb}.table-primary th,.table-primary td,.table-primary thead th,.table-primary tbody+tbody{border-color:#999b9e}.table-hover .table-primary:hover{background-color:#bbbcbf}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#bbbcbf}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#dadcde}.table-secondary th,.table-secondary td,.table-secondary thead th,.table-secondary tbody+tbody{border-color:#babec1}.table-hover .table-secondary:hover{background-color:#cdcfd2}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#cdcfd2}.table-success,.table-success>th,.table-success>td{background-color:#d3eed3}.table-success th,.table-success td,.table-success thead th,.table-success tbody+tbody{border-color:#ade0ad}.table-hover .table-success:hover{background-color:#c1e7c1}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#c1e7c1}.table-info,.table-info>th,.table-info>td{background-color:#d1edf6}.table-info th,.table-info td,.table-info thead th,.table-info tbody+tbody{border-color:#aadeee}.table-hover .table-info:hover{background-color:#bce5f2}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#bce5f2}.table-warning,.table-warning>th,.table-warning>td{background-color:#fde1b9}.table-warning th,.table-warning td,.table-warning thead th,.table-warning tbody+tbody{border-color:#fbc77e}.table-hover .table-warning:hover{background-color:#fcd6a0}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#fcd6a0}.table-danger,.table-danger>th,.table-danger>td{background-color:#fad2d1}.table-danger th,.table-danger td,.table-danger thead th,.table-danger tbody+tbody{border-color:#f6acaa}.table-hover .table-danger:hover{background-color:#f8bcba}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f8bcba}.table-light,.table-light>th,.table-light>td{background-color:#f9fafb}.table-light th,.table-light td,.table-light thead th,.table-light tbody+tbody{border-color:#f4f5f7}.table-hover .table-light:hover{background-color:#eaedf1}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#eaedf1}.table-dark,.table-dark>th,.table-dark>td{background-color:#c3c4c5}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#8f9193}.table-hover .table-dark:hover{background-color:#b6b7b8}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b6b7b8}.table-active,.table-active>th,.table-active>td{background-color:rgba(255,255,255,0.075)}.table-hover .table-active:hover{background-color:rgba(242,242,242,0.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(242,242,242,0.075)}.table .thead-dark th{color:#fff;background-color:#3A3F44;border-color:rgba(0,0,0,0.6)}.table .thead-light th{color:#52575C;background-color:#e9ecef;border-color:rgba(0,0,0,0.6)}.table-dark{color:#fff;background-color:#3A3F44}.table-dark th,.table-dark td,.table-dark thead th{border-color:rgba(0,0,0,0.6)}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,0.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,0.075)}@media (max-width: 575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width: 767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width: 991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width: 1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + 1.5rem + 2px);padding:0.75rem 1rem;font-size:0.9375rem;font-weight:400;line-height:1.5;color:#52575C;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:0.25rem;-webkit-transition:border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{-webkit-transition:none;transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #52575C}.form-control:focus{color:#52575C;background-color:#fff;border-color:#757f89;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25)}.form-control::-webkit-input-placeholder{color:#7A8288;opacity:1}.form-control::-ms-input-placeholder{color:#7A8288;opacity:1}.form-control::placeholder{color:#7A8288;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#ccc;opacity:1}select.form-control:focus::-ms-value{color:#52575C;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(0.75rem + 1px);padding-bottom:calc(0.75rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.171875rem;line-height:1.5}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.8203125rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:0.75rem 0;margin-bottom:0;font-size:0.9375rem;line-height:1.5;color:#aaa;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + 0.5rem + 2px);padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5;border-radius:0.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:0.5rem 1rem;font-size:1.171875rem;line-height:1.5;border-radius:0.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:0.25rem}.form-row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*="col-"]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:0.3rem;margin-left:-1.25rem}.form-check-input[disabled] ~ .form-check-label,.form-check-input:disabled ~ .form-check-label{color:#7A8288}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:0.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:0.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:0.25rem;font-size:80%;color:#62c462}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:0.25rem 0.5rem;margin-top:.1rem;font-size:0.8203125rem;line-height:1.5;color:#fff;background-color:rgba(98,196,98,0.9);border-radius:0.25rem}.was-validated :valid ~ .valid-feedback,.was-validated :valid ~ .valid-tooltip,.is-valid ~ .valid-feedback,.is-valid ~ .valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#62c462;padding-right:calc(1.5em + 1.5rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2362c462' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.375rem) center;background-size:calc(0.75em + 0.75rem) calc(0.75em + 0.75rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#62c462;-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 1.5rem);background-position:top calc(0.375em + 0.375rem) right calc(0.375em + 0.375rem)}.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#62c462;padding-right:calc(0.75em + 3.125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%233A3F44' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 1rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2362c462' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 2rem/calc(0.75em + 0.75rem) calc(0.75em + 0.75rem)}.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#62c462;-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25)}.was-validated .form-check-input:valid ~ .form-check-label,.form-check-input.is-valid ~ .form-check-label{color:#62c462}.was-validated .form-check-input:valid ~ .valid-feedback,.was-validated .form-check-input:valid ~ .valid-tooltip,.form-check-input.is-valid ~ .valid-feedback,.form-check-input.is-valid ~ .valid-tooltip{display:block}.was-validated .custom-control-input:valid ~ .custom-control-label,.custom-control-input.is-valid ~ .custom-control-label{color:#62c462}.was-validated .custom-control-input:valid ~ .custom-control-label::before,.custom-control-input.is-valid ~ .custom-control-label::before{border-color:#62c462}.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before,.custom-control-input.is-valid:checked ~ .custom-control-label::before{border-color:#87d287;background-color:#87d287}.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before,.custom-control-input.is-valid:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25)}.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before,.custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before{border-color:#62c462}.was-validated .custom-file-input:valid ~ .custom-file-label,.custom-file-input.is-valid ~ .custom-file-label{border-color:#62c462}.was-validated .custom-file-input:valid:focus ~ .custom-file-label,.custom-file-input.is-valid:focus ~ .custom-file-label{border-color:#62c462;-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.25)}.invalid-feedback{display:none;width:100%;margin-top:0.25rem;font-size:80%;color:#ee5f5b}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:0.25rem 0.5rem;margin-top:.1rem;font-size:0.8203125rem;line-height:1.5;color:#fff;background-color:rgba(238,95,91,0.9);border-radius:0.25rem}.was-validated :invalid ~ .invalid-feedback,.was-validated :invalid ~ .invalid-tooltip,.is-invalid ~ .invalid-feedback,.is-invalid ~ .invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#ee5f5b;padding-right:calc(1.5em + 1.5rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23ee5f5b' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ee5f5b' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.375rem) center;background-size:calc(0.75em + 0.75rem) calc(0.75em + 0.75rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#ee5f5b;-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 1.5rem);background-position:top calc(0.375em + 0.375rem) right calc(0.375em + 0.375rem)}.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#ee5f5b;padding-right:calc(0.75em + 3.125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%233A3F44' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 1rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23ee5f5b' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ee5f5b' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 2rem/calc(0.75em + 0.75rem) calc(0.75em + 0.75rem)}.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#ee5f5b;-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25)}.was-validated .form-check-input:invalid ~ .form-check-label,.form-check-input.is-invalid ~ .form-check-label{color:#ee5f5b}.was-validated .form-check-input:invalid ~ .invalid-feedback,.was-validated .form-check-input:invalid ~ .invalid-tooltip,.form-check-input.is-invalid ~ .invalid-feedback,.form-check-input.is-invalid ~ .invalid-tooltip{display:block}.was-validated .custom-control-input:invalid ~ .custom-control-label,.custom-control-input.is-invalid ~ .custom-control-label{color:#ee5f5b}.was-validated .custom-control-input:invalid ~ .custom-control-label::before,.custom-control-input.is-invalid ~ .custom-control-label::before{border-color:#ee5f5b}.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before,.custom-control-input.is-invalid:checked ~ .custom-control-label::before{border-color:#f38c89;background-color:#f38c89}.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before,.custom-control-input.is-invalid:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25)}.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before,.custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before{border-color:#ee5f5b}.was-validated .custom-file-input:invalid ~ .custom-file-label,.custom-file-input.is-invalid ~ .custom-file-label{border-color:#ee5f5b}.was-validated .custom-file-input:invalid:focus ~ .custom-file-label,.custom-file-input.is-invalid:focus ~ .custom-file-label{border-color:#ee5f5b;-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.25)}.form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width: 576px){.form-inline label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:0.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#aaa;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:0.75rem 1rem;font-size:0.9375rem;line-height:1.5;border-radius:0.25rem;-webkit-transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{-webkit-transition:none;transition:none}}.btn:hover{color:#aaa;text-decoration:none}.btn:focus,.btn.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25)}.btn.disabled,.btn:disabled{opacity:0.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#3A3F44;border-color:#3A3F44}.btn-primary:hover{color:#fff;background-color:#282c2f;border-color:#232628}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#282c2f;border-color:#232628;-webkit-box-shadow:0 0 0 0.2rem rgba(88,92,96,0.5);box-shadow:0 0 0 0.2rem rgba(88,92,96,0.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#3A3F44;border-color:#3A3F44}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#232628;border-color:#1d1f22}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(88,92,96,0.5);box-shadow:0 0 0 0.2rem rgba(88,92,96,0.5)}.btn-secondary{color:#fff;background-color:#7A8288;border-color:#7A8288}.btn-secondary:hover{color:#fff;background-color:#686f74;border-color:#62686d}.btn-secondary:focus,.btn-secondary.focus{color:#fff;background-color:#686f74;border-color:#62686d;-webkit-box-shadow:0 0 0 0.2rem rgba(142,149,154,0.5);box-shadow:0 0 0 0.2rem rgba(142,149,154,0.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#7A8288;border-color:#7A8288}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#62686d;border-color:#5c6267}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(142,149,154,0.5);box-shadow:0 0 0 0.2rem rgba(142,149,154,0.5)}.btn-success{color:#fff;background-color:#62c462;border-color:#62c462}.btn-success:hover{color:#fff;background-color:#46ba46;border-color:#42b142}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#46ba46;border-color:#42b142;-webkit-box-shadow:0 0 0 0.2rem rgba(122,205,122,0.5);box-shadow:0 0 0 0.2rem rgba(122,205,122,0.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#62c462;border-color:#62c462}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#42b142;border-color:#3fa73f}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(122,205,122,0.5);box-shadow:0 0 0 0.2rem rgba(122,205,122,0.5)}.btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-info:hover{color:#fff;background-color:#3bb4d8;border-color:#31b0d5}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#3bb4d8;border-color:#31b0d5;-webkit-box-shadow:0 0 0 0.2rem rgba(116,201,227,0.5);box-shadow:0 0 0 0.2rem rgba(116,201,227,0.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#2aaacf}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(116,201,227,0.5);box-shadow:0 0 0 0.2rem rgba(116,201,227,0.5)}.btn-warning{color:#fff;background-color:#f89406;border-color:#f89406}.btn-warning:hover{color:#fff;background-color:#d37e05;border-color:#c67605}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#d37e05;border-color:#c67605;-webkit-box-shadow:0 0 0 0.2rem rgba(249,164,43,0.5);box-shadow:0 0 0 0.2rem rgba(249,164,43,0.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#f89406;border-color:#f89406}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#c67605;border-color:#ba6f04}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(249,164,43,0.5);box-shadow:0 0 0 0.2rem rgba(249,164,43,0.5)}.btn-danger{color:#fff;background-color:#ee5f5b;border-color:#ee5f5b}.btn-danger:hover{color:#fff;background-color:#ea3d38;border-color:#e9322d}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#ea3d38;border-color:#e9322d;-webkit-box-shadow:0 0 0 0.2rem rgba(241,119,116,0.5);box-shadow:0 0 0 0.2rem rgba(241,119,116,0.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#ee5f5b;border-color:#ee5f5b}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#e9322d;border-color:#e82721}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(241,119,116,0.5);box-shadow:0 0 0 0.2rem rgba(241,119,116,0.5)}.btn-light{color:#272B30;background-color:#e9ecef;border-color:#e9ecef}.btn-light:hover{color:#272B30;background-color:#d3d9df;border-color:#cbd3da}.btn-light:focus,.btn-light.focus{color:#272B30;background-color:#d3d9df;border-color:#cbd3da;-webkit-box-shadow:0 0 0 0.2rem rgba(204,207,210,0.5);box-shadow:0 0 0 0.2rem rgba(204,207,210,0.5)}.btn-light.disabled,.btn-light:disabled{color:#272B30;background-color:#e9ecef;border-color:#e9ecef}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#272B30;background-color:#cbd3da;border-color:#c4ccd4}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(204,207,210,0.5);box-shadow:0 0 0 0.2rem rgba(204,207,210,0.5)}.btn-dark{color:#fff;background-color:#272B30;border-color:#272B30}.btn-dark:hover{color:#fff;background-color:#16181b;border-color:#101214}.btn-dark:focus,.btn-dark.focus{color:#fff;background-color:#16181b;border-color:#101214;-webkit-box-shadow:0 0 0 0.2rem rgba(71,75,79,0.5);box-shadow:0 0 0 0.2rem rgba(71,75,79,0.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#272B30;border-color:#272B30}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#101214;border-color:#0a0b0d}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(71,75,79,0.5);box-shadow:0 0 0 0.2rem rgba(71,75,79,0.5)}.btn-outline-primary{color:#3A3F44;border-color:#3A3F44}.btn-outline-primary:hover{color:#fff;background-color:#3A3F44;border-color:#3A3F44}.btn-outline-primary:focus,.btn-outline-primary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.5);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#3A3F44;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#3A3F44;border-color:#3A3F44}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.5);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.5)}.btn-outline-secondary{color:#7A8288;border-color:#7A8288}.btn-outline-secondary:hover{color:#fff;background-color:#7A8288;border-color:#7A8288}.btn-outline-secondary:focus,.btn-outline-secondary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(122,130,136,0.5);box-shadow:0 0 0 0.2rem rgba(122,130,136,0.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#7A8288;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#7A8288;border-color:#7A8288}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(122,130,136,0.5);box-shadow:0 0 0 0.2rem rgba(122,130,136,0.5)}.btn-outline-success{color:#62c462;border-color:#62c462}.btn-outline-success:hover{color:#fff;background-color:#62c462;border-color:#62c462}.btn-outline-success:focus,.btn-outline-success.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.5);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#62c462;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#62c462;border-color:#62c462}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.5);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.5)}.btn-outline-info{color:#5bc0de;border-color:#5bc0de}.btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info:focus,.btn-outline-info.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(91,192,222,0.5);box-shadow:0 0 0 0.2rem rgba(91,192,222,0.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#5bc0de;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(91,192,222,0.5);box-shadow:0 0 0 0.2rem rgba(91,192,222,0.5)}.btn-outline-warning{color:#f89406;border-color:#f89406}.btn-outline-warning:hover{color:#fff;background-color:#f89406;border-color:#f89406}.btn-outline-warning:focus,.btn-outline-warning.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(248,148,6,0.5);box-shadow:0 0 0 0.2rem rgba(248,148,6,0.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#f89406;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#f89406;border-color:#f89406}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(248,148,6,0.5);box-shadow:0 0 0 0.2rem rgba(248,148,6,0.5)}.btn-outline-danger{color:#ee5f5b;border-color:#ee5f5b}.btn-outline-danger:hover{color:#fff;background-color:#ee5f5b;border-color:#ee5f5b}.btn-outline-danger:focus,.btn-outline-danger.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.5);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#ee5f5b;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#ee5f5b;border-color:#ee5f5b}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.5);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.5)}.btn-outline-light{color:#e9ecef;border-color:#e9ecef}.btn-outline-light:hover{color:#272B30;background-color:#e9ecef;border-color:#e9ecef}.btn-outline-light:focus,.btn-outline-light.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(233,236,239,0.5);box-shadow:0 0 0 0.2rem rgba(233,236,239,0.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#e9ecef;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle{color:#272B30;background-color:#e9ecef;border-color:#e9ecef}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(233,236,239,0.5);box-shadow:0 0 0 0.2rem rgba(233,236,239,0.5)}.btn-outline-dark{color:#272B30;border-color:#272B30}.btn-outline-dark:hover{color:#fff;background-color:#272B30;border-color:#272B30}.btn-outline-dark:focus,.btn-outline-dark.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(39,43,48,0.5);box-shadow:0 0 0 0.2rem rgba(39,43,48,0.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#272B30;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#272B30;border-color:#272B30}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(39,43,48,0.5);box-shadow:0 0 0 0.2rem rgba(39,43,48,0.5)}.btn-link{font-weight:400;color:#fff;text-decoration:none}.btn-link:hover{color:#d9d9d9;text-decoration:underline}.btn-link:focus,.btn-link.focus{text-decoration:underline;-webkit-box-shadow:none;box-shadow:none}.btn-link:disabled,.btn-link.disabled{color:#7A8288;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:0.5rem 1rem;font-size:1.171875rem;line-height:1.5;border-radius:0.3rem}.btn-sm,.btn-group-sm>.btn{padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5;border-radius:0.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:0.5rem}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{-webkit-transition:opacity 0.15s linear;transition:opacity 0.15s linear}@media (prefers-reduced-motion: reduce){.fade{-webkit-transition:none;transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;transition:height 0.35s ease}@media (prefers-reduced-motion: reduce){.collapsing{-webkit-transition:none;transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid;border-right:0.3em solid transparent;border-bottom:0;border-left:0.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:0.5rem 0;margin:0.125rem 0 0;font-size:0.9375rem;color:#aaa;text-align:left;list-style:none;background-color:#3A3F44;background-clip:padding-box;border:1px solid rgba(0,0,0,0.6);border-radius:0.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width: 576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width: 768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width: 992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width: 1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:0.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0;border-right:0.3em solid transparent;border-bottom:0.3em solid;border-left:0.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:0.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid transparent;border-right:0;border-bottom:0.3em solid transparent;border-left:0.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:0.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid transparent;border-right:0.3em solid;border-bottom:0.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^="top"],.dropdown-menu[x-placement^="right"],.dropdown-menu[x-placement^="bottom"],.dropdown-menu[x-placement^="left"]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:0.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,0.15)}.dropdown-item{display:block;width:100%;padding:0.25rem 1.5rem;clear:both;font-weight:400;color:#aaa;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#fff;text-decoration:none;background-color:#272B30}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#3A3F44}.dropdown-item.disabled,.dropdown-item:disabled{color:#7A8288;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:0.5rem 1.5rem;margin-bottom:0;font-size:0.8203125rem;color:#7A8288;white-space:nowrap}.dropdown-item-text{display:block;padding:0.25rem 1.5rem;color:#aaa}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:0.75rem;padding-left:0.75rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:0.375rem;padding-left:0.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:0.75rem;padding-left:0.75rem}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type="radio"],.btn-group-toggle>.btn input[type="checkbox"],.btn-group-toggle>.btn-group>.btn input[type="radio"],.btn-group-toggle>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-control-plaintext,.input-group>.custom-select,.input-group>.custom-file{position:relative;-webkit-box-flex:1;-ms-flex:1 1 0%;flex:1 1 0%;min-width:0;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.form-control-plaintext+.form-control,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus ~ .custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:last-child),.input-group>.custom-select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-prepend,.input-group-append{display:-webkit-box;display:-ms-flexbox;display:flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn:focus,.input-group-append .btn:focus{z-index:3}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0.75rem 1rem;margin-bottom:0;font-size:0.9375rem;font-weight:400;line-height:1.5;color:#52575C;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:0.25rem}.input-group-text input[type="radio"],.input-group-text input[type="checkbox"]{margin-top:0}.input-group-lg>.form-control:not(textarea),.input-group-lg>.custom-select{height:calc(1.5em + 1rem + 2px)}.input-group-lg>.form-control,.input-group-lg>.custom-select,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{padding:0.5rem 1rem;font-size:1.171875rem;line-height:1.5;border-radius:0.3rem}.input-group-sm>.form-control:not(textarea),.input-group-sm>.custom-select{height:calc(1.5em + 0.5rem + 2px)}.input-group-sm>.form-control,.input-group-sm>.custom-select,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5;border-radius:0.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:2rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.40625rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.203125rem;opacity:0}.custom-control-input:checked ~ .custom-control-label::before{color:#fff;border-color:#3A3F44;background-color:#3A3F44}.custom-control-input:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25)}.custom-control-input:focus:not(:checked) ~ .custom-control-label::before{border-color:#757f89}.custom-control-input:not(:disabled):active ~ .custom-control-label::before{color:#fff;background-color:#9098a0;border-color:#9098a0}.custom-control-input[disabled] ~ .custom-control-label,.custom-control-input:disabled ~ .custom-control-label{color:#7A8288}.custom-control-input[disabled] ~ .custom-control-label::before,.custom-control-input:disabled ~ .custom-control-label::before{background-color:#ccc}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:0.203125rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#999 solid 1px}.custom-control-label::after{position:absolute;top:0.203125rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50% / 50% 50%}.custom-checkbox .custom-control-label::before{border-radius:0.25rem}.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before{border-color:#3A3F44;background-color:#3A3F44}.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(58,63,68,0.5)}.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before{background-color:rgba(58,63,68,0.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked ~ .custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(58,63,68,0.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:0.5rem}.custom-switch .custom-control-label::after{top:calc(0.203125rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#999;border-radius:0.5rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-switch .custom-control-label::after{-webkit-transition:none;transition:none}}.custom-switch .custom-control-input:checked ~ .custom-control-label::after{background-color:#fff;-webkit-transform:translateX(0.75rem);transform:translateX(0.75rem)}.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(58,63,68,0.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + 1.5rem + 2px);padding:0.75rem 2rem 0.75rem 1rem;font-size:0.9375rem;font-weight:400;line-height:1.5;color:#52575C;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%233A3F44' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 1rem center/8px 10px;border:1px solid #ced4da;border-radius:0.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#757f89;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25)}.custom-select:focus::-ms-value{color:#52575C;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:1rem;background-image:none}.custom-select:disabled{color:#7A8288;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #52575C}.custom-select-sm{height:calc(1.5em + 0.5rem + 2px);padding-top:0.25rem;padding-bottom:0.25rem;padding-left:0.5rem;font-size:0.8203125rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:0.5rem;padding-bottom:0.5rem;padding-left:1rem;font-size:1.171875rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + 1.5rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + 1.5rem + 2px);margin:0;opacity:0}.custom-file-input:focus ~ .custom-file-label{border-color:#757f89;-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25)}.custom-file-input[disabled] ~ .custom-file-label,.custom-file-input:disabled ~ .custom-file-label{background-color:#ccc}.custom-file-input:lang(en) ~ .custom-file-label::after{content:"Browse"}.custom-file-input ~ .custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + 1.5rem + 2px);padding:0.75rem 1rem;font-weight:400;line-height:1.5;color:#52575C;background-color:#fff;border:1px solid #ced4da;border-radius:0.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + 1.5rem);padding:0.75rem 1rem;line-height:1.5;color:#52575C;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 0.25rem 0.25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #272B30,0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 1px #272B30,0 0 0 0.2rem rgba(58,63,68,0.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #272B30,0 0 0 0.2rem rgba(58,63,68,0.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #272B30,0 0 0 0.2rem rgba(58,63,68,0.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;background-color:#3A3F44;border:0;border-radius:1rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#9098a0}.custom-range::-webkit-slider-runnable-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#3A3F44;border:0;border-radius:1rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-moz-range-thumb{-webkit-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#9098a0}.custom-range::-moz-range-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:0.2rem;margin-left:0.2rem;background-color:#3A3F44;border:0;border-radius:1rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-ms-thumb{-webkit-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#9098a0}.custom-range::-ms-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:0.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#999}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#999}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#999}.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:none;transition:none}}.nav{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:0.5rem 1rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#7A8288;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid rgba(0,0,0,0.6)}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:rgba(0,0,0,0.6)}.nav-tabs .nav-link.disabled{color:#7A8288;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#fff;background-color:#272B30;border-color:rgba(0,0,0,0.6)}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:0.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#3A3F44}.nav-fill .nav-item{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:0 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-sm,.navbar .container-md,.navbar .container-lg,.navbar .container-xl{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:0.32421875rem;padding-bottom:0.32421875rem;margin-right:1rem;font-size:1.171875rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:0.5rem;padding-bottom:0.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:0.25rem 0.75rem;font-size:1.171875rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:0.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width: 575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width: 767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width: 991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width: 1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:#3A3F44}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:#3A3F44}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,0.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:#3A3F44}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,0.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:#3A3F44}.navbar-light .navbar-toggler{color:rgba(0,0,0,0.5);border-color:rgba(0,0,0,0.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,0.5)}.navbar-light .navbar-text a{color:#3A3F44}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:#3A3F44}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:#fff}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,0.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,0.5);border-color:rgba(255,255,255,0.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#32383e;background-clip:border-box;border:1px solid rgba(0,0,0,0.6);border-radius:0.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:0.25rem;border-bottom-left-radius:0.25rem}.card-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:0.75rem}.card-subtitle{margin-top:-0.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:0.75rem 1.25rem;margin-bottom:0;background-color:#515960;border-bottom:1px solid rgba(0,0,0,0.6)}.card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:0.75rem 1.25rem;background-color:#515960;border-top:1px solid rgba(0,0,0,0.6)}.card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.card-header-tabs{margin-right:-0.625rem;margin-bottom:-0.75rem;margin-left:-0.625rem;border-bottom:0}.card-header-pills{margin-right:-0.625rem;margin-left:-0.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-top,.card-img-bottom{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width: 576px){.card-deck{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width: 576px){.card-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:0.75rem}@media (min-width: 576px){.card-columns{-webkit-column-count:3;column-count:3;-webkit-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:0.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:0.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:0.5rem;color:#7A8288;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#999}.pagination{display:-webkit-box;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:0.25rem}.page-link{position:relative;display:block;padding:0.5rem 0.75rem;margin-left:-1px;line-height:1.25;color:#fff;background-color:transparent;border:1px solid rgba(0,0,0,0.6)}.page-link:hover{z-index:2;color:#fff;text-decoration:none;background-color:transparent;border-color:rgba(0,0,0,0.6)}.page-link:focus{z-index:3;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:0.25rem;border-bottom-left-radius:0.25rem}.page-item:last-child .page-link{border-top-right-radius:0.25rem;border-bottom-right-radius:0.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:transparent;border-color:rgba(0,0,0,0.6)}.page-item.disabled .page-link{color:#7A8288;pointer-events:none;cursor:auto;background-color:transparent;border-color:rgba(0,0,0,0.6)}.pagination-lg .page-link{padding:0.75rem 1.5rem;font-size:1.171875rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:0.3rem;border-bottom-left-radius:0.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:0.3rem;border-bottom-right-radius:0.3rem}.pagination-sm .page-link{padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:0.2rem;border-bottom-left-radius:0.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:0.2rem;border-bottom-right-radius:0.2rem}.badge{display:inline-block;padding:0.25em 0.4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:0.25rem;-webkit-transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.badge{-webkit-transition:none;transition:none}}a.badge:hover,a.badge:focus{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:0.6em;padding-left:0.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#3A3F44}a.badge-primary:hover,a.badge-primary:focus{color:#fff;background-color:#232628}a.badge-primary:focus,a.badge-primary.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(58,63,68,0.5);box-shadow:0 0 0 0.2rem rgba(58,63,68,0.5)}.badge-secondary{color:#fff;background-color:#7A8288}a.badge-secondary:hover,a.badge-secondary:focus{color:#fff;background-color:#62686d}a.badge-secondary:focus,a.badge-secondary.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(122,130,136,0.5);box-shadow:0 0 0 0.2rem rgba(122,130,136,0.5)}.badge-success{color:#fff;background-color:#62c462}a.badge-success:hover,a.badge-success:focus{color:#fff;background-color:#42b142}a.badge-success:focus,a.badge-success.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(98,196,98,0.5);box-shadow:0 0 0 0.2rem rgba(98,196,98,0.5)}.badge-info{color:#fff;background-color:#5bc0de}a.badge-info:hover,a.badge-info:focus{color:#fff;background-color:#31b0d5}a.badge-info:focus,a.badge-info.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(91,192,222,0.5);box-shadow:0 0 0 0.2rem rgba(91,192,222,0.5)}.badge-warning{color:#fff;background-color:#f89406}a.badge-warning:hover,a.badge-warning:focus{color:#fff;background-color:#c67605}a.badge-warning:focus,a.badge-warning.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(248,148,6,0.5);box-shadow:0 0 0 0.2rem rgba(248,148,6,0.5)}.badge-danger{color:#fff;background-color:#ee5f5b}a.badge-danger:hover,a.badge-danger:focus{color:#fff;background-color:#e9322d}a.badge-danger:focus,a.badge-danger.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(238,95,91,0.5);box-shadow:0 0 0 0.2rem rgba(238,95,91,0.5)}.badge-light{color:#272B30;background-color:#e9ecef}a.badge-light:hover,a.badge-light:focus{color:#272B30;background-color:#cbd3da}a.badge-light:focus,a.badge-light.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(233,236,239,0.5);box-shadow:0 0 0 0.2rem rgba(233,236,239,0.5)}.badge-dark{color:#fff;background-color:#272B30}a.badge-dark:hover,a.badge-dark:focus{color:#fff;background-color:#101214}a.badge-dark:focus,a.badge-dark.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(39,43,48,0.5);box-shadow:0 0 0 0.2rem rgba(39,43,48,0.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#1c1e22;border-radius:0.3rem}@media (min-width: 576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:0.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:0.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3.90625rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:0.75rem 1.25rem;color:inherit}.alert-primary{color:#1e2123;background-color:#d8d9da;border-color:#c8c9cb}.alert-primary hr{border-top-color:#bbbcbf}.alert-primary .alert-link{color:#060708}.alert-secondary{color:#3f4447;background-color:#e4e6e7;border-color:#dadcde}.alert-secondary hr{border-top-color:#cdcfd2}.alert-secondary .alert-link{color:#272a2c}.alert-success{color:#336633;background-color:#e0f3e0;border-color:#d3eed3}.alert-success hr{border-top-color:#c1e7c1}.alert-success .alert-link{color:#224422}.alert-info{color:#2f6473;background-color:#def2f8;border-color:#d1edf6}.alert-info hr{border-top-color:#bce5f2}.alert-info .alert-link{color:#20454f}.alert-warning{color:#814d03;background-color:#feeacd;border-color:#fde1b9}.alert-warning hr{border-top-color:#fcd6a0}.alert-warning .alert-link{color:#4f2f02}.alert-danger{color:#7c312f;background-color:#fcdfde;border-color:#fad2d1}.alert-danger hr{border-top-color:#f8bcba}.alert-danger .alert-link{color:#572221}.alert-light{color:#797b7c;background-color:#fbfbfc;border-color:#f9fafb}.alert-light hr{border-top-color:#eaedf1}.alert-light .alert-link{color:#606162}.alert-dark{color:#141619;background-color:#d4d5d6;border-color:#c3c4c5}.alert-dark hr{border-top-color:#b6b7b8}.alert-dark .alert-link{color:black}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:0.703125rem;background-color:#1c1e22;border-radius:0.25rem}.progress-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#7A8288;text-align:center;white-space:nowrap;background-color:#3A3F44;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}@media (prefers-reduced-motion: reduce){.progress-bar{-webkit-transition:none;transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion: reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#fff;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#fff;text-decoration:none;background-color:#3e444c}.list-group-item-action:active{color:#aaa;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:0.75rem 1.25rem;background-color:#32383e;border:1px solid rgba(0,0,0,0.6)}.list-group-item:first-child{border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.list-group-item:last-child{border-bottom-right-radius:0.25rem;border-bottom-left-radius:0.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#52575C;pointer-events:none;background-color:#32383e}.list-group-item.active{z-index:2;color:#fff;background-color:#3e444c;border-color:rgba(0,0,0,0.6)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal .list-group-item.active{margin-top:0}.list-group-horizontal .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width: 576px){.list-group-horizontal-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm .list-group-item.active{margin-top:0}.list-group-horizontal-sm .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 768px){.list-group-horizontal-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-md .list-group-item.active{margin-top:0}.list-group-horizontal-md .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 992px){.list-group-horizontal-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg .list-group-item.active{margin-top:0}.list-group-horizontal-lg .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1200px){.list-group-horizontal-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl .list-group-item.active{margin-top:0}.list-group-horizontal-xl .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush .list-group-item{border-right-width:0;border-left-width:0;border-radius:0}.list-group-flush .list-group-item:first-child{border-top-width:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#1e2123;background-color:#c8c9cb}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#1e2123;background-color:#bbbcbf}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#1e2123;border-color:#1e2123}.list-group-item-secondary{color:#3f4447;background-color:#dadcde}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#3f4447;background-color:#cdcfd2}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#3f4447;border-color:#3f4447}.list-group-item-success{color:#336633;background-color:#d3eed3}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#336633;background-color:#c1e7c1}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#336633;border-color:#336633}.list-group-item-info{color:#2f6473;background-color:#d1edf6}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#2f6473;background-color:#bce5f2}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#2f6473;border-color:#2f6473}.list-group-item-warning{color:#814d03;background-color:#fde1b9}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#814d03;background-color:#fcd6a0}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#814d03;border-color:#814d03}.list-group-item-danger{color:#7c312f;background-color:#fad2d1}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#7c312f;background-color:#f8bcba}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#7c312f;border-color:#7c312f}.list-group-item-light{color:#797b7c;background-color:#f9fafb}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#797b7c;background-color:#eaedf1}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#797b7c;border-color:#797b7c}.list-group-item-dark{color:#141619;background-color:#c3c4c5}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#141619;background-color:#b6b7b8}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.close{float:right;font-size:1.40625rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:0.875rem;background-color:#32383e;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 0.25rem 0.75rem rgba(0,0,0,0.1);box-shadow:0 0.25rem 0.75rem rgba(0,0,0,0.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:0.25rem}.toast:not(:last-child){margin-bottom:0.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0.25rem 0.75rem;color:#aaa;background-color:#32383e;background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,0.2)}.toast-body{padding:0.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:0.5rem;pointer-events:none}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform 0.3s ease-out;transition:-webkit-transform 0.3s ease-out;transition:transform 0.3s ease-out;transition:transform 0.3s ease-out, -webkit-transform 0.3s ease-out;-webkit-transform:translate(0, -50px);transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{-webkit-transition:none;transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-webkit-box;display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-header,.modal-dialog-scrollable .modal-footer{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#32383e;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:0.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:0.5}.modal-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid rgba(0,0,0,0.2);border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:0.75rem;border-top:1px solid rgba(0,0,0,0.2);border-bottom-right-radius:calc(0.3rem - 1px);border-bottom-left-radius:calc(0.3rem - 1px)}.modal-footer>*{margin:0.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.8203125rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:0.9}.tooltip .arrow{position:absolute;display:block;width:0.8rem;height:0.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^="top"]{padding:0.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^="top"] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^="top"] .arrow::before{top:0;border-width:0.4rem 0.4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^="right"]{padding:0 0.4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^="right"] .arrow{left:0;width:0.4rem;height:0.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^="right"] .arrow::before{right:0;border-width:0.4rem 0.4rem 0.4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^="bottom"]{padding:0.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^="bottom"] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^="bottom"] .arrow::before{bottom:0;border-width:0 0.4rem 0.4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^="left"]{padding:0 0.4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^="left"] .arrow{right:0;width:0.4rem;height:0.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^="left"] .arrow::before{left:0;border-width:0.4rem 0 0.4rem 0.4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:0.25rem 0.5rem;color:#fff;text-align:center;background-color:#000;border-radius:0.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.8203125rem;word-wrap:break-word;background-color:#32383e;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:0.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:0.5rem;margin:0 0.3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^="top"]{margin-bottom:0.5rem}.bs-popover-top>.arrow,.bs-popover-auto[x-placement^="top"]>.arrow{bottom:calc(-0.5rem - 1px)}.bs-popover-top>.arrow::before,.bs-popover-auto[x-placement^="top"]>.arrow::before{bottom:0;border-width:0.5rem 0.5rem 0;border-top-color:rgba(0,0,0,0.25)}.bs-popover-top>.arrow::after,.bs-popover-auto[x-placement^="top"]>.arrow::after{bottom:1px;border-width:0.5rem 0.5rem 0;border-top-color:#32383e}.bs-popover-right,.bs-popover-auto[x-placement^="right"]{margin-left:0.5rem}.bs-popover-right>.arrow,.bs-popover-auto[x-placement^="right"]>.arrow{left:calc(-0.5rem - 1px);width:0.5rem;height:1rem;margin:0.3rem 0}.bs-popover-right>.arrow::before,.bs-popover-auto[x-placement^="right"]>.arrow::before{left:0;border-width:0.5rem 0.5rem 0.5rem 0;border-right-color:rgba(0,0,0,0.25)}.bs-popover-right>.arrow::after,.bs-popover-auto[x-placement^="right"]>.arrow::after{left:1px;border-width:0.5rem 0.5rem 0.5rem 0;border-right-color:#32383e}.bs-popover-bottom,.bs-popover-auto[x-placement^="bottom"]{margin-top:0.5rem}.bs-popover-bottom>.arrow,.bs-popover-auto[x-placement^="bottom"]>.arrow{top:calc(-0.5rem - 1px)}.bs-popover-bottom>.arrow::before,.bs-popover-auto[x-placement^="bottom"]>.arrow::before{top:0;border-width:0 0.5rem 0.5rem 0.5rem;border-bottom-color:rgba(0,0,0,0.25)}.bs-popover-bottom>.arrow::after,.bs-popover-auto[x-placement^="bottom"]>.arrow::after{top:1px;border-width:0 0.5rem 0.5rem 0.5rem;border-bottom-color:#32383e}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^="bottom"] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-0.5rem;content:"";border-bottom:1px solid #2c3036}.bs-popover-left,.bs-popover-auto[x-placement^="left"]{margin-right:0.5rem}.bs-popover-left>.arrow,.bs-popover-auto[x-placement^="left"]>.arrow{right:calc(-0.5rem - 1px);width:0.5rem;height:1rem;margin:0.3rem 0}.bs-popover-left>.arrow::before,.bs-popover-auto[x-placement^="left"]>.arrow::before{right:0;border-width:0.5rem 0 0.5rem 0.5rem;border-left-color:rgba(0,0,0,0.25)}.bs-popover-left>.arrow::after,.bs-popover-auto[x-placement^="left"]>.arrow::after{right:1px;border-width:0.5rem 0 0.5rem 0.5rem;border-left-color:#32383e}.popover-header{padding:0.5rem 0.75rem;margin-bottom:0;font-size:0.9375rem;background-color:#2c3036;border-bottom:1px solid #202328;border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:0.5rem 0.75rem;color:#aaa}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform 0.6s ease-in-out;transition:-webkit-transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out}@media (prefers-reduced-motion: reduce){.carousel-item{-webkit-transition:none;transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-left),.active.carousel-item-right{-webkit-transform:translateX(100%);transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-right),.active.carousel-item-left{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;-webkit-transition:opacity 0s 0.6s;transition:opacity 0s 0.6s}@media (prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{-webkit-transition:none;transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:0.5;-webkit-transition:opacity 0.15s ease;transition:opacity 0.15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{-webkit-transition:none;transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:0.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50% / 100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;-webkit-transition:opacity 0.6s ease;transition:opacity 0.6s ease}@media (prefers-reduced-motion: reduce){.carousel-indicators li{-webkit-transition:none;transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:0.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:0.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.bg-primary{background-color:#3A3F44 !important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#232628 !important}.bg-secondary{background-color:#7A8288 !important}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#62686d !important}.bg-success{background-color:#62c462 !important}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#42b142 !important}.bg-info{background-color:#5bc0de !important}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#31b0d5 !important}.bg-warning{background-color:#f89406 !important}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#c67605 !important}.bg-danger{background-color:#ee5f5b !important}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#e9322d !important}.bg-light{background-color:#e9ecef !important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#cbd3da !important}.bg-dark{background-color:#272B30 !important}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#101214 !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:transparent !important}.border{border:1px solid #dee2e6 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-right{border-right:1px solid #dee2e6 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-left{border-left:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.border-primary{border-color:#3A3F44 !important}.border-secondary{border-color:#7A8288 !important}.border-success{border-color:#62c462 !important}.border-info{border-color:#5bc0de !important}.border-warning{border-color:#f89406 !important}.border-danger{border-color:#ee5f5b !important}.border-light{border-color:#e9ecef !important}.border-dark{border-color:#272B30 !important}.border-white{border-color:#fff !important}.rounded-sm{border-radius:0.2rem !important}.rounded{border-radius:0.25rem !important}.rounded-top{border-top-left-radius:0.25rem !important;border-top-right-radius:0.25rem !important}.rounded-right{border-top-right-radius:0.25rem !important;border-bottom-right-radius:0.25rem !important}.rounded-bottom{border-bottom-right-radius:0.25rem !important;border-bottom-left-radius:0.25rem !important}.rounded-left{border-top-left-radius:0.25rem !important;border-bottom-left-radius:0.25rem !important}.rounded-lg{border-radius:0.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-0{border-radius:0 !important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-sm-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-md-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-lg-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-xl-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-print-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.8571428571%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-sm-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-sm-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-sm-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-sm-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-sm-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-sm-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-sm-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-sm-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-sm-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-sm-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-sm-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-sm-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-sm-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-sm-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-sm-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-sm-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-sm-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-sm-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-sm-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-sm-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-sm-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-sm-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-sm-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-sm-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-sm-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-sm-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-sm-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-sm-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-sm-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-sm-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-sm-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-sm-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-md-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-md-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-md-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-md-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-md-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-md-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-md-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-md-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-md-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-md-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-md-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-md-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-md-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-md-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-md-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-md-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-md-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-md-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-md-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-md-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-md-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-md-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-md-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-md-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-md-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-md-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-md-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-md-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-md-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-md-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-md-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-md-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-lg-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-lg-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-lg-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-lg-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-lg-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-lg-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-lg-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-lg-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-lg-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-lg-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-lg-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-lg-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-lg-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-lg-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-lg-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-lg-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-lg-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-lg-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-lg-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-lg-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-lg-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-lg-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-lg-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-lg-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-lg-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-lg-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-lg-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-lg-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-lg-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-lg-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-lg-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-lg-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-xl-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-xl-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-xl-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-xl-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-xl-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-xl-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-xl-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-xl-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-xl-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-xl-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-xl-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-xl-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-xl-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-xl-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-xl-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-xl-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-xl-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-xl-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-xl-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-xl-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-xl-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-xl-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-xl-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-xl-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-xl-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-xl-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-xl-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-xl-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-xl-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-xl-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-xl-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-xl-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 576px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 992px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1200px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:-webkit-sticky !important;position:sticky !important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports (position: -webkit-sticky) or (position: sticky){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{-webkit-box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important;box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important}.shadow{-webkit-box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important;box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important;box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important}.shadow-none{-webkit-box-shadow:none !important;box-shadow:none !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.min-vw-100{min-width:100vw !important}.min-vh-100{min-height:100vh !important}.vw-100{width:100vw !important}.vh-100{height:100vh !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:0.25rem !important}.mt-1,.my-1{margin-top:0.25rem !important}.mr-1,.mx-1{margin-right:0.25rem !important}.mb-1,.my-1{margin-bottom:0.25rem !important}.ml-1,.mx-1{margin-left:0.25rem !important}.m-2{margin:0.5rem !important}.mt-2,.my-2{margin-top:0.5rem !important}.mr-2,.mx-2{margin-right:0.5rem !important}.mb-2,.my-2{margin-bottom:0.5rem !important}.ml-2,.mx-2{margin-left:0.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:0.25rem !important}.pt-1,.py-1{padding-top:0.25rem !important}.pr-1,.px-1{padding-right:0.25rem !important}.pb-1,.py-1{padding-bottom:0.25rem !important}.pl-1,.px-1{padding-left:0.25rem !important}.p-2{padding:0.5rem !important}.pt-2,.py-2{padding-top:0.5rem !important}.pr-2,.px-2{padding-right:0.5rem !important}.pb-2,.py-2{padding-bottom:0.5rem !important}.pl-2,.px-2{padding-left:0.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-n1{margin:-0.25rem !important}.mt-n1,.my-n1{margin-top:-0.25rem !important}.mr-n1,.mx-n1{margin-right:-0.25rem !important}.mb-n1,.my-n1{margin-bottom:-0.25rem !important}.ml-n1,.mx-n1{margin-left:-0.25rem !important}.m-n2{margin:-0.5rem !important}.mt-n2,.my-n2{margin-top:-0.5rem !important}.mr-n2,.mx-n2{margin-right:-0.5rem !important}.mb-n2,.my-n2{margin-bottom:-0.5rem !important}.ml-n2,.mx-n2{margin-left:-0.5rem !important}.m-n3{margin:-1rem !important}.mt-n3,.my-n3{margin-top:-1rem !important}.mr-n3,.mx-n3{margin-right:-1rem !important}.mb-n3,.my-n3{margin-bottom:-1rem !important}.ml-n3,.mx-n3{margin-left:-1rem !important}.m-n4{margin:-1.5rem !important}.mt-n4,.my-n4{margin-top:-1.5rem !important}.mr-n4,.mx-n4{margin-right:-1.5rem !important}.mb-n4,.my-n4{margin-bottom:-1.5rem !important}.ml-n4,.mx-n4{margin-left:-1.5rem !important}.m-n5{margin:-3rem !important}.mt-n5,.my-n5{margin-top:-3rem !important}.mr-n5,.mx-n5{margin-right:-3rem !important}.mb-n5,.my-n5{margin-bottom:-3rem !important}.ml-n5,.mx-n5{margin-left:-3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:0.25rem !important}.mt-sm-1,.my-sm-1{margin-top:0.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:0.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:0.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:0.25rem !important}.m-sm-2{margin:0.5rem !important}.mt-sm-2,.my-sm-2{margin-top:0.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:0.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:0.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:0.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:0.25rem !important}.pt-sm-1,.py-sm-1{padding-top:0.25rem !important}.pr-sm-1,.px-sm-1{padding-right:0.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:0.25rem !important}.pl-sm-1,.px-sm-1{padding-left:0.25rem !important}.p-sm-2{padding:0.5rem !important}.pt-sm-2,.py-sm-2{padding-top:0.5rem !important}.pr-sm-2,.px-sm-2{padding-right:0.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:0.5rem !important}.pl-sm-2,.px-sm-2{padding-left:0.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-n1{margin:-0.25rem !important}.mt-sm-n1,.my-sm-n1{margin-top:-0.25rem !important}.mr-sm-n1,.mx-sm-n1{margin-right:-0.25rem !important}.mb-sm-n1,.my-sm-n1{margin-bottom:-0.25rem !important}.ml-sm-n1,.mx-sm-n1{margin-left:-0.25rem !important}.m-sm-n2{margin:-0.5rem !important}.mt-sm-n2,.my-sm-n2{margin-top:-0.5rem !important}.mr-sm-n2,.mx-sm-n2{margin-right:-0.5rem !important}.mb-sm-n2,.my-sm-n2{margin-bottom:-0.5rem !important}.ml-sm-n2,.mx-sm-n2{margin-left:-0.5rem !important}.m-sm-n3{margin:-1rem !important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem !important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem !important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem !important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem !important}.m-sm-n4{margin:-1.5rem !important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem !important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem !important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem !important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem !important}.m-sm-n5{margin:-3rem !important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem !important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem !important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem !important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:0.25rem !important}.mt-md-1,.my-md-1{margin-top:0.25rem !important}.mr-md-1,.mx-md-1{margin-right:0.25rem !important}.mb-md-1,.my-md-1{margin-bottom:0.25rem !important}.ml-md-1,.mx-md-1{margin-left:0.25rem !important}.m-md-2{margin:0.5rem !important}.mt-md-2,.my-md-2{margin-top:0.5rem !important}.mr-md-2,.mx-md-2{margin-right:0.5rem !important}.mb-md-2,.my-md-2{margin-bottom:0.5rem !important}.ml-md-2,.mx-md-2{margin-left:0.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:0.25rem !important}.pt-md-1,.py-md-1{padding-top:0.25rem !important}.pr-md-1,.px-md-1{padding-right:0.25rem !important}.pb-md-1,.py-md-1{padding-bottom:0.25rem !important}.pl-md-1,.px-md-1{padding-left:0.25rem !important}.p-md-2{padding:0.5rem !important}.pt-md-2,.py-md-2{padding-top:0.5rem !important}.pr-md-2,.px-md-2{padding-right:0.5rem !important}.pb-md-2,.py-md-2{padding-bottom:0.5rem !important}.pl-md-2,.px-md-2{padding-left:0.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-n1{margin:-0.25rem !important}.mt-md-n1,.my-md-n1{margin-top:-0.25rem !important}.mr-md-n1,.mx-md-n1{margin-right:-0.25rem !important}.mb-md-n1,.my-md-n1{margin-bottom:-0.25rem !important}.ml-md-n1,.mx-md-n1{margin-left:-0.25rem !important}.m-md-n2{margin:-0.5rem !important}.mt-md-n2,.my-md-n2{margin-top:-0.5rem !important}.mr-md-n2,.mx-md-n2{margin-right:-0.5rem !important}.mb-md-n2,.my-md-n2{margin-bottom:-0.5rem !important}.ml-md-n2,.mx-md-n2{margin-left:-0.5rem !important}.m-md-n3{margin:-1rem !important}.mt-md-n3,.my-md-n3{margin-top:-1rem !important}.mr-md-n3,.mx-md-n3{margin-right:-1rem !important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem !important}.ml-md-n3,.mx-md-n3{margin-left:-1rem !important}.m-md-n4{margin:-1.5rem !important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem !important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem !important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem !important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem !important}.m-md-n5{margin:-3rem !important}.mt-md-n5,.my-md-n5{margin-top:-3rem !important}.mr-md-n5,.mx-md-n5{margin-right:-3rem !important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem !important}.ml-md-n5,.mx-md-n5{margin-left:-3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:0.25rem !important}.mt-lg-1,.my-lg-1{margin-top:0.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:0.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:0.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:0.25rem !important}.m-lg-2{margin:0.5rem !important}.mt-lg-2,.my-lg-2{margin-top:0.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:0.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:0.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:0.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:0.25rem !important}.pt-lg-1,.py-lg-1{padding-top:0.25rem !important}.pr-lg-1,.px-lg-1{padding-right:0.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:0.25rem !important}.pl-lg-1,.px-lg-1{padding-left:0.25rem !important}.p-lg-2{padding:0.5rem !important}.pt-lg-2,.py-lg-2{padding-top:0.5rem !important}.pr-lg-2,.px-lg-2{padding-right:0.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:0.5rem !important}.pl-lg-2,.px-lg-2{padding-left:0.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-n1{margin:-0.25rem !important}.mt-lg-n1,.my-lg-n1{margin-top:-0.25rem !important}.mr-lg-n1,.mx-lg-n1{margin-right:-0.25rem !important}.mb-lg-n1,.my-lg-n1{margin-bottom:-0.25rem !important}.ml-lg-n1,.mx-lg-n1{margin-left:-0.25rem !important}.m-lg-n2{margin:-0.5rem !important}.mt-lg-n2,.my-lg-n2{margin-top:-0.5rem !important}.mr-lg-n2,.mx-lg-n2{margin-right:-0.5rem !important}.mb-lg-n2,.my-lg-n2{margin-bottom:-0.5rem !important}.ml-lg-n2,.mx-lg-n2{margin-left:-0.5rem !important}.m-lg-n3{margin:-1rem !important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem !important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem !important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem !important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem !important}.m-lg-n4{margin:-1.5rem !important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem !important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem !important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem !important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem !important}.m-lg-n5{margin:-3rem !important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem !important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem !important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem !important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:0.25rem !important}.mt-xl-1,.my-xl-1{margin-top:0.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:0.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:0.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:0.25rem !important}.m-xl-2{margin:0.5rem !important}.mt-xl-2,.my-xl-2{margin-top:0.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:0.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:0.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:0.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:0.25rem !important}.pt-xl-1,.py-xl-1{padding-top:0.25rem !important}.pr-xl-1,.px-xl-1{padding-right:0.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:0.25rem !important}.pl-xl-1,.px-xl-1{padding-left:0.25rem !important}.p-xl-2{padding:0.5rem !important}.pt-xl-2,.py-xl-2{padding-top:0.5rem !important}.pr-xl-2,.px-xl-2{padding-right:0.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:0.5rem !important}.pl-xl-2,.px-xl-2{padding-left:0.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-n1{margin:-0.25rem !important}.mt-xl-n1,.my-xl-n1{margin-top:-0.25rem !important}.mr-xl-n1,.mx-xl-n1{margin-right:-0.25rem !important}.mb-xl-n1,.my-xl-n1{margin-bottom:-0.25rem !important}.ml-xl-n1,.mx-xl-n1{margin-left:-0.25rem !important}.m-xl-n2{margin:-0.5rem !important}.mt-xl-n2,.my-xl-n2{margin-top:-0.5rem !important}.mr-xl-n2,.mx-xl-n2{margin-right:-0.5rem !important}.mb-xl-n2,.my-xl-n2{margin-bottom:-0.5rem !important}.ml-xl-n2,.mx-xl-n2{margin-left:-0.5rem !important}.m-xl-n3{margin:-1rem !important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem !important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem !important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem !important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem !important}.m-xl-n4{margin:-1.5rem !important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem !important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem !important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem !important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem !important}.m-xl-n5{margin:-3rem !important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem !important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem !important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem !important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.text-monospace{font-family:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important}.text-justify{text-align:justify !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}@media (min-width: 576px){.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-left{text-align:left !important}.text-md-right{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.text-lg-left{text-align:left !important}.text-lg-right{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.text-xl-left{text-align:left !important}.text-xl-right{text-align:right !important}.text-xl-center{text-align:center !important}}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.font-weight-light{font-weight:300 !important}.font-weight-lighter{font-weight:lighter !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:700 !important}.font-weight-bolder{font-weight:bolder !important}.font-italic{font-style:italic !important}.text-white{color:#fff !important}.text-primary{color:#3A3F44 !important}a.text-primary:hover,a.text-primary:focus{color:#17191b !important}.text-secondary{color:#7A8288 !important}a.text-secondary:hover,a.text-secondary:focus{color:#565b60 !important}.text-success{color:#62c462 !important}a.text-success:hover,a.text-success:focus{color:#3b9e3b !important}.text-info{color:#5bc0de !important}a.text-info:hover,a.text-info:focus{color:#28a1c5 !important}.text-warning{color:#f89406 !important}a.text-warning:hover,a.text-warning:focus{color:#ad6704 !important}.text-danger{color:#ee5f5b !important}a.text-danger:hover,a.text-danger:focus{color:#e51d18 !important}.text-light{color:#e9ecef !important}a.text-light:hover,a.text-light:focus{color:#bdc6cf !important}.text-dark{color:#272B30 !important}a.text-dark:hover,a.text-dark:focus{color:#050506 !important}.text-body{color:#aaa !important}.text-muted{color:#7A8288 !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none !important}.text-break{word-break:break-word !important;overflow-wrap:break-word !important}.text-reset{color:inherit !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media print{*,*::before,*::after{text-shadow:none !important;-webkit-box-shadow:none !important;box-shadow:none !important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap !important}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px !important}.container{min-width:992px !important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6 !important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:rgba(0,0,0,0.6)}.table .thead-dark th{color:inherit;border-color:rgba(0,0,0,0.6)}}.navbar{border:1px solid rgba(0,0,0,0.6);text-shadow:1px 1px 1px rgba(0,0,0,0.3)}.navbar .container{padding:0}.navbar .navbar-toggler{border-color:rgba(0,0,0,0.6)}.navbar-fixed-top{border-width:0 0 1px 0}.navbar-fixed-bottom{border-width:1px 0 0 0}.navbar .nav-link{padding:1rem;border-left:1px solid rgba(255,255,255,0.1);border-right:1px solid rgba(0,0,0,0.2)}.navbar .nav-link:hover,.navbar .nav-link:focus{background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none;border-left:1px solid rgba(0,0,0,0.2)}.navbar-brand{padding:0.75rem 1rem calc(54px - 0.75rem - 30px);margin-right:0;border-right:1px solid rgba(0,0,0,0.2)}.navbar .nav-item.active .nav-link{background-color:rgba(0,0,0,0.3);border-left:1px solid rgba(0,0,0,0.2)}.navbar-nav .nav-item+.nav-item{margin-left:0}.navbar.bg-light{text-shadow:1px 1px 1px rgba(0,0,0,0.1)}.navbar.bg-light .nav-link:hover,.navbar.bg-light .nav-link:focus{background-image:-webkit-gradient(linear, left top, left bottom, from(#4e5458), color-stop(40%, #565b60), to(#5b6165));background-image:linear-gradient(#4e5458, #565b60 40%, #5b6165);background-repeat:no-repeat;-webkit-filter:none;filter:none;border-left:1px solid rgba(0,0,0,0.2)}@media (max-width: 576px){.navbar-expand-sm .navbar-brand,.navbar-expand-sm .nav-link{border:none !important}}@media (max-width: 768px){.navbar-expand-md .navbar-brand,.navbar-expand-md .nav-link{border:none !important}}@media (max-width: 992px){.navbar-expand-lg .navbar-brand,.navbar-expand-lg .nav-link{border:none !important}}.btn{border-color:rgba(0,0,0,0.6);text-shadow:1px 1px 1px rgba(0,0,0,0.3)}.btn:not([disabled]):not(.disabled).active,.btn.disabled{border-color:rgba(0,0,0,0.6);-webkit-box-shadow:none;box-shadow:none}.btn:hover,.btn:focus,.btn:not([disabled]):not(.disabled):active,.btn:not([disabled]):not(.disabled):active:hover,.btn:not([disabled]):not(.disabled).active:hover{border-color:rgba(0,0,0,0.6)}.btn-primary{background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-primary:not([disabled]):not(.disabled):hover,.btn-primary:not([disabled]):not(.disabled):focus,.btn-primary:not([disabled]):not(.disabled):active:hover,.btn-primary:not([disabled]):not(.disabled).active:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-secondary{background-image:-webkit-gradient(linear, left top, left bottom, from(#8a9196), color-stop(60%, #7A8288), to(#70787d));background-image:linear-gradient(#8a9196, #7A8288 60%, #70787d);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-secondary:not([disabled]):not(.disabled):hover,.btn-secondary:not([disabled]):not(.disabled):focus,.btn-secondary:not([disabled]):not(.disabled):active,.btn-secondary:not([disabled]):not(.disabled).active{background-image:-webkit-gradient(linear, left top, left bottom, from(#4e5458), color-stop(40%, #565b60), to(#5b6165));background-image:linear-gradient(#4e5458, #565b60 40%, #5b6165);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-success{background-image:-webkit-gradient(linear, left top, left bottom, from(#78cc78), color-stop(60%, #62c462), to(#53be53));background-image:linear-gradient(#78cc78, #62c462 60%, #53be53);background-repeat:no-repeat;-webkit-filter:none;filter:none;color:#fff}.btn-success:not([disabled]):not(.disabled):hover,.btn-success:not([disabled]):not(.disabled):focus,.btn-success:not([disabled]):not(.disabled):active,.btn-success:not([disabled]):not(.disabled).active{background-image:-webkit-gradient(linear, left top, left bottom, from(#379337), color-stop(40%, #3b9e3b), to(#3ea63e));background-image:linear-gradient(#379337, #3b9e3b 40%, #3ea63e);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-info{background-image:-webkit-gradient(linear, left top, left bottom, from(#74cae3), color-stop(60%, #5bc0de), to(#4ab9db));background-image:linear-gradient(#74cae3, #5bc0de 60%, #4ab9db);background-repeat:no-repeat;-webkit-filter:none;filter:none;color:#fff}.btn-info:not([disabled]):not(.disabled):hover,.btn-info:not([disabled]):not(.disabled):focus,.btn-info:not([disabled]):not(.disabled):active,.btn-info:not([disabled]):not(.disabled).active{background-image:-webkit-gradient(linear, left top, left bottom, from(#2596b8), color-stop(40%, #28a1c5), to(#29a8cd));background-image:linear-gradient(#2596b8, #28a1c5 40%, #29a8cd);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-warning{background-image:-webkit-gradient(linear, left top, left bottom, from(#faa123), color-stop(60%, #f89406), to(#e48806));background-image:linear-gradient(#faa123, #f89406 60%, #e48806);background-repeat:no-repeat;-webkit-filter:none;filter:none;color:#fff}.btn-warning:not([disabled]):not(.disabled):hover,.btn-warning:not([disabled]):not(.disabled):focus,.btn-warning:not([disabled]):not(.disabled):active,.btn-warning:not([disabled]):not(.disabled).active{background-image:-webkit-gradient(linear, left top, left bottom, from(#9e5f04), color-stop(40%, #ad6704), to(#b76d04));background-image:linear-gradient(#9e5f04, #ad6704 40%, #b76d04);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-danger{background-image:-webkit-gradient(linear, left top, left bottom, from(#f17a77), color-stop(60%, #ee5f5b), to(#ec4d49));background-image:linear-gradient(#f17a77, #ee5f5b 60%, #ec4d49);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-danger:not([disabled]):not(.disabled):hover,.btn-danger:not([disabled]):not(.disabled):focus,.btn-danger:not([disabled]):not(.disabled):active,.btn-danger:not([disabled]):not(.disabled).active{background-image:-webkit-gradient(linear, left top, left bottom, from(#d71c16), color-stop(40%, #e51d18), to(#e8241f));background-image:linear-gradient(#d71c16, #e51d18 40%, #e8241f);background-repeat:no-repeat;-webkit-filter:none;filter:none}.btn-link,.btn-link:hover{border-color:transparent}.btn-group .btn.active,.btn-group-vertical .btn.active{border-color:rgba(0,0,0,0.6)}h1,h2,h3,h4,h5,h6{text-shadow:-1px -1px 0 rgba(0,0,0,0.3)}.table-primary,.table-secondary,.table-success,.table-info,.table-warning,.table-danger{color:#fff}.table-primary,.table-primary>th,.table-primary>td{background-color:#3A3F44}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#7A8288}.table-light,.table-light>th,.table-light>td{background-color:#e9ecef}.table-dark,.table-dark>th,.table-dark>td{background-color:#272B30}.table-success,.table-success>th,.table-success>td{background-color:#62c462}.table-info,.table-info>th,.table-info>td{background-color:#5bc0de}.table-danger,.table-danger>th,.table-danger>td{background-color:#ee5f5b}.table-warning,.table-warning>th,.table-warning>td{background-color:#f89406}.table-active,.table-active>th,.table-active>td{background-color:rgba(255,255,255,0.075)}.table-hover .table-primary:hover,.table-hover .table-primary:hover>th,.table-hover .table-primary:hover>td{background-color:#2e3236}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>th,.table-hover .table-secondary:hover>td{background-color:#6e757b}.table-hover .table-light:hover,.table-hover .table-light:hover>th,.table-hover .table-light:hover>td{background-color:#dadfe4}.table-hover .table-dark:hover,.table-hover .table-dark:hover>th,.table-hover .table-dark:hover>td{background-color:#1c1e22}.table-hover .table-success:hover,.table-hover .table-success:hover>th,.table-hover .table-success:hover>td{background-color:#4fbd4f}.table-hover .table-info:hover,.table-hover .table-info:hover>th,.table-hover .table-info:hover>td{background-color:#46b8da}.table-hover .table-danger:hover,.table-hover .table-danger:hover>th,.table-hover .table-danger:hover>td{background-color:#ec4844}.table-hover .table-warning:hover,.table-hover .table-warning:hover>th,.table-hover .table-warning:hover>td{background-color:#df8505}.table-hover .table-active:hover,.table-hover .table-active:hover>th,.table-hover .table-active:hover>td{background-color:rgba(255,255,255,0.075)}legend{color:#fff}.input-group-addon{background-image:-webkit-gradient(linear, left top, left bottom, from(#8a9196), color-stop(60%, #7A8288), to(#70787d));background-image:linear-gradient(#8a9196, #7A8288 60%, #70787d);background-repeat:no-repeat;-webkit-filter:none;filter:none;text-shadow:1px 1px 1px rgba(0,0,0,0.3);color:#fff}.nav-tabs .nav-link{background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none;border:1px solid rgba(0,0,0,0.6)}.nav-tabs .nav-link:not([disabled]):not(.disabled):hover,.nav-tabs .nav-link:not([disabled]):not(.disabled):focus,.nav-tabs .nav-link:not([disabled]):not(.disabled):active,.nav-tabs .nav-link:not([disabled]):not(.disabled).active{background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none}.nav-tabs .nav-link.disabled{border:1px solid rgba(0,0,0,0.6)}.nav-tabs .nav-link,.nav-tabs .nav-link:hover{color:#fff}.nav-pills .nav-link{background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none;border:1px solid rgba(0,0,0,0.6);text-shadow:1px 1px 1px rgba(0,0,0,0.3);color:#fff}.nav-pills .nav-link:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none;border:1px solid rgba(0,0,0,0.6)}.nav-pills .nav-link.active,.nav-pills .nav-link:hover{background-color:transparent;background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none;border:1px solid rgba(0,0,0,0.6)}.nav-pills .nav-link.disabled,.nav-pills .nav-link.disabled:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none;color:#7A8288}.pagination .page-link{text-shadow:1px 1px 1px rgba(0,0,0,0.3);background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none}.pagination .page-link:hover{background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none;text-decoration:none}.pagination .page-item.active .page-link{background-image:-webkit-gradient(linear, left top, left bottom, from(#101112), color-stop(40%, #17191b), to(#1b1e20));background-image:linear-gradient(#101112, #17191b 40%, #1b1e20);background-repeat:no-repeat;-webkit-filter:none;filter:none}.pagination .page-item.disabled .page-link{background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none}.breadcrumb{border:1px solid rgba(0,0,0,0.6);text-shadow:1px 1px 1px rgba(0,0,0,0.3);background-color:transparent;background-image:-webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3A3F44), to(#313539));background-image:linear-gradient(#484e55, #3A3F44 60%, #313539);background-repeat:no-repeat;-webkit-filter:none;filter:none}.breadcrumb a,.breadcrumb a:hover{color:#fff}.alert .close{color:#000;text-decoration:none}.alert{border:none;color:#fff}.alert a,.alert .alert-link{color:#fff;text-decoration:underline}.alert-primary{background-color:#3A3F44}.alert-secondary{background-color:#7A8288}.alert-success{background-color:#62c462}.alert-info{background-color:#5bc0de}.alert-warning{background-color:#f89406}.alert-danger{background-color:#ee5f5b}.alert-light{background-color:#e9ecef}.alert-dark{background-color:#272B30}.alert-light,.alert-light a:not(.btn),.alert-light .alert-link{color:#272B30}.badge-success,.badge-warning,.badge-info{color:#fff}.jumbotron{border:1px solid rgba(0,0,0,0.6)}.list-group-item:hover{background-color:#1c1e22} diff --git a/file-upload/jquery-file-upload/index.html b/file-upload/jquery-file-upload/index.html deleted file mode 100644 index f77ea8b5b..000000000 --- a/file-upload/jquery-file-upload/index.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - -%SITE_NAME% - - - - - - - - - - - - - - - - - - - -
- %SITE_NAME% -
-
-

%SITE_NAME%

-
-
-
-
- -
- -
-
- - - - Add files... - - - -    - - - -
- -
- -
-
-
- -
 
-
-
-
-
-
- Tags: -
-
- -
- -
- -
-
-
-
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/file-upload/jquery-file-upload/index.php b/file-upload/jquery-file-upload/index.php deleted file mode 100644 index b2a0f7494..000000000 --- a/file-upload/jquery-file-upload/index.php +++ /dev/null @@ -1,23 +0,0 @@ - 'handle_file_post', + 'BASE64_ENCODED_FILE_OBJECTS' => 'handle_base64_encoded_file_post', + 'TRANSFER_IDS' => 'handle_transfer_ids_post' +]); + +function console_log($data, $add_script_tags = false) { + $command = 'console.log('. json_encode($data, JSON_HEX_TAG).');'; + if ($add_script_tags) { + $command = ''; + } + echo $command; +} + +function sanitize_tagged_filename($filename) { + $info = pathinfo($filename); + $name = sanitize_tagged_filename_part($info['filename']); + $extension = sanitize_tagged_filename_part($info['extension']); + return (strlen($name) > 0 ? $name : '_') . '.' . $extension; +} + +function sanitize_tagged_filename_part($str) { + return preg_replace("/[^a-zA-Z0-9\s_\(\)\.,-]/", "", $str); +} + +function move_temp_file_prefixed($file, $path, $prefix) { + move_uploaded_file($file['tmp_name'], $path . DIRECTORY_SEPARATOR . sanitize_tagged_filename($prefix . $file['name'])); +} + +function move_file_prefixed($file, $path, $prefix) { + if (is_uploaded_file($file['tmp_name'])) { + return move_temp_file_prefixed($file, $path, $prefix); + } + return rename($file['tmp_name'], $path . DIRECTORY_SEPARATOR . sanitize_tagged_filename($prefix . $file['name'])); +} + + +function handle_file_post($files) { + + foreach($files as $file) { + FilePond\move_file($file, UPLOAD_DIR); + } + +} + +function handle_base64_encoded_file_post($files) { + + foreach ($files as $file) { + + // Suppress error messages, we'll assume these file objects are valid + /* Expected format: + { + "id": "iuhv2cpsu", + "name": "picture.jpg", + "type": "image/jpeg", + "size": 20636, + "metadata" : {...} + "data": "/9j/4AAQSkZJRgABAQEASABIAA..." + } + */ + $file = @json_decode($file); + if (!is_object($file)) continue; + + FilePond\write_file( + UPLOAD_DIR, + base64_decode($file->data), + FilePond\sanitize_filename($file->name) + ); + } + +} + +function handle_transfer_ids_post($ids) { + + foreach ($ids as $id) { + + $transfer = FilePond\get_transfer(TRANSFER_DIR, $id); + if (!$transfer) continue; + + $new_name_prefix = ''; + if (isset($_POST["tags"]) && (strlen($_POST["tags"]) > 0)) { + $new_name_prefix = $_POST["tags"] . ",USERTAG,"; + } + + $files = $transfer->getFiles(defined('TRANSFER_PROCESSOR') ? TRANSFER_PROCESSOR : null); + if($files != null){ + foreach($files as $file) { + move_file_prefixed($file, UPLOAD_DIR, $new_name_prefix); + } + } + + FilePond\remove_transfer_directory(TRANSFER_DIR, $id); + } + + $return_to = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/upload'; + header("Location: ". $return_to); +} \ No newline at end of file diff --git a/file-upload/site/index.html b/file-upload/site/index.html new file mode 100644 index 000000000..fa4377939 --- /dev/null +++ b/file-upload/site/index.html @@ -0,0 +1,181 @@ + + + + + + + File Upload + + + + + + %SITE_NAME% +

Network Traffic Artifact Upload

+ +
+ + +
+ + + +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/file-upload/supervisord.conf b/file-upload/supervisord.conf index abcac3abe..89e2b32ee 100644 --- a/file-upload/supervisord.conf +++ b/file-upload/supervisord.conf @@ -25,7 +25,7 @@ stdout_logfile_maxbytes=0 redirect_stderr=true [program:php] -command=php-fpm7.4 -F -R -g /tmp/php-fpm.pid +command=php-fpm8.2 -F -R -g /tmp/php-fpm.pid stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 redirect_stderr=true @@ -38,3 +38,13 @@ killasgroup=true stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 redirect_stderr=true + +[program:cron] +autorestart=true +command=/usr/local/bin/supercronic -json "%(ENV_SUPERCRONIC_CRONTAB)s" +user=%(ENV_PUSER)s +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true diff --git a/filebeat/scripts/filebeat-watch-zeeklogs-uploads-folder.py b/filebeat/scripts/filebeat-watch-zeeklogs-uploads-folder.py index 43978a662..1dfccf54a 100755 --- a/filebeat/scripts/filebeat-watch-zeeklogs-uploads-folder.py +++ b/filebeat/scripts/filebeat-watch-zeeklogs-uploads-folder.py @@ -104,6 +104,17 @@ def main(): type=str, required=False, ) + parser.add_argument( + '--recursive', + dest='recursiveAll', + help="Monitor all directories underneath --directory", + metavar='true|false', + type=str2bool, + nargs='?', + const=True, + default=False, + required=False, + ) parser.add_argument( '-p', '--polling', @@ -224,6 +235,7 @@ def main(): watch_common.WatchAndProcessDirectory( watchDirs, args.polling, + args.recursiveAll, file_processor, { "logger": logging, diff --git a/kubernetes/03-opensearch.yml b/kubernetes/03-opensearch.yml index 14607990e..980267a52 100644 --- a/kubernetes/03-opensearch.yml +++ b/kubernetes/03-opensearch.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: opensearch-container - image: ghcr.io/idaholab/malcolm/opensearch:23.07.1 + image: ghcr.io/idaholab/malcolm/opensearch:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -69,7 +69,7 @@ spec: subPath: "opensearch" initContainers: - name: opensearch-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/04-dashboards.yml b/kubernetes/04-dashboards.yml index 7ca5e4069..f1ffeb109 100644 --- a/kubernetes/04-dashboards.yml +++ b/kubernetes/04-dashboards.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: dashboards-container - image: ghcr.io/idaholab/malcolm/dashboards:23.07.1 + image: ghcr.io/idaholab/malcolm/dashboards:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/05-upload.yml b/kubernetes/05-upload.yml index 91104fa89..9bb21b84f 100644 --- a/kubernetes/05-upload.yml +++ b/kubernetes/05-upload.yml @@ -34,7 +34,7 @@ spec: spec: containers: - name: upload-container - image: ghcr.io/idaholab/malcolm/file-upload:23.07.1 + image: ghcr.io/idaholab/malcolm/file-upload:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -52,8 +52,6 @@ spec: name: ssl-env - secretRef: name: auth-env - - configMapRef: - name: upload-env env: - name: VIRTUAL_HOST value: "upload.malcolm.local" @@ -75,7 +73,7 @@ spec: subPath: "upload" initContainers: - name: upload-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -84,7 +82,7 @@ spec: name: process-env env: - name: PUSER_MKDIR - value: "/data/pcap:upload" + value: "/data/pcap:upload/tmp/spool,upload/variants" volumeMounts: - name: upload-pcap-volume mountPath: "/data/pcap" diff --git a/kubernetes/06-pcap-monitor.yml b/kubernetes/06-pcap-monitor.yml index a6d1fd0ba..61b282007 100644 --- a/kubernetes/06-pcap-monitor.yml +++ b/kubernetes/06-pcap-monitor.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: pcap-monitor-container - image: ghcr.io/idaholab/malcolm/pcap-monitor:23.07.1 + image: ghcr.io/idaholab/malcolm/pcap-monitor:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -70,7 +70,7 @@ spec: name: pcap-monitor-zeek-volume initContainers: - name: pcap-monitor-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/07-arkime.yml b/kubernetes/07-arkime.yml index 8f2e89f65..b2ed78f36 100644 --- a/kubernetes/07-arkime.yml +++ b/kubernetes/07-arkime.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: arkime-container - image: ghcr.io/idaholab/malcolm/arkime:23.07.1 + image: ghcr.io/idaholab/malcolm/arkime:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -83,7 +83,7 @@ spec: subPath: "arkime" initContainers: - name: arkime-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/08-api.yml b/kubernetes/08-api.yml index b9281e6e0..602f2cc2c 100644 --- a/kubernetes/08-api.yml +++ b/kubernetes/08-api.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: api-container - image: ghcr.io/idaholab/malcolm/api:23.07.1 + image: ghcr.io/idaholab/malcolm/api:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/09-dashboards-helper.yml b/kubernetes/09-dashboards-helper.yml index d67888078..d6307e18c 100644 --- a/kubernetes/09-dashboards-helper.yml +++ b/kubernetes/09-dashboards-helper.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: dashboards-helper-container - image: ghcr.io/idaholab/malcolm/dashboards-helper:23.07.1 + image: ghcr.io/idaholab/malcolm/dashboards-helper:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/10-zeek.yml b/kubernetes/10-zeek.yml index d9e68bd9f..dc4078e31 100644 --- a/kubernetes/10-zeek.yml +++ b/kubernetes/10-zeek.yml @@ -16,7 +16,7 @@ spec: spec: containers: - name: zeek-offline-container - image: ghcr.io/idaholab/malcolm/zeek:23.07.1 + image: ghcr.io/idaholab/malcolm/zeek:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -68,7 +68,7 @@ spec: subPath: "zeek/intel" initContainers: - name: zeek-offline-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/11-suricata.yml b/kubernetes/11-suricata.yml index 8651fd142..2473603be 100644 --- a/kubernetes/11-suricata.yml +++ b/kubernetes/11-suricata.yml @@ -16,7 +16,7 @@ spec: spec: containers: - name: suricata-offline-container - image: ghcr.io/idaholab/malcolm/suricata:23.07.1 + image: ghcr.io/idaholab/malcolm/suricata:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -61,7 +61,7 @@ spec: name: suricata-offline-custom-rules-volume initContainers: - name: suricata-offline-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/12-file-monitor.yml b/kubernetes/12-file-monitor.yml index 7c3a30a08..aff2875ea 100644 --- a/kubernetes/12-file-monitor.yml +++ b/kubernetes/12-file-monitor.yml @@ -33,7 +33,7 @@ spec: spec: containers: - name: file-monitor-container - image: ghcr.io/idaholab/malcolm/file-monitor:23.07.1 + image: ghcr.io/idaholab/malcolm/file-monitor:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -81,7 +81,7 @@ spec: name: file-monitor-yara-rules-custom-volume initContainers: - name: file-monitor-live-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/13-filebeat.yml b/kubernetes/13-filebeat.yml index 20405c4fa..f836629cb 100644 --- a/kubernetes/13-filebeat.yml +++ b/kubernetes/13-filebeat.yml @@ -33,7 +33,7 @@ spec: spec: containers: - name: filebeat-container - image: ghcr.io/idaholab/malcolm/filebeat-oss:23.07.1 + image: ghcr.io/idaholab/malcolm/filebeat-oss:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -83,7 +83,7 @@ spec: subPath: "nginx" initContainers: - name: filebeat-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/14-logstash.yml b/kubernetes/14-logstash.yml index c70cd7057..249f00757 100644 --- a/kubernetes/14-logstash.yml +++ b/kubernetes/14-logstash.yml @@ -49,7 +49,7 @@ spec: # topologyKey: "kubernetes.io/hostname" containers: - name: logstash-container - image: ghcr.io/idaholab/malcolm/logstash-oss:23.07.1 + image: ghcr.io/idaholab/malcolm/logstash-oss:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -113,7 +113,7 @@ spec: subPath: "logstash" initContainers: - name: logstash-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/15-netbox-redis.yml b/kubernetes/15-netbox-redis.yml index 1b44d5b45..8f1fef9cb 100644 --- a/kubernetes/15-netbox-redis.yml +++ b/kubernetes/15-netbox-redis.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: netbox-redis-container - image: ghcr.io/idaholab/malcolm/redis:23.07.1 + image: ghcr.io/idaholab/malcolm/redis:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -83,7 +83,7 @@ spec: subPath: netbox/redis initContainers: - name: netbox-redis-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/16-netbox-redis-cache.yml b/kubernetes/16-netbox-redis-cache.yml index 9a6a9bb53..6db92a48a 100644 --- a/kubernetes/16-netbox-redis-cache.yml +++ b/kubernetes/16-netbox-redis-cache.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: netbox-redis-cache-container - image: ghcr.io/idaholab/malcolm/redis:23.07.1 + image: ghcr.io/idaholab/malcolm/redis:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/17-netbox-postgres.yml b/kubernetes/17-netbox-postgres.yml index 041f521b2..9b41f4bfb 100644 --- a/kubernetes/17-netbox-postgres.yml +++ b/kubernetes/17-netbox-postgres.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: netbox-postgres-container - image: ghcr.io/idaholab/malcolm/postgresql:23.07.1 + image: ghcr.io/idaholab/malcolm/postgresql:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -74,7 +74,7 @@ spec: subPath: netbox/postgres initContainers: - name: netbox-postgres-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/18-netbox.yml b/kubernetes/18-netbox.yml index f5e68f26e..1b4e66c22 100644 --- a/kubernetes/18-netbox.yml +++ b/kubernetes/18-netbox.yml @@ -36,7 +36,7 @@ spec: spec: containers: - name: netbox-container - image: ghcr.io/idaholab/malcolm/netbox:23.07.1 + image: ghcr.io/idaholab/malcolm/netbox:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -81,16 +81,14 @@ spec: name: netbox-netmap-json-volume - mountPath: /etc/netbox/config/configmap name: netbox-config-volume - - mountPath: /etc/netbox/reports/configmap - name: netbox-reports-volume - - mountPath: /etc/netbox/scripts/configmap - name: netbox-scripts-volume + - mountPath: /opt/netbox-preload/configmap + name: netbox-preload-volume - mountPath: /opt/netbox/netbox/media name: netbox-media-volume subPath: netbox/media initContainers: - name: netbox-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -113,12 +111,9 @@ spec: - name: netbox-config-volume configMap: name: netbox-config - - name: netbox-reports-volume + - name: netbox-preload-volume configMap: - name: netbox-reports - - name: netbox-scripts-volume - configMap: - name: netbox-scripts + name: netbox-preload - name: netbox-media-volume persistentVolumeClaim: claimName: config-claim diff --git a/kubernetes/19-htadmin.yml b/kubernetes/19-htadmin.yml index 032b94af4..95e791715 100644 --- a/kubernetes/19-htadmin.yml +++ b/kubernetes/19-htadmin.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: htadmin-container - image: ghcr.io/idaholab/malcolm/htadmin:23.07.1 + image: ghcr.io/idaholab/malcolm/htadmin:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -63,7 +63,7 @@ spec: subPath: "htadmin" initContainers: - name: htadmin-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/20-pcap-capture.yml b/kubernetes/20-pcap-capture.yml index e5a0a3193..e42a4f17b 100644 --- a/kubernetes/20-pcap-capture.yml +++ b/kubernetes/20-pcap-capture.yml @@ -16,7 +16,7 @@ spec: spec: containers: - name: pcap-capture-container - image: ghcr.io/idaholab/malcolm/pcap-capture:23.07.1 + image: ghcr.io/idaholab/malcolm/pcap-capture:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -46,7 +46,7 @@ spec: subPath: "upload" initContainers: - name: pcap-capture-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/21-zeek-live.yml b/kubernetes/21-zeek-live.yml index 89a99df3a..8cb34eddd 100644 --- a/kubernetes/21-zeek-live.yml +++ b/kubernetes/21-zeek-live.yml @@ -16,7 +16,7 @@ spec: spec: containers: - name: zeek-live-container - image: ghcr.io/idaholab/malcolm/zeek:23.07.1 + image: ghcr.io/idaholab/malcolm/zeek:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -60,7 +60,7 @@ spec: subPath: "zeek/intel" initContainers: - name: zeek-live-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/22-suricata-live.yml b/kubernetes/22-suricata-live.yml index bcf568008..915f29970 100644 --- a/kubernetes/22-suricata-live.yml +++ b/kubernetes/22-suricata-live.yml @@ -16,7 +16,7 @@ spec: spec: containers: - name: suricata-live-container - image: ghcr.io/idaholab/malcolm/suricata:23.07.1 + image: ghcr.io/idaholab/malcolm/suricata:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -51,7 +51,7 @@ spec: name: suricata-live-suricata-logs-volume initContainers: - name: suricata-live-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/23-freq.yml b/kubernetes/23-freq.yml index 824b611cc..d215d71c4 100644 --- a/kubernetes/23-freq.yml +++ b/kubernetes/23-freq.yml @@ -30,7 +30,7 @@ spec: spec: containers: - name: freq-container - image: ghcr.io/idaholab/malcolm/freq:23.07.1 + image: ghcr.io/idaholab/malcolm/freq:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/98-nginx-proxy.yml b/kubernetes/98-nginx-proxy.yml index 2ec8d3a23..b8dd6abb4 100644 --- a/kubernetes/98-nginx-proxy.yml +++ b/kubernetes/98-nginx-proxy.yml @@ -39,7 +39,7 @@ spec: spec: containers: - name: nginx-proxy-container - image: ghcr.io/idaholab/malcolm/nginx-proxy:23.07.1 + image: ghcr.io/idaholab/malcolm/nginx-proxy:23.08.0 imagePullPolicy: Always stdin: false tty: true @@ -95,7 +95,7 @@ spec: subPath: "nginx" initContainers: - name: nginx-dirinit-container - image: ghcr.io/idaholab/malcolm/dirinit:23.07.1 + image: ghcr.io/idaholab/malcolm/dirinit:23.08.0 imagePullPolicy: Always stdin: false tty: true diff --git a/kubernetes/vagrant/Vagrantfile b/kubernetes/vagrant/Vagrantfile index fefc7d6d8..054b20104 100644 --- a/kubernetes/vagrant/Vagrantfile +++ b/kubernetes/vagrant/Vagrantfile @@ -130,7 +130,7 @@ agent_script_1 = <<-SHELL SHELL Vagrant.configure("2") do |config| - config.vm.box = "bento/debian-11" + config.vm.box = "bento/debian-12" config.ssh.config = "ssh_config" config.vm.define "server", primary: true do |server| diff --git a/logstash/pipelines/zeek/11_zeek_parse.conf b/logstash/pipelines/zeek/11_zeek_parse.conf index d0bfcdd10..5f84a1906 100644 --- a/logstash/pipelines/zeek/11_zeek_parse.conf +++ b/logstash/pipelines/zeek/11_zeek_parse.conf @@ -214,7 +214,7 @@ filter { id => "dissect_zeek_bacnet" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][bvlc_function]} %{[zeek_cols][pdu_type]} %{[zeek_cols][pdu_service]} %{[zeek_cols][invoke_id]} %{[zeek_cols][result_code]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][bvlc_function]} %{[zeek_cols][pdu_type]} %{[zeek_cols][pdu_service]} %{[zeek_cols][invoke_id]} %{[zeek_cols][result_code]}" } } if ("_dissectfailure" in [tags]) { @@ -225,7 +225,7 @@ filter { } ruby { id => "ruby_zip_zeek_bacnet" - init => "$zeek_bacnet_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'bvlc_function', 'pdu_type', 'pdu_service', 'invoke_id', 'result_code' ]" + init => "$zeek_bacnet_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'bvlc_function', 'pdu_type', 'pdu_service', 'invoke_id', 'result_code' ]" code => "event.set('[zeek_cols]', $zeek_bacnet_field_names.zip(event.get('[message]')).to_h)" } } @@ -275,7 +275,7 @@ filter { id => "dissect_zeek_bsap_ip_header" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][num_msg]} %{[zeek_cols][type_name]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][num_msg]} %{[zeek_cols][type_name]}" } } if ("_dissectfailure" in [tags]) { @@ -286,7 +286,7 @@ filter { } ruby { id => "ruby_zip_zeek_bsap_ip_header" - init => "$zeek_bsap_ip_header_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'num_msg', 'type_name' ]" + init => "$zeek_bsap_ip_header_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'num_msg', 'type_name' ]" code => "event.set('[zeek_cols]', $zeek_bsap_ip_header_field_names.zip(event.get('[message]')).to_h)" } } @@ -309,7 +309,7 @@ filter { id => "dissect_zeek_bsap_ip_rdb" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][header_size]} %{[zeek_cols][mes_seq]} %{[zeek_cols][res_seq]} %{[zeek_cols][data_len]} %{[zeek_cols][sequence]} %{[zeek_cols][app_func_code]} %{[zeek_cols][node_status]} %{[zeek_cols][func_code]} %{[zeek_cols][variable_count]} %{[zeek_cols][variables]} %{[zeek_cols][variable_value]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][header_size]} %{[zeek_cols][mes_seq]} %{[zeek_cols][res_seq]} %{[zeek_cols][data_len]} %{[zeek_cols][sequence]} %{[zeek_cols][app_func_code]} %{[zeek_cols][node_status]} %{[zeek_cols][func_code]} %{[zeek_cols][variable_count]} %{[zeek_cols][variables]} %{[zeek_cols][variable_value]}" } } if ("_dissectfailure" in [tags]) { @@ -320,7 +320,7 @@ filter { } ruby { id => "ruby_zip_zeek_bsap_ip_rdb" - init => "$zeek_bsap_ip_rdb_field_names = [ 'ts', 'uid', 'header_size', 'mes_seq', 'res_seq', 'data_len', 'sequence', 'app_func_code', 'node_status', 'func_code', 'variable_count', 'variables', 'variable_value' ]" + init => "$zeek_bsap_ip_rdb_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'header_size', 'mes_seq', 'res_seq', 'data_len', 'sequence', 'app_func_code', 'node_status', 'func_code', 'variable_count', 'variables', 'variable_value' ]" code => "event.set('[zeek_cols]', $zeek_bsap_ip_rdb_field_names.zip(event.get('[message]')).to_h)" } } @@ -343,7 +343,7 @@ filter { id => "dissect_zeek_bsap_serial_header" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][ser]} %{[zeek_cols][dadd]} %{[zeek_cols][sadd]} %{[zeek_cols][ctl]} %{[zeek_cols][dfun]} %{[zeek_cols][seq]} %{[zeek_cols][sfun]} %{[zeek_cols][nsb]} %{[zeek_cols][type_name]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][ser]} %{[zeek_cols][dadd]} %{[zeek_cols][sadd]} %{[zeek_cols][ctl]} %{[zeek_cols][dfun]} %{[zeek_cols][seq]} %{[zeek_cols][sfun]} %{[zeek_cols][nsb]} %{[zeek_cols][type_name]}" } } if ("_dissectfailure" in [tags]) { @@ -354,7 +354,7 @@ filter { } ruby { id => "ruby_zip_zeek_bsap_serial_header" - init => "$zeek_bsap_serial_header_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'ser', 'dadd', 'sadd', 'ctl', 'dfun', 'seq', 'sfun', 'nsb', 'type_name' ]" + init => "$zeek_bsap_serial_header_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'ser', 'dadd', 'sadd', 'ctl', 'dfun', 'seq', 'sfun', 'nsb', 'type_name' ]" code => "event.set('[zeek_cols]', $zeek_bsap_serial_header_field_names.zip(event.get('[message]')).to_h)" } } @@ -377,7 +377,7 @@ filter { id => "dissect_zeek_bsap_serial_rdb" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][func_code]} %{[zeek_cols][variable_count]} %{[zeek_cols][variables]} %{[zeek_cols][variable_value]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][func_code]} %{[zeek_cols][variable_count]} %{[zeek_cols][variables]} %{[zeek_cols][variable_value]}" } } if ("_dissectfailure" in [tags]) { @@ -388,7 +388,7 @@ filter { } ruby { id => "ruby_zip_zeek_bsap_serial_rdb" - init => "$zeek_bsap_serial_rdb_field_names = [ 'ts', 'uid', 'func_code', 'variable_count', 'variables', 'variable_value' ]" + init => "$zeek_bsap_serial_rdb_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'func_code', 'variable_count', 'variables', 'variable_value' ]" code => "event.set('[zeek_cols]', $zeek_bsap_serial_rdb_field_names.zip(event.get('[message]')).to_h)" } } @@ -411,7 +411,7 @@ filter { id => "dissect_zeek_bsap_serial_rdb_ext" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][dfun]} %{[zeek_cols][seq]} %{[zeek_cols][sfun]} %{[zeek_cols][nsb]} %{[zeek_cols][extfun]} %{[zeek_cols][data]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][dfun]} %{[zeek_cols][seq]} %{[zeek_cols][sfun]} %{[zeek_cols][nsb]} %{[zeek_cols][extfun]} %{[zeek_cols][data]}" } } if ("_dissectfailure" in [tags]) { @@ -422,7 +422,7 @@ filter { } ruby { id => "ruby_zip_zeek_bsap_serial_rdb_ext" - init => "$zeek_bsap_serial_rdb_ext_field_names = [ 'ts', 'uid', 'dfun', 'seq', 'sfun', 'nsb', 'extfun', 'data' ]" + init => "$zeek_bsap_serial_rdb_ext_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'dfun', 'seq', 'sfun', 'nsb', 'extfun', 'data' ]" code => "event.set('[zeek_cols]', $zeek_bsap_serial_rdb_ext_field_names.zip(event.get('[message]')).to_h)" } } @@ -451,7 +451,7 @@ filter { id => "dissect_zeek_bacnet_device_control" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][invoke_id]} %{[zeek_cols][pdu_service]} %{[zeek_cols][time_duration]} %{[zeek_cols][device_state]} %{[zeek_cols][password]} %{[zeek_cols][result]} %{[zeek_cols][result_code]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][invoke_id]} %{[zeek_cols][pdu_service]} %{[zeek_cols][time_duration]} %{[zeek_cols][device_state]} %{[zeek_cols][password]} %{[zeek_cols][result]} %{[zeek_cols][result_code]}" } } if ("_dissectfailure" in [tags]) { @@ -462,7 +462,7 @@ filter { } ruby { id => "ruby_zip_zeek_bacnet_device_control" - init => "$zeek_bacnet_device_control_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'invoke_id', 'pdu_service', 'time_duration', 'device_state', 'password', 'result', 'result_code' ]" + init => "$zeek_bacnet_device_control_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'invoke_id', 'pdu_service', 'time_duration', 'device_state', 'password', 'result', 'result_code' ]" code => "event.set('[zeek_cols]', $zeek_bacnet_device_control_field_names.zip(event.get('[message]')).to_h)" } } @@ -485,7 +485,7 @@ filter { id => "dissect_zeek_bacnet_discovery" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][pdu_service]} %{[zeek_cols][object_type]} %{[zeek_cols][instance_number]} %{[zeek_cols][vendor]} %{[zeek_cols][range]} %{[zeek_cols][object_name]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][pdu_service]} %{[zeek_cols][object_type]} %{[zeek_cols][instance_number]} %{[zeek_cols][vendor]} %{[zeek_cols][range]} %{[zeek_cols][object_name]}" } } if ("_dissectfailure" in [tags]) { @@ -496,7 +496,7 @@ filter { } ruby { id => "ruby_zip_zeek_bacnet_discovery" - init => "$zeek_bacnet_discovery_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'pdu_service', 'object_type', 'instance_number', 'vendor', 'range', 'object_name' ]" + init => "$zeek_bacnet_discovery_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'pdu_service', 'object_type', 'instance_number', 'vendor', 'range', 'object_name' ]" code => "event.set('[zeek_cols]', $zeek_bacnet_discovery_field_names.zip(event.get('[message]')).to_h)" } } @@ -519,7 +519,7 @@ filter { id => "dissect_zeek_bacnet_property" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][invoke_id]} %{[zeek_cols][pdu_service]} %{[zeek_cols][object_type]} %{[zeek_cols][instance_number]} %{[zeek_cols][property]} %{[zeek_cols][array_index]} %{[zeek_cols][value]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][invoke_id]} %{[zeek_cols][pdu_service]} %{[zeek_cols][object_type]} %{[zeek_cols][instance_number]} %{[zeek_cols][property]} %{[zeek_cols][array_index]} %{[zeek_cols][value]}" } } if ("_dissectfailure" in [tags]) { @@ -530,7 +530,7 @@ filter { } ruby { id => "ruby_zip_zeek_bacnet_property" - init => "$zeek_bacnet_property_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'invoke_id', 'pdu_service', 'object_type', 'instance_number', 'property', 'array_index', 'value' ]" + init => "$zeek_bacnet_property_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'invoke_id', 'pdu_service', 'object_type', 'instance_number', 'property', 'array_index', 'value' ]" code => "event.set('[zeek_cols]', $zeek_bacnet_property_field_names.zip(event.get('[message]')).to_h)" } } @@ -555,7 +555,7 @@ filter { id => "dissect_zeek_cip" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][cip_sequence_count]} %{[zeek_cols][direction]} %{[zeek_cols][cip_service_code]} %{[zeek_cols][cip_service]} %{[zeek_cols][cip_status_code]} %{[zeek_cols][cip_status]} %{[zeek_cols][cip_extended_status_code]} %{[zeek_cols][cip_extended_status]} %{[zeek_cols][class_id]} %{[zeek_cols][class_name]} %{[zeek_cols][instance_id]} %{[zeek_cols][attribute_id]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][cip_sequence_count]} %{[zeek_cols][direction]} %{[zeek_cols][cip_service_code]} %{[zeek_cols][cip_service]} %{[zeek_cols][cip_status_code]} %{[zeek_cols][cip_status]} %{[zeek_cols][cip_extended_status_code]} %{[zeek_cols][cip_extended_status]} %{[zeek_cols][class_id]} %{[zeek_cols][class_name]} %{[zeek_cols][instance_id]} %{[zeek_cols][attribute_id]}" } } if ("_dissectfailure" in [tags]) { @@ -566,7 +566,7 @@ filter { } ruby { id => "ruby_zip_zeek_cip" - init => "$zeek_cip_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'cip_sequence_count', 'direction', 'cip_service_code', 'cip_service', 'cip_status_code', 'cip_status', 'cip_extended_status_code', 'cip_extended_status', 'class_id', 'class_name', 'instance_id', 'attribute_id' ]" + init => "$zeek_cip_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'cip_sequence_count', 'direction', 'cip_service_code', 'cip_service', 'cip_status_code', 'cip_status', 'cip_extended_status_code', 'cip_extended_status', 'class_id', 'class_name', 'instance_id', 'attribute_id' ]" code => "event.set('[zeek_cols]', $zeek_cip_field_names.zip(event.get('[message]')).to_h)" } } @@ -588,7 +588,7 @@ filter { id => "dissect_zeek_cip_identity" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][encapsulation_version]} %{[zeek_cols][socket_address]} %{[zeek_cols][socket_port]} %{[zeek_cols][vendor_id]} %{[zeek_cols][vendor_name]} %{[zeek_cols][device_type_id]} %{[zeek_cols][device_type_name]} %{[zeek_cols][product_code]} %{[zeek_cols][revision]} %{[zeek_cols][device_status]} %{[zeek_cols][serial_number]} %{[zeek_cols][product_name]} %{[zeek_cols][device_state]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][encapsulation_version]} %{[zeek_cols][socket_address]} %{[zeek_cols][socket_port]} %{[zeek_cols][vendor_id]} %{[zeek_cols][vendor_name]} %{[zeek_cols][device_type_id]} %{[zeek_cols][device_type_name]} %{[zeek_cols][product_code]} %{[zeek_cols][revision]} %{[zeek_cols][device_status]} %{[zeek_cols][serial_number]} %{[zeek_cols][product_name]} %{[zeek_cols][device_state]}" } } if ("_dissectfailure" in [tags]) { @@ -599,7 +599,7 @@ filter { } ruby { id => "ruby_zip_zeek_cip_identity" - init => "$zeek_cip_identity_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'encapsulation_version', 'socket_address', 'socket_port', 'vendor_id', 'vendor_name', 'device_type_id', 'device_type_name', 'product_code', 'device_status', 'serial_number', 'product_name', 'device_state' ]" + init => "$zeek_cip_identity_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'encapsulation_version', 'socket_address', 'socket_port', 'vendor_id', 'vendor_name', 'device_type_id', 'device_type_name', 'product_code', 'device_status', 'serial_number', 'product_name', 'device_state' ]" code => "event.set('[zeek_cols]', $zeek_cip_identity_field_names.zip(event.get('[message]')).to_h)" } } @@ -620,7 +620,7 @@ filter { id => "dissect_zeek_cip_io" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][connection_id]} %{[zeek_cols][sequence_number]} %{[zeek_cols][data_length]} %{[zeek_cols][io_data]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][connection_id]} %{[zeek_cols][sequence_number]} %{[zeek_cols][data_length]} %{[zeek_cols][io_data]}" } } if ("_dissectfailure" in [tags]) { @@ -631,7 +631,7 @@ filter { } ruby { id => "ruby_zip_zeek_cip_io" - init => "$zeek_cip_io_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'connection_id', 'sequence_number', 'data_length', 'io_data' ]" + init => "$zeek_cip_io_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'connection_id', 'sequence_number', 'data_length', 'io_data' ]" code => "event.set('[zeek_cols]', $zeek_cip_io_field_names.zip(event.get('[message]')).to_h)" } } @@ -805,7 +805,7 @@ filter { id => "dissect_zeek_dnp3_control" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][block_type]} %{[zeek_cols][function_code]} %{[zeek_cols][index_number]} %{[zeek_cols][trip_control_code]} %{[zeek_cols][operation_type]} %{[zeek_cols][execute_count]} %{[zeek_cols][on_time]} %{[zeek_cols][off_time]} %{[zeek_cols][status_code]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][block_type]} %{[zeek_cols][function_code]} %{[zeek_cols][index_number]} %{[zeek_cols][trip_control_code]} %{[zeek_cols][operation_type]} %{[zeek_cols][execute_count]} %{[zeek_cols][on_time]} %{[zeek_cols][off_time]} %{[zeek_cols][status_code]}" } } if ("_dissectfailure" in [tags]) { @@ -816,7 +816,7 @@ filter { } ruby { id => "ruby_zip_zeek_dnp3_control" - init => "$zeek_dnp3_control_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'block_type', 'function_code', 'index_number', 'trip_control_code', 'operation_type', 'execute_count', 'on_time', 'off_time', 'status_code' ]" + init => "$zeek_dnp3_control_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'block_type', 'function_code', 'index_number', 'trip_control_code', 'operation_type', 'execute_count', 'on_time', 'off_time', 'status_code' ]" code => "event.set('[zeek_cols]', $zeek_dnp3_control_field_names.zip(event.get('[message]')).to_h)" } } @@ -836,7 +836,7 @@ filter { id => "dissect_zeek_dnp3_objects" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][function_code]} %{[zeek_cols][object_type]} %{[zeek_cols][object_count]} %{[zeek_cols][range_low]} %{[zeek_cols][range_high]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][function_code]} %{[zeek_cols][object_type]} %{[zeek_cols][object_count]} %{[zeek_cols][range_low]} %{[zeek_cols][range_high]}" } } if ("_dissectfailure" in [tags]) { @@ -847,7 +847,7 @@ filter { } ruby { id => "ruby_zip_zeek_dnp3_objects" - init => "$zeek_dnp3_objects_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'function_code', 'object_type', 'object_count', 'range_low', 'range_high' ]" + init => "$zeek_dnp3_objects_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'function_code', 'object_type', 'object_count', 'range_low', 'range_high' ]" code => "event.set('[zeek_cols]', $zeek_dnp3_objects_field_names.zip(event.get('[message]')).to_h)" } } @@ -942,7 +942,7 @@ filter { id => "dissect_zeek_enip" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][enip_command_code]} %{[zeek_cols][enip_command]} %{[zeek_cols][length]} %{[zeek_cols][session_handle]} %{[zeek_cols][enip_status]} %{[zeek_cols][sender_context]} %{[zeek_cols][options]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][enip_command_code]} %{[zeek_cols][enip_command]} %{[zeek_cols][length]} %{[zeek_cols][session_handle]} %{[zeek_cols][enip_status]} %{[zeek_cols][sender_context]} %{[zeek_cols][options]}" } } if ("_dissectfailure" in [tags]) { @@ -953,7 +953,7 @@ filter { } ruby { id => "ruby_zip_zeek_enip" - init => "$zeek_enip_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'enip_command', 'length', 'session_handle', 'enip_status', 'sender_context', 'options' ]" + init => "$zeek_enip_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'enip_command', 'length', 'session_handle', 'enip_status', 'sender_context', 'options' ]" code => "event.set('[zeek_cols]', $zeek_enip_field_names.zip(event.get('[message]')).to_h)" } } @@ -1623,7 +1623,7 @@ filter { id => "dissect_zeek_cotp" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][pdu_code]} %{[zeek_cols][pdu_name]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][pdu_code]} %{[zeek_cols][pdu_name]}" } } if ("_dissectfailure" in [tags]) { @@ -1634,7 +1634,7 @@ filter { } ruby { id => "ruby_zip_zeek_cotp" - init => "$zeek_cotp_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'pdu_code', 'pdu_name' ]" + init => "$zeek_cotp_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'pdu_code', 'pdu_name' ]" code => "event.set('[zeek_cols]', $zeek_cotp_field_names.zip(event.get('[message]')).to_h)" } } @@ -1938,7 +1938,7 @@ filter { id => "dissect_zeek_modbus_detailed" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][unit_id]} %{[zeek_cols][func]} %{[zeek_cols][network_direction]} %{[zeek_cols][address]} %{[zeek_cols][quantity]} %{[zeek_cols][values]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][unit_id]} %{[zeek_cols][func]} %{[zeek_cols][network_direction]} %{[zeek_cols][address]} %{[zeek_cols][quantity]} %{[zeek_cols][values]}" } } if ("_dissectfailure" in [tags]) { @@ -1949,7 +1949,7 @@ filter { } ruby { id => "ruby_zip_zeek_modbus_detailed" - init => "$zeek_modbus_detailed_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'unit_id', 'func', 'network_direction', 'address', 'quantity', 'values' ]" + init => "$zeek_modbus_detailed_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'unit_id', 'func', 'network_direction', 'address', 'quantity', 'values' ]" code => "event.set('[zeek_cols]', $zeek_modbus_detailed_field_names.zip(event.get('[message]')).to_h)" } } @@ -1969,7 +1969,7 @@ filter { id => "dissect_zeek_modbus_mask_write_register" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][unit_id]} %{[zeek_cols][func]} %{[zeek_cols][network_direction]} %{[zeek_cols][address]} %{[zeek_cols][and_mask]} %{[zeek_cols][or_mask]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][unit_id]} %{[zeek_cols][func]} %{[zeek_cols][network_direction]} %{[zeek_cols][address]} %{[zeek_cols][and_mask]} %{[zeek_cols][or_mask]}" } } if ("_dissectfailure" in [tags]) { @@ -1980,7 +1980,7 @@ filter { } ruby { id => "ruby_zip_zeek_modbus_mask_write_register" - init => "$zeek_modbus_mask_write_register_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'unit_id', 'func', 'network_direction', 'address', 'and_mask', 'or_mask' ]" + init => "$zeek_modbus_mask_write_register_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'unit_id', 'func', 'network_direction', 'address', 'and_mask', 'or_mask' ]" code => "event.set('[zeek_cols]', $zeek_modbus_modbus_mask_write_register_field_names.zip(event.get('[message]')).to_h)" } } @@ -1999,7 +1999,7 @@ filter { id => "dissect_zeek_modbus_read_write_multiple_registers" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][unit_id]} %{[zeek_cols][func]} %{[zeek_cols][network_direction]} %{[zeek_cols][write_start_address]} %{[zeek_cols][write_registers]} %{[zeek_cols][read_start_address]} %{[zeek_cols][read_quantity]} %{[zeek_cols][read_registers]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][unit_id]} %{[zeek_cols][func]} %{[zeek_cols][network_direction]} %{[zeek_cols][write_start_address]} %{[zeek_cols][write_registers]} %{[zeek_cols][read_start_address]} %{[zeek_cols][read_quantity]} %{[zeek_cols][read_registers]}" } } if ("_dissectfailure" in [tags]) { @@ -2010,7 +2010,7 @@ filter { } ruby { id => "ruby_zip_zeek_modbus_read_write_multiple_registers" - init => "$zeek_modbus_read_write_multiple_registers_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'unit_id', 'func', 'network_direction', 'write_start_address', 'write_registers', 'read_start_address', 'read_quantity', 'read_registers' ]" + init => "$zeek_modbus_read_write_multiple_registers_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'unit_id', 'func', 'network_direction', 'write_start_address', 'write_registers', 'read_start_address', 'read_quantity', 'read_registers' ]" code => "event.set('[zeek_cols]', $zeek_modbus_read_write_multiple_registers_field_names.zip(event.get('[message]')).to_h)" } } @@ -2549,7 +2549,7 @@ filter { id => "dissect_zeek_s7comm" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][rosctr_code]} %{[zeek_cols][rosctr_name]} %{[zeek_cols][pdu_reference]} %{[zeek_cols][function_code]} %{[zeek_cols][function_name]} %{[zeek_cols][subfunction_code]} %{[zeek_cols][subfunction_name]} %{[zeek_cols][error_class]} %{[zeek_cols][error_code]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][rosctr_code]} %{[zeek_cols][rosctr_name]} %{[zeek_cols][pdu_reference]} %{[zeek_cols][function_code]} %{[zeek_cols][function_name]} %{[zeek_cols][subfunction_code]} %{[zeek_cols][subfunction_name]} %{[zeek_cols][error_class]} %{[zeek_cols][error_code]}" } } if ("_dissectfailure" in [tags]) { @@ -2560,7 +2560,7 @@ filter { } ruby { id => "ruby_zip_zeek_s7comm" - init => "$zeek_s7comm_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'rosctr_code', 'rosctr_name', 'pdu_reference', 'function_code', 'function_name', 'subfunction_code', 'subfunction_name', 'error_class', 'error_code' ]" + init => "$zeek_s7comm_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'rosctr_code', 'rosctr_name', 'pdu_reference', 'function_code', 'function_name', 'subfunction_code', 'subfunction_name', 'error_class', 'error_code' ]" code => "event.set('[zeek_cols]', $zeek_s7comm_field_names.zip(event.get('[message]')).to_h)" } } @@ -2583,7 +2583,7 @@ filter { id => "dissect_zeek_s7comm_plus" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][version]} %{[zeek_cols][opcode]} %{[zeek_cols][opcode_name]} %{[zeek_cols][function_code]} %{[zeek_cols][function_name]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][version]} %{[zeek_cols][opcode]} %{[zeek_cols][opcode_name]} %{[zeek_cols][function_code]} %{[zeek_cols][function_name]}" } } if ("_dissectfailure" in [tags]) { @@ -2594,7 +2594,7 @@ filter { } ruby { id => "ruby_zip_zeek_s7comm_plus" - init => "$zeek_s7comm_plus_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'is_orig', 'version', 'opcode', 'opcode_name', 'function_code', 'function_name' ]" + init => "$zeek_s7comm_plus_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'version', 'opcode', 'opcode_name', 'function_code', 'function_name' ]" code => "event.set('[zeek_cols]', $zeek_s7comm_plus_field_names.zip(event.get('[message]')).to_h)" } } @@ -2617,7 +2617,7 @@ filter { id => "dissect_zeek_s7comm_read_szl" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][pdu_reference]} %{[zeek_cols][method]} %{[zeek_cols][szl_id]} %{[zeek_cols][szl_id_name]} %{[zeek_cols][szl_index]} %{[zeek_cols][return_code]} %{[zeek_cols][return_code_name]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][pdu_reference]} %{[zeek_cols][method]} %{[zeek_cols][szl_id]} %{[zeek_cols][szl_id_name]} %{[zeek_cols][szl_index]} %{[zeek_cols][return_code]} %{[zeek_cols][return_code_name]}" } } if ("_dissectfailure" in [tags]) { @@ -2628,7 +2628,7 @@ filter { } ruby { id => "ruby_zip_zeek_s7comm_read_szl" - init => "$zeek_s7comm_read_szl_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'pdu_reference', 'method', 'szl_id', 'szl_id_name', 'szl_index', 'return_code', 'return_code_name' ]" + init => "$zeek_s7comm_read_szl_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'pdu_reference', 'method', 'szl_id', 'szl_id_name', 'szl_index', 'return_code', 'return_code_name' ]" code => "event.set('[zeek_cols]', $zeek_s7comm_read_szl_field_names.zip(event.get('[message]')).to_h)" } } @@ -2651,7 +2651,7 @@ filter { id => "dissect_zeek_s7comm_upload_download" # zeek's default delimiter is a literal tab, MAKE SURE YOUR EDITOR DOESN'T SCREW IT UP mapping => { - "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][rosctr_name]} %{[zeek_cols][pdu_reference]} %{[zeek_cols][function_name]} %{[zeek_cols][function_status]} %{[zeek_cols][session_id]} %{[zeek_cols][blocklength]} %{[zeek_cols][filename]} %{[zeek_cols][block_type]} %{[zeek_cols][block_number]} %{[zeek_cols][destination_filesystem]}" + "[message]" => "%{[zeek_cols][ts]} %{[zeek_cols][uid]} %{[zeek_cols][drop_orig_h]} %{[zeek_cols][drop_orig_p]} %{[zeek_cols][drop_resp_h]} %{[zeek_cols][drop_resp_p]} %{[zeek_cols][is_orig]} %{[zeek_cols][orig_h]} %{[zeek_cols][orig_p]} %{[zeek_cols][resp_h]} %{[zeek_cols][resp_p]} %{[zeek_cols][rosctr_name]} %{[zeek_cols][pdu_reference]} %{[zeek_cols][function_name]} %{[zeek_cols][function_status]} %{[zeek_cols][session_id]} %{[zeek_cols][blocklength]} %{[zeek_cols][filename]} %{[zeek_cols][block_type]} %{[zeek_cols][block_number]} %{[zeek_cols][destination_filesystem]}" } } if ("_dissectfailure" in [tags]) { @@ -2662,7 +2662,7 @@ filter { } ruby { id => "ruby_zip_zeek_s7comm_upload_download" - init => "$zeek_s7comm_upload_download_field_names = [ 'ts', 'uid', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'rosctr_name', 'pdu_reference', 'function_name', 'function_status', 'session_id', 'blocklength', 'filename', 'block_type', 'block_number', 'destination_filesystem' ]" + init => "$zeek_s7comm_upload_download_field_names = [ 'ts', 'uid', 'drop_orig_h', 'drop_orig_p', 'drop_resp_h', 'drop_resp_p', 'is_orig', 'orig_h', 'orig_p', 'resp_h', 'resp_p', 'rosctr_name', 'pdu_reference', 'function_name', 'function_status', 'session_id', 'blocklength', 'filename', 'block_type', 'block_number', 'destination_filesystem' ]" code => "event.set('[zeek_cols]', $zeek_s7comm_upload_download_field_names.zip(event.get('[message]')).to_h)" } } diff --git a/logstash/pipelines/zeek/12_zeek_mutate.conf b/logstash/pipelines/zeek/12_zeek_mutate.conf index ad3bc4873..1ae4e31cb 100644 --- a/logstash/pipelines/zeek/12_zeek_mutate.conf +++ b/logstash/pipelines/zeek/12_zeek_mutate.conf @@ -41,6 +41,15 @@ filter { rename => { "[zeek][%{[log_source]}][community_id]" => "[network][community_id]" } } + # we'll just save the "true" source and destination fields. + # see, for example, https://github.com/cisagov/icsnpp-bacnet#source-and-destination-fields + mutate { id => "mutate_remove_zeek_common_fields" + remove_field => [ + "[zeek][%{[log_source]}][drop_orig_h]", + "[zeek][%{[log_source]}][drop_orig_p]", + "[zeek][%{[log_source]}][drop_resp_h]", + "[zeek][%{[log_source]}][drop_resp_p]" ] } + # create a repeatable fingerprint for document ID fingerprint { id => "fingerprint_zeek_event_hash" diff --git a/logstash/ruby/mac_lookup.rb b/logstash/ruby/mac_lookup.rb index 9af301f68..ae2ec0687 100644 --- a/logstash/ruby/mac_lookup.rb +++ b/logstash/ruby/mac_lookup.rb @@ -3,11 +3,13 @@ def concurrency end def register(params) + require 'psych' + @source = params["source"] @target = params["target"] if File.exist?(params["map_path"]) @macarray = Array.new - YAML.safe_load(File.read(params["map_path"])).each do |mac| + psych_load_yaml(params["map_path"]).each do |mac| @macarray.push([mac_string_to_integer(mac['low']), mac_string_to_integer(mac['high']), mac['name']]) end # Array.bsearch only works on a sorted array @@ -57,6 +59,18 @@ def mac_string_to_integer(string) string.tr('.:-','').to_i(16) end +def psych_load_yaml(filename) + parser = Psych::Parser.new(Psych::TreeBuilder.new) + parser.code_point_limit = 64*1024*1024 + parser.parse(IO.read(filename, :mode => 'r:bom|utf-8')) + yaml_obj = Psych::Visitors::ToRuby.create().accept(parser.handler.root) + if yaml_obj.is_a?(Array) && (yaml_obj.length() == 1) + yaml_obj.first + else + yaml_obj + end +end + ############################################################################### # tests diff --git a/logstash/ruby/netbox_enrich.rb b/logstash/ruby/netbox_enrich.rb index 3cea6ec06..4d0c9c608 100644 --- a/logstash/ruby/netbox_enrich.rb +++ b/logstash/ruby/netbox_enrich.rb @@ -9,6 +9,7 @@ def register(params) require 'ipaddr' require 'json' require 'lru_redux' + require 'psych' require 'stringex_lite' # global enable/disable for this plugin based on environment variable(s) @@ -116,7 +117,7 @@ def register(params) _vendor_oui_map_path = params.fetch("vendor_oui_map_path", "/etc/vendor_macs.yaml") if File.exist?(_vendor_oui_map_path) @macarray = Array.new - YAML.safe_load(File.read(_vendor_oui_map_path)).each do |mac| + psych_load_yaml(_vendor_oui_map_path).each do |mac| @macarray.push([mac_string_to_integer(mac['low']), mac_string_to_integer(mac['high']), mac['name']]) end # Array.bsearch only works on a sorted array @@ -129,7 +130,7 @@ def register(params) _vm_oui_map_path = params.fetch("vm_oui_map_path", "/etc/vm_macs.yaml") if File.exist?(_vm_oui_map_path) @vm_namesarray = Set.new - YAML.safe_load(File.read(_vm_oui_map_path)).each do |mac| + psych_load_yaml(_vm_oui_map_path).each do |mac| @vm_namesarray.add(mac['name'].to_s.downcase) end else @@ -164,7 +165,7 @@ def register(params) _autopopulate_fuzzy_threshold_str = ENV[_autopopulate_fuzzy_threshold_str_env] end if _autopopulate_fuzzy_threshold_str.nil? || _autopopulate_fuzzy_threshold_str.empty? - @autopopulate_fuzzy_threshold = 0.75 + @autopopulate_fuzzy_threshold = 0.80 else @autopopulate_fuzzy_threshold = _autopopulate_fuzzy_threshold_str.to_f end @@ -724,6 +725,18 @@ def mac_string_to_integer(string) string.tr('.:-','').to_i(16) end +def psych_load_yaml(filename) + parser = Psych::Parser.new(Psych::TreeBuilder.new) + parser.code_point_limit = 64*1024*1024 + parser.parse(IO.read(filename, :mode => 'r:bom|utf-8')) + yaml_obj = Psych::Visitors::ToRuby.create().accept(parser.handler.root) + if yaml_obj.is_a?(Array) && (yaml_obj.length() == 1) + yaml_obj.first + else + yaml_obj + end +end + def collect_values(hashes) # https://stackoverflow.com/q/5490952 hashes.reduce({}){ |h, pairs| pairs.each { |k,v| (h[k] ||= []) << v}; h } diff --git a/malcolm-iso/build.sh b/malcolm-iso/build.sh index b16f38132..44f795369 100755 --- a/malcolm-iso/build.sh +++ b/malcolm-iso/build.sh @@ -3,7 +3,7 @@ IMAGE_NAME=malcolm IMAGE_PUBLISHER=idaholab IMAGE_VERSION=1.0.0 -IMAGE_DISTRIBUTION=bullseye +IMAGE_DISTRIBUTION=bookworm BUILD_ERROR_CODE=1 @@ -70,14 +70,8 @@ if [ -d "$WORKDIR" ]; then chown -R root:root * - # if fasttrack.debian.net is down, use mirror.linux.pizza instead - FASTTRACK_MIRROR=$(( curl -fsSL -o /dev/null "https://fasttrack.debian.net/debian-fasttrack/" 2>/dev/null && echo "fasttrack.debian.net" ) || ( curl -fsSL -o /dev/null "https://mirror.linux.pizza/debian-fasttrack/" 2>/dev/null && echo "mirror.linux.pizza" )) - if [[ -n "$FASTTRACK_MIRROR" ]] && [[ "$FASTTRACK_MIRROR" != "fasttrack.debian.net" ]]; then - sed -i "s/fasttrack.debian.net/$FASTTRACK_MIRROR/g" ./config/archives/fasttrack.list.* - fi - # configure installation options - YML_IMAGE_VERSION="$(grep -P "^\s+image:\s*malcolm" "$SCRIPT_PATH"/../docker-compose-standalone.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" + YML_IMAGE_VERSION="$(grep -P "^\s+image:.*/malcolm/" "$SCRIPT_PATH"/../docker-compose-standalone.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" [[ -n $YML_IMAGE_VERSION ]] && IMAGE_VERSION="$YML_IMAGE_VERSION" sed -i "s@^\(title-text[[:space:]]*:\).*@\1 \"Malcolm $IMAGE_VERSION $(date +'%Y-%m-%d %H:%M:%S')\"@g" ./config/bootloaders/grub-pc/live-theme/theme.txt cp ./config/includes.binary/install/preseed_multipar.cfg ./config/includes.binary/install/preseed_multipar_crypto.cfg @@ -108,25 +102,27 @@ if [ -d "$WORKDIR" ]; then mkdir -p "$MALCOLM_DEST_DIR/netbox/media/" mkdir -p "$MALCOLM_DEST_DIR/netbox/postgres/" mkdir -p "$MALCOLM_DEST_DIR/netbox/redis/" + mkdir -p "$MALCOLM_DEST_DIR/netbox/preload/" mkdir -p "$MALCOLM_DEST_DIR/nginx/ca-trust/" mkdir -p "$MALCOLM_DEST_DIR/nginx/certs/" mkdir -p "$MALCOLM_DEST_DIR/kubernetes/" mkdir -p "$MALCOLM_DEST_DIR/opensearch-backup/" mkdir -p "$MALCOLM_DEST_DIR/opensearch/nodes/" mkdir -p "$MALCOLM_DEST_DIR/pcap/processed/" - mkdir -p "$MALCOLM_DEST_DIR/pcap/upload/" + mkdir -p "$MALCOLM_DEST_DIR/pcap/upload/tmp/spool/" + mkdir -p "$MALCOLM_DEST_DIR/pcap/upload/variants/" mkdir -p "$MALCOLM_DEST_DIR/scripts/" - mkdir -p "$MALCOLM_DEST_DIR/suricata-logs/live" + mkdir -p "$MALCOLM_DEST_DIR/suricata-logs/live/" mkdir -p "$MALCOLM_DEST_DIR/suricata/rules/" mkdir -p "$MALCOLM_DEST_DIR/yara/rules/" mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/current/" - mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/extract_files/preserved" - mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/extract_files/quarantine" + mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/extract_files/preserved/" + mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/extract_files/quarantine/" mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/live/" mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/processed/" mkdir -p "$MALCOLM_DEST_DIR/zeek-logs/upload/" - mkdir -p "$MALCOLM_DEST_DIR/zeek/intel/MISP" - mkdir -p "$MALCOLM_DEST_DIR/zeek/intel/STIX" + mkdir -p "$MALCOLM_DEST_DIR/zeek/intel/MISP/" + mkdir -p "$MALCOLM_DEST_DIR/zeek/intel/STIX/" cp ./docker-compose-standalone.yml "$MALCOLM_DEST_DIR/docker-compose.yml" cp ./net-map.json "$MALCOLM_DEST_DIR/" cp ./scripts/install.py "$MALCOLM_DEST_DIR/scripts/" @@ -152,6 +148,7 @@ if [ -d "$WORKDIR" ]; then cp ./logstash/certs/*.conf "$MALCOLM_DEST_DIR/logstash/certs/" cp ./logstash/maps/malcolm_severity.yaml "$MALCOLM_DEST_DIR/logstash/maps/" cp -r ./netbox/config/ "$MALCOLM_DEST_DIR/netbox/" + cp ./netbox/preload/*.yml "$MALCOLM_DEST_DIR/netbox/preload/" touch "$MALCOLM_DEST_DIR"/firstrun popd >/dev/null 2>&1 @@ -178,11 +175,6 @@ if [ -d "$WORKDIR" ]; then cat "$SCRIPT_PATH/shared/environment.chroot" >> ./config/environment.chroot echo "PYTHONDONTWRITEBYTECODE=1" >> ./config/environment.chroot - # clone and build aide .deb package in its own clean environment (rather than in hooks/) - bash "$SCRIPT_PATH/../shared/aide/build-docker-image.sh" - docker run --rm -v "$SCRIPT_PATH"/../shared/aide:/build aide-build:latest -o /build - mv "$SCRIPT_PATH/../shared/aide"/*.deb ./config/packages.chroot/ - # copy shared scripts and some branding stuff mkdir -p ./config/includes.chroot/usr/local/bin/ rsync -a "$SCRIPT_PATH/../shared/bin/" ./config/includes.chroot/usr/local/bin/ @@ -209,8 +201,8 @@ if [ -d "$WORKDIR" ]; then --apt-secure true \ --apt-source-archives false \ --architectures amd64 \ - --archive-areas 'main contrib non-free' \ - --backports true \ + --archive-areas 'main contrib non-free non-free-firmware' \ + --backports false \ --binary-images iso-hybrid \ --bootappend-install "auto=true locales=en_US.UTF-8 keyboard-layouts=us" \ --bootappend-live "boot=live components username=analyst nosplash random.trust_cpu=on elevator=deadline cgroup_enable=memory swapaccount=1 cgroup.memory=nokmem systemd.unified_cgroup_hierarchy=1" \ @@ -218,7 +210,7 @@ if [ -d "$WORKDIR" ]; then --debian-installer live \ --debian-installer-distribution $IMAGE_DISTRIBUTION \ --debian-installer-gui false \ - --debootstrap-options "--include=apt-transport-https,bc,ca-certificates,gnupg,debian-archive-keyring,fasttrack-archive-keyring,jq,openssl --no-merged-usr" \ + --debootstrap-options "--include=apt-transport-https,bc,ca-certificates,gnupg,debian-archive-keyring,jq,openssl --no-merged-usr" \ --distribution $IMAGE_DISTRIBUTION \ --image-name "$IMAGE_NAME" \ --iso-application "$IMAGE_NAME" \ @@ -227,7 +219,7 @@ if [ -d "$WORKDIR" ]; then --linux-flavours "amd64:amd64" \ --linux-packages "linux-image linux-headers" \ --memtest none \ - --parent-archive-areas 'main contrib non-free' \ + --parent-archive-areas 'main contrib non-free non-free-firmware' \ --parent-debian-installer-distribution $IMAGE_DISTRIBUTION \ --parent-distribution $IMAGE_DISTRIBUTION \ --security true \ diff --git a/malcolm-iso/config/archives/docker.list.binary b/malcolm-iso/config/archives/docker.list.binary index dfe8f16e8..f36f764bc 100644 --- a/malcolm-iso/config/archives/docker.list.binary +++ b/malcolm-iso/config/archives/docker.list.binary @@ -1,2 +1,2 @@ -deb [arch=amd64] https://download.docker.com/linux/debian bullseye stable +deb [arch=amd64] https://download.docker.com/linux/debian bookworm stable diff --git a/malcolm-iso/config/archives/docker.list.chroot b/malcolm-iso/config/archives/docker.list.chroot index dfe8f16e8..f36f764bc 100644 --- a/malcolm-iso/config/archives/docker.list.chroot +++ b/malcolm-iso/config/archives/docker.list.chroot @@ -1,2 +1,2 @@ -deb [arch=amd64] https://download.docker.com/linux/debian bullseye stable +deb [arch=amd64] https://download.docker.com/linux/debian bookworm stable diff --git a/malcolm-iso/config/archives/fasttrack.list.binary b/malcolm-iso/config/archives/fasttrack.list.binary deleted file mode 100644 index f2126f979..000000000 --- a/malcolm-iso/config/archives/fasttrack.list.binary +++ /dev/null @@ -1,2 +0,0 @@ -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-fasttrack main contrib non-free -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-backports-staging main contrib non-free diff --git a/malcolm-iso/config/archives/fasttrack.list.chroot b/malcolm-iso/config/archives/fasttrack.list.chroot deleted file mode 100644 index f2126f979..000000000 --- a/malcolm-iso/config/archives/fasttrack.list.chroot +++ /dev/null @@ -1,2 +0,0 @@ -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-fasttrack main contrib non-free -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-backports-staging main contrib non-free diff --git a/malcolm-iso/config/archives/fluentbit.list.binary b/malcolm-iso/config/archives/fluentbit.list.binary index 2eeb67a7c..7bbcff079 100644 --- a/malcolm-iso/config/archives/fluentbit.list.binary +++ b/malcolm-iso/config/archives/fluentbit.list.binary @@ -1 +1 @@ -deb https://packages.fluentbit.io/debian/bullseye bullseye main \ No newline at end of file +deb https://packages.fluentbit.io/debian/bookworm bookworm main \ No newline at end of file diff --git a/malcolm-iso/config/archives/fluentbit.list.chroot b/malcolm-iso/config/archives/fluentbit.list.chroot index 2eeb67a7c..7bbcff079 100644 --- a/malcolm-iso/config/archives/fluentbit.list.chroot +++ b/malcolm-iso/config/archives/fluentbit.list.chroot @@ -1 +1 @@ -deb https://packages.fluentbit.io/debian/bullseye bullseye main \ No newline at end of file +deb https://packages.fluentbit.io/debian/bookworm bookworm main \ No newline at end of file diff --git a/malcolm-iso/config/hooks/normal/0169-pip-installs.hook.chroot b/malcolm-iso/config/hooks/normal/0169-pip-installs.hook.chroot index 605e90427..f59667626 100755 --- a/malcolm-iso/config/hooks/normal/0169-pip-installs.hook.chroot +++ b/malcolm-iso/config/hooks/normal/0169-pip-installs.hook.chroot @@ -4,7 +4,7 @@ export LC_ALL=C.UTF-8 export LANG=C.UTF-8 # python 3 -pip3 install --no-compile --no-cache-dir --force-reinstall --upgrade \ +pip3 install --break-system-packages --no-compile --no-cache-dir --force-reinstall --upgrade \ debinterface \ kubernetes \ python-dotenv \ diff --git a/malcolm-iso/config/hooks/normal/0910-agg-build.hook.chroot b/malcolm-iso/config/hooks/normal/0910-agg-build.hook.chroot index 02879baec..7f04f501d 100755 --- a/malcolm-iso/config/hooks/normal/0910-agg-build.hook.chroot +++ b/malcolm-iso/config/hooks/normal/0910-agg-build.hook.chroot @@ -1,9 +1,6 @@ #!/bin/bash -apt-get -qqy update - -# aide itself was built from github master branch (for JSON output) -apt-get install --no-install-recommends -y -q aide-common +# tweak some stuff for aide chmod a-x /etc/cron.daily/aide chattr +i /etc/cron.daily/aide mkdir -p /etc/aide/aide.conf.d /var/lib/aide @@ -104,18 +101,6 @@ chmod 755 ./croc chown root:root ./croc ### -# step -RELEASE_URL="https://api.github.com/repos/smallstep/cli/releases/latest" -RELEASE_FILE_REGEX="_linux_.+amd64\\\.tar\\\.gz$" -cd /tmp -mkdir -p ./step -curl "${GITHUB_API_CURL_ARGS[@]}" "$(curl "${GITHUB_API_CURL_ARGS[@]}" "$(curl "${GITHUB_API_CURL_ARGS[@]}" "$RELEASE_URL" | jq '.assets_url' | tr -d '"')" | jq ".[] | select(.browser_download_url|test(\"$RELEASE_FILE_REGEX\")) | .browser_download_url" | tr -d '"')" | tar xzf - -C ./step --strip-components 1 -mv ./step/bin/step /usr/local/bin/step -chmod 755 /usr/local/bin/step -chown root:root /usr/local/bin/step -rm -rf /tmp/step* -### - # stern RELEASE_URL="https://api.github.com/repos/stern/stern/releases/latest" RELEASE_FILE_REGEX="_linux_amd64\\\.tar\\\.gz$" diff --git a/malcolm-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot b/malcolm-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot index caaabeb8c..99d3535c4 100755 --- a/malcolm-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot +++ b/malcolm-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot @@ -1,7 +1,7 @@ #!/bin/bash # remove development packages -apt-get -y --purge remove build-essential $(dpkg --get-selections | grep -v deinstall$ | cut -f1 | grep -P -- '-dev(:\w+)?$' | grep -Pv -- '^(dpkg|libgcc)') || true +apt-get -y --purge remove build-essential sparse $(dpkg --get-selections | grep -v deinstall$ | cut -f1 | grep -P -- '-dev(:\w+)?$' | grep -Pv -- '^(dpkg|libgcc)') || true # remove unwanted packages apt-get -y --purge remove bluez-firmware \ @@ -11,11 +11,11 @@ apt-get -y --purge remove bluez-firmware \ gdebi* \ gdb \ firmware-netronome \ + firmware-nvidia* \ firmware-qcom-soc \ gnome-accessibility-themes \ libasound2-plugins \ libx264* \ - libx265* \ nvidia* \ pavucontrol \ poppler-data \ @@ -32,7 +32,6 @@ dpkg -l | awk '/^rc/ { print $2 }' | xargs -r -l dpkg --purge # disable automatic/initial running of some services (but don't abort if we fail) systemctl disable ctrl-alt-del.target || true -systemctl disable hddtemp.service || true systemctl disable apt-daily.service || true systemctl disable apt-daily.timer || true systemctl disable apt-daily-upgrade.timer || true diff --git a/malcolm-iso/config/hooks/normal/0992-localepurge.hook.chroot b/malcolm-iso/config/hooks/normal/0992-localepurge.hook.chroot index 777533438..08f4e6a07 100755 --- a/malcolm-iso/config/hooks/normal/0992-localepurge.hook.chroot +++ b/malcolm-iso/config/hooks/normal/0992-localepurge.hook.chroot @@ -13,8 +13,6 @@ localepurge localepurge/none_selected boolean false EOF debconf-set-selections < /tmp/localepurge.preseed rm -f /tmp/localepurge.preseed -apt-get -qqy update -apt-get -y install localepurge dpkg-reconfigure --frontend=noninteractive localepurge sed -i "s/^\(USE_DPKG\)/#\1/" /etc/locale.nopurge sed -i "s/^\(NEEDSCONFIGFIRST\)/#\1/" /etc/locale.nopurge diff --git a/malcolm-iso/config/includes.binary/install/preseed_base.cfg b/malcolm-iso/config/includes.binary/install/preseed_base.cfg index ba6dd9e87..1d18bfce4 100644 --- a/malcolm-iso/config/includes.binary/install/preseed_base.cfg +++ b/malcolm-iso/config/includes.binary/install/preseed_base.cfg @@ -32,10 +32,9 @@ d-i apt-setup/use_mirror boolean false d-i finish-install/reboot_in_progress note d-i preseed/late_command string \ - echo 'deb http://deb.debian.org/debian bullseye main contrib non-free' > /target/etc/apt/sources.list; \ - echo 'deb http://security.debian.org/debian-security bullseye-security main contrib non-free' >> /target/etc/apt/sources.list; \ - echo 'deb http://deb.debian.org/debian bullseye-updates main contrib non-free' >> /target/etc/apt/sources.list; \ - echo 'deb http://deb.debian.org/debian bullseye-backports main contrib non-free' >> /target/etc/apt/sources.list; \ + echo 'deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware' > /target/etc/apt/sources.list; \ + echo 'deb http://security.debian.org/debian-security bookworm-security main contrib non-free' >> /target/etc/apt/sources.list; \ + echo 'deb http://deb.debian.org/debian bookworm-updates main contrib non-free' >> /target/etc/apt/sources.list; \ in-target bash /usr/local/bin/agg-init.sh; \ in-target bash -c "(virt-what | grep -q vmware) || apt-get purge -y open-vm-tools-desktop"; \ in-target bash -c "(virt-what | grep -q virtualbox) || apt-get purge -y virtualbox-guest*"; \ diff --git a/malcolm-iso/config/package-lists/system.list.chroot b/malcolm-iso/config/package-lists/system.list.chroot index 8ad560c97..9525899e4 100644 --- a/malcolm-iso/config/package-lists/system.list.chroot +++ b/malcolm-iso/config/package-lists/system.list.chroot @@ -1,4 +1,6 @@ accountsservice +aide +aide-common apache2-utils apparmor apparmor-profiles @@ -35,7 +37,6 @@ dosfstools ebtables efibootmgr eject -fasttrack-archive-keyring fatresize file findutils @@ -64,7 +65,6 @@ gvfs-backends gvfs-daemons gvfs-fuse gzip -hddtemp hdparm hfsplus hfsprogs @@ -86,7 +86,7 @@ libpcre2-16-0 libpcre2-32-0 libpcre2-8-0 libssl-dev -libssl1.1 +libssl3 libykpers-1-1 libyubikey0 lm-sensors diff --git a/malcolm-iso/config/package-lists/virtualguest.list.chroot b/malcolm-iso/config/package-lists/virtualguest.list.chroot index 2c9182560..35946639a 100644 --- a/malcolm-iso/config/package-lists/virtualguest.list.chroot +++ b/malcolm-iso/config/package-lists/virtualguest.list.chroot @@ -1,5 +1,3 @@ open-vm-tools-desktop qemu-guest-agent virt-what -virtualbox-guest-utils -virtualbox-guest-x11 \ No newline at end of file diff --git a/malcolm-iso/vagrant/Vagrantfile b/malcolm-iso/vagrant/Vagrantfile index c1aef65f7..0558db616 100644 --- a/malcolm-iso/vagrant/Vagrantfile +++ b/malcolm-iso/vagrant/Vagrantfile @@ -14,7 +14,7 @@ end Vagrant.configure("2") do |config| config.vm.define "vagrant-malcolm-build" - config.vm.box = "bento/debian-11" + config.vm.box = "bento/debian-12" config.vm.network "private_network", type: "dhcp" config.ssh.config = "ssh_config" @@ -39,12 +39,9 @@ Vagrant.configure("2") do |config| config.vm.provision "shell", inline: <<-STEP1 dpkg-reconfigure debconf -f noninteractive -p critical export DEBIAN_FRONTEND=noninteractive - sed -i "s/main/main contrib non-free/g" /etc/apt/sources.list + sed -i "s/main/main contrib non-free non-free-firmware/g" /etc/apt/sources.list apt-get -qqy update - echo "deb http://httpredir.debian.org/debian/ bullseye-backports main contrib non-free" >> /etc/apt/sources.list - echo "deb-src http://httpredir.debian.org/debian/ bullseye-backports main contrib non-free" >> /etc/apt/sources.list - apt-get -qqy update - apt-get -t bullseye-backports -y install \ + apt-get -y install \ apt-transport-https \ bc \ build-essential \ diff --git a/netbox/config/plugins.py b/netbox/config/plugins.py index c0b1a1fb5..f170eef4e 100644 --- a/netbox/config/plugins.py +++ b/netbox/config/plugins.py @@ -4,7 +4,9 @@ # To learn how to build images with your required plugins # See https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins -# PLUGINS = ["netbox_bgp"] +PLUGINS = [ + 'netbox_initializers', +] # PLUGINS_CONFIG = { # "netbox_bgp": { diff --git a/netbox/device-roles-defaults.json b/netbox/device-roles-defaults.json deleted file mode 100644 index 503edd9dc..000000000 --- a/netbox/device-roles-defaults.json +++ /dev/null @@ -1,260 +0,0 @@ -{ - "device-roles": [ - { - "name": "Access point", - "description": "" - }, - { - "name": "Application server", - "description": "" - }, - { - "name": "Authentication server", - "description": "" - }, - { - "name": "BAS", - "description": "Building automation" - }, - { - "name": "BMS", - "description": "Building management" - }, - { - "name": "Bridge", - "description": "" - }, - { - "name": "CNC", - "description": "Computer numerical control" - }, - { - "name": "Camera", - "description": "" - }, - { - "name": "Cloud server", - "description": "" - }, - { - "name": "Collaboration server", - "description": "" - }, - { - "name": "DCS", - "description": "Distributed control" - }, - { - "name": "DHCP server", - "description": "Dynamic host communication protocol server" - }, - { - "name": "DNS server", - "description": "Domain name system server" - }, - { - "name": "Database server", - "description": "" - }, - { - "name": "Domain controller", - "description": "" - }, - { - "name": "EACS", - "description": "Electronic access control" - }, - { - "name": "Fax", - "description": "" - }, - { - "name": "File server", - "description": "" - }, - { - "name": "Firewall", - "description": "" - }, - { - "name": "Gateway", - "description": "" - }, - { - "name": "Gateway", - "description": "" - }, - { - "name": "HMI", - "description": "Human machine interface" - }, - { - "name": "HVAC", - "description": "Heating, ventilation and air conditioning" - }, - { - "name": "Historian", - "description": "" - }, - { - "name": "Hub", - "description": "" - }, - { - "name": "Hypervisor", - "description": "" - }, - { - "name": "IDS", - "description": "Intrusion detection system" - }, - { - "name": "IIoT", - "description": "Industrial internet of things device" - }, - { - "name": "IPS", - "description": "Intrusion prevention system" - }, - { - "name": "IoT", - "description": "Internet of things device" - }, - { - "name": "KVM", - "description": "Keyboard, video and mouse switch" - }, - { - "name": "Kiosk", - "description": "" - }, - { - "name": "Lighting", - "description": "Lighting controls" - }, - { - "name": "Load balancer", - "description": "" - }, - { - "name": "MES", - "description": "Manufacturing execution system" - }, - { - "name": "Mail server", - "description": "" - }, - { - "name": "Media server", - "description": "" - }, - { - "name": "Modem", - "description": "" - }, - { - "name": "NAS", - "description": "Network attached storage" - }, - { - "name": "NTP server", - "description": "Network time protocol server" - }, - { - "name": "Network sensor", - "description": "" - }, - { - "name": "PLC", - "description": "Programmable logic controller" - }, - { - "name": "PLM", - "description": "Product lifecycle management system" - }, - { - "name": "Photocopier", - "description": "" - }, - { - "name": "Physical sensor", - "description": "" - }, - { - "name": "Print server", - "description": "" - }, - { - "name": "Printer", - "description": "" - }, - { - "name": "Proxy server", - "description": "" - }, - { - "name": "RTU", - "description": "Remote terminal unit" - }, - { - "name": "Real-time communication server", - "description": "" - }, - { - "name": "Repeater", - "description": "" - }, - { - "name": "Router", - "description": "" - }, - { - "name": "SCADA", - "description": "Supervisory control and data acquisition" - }, - { - "name": "SIEM", - "description": "Security information and event management" - }, - { - "name": "Safety automation system", - "description": "" - }, - { - "name": "Scanner", - "description": "" - }, - { - "name": "Server", - "description": "" - }, - { - "name": "Switch", - "description": "" - }, - { - "name": "Telephony", - "description": "" - }, - { - "name": "VCS", - "description": "Version control system" - }, - { - "name": "VFD", - "description": "Variable frequency drive" - }, - { - "name": "VPN server", - "description": "Virtual private network server" - }, - { - "name": "Web server", - "description": "" - }, - { - "name": "Workstation", - "description": "" - } - ] -} diff --git a/netbox/patch/remove-news-feed.patch b/netbox/patch/remove-news-feed.patch new file mode 100644 index 000000000..45d754807 --- /dev/null +++ b/netbox/patch/remove-news-feed.patch @@ -0,0 +1,21 @@ +diff -Naur a/netbox/extras/constants.py b/netbox/extras/constants.py +--- a/netbox/extras/constants.py 2023-08-02 10:43:07.996021664 -0600 ++++ b/netbox/extras/constants.py 2023-08-02 10:47:21.220034275 -0600 +@@ -76,17 +76,6 @@ + } + }, + { +- 'widget': 'extras.RSSFeedWidget', +- 'width': 4, +- 'height': 4, +- 'title': 'NetBox News', +- 'config': { +- 'feed_url': 'http://netbox.dev/rss/', +- 'max_entries': 10, +- 'cache_timeout': 14400, +- } +- }, +- { + 'widget': 'extras.ObjectCountsWidget', + 'width': 4, + 'height': 3, diff --git a/netbox/preload/device_roles.yml b/netbox/preload/device_roles.yml new file mode 100644 index 000000000..3068b7785 --- /dev/null +++ b/netbox/preload/device_roles.yml @@ -0,0 +1,282 @@ +- name: Access point + slug: access-point + color: Pink + vm_role: true +- name: Application server + slug: application-server + color: Green + vm_role: true +- name: Authentication server + slug: authentication-server + color: Dark Green + vm_role: true +- name: BAS + slug: bas + description: Building automation + color: Amber + vm_role: true +- name: BMS + slug: bms + description: Building management + color: Amber + vm_role: true +- name: Bridge + slug: bridge + color: Pink + vm_role: true +- name: CNC + slug: cnc + description: Computer numerical control + color: Indigo + vm_role: true +- name: Camera + slug: camera + color: Amber + vm_role: true +- name: Cloud server + slug: cloud-server + color: Green + vm_role: true +- name: Collaboration server + slug: collaboration-server + color: Green + vm_role: true +- name: DCS + slug: dcs + description: Distributed control system + color: Purple + vm_role: true +- name: DHCP server + slug: dhcp-server + description: Dynamic host communication protocol server + color: Dark Green + vm_role: true +- name: DNS server + slug: dns-server + description: Domain name system server + color: Dark Green + vm_role: true +- name: Database server + slug: database-server + color: Green + vm_role: true +- name: Domain controller + slug: domain-controller + color: Dark Green + vm_role: true +- name: EACS + slug: eacs + description: Electronic access control + color: Amber + vm_role: true +- name: Fax + slug: fax + color: Cyan + vm_role: true +- name: File server + slug: file-server + color: Green + vm_role: true +- name: Firewall + slug: firewall + color: Dark Red + vm_role: true +- name: Gateway + slug: gateway + color: Pink + vm_role: true +- name: HMI + slug: hmi + description: Human machine interface + color: Purple + vm_role: true +- name: HVAC + slug: hvac + description: Heating, ventilation and air conditioning + color: Amber + vm_role: true +- name: Historian + slug: historian + color: Purple + vm_role: true +- name: Hub + slug: hub + color: Grey + vm_role: true +- name: Hypervisor + slug: hypervisor + color: Light Green + vm_role: true +- name: IDS + slug: ids + description: Intrusion detection system + color: Fuchsia + vm_role: true +- name: IIoT + slug: iiot + description: Industrial internet of things device + color: Purple + vm_role: true +- name: IPS + slug: ips + description: Intrusion prevention system + color: Fuchsia + vm_role: true +- name: IoT + slug: iot + description: Internet of things device + color: Light Blue + vm_role: true +- name: KVM + slug: kvm + description: Keyboard, video and mouse switch + color: Light Blue + vm_role: true +- name: Kiosk + slug: kiosk + color: Light Blue + vm_role: true +- name: Lighting + slug: lighting + description: Lighting controls + color: Amber + vm_role: true +- name: Load balancer + slug: load-balancer + color: Pink + vm_role: true +- name: MES + slug: mes + description: Manufacturing execution system + color: Indigo + vm_role: true +- name: Mail server + slug: mail-server + color: Green + vm_role: true +- name: Media server + slug: media-server + color: Green + vm_role: true +- name: Modem + slug: modem + color: Pink + vm_role: true +- name: NAS + slug: nas + description: Network attached storage + color: Green + vm_role: true +- name: NTP server + slug: ntp-server + description: Network time protocol server + color: Dark Green + vm_role: true +- name: Network sensor + slug: network-sensor + color: Fuchsia + vm_role: true +- name: PLC + slug: plc + description: Programmable logic controller + color: Purple + vm_role: true +- name: PLM + slug: plm + description: Product lifecycle management system + color: Indigo + vm_role: true +- name: Photocopier + slug: photocopier + color: Light Blue + vm_role: true +- name: Physical sensor + slug: physical-sensor + color: Indigo + vm_role: true +- name: Print server + slug: print-server + color: Green + vm_role: true +- name: Printer + slug: printer + color: Light Blue + vm_role: true +- name: Proxy server + slug: proxy-server + color: Dark Green + vm_role: true +- name: RTU + slug: rtu + description: Remote terminal unit + color: Purple + vm_role: true +- name: Real-time communication server + slug: real-time-communication-server + color: Dark Green + vm_role: true +- name: Repeater + slug: repeater + color: Pink + vm_role: true +- name: Router + slug: router + color: Pink + vm_role: true +- name: SCADA + slug: scada + description: Supervisory control and data acquisition + color: Purple + vm_role: true +- name: SIEM + slug: siem + description: Security information and event management + color: Fuchsia + vm_role: true +- name: Safety automation system + slug: safety-automation-system + color: Amber + vm_role: true +- name: Scanner + slug: scanner + color: Light Blue + vm_role: true +- name: Server + slug: server + color: Green + vm_role: true +- name: Switch + slug: switch + color: Grey + vm_role: true +- name: Telephony + slug: telephony + color: Cyan + vm_role: true +- name: VCS + slug: vcs + description: Version control system + color: Green + vm_role: true +- name: VFD + slug: vfd + description: Variable frequency drive + color: Indigo + vm_role: true +- name: VPN server + slug: vpn-server + description: Virtual private network server + color: Dark Green + vm_role: true +- name: Web server + slug: web-server + color: Green + vm_role: true +- name: Workstation + slug: workstation + color: Light Green + vm_role: true +- name: Virtual Machine Server + slug: vm-server + color: Light Green + vm_role: true diff --git a/netbox/preload/initializers.txt b/netbox/preload/initializers.txt new file mode 100644 index 000000000..6640ff227 --- /dev/null +++ b/netbox/preload/initializers.txt @@ -0,0 +1,2 @@ +Files in this directory should be formatted for import by the netbox-initializers +plugin (https://github.com/tobiasge/netbox-initializers). \ No newline at end of file diff --git a/netbox/preload/manufacturers.yml b/netbox/preload/manufacturers.yml new file mode 100644 index 000000000..f2c5337b4 --- /dev/null +++ b/netbox/preload/manufacturers.yml @@ -0,0 +1,22 @@ +- name: ABB + slug: abb +- name: Accenture + slug: accenture +- name: Emerson Electric + slug: emerson-electric +- name: General Electric + slug: general-electric +- name: Hitachi + slug: hitachi +- name: Honeywell + slug: honeywell +- name: Mitsubishi + slug: mitsubishi +- name: Oracle + slug: oracle +- name: Schneider Electric + slug: schneider-electric +- name: Yokogawa Electric + slug: yokogawa-electric +- name: Unspecified + slug: unspecified diff --git a/netbox/preload/service_templates.yml b/netbox/preload/service_templates.yml new file mode 100644 index 000000000..51c35a821 --- /dev/null +++ b/netbox/preload/service_templates.yml @@ -0,0 +1,274 @@ +- name: FTP + protocol: TCP + ports: + - 20 + - 21 +- name: SSH + protocol: TCP + ports: + - 22 +- name: Telnet + protocol: TCP + ports: + - 23 +- name: SMTP + protocol: TCP + ports: + - 25 + - 2525 +- name: DNS (UDP) + protocol: UDP + ports: + - 53 + - 853 + - 5353 +- name: DNS (TCP) + protocol: TCP + ports: + - 53 + - 853 + - 5353 +- name: DHCP + protocol: UDP + ports: + - 67 + - 68 + - 546 + - 547 +- name: HTTP + protocol: TCP + ports: + - 80 + - 8000 + - 8080 +- name: COTP and S7comm + protocol: TCP + ports: + - 102 +- name: POP3 + protocol: TCP + ports: + - 110 +- name: SFTP + protocol: TCP + ports: + - 115 +- name: NTP + protocol: TCP + ports: + - 123 +- name: Microsoft-DS (UDP) + protocol: UDP + ports: + - 135 + - 137 + - 138 + - 445 + - 3702 +- name: Microsoft-DS (TCP) + protocol: TCP + ports: + - 135 + - 139 + - 445 + - 5357 + - 5358 +- name: NetBIOS (TCP) + protocol: TCP + ports: + - 137 + - 138 + - 139 +- name: NetBIOS (UDP) + protocol: UDP + ports: + - 137 + - 138 + - 139 +- name: IMAP + protocol: TCP + ports: + - 143 +- name: SNMP + protocol: UDP + ports: + - 161 + - 162 +- name: LDAP (UDP) + protocol: UDP + ports: + - 389 + - 3268 +- name: LDAP (TCP) + protocol: TCP + ports: + - 389 + - 3268 +- name: HTTPS + protocol: TCP + ports: + - 443 + - 8443 +- name: SMTP SSL/TLS + protocol: TCP + ports: + - 465 + - 587 +- name: IPSec (UDP) + protocol: UDP + ports: + - 500 + - 4500 +- name: IPSec (TCP) + protocol: TCP + ports: + - 500 + - 4500 +- name: Modbus (UDP) + protocol: UDP + ports: + - 502 +- name: Modbus (TCP) + protocol: TCP + ports: + - 502 + - 802 +- name: Syslog (UDP) + protocol: UDP + ports: + - 514 + - 601 +- name: Syslog (TCP) + protocol: TCP + ports: + - 514 + - 601 +- name: LPD + protocol: TCP + ports: + - 515 +- name: IPP and CUPS (UDP) + protocol: UDP + ports: + - 631 +- name: IPP and CUPS (TCP) + protocol: TCP + ports: + - 631 +- name: LDAP SSL/TLS (UDP) + protocol: UDP + ports: + - 636 + - 3269 +- name: LDAP SSL/TLS (TCP) + protocol: TCP + ports: + - 636 + - 3269 +- name: rsync + protocol: TCP + ports: + - 873 +- name: FTP SSL/TLS + protocol: TCP + ports: + - 989 + - 990 +- name: Telnet SSL/TLS + protocol: TCP + ports: + - 992 +- name: IMAP SSL/TLS + protocol: TCP + ports: + - 993 +- name: POP3 SSL/TLS + protocol: TCP + ports: + - 995 +- name: OpenVPN (UDP) + protocol: UDP + ports: + - 1194 +- name: OpenVPN (TCP) + protocol: TCP + ports: + - 1194 +- name: MSSQL + protocol: TCP + ports: + - 1433 + - 1434 + - 5022 +- name: Tabular Data Stream + protocol: TCP + ports: + - 1443 +- name: CIP and EtherNet/IP (UDP) + protocol: UDP + ports: + - 2222 + - 44818 +- name: CIP and EtherNet/IP (TCP) + protocol: TCP + ports: + - 2222 + - 44818 +- name: MySQL + protocol: TCP + ports: + - 3306 +- name: RDP + protocol: TCP + ports: + - 3389 +- name: LLMNR (UDP) + protocol: UDP + ports: + - 5355 +- name: LLMNR (TCP) + protocol: TCP + ports: + - 5355 +- name: PostgreSQL + protocol: TCP + ports: + - 5432 +- name: VNC + protocol: TCP + ports: + - 5800 + - 5900 + - 5901 + - 5902 + - 5903 + - 5904 + - 5905 + - 5906 + - 5907 + - 5908 + - 5909 + - 5910 + - 6000 +- name: AppSocket and JetDirect + protocol: TCP + ports: + - 9100 + - 9101 + - 9102 +- name: Git + protocol: TCP + ports: + - 9418 +- name: BACnet (UDP) + protocol: UDP + ports: + - 47808 +- name: BACnet (TCP) + protocol: TCP + ports: + - 47808 +- name: WireGuard + protocol: UDP + ports: + - 51820 diff --git a/netbox/scripts/netbox_init.py b/netbox/scripts/netbox_init.py index 1f04b14b2..26b1dd8f9 100755 --- a/netbox/scripts/netbox_init.py +++ b/netbox/scripts/netbox_init.py @@ -14,6 +14,7 @@ import re import sys import time +import malcolm_utils from collections.abc import Iterable from datetime import datetime @@ -157,7 +158,6 @@ def main(): help="Site(s) to create", ) parser.add_argument( - '-n', '--net-map', dest='netMapFileName', type=str, @@ -165,14 +165,6 @@ def main(): required=False, help="Filename of JSON file containing network subnet/host name mapping", ) - parser.add_argument( - '--service-templates', - dest='serviceTemplateFileName', - type=str, - default=None, - required=False, - help="Filename of JSON file containing default service template definitions", - ) parser.add_argument( '--default-group', dest='defaultGroupName', @@ -209,14 +201,6 @@ def main(): required=False, help="Device role(s) to create (see also --device-roles)", ) - parser.add_argument( - '--device-roles', - dest='deviceRolesFileName', - type=str, - default=None, - required=False, - help="Filename of JSON file containing default device role definitions (see also -r/--device-role)", - ) parser.add_argument( '-y', '--device-type', @@ -227,15 +211,33 @@ def main(): required=False, help="Device types(s) to create", ) + parser.add_argument( + '-n', + '--netbox', + dest='netboxDir', + type=str, + default=os.getenv('NETBOX_PATH', '/opt/netbox'), + required=False, + help="NetBox installation directory", + ) parser.add_argument( '-l', '--library', dest='libraryDir', type=str, - default=None, + default=os.getenv('NETBOX_DEVICETYPE_LIBRARY_PATH', '/opt/netbox-devicetype-library'), required=False, help="Directory containing NetBox device type library", ) + parser.add_argument( + '-p', + '--preload', + dest='preloadDir', + type=str, + default=os.getenv('NETBOX_PRELOAD_PATH', '/opt/netbox-preload'), + required=False, + help="Directory containing netbox-initializers files to preload", + ) try: parser.error = parser.exit args = parser.parse_args() @@ -407,35 +409,10 @@ def main(): except pynetbox.RequestError as nbe: logging.warning(f"{type(nbe).__name__} processing device role \"{deviceRoleName}\": {nbe}") - except Exception as e: - logging.error(f"{type(e).__name__} processing device roles: {e}") - - try: - # load device-roles-defaults.json from file - deviceRolesJson = None - if args.deviceRolesFileName is not None and os.path.isfile(args.deviceRolesFileName): - with open(args.deviceRolesFileName) as f: - deviceRolesJson = json.load(f) - if deviceRolesJson is not None and "device-roles" in deviceRolesJson: - for role in [r for r in deviceRolesJson["device-roles"] if "name" in r]: - roleDef = { - "name": role["name"], - "slug": slugify(role["name"]), - "vm_role": True, - "color": randColor.generate()[0][1:], - } - if ("description" in role) and role["description"]: - roleDef["description"] = role["description"] - try: - nb.dcim.device_roles.create(roleDef) - except pynetbox.RequestError as nbe: - logging.warning(f"{type(nbe).__name__} processing device role \"{role['name']}\": {nbe}") - deviceRoles = {x.name: x for x in nb.dcim.device_roles.all()} logging.debug(f"Device roles (after): { {k:v.id for k, v in deviceRoles.items()} }") - except Exception as e: - logging.error(f"{type(e).__name__} processing device roles JSON \"{args.deviceRolesFileName}\": {e}") + logging.error(f"{type(e).__name__} processing device roles: {e}") # ###### DEVICE TYPES ########################################################################################## try: @@ -454,7 +431,7 @@ def main(): }, ) except pynetbox.RequestError as nbe: - logging.warning(f"{type(nbe).__model__} processing device type \"{deviceTypeModel}\": {nbe}") + logging.warning(f"{type(nbe).__name__} processing device type \"{deviceTypeModel}\": {nbe}") deviceTypes = {x.model: x for x in nb.dcim.device_types.all()} logging.debug(f"Device types (after): { {k:v.id for k, v in deviceTypes.items()} }") @@ -483,47 +460,6 @@ def main(): except Exception as e: logging.error(f"{type(e).__name__} processing sites: {e}") - # ###### Service templates ##################################################################################### - try: - # load service-template-defaults.json from file - serviceTemplatesJson = None - if args.serviceTemplateFileName is not None and os.path.isfile(args.serviceTemplateFileName): - with open(args.serviceTemplateFileName) as f: - serviceTemplatesJson = json.load(f) - if serviceTemplatesJson is not None and "service-templates" in serviceTemplatesJson: - for srv in serviceTemplatesJson["service-templates"]: - if ( - ("name" in srv) - and (srv["name"]) - and ("protocols" in srv) - and (len(srv["protocols"]) > 0) - and ("ports" in srv) - and (len(srv["ports"]) > 0) - ): - for prot in srv["protocols"]: - srvName = f"{srv['name']} ({prot.upper()})" if (len(srv["protocols"]) > 1) else srv["name"] - portInts = [p for p in srv["ports"] if isinstance(p, int)] - for portRange in [ - r.split('-') for r in srv["ports"] if isinstance(r, str) and re.match(r'^\d+-\d+$', r) - ]: - portInts = portInts + list(range(int(portRange[0]), int(portRange[1]) + 1)) - srvTempl = { - "name": srvName, - "protocol": prot.lower(), - "ports": list(set(portInts)), - } - if ("description" in srv) and srv["description"]: - srvTempl["description"] = srv["description"] - try: - nb.ipam.service_templates.create( - srvTempl, - ) - except pynetbox.RequestError as nbe: - logging.warning(f"{type(nbe).__name__} processing service template \"{srvName}\": {nbe}") - - except Exception as e: - logging.error(f"{type(e).__name__} processing service templates JSON \"{args.serviceTemplateFileName}\": {e}") - # ###### Net Map ############################################################################################### try: # load net-map.json from file @@ -700,13 +636,38 @@ def main(): except Exception as e: logging.error(f"{type(e).__name__} processing net map JSON \"{args.netMapFileName}\": {e}") + # ###### Netbox-Initializers ################################################################################### + netboxVenvPy = os.path.join(os.path.join(os.path.join(args.netboxDir, 'venv'), 'bin'), 'python') + manageScript = os.path.join(os.path.join(args.netboxDir, 'netbox'), 'manage.py') + if os.path.isfile(netboxVenvPy) and os.path.isfile(manageScript) and os.path.isdir(args.preloadDir): + try: + with malcolm_utils.pushd(os.path.dirname(manageScript)): + retcode, output = malcolm_utils.run_process( + [ + netboxVenvPy, + os.path.basename(manageScript), + "load_initializer_data", + "--path", + args.preloadDir, + ], + logger=logging, + ) + if retcode == 0: + logging.debug(f"netbox-initializers: {retcode} {output}") + else: + logging.error(f"Error processing netbox-initializers: {retcode} {output}") + + except Exception as e: + logging.error(f"{type(e).__name__} processing netbox-initializers: {e}") + # ###### Library ############################################################################################### - try: - counter = import_library(nb, args.libraryDir) - logging.debug(f"import library results: { counter }") + if os.path.isdir(args.libraryDir): + try: + counter = import_library(nb, args.libraryDir) + logging.debug(f"import library results: { counter }") - except Exception as e: - logging.error(f"{type(e).__name__} processing library: {e}") + except Exception as e: + logging.error(f"{type(e).__name__} processing library: {e}") ################################################################################################### diff --git a/netbox/service-template-defaults.json b/netbox/service-template-defaults.json deleted file mode 100644 index d9475942e..000000000 --- a/netbox/service-template-defaults.json +++ /dev/null @@ -1,486 +0,0 @@ -{ - "service-templates": [ - { - "name": "FTP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 20, - 21 - ] - }, - { - "name": "SSH", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 22 - ] - }, - { - "name": "Telnet", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 23 - ] - }, - { - "name": "SMTP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 25, - 2525 - ] - }, - { - "name": "DNS", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 53, - 853, - 5353 - ] - }, - { - "name": "DHCP", - "description": "", - "protocols": [ - "udp" - ], - "ports": [ - 67, - 68, - 546, - 547 - ] - }, - { - "name": "HTTP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 80, - 8000, - 8080 - ] - }, - { - "name": "COTP and S7comm", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 102 - ] - }, - { - "name": "POP3", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 110 - ] - }, - { - "name": "SFTP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 115 - ] - }, - { - "name": "NTP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 123 - ] - }, - { - "name": "Microsoft-DS (UDP)", - "description": "", - "protocols": [ - "udp" - ], - "ports": [ - 135, - 137, - 138, - 445, - 3702 - ] - }, - { - "name": "Microsoft-DS (TCP)", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 135, - 139, - 445, - 5357, - 5358 - ] - }, - { - "name": "NetBIOS", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - "137-139" - ] - }, - { - "name": "IMAP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 143 - ] - }, - { - "name": "SNMP", - "description": "", - "protocols": [ - "udp" - ], - "ports": [ - 161, - 162 - ] - }, - { - "name": "LDAP", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 389, - 3268 - ] - }, - { - "name": "HTTPS", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 443, - 8443 - ] - }, - { - "name": "SMTP SSL/TLS", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 465, - 587 - ] - }, - { - "name": "IPSec", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 500, - 4500 - ] - }, - { - "name": "Modbus", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 502 - ] - }, - { - "name": "Syslog", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 514, - 601 - ] - }, - { - "name": "LPD", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 515 - ] - }, - { - "name": "IPP and CUPS", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 631 - ] - }, - { - "name": "LDAP SSL/TLS", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 636, - 3269 - ] - }, - { - "name": "Modbus/TCP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 802 - ] - }, - { - "name": "rsync", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 873 - ] - }, - { - "name": "FTP SSL/TLS", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 989, - 990 - ] - }, - { - "name": "Telnet SSL/TLS", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 992 - ] - }, - { - "name": "IMAP SSL/TLS", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 993 - ] - }, - { - "name": "POP3 SSL/TLS", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 995 - ] - }, - { - "name": "OpenVPN", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 1194 - ] - }, - { - "name": "MSSQL", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 1433, - 1434, - 5022 - ] - }, - { - "name": "Tabular Data Stream", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 1443 - ] - }, - { - "name": "CIP and EtherNet/IP", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 2222, - 44818 - ] - }, - { - "name": "MySQL", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 3306 - ] - }, - { - "name": "RDP", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 3389 - ] - }, - { - "name": "LLMNR", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 5355 - ] - }, - { - "name": "PostgreSQL", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 5432 - ] - }, - { - "name": "VNC", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 5800, - "5900-5910", - 6000 - ] - }, - { - "name": "AppSocket and JetDirect", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - "9100-9102" - ] - }, - { - "name": "Git", - "description": "", - "protocols": [ - "tcp" - ], - "ports": [ - 9418 - ] - }, - { - "name": "BACnet", - "description": "", - "protocols": [ - "tcp", - "udp" - ], - "ports": [ - 47808 - ] - }, - { - "name": "WireGuard", - "description": "", - "protocols": [ - "udp" - ], - "ports": [ - 51820 - ] - } - ] -} diff --git a/netbox/supervisord.conf b/netbox/supervisord.conf index d7e1b8e47..ce5980afb 100644 --- a/netbox/supervisord.conf +++ b/netbox/supervisord.conf @@ -39,8 +39,6 @@ command=/opt/netbox/venv/bin/python /usr/local/bin/netbox_init.py --token "%(ENV_SUPERUSER_API_TOKEN)s" --net-map /usr/local/share/net-map.json --library "%(ENV_NETBOX_DEVICETYPE_LIBRARY_PATH)s" - --service-templates /etc/service-template-defaults.json - --device-roles /etc/device-roles-defaults.json autostart=true autorestart=false startsecs=0 diff --git a/pcap-monitor/scripts/watch-pcap-uploads-folder.py b/pcap-monitor/scripts/watch-pcap-uploads-folder.py index afe8699b6..dbc9a7fa7 100755 --- a/pcap-monitor/scripts/watch-pcap-uploads-folder.py +++ b/pcap-monitor/scripts/watch-pcap-uploads-folder.py @@ -115,6 +115,17 @@ def main(): type=str, required=False, ) + parser.add_argument( + '--recursive', + dest='recursiveAll', + help="Monitor all directories underneath --directory", + metavar='true|false', + type=str2bool, + nargs='?', + const=True, + default=False, + required=False, + ) parser.add_argument( '-p', '--polling', @@ -244,6 +255,7 @@ def main(): watch_common.WatchAndProcessDirectory( watchDirs, args.polling, + args.recursiveAll, file_processor, { "logger": logging, diff --git a/pcap/upload/tmp/.gitignore b/pcap/upload/tmp/.gitignore new file mode 100644 index 000000000..a5baada18 --- /dev/null +++ b/pcap/upload/tmp/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore + diff --git a/pcap/upload/variants/.gitignore b/pcap/upload/variants/.gitignore new file mode 100644 index 000000000..a5baada18 --- /dev/null +++ b/pcap/upload/variants/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore + diff --git a/scripts/build.sh b/scripts/build.sh index 751bc78b1..e3c5635e3 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -93,7 +93,7 @@ fi # we're going to do some validation that some things got pulled/built correctly FILES_IN_IMAGES=( "/usr/share/filebeat/filebeat.yml;filebeat-oss" - "/var/www/upload/js/jquery.fileupload.js;file-upload" + "/var/www/upload/filepond/dist/filepond.js;file-upload" "/opt/freq_server/freq_server.py;freq" "/var/www/htadmin/htadmin.php;htadmin" "/etc/ip_protocol_name_to_number.yaml;logstash" diff --git a/scripts/control.py b/scripts/control.py index 73401cbc5..9f75030ee 100755 --- a/scripts/control.py +++ b/scripts/control.py @@ -827,7 +827,13 @@ def stop(wipe=False): BoundPath("opensearch", "/usr/share/opensearch/data", True, ["nodes"], None), BoundPath("pcap-monitor", "/pcap", True, ["processed", "upload"], None), BoundPath("suricata", "/var/log/suricata", True, None, ["."]), - BoundPath("upload", "/var/www/upload/server/php/chroot/files", True, None, None), + BoundPath( + "upload", + "/var/www/upload/server/php/chroot/files", + True, + [os.path.join('tmp', 'spool'), "variants"], + None, + ), BoundPath("zeek", "/zeek/extract_files", True, None, None), BoundPath("zeek", "/zeek/upload", True, None, None), BoundPath("zeek-live", "/zeek/live", True, ["spool"], None), @@ -973,7 +979,13 @@ def start(): BoundPath("opensearch", "/opt/opensearch/backup", False, None, None), BoundPath("pcap-monitor", "/pcap", False, ["processed", "upload"], None), BoundPath("suricata", "/var/log/suricata", False, ["live"], None), - BoundPath("upload", "/var/www/upload/server/php/chroot/files", False, None, None), + BoundPath( + "upload", + "/var/www/upload/server/php/chroot/files", + False, + [os.path.join('tmp', 'spool'), "variants"], + None, + ), BoundPath("zeek", "/zeek/extract_files", False, None, None), BoundPath("zeek", "/zeek/upload", False, None, None), BoundPath("zeek", "/opt/zeek/share/zeek/site/intel", False, ["MISP", "STIX"], None), diff --git a/scripts/github_image_helper.sh b/scripts/github_image_helper.sh index 9f922d03e..124a9e0e5 100755 --- a/scripts/github_image_helper.sh +++ b/scripts/github_image_helper.sh @@ -181,7 +181,7 @@ for i in "${!FUNCTIONS[@]}"; do printf "%s\t%s\n" "$IPLUS" "${FUNCTIONS[$i]}" done echo -n "Operation:" -read USER_FUNCTION_IDX +[[ -n "${1-}" ]] && USER_FUNCTION_IDX="$1" || read USER_FUNCTION_IDX if (( $USER_FUNCTION_IDX > 0 )) && (( $USER_FUNCTION_IDX <= "${#FUNCTIONS[@]}" )); then # execute one function, à la carte diff --git a/scripts/install.py b/scripts/install.py index 295e9ba39..3e3ad3cb6 100755 --- a/scripts/install.py +++ b/scripts/install.py @@ -751,7 +751,8 @@ def tweak_malcolm_runtime( indexDirFull, indexSnapshotDirFull, os.path.join(pcapDirFull, 'processed'), - os.path.join(pcapDirFull, 'upload'), + os.path.join(pcapDirFull, os.path.join('upload', os.path.join('tmp', 'spool'))), + os.path.join(pcapDirFull, os.path.join('upload', 'variants')), os.path.join(suricataLogDirFull, 'live'), os.path.join(zeekLogDirFull, 'current'), os.path.join(zeekLogDirFull, 'live'), @@ -809,16 +810,36 @@ def tweak_malcolm_runtime( autoOui = InstallerYesOrNo('Perform hardware vendor OUI lookups for MAC addresses?', default=True) autoFreq = InstallerYesOrNo('Perform string randomness scoring on some fields?', default=True) + openPortsSelection = 'unset' if self.orchMode is OrchestrationFramework.DOCKER_COMPOSE: - opensearchOpen = (not opensearchPrimaryRemote) and InstallerYesOrNo( - 'Expose OpenSearch port to external hosts?', default=expose_opensearch_default - ) - logstashOpen = InstallerYesOrNo('Expose Logstash port to external hosts?', default=expose_logstash_default) - filebeatTcpOpen = InstallerYesOrNo( - 'Expose Filebeat TCP port to external hosts?', default=expose_filebeat_default - ) + openPortsOptions = ('no', 'yes', 'customize') + while openPortsSelection not in [x[0] for x in openPortsOptions]: + openPortsSelection = InstallerChooseOne( + 'Should Malcolm accept logs and metrics from a Hedgehog Linux sensor or other forwarder?', + choices=[(x, '', x == openPortsOptions[0]) for x in openPortsOptions], + )[0] + if openPortsSelection == 'n': + opensearchOpen = False + logstashOpen = False + filebeatTcpOpen = False + elif openPortsSelection == 'y': + opensearchOpen = True + logstashOpen = True + filebeatTcpOpen = True + else: + openPortsSelection = 'c' + opensearchOpen = (not opensearchPrimaryRemote) and InstallerYesOrNo( + 'Expose OpenSearch port to external hosts?', default=expose_opensearch_default + ) + logstashOpen = InstallerYesOrNo( + 'Expose Logstash port to external hosts?', default=expose_logstash_default + ) + filebeatTcpOpen = InstallerYesOrNo( + 'Expose Filebeat TCP port to external hosts?', default=expose_filebeat_default + ) else: opensearchOpen = not opensearchPrimaryRemote + openPortsSelection = 'y' logstashOpen = True filebeatTcpOpen = True @@ -827,8 +848,10 @@ def tweak_malcolm_runtime( filebeatTcpTargetField = 'miscbeat' filebeatTcpDropField = filebeatTcpSourceField filebeatTcpTag = '_malcolm_beats' - if filebeatTcpOpen and not InstallerYesOrNo( - 'Use default field values for Filebeat TCP listener?', default=True + if ( + filebeatTcpOpen + and (openPortsSelection == 'c') + and not InstallerYesOrNo('Use default field values for Filebeat TCP listener?', default=True) ): allowedFilebeatTcpFormats = ('json', 'raw') filebeatTcpFormat = 'unset' @@ -855,8 +878,10 @@ def tweak_malcolm_runtime( default=filebeatTcpTag, ) - sftpOpen = (self.orchMode is OrchestrationFramework.DOCKER_COMPOSE) and InstallerYesOrNo( - 'Expose SFTP server (for PCAP upload) to external hosts?', default=expose_sftp_default + sftpOpen = ( + (self.orchMode is OrchestrationFramework.DOCKER_COMPOSE) + and (openPortsSelection == 'c') + and InstallerYesOrNo('Expose SFTP server (for PCAP upload) to external hosts?', default=expose_sftp_default) ) # input file extraction parameters @@ -1143,12 +1168,6 @@ def tweak_malcolm_runtime( 'NETBOX_REDIS_DISABLED', TrueOrFalseNoQuote(not netboxEnabled), ), - # enable/disable netbox (redis cache) - EnvValue( - os.path.join(args.configDir, 'netbox-common.env'), - 'NETBOX_REDIS_CACHE_DISABLED', - TrueOrFalseNoQuote(not netboxEnabled), - ), # HTTPS (nginxSSL=True) vs unencrypted HTTP (nginxSSL=False) EnvValue( os.path.join(args.configDir, 'nginx.env'), diff --git a/scripts/malcolm_appliance_packager.sh b/scripts/malcolm_appliance_packager.sh index 716f4cbcc..b4bb406a5 100755 --- a/scripts/malcolm_appliance_packager.sh +++ b/scripts/malcolm_appliance_packager.sh @@ -67,29 +67,30 @@ if mkdir "$DESTDIR"; then mkdir $VERBOSE -p "$DESTDIR/htadmin/" mkdir $VERBOSE -p "$DESTDIR/logstash/certs/" mkdir $VERBOSE -p "$DESTDIR/logstash/maps/" - mkdir $VERBOSE -p "$DESTDIR/netbox/" mkdir $VERBOSE -p "$DESTDIR/netbox/media/" mkdir $VERBOSE -p "$DESTDIR/netbox/postgres/" mkdir $VERBOSE -p "$DESTDIR/netbox/redis/" + mkdir $VERBOSE -p "$DESTDIR/netbox/preload/" mkdir $VERBOSE -p "$DESTDIR/nginx/ca-trust/" mkdir $VERBOSE -p "$DESTDIR/nginx/certs/" mkdir $VERBOSE -p "$DESTDIR/opensearch-backup/" mkdir $VERBOSE -p "$DESTDIR/opensearch/nodes/" mkdir $VERBOSE -p "$DESTDIR/pcap/processed/" - mkdir $VERBOSE -p "$DESTDIR/pcap/upload/" + mkdir $VERBOSE -p "$DESTDIR/pcap/upload/tmp/spool" + mkdir $VERBOSE -p "$DESTDIR/pcap/upload/variants/" mkdir $VERBOSE -p "$DESTDIR/config/" mkdir $VERBOSE -p "$DESTDIR/scripts/" - mkdir $VERBOSE -p "$DESTDIR/suricata-logs/live" + mkdir $VERBOSE -p "$DESTDIR/suricata-logs/live/" mkdir $VERBOSE -p "$DESTDIR/suricata/rules/" mkdir $VERBOSE -p "$DESTDIR/yara/rules/" mkdir $VERBOSE -p "$DESTDIR/zeek-logs/current/" - mkdir $VERBOSE -p "$DESTDIR/zeek-logs/extract_files/preserved" - mkdir $VERBOSE -p "$DESTDIR/zeek-logs/extract_files/quarantine" + mkdir $VERBOSE -p "$DESTDIR/zeek-logs/extract_files/preserved/" + mkdir $VERBOSE -p "$DESTDIR/zeek-logs/extract_files/quarantine/" mkdir $VERBOSE -p "$DESTDIR/zeek-logs/live/" mkdir $VERBOSE -p "$DESTDIR/zeek-logs/processed/" mkdir $VERBOSE -p "$DESTDIR/zeek-logs/upload/" - mkdir $VERBOSE -p "$DESTDIR/zeek/intel/MISP" - mkdir $VERBOSE -p "$DESTDIR/zeek/intel/STIX" + mkdir $VERBOSE -p "$DESTDIR/zeek/intel/MISP/" + mkdir $VERBOSE -p "$DESTDIR/zeek/intel/STIX/" cp $VERBOSE ./config/*.example "$DESTDIR/config/" cp $VERBOSE ./docker-compose-standalone.yml "$DESTDIR/docker-compose.yml" @@ -103,6 +104,7 @@ if mkdir "$DESTDIR"; then cp $VERBOSE ./logstash/certs/*.conf "$DESTDIR/logstash/certs/" cp $VERBOSE ./logstash/maps/malcolm_severity.yaml "$DESTDIR/logstash/maps/" cp $VERBOSE -r ./netbox/config/ "$DESTDIR/netbox/" + cp $VERBOSE ./netbox/preload/*.yml "$DESTDIR/netbox/preload/" unset CONFIRMATION echo "" @@ -130,7 +132,7 @@ if mkdir "$DESTDIR"; then ln -s ./install.py configure popd >/dev/null 2>&1 pushd .. >/dev/null 2>&1 - DESTNAME="$RUN_PATH/$(basename $DESTDIR).tar.xz" + DESTNAME="$RUN_PATH/$(basename $DESTDIR).tar.gz" README="$RUN_PATH/$(basename $DESTDIR).README.txt" cp $VERBOSE "$SCRIPT_PATH/install.py" "$RUN_PATH/" cp $VERBOSE "$SCRIPT_PATH/malcolm_common.py" "$RUN_PATH/" diff --git a/scripts/malcolm_common.py b/scripts/malcolm_common.py index b200bfa1e..3aecd642e 100644 --- a/scripts/malcolm_common.py +++ b/scripts/malcolm_common.py @@ -677,6 +677,7 @@ def DownloadToFile(url, local_filename, debug=False): | curl.+localhost.+GET\s+/api/status\s+200 | DEPRECATION | descheduling\s+job\s*id + | (relation|SELECT)\s+"django_content_type" | eshealth | esindices/list | executing\s+attempt_(transition|set_replica_count)\s+for diff --git a/scripts/malcolm_kubernetes.py b/scripts/malcolm_kubernetes.py index af95d2ba2..ebb150d0b 100644 --- a/scripts/malcolm_kubernetes.py +++ b/scripts/malcolm_kubernetes.py @@ -132,19 +132,13 @@ 'netbox-config': [ { 'secret': False, - 'path': os.path.join(MalcolmPath, os.path.join(os.path.join('netbox', 'config'), 'configuration')), + 'path': os.path.join(MalcolmPath, os.path.join('netbox', 'config')), }, ], - 'netbox-reports': [ + 'netbox-preload': [ { 'secret': False, - 'path': os.path.join(MalcolmPath, os.path.join(os.path.join('netbox', 'config'), 'reports')), - }, - ], - 'netbox-scripts': [ - { - 'secret': False, - 'path': os.path.join(MalcolmPath, os.path.join(os.path.join('netbox', 'config'), 'scripts')), + 'path': os.path.join(MalcolmPath, os.path.join('netbox', 'preload')), }, ], 'htadmin-config': [ diff --git a/scripts/third-party-logs/fluent-bit-setup.ps1 b/scripts/third-party-logs/fluent-bit-setup.ps1 index 83916837b..87a2818e2 100644 --- a/scripts/third-party-logs/fluent-bit-setup.ps1 +++ b/scripts/third-party-logs/fluent-bit-setup.ps1 @@ -9,7 +9,7 @@ ############################################################################### $fluent_bit_version = '2.1' -$fluent_bit_full_version = '2.1.6' +$fluent_bit_full_version = '2.1.8' ############################################################################### # select an item from a menu provided in an array diff --git a/sensor-iso/arkime/Dockerfile b/sensor-iso/arkime/Dockerfile index 555a31757..e2fa621d3 100644 --- a/sensor-iso/arkime/Dockerfile +++ b/sensor-iso/arkime/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. @@ -6,10 +6,10 @@ LABEL maintainer="malcolm@inl.gov" ENV DEBIAN_FRONTEND noninteractive -ENV ARKIME_VERSION "4.3.2" +ENV ARKIME_VERSION "4.4.0" ENV ARKIME_DIR "/opt/arkime" -RUN sed -i "s/bullseye main/bullseye main contrib non-free/g" /etc/apt/sources.list && \ +RUN sed -i "s/main$/main contrib non-free/g" /etc/apt/sources.list.d/debian.sources && \ apt-get -q update && \ apt-get install -q -y --no-install-recommends \ build-essential \ diff --git a/sensor-iso/build.sh b/sensor-iso/build.sh index 3438477eb..3193505be 100755 --- a/sensor-iso/build.sh +++ b/sensor-iso/build.sh @@ -3,7 +3,14 @@ IMAGE_NAME=hedgehog IMAGE_PUBLISHER=idaholab IMAGE_VERSION=1.0.0 -IMAGE_DISTRIBUTION=bullseye +IMAGE_DISTRIBUTION=bookworm + +ZEEK_DISTRO=Debian_12 +ZEEK_VER=5.2.2-0 +ZEEK_LTS= + +BEATS_VER="8.9.0" +BEATS_OSS="-oss" BUILD_ERROR_CODE=1 @@ -56,12 +63,6 @@ if [ -d "$WORKDIR" ]; then chown -R root:root * - # if fasttrack.debian.net is down, use mirror.linux.pizza instead - FASTTRACK_MIRROR=$(( curl -fsSL -o /dev/null "https://fasttrack.debian.net/debian-fasttrack/" 2>/dev/null && echo "fasttrack.debian.net" ) || ( curl -fsSL -o /dev/null "https://mirror.linux.pizza/debian-fasttrack/" 2>/dev/null && echo "mirror.linux.pizza" )) - if [[ -n "$FASTTRACK_MIRROR" ]] && [[ "$FASTTRACK_MIRROR" != "fasttrack.debian.net" ]]; then - sed -i "s/fasttrack.debian.net/$FASTTRACK_MIRROR/g" ./config/archives/fasttrack.list.* - fi - if [[ -f "$SCRIPT_PATH/shared/version.txt" ]]; then SHARED_IMAGE_VERSION="$(cat "$SCRIPT_PATH/shared/version.txt" | head -n 1)" [[ -n $SHARED_IMAGE_VERSION ]] && IMAGE_VERSION="$SHARED_IMAGE_VERSION" @@ -80,7 +81,7 @@ if [ -d "$WORKDIR" ]; then echo "#!/bin/sh" >> ./config/hooks/normal/0168-pip-sensor-interface-installs.hook.chroot echo "export LC_ALL=C.UTF-8" >> ./config/hooks/normal/0168-pip-sensor-interface-installs.hook.chroot echo "export LANG=C.UTF-8" >> ./config/hooks/normal/0168-pip-sensor-interface-installs.hook.chroot - echo -n "pip3 install --system --no-compile --no-cache-dir --force-reinstall --upgrade" >> ./config/hooks/normal/0168-pip-sensor-interface-installs.hook.chroot + echo -n "python3 -m pip install --break-system-packages --no-compile --no-cache-dir --force-reinstall --upgrade" >> ./config/hooks/normal/0168-pip-sensor-interface-installs.hook.chroot while read LINE; do echo -n -e " \\\\\n $LINE" >> ./config/hooks/normal/0168-pip-sensor-interface-installs.hook.chroot done <"$SCRIPT_PATH/interface/requirements.txt" @@ -100,8 +101,6 @@ if [ -d "$WORKDIR" ]; then echo "$PKG" >> ./config/package-lists/firmwares.list.chroot done - mkdir -p ./config/includes.chroot/opt/hedgehog_install_artifacts - # copy the interface code into place for the resultant image mkdir -p ./config/includes.chroot/opt rsync -a "$SCRIPT_PATH/interface/" ./config/includes.chroot/opt/sensor/ @@ -146,11 +145,29 @@ if [ -d "$WORKDIR" ]; then ln -r -s ./config/includes.chroot/usr/share/images/hedgehog/*wallpaper*.png ./config/includes.chroot/usr/share/images/desktop-base/ find "$SCRIPT_PATH/docs/images/hedgehog/logo/font/" -type f -name "*.ttf" -exec cp "{}" ./config/includes.chroot/usr/share/fonts/truetype/ubuntu/ \; - # clone and build aide .deb package in its own clean environment (rather than in hooks/) - bash "$SCRIPT_PATH/shared/aide/build-docker-image.sh" - docker run --rm -v "$SCRIPT_PATH"/shared/aide:/build aide-build:latest -o /build - cp "$SCRIPT_PATH/shared/aide"/*.deb ./config/includes.chroot/opt/hedgehog_install_artifacts/ - mv "$SCRIPT_PATH/shared/aide"/*.deb ./config/packages.chroot/ + # download deb files to be installed during installation + pushd ./config/packages.chroot/ >/dev/null 2>&1 + + # zeek + if [ -n "${ZEEK_LTS}" ]; then ZEEK_LTS="-lts"; fi && export ZEEK_LTS + curl -sSL --remote-name-all \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/amd64/libbroker${ZEEK_LTS}-dev_${ZEEK_VER}_amd64.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/amd64/zeek${ZEEK_LTS}-core-dev_${ZEEK_VER}_amd64.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/amd64/zeek${ZEEK_LTS}-core_${ZEEK_VER}_amd64.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/amd64/zeek${ZEEK_LTS}-spicy-dev_${ZEEK_VER}_amd64.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/amd64/zeek${ZEEK_LTS}_${ZEEK_VER}_amd64.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/amd64/zeekctl${ZEEK_LTS}_${ZEEK_VER}_amd64.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/all/zeek${ZEEK_LTS}-client_${ZEEK_VER}_all.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/all/zeek${ZEEK_LTS}-zkg_${ZEEK_VER}_all.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/all/zeek${ZEEK_LTS}-btest_${ZEEK_VER}_all.deb" \ + "https://download.zeek.org/binary-packages/${ZEEK_DISTRO}/all/zeek${ZEEK_LTS}-btest-data_${ZEEK_VER}_all.deb" + + popd >/dev/null 2>&1 + + # clone and build yara .deb package in its own clean environment (rather than in hooks/) + bash "$SCRIPT_PATH/yara/build-docker-image.sh" + docker run --rm -v "$SCRIPT_PATH"/yara:/build yara-build:latest -o /build + mv "$SCRIPT_PATH/yara"/*.deb ./config/packages.chroot/ # grab maxmind geoip database files, iana ipv4 address ranges, wireshark oui lists, etc. mkdir -p "$SCRIPT_PATH/arkime/etc" @@ -167,16 +184,19 @@ if [ -d "$WORKDIR" ]; then fi fi curl -s -S -L -o ipv4-address-space.csv "https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.csv" - curl -s -S -L -o oui.txt "https://raw.githubusercontent.com/wireshark/wireshark/master/manuf" + curl -s -S -L -o oui.txt "https://gitlab.com/wireshark/wireshark/raw/release-4.0/manuf" popd >/dev/null 2>&1 # clone and build Arkime .deb package in its own clean environment (rather than in hooks/) rsync -a "$SCRIPT_PATH"/shared/arkime_patch "$SCRIPT_PATH"/arkime/arkime_patch bash "$SCRIPT_PATH/arkime/build-docker-image.sh" docker run --rm -v "$SCRIPT_PATH"/arkime:/build arkime-build:latest -o /build - cp "$SCRIPT_PATH/arkime"/*.deb ./config/includes.chroot/opt/hedgehog_install_artifacts/ mv "$SCRIPT_PATH/arkime"/*.deb ./config/packages.chroot/ + # save these extra debs off into hedgehog_install_artifacts + mkdir -p ./config/includes.chroot/opt/hedgehog_install_artifacts + cp ./config/packages.chroot/*.deb ./config/includes.chroot/opt/hedgehog_install_artifacts/ + mkdir -p ./config/includes.installer cp -v ./config/includes.binary/install/* ./config/includes.installer/ cp -v ./config/includes.chroot/usr/local/bin/preseed_partman_determine_disk.sh ./config/includes.installer/ @@ -187,8 +207,8 @@ if [ -d "$WORKDIR" ]; then --apt-secure true \ --apt-source-archives false \ --architectures amd64 \ - --archive-areas 'main contrib non-free' \ - --backports true \ + --archive-areas 'main contrib non-free non-free-firmware' \ + --backports false \ --binary-images iso-hybrid \ --bootappend-install "auto=true locales=en_US.UTF-8 keyboard-layouts=us" \ --bootappend-live "boot=live components username=sensor nosplash random.trust_cpu=on elevator=deadline cgroup_enable=memory swapaccount=1 cgroup.memory=nokmem systemd.unified_cgroup_hierarchy=1" \ @@ -196,7 +216,7 @@ if [ -d "$WORKDIR" ]; then --debian-installer live \ --debian-installer-distribution $IMAGE_DISTRIBUTION \ --debian-installer-gui false \ - --debootstrap-options "--include=apt-transport-https,bc,ca-certificates,gnupg,debian-archive-keyring,fasttrack-archive-keyring,jq,openssl --no-merged-usr" \ + --debootstrap-options "--include=apt-transport-https,bc,ca-certificates,gnupg,debian-archive-keyring,jq,openssl --no-merged-usr" \ --distribution $IMAGE_DISTRIBUTION \ --image-name "$IMAGE_NAME" \ --iso-application "$IMAGE_NAME" \ @@ -205,7 +225,7 @@ if [ -d "$WORKDIR" ]; then --linux-flavours "amd64:amd64" \ --linux-packages "linux-image linux-headers" \ --memtest none \ - --parent-archive-areas 'main contrib non-free' \ + --parent-archive-areas 'main contrib non-free non-free-firmware' \ --parent-debian-installer-distribution $IMAGE_DISTRIBUTION \ --parent-distribution $IMAGE_DISTRIBUTION \ --security true \ diff --git a/sensor-iso/build_via_vagrant.sh b/sensor-iso/build_via_vagrant.sh index 73aa5b738..7fd7fd43d 100755 --- a/sensor-iso/build_via_vagrant.sh +++ b/sensor-iso/build_via_vagrant.sh @@ -88,7 +88,7 @@ cp -r "$SCRIPT_PATH"/../shared \ cp "$SCRIPT_PATH"/../scripts/documentation_build.sh "$SCRIPT_PATH"/docs/ cp "$SCRIPT_PATH"/../scripts/malcolm_utils.py "$SCRIPT_PATH"/shared/bin/ -YML_IMAGE_VERSION="$(grep -P "^\s+image:\s*malcolm" "$SCRIPT_PATH"/../docker-compose-standalone.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" +YML_IMAGE_VERSION="$(grep -P "^\s+image:.*/malcolm/" "$SCRIPT_PATH"/../docker-compose-standalone.yml | awk '{print $2}' | cut -d':' -f2 | uniq -c | sort -nr | awk '{print $2}' | head -n 1)" [[ -n $YML_IMAGE_VERSION ]] && echo "$YML_IMAGE_VERSION" > "$SCRIPT_PATH"/shared/version.txt [[ ${#MAXMIND_GEOIP_DB_LICENSE_KEY} -gt 1 ]] && echo "$MAXMIND_GEOIP_DB_LICENSE_KEY" > "$SCRIPT_PATH"/shared/maxmind_license.txt [[ ${#GITHUB_TOKEN} -gt 1 ]] && echo "GITHUB_TOKEN=$GITHUB_TOKEN" >> "$SCRIPT_PATH"/shared/environment.chroot diff --git a/sensor-iso/config/archives/beats.key.binary b/sensor-iso/config/archives/beats.key.binary new file mode 100644 index 000000000..1b50dcca7 --- /dev/null +++ b/sensor-iso/config/archives/beats.key.binary @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/sensor-iso/config/archives/beats.key.chroot b/sensor-iso/config/archives/beats.key.chroot new file mode 100644 index 000000000..1b50dcca7 --- /dev/null +++ b/sensor-iso/config/archives/beats.key.chroot @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/sensor-iso/config/archives/beats.list.binary b/sensor-iso/config/archives/beats.list.binary new file mode 100644 index 000000000..c469d1942 --- /dev/null +++ b/sensor-iso/config/archives/beats.list.binary @@ -0,0 +1 @@ +deb https://artifacts.elastic.co/packages/oss-8.x/apt stable main \ No newline at end of file diff --git a/sensor-iso/config/archives/beats.list.chroot b/sensor-iso/config/archives/beats.list.chroot new file mode 100644 index 000000000..65858a0c3 --- /dev/null +++ b/sensor-iso/config/archives/beats.list.chroot @@ -0,0 +1,2 @@ +deb https://artifacts.elastic.co/packages/oss-8.x/apt stable main + diff --git a/sensor-iso/config/archives/fasttrack.list.binary b/sensor-iso/config/archives/fasttrack.list.binary deleted file mode 100644 index f2126f979..000000000 --- a/sensor-iso/config/archives/fasttrack.list.binary +++ /dev/null @@ -1,2 +0,0 @@ -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-fasttrack main contrib non-free -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-backports-staging main contrib non-free diff --git a/sensor-iso/config/archives/fasttrack.list.chroot b/sensor-iso/config/archives/fasttrack.list.chroot deleted file mode 100644 index f2126f979..000000000 --- a/sensor-iso/config/archives/fasttrack.list.chroot +++ /dev/null @@ -1,2 +0,0 @@ -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-fasttrack main contrib non-free -deb https://fasttrack.debian.net/debian-fasttrack/ bullseye-backports-staging main contrib non-free diff --git a/sensor-iso/config/archives/fluentbit.list.binary b/sensor-iso/config/archives/fluentbit.list.binary index 2eeb67a7c..7bbcff079 100644 --- a/sensor-iso/config/archives/fluentbit.list.binary +++ b/sensor-iso/config/archives/fluentbit.list.binary @@ -1 +1 @@ -deb https://packages.fluentbit.io/debian/bullseye bullseye main \ No newline at end of file +deb https://packages.fluentbit.io/debian/bookworm bookworm main \ No newline at end of file diff --git a/sensor-iso/config/archives/fluentbit.list.chroot b/sensor-iso/config/archives/fluentbit.list.chroot index 2eeb67a7c..7bbcff079 100644 --- a/sensor-iso/config/archives/fluentbit.list.chroot +++ b/sensor-iso/config/archives/fluentbit.list.chroot @@ -1 +1 @@ -deb https://packages.fluentbit.io/debian/bullseye bullseye main \ No newline at end of file +deb https://packages.fluentbit.io/debian/bookworm bookworm main \ No newline at end of file diff --git a/sensor-iso/config/hooks/normal/0169-pip-installs.hook.chroot b/sensor-iso/config/hooks/normal/0169-pip-installs.hook.chroot index 952ce3fc4..fc48f7cbf 100755 --- a/sensor-iso/config/hooks/normal/0169-pip-installs.hook.chroot +++ b/sensor-iso/config/hooks/normal/0169-pip-installs.hook.chroot @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 export LANG=C.UTF-8 # python 3 -pip3 install --no-compile --no-cache-dir --force-reinstall --upgrade \ +pip3 install --break-system-packages --no-compile --no-cache-dir --force-reinstall --upgrade \ clamd \ dateparser \ debinterface \ diff --git a/sensor-iso/config/hooks/normal/0910-sensor-build.hook.chroot b/sensor-iso/config/hooks/normal/0910-sensor-build.hook.chroot index aadf77802..f1e5b234b 100755 --- a/sensor-iso/config/hooks/normal/0910-sensor-build.hook.chroot +++ b/sensor-iso/config/hooks/normal/0910-sensor-build.hook.chroot @@ -13,70 +13,24 @@ GITHUB_API_CURL_ARGS+=( -H ) GITHUB_API_CURL_ARGS+=( "Accept: application/vnd.github.v3+json" ) [[ -n "$GITHUB_TOKEN" ]] && GITHUB_API_CURL_ARGS+=( -H ) && GITHUB_API_CURL_ARGS+=( "Authorization: token $GITHUB_TOKEN" ) -ZEEK_VER=5.2.2-0 -ZEEK_LTS= ZEEK_DIR="/opt/zeek" export PATH="${ZEEK_DIR}"/bin:$PATH SURICATA_RULES_DIR="/etc/suricata/rules" -BEATS_VER="8.8.2" -BEATS_OSS="-oss" -BEATS_DEB_URL_TEMPLATE_REPLACER="XXXXX" -BEATS_DEB_URL_TEMPLATE="https://artifacts.elastic.co/downloads/beats/$BEATS_DEB_URL_TEMPLATE_REPLACER/$BEATS_DEB_URL_TEMPLATE_REPLACER$BEATS_OSS-$BEATS_VER-amd64.deb" - -NETSNIFF_RELEASE_URL="https://api.github.com/repos/netsniff-ng/netsniff-ng/releases/latest" CAPA_RELEASE_URL="https://api.github.com/repos/fireeye/capa/releases/latest" YQ_RELEASE_URL="https://api.github.com/repos/mikefarah/yq/releases/latest" SUPERCRONIC_RELEASE_URL="https://api.github.com/repos/aptible/supercronic/releases/latest" CROC_RELEASE_URL="https://api.github.com/repos/schollz/croc/releases/latest" -STEP_RELEASE_URL="https://api.github.com/repos/smallstep/cli/releases/latest" -YARA_RELEASE_URL="https://api.github.com/repos/VirusTotal/yara/releases/latest" YARA_RULES_SRC_DIR="/opt/yara-rules-src" YARA_RULES_DIR="/opt/yara-rules" mkdir -p /opt/hedgehog_install_artifacts/ -apt-get -qqy update - -# an arkime .deb is built and installed in a different context - -# Install netsniff-ng -cd /tmp -mkdir ./netsniff-ng -NETSNIFF_VER="$(curl "${GITHUB_API_CURL_ARGS[@]}" "$NETSNIFF_RELEASE_URL" | jq '.tag_name' | tr -d '"' | sed 's/^v//')" -curl "${GITHUB_API_CURL_ARGS[@]}" "$(curl "${GITHUB_API_CURL_ARGS[@]}" "$NETSNIFF_RELEASE_URL" | jq '.tarball_url' | tr -d '"')" | tar xzf - -C ./netsniff-ng --strip-components 1 -cd ./netsniff-ng -./configure --prefix=/usr --disable-geoip -make netsniff-ng -# make netsniff-ng_install -checkinstall -y -D --strip=yes --stripso=yes --install=yes --fstrans=no --pkgname="netsniff-ng" --pkgversion="$NETSNIFF_VER" --pkgarch="amd64" --pkgsource="$NETSNIFF_URL" make netsniff-ng_install -cp *.deb /opt/hedgehog_install_artifacts/ +# Download and install spicy and 3rd-party zeek plugins +mkdir -p "${CCACHE_DIR}" -cd /tmp -rm -Rf ./netsniff-ng -## - -# Download and install zeek, spicy and 3rd-party zeek plugins -mkdir -p /tmp/zeek-packages "${CCACHE_DIR}" - -# zeek -cd /tmp/zeek-packages -if [ -n "${ZEEK_LTS}" ]; then ZEEK_LTS="-lts"; fi && export ZEEK_LTS -curl -sSL --remote-name-all \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/libbroker${ZEEK_LTS}-dev_${ZEEK_VER}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}-core-dev_${ZEEK_VER}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}-core_${ZEEK_VER}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}-spicy-dev_${ZEEK_VER}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeek${ZEEK_LTS}_${ZEEK_VER}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/amd64/zeekctl${ZEEK_LTS}_${ZEEK_VER}_amd64.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-client_${ZEEK_VER}_all.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-zkg_${ZEEK_VER}_all.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-btest_${ZEEK_VER}_all.deb" \ - "https://download.zeek.org/binary-packages/Debian_11/all/zeek${ZEEK_LTS}-btest-data_${ZEEK_VER}_all.deb" -dpkg -i ./*.deb - -# plugins +# zeek plugins cd /tmp zkg autoconfig --force bash /usr/local/bin/zeek_install_plugins.sh @@ -107,12 +61,11 @@ touch /opt/sensor/sensor_ctl/zeek/intel/__load__.zeek # cleanup cd /usr/local/src tar czf zeek-$ZEEK_VER-hedgehog.tar.gz -C /opt zeek spicy -mv ./zeek-$ZEEK_VER-hedgehog.tar.gz /tmp/zeek-packages /opt/hedgehog_install_artifacts/ +mv ./zeek-$ZEEK_VER-hedgehog.tar.gz /opt/hedgehog_install_artifacts/ rm -Rf zeek-$ZEEK_VER* ### -# aide itself was built from github master branch (for JSON output) -apt-get install --no-install-recommends -y -q aide-common +# tweak some stuff for aide chmod a-x /etc/cron.daily/aide chattr +i /etc/cron.daily/aide mkdir -p /etc/aide/aide.conf.d /var/lib/aide @@ -198,9 +151,7 @@ cat << 'EOF' >> /etc/aide/aide.conf.d/00_local_excludes EOF ### -# suricata -apt-get install -t bullseye-backports --no-install-recommends -y -q suricata suricata-update - +# update suricata rules /usr/bin/suricata-update -v -D /var/lib/suricata --etopen cd "${SURICATA_RULES_DIR}"/.. @@ -208,20 +159,7 @@ tar czf suricata-rules-hedgehog.tar.gz "$(basename "${SURICATA_RULES_DIR}")" mv ./suricata-rules-hedgehog.tar.gz /opt/hedgehog_install_artifacts/ ### -# yara -cd /tmp -mkdir ./yara -YARA_VER="$(curl "${GITHUB_API_CURL_ARGS[@]}" "$YARA_RELEASE_URL" | jq '.tag_name' | tr -d '"' | sed 's/^v//')" -curl "${GITHUB_API_CURL_ARGS[@]}" "$(curl "${GITHUB_API_CURL_ARGS[@]}" "$YARA_RELEASE_URL" | jq '.tarball_url' | tr -d '"')" | tar xzf - -C ./yara --strip-components 1 -cd ./yara -./bootstrap.sh -./configure --prefix=/usr --with-crypto --enable-magic --enable-cuckoo --enable-dotnet -make -#make install -checkinstall -y -D --strip=yes --stripso=yes --install=yes --fstrans=no --pkgname="yara" --pkgversion="$YARA_VER" --pkgarch="amd64" --pkgsource="$YARA_URL" -cp *.deb /opt/hedgehog_install_artifacts/ -cd /tmp -rm -rf /yara +# update yara rules mkdir -p "${YARA_RULES_DIR}"/custom "${YARA_RULES_SRC_DIR}" /usr/local/bin/yara_rules_setup.sh -r "${YARA_RULES_SRC_DIR}" -y "${YARA_RULES_DIR}" @@ -265,34 +203,11 @@ mv ./croc /usr/local/bin/croc chmod 755 /usr/local/bin/croc ### -# step -cd /tmp -mkdir -p ./step -curl "${GITHUB_API_CURL_ARGS[@]}" "$(curl "${GITHUB_API_CURL_ARGS[@]}" "$(curl "${GITHUB_API_CURL_ARGS[@]}" "$STEP_RELEASE_URL" | jq '.assets_url' | tr -d '"')" | jq '.[] | select(.browser_download_url|test("_linux_.+amd64\\.tar\\.gz$")) | .browser_download_url' | tr -d '"')" | tar xzf - -C ./step --strip-components 1 -mv ./step/bin/step /usr/local/bin/step -chmod 755 /usr/local/bin/step -rm -rf /tmp/step* -### - # update clamav signatures freshclam --stdout --quiet --no-warnings ### -# install filebeat -for BEAT in filebeat; do - BEATS_URL="$(echo "$BEATS_DEB_URL_TEMPLATE" | sed "s/$BEATS_DEB_URL_TEMPLATE_REPLACER/$BEAT/g")" - BEATS_DEB="$BEAT-$BEATS_VER-amd64.deb" - pushd /tmp && \ - curl -f -L -o "$BEATS_DEB" "$BEATS_URL" && \ - dpkg -i "$BEATS_DEB" && \ - cp "$BEATS_DEB" /opt/hedgehog_install_artifacts/ && \ - rm -rf "$BEATS_DEB" && \ - popd -done - -### - # set up capabilities for network-related tools chown root:netdev /usr/sbin/netsniff-ng && \ setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip CAP_IPC_LOCK+eip CAP_SYS_ADMIN+eip' /usr/sbin/netsniff-ng diff --git a/sensor-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot b/sensor-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot index 1e893eed0..5464579c9 100755 --- a/sensor-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot +++ b/sensor-iso/config/hooks/normal/0990-remove-unwanted-pkg.hook.chroot @@ -4,10 +4,10 @@ # remove development packages not necessary for building dynamic Zeek plugins apt-get -y --purge remove \ - checkinstall \ gdb \ libc6-dbg \ ninja-build \ + sparse \ $(dpkg --get-selections | grep -Pv "(^(dpkg|libbroker|libc6|libcrypt|libdbus|libffi|libfl|libgcc|libmaxminddb|libncurses|libnsl|libobjc|libomp|libpcap|libssl|libstdc|libtinfo|libtirpc|libxml|libyaml|libz|linux-libc|zeek|zlib1g)|deinstall$)" | cut -f1 | grep -P -- '-dev(:\w+)?$') || true rm -rf /var/spool/ccache @@ -16,13 +16,13 @@ apt-get -y --purge remove \ bluez-firmware \ cracklib-runtime \ firmware-netronome \ + firmware-nvidia* \ firmware-qcom-soc \ gdb \ gdebi* \ gnome-accessibility-themes \ libasound2-plugins \ libx264* \ - libx265* \ lintian \ nvidia* \ network-manager* \ @@ -44,7 +44,6 @@ dpkg -l | awk '/^rc/ { print $2 }' | xargs -r -l dpkg --purge # disable automatic running of some services (but don't abort if we fail) systemctl disable supervisor.service || true systemctl disable ctrl-alt-del.target || true -systemctl disable hddtemp.service || true systemctl disable apt-daily.service || true systemctl disable apt-daily.timer || true systemctl disable apt-daily-upgrade.timer || true diff --git a/sensor-iso/config/hooks/normal/0992-localepurge.hook.chroot b/sensor-iso/config/hooks/normal/0992-localepurge.hook.chroot index bfce4cfe2..08f4e6a07 100755 --- a/sensor-iso/config/hooks/normal/0992-localepurge.hook.chroot +++ b/sensor-iso/config/hooks/normal/0992-localepurge.hook.chroot @@ -13,7 +13,6 @@ localepurge localepurge/none_selected boolean false EOF debconf-set-selections < /tmp/localepurge.preseed rm -f /tmp/localepurge.preseed -apt-get -y install localepurge dpkg-reconfigure --frontend=noninteractive localepurge sed -i "s/^\(USE_DPKG\)/#\1/" /etc/locale.nopurge sed -i "s/^\(NEEDSCONFIGFIRST\)/#\1/" /etc/locale.nopurge diff --git a/sensor-iso/config/includes.binary/install/preseed_base.cfg b/sensor-iso/config/includes.binary/install/preseed_base.cfg index 4ecdc391c..81b5ba435 100644 --- a/sensor-iso/config/includes.binary/install/preseed_base.cfg +++ b/sensor-iso/config/includes.binary/install/preseed_base.cfg @@ -43,10 +43,9 @@ d-i apt-setup/use_mirror boolean false d-i finish-install/reboot_in_progress note d-i preseed/late_command string \ - echo 'deb http://deb.debian.org/debian bullseye main contrib non-free' > /target/etc/apt/sources.list; \ - echo 'deb http://security.debian.org/debian-security bullseye-security main contrib non-free' >> /target/etc/apt/sources.list; \ - echo 'deb http://deb.debian.org/debian bullseye-updates main contrib non-free' >> /target/etc/apt/sources.list; \ - echo 'deb http://deb.debian.org/debian bullseye-backports main contrib non-free' >> /target/etc/apt/sources.list; \ + echo 'deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware' > /target/etc/apt/sources.list; \ + echo 'deb http://security.debian.org/debian-security bookworm-security main contrib non-free' >> /target/etc/apt/sources.list; \ + echo 'deb http://deb.debian.org/debian bookworm-updates main contrib non-free' >> /target/etc/apt/sources.list; \ in-target touch /etc/capture_storage_format; \ in-target bash /usr/local/bin/sensor-init.sh; \ in-target bash -c "(virt-what | grep -q vmware) || apt-get purge -y open-vm-tools-desktop"; \ diff --git a/sensor-iso/config/package-lists/build.list.chroot b/sensor-iso/config/package-lists/build.list.chroot index 7cd4a9e5a..b0ee3b83c 100644 --- a/sensor-iso/config/package-lists/build.list.chroot +++ b/sensor-iso/config/package-lists/build.list.chroot @@ -1,6 +1,5 @@ bison ccache -checkinstall cmake gcc g++ @@ -15,12 +14,13 @@ libmagic-dev libmagic1 libmaxminddb-dev libmaxminddb0 +libnl-3-dev libpcap-dev libpcap0.8 libsodium-dev libsodium23 libssl-dev -libssl1.1 +libssl3 libtcmalloc-minimal4 locales-all make diff --git a/sensor-iso/config/package-lists/desktopmanager.list.chroot b/sensor-iso/config/package-lists/desktopmanager.list.chroot index e000d5318..ad2156d0f 100644 --- a/sensor-iso/config/package-lists/desktopmanager.list.chroot +++ b/sensor-iso/config/package-lists/desktopmanager.list.chroot @@ -9,7 +9,7 @@ fonts-symbola galculator gnome-themes-extra gvfs-backends -libclamunrar9 +libclamunrar11 libnotify-bin light-locker mousepad diff --git a/sensor-iso/config/package-lists/net.list.chroot b/sensor-iso/config/package-lists/net.list.chroot index 6e75c971b..511f0fb59 100644 --- a/sensor-iso/config/package-lists/net.list.chroot +++ b/sensor-iso/config/package-lists/net.list.chroot @@ -13,6 +13,7 @@ libpcap0.8 libssh2-1 macchanger netcat-openbsd +netsniff-ng ntp openssh-client openssh-server diff --git a/sensor-iso/config/package-lists/sensor.list.chroot b/sensor-iso/config/package-lists/sensor.list.chroot index 02e62b868..7af1c3a42 100644 --- a/sensor-iso/config/package-lists/sensor.list.chroot +++ b/sensor-iso/config/package-lists/sensor.list.chroot @@ -1 +1,4 @@ -fluent-bit \ No newline at end of file +filebeat +fluent-bit +suricata +suricata-update diff --git a/sensor-iso/config/package-lists/system.list.chroot b/sensor-iso/config/package-lists/system.list.chroot index 2fe6b6fb4..b1cb7cc67 100644 --- a/sensor-iso/config/package-lists/system.list.chroot +++ b/sensor-iso/config/package-lists/system.list.chroot @@ -1,4 +1,6 @@ accountsservice +aide +aide-common apparmor apparmor-profiles apparmor-utils @@ -34,7 +36,6 @@ dosfstools ebtables efibootmgr eject -fasttrack-archive-keyring fatresize file findutils @@ -62,7 +63,6 @@ gvfs-backends gvfs-daemons gvfs-fuse gzip -hddtemp hdparm hfsplus hfsprogs @@ -73,7 +73,7 @@ javascript-common jq less libatomic1 -libffi7 +libffi8 libgtk2.0-bin libjson-perl libkrb5-3 @@ -86,6 +86,7 @@ libpam-pwquality libpcre2-16-0 libpcre2-32-0 libpcre2-8-0 +libpcre3 libtool libtsan0 libubsan1 diff --git a/sensor-iso/config/package-lists/virtualguest.list.chroot b/sensor-iso/config/package-lists/virtualguest.list.chroot index 2c9182560..35946639a 100644 --- a/sensor-iso/config/package-lists/virtualguest.list.chroot +++ b/sensor-iso/config/package-lists/virtualguest.list.chroot @@ -1,5 +1,3 @@ open-vm-tools-desktop qemu-guest-agent virt-what -virtualbox-guest-utils -virtualbox-guest-x11 \ No newline at end of file diff --git a/sensor-iso/interface/requirements.txt b/sensor-iso/interface/requirements.txt index 1cf7ef0c4..e2b579534 100644 --- a/sensor-iso/interface/requirements.txt +++ b/sensor-iso/interface/requirements.txt @@ -1,4 +1,4 @@ -certifi==2022.12.7 +certifi==2023.07.22 chardet==5.1.0 click==8.1.3 Flask==2.3.2 diff --git a/sensor-iso/interface/sensor_ctl/arkime/config.ini b/sensor-iso/interface/sensor_ctl/arkime/config.ini index 3214dbec3..9b67ff43e 100644 --- a/sensor-iso/interface/sensor_ctl/arkime/config.ini +++ b/sensor-iso/interface/sensor_ctl/arkime/config.ini @@ -34,6 +34,7 @@ smtpIpHeaders=X-Originating-IP:;X-Barracuda-Apparent-Source-IP: parsersDir=/dummy/parsers pluginsDir=/dummy/plugins spiDataMaxIndices=2 +uploadCommand= compressES=false maxESConns=30 maxESRequests=500 diff --git a/sensor-iso/interface/sensor_ctl/control.sh b/sensor-iso/interface/sensor_ctl/control.sh index 522fb2b68..eb020d25d 100755 --- a/sensor-iso/interface/sensor_ctl/control.sh +++ b/sensor-iso/interface/sensor_ctl/control.sh @@ -12,8 +12,12 @@ CONTROL_VARS_FILE="control_vars.conf" CONTROL_COMMAND="$(basename "${BASH_SOURCE[0]}")" if [[ ($# -eq 0) || (($# -eq 1) && ("$1" = "all")) ]]; then - # no arguments, defaults to all managed processes - CONTROL_PROCESS="all" + if [[ "$CONTROL_COMMAND" = "shutdown" ]]; then + CONTROL_PROCESS=() + else + # no arguments, defaults to all managed processes + CONTROL_PROCESS="all" + fi else # eg., tcpdump, zeek CONTROL_PROCESS="$@" diff --git a/sensor-iso/vagrant/Vagrantfile b/sensor-iso/vagrant/Vagrantfile index ed2974bbd..500ab7083 100644 --- a/sensor-iso/vagrant/Vagrantfile +++ b/sensor-iso/vagrant/Vagrantfile @@ -14,7 +14,7 @@ end Vagrant.configure("2") do |config| config.vm.define "vagrant-hedgehog-build" - config.vm.box = "bento/debian-11" + config.vm.box = "bento/debian-12" config.vm.network "private_network", type: "dhcp" config.ssh.config = "ssh_config" @@ -39,12 +39,9 @@ Vagrant.configure("2") do |config| config.vm.provision "shell", inline: <<-STEP1 dpkg-reconfigure debconf -f noninteractive -p critical export DEBIAN_FRONTEND=noninteractive - sed -i "s/main/main contrib non-free/g" /etc/apt/sources.list + sed -i "s/main/main contrib non-free non-free-firmware/g" /etc/apt/sources.list apt-get -qqy update - echo "deb http://httpredir.debian.org/debian/ bullseye-backports main contrib non-free" >> /etc/apt/sources.list - echo "deb-src http://httpredir.debian.org/debian/ bullseye-backports main contrib non-free" >> /etc/apt/sources.list - apt-get -qqy update - apt-get -t bullseye-backports -y install \ + apt-get -y install \ apt-transport-https \ bc \ build-essential \ diff --git a/shared/aide/Dockerfile b/sensor-iso/yara/Dockerfile similarity index 54% rename from shared/aide/Dockerfile rename to sensor-iso/yara/Dockerfile index 45740b249..4afe51c14 100644 --- a/shared/aide/Dockerfile +++ b/sensor-iso/yara/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:11-slim +FROM debian:12-slim # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. @@ -8,26 +8,21 @@ ENV DEBIAN_FRONTEND noninteractive RUN apt-get -q update && \ apt-get install -q -y --no-install-recommends \ - autoconf \ - autoconf-archive \ automake \ - autotools-dev \ - binutils \ bison \ - build-essential \ ca-certificates \ checkinstall \ + curl \ flex \ - git \ - libmhash-dev \ - libpcre2-dev \ + gcc \ + libjansson-dev \ + libmagic-dev \ + libssl-dev \ libtool \ - m4 \ make \ - pkg-config \ - zlib1g-dev && \ + pkg-config && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -ADD build-aide-deb.sh /usr/local/bin/ +ADD build-yara-deb.sh /usr/local/bin/ -ENTRYPOINT ["/bin/bash", "/usr/local/bin/build-aide-deb.sh"] +ENTRYPOINT ["/bin/bash", "/usr/local/bin/build-yara-deb.sh"] diff --git a/shared/aide/build-docker-image.sh b/sensor-iso/yara/build-docker-image.sh similarity index 87% rename from shared/aide/build-docker-image.sh rename to sensor-iso/yara/build-docker-image.sh index ccfd1d43b..190dd2454 100755 --- a/shared/aide/build-docker-image.sh +++ b/sensor-iso/yara/build-docker-image.sh @@ -6,6 +6,6 @@ SCRIPT_PATH="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" pushd "$SCRIPT_PATH" >/dev/null 2>&1 -docker build -t aide-build:latest . +docker build -t yara-build:latest . popd >/dev/null 2>&1 diff --git a/sensor-iso/yara/build-yara-deb.sh b/sensor-iso/yara/build-yara-deb.sh new file mode 100755 index 000000000..dd8415742 --- /dev/null +++ b/sensor-iso/yara/build-yara-deb.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. + +YARA_URL="https://github.com/VirusTotal/YARA" +YARA_VER="$(curl -sqI "$YARA_URL/releases/latest" | awk -F '/' '/^location/ {print substr($NF, 1, length($NF)-1)}' | sed 's/^v//')" +OUTPUT_DIR="/tmp" +unset VERBOSE + +while getopts o:v opts; do + case ${opts} in + o) OUTPUT_DIR=${OPTARG} ;; + v) VERBOSE=1 ;; + esac +done + +set -e +if [[ -n $VERBOSE ]]; then + set -x +fi + + +cd /tmp +mkdir ./yara +curl -sSL "$YARA_URL/tarball/v$YARA_VER" | tar xzf - -C ./yara --strip-components 1 +cd ./yara +./bootstrap.sh +./configure --prefix=/usr --with-crypto --enable-magic --enable-cuckoo +make +checkinstall -y -D --strip=yes --stripso=yes --install=no --fstrans=no --pkgname=yara --pkgversion="$YARA_VER" --pkgarch="amd64" --pkgsource="$YARA_URL" +ls -l *.deb && mv -v *.deb "$OUTPUT_DIR"/ + +cd /tmp + +if [[ -n $VERBOSE ]]; then + set +x +fi +set +e diff --git a/shared/aide/build-aide-deb.sh b/shared/aide/build-aide-deb.sh deleted file mode 100755 index 132181cf2..000000000 --- a/shared/aide/build-aide-deb.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. - -AIDE_URL="https://github.com/aide/aide.git" -AIDE_BRANCH=master -OUTPUT_DIR="/tmp" -unset VERBOSE - -while getopts o:v opts; do - case ${opts} in - o) OUTPUT_DIR=${OPTARG} ;; - v) VERBOSE=1 ;; - esac -done - -set -e -if [[ -n $VERBOSE ]]; then - set -x -fi - -apt-get -q update - -cd /tmp -git clone --depth=1 --single-branch --recurse-submodules --shallow-submodules --no-tags --branch="$AIDE_BRANCH" "$AIDE_URL" "./aide-$AIDE_BRANCH" -cd "./aide-$AIDE_BRANCH" -AIDE_COMMIT_DATE="$(git log -1 --format="%at" | xargs -I{} date -d @{} "+%Y%m%d%H%M%S")" - -bash ./autogen.sh -./configure --prefix=/usr -make -checkinstall -y -D \ - --strip=yes \ - --stripso=yes \ - --install=no \ - --fstrans=no \ - --pkgname=aide \ - --pkgversion="$AIDE_COMMIT_DATE" \ - --pkgarch="amd64" \ - --pkgsource="$AIDE_URL" - -ls -l *.deb && mv -v *.deb "$OUTPUT_DIR"/ - -cd /tmp - -if [[ -n $VERBOSE ]]; then - set +x -fi -set +e diff --git a/shared/bin/agg-init.sh b/shared/bin/agg-init.sh index 9b7a1de0e..3f8d0857f 100755 --- a/shared/bin/agg-init.sh +++ b/shared/bin/agg-init.sh @@ -15,6 +15,9 @@ if [[ -r "$SCRIPT_PATH"/common-init.sh ]]; then MAIN_USER="$(id -nu 1000)" if [[ -n $MAIN_USER ]]; then + # setup initial user's home directory if it hasn't been done + InjectSkeleton "$MAIN_USER" + # fix some permisions to make sure things belong to the right person FixPermissions "$MAIN_USER" @@ -40,7 +43,7 @@ if [[ -r "$SCRIPT_PATH"/common-init.sh ]]; then # if we need to import prebuilt Malcolm docker images, do so now (but not if we're in a live-usb boot) DOCKER_DRIVER="$(docker info 2>/dev/null | grep 'Storage Driver' | cut -d' ' -f3)" - if [[ -n $DOCKER_DRIVER ]] && [[ "$DOCKER_DRIVER" != "vfs" ]] && [[ -r /malcolm_images.tar.xz ]]; then + if [[ -n $DOCKER_DRIVER ]] && [[ "$DOCKER_DRIVER" != "vfs" ]] && ! grep -q boot=live /proc/cmdline; then docker load -q -i /malcolm_images.tar.xz && rm -f /malcolm_images.tar.xz fi diff --git a/shared/bin/common-init.sh b/shared/bin/common-init.sh index ddc0bbd26..645e0d181 100755 --- a/shared/bin/common-init.sh +++ b/shared/bin/common-init.sh @@ -44,6 +44,20 @@ function CleanDefaultAccounts() { chmod 600 "/etc/crontab" "/etc/group-" "/etc/gshadow-" "/etc/passwd-" "/etc/shadow-" >/dev/null 2>&1 || true chmod 700 "/etc/cron.hourly" "/etc/cron.daily" "/etc/cron.weekly" "/etc/cron.monthly" "/etc/cron.d" >/dev/null 2>&1 || true } + +# setup initially-created user's directory based on /etc/skel +function InjectSkeleton() { + if [ -n "$1" ]; then + USER_TO_FIX="$1" + USER_HOME="$(getent passwd "$USER_TO_FIX" | cut -d: -f6)" + if [ -d "$USER_HOME" ] && [ -d /etc/skel ] && [ ! -f "$USER_HOME"/.config/skel.synced ]; then + rsync -a --ignore-existing --chown="$(id -u "$USER_TO_FIX"):$(id -g "$USER_TO_FIX")" /etc/skel/ "$USER_HOME"/ + date -Iseconds > "$USER_HOME"/.config/skel.synced + chown $(id -u "$USER_TO_FIX"):$(id -g "$USER_TO_FIX") "$USER_HOME"/.config/skel.synced + fi + fi +} + # if the network configuration files for the interfaces haven't been set to come up on boot, configure that function InitializeSensorNetworking() { unset NEED_NETWORKING_RESTART @@ -96,8 +110,9 @@ function InitializeAggregatorNetworking() { function FixPermissions() { if [ -n "$1" ]; then USER_TO_FIX="$1" - [ -d /home/"$USER_TO_FIX" ] && find /home/"$USER_TO_FIX" \( -type d -o -type f \) -exec chmod o-rwx "{}" \; - [ -d /home/"$USER_TO_FIX" ] && find /home/"$USER_TO_FIX" -type f -name ".*" -exec chmod g-wx "{}" \; + USER_HOME="$(getent passwd "$USER_TO_FIX" | cut -d: -f6)" + [ -d "$USER_HOME" ] && find "$USER_HOME" \( -type d -o -type f \) -exec chmod o-rwx "{}" \; + [ -d "$USER_HOME" ] && find "$USER_HOME" -type f -name ".*" -exec chmod g-wx "{}" \; if [ ! -f /etc/cron.allow ] || ! grep -q "$USER_TO_FIX" /etc/cron.allow; then echo "$USER_TO_FIX" >> /etc/cron.allow fi @@ -115,17 +130,18 @@ function BadTelemetry() { echo >> /etc/hosts echo '127.0.0.1 _googlecast._tcp.local' >> /etc/hosts echo '127.0.0.1 accounts.google.com' >> /etc/hosts + echo '127.0.0.1 census.netbox.dev' >> /etc/hosts echo '127.0.0.1 clients.l.google.com' >> /etc/hosts + echo '127.0.0.1 connectivitycheck.gstatic.com' >> /etc/hosts + echo '127.0.0.1 detectportal.firefox.com' >> /etc/hosts + echo '127.0.0.1 detectportal.prod.mozaws.net' >> /etc/hosts echo '127.0.0.1 fonts.googleapis.com' >> /etc/hosts + echo '127.0.0.1 incoming.telemetry.mozilla.org' >> /etc/hosts + echo '127.0.0.1 prod.detectportal.prod.cloudops.mozgcp.net' >> /etc/hosts echo '127.0.0.1 safebrowsing-cache.google.com' >> /etc/hosts echo '127.0.0.1 safebrowsing.clients.google.com' >> /etc/hosts echo '127.0.0.1 update.googleapis.com' >> /etc/hosts echo '127.0.0.1 www.google-analytics.com' >> /etc/hosts echo '127.0.0.1 www.gstatic.com' >> /etc/hosts - echo '127.0.0.1 connectivitycheck.gstatic.com' >> /etc/hosts - echo '127.0.0.1 incoming.telemetry.mozilla.org' >> /etc/hosts - echo '127.0.0.1 detectportal.firefox.com' >> /etc/hosts - echo '127.0.0.1 prod.detectportal.prod.cloudops.mozgcp.net' >> /etc/hosts - echo '127.0.0.1 detectportal.prod.mozaws.net' >> /etc/hosts fi } diff --git a/shared/bin/configure-interfaces.py b/shared/bin/configure-interfaces.py index bd5d17a67..23f061756 100755 --- a/shared/bin/configure-interfaces.py +++ b/shared/bin/configure-interfaces.py @@ -52,8 +52,8 @@ class Constants: TIME_SYNC_NTP = 'ntp' TIME_SYNC_HTPDATE = 'htpdate' TIME_SYNC_HTPDATE_CRON = '/etc/cron.d/htpdate' - TIME_SYNC_HTPDATE_TEST_COMMAND = '/usr/sbin/htpdate -4 -a -b -d' - TIME_SYNC_HTPDATE_COMMAND = '/usr/sbin/htpdate -4 -a -b -l -s' + TIME_SYNC_HTPDATE_TEST_COMMAND = '/usr/sbin/htpdate -4 -a -d' + TIME_SYNC_HTPDATE_COMMAND = '/usr/sbin/htpdate -4 -a -l -s' TIME_SYNC_NTP_CONFIG = '/etc/ntp.conf' SSHD_CONFIG_FILE = "/etc/ssh/sshd_config" diff --git a/shared/bin/manuf-oui-parse.py b/shared/bin/manuf-oui-parse.py index 7cc0be2f4..e37d65ed0 100755 --- a/shared/bin/manuf-oui-parse.py +++ b/shared/bin/manuf-oui-parse.py @@ -17,7 +17,7 @@ except ImportError: import yaml -DEFAULT_MANUF_URL = "https://gitlab.com/wireshark/wireshark/raw/master/manuf" +DEFAULT_MANUF_URL = "https://gitlab.com/wireshark/wireshark/raw/release-4.0/manuf" padded_mac_low = '00:00:00:00:00:00' padded_mac_high = 'FF:FF:FF:FF:FF:FF' mac_pattern = re.compile(r"[-:\.]") diff --git a/shared/bin/preseed_late_user_config.sh b/shared/bin/preseed_late_user_config.sh index 2081162ed..f5036608a 100755 --- a/shared/bin/preseed_late_user_config.sh +++ b/shared/bin/preseed_late_user_config.sh @@ -7,6 +7,7 @@ # prompt whether or not to lock screen for the GUI session on inactivity # prompt whether to use U.S. DoD login banner (https://www.stigviewer.com/stig/general_purpose_operating_system_srg/2015-06-26/finding/V-56585) # prompt for disabling IPV6 or not +# prompt for enabling SSH password authentication # this is a debconf-compatible script . /usr/share/debconf/confmodule diff --git a/shared/bin/sensor-init.sh b/shared/bin/sensor-init.sh index 5a46cd726..95d8a05d4 100755 --- a/shared/bin/sensor-init.sh +++ b/shared/bin/sensor-init.sh @@ -119,8 +119,13 @@ if [[ -r "$SCRIPT_PATH"/common-init.sh ]]; then # if the network configuration files for the interfaces haven't been set to come up on boot, configure that now. InitializeSensorNetworking - # fix some permisions to make sure things belong to the right person - [[ -n $MAIN_USER ]] && FixPermissions "$MAIN_USER" + if [[ -n $MAIN_USER ]]; then + # setup initial user's home directory if it hasn't been done + InjectSkeleton "$MAIN_USER" + + # fix some permisions to make sure things belong to the right person + FixPermissions "$MAIN_USER" + fi # block some call-homes BadTelemetry diff --git a/shared/bin/watch_common.py b/shared/bin/watch_common.py index 17caa9300..9457a1604 100644 --- a/shared/bin/watch_common.py +++ b/shared/bin/watch_common.py @@ -287,6 +287,7 @@ def ProcessFileEventWorker(workerArgs): def WatchAndProcessDirectory( directories, polling, + recursive, fileProcessor, fileProcessorKwargs, assumeClosedSec, @@ -301,7 +302,7 @@ def WatchAndProcessDirectory( ) for directory in directories: loggerToUse.info(f"🗐\tScheduling {directory}") - observer.schedule(handler, directory, recursive=True) + observer.schedule(handler, directory, recursive=recursive) observer.start() try: