├── .gitignore ├── README.md ├── chatgpt_vs_snyk ├── README.md ├── chatgpt_s3.tf ├── kms.tf ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── cloudtrail_siem ├── main.tf ├── outputs.tf ├── providers.tf ├── s3.tf ├── sqs.tf ├── variables.tf └── versions.tf ├── code_scanning ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── container_security ├── secure │ └── Dockerfile └── vulnerable │ └── Dockerfile ├── elk_stack ├── docker-compose.yml └── logstash.conf ├── golden_image_pipeline ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── imdsv2_control ├── README.md ├── ec2.tf ├── imdsv1.tf ├── imdsv2.tf ├── outputs.tf ├── providers.tf ├── variables.tf ├── versions.tf └── vpc.tf ├── immutable_infrastructure ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── misp ├── misp-docker │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── core │ │ ├── Dockerfile │ │ └── files │ │ │ ├── configure_misp.sh │ │ │ ├── entrypoint.sh │ │ │ ├── entrypoint_cron.sh │ │ │ ├── entrypoint_fpm.sh │ │ │ ├── entrypoint_nginx.sh │ │ │ ├── etc │ │ │ ├── misp-docker │ │ │ │ ├── critical.defaults.json │ │ │ │ ├── critical.envars.json │ │ │ │ ├── db_enable.envars.json │ │ │ │ ├── gpg.defaults.json │ │ │ │ ├── gpg.envars.json │ │ │ │ ├── initialisation.defaults.json │ │ │ │ ├── initialisation.envars.json │ │ │ │ ├── minimum_config.defaults.json │ │ │ │ ├── minimum_config.envars.json │ │ │ │ ├── optional.defaults.json │ │ │ │ └── proxy.envars.json │ │ │ ├── nginx │ │ │ │ ├── includes │ │ │ │ │ └── misp │ │ │ │ └── sites-available │ │ │ │ │ ├── misp443 │ │ │ │ │ └── misp80 │ │ │ └── supervisor │ │ │ │ └── conf.d │ │ │ │ ├── 10-supervisor.conf │ │ │ │ └── 50-workers.conf │ │ │ ├── rest_client.sh │ │ │ ├── utilities.sh │ │ │ └── var │ │ │ └── www │ │ │ └── html │ │ │ └── index.php │ ├── docker-bake.hcl │ ├── docker-compose.yml │ ├── modules │ │ └── Dockerfile │ └── template.env └── opencti │ └── docker-compose.yml ├── oidc_auth_using_jwt ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── opencti_demo ├── docker-compose.yml └── opencti.env ├── permission_boundaries ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── pi_hole_demo ├── docker-compose.yml └── environment.env ├── s3_private_buckets_via_cloudfront ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf ├── service_control_policies ├── README.md ├── enforce_ebs_encryption.json ├── enforce_regions.json ├── enforce_tagging.json ├── prevent_ami_public.json ├── prevent_changes_to_config.json ├── prevent_external_sharing.json ├── prevent_iam_users_keys.json ├── prevent_imdsv1.json ├── prevent_internet_egress.json ├── prevent_keys_for_root.json ├── prevent_member_accounts_leaving.json ├── prevent_s3_public_access_block_change.json ├── prevent_s3_unencrypted_uploads.json ├── protect_cloudwatch.json ├── protect_guard_duty.json ├── protect_role.json └── protect_vpc_flow_logs.json ├── systems_manager_recording ├── cloudwatch.tf ├── data.tf ├── ec2.tf ├── kms.tf ├── outputs.tf ├── providers.tf ├── s3.tf ├── variables.tf └── versions.tf ├── vpc_flow_logs_analysis ├── README.md ├── cloudwatch.tf ├── data.tf ├── ec2.tf ├── iam.tf ├── kms.tf ├── main.tf ├── outputs.tf ├── providers.tf ├── variables.tf └── versions.tf └── yeti_cti_platform └── yeti-docker └── prod ├── .env ├── README.md ├── docker-compose.yaml ├── frontend ├── Dockerfile └── nginx.conf └── yeti └── Dockerfile /.gitignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | .dccache 3 | .terraform.lock.hcl 4 | .tftstate 5 | .backup 6 | terraform.tfstate 7 | terraform.tfstate.backup -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Examples and samples from Medium Articles 2 | [Medium Profile](https://medium.com/@andyblooman) 3 | 4 | [LinkedIn Profile](https://www.linkedin.com/in/andrewblooman/) 5 | 6 | ## Included Projects 7 | - Making S3 Buckets Private with CloudFront and OAC 8 | - Deploy Third Party Authentication with OIDC/JWT 9 | - OpenCTI for Threat Intelligence 10 | - Permission Boundaries 11 | - Session Manager Recordings 12 | - IMDSV2 Guidance 13 | - Pi-Hole Demo 14 | - MISP Threat Intel Feeds 15 | - ChatGPT vs Snyk Code scanning of S3 Bucket 16 | - VPC Flow Log Analysis 17 | - Service Control Policies 18 | - YETI Threat Intel Platform 19 | - ELK Stack on Docker 20 | - Container Security 21 | 22 | ## Upcoming 23 | - Code Scanning 24 | - Golden Image Pipeline 25 | - Immutable Infrastructure 26 | -------------------------------------------------------------------------------- /chatgpt_vs_snyk/README.md: -------------------------------------------------------------------------------- 1 | # Project Summary 2 | Demonstrates how to secure Terraform using the Snyk IDE extension, highlighting issues with the code. 3 | 4 | # How to Use 5 | Observe the issues raised in the chatgpt_s3 terraform file. The issues have been addressed in the remaining terraform configuration, however there are still some issues. Use Snyk to understand and try to correct them yourself. 6 | 7 | # Notes 8 | Ensure to update the variables to those for your AWS account. -------------------------------------------------------------------------------- /chatgpt_vs_snyk/chatgpt_s3.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "us-west-2" # Replace with your preferred region 3 | } 4 | 5 | resource "aws_s3_bucket" "my_bucket" { 6 | bucket = "my-unique-bucket-name" # Replace with your desired bucket name 7 | acl = "private" 8 | 9 | tags = { 10 | Name = "MyS3Bucket" 11 | Environment = "Dev" 12 | } 13 | } -------------------------------------------------------------------------------- /chatgpt_vs_snyk/kms.tf: -------------------------------------------------------------------------------- 1 | resource "aws_kms_alias" "log_key_alias" { 2 | name = "alias/logging_key" 3 | target_key_id = aws_kms_key.log_key.id 4 | } 5 | 6 | resource "aws_kms_key" "log_key" { 7 | description = "KMS key for S3 bucket encryption" 8 | enable_key_rotation = true 9 | rotation_period_in_days = 90 10 | policy = < 1514 4 | } 5 | } 6 | 7 | output { 8 | stdout { 9 | codec => rubydebug 10 | } 11 | elasticsearch { 12 | hosts => ["http://elasticsearch:9200"] 13 | index => "syslog-%{+yyyy.MM.dd}" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /golden_image_pipeline/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/golden_image_pipeline/main.tf -------------------------------------------------------------------------------- /golden_image_pipeline/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/golden_image_pipeline/outputs.tf -------------------------------------------------------------------------------- /golden_image_pipeline/providers.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/golden_image_pipeline/providers.tf -------------------------------------------------------------------------------- /golden_image_pipeline/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/golden_image_pipeline/variables.tf -------------------------------------------------------------------------------- /golden_image_pipeline/versions.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/golden_image_pipeline/versions.tf -------------------------------------------------------------------------------- /imdsv2_control/README.md: -------------------------------------------------------------------------------- 1 | # Project Summary 2 | Demonstrates how to fix the Server Side Request Forgery Vulnerabilty in Instance Metadata Service Version 1. 3 | 4 | # How to Use 5 | As per my article, use the following process to exploit IMDSv1 on the EC2 instance. 6 | 7 | - Run the following command to see the name of the role (if any) attached to the EC2 instance 8 | 9 | `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/` 10 | 11 | - We can store the output as an environment variable, in this case role_name 12 | 13 | `role_name=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)` 14 | 15 | - Finally, we can run a command to retrieve the credentials 16 | 17 | `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$role_name` 18 | 19 | # Notes 20 | Ensure to update the variables to those for your AWS account. -------------------------------------------------------------------------------- /imdsv2_control/ec2.tf: -------------------------------------------------------------------------------- 1 | # Create a new security group that allows SSH access 2 | resource "aws_security_group" "inbound_ssh" { 3 | name = "inbound_ssh" 4 | description = "Allow SSH inbound traffic" 5 | 6 | ingress { 7 | from_port = 22 8 | to_port = 22 9 | protocol = "tcp" 10 | cidr_blocks = ["0.0.0.0/0"] 11 | } 12 | 13 | egress { 14 | from_port = 0 15 | to_port = 0 16 | protocol = "-1" 17 | cidr_blocks = ["0.0.0.0/0"] 18 | } 19 | } 20 | 21 | data "aws_ami" "amazon_linux_2023" { 22 | most_recent = true 23 | owners = ["amazon"] 24 | 25 | filter { 26 | name = "name" 27 | values = ["amzn2-ami-kernel-5.10-hvm-*-x86_64-gp2"] 28 | } 29 | 30 | filter { 31 | name = "virtualization-type" 32 | values = ["hvm"] 33 | } 34 | 35 | filter { 36 | name = "architecture" 37 | values = ["x86_64"] 38 | } 39 | } 40 | 41 | # Creates IAM role 42 | resource "aws_iam_role" "imds_role" { 43 | name = "imds_role" 44 | 45 | assume_role_policy = jsonencode({ 46 | Version = "2012-10-17" 47 | Statement = [ 48 | { 49 | Effect = "Allow" 50 | Principal = { 51 | Service = "ec2.amazonaws.com" 52 | } 53 | Action = "sts:AssumeRole" 54 | } 55 | ] 56 | }) 57 | managed_policy_arns = ["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"] 58 | } 59 | 60 | # Creates instance profile 61 | resource "aws_iam_instance_profile" "ec2_ssm_instance_profile" { 62 | name = "ec2_ssm_instance_profile" 63 | role = aws_iam_role.imds_role.name 64 | } -------------------------------------------------------------------------------- /imdsv2_control/imdsv1.tf: -------------------------------------------------------------------------------- 1 | # Creates EC2 instance with IMDSv1 2 | resource "aws_instance" "imdsv1_example" { 3 | ami = data.aws_ami.amazon_linux_2023.id 4 | instance_type = "t3.micro" 5 | iam_instance_profile = aws_iam_instance_profile.ec2_ssm_instance_profile.name 6 | subnet_id = data.aws_subnet.subnet.id 7 | vpc_security_group_ids = ["${aws_security_group.inbound_ssh.id}"] 8 | disable_api_termination = true 9 | root_block_device { 10 | volume_size = 8 11 | volume_type = "gp2" 12 | delete_on_termination = true 13 | encrypted = true 14 | } 15 | tags = { 16 | Name = "imdsv1_example" 17 | Environment = "Development" 18 | Owner = "Medium Article" 19 | } 20 | } -------------------------------------------------------------------------------- /imdsv2_control/imdsv2.tf: -------------------------------------------------------------------------------- 1 | # Creates EC2 instance with IMDSv2 2 | resource "aws_instance" "imdsv2_example" { 3 | ami = data.aws_ami.amazon_linux_2023.id 4 | instance_type = "t3.micro" 5 | iam_instance_profile = aws_iam_instance_profile.ec2_ssm_instance_profile.name 6 | subnet_id = data.aws_subnet.subnet.id 7 | vpc_security_group_ids = ["${aws_security_group.inbound_ssh.id}"] 8 | disable_api_termination = true 9 | metadata_options { 10 | http_endpoint = "enabled" 11 | http_tokens = "required" # This enforces the use of IMDSv2 12 | http_put_response_hop_limit = 1 13 | } 14 | root_block_device { 15 | volume_size = 20 16 | volume_type = "gp3" 17 | delete_on_termination = true 18 | encrypted = true 19 | } 20 | tags = { 21 | Name = "imdsv2_example" 22 | Environment = "Development" 23 | Owner = "Medium Article" 24 | } 25 | } -------------------------------------------------------------------------------- /imdsv2_control/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output the instance ID 2 | output "imdvsv1_instance_id" { 3 | value = aws_instance.imdsv1_example.id 4 | } 5 | 6 | # Output the instance ID 7 | output "imdvsv2_instance_id" { 8 | value = aws_instance.imdsv1_example.id 9 | } 10 | 11 | output "ami_id" { 12 | value = data.aws_ami.amazon_linux_2023.id 13 | } -------------------------------------------------------------------------------- /imdsv2_control/providers.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "eu-west-2" 3 | } -------------------------------------------------------------------------------- /imdsv2_control/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | type = string 3 | default = "eu-west-1" 4 | } 5 | 6 | variable "vpc_name" { 7 | type = string 8 | default = "INSERT_NAME" 9 | } 10 | 11 | variable "subnet_name" { 12 | type = string 13 | default = "INSERT_NAME" 14 | } 15 | -------------------------------------------------------------------------------- /imdsv2_control/versions.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/imdsv2_control/versions.tf -------------------------------------------------------------------------------- /imdsv2_control/vpc.tf: -------------------------------------------------------------------------------- 1 | 2 | data "aws_vpc" "main" { 3 | filter { 4 | name = "tag:Name" 5 | values = ["${var.vpc_name}"] 6 | } 7 | } 8 | 9 | data "aws_subnet" "subnet" { 10 | filter { 11 | name = "tag:Name" 12 | values = ["${var.subnet_name}"] 13 | } 14 | } -------------------------------------------------------------------------------- /immutable_infrastructure/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/immutable_infrastructure/main.tf -------------------------------------------------------------------------------- /immutable_infrastructure/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/immutable_infrastructure/outputs.tf -------------------------------------------------------------------------------- /immutable_infrastructure/providers.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/immutable_infrastructure/providers.tf -------------------------------------------------------------------------------- /immutable_infrastructure/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/immutable_infrastructure/variables.tf -------------------------------------------------------------------------------- /immutable_infrastructure/versions.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewblooman/medium/8318c6f1ef2755785e43d0ef921dbf3a61246bea/immutable_infrastructure/versions.tf -------------------------------------------------------------------------------- /misp/misp-docker/.gitignore: -------------------------------------------------------------------------------- 1 | /configs/ 2 | /files/ 3 | /gnupg/ 4 | /logs/ 5 | /ssl/ 6 | .env 7 | env.hcl 8 | rootca.crt 9 | -------------------------------------------------------------------------------- /misp/misp-docker/README.md: -------------------------------------------------------------------------------- 1 | # MISP Docker images 2 | 3 | [![Build Status](https://img.shields.io/github/actions/workflow/status/MISP/misp-docker/release-latest.yml)](https://github.com/orgs/MISP/packages) 4 | [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/MISP/Docker) 5 | 6 | A production ready Docker MISP image (formerly hosted at https://github.com/ostefano/docker-misp, now deprecated) loosely based on CoolAcid and DSCO builds, with nearly all logic rewritten and verified for correctness and portability. 7 | 8 | Notable features: 9 | - MISP and MISP modules are split into two different Docker images, `misp-core` and `misp-modules` 10 | - Docker images are pushed regularly, no build required 11 | - Lightweigth Docker images by using multiple build stages and a slim parent image 12 | - Rely on off the shelf Docker images for Exim4, Redis, and MariaDB 13 | - Cron jobs run updates, pushes, and pulls 14 | - Fix supervisord process control (processes are correctly terminated upon reload) 15 | - Fix schema update by making it completely offline (no user interaction required) 16 | - Fix enforcement of permissions 17 | - Fix MISP modules loading of faup library 18 | - Fix MISP modules loading of gl library 19 | - Add support for new background job [system](https://github.com/MISP/MISP/blob/2.4/docs/background-jobs-migration-guide.md) 20 | - Add support for building specific MISP and MISP-modules commits 21 | - Add automatic configuration of syncservers (see `configure_misp.sh`) 22 | - Add automatic configuration of authentication keys (see `configure_misp.sh`) 23 | - Add direct push of docker images to GitHub Packages 24 | - Consolidated `docker-compose.yml` file 25 | - Workardound VirtioFS bug when running Docker Desktop for Mac 26 | - ... and many others 27 | 28 | The underlying spirit of this project is to allow "repeatable deployments", and all pull requests in this direction will be merged post-haste. 29 | 30 | ## Getting Started 31 | 32 | - Copy the `template.env` to `.env` 33 | - Customize `.env` based on your needs (optional step) 34 | 35 | ### Run 36 | 37 | - `docker-compose pull` if you want to use pre-built images or `docker-compose build` if you want to build your own (see the `Troubleshooting` section in case of errors) 38 | - `docker-compose up` 39 | - Login to `https://localhost` 40 | - User: `admin@admin.test` 41 | - Password: `admin` 42 | 43 | Keeping the image up-to-date with upstream should be as simple as running `docker-compose pull`. 44 | 45 | ### Configuration 46 | 47 | The `docker-compose.yml` file allows further configuration settings: 48 | 49 | ``` 50 | "MYSQL_HOST=db" 51 | "MYSQL_USER=misp" 52 | "MYSQL_PASSWORD=example" # NOTE: This should be AlphaNum with no Special Chars. Otherwise, edit config files after first run. 53 | "MYSQL_DATABASE=misp" 54 | "MISP_MODULES_FQDN=http://misp-modules" # Set the MISP Modules FQDN, used for Enrichment_services_url/Import_services_url/Export_services_url 55 | "WORKERS=1" # Legacy variable controlling the number of parallel workers (use variables below instead) 56 | "NUM_WORKERS_DEFAULT=5" # To set the number of default workers 57 | "NUM_WORKERS_PRIO=5" # To set the number of prio workers 58 | "NUM_WORKERS_EMAIL=5" # To set the number of email workers 59 | "NUM_WORKERS_UPDATE=1" # To set the number of update workers 60 | "NUM_WORKERS_CACHE=5" # To set the number of cache workers 61 | ``` 62 | 63 | New options are added on a regular basis. 64 | 65 | #### Environment variable behaviour 66 | 67 | Set environment variables in .env to configure settings instead of in docker-compose.yml where possible. Setting the variables in .env will allow you to pull updates from Github without issues caused by a modified docker-compose.yml file, should there be an update for it. 68 | 69 | Environment variable driven settings are enforced every time the misp-core container starts. This means that if you change the config.php file or database for a setting that has a set environment variable, it will be changed to the environment variable value upon next container start. Empty environment variables may have a safe default which is enforced instead. 70 | 71 | If you push a change to add or remove an environment variable, please look in "core/files/etc/misp-docker/" for json files with "envars" in the name and adjust there. 72 | 73 | #### Unset safe default settings behaviour 74 | 75 | The misp-core container has definitions for minimum safe default settings which are set if needed each time the container starts. They will only be set if there is no existing entry in the config.php file or database for these settings. If you specify a custom value for any of these settings it will be respected. See the definitions of these in "core/files/etc/misp-docker" where the filenames contain the word "defaults". 76 | 77 | #### Storing system settings in the DB 78 | 79 | This container includes the "ENABLE_DB_SETTINGS" environment variable, which can be used to set "MISP.system_setting_db" to true or false. This changes the behaviour of where MISP chooses to store operator made settings changes; in config.php or in the system_settings database table. By default this is set to false. 80 | 81 | If a setting is not defined in the DB, but is defined in config.php, it will be read out of config.php and used. This can sometimes lead to operator confusion, so please check both locations for values when troubleshooting. 82 | 83 | If you change this setting from false to true, settings are not migrated from config.php to the database, but rather the above behaviour is relied upon. 84 | 85 | While storing system settings in the DB works as expected most of the time, you may come across some instances where a particular setting MUST be set in the config.php file. We have tried to side-step this issue by prepopulating the config.php file with all of these settings, but there could be more. If you encounter any issues like this, please raise an issue, and try configuring the setting in the config.php file instead. 86 | 87 | #### Overriding environment variable and unset safe default settings behaviours 88 | 89 | If you are trying to accomplish something and the above behaviours get in the way, please let us know as this is not intended. 90 | 91 | To override these behaviours edit the docker-compose.yml file's misp-core volume definitions to enable the "customize_misp.sh" behaviour (see the bottom of the Production section for details). The "customize_misp.sh" script triggers after the above behaviours complete and is an appropriate place to override a setting. It is suggested that you use the "/var/www/MISP/app/cake Admin setSetting" command to override a setting, as this tool is config.php file and database setting aware. 92 | 93 | #### Adding a new setting and unsure what files to edit? 94 | 95 | If it is just a default setting that is meant to be set if not already set by the user, add it in one of the `*.default.json` files. 96 | If it is a setting controlled by an environment variable which is meant to override whatever is set, add it in one of the `*.envars.json` files (note that you can still specify a default value). 97 | 98 | ### Production 99 | 100 | - It is recommended to specify the build you want run by editing `docker-compose.yml` (see here for the list of available tags https://github.com/orgs/MISP/packages) 101 | - Directory volume mount SSL Certs `./ssl`: `/etc/ssl/certs` 102 | - Certificate File: `cert.pem` 103 | - Certificate Key File: `key.pem` 104 | - CA File for Cert Authentication (optional) `ca.pem` 105 | - Additional directory volume mounts: 106 | - `./configs`: `/var/www/MISP/app/Config/` 107 | - `./logs`: `/var/www/MISP/app/tmp/logs/` 108 | - `./files`: `/var/www/MISP/app/files/` 109 | - `./gnupg`: `/var/www/MISP/.gnupg/` 110 | - If you need to automatically run additional steps each time the container starts, create a new file `files/customize_misp.sh`, and replace the variable `${CUSTOM_PATH}` inside `docker-compose.yml` with its parent path. 111 | 112 | ## Installing custom root CA certificates 113 | 114 | Custom root CA certificates can be mounted under `/usr/local/share/ca-certificates` and will be installed during the `misp-core` container start. 115 | 116 | **Note:** It is important to have the .crt extension on the file, otherwise it will not be processed. 117 | 118 | ```yaml 119 | misp-core: 120 | # ... 121 | volumes: 122 | - "./configs/:/var/www/MISP/app/Config/" 123 | - "./logs/:/var/www/MISP/app/tmp/logs/" 124 | - "./files/:/var/www/MISP/app/files/" 125 | - "./ssl/:/etc/nginx/certs/" 126 | - "./gnupg/:/var/www/MISP/.gnupg/" 127 | # customize by replacing ${CUSTOM_PATH} with a path containing 'files/customize_misp.sh' 128 | # - "${CUSTOM_PATH}/:/custom/" 129 | # mount custom ca root certificates 130 | - "./rootca.pem:/usr/local/share/ca-certificates/rootca.crt" 131 | ``` 132 | 133 | ## Troubleshooting 134 | 135 | - Make sure you run a fairly recent version of Docker and Docker Compose (if in doubt, update following the steps outlined in https://docs.docker.com/engine/install/ubuntu/) 136 | - Some Linux distributions provide a recent version of Docker but a legacy version of Docker Compose, so you can try running `docker compose` instead of `docker-compose` 137 | - Make sure you are not running an old image or container; when in doubt run `docker system prune --volumes` and clone this repository into an empty directory 138 | 139 | ## Versioning 140 | 141 | A GitHub Action builds both `misp-core` and `misp-modules` images automatically and pushes them to the [GitHub Package registry](https://github.com/orgs/MISP/packages). We do not use tags inside the repository; instead we tag images as they are pushed to the registry. For each build, `misp-core` and `misp-modules` images are tagged as follows: 142 | - `misp-core:${commit-sha1}[0:7]` and `misp-modules:${commit-sha1}[0:7]` where `${commit-sha1}` is the commit hash triggering the build 143 | - `misp-core:latest` and `misp-modules:latest` in order to track the latest builds available 144 | - `misp-core:${CORE_TAG}` and `misp-modules:${MODULES_TAG}` reflecting the underlying version of MISP and MISP modules (as specified inside the `template.env` file at build time) 145 | -------------------------------------------------------------------------------- /misp/misp-docker/core/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG DOCKER_HUB_PROXY="" 2 | 3 | 4 | FROM "${DOCKER_HUB_PROXY}python:3.12-slim-bookworm" AS php-base 5 | ENV DEBIAN_FRONTEND noninteractive 6 | 7 | # Uncomment when building in corporate environments 8 | # COPY ./rootca.crt /usr/local/share/ca-certificates/rootca.pem 9 | # COPY ./rootca.crt /usr/lib/ssl/cert.pem 10 | 11 | RUN apt-get update; apt-get install -y --no-install-recommends \ 12 | lsb-release \ 13 | ca-certificates \ 14 | curl 15 | RUN curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb 16 | RUN dpkg -i /tmp/debsuryorg-archive-keyring.deb 17 | RUN echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list 18 | RUN apt-get update 19 | 20 | 21 | FROM php-base AS composer-build 22 | ENV DEBIAN_FRONTEND noninteractive 23 | ENV COMPOSER_ALLOW_SUPERUSER 1 24 | ARG CORE_TAG 25 | ARG CORE_COMMIT 26 | 27 | RUN apt-get install -y --no-install-recommends \ 28 | php7.4 \ 29 | php7.4-apcu \ 30 | php7.4-curl \ 31 | php7.4-xml \ 32 | php7.4-intl \ 33 | php7.4-bcmath \ 34 | php7.4-mbstring \ 35 | php7.4-mysql \ 36 | php7.4-redis \ 37 | php7.4-gd \ 38 | php7.4-fpm \ 39 | php7.4-zip \ 40 | unzip \ 41 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 42 | 43 | WORKDIR /tmp 44 | ADD https://raw.githubusercontent.com/MISP/MISP/${CORE_COMMIT:-${CORE_TAG}}/app/composer.json /tmp 45 | COPY --from=composer:latest /usr/bin/composer /usr/bin/composer 46 | RUN composer config --no-interaction allow-plugins.composer/installers true 47 | RUN composer install 48 | RUN composer require --with-all-dependencies --no-interaction \ 49 | supervisorphp/supervisor:^4.0 \ 50 | guzzlehttp/guzzle:^7.4.5 \ 51 | lstrojny/fxmlrpc \ 52 | php-http/message \ 53 | php-http/message-factory \ 54 | # docker image specific dependencies 55 | elasticsearch/elasticsearch:^8.7.0 \ 56 | jakub-onderka/openid-connect-php:^1.0.0 \ 57 | aws/aws-sdk-php 58 | 59 | 60 | FROM php-base AS php-build 61 | ENV DEBIAN_FRONTEND noninteractive 62 | ENV TZ Etc/UTC 63 | 64 | RUN apt-get install -y --no-install-recommends \ 65 | gcc \ 66 | g++ \ 67 | make \ 68 | php7.4 \ 69 | php7.4-dev \ 70 | php7.4-xml \ 71 | php-pear \ 72 | libbrotli-dev \ 73 | libfuzzy-dev \ 74 | librdkafka-dev \ 75 | libsimdjson-dev \ 76 | libzstd-dev \ 77 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 78 | 79 | RUN update-alternatives --set php /usr/bin/php7.4 80 | RUN update-alternatives --set php-config /usr/bin/php-config7.4 81 | RUN update-alternatives --set phpize /usr/bin/phpize7.4 82 | 83 | RUN cp "/usr/lib/$(gcc -dumpmachine)"/libfuzzy.* /usr/lib 84 | RUN pecl channel-update pecl.php.net && \ 85 | pecl install ssdeep && \ 86 | pecl install rdkafka && \ 87 | pecl install simdjson && \ 88 | pecl install zstd && \ 89 | pecl install brotli 90 | 91 | 92 | FROM php-base AS python-build 93 | ENV DEBIAN_FRONTEND noninteractive 94 | ARG CORE_TAG 95 | ARG CORE_COMMIT 96 | ARG PYPI_REDIS_VERSION 97 | ARG PYPI_LIEF_VERSION 98 | ARG PYPI_PYDEEP2_VERSION 99 | ARG PYPI_PYTHON_MAGIC_VERSION 100 | ARG PYPI_MISP_LIB_STIX2_VERSION 101 | ARG PYPI_MAEC_VERSION 102 | ARG PYPI_MIXBOX_VERSION 103 | ARG PYPI_CYBOX_VERSION 104 | ARG PYPI_PYMISP_VERSION 105 | ARG PYPI_MISP_STIX_VERSION 106 | 107 | RUN apt-get install -y --no-install-recommends \ 108 | git \ 109 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 110 | 111 | # Download MISP using git in the /var/www/ directory. Remove unnecessary items. 112 | RUN <<-EOF 113 | if [ ! -z "${CORE_COMMIT}" ]; then 114 | git clone https://github.com/MISP/MISP.git /var/www/MISP && cd /var/www/MISP && git checkout "${CORE_COMMIT}" 115 | else 116 | git clone --branch "${CORE_TAG}" --depth 1 https://github.com/MISP/MISP.git /var/www/MISP 117 | fi 118 | cd /var/www/MISP || exit; git submodule update --init --recursive . 119 | EOF 120 | 121 | RUN <<-EOF 122 | mkdir /wheels 123 | 124 | # Add additional dependencies (container specific) 125 | # The "set" line contains the list of modules we want to ensure are present. 126 | # PYPI_MODULE_NAME_VERSION env vars can be set to specify the version desired, 127 | # e.g. PYPI_SURICATA_VERSION="==2.0" to specify exactly version 2.0 for the suricata package 128 | # 129 | # 1. Check for presence of each module in requirements.txt 130 | # 2. If missing, add it (with optional version from env (defaults to empty string)) 131 | # 3. If present, replace with our specified version if it exists, otherwise leave 132 | # the upstream version alone. 133 | set -- "redis" "lief" "pydeep2" "python-magic" "misp-lib-stix2" "maec" "mixbox" "cybox" "pymisp" "misp-stix" 134 | for mod in "$@"; do 135 | mod_version_var=$(echo "PYPI_${mod}_VERSION" | tr '[:lower:]' '[:upper:]' | tr '-' '_') 136 | mod_version=$(eval "echo \"\$$mod_version_var\"") 137 | grep -q ${mod} /var/www/MISP/requirements.txt 138 | exists=$? 139 | if [ "${exists}" -eq "1" ]; then 140 | echo "Adding missing module ${mod} with version '${mod_version}'" 141 | echo ${mod}${mod_version} >> /var/www/MISP/requirements.txt 142 | else 143 | if [ "$(echo ${mod_version} | wc -m)" -gt 1 ]; then 144 | echo "Overwriting existing module ${mod}, version '${mod_version}'" 145 | sed -i "/${mod}/s/.*/${mod}${mod_version}/" /var/www/MISP/requirements.txt 146 | else 147 | echo "Skipping overwriting ${mod} due to missing version variable" 148 | fi 149 | fi 150 | done; 151 | 152 | pip wheel --no-cache-dir -w /wheels/ -r /var/www/MISP/requirements.txt 153 | 154 | # Remove files we do not care for 155 | find /var/www/MISP/INSTALL/* ! -name 'MYSQL.sql' -type f -exec rm {} + 156 | find /var/www/MISP/INSTALL/* ! -name 'MYSQL.sql' -type l -exec rm {} + 157 | # Remove most files in .git - we do not use git functionality in docker 158 | find /var/www/MISP/.git/* ! -name HEAD -exec rm -rf {} + 159 | # Remove libraries' submodules 160 | rm -r /var/www/MISP/PyMISP 161 | rm -r /var/www/MISP/app/files/scripts/cti-python-stix2 162 | rm -r /var/www/MISP/app/files/scripts/misp-stix 163 | rm -r /var/www/MISP/app/files/scripts/mixbox 164 | rm -r /var/www/MISP/app/files/scripts/python-cybox 165 | rm -r /var/www/MISP/app/files/scripts/python-maec 166 | rm -r /var/www/MISP/app/files/scripts/python-stix 167 | EOF 168 | 169 | 170 | FROM php-base 171 | ENV DEBIAN_FRONTEND noninteractive 172 | ARG CORE_TAG 173 | ARG CORE_COMMIT 174 | ARG PHP_VER 175 | 176 | RUN apt-get install -y --no-install-recommends \ 177 | gettext \ 178 | procps \ 179 | sudo \ 180 | nginx \ 181 | supervisor \ 182 | cron \ 183 | openssl \ 184 | gpg \ 185 | gpg-agent \ 186 | mariadb-client \ 187 | rsync \ 188 | # PHP Requirements 189 | php7.4 \ 190 | php7.4-apcu \ 191 | php7.4-curl \ 192 | php7.4-xml \ 193 | php7.4-intl \ 194 | php7.4-bcmath \ 195 | php7.4-mbstring \ 196 | php7.4-mysql \ 197 | php7.4-redis \ 198 | php7.4-gd \ 199 | php7.4-fpm \ 200 | php7.4-zip \ 201 | php7.4-ldap \ 202 | libmagic1 \ 203 | libldap-common \ 204 | librdkafka1 \ 205 | libbrotli1 \ 206 | libsimdjson14 \ 207 | libzstd1 \ 208 | ssdeep \ 209 | libfuzzy2 \ 210 | # Unsure we need these 211 | zip unzip \ 212 | # Require for advanced an unattended configuration 213 | curl jq \ 214 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 215 | 216 | RUN update-alternatives --set php /usr/bin/php7.4 217 | 218 | # Install python modules 219 | COPY --from=python-build /wheels /wheels 220 | RUN pip install --no-cache-dir /wheels/*.whl && rm -rf /wheels 221 | RUN pip uninstall -y pip 222 | 223 | # PHP: install prebuilt libraries, then install the app's PHP deps 224 | COPY --from=php-build ["/usr/lib/php/${PHP_VER}/ssdeep.so", "/usr/lib/php/${PHP_VER}/rdkafka.so", "/usr/lib/php/${PHP_VER}/brotli.so", "/usr/lib/php/${PHP_VER}/simdjson.so", "/usr/lib/php/${PHP_VER}/zstd.so", "/usr/lib/php/${PHP_VER}/"] 225 | 226 | # Do an early chown to limit image size 227 | COPY --from=python-build --chown=www-data:www-data --chmod=0550 /var/www/MISP /var/www/MISP 228 | COPY --from=composer-build --chown=www-data:www-data --chmod=0550 /tmp/composer.lock /var/www/MISP/app/composer.lock 229 | COPY --from=composer-build --chown=www-data:www-data --chmod=0550 /tmp/Vendor /var/www/MISP/app/Vendor 230 | COPY --from=composer-build --chown=www-data:www-data --chmod=0550 /tmp/Plugin /var/www/MISP/app/Plugin 231 | 232 | # Gather these in one layer, only act on actual directories under /etc/php/ 233 | RUN <<-EOF 234 | set -- "ssdeep" "rdkafka" "brotli" "simdjson" "zstd" 235 | for mod in "$@"; do 236 | for dir in /etc/php/*/; do 237 | echo "extension=${mod}.so" > "${dir}mods-available/${mod}.ini" 238 | done; 239 | phpenmod "${mod}" 240 | done; 241 | phpenmod redis 242 | EOF 243 | 244 | # nginx 245 | RUN rm /etc/nginx/sites-enabled/*; mkdir -p /run/php /etc/nginx/certs 246 | 247 | # Make a copy of the file and configuration stores, so we can sync from it 248 | 249 | # The spirit of the upstream dockerization is to make: 250 | # 1) User and group aligned in terms of permissions 251 | # 2) Files executable and read only, because of some rogue scripts like 'cake' 252 | # 3) Directories writable, because sometimes MISP add new files 253 | 254 | RUN <<-EOF 255 | cp -R /var/www/MISP/app/files /var/www/MISP/app/files.dist 256 | cp -R /var/www/MISP/app/Config /var/www/MISP/app/Config.dist 257 | find /var/www/MISP \( ! -user www-data -or ! -group www-data \) -exec chown www-data:www-data '{}' +; 258 | find /var/www/MISP -not -perm 550 -type f -exec chmod 0550 '{}' +; 259 | find /var/www/MISP -not -perm 770 -type d -exec chmod 0770 '{}' +; 260 | # Diagnostics wants this file to be present and writable even if we do not use git in docker land 261 | touch /var/www/MISP/.git/ORIG_HEAD && chmod 0600 /var/www/MISP/.git/ORIG_HEAD && chown www-data:www-data /var/www/MISP/.git/ORIG_HEAD 262 | EOF 263 | 264 | # Copy all our image specific files to appropriate locations 265 | COPY files/ / 266 | ENTRYPOINT [ "/entrypoint.sh" ] 267 | 268 | # Change Workdirectory 269 | WORKDIR /var/www/MISP -------------------------------------------------------------------------------- /misp/misp-docker/core/files/configure_misp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source /rest_client.sh 4 | source /utilities.sh 5 | [ -z "$ADMIN_EMAIL" ] && export ADMIN_EMAIL="admin@admin.test" 6 | [ -z "$GPG_PASSPHRASE" ] && export GPG_PASSPHRASE="passphrase" 7 | [ -z "$REDIS_FQDN" ] && export REDIS_FQDN="redis" 8 | [ -z "$MISP_MODULES_FQDN" ] && export MISP_MODULES_FQDN="http://misp-modules" 9 | 10 | # Switches to selectively disable configuration logic 11 | [ -z "$AUTOCONF_GPG" ] && AUTOCONF_GPG="true" 12 | [ -z "$AUTOCONF_ADMIN_KEY" ] && AUTOCONF_ADMIN_KEY="true" 13 | [ -z "$OIDC_ENABLE" ] && OIDC_ENABLE="false" 14 | [ -z "$LDAP_ENABLE" ] && LDAP_ENABLE="false" 15 | [ -z "$ENABLE_DB_SETTINGS" ] && ENABLE_DB_SETTINGS="false" 16 | [ -z "$PROXY_ENABLE" ] && PROXY_ENABLE="false" 17 | [ -z "$DEBUG" ] && DEBUG=0 18 | 19 | # We now use envsubst for safe variable substitution with pseudo-json objects for env var enforcement 20 | # envsubst won't evaluate anything like $() or conditional variable expansion so lets do that here 21 | export PYTHON_BIN="$(which python3)" 22 | export GPG_BINARY="$(which gpg)" 23 | export SETTING_CONTACT="${MISP_CONTACT-$ADMIN_EMAIL}" 24 | export SETTING_EMAIL="${MISP_EMAIL-$ADMIN_EMAIL}" 25 | 26 | init_minimum_config() { 27 | # Temporarily disable DB to apply config file settings, reenable after if needed 28 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "MISP.system_setting_db" false 29 | init_settings "minimum_config" 30 | } 31 | 32 | init_configuration() { 33 | init_settings "db_enable" 34 | init_settings "initialisation" 35 | } 36 | 37 | init_workers() { 38 | echo "... starting background workers" 39 | stdbuf -oL supervisorctl start misp-workers:* 40 | } 41 | 42 | configure_gnupg() { 43 | if [ "$AUTOCONF_GPG" != "true" ]; then 44 | echo "... GPG auto configuration disabled" 45 | return 46 | fi 47 | 48 | export GPG_DIR=/var/www/MISP/.gnupg 49 | GPG_ASC=/var/www/MISP/app/webroot/gpg.asc 50 | GPG_TMP=/tmp/gpg.tmp 51 | 52 | if [ ! -f "${GPG_DIR}/trustdb.gpg" ]; then 53 | echo "... generating new GPG key in ${GPG_DIR}" 54 | cat >${GPG_TMP} < ${GPG_ASC} 80 | else 81 | echo "... found exported key ${GPG_ASC}" 82 | fi 83 | 84 | init_settings "gpg" 85 | } 86 | 87 | set_up_oidc() { 88 | if [[ "$OIDC_ENABLE" != "true" ]]; then 89 | echo "... OIDC authentication disabled" 90 | return 91 | fi 92 | 93 | if [[ -z "$OIDC_ROLES_MAPPING" ]]; then 94 | OIDC_ROLES_MAPPING="\"\"" 95 | fi 96 | 97 | # Check required variables 98 | # OIDC_ISSUER may be empty 99 | check_env_vars OIDC_PROVIDER_URL OIDC_CLIENT_ID OIDC_CLIENT_SECRET OIDC_ROLES_PROPERTY OIDC_ROLES_MAPPING OIDC_DEFAULT_ORG 100 | 101 | sudo -u www-data php /var/www/MISP/tests/modify_config.php modify "{ 102 | \"Security\": { 103 | \"auth\": [\"OidcAuth.Oidc\"] 104 | } 105 | }" > /dev/null 106 | 107 | sudo -u www-data php /var/www/MISP/tests/modify_config.php modify "{ 108 | \"OidcAuth\": { 109 | \"provider_url\": \"${OIDC_PROVIDER_URL}\", 110 | ${OIDC_ISSUER:+\"issuer\": \"${OIDC_ISSUER}\",} 111 | \"client_id\": \"${OIDC_CLIENT_ID}\", 112 | \"client_secret\": \"${OIDC_CLIENT_SECRET}\", 113 | \"roles_property\": \"${OIDC_ROLES_PROPERTY}\", 114 | \"role_mapper\": ${OIDC_ROLES_MAPPING}, 115 | \"default_org\": \"${OIDC_DEFAULT_ORG}\" 116 | } 117 | }" > /dev/null 118 | 119 | # Disable password confirmation as stated at https://github.com/MISP/MISP/issues/8116 120 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.require_password_confirmation" false 121 | } 122 | 123 | set_up_ldap() { 124 | if [[ "$LDAP_ENABLE" != "true" ]]; then 125 | echo "... LDAP authentication disabled" 126 | return 127 | fi 128 | 129 | # Check required variables 130 | # LDAP_SEARCH_FILTER may be empty 131 | check_env_vars LDAP_APACHE_ENV LDAP_SERVER LDAP_STARTTLS LDAP_READER_USER LDAP_READER_PASSWORD LDAP_DN LDAP_SEARCH_ATTRIBUTE LDAP_FILTER LDAP_DEFAULT_ROLE_ID LDAP_DEFAULT_ORG LDAP_OPT_PROTOCOL_VERSION LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_REFERRALS 132 | 133 | sudo -u www-data php /var/www/MISP/tests/modify_config.php modify "{ 134 | \"ApacheSecureAuth\": { 135 | \"apacheEnv\": \"${LDAP_APACHE_ENV}\", 136 | \"ldapServer\": \"${LDAP_SERVER}\", 137 | \"starttls\": ${LDAP_STARTTLS}, 138 | \"ldapProtocol\": ${LDAP_OPT_PROTOCOL_VERSION}, 139 | \"ldapNetworkTimeout\": ${LDAP_OPT_NETWORK_TIMEOUT}, 140 | \"ldapReaderUser\": \"${LDAP_READER_USER}\", 141 | \"ldapReaderPassword\": \"${LDAP_READER_PASSWORD}\", 142 | \"ldapDN\": \"${LDAP_DN}\", 143 | \"ldapSearchFilter\": \"${LDAP_SEARCH_FILTER}\", 144 | \"ldapSearchAttribut\": \"${LDAP_SEARCH_ATTRIBUTE}\", 145 | \"ldapFilter\": ${LDAP_FILTER}, 146 | \"ldapDefaultRoleId\": ${LDAP_DEFAULT_ROLE_ID}, 147 | \"ldapDefaultOrg\": \"${LDAP_DEFAULT_ORG}\", 148 | \"ldapAllowReferrals\": ${LDAP_OPT_REFERRALS}, 149 | \"ldapEmailField\": ${LDAP_EMAIL_FIELD} 150 | } 151 | }" > /dev/null 152 | 153 | # Disable password confirmation as stated at https://github.com/MISP/MISP/issues/8116 154 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.require_password_confirmation" false 155 | } 156 | 157 | set_up_aad() { 158 | if [[ "$AAD_ENABLE" != "true" ]]; then 159 | echo "... Entra (AzureAD) authentication disabled" 160 | return 161 | fi 162 | 163 | # Check required variables 164 | check_env_vars AAD_CLIENT_ID AAD_TENANT_ID AAD_CLIENT_SECRET AAD_REDIRECT_URI AAD_PROVIDER AAD_PROVIDER_USER AAD_MISP_ORGADMIN AAD_MISP_SITEADMIN AAD_CHECK_GROUPS 165 | 166 | # Note: Not necessary to edit bootstrap.php to load AadAuth Cake plugin because 167 | # existing loadAll() call in bootstrap.php already loads all available Cake plugins 168 | 169 | # Set auth mechanism to AAD in config.php file 170 | sudo -u www-data php /var/www/MISP/tests/modify_config.php modify "{ 171 | \"Security\": { 172 | \"auth\": [\"AadAuth.AadAuthenticate\"] 173 | } 174 | }" > /dev/null 175 | 176 | # Configure AAD auth settings from environment variables in config.php file 177 | sudo -u www-data php /var/www/MISP/tests/modify_config.php modify "{ 178 | \"AadAuth\": { 179 | \"client_id\": \"${AAD_CLIENT_ID}\", 180 | \"ad_tenant\": \"${AAD_TENANT_ID}\", 181 | \"client_secret\": \"${AAD_CLIENT_SECRET}\", 182 | \"redirect_uri\": \"${AAD_REDIRECT_URI}\", 183 | \"auth_provider\": \"${AAD_PROVIDER}\", 184 | \"auth_provider_user\": \"${AAD_PROVIDER_USER}\", 185 | \"misp_user\": \"${AAD_MISP_USER}\", 186 | \"misp_orgadmin\": \"${AAD_MISP_ORGADMIN}\", 187 | \"misp_siteadmin\": \"${AAD_MISP_SITEADMIN}\", 188 | \"check_ad_groups\": ${AAD_CHECK_GROUPS} 189 | } 190 | }" > /dev/null 191 | 192 | # Disable self-management, username change, and password change to prevent users from circumventing AAD login flow 193 | # Recommended per https://github.com/MISP/MISP/blob/2.4/app/Plugin/AadAuth/README.md 194 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "MISP.disableUserSelfManagement" true 195 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "MISP.disable_user_login_change" true 196 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "MISP.disable_user_password_change" true 197 | 198 | # Disable password confirmation as stated at https://github.com/MISP/MISP/issues/8116 199 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.require_password_confirmation" false 200 | } 201 | 202 | set_up_proxy() { 203 | if [[ "$PROXY_ENABLE" == "true" ]]; then 204 | echo "... configuring proxy settings" 205 | init_settings "proxy" 206 | else 207 | echo "... Proxy disabled" 208 | fi 209 | } 210 | 211 | apply_updates() { 212 | # Disable 'ZeroMQ_enable' to get better logs when applying updates 213 | # sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Plugin.ZeroMQ_enable" false 214 | # Run updates (strip colors since output might end up in a log) 215 | sudo -u www-data /var/www/MISP/app/Console/cake Admin runUpdates | stdbuf -oL sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g" 216 | # Re-enable 'ZeroMQ_enable' 217 | # sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Plugin.ZeroMQ_enable" true 218 | } 219 | 220 | init_user() { 221 | # Create the main user if it is not there already 222 | sudo -u www-data /var/www/MISP/app/Console/cake user init -q > /dev/null 2>&1 223 | 224 | echo "UPDATE misp.users SET email = \"${ADMIN_EMAIL}\" WHERE id = 1;" | ${MYSQLCMD} 225 | 226 | if [ ! -z "$ADMIN_ORG" ]; then 227 | echo "UPDATE misp.organisations SET name = \"${ADMIN_ORG}\" where id = 1;" | ${MYSQLCMD} 228 | fi 229 | 230 | if [ -n "$ADMIN_KEY" ]; then 231 | echo "... setting admin key to '${ADMIN_KEY}'" 232 | CHANGE_CMD=(sudo -u www-data /var/www/MISP/app/Console/cake User change_authkey 1 "${ADMIN_KEY}") 233 | elif [ -z "$ADMIN_KEY" ] && [ "$AUTOGEN_ADMIN_KEY" == "true" ]; then 234 | echo "... regenerating admin key (set \$ADMIN_KEY if you want it to change)" 235 | CHANGE_CMD=(sudo -u www-data /var/www/MISP/app/Console/cake User change_authkey 1) 236 | else 237 | echo "... admin user key auto generation disabled" 238 | fi 239 | 240 | if [[ -v CHANGE_CMD[@] ]]; then 241 | ADMIN_KEY=$("${CHANGE_CMD[@]}" | awk 'END {print $NF; exit}') 242 | echo "... admin user key set to '${ADMIN_KEY}'" 243 | fi 244 | 245 | if [ ! -z "$ADMIN_PASSWORD" ]; then 246 | echo "... setting admin password to '${ADMIN_PASSWORD}'" 247 | PASSWORD_POLICY=$(sudo -u www-data /var/www/MISP/app/Console/cake Admin getSetting "Security.password_policy_complexity" | jq ".value" -r) 248 | PASSWORD_LENGTH=$(sudo -u www-data /var/www/MISP/app/Console/cake Admin getSetting "Security.password_policy_length" | jq ".value" -r) 249 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.password_policy_length" 1 250 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.password_policy_complexity" '/.*/' 251 | sudo -u www-data /var/www/MISP/app/Console/cake User change_pw "${ADMIN_EMAIL}" "${ADMIN_PASSWORD}" 252 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.password_policy_complexity" "${PASSWORD_POLICY}" 253 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q "Security.password_policy_length" "${PASSWORD_LENGTH}" 254 | else 255 | echo "... setting admin password skipped" 256 | fi 257 | echo 'UPDATE misp.users SET change_pw = 0 WHERE id = 1;' | ${MYSQLCMD} 258 | } 259 | 260 | apply_critical_fixes() { 261 | init_settings "critical" 262 | 263 | # Kludge for handling Security.auth array. Unrecognised by tools like cake admin setsetting. 264 | local config_json=$(echo ''|/usr/bin/php) 265 | if $(echo $config_json |jq -e 'getpath(("Security.auth" | split("."))) == null'); then 266 | echo "Updating unset critical setting 'Security.auth' to 'Array()'..." 267 | sudo -u www-data php /var/www/MISP/tests/modify_config.php modify "{ 268 | \"Security\": { 269 | \"auth\": {} 270 | } 271 | }" > /dev/null 272 | fi 273 | } 274 | 275 | apply_optional_fixes() { 276 | init_settings "optional" 277 | } 278 | 279 | # Some settings return a value from cake Admin getSetting even if not set in config.php and database. 280 | # This means we cannot rely on that tool which inspects both db and file. 281 | # Leaving this here though in case the serverSettings model for those odd settings is fixed one day. 282 | #setting_is_set() { 283 | # local setting="$1" 284 | # local current_value="$(sudo -u www-data /var/www/MISP/app/Console/cake Admin getSetting $setting)" 285 | # local error_value="$(jq -r '.errorMessage' <<< $current_value)" 286 | # 287 | # if [[ "$current_value" =~ ^\{.*\}$ && "$error_value" != "Value not set." && "$error_value" != Invalid* ]]; then 288 | # return 0 289 | # else 290 | # return 1 291 | # fi 292 | #} 293 | 294 | # Kludgy alternative to using cake Admin getSetting. 295 | setting_is_set_alt() { 296 | local setting="$1" 297 | local config_json=$(echo ''|/usr/bin/php) 298 | local db_settings_enabled=$(jq -e 'getpath(("MISP.system_setting_db" | split("."))) // false' <<< $config_json) 299 | local setting_in_config_file=$(jq -e 'getpath(("'"$setting"'" | split("."))) != null' <<< $config_json) 300 | if $setting_in_config_file; then 301 | return 0 302 | elif $db_settings_enabled; then 303 | local setting_in_db=$(echo "SELECT EXISTS(SELECT 1 FROM $MYSQL_DATABASE.system_settings WHERE setting = \"${setting}\");" | ${MYSQLCMD}) 304 | if [[ $setting_in_db -eq 1 ]]; then 305 | return 0 306 | fi 307 | fi 308 | return 1 309 | } 310 | 311 | set_default_settings() { 312 | local settings_json="$1" 313 | local description="$2" 314 | 315 | for setting in $(jq -r 'keys[]' <<< $settings_json); do 316 | local default_value="$(jq -r '."'"$setting"'"["default_value"]' <<< $settings_json)" 317 | local command_args="$(jq -r '."'"$setting"'"["command_args"] // ""' <<< $settings_json)" 318 | 319 | set_safe_default "$setting" "$default_value" "$description" "$command_args" 320 | done 321 | } 322 | 323 | enforce_env_settings() { 324 | local settings_json="$1" 325 | local description="$2" 326 | for setting in $(jq -r 'keys[]' <<< $settings_json); do 327 | local default_value="$(jq -r '."'"$setting"'"["default_value"]' <<< $settings_json)" 328 | local command_args="$(jq -r '."'"$setting"'"["command_args"] // ""' <<< $settings_json)" 329 | echo "Enforcing $description setting '$setting' to env var or default value '$default_value'..." 330 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q $command_args "$setting" "$default_value" 331 | done 332 | } 333 | 334 | set_safe_default() { 335 | local setting="$1" 336 | local default_value="$2" 337 | local description="$3" 338 | local command_args="$4" 339 | 340 | if ! setting_is_set_alt "$setting"; then 341 | echo "Updating unset $description setting '$setting' to '$default_value'..." 342 | sudo -u www-data /var/www/MISP/app/Console/cake Admin setSetting -q $command_args "$setting" "$default_value" 343 | fi 344 | } 345 | 346 | init_settings() { 347 | local description="$1" 348 | local enforced="/etc/misp-docker/${description}.envars.json" 349 | local defaults="/etc/misp-docker/${description}.defaults.json" 350 | 351 | if [[ -e "$enforced" ]]; then 352 | echo "... enforcing env var settings" 353 | local settings_json="$(envsubst < $enforced)" 354 | enforce_env_settings "$settings_json" "$description" 355 | fi 356 | 357 | if [[ -e "$defaults" ]]; then 358 | echo "... checking for unset default settings" 359 | local settings_json="$(cat $defaults)" 360 | set_default_settings "$settings_json" "$description" 361 | fi 362 | } 363 | 364 | update_components() { 365 | sudo -u www-data /var/www/MISP/app/Console/cake Admin updateGalaxies 366 | sudo -u www-data /var/www/MISP/app/Console/cake Admin updateTaxonomies 367 | sudo -u www-data /var/www/MISP/app/Console/cake Admin updateWarningLists 368 | sudo -u www-data /var/www/MISP/app/Console/cake Admin updateNoticeLists 369 | sudo -u www-data /var/www/MISP/app/Console/cake Admin updateObjectTemplates "$CRON_USER_ID" 370 | } 371 | 372 | update_ca_certificates() { 373 | # Upgrade host os certificates 374 | update-ca-certificates 375 | # Upgrade cake cacert.pem file from Mozilla project 376 | echo "Updating /var/www/MISP/app/Lib/cakephp/lib/Cake/Config/cacert.pem..." 377 | sudo -E -u www-data curl -s --etag-compare /var/www/MISP/app/Lib/cakephp/lib/Cake/Config/etag.txt --etag-save /var/www/MISP/app/Lib/cakephp/lib/Cake/Config/etag.txt https://curl.se/ca/cacert.pem -o /var/www/MISP/app/Lib/cakephp/lib/Cake/Config/cacert.pem 378 | } 379 | 380 | create_sync_servers() { 381 | if [ -z "$ADMIN_KEY" ]; then 382 | echo "... admin key auto configuration is required to configure sync servers" 383 | return 384 | fi 385 | 386 | SPLITTED_SYNCSERVERS=$(echo $SYNCSERVERS | tr ',' '\n') 387 | for ID in $SPLITTED_SYNCSERVERS; do 388 | DATA="SYNCSERVERS_${ID}_DATA" 389 | 390 | # Validate #1 391 | NAME=$(echo "${!DATA}" | jq -r '.name') 392 | if [[ -z $NAME ]]; then 393 | echo "... error missing sync server name" 394 | continue 395 | fi 396 | 397 | # Skip sync server if we can 398 | echo "... searching sync server ${NAME}" 399 | SERVER_ID=$(get_server ${BASE_URL} ${ADMIN_KEY} ${NAME}) 400 | if [[ -n "$SERVER_ID" ]]; then 401 | echo "... found existing sync server ${NAME} with id ${SERVER_ID}" 402 | continue 403 | fi 404 | 405 | # Validate #2 406 | UUID=$(echo "${!DATA}" | jq -r '.remote_org_uuid') 407 | if [[ -z "$UUID" ]]; then 408 | echo "... error missing sync server remote_org_uuid" 409 | continue 410 | fi 411 | 412 | # Get remote organization 413 | echo "... searching remote organization ${UUID}" 414 | ORG_ID=$(get_organization ${BASE_URL} ${ADMIN_KEY} ${UUID}) 415 | if [[ -z "$ORG_ID" ]]; then 416 | # Add remote organization if missing 417 | echo "... adding missing organization ${UUID}" 418 | add_organization ${BASE_URL} ${ADMIN_KEY} ${NAME} false ${UUID} > /dev/null 419 | ORG_ID=$(get_organization ${BASE_URL} ${ADMIN_KEY} ${UUID}) 420 | fi 421 | 422 | # Add sync server 423 | echo "... adding new sync server ${NAME} with organization id ${ORG_ID}" 424 | JSON_DATA=$(echo "${!DATA}" | jq --arg org_id ${ORG_ID} 'del(.remote_org_uuid) | . + {remote_org_id: $org_id} | del(..|select(. == ""))') 425 | add_server ${BASE_URL} ${ADMIN_KEY} "$JSON_DATA" > /dev/null 426 | done 427 | } 428 | 429 | echo "MISP | Update CA certificates ..." && update_ca_certificates 430 | 431 | echo "MISP | Apply minimum configuration directives ..." && init_minimum_config 432 | 433 | echo "MISP | Apply DB updates ..." && apply_updates 434 | 435 | echo "MISP | Initialize configuration ..." && init_configuration 436 | 437 | echo "MISP | Initialize workers ..." && init_workers 438 | 439 | echo "MISP | Configure GPG key ..." && configure_gnupg 440 | 441 | echo "MISP | Init default user and organization ..." && init_user 442 | 443 | echo "MISP | Resolve critical issues ..." && apply_critical_fixes 444 | 445 | echo "MISP | Resolve non-critical issues ..." && apply_optional_fixes 446 | 447 | echo "MISP | Create sync servers ..." && create_sync_servers 448 | 449 | echo "MISP | Update components ..." && update_components 450 | 451 | echo "MISP | Set Up OIDC ..." && set_up_oidc 452 | 453 | echo "MISP | Set Up LDAP ..." && set_up_ldap 454 | 455 | echo "MISP | Set Up AAD ..." && set_up_aad 456 | 457 | echo "MISP | Set Up Proxy ..." && set_up_proxy 458 | 459 | echo "MISP | Mark instance live" 460 | sudo -u www-data /var/www/MISP/app/Console/cake Admin live 1 461 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # export env variables again so they are not mandatory in docker-compose.yml in a backward compatible manner 4 | export NUM_WORKERS_DEFAULT=${NUM_WORKERS_DEFAULT:-${WORKERS:-5}} 5 | export NUM_WORKERS_PRIO=${NUM_WORKERS_PRIO:-${WORKERS:-5}} 6 | export NUM_WORKERS_EMAIL=${NUM_WORKERS_EMAIL:-${WORKERS:-5}} 7 | export NUM_WORKERS_UPDATE=${NUM_WORKERS_UPDATE:-${WORKERS:-1}} 8 | export NUM_WORKERS_CACHE=${NUM_WORKERS_CACHE:-${WORKERS:-5}} 9 | 10 | # start supervisord using the main configuration file so we have a socket interface 11 | /usr/bin/supervisord -c /etc/supervisor/supervisord.conf 12 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/entrypoint_cron.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$CRON_USER_ID" ] && CRON_USER_ID=1 4 | 5 | term_procs() { 6 | echo "Entrypoint CRON caught SIGTERM signal!" 7 | echo "Killing process $p1_pid" 8 | kill -TERM "$p1_pid" 2>/dev/null 9 | echo "Killing process $p2_pid" 10 | kill -TERM "$p2_pid" 2>/dev/null 11 | } 12 | 13 | trap term_procs SIGTERM 14 | 15 | # Create the misp cron tab 16 | cat << EOF > /etc/cron.d/misp 17 | 20 2 * * * www-data /var/www/MISP/app/Console/cake Server cacheFeed "$CRON_USER_ID" all > /tmp/cronlog 2>&1 18 | 30 2 * * * www-data /var/www/MISP/app/Console/cake Server fetchFeed "$CRON_USER_ID" all > /tmp/cronlog 2>&1 19 | 20 | 0 0 * * * www-data /var/www/MISP/app/Console/cake Server pullAll "$CRON_USER_ID" > /tmp/cronlog 2>&1 21 | 0 1 * * * www-data /var/www/MISP/app/Console/cake Server pushAll "$CRON_USER_ID" > /tmp/cronlog 2>&1 22 | 23 | 00 3 * * * www-data /var/www/MISP/app/Console/cake Admin updateGalaxies > /tmp/cronlog 2>&1 24 | 10 3 * * * www-data /var/www/MISP/app/Console/cake Admin updateTaxonomies > /tmp/cronlog 2>&1 25 | 20 3 * * * www-data /var/www/MISP/app/Console/cake Admin updateWarningLists > /tmp/cronlog 2>&1 26 | 30 3 * * * www-data /var/www/MISP/app/Console/cake Admin updateNoticeLists > /tmp/cronlog 2>&1 27 | 45 3 * * * www-data /var/www/MISP/app/Console/cake Admin updateObjectTemplates "$CRON_USER_ID" > /tmp/cronlog 2>&1 28 | 29 | EOF 30 | 31 | # Build a fifo buffer for the cron logs, 777 so anyone can write to it 32 | if [[ ! -p /tmp/cronlog ]]; then 33 | mkfifo -m 777 /tmp/cronlog 34 | fi 35 | 36 | # Build another fifo for the cron pipe 37 | if [[ ! -p /tmp/cronpipe ]]; then 38 | mkfifo /tmp/cronpipe 39 | fi 40 | 41 | # Execute the cron pipe 42 | cron -l -f > /tmp/cronpipe & p1_pid=$! 43 | tail -f /tmp/cronlog < /tmp/cronpipe & p2_pid=$! 44 | 45 | # Wait for both processes of the cron pipe 46 | wait "$p2_pid" 47 | wait "$p1_pid" 48 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/entrypoint_fpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$REDIS_FQDN" ] && REDIS_FQDN=redis 4 | 5 | term_proc() { 6 | echo "Entrypoint FPM caught SIGTERM signal!" 7 | echo "Killing process $master_pid" 8 | kill -TERM "$master_pid" 2>/dev/null 9 | } 10 | 11 | trap term_proc SIGTERM 12 | 13 | change_php_vars() { 14 | for FILE in /etc/php/*/fpm/php.ini 15 | do 16 | [[ -e $FILE ]] || break 17 | sed -i "s/memory_limit = .*/memory_limit = 2048M/" "$FILE" 18 | sed -i "s/max_execution_time = .*/max_execution_time = 300/" "$FILE" 19 | sed -i "s/upload_max_filesize = .*/upload_max_filesize = 50M/" "$FILE" 20 | sed -i "s/post_max_size = .*/post_max_size = 50M/" "$FILE" 21 | sed -i "s/session.save_handler = .*/session.save_handler = redis/" "$FILE" 22 | sed -i "s|.*session.save_path = .*|session.save_path = '$(echo $REDIS_FQDN | grep -E '^\w+://' || echo tcp://$REDIS_FQDN):6379'|" "$FILE" 23 | sed -i "s/session.sid_length = .*/session.sid_length = 64/" "$FILE" 24 | sed -i "s/session.use_strict_mode = .*/session.use_strict_mode = 1/" "$FILE" 25 | done 26 | } 27 | 28 | echo "Configure PHP | Change PHP values ..." && change_php_vars 29 | 30 | echo "Configure PHP | Starting PHP FPM" 31 | /usr/sbin/php-fpm7.4 -R -F & master_pid=$! 32 | 33 | # Wait for it 34 | wait "$master_pid" 35 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/entrypoint_nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | term_proc() { 4 | echo "Entrypoint NGINX caught SIGTERM signal!" 5 | echo "Killing process $master_pid" 6 | kill -TERM "$master_pid" 2>/dev/null 7 | } 8 | 9 | trap term_proc SIGTERM 10 | 11 | [ -z "$MYSQL_HOST" ] && MYSQL_HOST=db 12 | [ -z "$MYSQL_PORT" ] && MYSQL_PORT=3306 13 | [ -z "$MYSQL_USER" ] && MYSQL_USER=misp 14 | [ -z "$MYSQL_PASSWORD" ] && MYSQL_PASSWORD=example 15 | [ -z "$MYSQL_DATABASE" ] && MYSQL_DATABASE=misp 16 | [ -z "$MYSQLCMD" ] && export MYSQLCMD="mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -P $MYSQL_PORT -h $MYSQL_HOST -r -N $MYSQL_DATABASE" 17 | [ -z "$CRON_USER_ID" ] && export CRON_USER_ID="1" 18 | [ -z "$BASE_URL" ] && export BASE_URL="https://localhost" 19 | [ -z "$DISABLE_IPV6" ] && export DISABLE_IPV6=false 20 | [ -z "$DISABLE_SSL_REDIRECT" ] && export DISABLE_SSL_REDIRECT=false 21 | [ -z "$SMTP_FQDN" ] && export SMTP_FQDN=mail 22 | 23 | init_mysql(){ 24 | # Test when MySQL is ready.... 25 | # wait for Database come ready 26 | isDBup () { 27 | echo "SHOW STATUS" | $MYSQLCMD 1>/dev/null 28 | echo $? 29 | } 30 | 31 | isDBinitDone () { 32 | # Table attributes has existed since at least v2.1 33 | echo "DESCRIBE attributes" | $MYSQLCMD 1>/dev/null 34 | echo $? 35 | } 36 | 37 | RETRY=100 38 | until [ $(isDBup) -eq 0 ] || [ $RETRY -le 0 ] ; do 39 | echo "... waiting for database to come up" 40 | sleep 5 41 | RETRY=$(( RETRY - 1)) 42 | done 43 | if [ $RETRY -le 0 ]; then 44 | >&2 echo "... error: Could not connect to Database on $MYSQL_HOST:$MYSQL_PORT" 45 | exit 1 46 | fi 47 | 48 | if [ $(isDBinitDone) -eq 0 ]; then 49 | echo "... database has already been initialized" 50 | else 51 | echo "... database has not been initialized, importing MySQL scheme..." 52 | $MYSQLCMD < /var/www/MISP/INSTALL/MYSQL.sql 53 | fi 54 | } 55 | 56 | init_misp_data_files(){ 57 | # Init config (shared with host) 58 | echo "... initialize configuration files" 59 | MISP_APP_CONFIG_PATH=/var/www/MISP/app/Config 60 | # workaround for https://forums.docker.com/t/sed-couldnt-open-temporary-file-xyz-permission-denied-when-using-virtiofs/125473 61 | # [ -f $MISP_APP_CONFIG_PATH/bootstrap.php ] || cp $MISP_APP_CONFIG_PATH.dist/bootstrap.default.php $MISP_APP_CONFIG_PATH/bootstrap.php 62 | # [ -f $MISP_APP_CONFIG_PATH/database.php ] || cp $MISP_APP_CONFIG_PATH.dist/database.default.php $MISP_APP_CONFIG_PATH/database.php 63 | # [ -f $MISP_APP_CONFIG_PATH/core.php ] || cp $MISP_APP_CONFIG_PATH.dist/core.default.php $MISP_APP_CONFIG_PATH/core.php 64 | # [ -f $MISP_APP_CONFIG_PATH/config.php ] || cp $MISP_APP_CONFIG_PATH.dist/config.default.php $MISP_APP_CONFIG_PATH/config.php 65 | # [ -f $MISP_APP_CONFIG_PATH/email.php ] || cp $MISP_APP_CONFIG_PATH.dist/email.php $MISP_APP_CONFIG_PATH/email.php 66 | # [ -f $MISP_APP_CONFIG_PATH/routes.php ] || cp $MISP_APP_CONFIG_PATH.dist/routes.php $MISP_APP_CONFIG_PATH/routes.php 67 | [ -f $MISP_APP_CONFIG_PATH/bootstrap.php ] || dd if=$MISP_APP_CONFIG_PATH.dist/bootstrap.default.php of=$MISP_APP_CONFIG_PATH/bootstrap.php 68 | [ -f $MISP_APP_CONFIG_PATH/database.php ] || dd if=$MISP_APP_CONFIG_PATH.dist/database.default.php of=$MISP_APP_CONFIG_PATH/database.php 69 | [ -f $MISP_APP_CONFIG_PATH/core.php ] || dd if=$MISP_APP_CONFIG_PATH.dist/core.default.php of=$MISP_APP_CONFIG_PATH/core.php 70 | [ -f $MISP_APP_CONFIG_PATH/config.php.template ] || dd if=$MISP_APP_CONFIG_PATH.dist/config.default.php of=$MISP_APP_CONFIG_PATH/config.php.template 71 | [ -f $MISP_APP_CONFIG_PATH/config.php ] || echo -e "" > $MISP_APP_CONFIG_PATH/config.php 72 | [ -f $MISP_APP_CONFIG_PATH/email.php ] || dd if=$MISP_APP_CONFIG_PATH.dist/email.php of=$MISP_APP_CONFIG_PATH/email.php 73 | [ -f $MISP_APP_CONFIG_PATH/routes.php ] || dd if=$MISP_APP_CONFIG_PATH.dist/routes.php of=$MISP_APP_CONFIG_PATH/routes.php 74 | 75 | echo "... initialize database.php settings" 76 | # workaround for https://forums.docker.com/t/sed-couldnt-open-temporary-file-xyz-permission-denied-when-using-virtiofs/125473 77 | # sed -i "s/localhost/$MYSQL_HOST/" $MISP_APP_CONFIG_PATH/database.php 78 | # sed -i "s/db\s*login/$MYSQL_USER/" $MISP_APP_CONFIG_PATH/database.php 79 | # sed -i "s/3306/$MYSQL_PORT/" $MISP_APP_CONFIG_PATH/database.php 80 | # sed -i "s/db\s*password/$MYSQL_PASSWORD/" $MISP_APP_CONFIG_PATH/database.php 81 | # sed -i "s/'database' => 'misp'/'database' => '$MYSQL_DATABASE'/" $MISP_APP_CONFIG_PATH/database.php 82 | chmod +w $MISP_APP_CONFIG_PATH/database.php 83 | sed "s/localhost/$MYSQL_HOST/" $MISP_APP_CONFIG_PATH/database.php > tmp; cat tmp > $MISP_APP_CONFIG_PATH/database.php; rm tmp 84 | sed "s/db\s*login/$MYSQL_USER/" $MISP_APP_CONFIG_PATH/database.php > tmp; cat tmp > $MISP_APP_CONFIG_PATH/database.php; rm tmp 85 | sed "s/3306/$MYSQL_PORT/" $MISP_APP_CONFIG_PATH/database.php > tmp; cat tmp > $MISP_APP_CONFIG_PATH/database.php; rm tmp 86 | sed "s/db\s*password/$MYSQL_PASSWORD/" $MISP_APP_CONFIG_PATH/database.php > tmp; cat tmp > $MISP_APP_CONFIG_PATH/database.php; rm tmp 87 | sed "s/'database' => 'misp'/'database' => '$MYSQL_DATABASE'/" $MISP_APP_CONFIG_PATH/database.php > tmp; cat tmp > $MISP_APP_CONFIG_PATH/database.php; rm tmp 88 | 89 | echo "... initialize email.php settings" 90 | chmod +w $MISP_APP_CONFIG_PATH/email.php 91 | tee $MISP_APP_CONFIG_PATH/email.php > /dev/null < 'Smtp', 96 | 'from' => array('misp-dev@admin.test' => 'Misp DEV'), 97 | 'host' => '$SMTP_FQDN', 98 | 'port' => 25, 99 | 'timeout' => 30, 100 | 'client' => null, 101 | 'log' => false, 102 | ); 103 | public \$smtp = array( 104 | 'transport' => 'Smtp', 105 | 'from' => array('misp-dev@admin.test' => 'Misp DEV'), 106 | 'host' => '$SMTP_FQDN', 107 | 'port' => 25, 108 | 'timeout' => 30, 109 | 'client' => null, 110 | 'log' => false, 111 | ); 112 | public \$fast = array( 113 | 'from' => 'misp-dev@admin.test', 114 | 'sender' => null, 115 | 'to' => null, 116 | 'cc' => null, 117 | 'bcc' => null, 118 | 'replyTo' => null, 119 | 'readReceipt' => null, 120 | 'returnPath' => null, 121 | 'messageId' => true, 122 | 'subject' => null, 123 | 'message' => null, 124 | 'headers' => null, 125 | 'viewRender' => null, 126 | 'template' => false, 127 | 'layout' => false, 128 | 'viewVars' => null, 129 | 'attachments' => null, 130 | 'emailFormat' => null, 131 | 'transport' => 'Smtp', 132 | 'host' => '$SMTP_FQDN', 133 | 'port' => 25, 134 | 'timeout' => 30, 135 | 'client' => null, 136 | 'log' => true, 137 | ); 138 | } 139 | EOT 140 | chmod -w $MISP_APP_CONFIG_PATH/email.php 141 | 142 | # Init files (shared with host) 143 | echo "... initialize app files" 144 | MISP_APP_FILES_PATH=/var/www/MISP/app/files 145 | if [ ! -f ${MISP_APP_FILES_PATH}/INIT ]; then 146 | cp -R ${MISP_APP_FILES_PATH}.dist/* ${MISP_APP_FILES_PATH} 147 | touch ${MISP_APP_FILES_PATH}/INIT 148 | fi 149 | } 150 | 151 | update_misp_data_files(){ 152 | for DIR in $(ls /var/www/MISP/app/files.dist); do 153 | if [ "$DIR" = "certs" ] || [ "$DIR" = "img" ] || [ "$DIR" == "taxonomies" ] ; then 154 | echo "... rsync -azh \"/var/www/MISP/app/files.dist/$DIR\" \"/var/www/MISP/app/files/\"" 155 | rsync -azh "/var/www/MISP/app/files.dist/$DIR" "/var/www/MISP/app/files/" 156 | else 157 | echo "... rsync -azh --delete \"/var/www/MISP/app/files.dist/$DIR\" \"/var/www/MISP/app/files/\"" 158 | rsync -azh --delete "/var/www/MISP/app/files.dist/$DIR" "/var/www/MISP/app/files/" 159 | fi 160 | done 161 | } 162 | 163 | enforce_misp_data_permissions(){ 164 | echo "... chown -R www-data:www-data /var/www/MISP/app/tmp" && find /var/www/MISP/app/tmp \( ! -user www-data -or ! -group www-data \) -exec chown www-data:www-data {} + 165 | # Files are also executable and read only, because we have some rogue scripts like 'cake' and we can not do a full inventory 166 | echo "... chmod -R 0550 files /var/www/MISP/app/tmp" && find /var/www/MISP/app/tmp -not -perm 550 -type f -exec chmod 0550 {} + 167 | # Directories are also writable, because there seems to be a requirement to add new files every once in a while 168 | echo "... chmod -R 0770 directories /var/www/MISP/app/tmp" && find /var/www/MISP/app/tmp -not -perm 770 -type d -exec chmod 0770 {} + 169 | # We make 'files' and 'tmp' (logs) directories and files user and group writable (we removed the SGID bit) 170 | echo "... chmod -R u+w,g+w /var/www/MISP/app/tmp" && chmod -R u+w,g+w /var/www/MISP/app/tmp 171 | 172 | echo "... chown -R www-data:www-data /var/www/MISP/app/files" && find /var/www/MISP/app/files \( ! -user www-data -or ! -group www-data \) -exec chown www-data:www-data {} + 173 | # Files are also executable and read only, because we have some rogue scripts like 'cake' and we can not do a full inventory 174 | echo "... chmod -R 0550 files /var/www/MISP/app/files" && find /var/www/MISP/app/files -not -perm 550 -type f -exec chmod 0550 {} + 175 | # Directories are also writable, because there seems to be a requirement to add new files every once in a while 176 | echo "... chmod -R 0770 directories /var/www/MISP/app/files" && find /var/www/MISP/app/files -not -perm 770 -type d -exec chmod 0770 {} + 177 | # We make 'files' and 'tmp' (logs) directories and files user and group writable (we removed the SGID bit) 178 | echo "... chmod -R u+w,g+w /var/www/MISP/app/files" && chmod -R u+w,g+w /var/www/MISP/app/files 179 | 180 | echo "... chown -R www-data:www-data /var/www/MISP/app/Config" && find /var/www/MISP/app/Config \( ! -user www-data -or ! -group www-data \) -exec chown www-data:www-data {} + 181 | # Files are also executable and read only, because we have some rogue scripts like 'cake' and we can not do a full inventory 182 | echo "... chmod -R 0550 files /var/www/MISP/app/Config ..." && find /var/www/MISP/app/Config -not -perm 550 -type f -exec chmod 0550 {} + 183 | # Directories are also writable, because there seems to be a requirement to add new files every once in a while 184 | echo "... chmod -R 0770 directories /var/www/MISP/app/Config" && find /var/www/MISP/app/Config -not -perm 770 -type d -exec chmod 0770 {} + 185 | # We make configuration files read only 186 | echo "... chmod 600 /var/www/MISP/app/Config/{config,database,email}.php" && chmod 600 /var/www/MISP/app/Config/{config,database,email}.php 187 | } 188 | 189 | flip_nginx() { 190 | local live="$1"; 191 | local reload="$2"; 192 | 193 | if [[ "$live" = "true" ]]; then 194 | NGINX_DOC_ROOT=/var/www/MISP/app/webroot 195 | elif [[ -x /custom/files/var/www/html/index.php ]]; then 196 | NGINX_DOC_ROOT=/custom/files/var/www/html/ 197 | else 198 | NGINX_DOC_ROOT=/var/www/html/ 199 | fi 200 | 201 | # must be valid for all roots 202 | echo "... nginx docroot set to ${NGINX_DOC_ROOT}" 203 | sed -i "s|root.*var/www.*|root ${NGINX_DOC_ROOT};|" /etc/nginx/includes/misp 204 | 205 | if [[ "$reload" = "true" ]]; then 206 | echo "... nginx reloaded" 207 | nginx -s reload 208 | fi 209 | } 210 | 211 | init_nginx() { 212 | # Testing for files also test for links, and generalize better to mounted files 213 | if [[ ! -f "/etc/nginx/sites-enabled/misp80" ]]; then 214 | echo "... enabling port 80 redirect" 215 | ln -s /etc/nginx/sites-available/misp80 /etc/nginx/sites-enabled/misp80 216 | else 217 | echo "... port 80 already enabled" 218 | fi 219 | if [[ "$DISABLE_IPV6" = "true" ]]; then 220 | echo "... disabling IPv6 on port 80" 221 | sed -i "s/[^#] listen \[/ # listen \[/" /etc/nginx/sites-enabled/misp80 222 | else 223 | echo "... enabling IPv6 on port 80" 224 | sed -i "s/# listen \[/listen \[/" /etc/nginx/sites-enabled/misp80 225 | fi 226 | if [[ "$DISABLE_SSL_REDIRECT" = "true" ]]; then 227 | echo "... disabling SSL redirect" 228 | sed -i "s/[^#] return / # return /" /etc/nginx/sites-enabled/misp80 229 | sed -i "s/# include /include /" /etc/nginx/sites-enabled/misp80 230 | else 231 | echo "... enabling SSL redirect" 232 | sed -i "s/[^#] include / # include /" /etc/nginx/sites-enabled/misp80 233 | sed -i "s/# return /return /" /etc/nginx/sites-enabled/misp80 234 | fi 235 | 236 | # Testing for files also test for links, and generalize better to mounted files 237 | if [[ ! -f "/etc/nginx/sites-enabled/misp443" ]]; then 238 | echo "... enabling port 443" 239 | ln -s /etc/nginx/sites-available/misp443 /etc/nginx/sites-enabled/misp443 240 | else 241 | echo "... port 443 already enabled" 242 | fi 243 | if [[ "$DISABLE_IPV6" = "true" ]]; then 244 | echo "... disabling IPv6 on port 443" 245 | sed -i "s/[^#] listen \[/ # listen \[/" /etc/nginx/sites-enabled/misp443 246 | else 247 | echo "... enabling IPv6 on port 443" 248 | sed -i "s/# listen \[/listen \[/" /etc/nginx/sites-enabled/misp443 249 | fi 250 | 251 | if [[ ! -f /etc/nginx/certs/cert.pem || ! -f /etc/nginx/certs/key.pem ]]; then 252 | echo "... generating new self-signed TLS certificate" 253 | openssl req -x509 -subj '/CN=localhost' -nodes -newkey rsa:4096 -keyout /etc/nginx/certs/key.pem -out /etc/nginx/certs/cert.pem -days 365 \ 254 | -addext "subjectAltName = DNS:localhost, IP:127.0.0.1, IP:::1" 255 | else 256 | echo "... TLS certificates found" 257 | fi 258 | 259 | if [[ ! -f /etc/nginx/certs/dhparams.pem ]]; then 260 | echo "... generating new DH parameters" 261 | openssl dhparam -out /etc/nginx/certs/dhparams.pem 2048 262 | else 263 | echo "... DH parameters found" 264 | fi 265 | 266 | flip_nginx false false 267 | } 268 | 269 | 270 | # Initialize MySQL 271 | echo "INIT | Initialize MySQL ..." && init_mysql 272 | 273 | # Initialize NGINX 274 | echo "INIT | Initialize NGINX ..." && init_nginx 275 | nginx -g 'daemon off;' & master_pid=$! 276 | 277 | # Initialize MISP 278 | echo "INIT | Initialize MISP files and configurations ..." && init_misp_data_files 279 | echo "INIT | Update MISP app/files directory ..." && update_misp_data_files 280 | echo "INIT | Enforce MISP permissions ..." && enforce_misp_data_permissions 281 | echo "INIT | Flip NGINX live ..." && flip_nginx true true 282 | 283 | # Run configure MISP script 284 | echo "INIT | Configure MISP installation ..." 285 | /configure_misp.sh 286 | 287 | if [[ -x /custom/files/customize_misp.sh ]]; then 288 | echo "INIT | Customize MISP installation ..." 289 | /custom/files/customize_misp.sh 290 | fi 291 | 292 | # Wait for it 293 | wait "$master_pid" 294 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/critical.defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.host_org_id": { 3 | "default_value": 1 4 | }, 5 | "Plugin.Action_services_enable": { 6 | "default_value": false 7 | }, 8 | "Plugin.Enrichment_hover_enable": { 9 | "default_value": false 10 | }, 11 | "Plugin.Enrichment_hover_popover_only": { 12 | "default_value": false 13 | }, 14 | "Security.csp_enforce": { 15 | "default_value": true 16 | }, 17 | "Security.do_not_log_authkeys": { 18 | "default_value": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/critical.envars.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.external_baseurl": { 3 | "default_value": "${BASE_URL}" 4 | }, 5 | "Security.rest_client_baseurl": { 6 | "default_value": "${BASE_URL}" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/db_enable.envars.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.system_setting_db": { 3 | "default_value": "$ENABLE_DB_SETTINGS" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/gpg.defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "GnuPG.onlyencrypted": { 3 | "default_value": false 4 | }, 5 | "SMIME.enabled": { 6 | "default_value": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/gpg.envars.json: -------------------------------------------------------------------------------- 1 | { 2 | "GnuPG.email": { 3 | "default_value": "${SETTING_EMAIL}" 4 | }, 5 | "GnuPG.homedir": { 6 | "default_value": "${GPG_DIR}" 7 | }, 8 | "GnuPG.password": { 9 | "default_value": "${GPG_PASSPHRASE}" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/initialisation.defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.ca_path": { 3 | "default_value": "/var/www/MISP/app/Lib/cakephp/lib/Cake/Config/cacert.pem" 4 | }, 5 | "MISP.language": { 6 | "default_value": "eng" 7 | }, 8 | "MISP.showorg": { 9 | "default_value": true 10 | }, 11 | "MISP.default_event_distribution": { 12 | "default_value": 1 13 | }, 14 | "MISP.default_event_tag_collection": { 15 | "default_value": 0 16 | }, 17 | "MISP.default_attribute_distribution": { 18 | "default_value": "event" 19 | }, 20 | "MISP.proposals_block_attributes": { 21 | "default_value": false 22 | }, 23 | "MISP.tagging": { 24 | "default_value": true 25 | }, 26 | "MISP.enableEventBlocklisting": { 27 | "default_value": true 28 | }, 29 | "MISP.enableOrgBlocklisting": { 30 | "default_value": true 31 | }, 32 | "MISP.store_api_access_time": { 33 | "default_value": false 34 | }, 35 | "MISP.log_auth": { 36 | "default_value": true 37 | }, 38 | "MISP.log_new_audit": { 39 | "default_value": true 40 | }, 41 | "MISP.disable_user_login_change": { 42 | "default_value": false 43 | }, 44 | "MISP.incoming_tags_disabled_by_default": { 45 | "default_value": false 46 | }, 47 | "MISP.full_tags_on_event_index": { 48 | "default_value": 1 49 | }, 50 | "MISP.event_alert_republish_ban": { 51 | "default_value": true 52 | }, 53 | "MISP.showCorrelationsOnIndex": { 54 | "default_value": true 55 | }, 56 | "MISP.server_settings_skip_backup_rotate": { 57 | "default_value": false 58 | }, 59 | "MISP.user_email_notification_ban": { 60 | "default_value": true 61 | }, 62 | "MISP.delegation": { 63 | "default_value": true 64 | }, 65 | "MISP.take_ownership_xml_import": { 66 | "default_value": false 67 | }, 68 | "MISP.unpublishedprivate": { 69 | "default_value": false 70 | }, 71 | "MISP.terms_download": { 72 | "default_value": false 73 | }, 74 | "MISP.showorgalternate": { 75 | "default_value": false 76 | }, 77 | "MISP.event_alert_republish_ban_refresh_on_retry": { 78 | "default_value": true 79 | }, 80 | "MISP.event_alert_republish_ban_threshold": { 81 | "default_value": 120 82 | }, 83 | "Plugin.ZeroMQ_enable": { 84 | "default_value": false 85 | }, 86 | "Plugin.Enrichment_services_enable": { 87 | "default_value": true 88 | }, 89 | "Plugin.Import_services_enable": { 90 | "default_value": true 91 | }, 92 | "Plugin.Export_services_enable": { 93 | "default_value": true 94 | }, 95 | "Plugin.Cortex_services_enable": { 96 | "default_value": false 97 | }, 98 | "Security.advanced_authkeys": { 99 | "default_value": true 100 | }, 101 | "Security.disable_browser_cache": { 102 | "default_value": true 103 | }, 104 | "Security.check_sec_fetch_site_header": { 105 | "default_value": true 106 | }, 107 | "Security.encryption_key": { 108 | "default_value": "", 109 | "command_args": "-f" 110 | }, 111 | "Security.username_in_response_header": { 112 | "default_value": true 113 | }, 114 | "Security.do_not_log_authkeys": { 115 | "default_value": true 116 | }, 117 | "Security.log_each_individual_auth_fail": { 118 | "default_value": true 119 | }, 120 | "Security.alert_on_suspicious_logins": { 121 | "default_value": true 122 | }, 123 | "Security.require_password_confirmation": { 124 | "default_value": true 125 | }, 126 | "SecureAuth.amount": { 127 | "default_value": 5 128 | }, 129 | "SecureAuth.expire": { 130 | "default_value": 300 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/initialisation.envars.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": { 3 | "default_value": "${DEBUG}", 4 | "command_args": "-f" 5 | }, 6 | "MISP.baseurl": { 7 | "default_value": "${BASE_URL}" 8 | }, 9 | "MISP.email": { 10 | "default_value": "${SETTING_EMAIL}" 11 | }, 12 | "MISP.contact": { 13 | "default_value": "${SETTING_CONTACT}" 14 | }, 15 | "Plugin.ZeroMQ_redis_host": { 16 | "default_value": "${REDIS_FQDN}" 17 | }, 18 | "Plugin.Enrichment_services_url": { 19 | "default_value": "${MISP_MODULES_FQDN}" 20 | }, 21 | "Plugin.Import_services_url": { 22 | "default_value": "${MISP_MODULES_FQDN}" 23 | }, 24 | "Plugin.Action_services_url": { 25 | "default_value": "${MISP_MODULES_FQDN}" 26 | }, 27 | "Plugin.Export_services_url": { 28 | "default_value": "${MISP_MODULES_FQDN}" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/minimum_config.defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.tmpdir": { 3 | "default_value": "/var/www/MISP/app/tmp" 4 | }, 5 | "MISP.attachments_dir": { 6 | "default_value": "/var/www/MISP/app/files" 7 | }, 8 | "MISP.download_gpg_from_homedir": { 9 | "default_value": false 10 | }, 11 | "MISP.background_jobs": { 12 | "default_value": true 13 | }, 14 | "MISP.osuser": { 15 | "default_value": "www-data" 16 | }, 17 | "MISP.online_version_check": { 18 | "default_value": true 19 | }, 20 | "MISP.self_update": { 21 | "default_value": false 22 | }, 23 | "MISP.ca_path": { 24 | "default_value": "/etc/ssl/certs/ca-certificates.crt", 25 | "command_args": "-f" 26 | }, 27 | "MISP.redis_port": { 28 | "default_value": 6379 29 | }, 30 | "MISP.redis_database": { 31 | "default_value": 13 32 | }, 33 | "MISP.redis_password": { 34 | "default_value": "" 35 | }, 36 | "MISP.menu_custom_right_link": { 37 | "default_value": "" 38 | }, 39 | "MISP.menu_custom_right_link_html": { 40 | "default_value": "" 41 | }, 42 | "Security.rest_client_enable_arbitrary_urls": { 43 | "default_value": false 44 | }, 45 | "Security.disable_local_feed_access": { 46 | "default_value": false 47 | }, 48 | "Security.disable_instance_file_uploads": { 49 | "default_value": false 50 | }, 51 | "Security.salt": { 52 | "default_value": "", 53 | "command_args": "-f" 54 | }, 55 | "SimpleBackgroundJobs.enabled": { 56 | "default_value": true 57 | }, 58 | "SimpleBackgroundJobs.supervisor_host": { 59 | "default_value": "127.0.0.1" 60 | }, 61 | "SimpleBackgroundJobs.supervisor_port": { 62 | "default_value": 9001 63 | }, 64 | "SimpleBackgroundJobs.supervisor_password": { 65 | "default_value": "supervisor" 66 | }, 67 | "SimpleBackgroundJobs.supervisor_user": { 68 | "default_value": "supervisor" 69 | }, 70 | "SimpleBackgroundJobs.redis_port": { 71 | "default_value": 6379 72 | }, 73 | "SimpleBackgroundJobs.redis_database": { 74 | "default_value": 1 75 | }, 76 | "SimpleBackgroundJobs.redis_password": { 77 | "default_value": "" 78 | }, 79 | "SimpleBackgroundJobs.redis_namespace": { 80 | "default_value": "background_jobs" 81 | }, 82 | "SimpleBackgroundJobs.max_job_history_ttl": { 83 | "default_value": 86400 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/minimum_config.envars.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.python_bin": { 3 | "default_value": "${PYTHON_BIN}" 4 | }, 5 | "MISP.redis_host": { 6 | "default_value": "${REDIS_FQDN}" 7 | }, 8 | "GnuPG.binary": { 9 | "default_value": "${GPG_BINARY}" 10 | }, 11 | "SimpleBackgroundJobs.redis_host": { 12 | "default_value": "${REDIS_FQDN}" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/optional.defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "MISP.welcome_text_top": { 3 | "default_value": "", 4 | "command_args": "-f" 5 | }, 6 | "MISP.welcome_text_bottom": { 7 | "default_value": "", 8 | "command_args": "-f" 9 | }, 10 | "MISP.log_client_ip": { 11 | "default_value": true 12 | }, 13 | "MISP.log_user_ips": { 14 | "default_value": true 15 | }, 16 | "MISP.log_user_ips_authkeys": { 17 | "default_value": true 18 | }, 19 | "Plugin.Enrichment_timeout": { 20 | "default_value": 30 21 | }, 22 | "Plugin.Enrichment_hover_timeout": { 23 | "default_value": 5 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/misp-docker/proxy.envars.json: -------------------------------------------------------------------------------- 1 | { 2 | "Proxy.host": { 3 | "default_value": "${PROXY_HOST}" 4 | }, 5 | "Proxy.port": { 6 | "default_value": "${PROXY_PORT}" 7 | }, 8 | "Proxy.method": { 9 | "default_value": "${PROXY_METHOD}" 10 | }, 11 | "Proxy.user": { 12 | "default_value": "${PROXY_USER}" 13 | }, 14 | "Proxy.password": { 15 | "default_value": "${PROXY_PASSWORD}" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/nginx/includes/misp: -------------------------------------------------------------------------------- 1 | # define the root dir 2 | root /var/www/MISP/app/webroot; 3 | index index.php; 4 | 5 | # incrase the maximum body size 6 | client_max_body_size 50M; 7 | 8 | # added headers for hardening browser security 9 | add_header Referrer-Policy "no-referrer" always; 10 | add_header X-Content-Type-Options "nosniff" always; 11 | add_header X-Download-Options "noopen" always; 12 | add_header X-Frame-Options "SAMEORIGIN" always; 13 | add_header X-Permitted-Cross-Domain-Policies "none" always; 14 | add_header X-Robots-Tag "none" always; 15 | add_header X-XSS-Protection "1; mode=block" always; 16 | 17 | # remove X-Powered-By and nginx version, which is an information leak 18 | fastcgi_hide_header X-Powered-By; 19 | server_tokens off; 20 | 21 | location / { 22 | try_files $uri $uri/ /index.php$is_args$query_string; 23 | } 24 | 25 | location ~ ^/[^/]+\.php(/|$) { 26 | include snippets/fastcgi-php.conf; 27 | fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; 28 | fastcgi_read_timeout 300; 29 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 30 | set $path_info $fastcgi_path_info; 31 | fastcgi_param PATH_INFO $path_info; 32 | } 33 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/nginx/sites-available/misp443: -------------------------------------------------------------------------------- 1 | server { 2 | listen 443 ssl http2; 3 | listen [::]:443 ssl http2; 4 | 5 | # disable access logs 6 | access_log off; 7 | log_not_found off; 8 | error_log /dev/stderr error; 9 | 10 | # ssl options 11 | ssl_certificate /etc/nginx/certs/cert.pem; 12 | ssl_certificate_key /etc/nginx/certs/key.pem; 13 | ssl_session_timeout 1d; 14 | ssl_session_cache shared:MozSSL:10m; # about 40000 sessions 15 | ssl_session_tickets off; 16 | 17 | # ssl intermediate configuration 18 | ssl_dhparam /etc/nginx/certs/dhparams.pem; 19 | ssl_protocols TLSv1.2 TLSv1.3; 20 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 21 | ssl_prefer_server_ciphers off; 22 | 23 | # ssl enable HSTS 24 | add_header Strict-Transport-Security "max-age=15768000; includeSubdomains"; 25 | add_header X-Frame-Options SAMEORIGIN; 26 | 27 | # include misp 28 | include includes/misp; 29 | } 30 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/nginx/sites-available/misp80: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | 5 | # disable access logs 6 | access_log off; 7 | log_not_found off; 8 | error_log /dev/stderr error; 9 | 10 | # include includes/misp; 11 | # return 301 https://$host$request_uri; 12 | } 13 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/supervisor/conf.d/10-supervisor.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | user=root 4 | stdout_logfile=/dev/stdout 5 | stdout_logfile_maxbytes=0 6 | stderr_logfile=/dev/stderr 7 | stderr_logfile_maxbytes=0 8 | 9 | [inet_http_server] 10 | port=127.0.0.1:9001 11 | username=supervisor 12 | password=supervisor 13 | 14 | [program:nginx] 15 | command=/entrypoint_nginx.sh 16 | autorestart=true 17 | redirect_stderr=true 18 | stdout_logfile=/dev/stdout 19 | stdout_logfile_maxbytes=0 20 | stderr_logfile=/dev/stderr 21 | stderr_logfile_maxbytes=0 22 | 23 | [program:php-fpm] 24 | command=/entrypoint_fpm.sh 25 | autorestart=true 26 | redirect_stderr=true 27 | stdout_logfile=/dev/stdout 28 | stdout_logfile_maxbytes=0 29 | stderr_logfile=/dev/stderr 30 | stderr_logfile_maxbytes=0 31 | 32 | [program:cron] 33 | command=/entrypoint_cron.sh 34 | autorestart=true 35 | redirect_stderr=true 36 | stdout_logfile=/dev/stdout 37 | stdout_logfile_maxbytes=0 38 | stderr_logfile=/dev/stderr 39 | stderr_logfile_maxbytes=0 40 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/etc/supervisor/conf.d/50-workers.conf: -------------------------------------------------------------------------------- 1 | # Workers are set to NOT auto start so we have time to enforce permissions on the cache first 2 | 3 | [group:misp-workers] 4 | programs=default,email,cache,prio,update 5 | 6 | [program:default] 7 | directory=/var/www/MISP 8 | command=/var/www/MISP/app/Console/cake start_worker default 9 | process_name=%(program_name)s_%(process_num)02d 10 | numprocs=%(ENV_NUM_WORKERS_DEFAULT)s 11 | autostart=false 12 | autorestart=true 13 | redirect_stderr=false 14 | stderr_logfile=/var/www/MISP/app/tmp/logs/misp-workers-errors.log 15 | stdout_logfile=/var/www/MISP/app/tmp/logs/misp-workers.log 16 | directory=/var/www/MISP 17 | user=www-data 18 | 19 | [program:prio] 20 | directory=/var/www/MISP 21 | command=/var/www/MISP/app/Console/cake start_worker prio 22 | process_name=%(program_name)s_%(process_num)02d 23 | numprocs=%(ENV_NUM_WORKERS_PRIO)s 24 | autostart=false 25 | autorestart=true 26 | redirect_stderr=false 27 | stderr_logfile=/var/www/MISP/app/tmp/logs/misp-workers-errors.log 28 | stdout_logfile=/var/www/MISP/app/tmp/logs/misp-workers.log 29 | directory=/var/www/MISP 30 | user=www-data 31 | 32 | [program:email] 33 | directory=/var/www/MISP 34 | command=/var/www/MISP/app/Console/cake start_worker email 35 | process_name=%(program_name)s_%(process_num)02d 36 | numprocs=%(ENV_NUM_WORKERS_EMAIL)s 37 | autostart=false 38 | autorestart=true 39 | redirect_stderr=false 40 | stderr_logfile=/var/www/MISP/app/tmp/logs/misp-workers-errors.log 41 | stdout_logfile=/var/www/MISP/app/tmp/logs/misp-workers.log 42 | directory=/var/www/MISP 43 | user=www-data 44 | 45 | [program:update] 46 | directory=/var/www/MISP 47 | command=/var/www/MISP/app/Console/cake start_worker update 48 | process_name=%(program_name)s_%(process_num)02d 49 | numprocs=%(ENV_NUM_WORKERS_UPDATE)s 50 | autostart=false 51 | autorestart=true 52 | redirect_stderr=false 53 | stderr_logfile=/var/www/MISP/app/tmp/logs/misp-workers-errors.log 54 | stdout_logfile=/var/www/MISP/app/tmp/logs/misp-workers.log 55 | directory=/var/www/MISP 56 | user=www-data 57 | 58 | [program:cache] 59 | directory=/var/www/MISP 60 | command=/var/www/MISP/app/Console/cake start_worker cache 61 | process_name=%(program_name)s_%(process_num)02d 62 | numprocs=%(ENV_NUM_WORKERS_CACHE)s 63 | autostart=false 64 | autorestart=true 65 | redirect_stderr=false 66 | stderr_logfile=/var/www/MISP/app/tmp/logs/misp-workers-errors.log 67 | stdout_logfile=/var/www/MISP/app/tmp/logs/misp-workers.log 68 | user=www-data 69 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/rest_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if ! command -v jq &> /dev/null 4 | then 5 | echo "aborting. jq could not be found" 6 | exit 7 | fi 8 | 9 | if ! command -v curl &> /dev/null 10 | then 11 | echo "aborting. curl could not be found" 12 | exit 13 | fi 14 | 15 | add_organization() { 16 | # empty uuid fallbacks to auto-generate 17 | curl -s --show-error -k \ 18 | -H "Authorization: ${2}" \ 19 | -H "Accept: application/json" \ 20 | -H "Content-type: application/json" \ 21 | -d "{ \ 22 | \"uuid\": \"${5}\", \ 23 | \"name\": \"${3}\", \ 24 | \"local\": ${4} \ 25 | }" ${1}/admin/organisations/add 26 | } 27 | 28 | get_organization() { 29 | curl -s --show-error -k \ 30 | -H "Authorization: ${2}" \ 31 | -H "Accept: application/json" \ 32 | -H "Content-type: application/json" ${1}/organisations/view/${3} | jq -e -r ".Organisation.id // empty" 33 | } 34 | 35 | add_server() { 36 | curl -s --show-error -k \ 37 | -H "Authorization: ${2}" \ 38 | -H "Accept: application/json" \ 39 | -H "Content-type: application/json" \ 40 | -d "${3}" ${1}/servers/add 41 | } 42 | 43 | get_server() { 44 | curl -s --show-error -k \ 45 | -H "Authorization: ${2}" \ 46 | -H "Accept: application/json" \ 47 | -H "Content-type: application/json" ${1}/servers | jq -e -r ".[] | select(.Server[\"name\"] == \"${3}\") | .Server.id" 48 | } 49 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/utilities.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check whether passed env variables are defined 4 | check_env_vars() { 5 | local required_vars=("$@") 6 | 7 | missing_vars=() 8 | for i in "${required_vars[@]}" 9 | do 10 | test -n "${!i:+y}" || missing_vars+=("$i") 11 | done 12 | if [ ${#missing_vars[@]} -ne 0 ] 13 | then 14 | echo "The following env variables are not set:" 15 | printf ' %q\n' "${missing_vars[@]}" 16 | exit 1 17 | fi 18 | } 19 | -------------------------------------------------------------------------------- /misp/misp-docker/core/files/var/www/html/index.php: -------------------------------------------------------------------------------- 1 | 2 | MISP is loading... 3 | -------------------------------------------------------------------------------- /misp/misp-docker/docker-bake.hcl: -------------------------------------------------------------------------------- 1 | variable "PLATFORMS" { 2 | default = ["linux/amd64", "linux/arm64"] 3 | } 4 | 5 | variable "PYPI_REDIS_VERSION" { 6 | default = "" 7 | } 8 | 9 | variable "PYPI_LIEF_VERSION" { 10 | default = "" 11 | } 12 | 13 | variable "PYPI_PYDEEP2_VERSION" { 14 | default = "" 15 | } 16 | 17 | variable "PYPI_PYTHON_MAGIC_VERSION" { 18 | default = "" 19 | } 20 | 21 | variable "PYPI_MISP_LIB_STIX2_VERSION" { 22 | default = "" 23 | } 24 | 25 | variable "PYPI_MAEC_VERSION" { 26 | default = "" 27 | } 28 | 29 | variable "PYPI_MIXBOX_VERSION" { 30 | default = "" 31 | } 32 | 33 | variable "PYPI_CYBOX_VERSION" { 34 | default = "" 35 | } 36 | 37 | variable "PYPI_PYMISP_VERSION" { 38 | default = "" 39 | } 40 | 41 | variable "PYPI_MISP_STIX" { 42 | default = "" 43 | } 44 | 45 | variable "NAMESPACE" { 46 | default = null 47 | } 48 | 49 | variable "COMMIT_HASH" { 50 | default = null 51 | } 52 | 53 | variable "MODULES_TAG" { 54 | default = "" 55 | } 56 | 57 | variable "MODULES_COMMIT" { 58 | default = "" 59 | } 60 | 61 | variable "LIBFAUP_COMMIT" { 62 | default = "" 63 | } 64 | 65 | variable "CORE_TAG" { 66 | default = "" 67 | } 68 | 69 | variable "CORE_COMMIT" { 70 | default = "" 71 | } 72 | 73 | variable "PHP_VER" { 74 | default = null 75 | } 76 | 77 | group "default" { 78 | targets = [ 79 | "misp-modules", 80 | "misp-core", 81 | ] 82 | } 83 | 84 | target "misp-modules" { 85 | context = "modules/." 86 | dockerfile = "Dockerfile" 87 | tags = flatten(["${NAMESPACE}/misp-modules:latest", "${NAMESPACE}/misp-modules:${COMMIT_HASH}", MODULES_TAG != "" ? ["${NAMESPACE}/misp-modules:${MODULES_TAG}"] : []]) 88 | args = { 89 | "MODULES_TAG": "${MODULES_TAG}", 90 | "MODULES_COMMIT": "${MODULES_COMMIT}", 91 | "LIBFAUP_COMMIT": "${LIBFAUP_COMMIT}", 92 | } 93 | platforms = "${PLATFORMS}" 94 | } 95 | 96 | target "misp-core" { 97 | context = "core/." 98 | dockerfile = "Dockerfile" 99 | tags = flatten(["${NAMESPACE}/misp-core:latest", "${NAMESPACE}/misp-core:${COMMIT_HASH}", CORE_TAG != "" ? ["${NAMESPACE}/misp-core:${CORE_TAG}"] : []]) 100 | args = { 101 | "CORE_TAG": "${CORE_TAG}", 102 | "CORE_COMMIT": "${CORE_COMMIT}", 103 | "PHP_VER": "${PHP_VER}", 104 | "PYPI_REDIS_VERSION": "${PYPI_REDIS_VERSION}", 105 | "PYPI_LIEF_VERSION": "${PYPI_LIEF_VERSION}", 106 | "PYPI_PYDEEP2_VERSION": "${PYPI_PYDEEP2_VERSION}", 107 | "PYPI_PYTHON_MAGIC_VERSION": "${PYPI_PYTHON_MAGIC_VERSION}", 108 | "PYPI_MISP_LIB_STIX2_VERSION": "${PYPI_MISP_LIB_STIX2_VERSION}", 109 | "PYPI_MAEC_VERSION": "${PYPI_MAEC_VERSION}", 110 | "PYPI_MIXBOX_VERSION": "${PYPI_MIXBOX_VERSION}", 111 | "PYPI_CYBOX_VERSION": "${PYPI_CYBOX_VERSION}", 112 | "PYPI_PYMISP_VERSION": "${PYPI_PYMISP_VERSION}", 113 | } 114 | platforms = "${PLATFORMS}" 115 | } 116 | -------------------------------------------------------------------------------- /misp/misp-docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | # This is capable to relay via gmail, Amazon SES, or generic relays 4 | # See: https://hub.docker.com/r/ixdotai/smtp 5 | mail: 6 | image: ixdotai/smtp 7 | environment: 8 | - "SMARTHOST_ADDRESS=${SMARTHOST_ADDRESS}" 9 | - "SMARTHOST_PORT=${SMARTHOST_PORT}" 10 | - "SMARTHOST_USER=${SMARTHOST_USER}" 11 | - "SMARTHOST_PASSWORD=${SMARTHOST_PASSWORD}" 12 | - "SMARTHOST_ALIASES=${SMARTHOST_ALIASES}" 13 | 14 | redis: 15 | image: valkey/valkey:7.2 16 | healthcheck: 17 | test: valkey-cli ping || exit 1 18 | interval: 2s 19 | timeout: 1s 20 | retries: 3 21 | start_period: 30s 22 | 23 | db: 24 | # We use MariaDB because it supports ARM and has the expected collations 25 | image: mariadb:10.11 26 | restart: always 27 | environment: 28 | - "MYSQL_USER=${MYSQL_USER:-misp}" 29 | - "MYSQL_PASSWORD=${MYSQL_PASSWORD:-example}" 30 | - "MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-password}" 31 | - "MYSQL_DATABASE=${MYSQL_DATABASE:-misp}" 32 | volumes: 33 | - mysql_data:/var/lib/mysql 34 | cap_add: 35 | - SYS_NICE # CAP_SYS_NICE Prevent runaway mysql log 36 | healthcheck: 37 | test: mysqladmin --user=$$MYSQL_USER --password=$$MYSQL_PASSWORD status 38 | interval: 2s 39 | timeout: 1s 40 | retries: 3 41 | start_period: 30s 42 | 43 | misp-core: 44 | image: ghcr.io/misp/misp-docker/misp-core:latest 45 | build: 46 | context: core/. 47 | args: 48 | - CORE_TAG=${CORE_TAG:?Missing .env file, see README.md for instructions} 49 | - CORE_COMMIT=${CORE_COMMIT} 50 | - PHP_VER=${PHP_VER:?Missing .env file, see README.md for instructions} 51 | - PYPI_REDIS_VERSION=${PYPI_REDIS_VERSION} 52 | - PYPI_LIEF_VERSION=${PYPI_LIEF_VERSION} 53 | - PYPI_PYDEEP2_VERSION=${PYPI_PYDEEP2_VERSION} 54 | - PYPI_PYTHON_MAGIC_VERSION=${PYPI_PYTHON_MAGIC_VERSION} 55 | - PYPI_MISP_LIB_STIX2_VERSION=${PYPI_MISP_LIB_STIX2_VERSION} 56 | - PYPI_MAEC_VERSION=${PYPI_MAEC_VERSION} 57 | - PYPI_MIXBOX_VERSION=${PYPI_MIXBOX_VERSION} 58 | - PYPI_CYBOX_VERSION=${PYPI_CYBOX_VERSION} 59 | - PYPI_PYMISP_VERSION=${PYPI_PYMISP_VERSION} 60 | - PYPI_MISP_STIX_VERSION=${PYPI_MISP_STIX_VERSION} 61 | depends_on: 62 | redis: 63 | condition: service_healthy 64 | db: 65 | condition: service_healthy 66 | healthcheck: 67 | test: curl -ks https://localhost/users/heartbeat > /dev/null || exit 1 68 | interval: 2s 69 | timeout: 1s 70 | retries: 3 71 | start_period: 30s 72 | start_interval: 30s 73 | ports: 74 | - "80:80" 75 | - "443:443" 76 | volumes: 77 | - "./configs/:/var/www/MISP/app/Config/" 78 | - "./logs/:/var/www/MISP/app/tmp/logs/" 79 | - "./files/:/var/www/MISP/app/files/" 80 | - "./ssl/:/etc/nginx/certs/" 81 | - "./gnupg/:/var/www/MISP/.gnupg/" 82 | # customize by replacing ${CUSTOM_PATH} with a path containing 'files/customize_misp.sh' 83 | # - "${CUSTOM_PATH}/:/custom/" 84 | # mount custom ca root certificates 85 | # - "./rootca.pem:/usr/local/share/ca-certificates/rootca.crt" 86 | environment: 87 | - "BASE_URL=${BASE_URL}" 88 | - "CRON_USER_ID=${CRON_USER_ID}" 89 | - "DISABLE_IPV6=${DISABLE_IPV6}" 90 | - "DISABLE_SSL_REDIRECT=${DISABLE_SSL_REDIRECT}" 91 | - "ENABLE_DB_SETTINGS=${ENABLE_DB_SETTINGS}" 92 | # standard settings 93 | - "ADMIN_EMAIL=${ADMIN_EMAIL}" 94 | - "ADMIN_PASSWORD=${ADMIN_PASSWORD}" 95 | - "ADMIN_KEY=${ADMIN_KEY}" 96 | - "ADMIN_ORG=${ADMIN_ORG}" 97 | - "GPG_PASSPHRASE=${GPG_PASSPHRASE}" 98 | # OIDC authentication settings 99 | - "OIDC_ENABLE=${OIDC_ENABLE}" 100 | - "OIDC_PROVIDER_URL=${OIDC_PROVIDER_URL}" 101 | - "OIDC_CLIENT_ID=${OIDC_CLIENT_ID}" 102 | - "OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}" 103 | - "OIDC_ROLES_PROPERTY=${OIDC_ROLES_PROPERTY}" 104 | - "OIDC_ROLES_MAPPING=${OIDC_ROLES_MAPPING}" 105 | - "OIDC_DEFAULT_ORG=${OIDC_DEFAULT_ORG}" 106 | # LDAP authentication settings 107 | - "LDAP_ENABLE=${LDAP_ENABLE}" 108 | - "LDAP_APACHE_ENV=${LDAP_APACHE_ENV}" 109 | - "LDAP_SERVER=${LDAP_SERVER}" 110 | - "LDAP_STARTTLS=${LDAP_STARTTLS}" 111 | - "LDAP_READER_USER=${LDAP_READER_USER}" 112 | - "LDAP_READER_PASSWORD=${LDAP_READER_PASSWORD}" 113 | - "LDAP_DN=${LDAP_DN}" 114 | - "LDAP_SEARCH_FILTER=${LDAP_SEARCH_FILTER}" 115 | - "LDAP_SEARCH_ATTRIBUTE=${LDAP_SEARCH_ATTRIBUTE}" 116 | - "LDAP_FILTER=${LDAP_FILTER}" 117 | - "LDAP_DEFAULT_ROLE_ID=${LDAP_DEFAULT_ROLE_ID}" 118 | - "LDAP_DEFAULT_ORG=${LDAP_DEFAULT_ORG}" 119 | - "LDAP_EMAIL_FIELD=${LDAP_EMAIL_FIELD}" 120 | - "LDAP_OPT_PROTOCOL_VERSION=${LDAP_OPT_PROTOCOL_VERSION}" 121 | - "LDAP_OPT_NETWORK_TIMEOUT=${LDAP_OPT_NETWORK_TIMEOUT}" 122 | - "LDAP_OPT_REFERRALS=${LDAP_OPT_REFERRALS}" 123 | # AAD authentication settings 124 | - "AAD_ENABLE=${AAD_ENABLE}" 125 | - "AAD_CLIENT_ID=${AAD_CLIENT_ID}" 126 | - "AAD_TENANT_ID=${AAD_TENANT_ID}" 127 | - "AAD_CLIENT_SECRET=${AAD_CLIENT_SECRET}" 128 | - "AAD_REDIRECT_URI=${AAD_REDIRECT_URI}" 129 | - "AAD_PROVIDER=${AAD_PROVIDER}" 130 | - "AAD_PROVIDER_USER=${AAD_PROVIDER_USER}" 131 | - "AAD_MISP_USER=${AAD_MISP_USER}" 132 | - "AAD_MISP_ORGADMIN=${AAD_MISP_ORGADMIN}" 133 | - "AAD_MISP_SITEADMIN=${AAD_MISP_SITEADMIN}" 134 | - "AAD_CHECK_GROUPS=${AAD_CHECK_GROUPS}" 135 | # Proxy settings 136 | - "PROXY_ENABLE=${PROXY_ENABLE}" 137 | - "PROXY_HOST=${PROXY_HOST}" 138 | - "PROXY_PORT=${PROXY_PORT}" 139 | - "PROXY_METHOD=${PROXY_METHOD}" 140 | - "PROXY_USER=${PROXY_USER}" 141 | - "PROXY_PASSWORD=${PROXY_PASSWORD}" 142 | # sync server settings (see https://www.misp-project.org/openapi/#tag/Servers for more options) 143 | - "SYNCSERVERS=${SYNCSERVERS}" 144 | - | 145 | SYNCSERVERS_1_DATA= 146 | { 147 | "remote_org_uuid": "${SYNCSERVERS_1_UUID}", 148 | "name": "${SYNCSERVERS_1_NAME}", 149 | "authkey": "${SYNCSERVERS_1_KEY}", 150 | "url": "${SYNCSERVERS_1_URL}", 151 | "pull_rules": "${SYNCSERVERS_1_PULL_RULES}", 152 | "pull": true 153 | } 154 | # mysql settings 155 | - "MYSQL_HOST=${MYSQL_HOST:-db}" 156 | - "MYSQL_PORT=${MYSQL_PORT:-3306}" 157 | - "MYSQL_USER=${MYSQL_USER:-misp}" 158 | - "MYSQL_PASSWORD=${MYSQL_PASSWORD:-example}" 159 | - "MYSQL_DATABASE=${MYSQL_DATABASE:-misp}" 160 | # Debug setting 161 | - "DEBUG=${DEBUG}" 162 | # SMTP setting 163 | - "SMTP_FQDN=${SMTP_FQDN}" 164 | 165 | misp-modules: 166 | image: ghcr.io/misp/misp-docker/misp-modules:latest 167 | build: 168 | context: modules/. 169 | args: 170 | - MODULES_TAG=${MODULES_TAG:?Missing .env file, see README.md for instructions} 171 | - MODULES_COMMIT=${MODULES_COMMIT} 172 | - LIBFAUP_COMMIT=${LIBFAUP_COMMIT:?Missing .env file, see README.md for instructions} 173 | environment: 174 | - "REDIS_BACKEND=redis" 175 | depends_on: 176 | redis: 177 | condition: service_healthy 178 | 179 | volumes: 180 | mysql_data: 181 | -------------------------------------------------------------------------------- /misp/misp-docker/modules/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG DOCKER_HUB_PROXY="" 2 | 3 | FROM "${DOCKER_HUB_PROXY}python:3.12-slim-bookworm" AS python-build 4 | ENV DEBIAN_FRONTEND noninteractive 5 | ARG MODULES_TAG 6 | ARG MODULES_COMMIT 7 | ARG LIBFAUP_COMMIT 8 | 9 | RUN apt-get update && apt-get install -y --no-install-recommends \ 10 | cmake \ 11 | git \ 12 | build-essential \ 13 | libpoppler-cpp-dev \ 14 | libfuzzy-dev \ 15 | libffi-dev \ 16 | libxml2-dev \ 17 | libxslt-dev \ 18 | libssl-dev \ 19 | ninja-build \ 20 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 21 | 22 | RUN mkdir /wheels 23 | 24 | RUN <<-EOF 25 | if [ ! -z ${MODULES_COMMIT} ]; then 26 | git clone https://github.com/MISP/misp-modules.git /srv/misp-modules && cd /srv/misp-modules && git checkout ${MODULES_COMMIT} 27 | else 28 | git clone --branch ${MODULES_TAG} --depth 1 https://github.com/MISP/misp-modules.git /srv/misp-modules 29 | fi 30 | EOF 31 | 32 | WORKDIR /srv/misp-modules 33 | RUN pip install pipenv 34 | RUN pipenv requirements > requirements.txt 35 | RUN pip wheel -r requirements.txt --no-cache-dir -w /wheels/ 36 | 37 | WORKDIR /srv/ 38 | RUN rm -rf /srv/misp-modules 39 | 40 | RUN <<-EOF 41 | git clone --depth 1 https://github.com/stricaud/faup.git /srv/faup 42 | cd /srv/faup 43 | if [ ! -z ${LIBFAUP_COMMIT} ]; then 44 | git checkout ${LIBFAUP_COMMIT} 45 | fi 46 | EOF 47 | 48 | WORKDIR /srv/faup/build 49 | RUN cmake -G "Ninja" ../ 50 | RUN ninja 51 | RUN ninja install 52 | WORKDIR /srv/faup/src/lib/bindings/python 53 | RUN pip wheel --no-cache-dir --no-dependencies -w /wheels/ . 54 | 55 | WORKDIR /srv/ 56 | RUN rm -rf /srv/faup 57 | 58 | 59 | FROM "${DOCKER_HUB_PROXY}python:3.12-slim-bookworm" 60 | ENV DEBIAN_FRONTEND noninteractive 61 | 62 | RUN apt-get update && apt-get install -y --no-install-recommends \ 63 | libglib2.0-0 \ 64 | libpoppler-cpp0v5 \ 65 | libgl1 \ 66 | libfuzzy2 \ 67 | libffi8 \ 68 | libxext6 \ 69 | libxml2 \ 70 | libxslt1.1 \ 71 | libzbar0 \ 72 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 73 | 74 | COPY --from=python-build /wheels /wheels 75 | COPY --from=python-build /usr/local/lib/libfaupl* /usr/local/lib/ 76 | RUN ldconfig 77 | RUN pip install --no-cache-dir --use-deprecated=legacy-resolver /wheels/*.whl && rm -rf /wheels 78 | RUN pip uninstall -y pip 79 | 80 | # Since we compile faup ourselves and lua is not required anymore, we can load our own library 81 | # and skip the pre-compiled blob to improve compatibility with other architectures like ARM 82 | RUN sed -i s/LoadLibrary\(LOAD_LIB\)/LoadLibrary\(\"\\/usr\\/local\\/lib\\/libfaupl.so\"\)/ \ 83 | /usr/local/lib/python3.12/site-packages/pyfaup/__init__.py 84 | 85 | # Disable (all) warnings raised when using 'future' 86 | RUN sed -i '/import sys/a import warnings\nwarnings.warn = lambda *args, **kwargs: None' \ 87 | /usr/local/bin/misp-modules 88 | 89 | ENTRYPOINT [ "/usr/local/bin/misp-modules", "-l", "0.0.0.0"] 90 | -------------------------------------------------------------------------------- /misp/misp-docker/template.env: -------------------------------------------------------------------------------- 1 | ## 2 | # Build-time variables 3 | ## 4 | 5 | CORE_TAG=v2.4.195 6 | MODULES_TAG=v2.4.195 7 | PHP_VER=20190902 8 | LIBFAUP_COMMIT=3a26d0a 9 | 10 | # PYPY_* vars take precedence over MISP's 11 | # PYPI_REDIS_VERSION="==5.0.*" 12 | # PYPI_LIEF_VERSION=">=0.13.1" 13 | # PYPI_PYDEEP2_VERSION="==0.5.*" 14 | # PYPI_PYTHON_MAGIC_VERSION="==0.4.*" 15 | # PYPI_MISP_LIB_STIX2_VERSION="==3.0.*" 16 | # PYPI_MAEC_VERSION="==4.1.*" 17 | # PYPI_MIXBOX_VERSION="==1.0.*" 18 | # PYPI_CYBOX_VERSION="==2.1.*" 19 | # PYPI_PYMISP_VERSION="==2.4.178" 20 | # PYPI_MISP_STIX_VERSION"==2.4.194" 21 | 22 | # CORE_COMMIT takes precedence over CORE_TAG 23 | # CORE_COMMIT=c56d537 24 | # MODULES_COMMIT takes precedence over MODULES_TAG 25 | # MODULES_COMMIT=de69ae3 26 | 27 | ## 28 | # Run-time variables 29 | ## 30 | 31 | # Email/username for user #1, defaults to MISP's default (admin@admin.test) 32 | ADMIN_EMAIL=hacker@misp.io 33 | # name of org #1, default to MISP's default (ORGNAME) 34 | ADMIN_ORG=MISPLab 35 | # defaults to an automatically generated one 36 | ADMIN_KEY= 37 | # defaults to MISP's default (admin) 38 | ADMIN_PASSWORD= 39 | # defaults to 'passphrase' 40 | GPG_PASSPHRASE= 41 | # defaults to 1 (the admin user) 42 | CRON_USER_ID= 43 | # defaults to 'https://localhost' 44 | BASE_URL=https://192.168.1.9 45 | # store settings in db except those that must stay in config.php. true/false, defaults to false 46 | ENABLE_DB_SETTINGS= 47 | 48 | # defines the FQDN of the mail sub-system (defaults to 'mail') 49 | # SMTP_FQDN= 50 | 51 | # optional and used by the mail sub-system 52 | SMARTHOST_ADDRESS= 53 | SMARTHOST_PORT= 54 | SMARTHOST_USER= 55 | SMARTHOST_PASSWORD= 56 | SMARTHOST_ALIASES= 57 | 58 | # optional comma separated list of IDs of syncservers (e.g. SYNCSERVERS=1) 59 | # For this to work ADMIN_KEY must be set, or AUTOGEN_ADMIN_KEY must be true (default) 60 | SYNCSERVERS= 61 | # note: if you have more than one syncserver, you need to update docker-compose.yml 62 | SYNCSERVERS_1_URL= 63 | SYNCSERVERS_1_NAME= 64 | SYNCSERVERS_1_UUID= 65 | SYNCSERVERS_1_KEY= 66 | # pull rules are JSON encoded (and escaped) dictionaries 67 | # Example: only pull events where the analysis is complete 68 | # SYNCSERVERS_1_PULL_RULES='{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]},\"url_params\":\"{\\\"searchanalysis\\\": \\\"2\\\"}\"}' 69 | SYNCSERVERS_1_PULL_RULES= 70 | 71 | # optional and used to set mysql db and credentials 72 | # MYSQL_HOST= 73 | # MYSQL_PORT= 74 | # MYSQL_USER= 75 | # MYSQL_PASSWORD= 76 | # MYSQL_ROOT_PASSWORD= 77 | # MYSQL_DATABASE= 78 | 79 | # These variables allows overriding some MISP email values. 80 | # They all default to ADMIN_EMAIL. 81 | 82 | # MISP.email, used for notifications. Also used 83 | # for GnuPG.email and GPG autogeneration. 84 | # MISP_EMAIL= 85 | 86 | # MISP.contact, the e-mail address that 87 | # MISP should include as a contact address 88 | # for the instance's support team. 89 | # MISP_CONTACT= 90 | 91 | # Enable GPG autogeneration (default true) 92 | # AUTOCONF_GPG=true 93 | 94 | # Enable admin (user #1) API key autogeneration 95 | # if ADMIN_KEY is not set above (default true) 96 | # AUTOGEN_ADMIN_KEY=true 97 | 98 | # Disable IPv6 completely 99 | # DISABLE_IPV6=true 100 | 101 | # Disable SSL redirect 102 | # DISABLE_SSL_REDIRECT=true 103 | 104 | # Enable OIDC authentication, according to https://github.com/MISP/MISP/blob/2.4/app/Plugin/OidcAuth/README.md 105 | # OIDC_ENABLE=true 106 | # OIDC_PROVIDER_URL= 107 | # OIDC_CLIENT_ID= 108 | # OIDC_CLIENT_SECRET= 109 | # OIDC_ROLES_PROPERTY="roles" 110 | # OIDC_ROLES_MAPPING="{\"admin\": \"1\"}" 111 | # OIDC_DEFAULT_ORG= 112 | 113 | # Enable LDAP (using the ApacheSecureAuth component) authentication, according to https://github.com/MISP/MISP/issues/6189 114 | # NOTE: Once you enable LDAP authentication with the ApacheSecureAuth component, 115 | # users should not be able to control the HTTP header configured in LDAP_APACHE_ENV 116 | # (e.g. REMOTE_USER), this means you must not allow direct access to MISP. 117 | # NOTE 2: You need to escape special characters twice, e.g., "pass\word" becomes "pass\\\\word". 118 | # LDAP_ENABLE=true 119 | # LDAP_APACHE_ENV="REMOTE_USER" 120 | # LDAP_SERVER="ldap://your_domain_controller" 121 | # LDAP_STARTTLS=true 122 | # LDAP_READER_USER="CN=service_account_name,OU=Users,DC=domain,DC=net" 123 | # LDAP_READER_PASSWORD="password" 124 | # LDAP_DN="OU=Users,DC=domain,DC=net" 125 | # LDAP_SEARCH_FILTER="" 126 | # LDAP_SEARCH_ATTRIBUTE="uid" 127 | # LDAP_FILTER="[\"mail\", \"uid\", \"cn\" ]" 128 | # LDAP_DEFAULT_ROLE_ID="3" 129 | # LDAP_DEFAULT_ORG="1" 130 | # LDAP_EMAIL_FIELD="[\"mail\"]" 131 | # LDAP_OPT_PROTOCOL_VERSION="3" 132 | # LDAP_OPT_NETWORK_TIMEOUT="-1" 133 | # LDAP_OPT_REFERRALS=false 134 | 135 | # Enable Azure AD (Entra) authentication, according to https://github.com/MISP/MISP/blob/2.4/app/Plugin/AadAuth/README.md 136 | # AAD_ENABLE=true 137 | # AAD_CLIENT_ID= 138 | # AAD_TENANT_ID= 139 | # AAD_CLIENT_SECRET= 140 | # AAD_REDIRECT_URI="https://misp.mydomain.com/users/login" 141 | # AAD_PROVIDER="https://login.microsoftonline.com/" 142 | # AAD_PROVIDER_USER="https://graph.microsoft.com/" 143 | # AAD_MISP_USER="Misp Users" 144 | # AAD_MISP_ORGADMIN="Misp Org Admins" 145 | # AAD_MISP_SITEADMIN="Misp Site Admins" 146 | # AAD_CHECK_GROUPS=false 147 | 148 | # Enable the use of a Proxy server 149 | # PROXY_ENABLE=true 150 | # PROXY_HOST= 151 | # PROXY_PORT= 152 | # PROXY_METHOD= 153 | # PROXY_USER= 154 | # PROXY_PASSWORD= 155 | 156 | # Enable debugging 157 | # ALWAYS SET THIS TO 0 IN PRODUCTION 158 | # 0 - Debug off (default) 159 | # 1 - Debug on 160 | # 2 - Debug on + SQL dump 161 | # DEBUG= 162 | -------------------------------------------------------------------------------- /misp/opencti/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | connector-misp: 4 | image: opencti/connector-misp:6.2.12 5 | environment: 6 | - OPENCTI_URL=http://opencti:8080 7 | - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN} 8 | - CONNECTOR_ID=59df189d-36b9-475e-9c36-58e333f9b38a 9 | - CONNECTOR_TYPE=EXTERNAL_IMPORT 10 | - CONNECTOR_NAME=MISP 11 | - CONNECTOR_SCOPE=misp 12 | - CONNECTOR_LOG_LEVEL=error 13 | - CONNECTOR_EXPOSE_METRICS=false 14 | - MISP_URL=https://MISP_URL # Required 15 | - MISP_REFERENCE_URL= # Optional, will be used to create external reference to MISP event (default is "url") 16 | - MISP_KEY=MISP_API_TOKEN # Required 17 | - MISP_SSL_VERIFY=false # Required 18 | - MISP_DATETIME_ATTRIBUTE=timestamp # Required, filter to be used in query for new MISP events 19 | - MISP_DATE_FILTER_FIELD=timestamp # Required, field to filter on date 20 | - MISP_REPORT_DESCRIPTION_ATTRIBUTE_FILTER= # Optional, filter to be used to find the attribute with report description (example: "type=comment,category=Internal reference") 21 | - MISP_CREATE_REPORTS=true # Required, create report for MISP event 22 | - MISP_CREATE_INDICATORS=true # Required, create indicators from attributes 23 | - MISP_CREATE_OBSERVABLES=true # Required, create observables from attributes 24 | - MISP_CREATE_OBJECT_OBSERVABLES=true # Required, create text observables for MISP objects 25 | - MISP_CREATE_TAGS_AS_LABELS=true # Optional, create tags as labels (sanitize MISP tag to OpenCTI labels) 26 | - MISP_GUESS_THREAT_FROM_TAGS=false # Optional, try to guess threats (threat actor, intrusion set, malware, etc.) from MISP tags when they are present in OpenCTI 27 | - MISP_AUTHOR_FROM_TAGS=false # Optional, map creator:XX=YY (author of event will be YY instead of the author of the event) 28 | - MISP_MARKINGS_FROM_TAGS=false # Optional, map marking:XX=YY (in addition to TLP, add XX:YY as marking definition, where XX is marking type, YY is marking value) 29 | - MISP_ENFORCE_WARNING_LIST=false # Optional, enforce warning list in MISP queries 30 | - MISP_REPORT_TYPE=misp-event # Optional, report_class if creating report for event 31 | - MISP_IMPORT_FROM_DATE=2000-01-01 # Required, import all event from this date 32 | - MISP_IMPORT_TAGS=opencti:import,type:osint,tlp:white,type:OSINT,veris:action:social:variety="Phishing",tlp:green # Optional, list of tags used for import events 33 | - MISP_IMPORT_TAGS_NOT= # Optional, list of tags to not include 34 | - MISP_IMPORT_CREATOR_ORGS= # Optional, only import events created by those orgs (put the identifiers here) 35 | - MISP_IMPORT_CREATOR_ORGS_NOT= # Optional, do not import events created by those orgs (put the identifiers here) 36 | - MISP_IMPORT_OWNER_ORGS= # Optional, only import events owned by those orgs (put the identifiers here) 37 | - MISP_IMPORT_OWNER_ORGS_NOT= # Optional, do not import events owned by those orgs (put the identifiers here) 38 | - MISP_IMPORT_KEYWORD= # Optional, search only events based on a keyword 39 | - MISP_IMPORT_DISTRIBUTION_LEVELS= # Optional, only import events with the given distribution levels (ex: 0,1,2,3) 40 | - MISP_IMPORT_THREAT_LEVELS= # Optional only import events with the given threat levels (ex: 1,2,3,4) 41 | - MISP_IMPORT_ONLY_PUBLISHED=false 42 | - MISP_IMPORT_WITH_ATTACHMENTS=false # Optional, try to import a PDF file from the attachment attribute 43 | - MISP_IMPORT_TO_IDS_NO_SCORE=40 # Optional, use as a score for the indicator/observable if the attribute to_ids is no 44 | - MISP_IMPORT_UNSUPPORTED_OBSERVABLES_AS_TEXT=false # Optional, import unsupported observable as x_opencti_text 45 | - MISP_IMPORT_UNSUPPORTED_OBSERVABLES_AS_TEXT_TRANSPARENT=true # Optional, import unsupported observable as x_opencti_text just with the value 46 | - MISP_INTERVAL=5 # Required, in minutes 47 | restart: always -------------------------------------------------------------------------------- /oidc_auth_using_jwt/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_openid_connect_provider" "gitlab" { 2 | url = "https://gitlab.com" 3 | client_id_list = [ 4 | "https://gitlab.com" 5 | ] 6 | thumbprint_list = ["2B8F1B57330DBBA2D07A6C51F70EE90DDAB9AD8E"] 7 | } 8 | 9 | resource "aws_iam_role" "gitlab_cicd_oidc" { 10 | assume_role_policy = <