├── Chapter 3
└── Lab build
│ ├── esk
│ ├── .env
│ └── docker-compose.yaml
│ └── fleet
│ ├── .env
│ └── docker-compose.yaml
├── Chapter 4
└── docker-compose.yaml
├── Chapter 7
└── sysmon_config.xml
├── Chapter 8
└── Possible-MOTW-bypass-ISO.yaml
├── LICENSE
├── README.md
└── lab
├── esk
├── .env
└── docker-compose.yml
├── fleet
├── .env
└── docker-compose.yml
└── readme.md
/Chapter 3/Lab build/esk/.env:
--------------------------------------------------------------------------------
1 | ELASTIC_PASSWORD=<>
2 | KIBANA_PASSWORD=<>
3 | STACK_VERSION=8.4.3
4 | CLUSTER_NAME=docker-cluster
5 | LICENSE=basic
6 | ES_PORT=9200
7 | KIBANA_PORT=5601
8 | MEM_LIMIT=1073741824
9 | XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=<>
10 | XPACK_SECURITY_ENCRYPTIONKEY=<>
11 | XPACK_REPORTING_ENCRYPTIONKEY=<>
12 |
--------------------------------------------------------------------------------
/Chapter 3/Lab build/esk/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 |
3 | services:
4 | setup:
5 | image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
6 | volumes:
7 | - ../certs:/usr/share/elasticsearch/config/certs
8 | user: "0"
9 | command: >
10 | bash -c '
11 | if [ x${ELASTIC_PASSWORD} == x ]; then
12 | echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
13 | exit 1;
14 | elif [ x${KIBANA_PASSWORD} == x ]; then
15 | echo "Set the KIBANA_PASSWORD environment variable in the .env file";
16 | exit 1;
17 | fi;
18 | if [ ! -f config/certs/ca.zip ]; then
19 | echo "Creating CA";
20 | bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
21 | unzip config/certs/ca.zip -d config/certs;
22 | fi;
23 | if [ ! -f config/certs/certs.zip ]; then
24 | echo "Creating certs";
25 | echo -ne \
26 | "instances:\n"\
27 | " - name: es01\n"\
28 | " dns:\n"\
29 | " - es01\n"\
30 | " - localhost\n"\
31 | " ip:\n"\
32 | " - 127.0.0.1\n"\
33 | " - name: es02\n"\
34 | " dns:\n"\
35 | " - es02\n"\
36 | " - localhost\n"\
37 | " ip:\n"\
38 | " - 127.0.0.1\n"\
39 | > config/certs/instances.yml;
40 | bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
41 | unzip config/certs/certs.zip -d config/certs;
42 | fi;
43 | echo "Setting file permissions"
44 | chown -R root:root config/certs;
45 | find . -type d -exec chmod 750 \{\} \;;
46 | find . -type f -exec chmod 640 \{\} \;;
47 | echo "Waiting for Elasticsearch availability";
48 | until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
49 | echo "Setting kibana_system password";
50 | until curl -s -X POST --cacert config/certs/ca/ca.crt -u elastic:${ELASTIC_PASSWORD} -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
51 | echo "All done!";
52 | '
53 | healthcheck:
54 | test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
55 | interval: 1s
56 | timeout: 5s
57 | retries: 120
58 |
59 | es01:
60 | depends_on:
61 | setup:
62 | condition: service_healthy
63 | image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
64 | volumes:
65 | - ../certs:/usr/share/elasticsearch/config/certs
66 | ports:
67 | - ${ES_PORT}:9200
68 | environment:
69 | - node.name=es01
70 | - cluster.name=${CLUSTER_NAME}
71 | - cluster.initial_master_nodes=es01,es02
72 | - discovery.seed_hosts=es02
73 | - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
74 | - bootstrap.memory_lock=true
75 | - xpack.security.enabled=true
76 | - xpack.security.http.ssl.enabled=true
77 | - xpack.security.http.ssl.key=certs/es01/es01.key
78 | - xpack.security.http.ssl.certificate=certs/es01/es01.crt
79 | - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
80 | - xpack.security.http.ssl.verification_mode=certificate
81 | - xpack.security.transport.ssl.enabled=true
82 | - xpack.security.transport.ssl.key=certs/es01/es01.key
83 | - xpack.security.transport.ssl.certificate=certs/es01/es01.crt
84 | - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
85 | - xpack.security.transport.ssl.verification_mode=certificate
86 | - xpack.license.self_generated.type=${LICENSE}
87 | mem_limit: ${MEM_LIMIT}
88 | ulimits:
89 | memlock:
90 | soft: -1
91 | hard: -1
92 | healthcheck:
93 | test:
94 | [
95 | "CMD-SHELL",
96 | "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
97 | ]
98 | interval: 10s
99 | timeout: 10s
100 | retries: 120
101 |
102 | es02:
103 | depends_on:
104 | - es01
105 | image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
106 | volumes:
107 | - ../certs:/usr/share/elasticsearch/config/certs
108 | environment:
109 | - node.name=es02
110 | - cluster.name=${CLUSTER_NAME}
111 | - cluster.initial_master_nodes=es01,es02
112 | - discovery.seed_hosts=es01
113 | - bootstrap.memory_lock=true
114 | - xpack.security.enabled=true
115 | - xpack.security.http.ssl.enabled=true
116 | - xpack.security.http.ssl.key=certs/es02/es02.key
117 | - xpack.security.http.ssl.certificate=certs/es02/es02.crt
118 | - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
119 | - xpack.security.http.ssl.verification_mode=certificate
120 | - xpack.security.transport.ssl.enabled=true
121 | - xpack.security.transport.ssl.key=certs/es02/es02.key
122 | - xpack.security.transport.ssl.certificate=certs/es02/es02.crt
123 | - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
124 | - xpack.security.transport.ssl.verification_mode=certificate
125 | - xpack.license.self_generated.type=${LICENSE}
126 | mem_limit: ${MEM_LIMIT}
127 | ulimits:
128 | memlock:
129 | soft: -1
130 | hard: -1
131 | healthcheck:
132 | test:
133 | [
134 | "CMD-SHELL",
135 | "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
136 | ]
137 | interval: 10s
138 | timeout: 10s
139 | retries: 120
140 | kibana:
141 | depends_on:
142 | es01:
143 | condition: service_healthy
144 | es02:
145 | condition: service_healthy
146 | image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
147 | volumes:
148 | - ../certs:/usr/share/kibana/config/certs
149 | ports:
150 | - ${KIBANA_PORT}:5601
151 | environment:
152 | - SERVERNAME=kibana
153 | - ELASTICSEARCH_HOSTS=https://es01:9200
154 | - ELASTICSEARCH_USERNAME=kibana_system
155 | - ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
156 | - ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
157 | - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=${XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY}
158 | - XPACK_SECURITY_ENCRYPTIONKEY=${XPACK_SECURITY_ENCRYPTIONKEY}
159 | - XPACK_REPORTING_ENCRYPTIONKEY=${XPACK_REPORTING_ENCRYPTIONKEY}
160 | mem_limit: ${MEM_LIMIT}
161 | healthcheck:
162 | test:
163 | [
164 | "CMD-SHELL",
165 | "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
166 | ]
167 | interval: 10s
168 | timeout: 10s
169 | retries: 120
170 | networks:
171 | default:
172 | name: elastic-stack-network
173 | volumes:
174 | certs:
175 | driver: local
176 | esdata01:
177 | driver: local
178 | esdata02:
179 | driver: local
180 | kibanadata:
181 | driver: local
182 |
--------------------------------------------------------------------------------
/Chapter 3/Lab build/fleet/.env:
--------------------------------------------------------------------------------
1 | FLEET_SERVER_SERVICE_TOKEN=<>
2 |
--------------------------------------------------------------------------------
/Chapter 3/Lab build/fleet/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3.6"
2 | services:
3 | fleet-server:
4 | image: docker.elastic.co/beats/elastic-agent:8.4.3
5 | container_name: fleet-server
6 | restart: always
7 | volumes:
8 | - ../certs:/certs
9 | ports: [8220:8220]
10 | user: root
11 | environment:
12 | - FLEET_SERVER_ENABLE=true
13 | - FLEET_SERVER_POLICY_NAME=fleet-server-policy
14 | - FLEET_SERVER_ELASTICSEARCH_HOST=https://es01:9200
15 | - FLEET_SERVER_SERVICE_TOKEN=${FLEET_SERVER_SERVICE_TOKEN}
16 | - FLEET_SERVER_ELASTICSEARCH_CA=/certs/ca/ca.crt
17 | - FLEET_INSECURE=true
18 | networks:
19 | default:
20 | name: elastic-stack-network
21 |
--------------------------------------------------------------------------------
/Chapter 4/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 | services:
3 | webapp:
4 | build:
5 | context: ./diwa
6 | ports:
7 | - 80:80
8 | volumes:
9 | - /var/log/apache2:/var/log/apache2
--------------------------------------------------------------------------------
/Chapter 7/sysmon_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HKLM\SYSTEM\CurrentControlSet\Services
6 |
7 |
8 | \ImagePath
9 |
10 |
11 | \ImagePath
12 |
13 |
14 |
15 |
16 |
17 | \
18 |
19 |
20 | msedgeview
21 | \wkssvc
22 | \srvsvc
23 | \lsass
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Chapter 8/Possible-MOTW-bypass-ISO.yaml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | creation_date = "2023/01/30"
3 | maturity = "development"
4 | updated_date = "2023/01/30"
5 |
6 | [rule]
7 | author = ["Jason Deyalsingh"]
8 | description = """
9 | This detection identifies an ISO mounted from a zip existing in a temp directory, which is a procedure used by Qakbot
10 | to perform MOTW bypass. Mark of the web tags exist on Windows operating systems, to inform the user and system
11 | when certain files were downloaded from the internet. This tag attempts to block or otherwise subvert certain
12 | potentially unsafe actions from being performed. Mark of the web bypass techniques attempt to deliver files to the end
13 | user without this tag set, allowing potentially unsafe actions to be taken.
14 | """
15 | from = "now-9m"
16 | index = ["winlogbeat-*"]
17 | language = "eql"
18 | license = "MIT"
19 | name = "ISO mounted from zip temporary directory"
20 | note = """## Investigation Suggestions:
21 |
22 | The ISO run within the temporary directory should be investigated as possible malware. Attempt to identify and evaluate the carrier email message that delivered the ISO as a possible phishing email or investigate the domain or website the ISO was downloaded from. Continue to monitor the endpoint for the "Wermgr running reconnaissance commands" alert which identifies suspicious activity that has been seen occurring after this activity and can be used to confirm the threat as a true positive.
23 |
24 | ##Responses or Remediations:
25 | If confirmed as malicious activity, contain the endpoint prior to remediating. Check all outgoing network connections from the endpoint to identify possible C2. This activity has been associated with ransomware activity and lateral movement using Brute Ratel and Cobalt Strike.
26 |
27 | ##False Positives
28 | Users can legitimately download a zipped ISO file as a developer or network admin role.
29 | """
30 | references = [
31 | "https://www.trendmicro.com/en_us/research/22/j/black-basta-infiltrates-networks-via-qakbot-brute-ratel-and-coba.html"
32 | ]
33 | risk_score = 50
34 | rule_id = "8a1d4831-3ce6-4859-9891-28931fa6101d"
35 | severity = "medium"
36 | tags = ["Elastic", "Host", "Windows", "Threat Detection", "Defense Evasion"]
37 | timestamp_override = "event.ingested"
38 | type = "eql"
39 |
40 | query = '''
41 | any where event.code=="1" and winlog.channel=="Microsoft-Windows-VHDMP-Operational" and winlog.event_data.VhdFileName like~ ("*Temp*","*.zip*","*.iso")
42 | '''
43 |
44 |
45 | [[rule.threat]]
46 | framework = "MITRE ATT&CK"
47 | [[rule.threat.technique]]
48 | id = "T1027"
49 | name = "Obfuscated Files or Information"
50 | reference = "https://attack.mitre.org/techniques/T1027/"
51 |
52 | framework = "MITRE ATT&CK"
53 | [[rule.threat.technique]]
54 | id = "T1553"
55 | name = "Subvert Trust Controls"
56 | reference = "https://attack.mitre.org/techniques/T1553/"
57 | [[rule.threat.technique.subtechnique]]
58 | id = "T1553.005"
59 | name = "Subvert Trust Controls: Mark-of-the-Web"
60 | reference = "https://attack.mitre.org/techniques/T1553/005/"
61 |
62 |
63 | [rule.threat.tactic]
64 | id = "TA0005"
65 | name = "Defense Evasion"
66 | reference = "https://attack.mitre.org/tactics/TA0005/"
67 | [[rule.threat]]
68 |
69 | framework = "MITRE ATT&CK"
70 | [[rule.threat.technique]]
71 | id = "T1204"
72 | name = "User Execution"
73 | reference = "https://attack.mitre.org/techniques/T1204/"
74 | [[rule.threat.technique.subtechnique]]
75 | id = "T1204.002"
76 | name = "User Execution: Malicious Image"
77 | reference = "https://attack.mitre.org/techniques/T1059/002/"
78 |
79 | [rule.threat.tactic]
80 | id = "TA0002"
81 | name = "Execution"
82 | reference = "https://attack.mitre.org/tactics/TA0002/"
83 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Packt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Practical Threat Detection Engineering
2 |
3 |
4 |
5 | This is the code repository for [Practical Threat Detection Engineering](https://www.packtpub.com/product/practical-detection-engineering/9781801076715?utm_source=github&utm_medium=repository&utm_campaign=9781801076715), published by Packt.
6 |
7 | **A hands-on guide to planning, developing, and validating detection capabilities**
8 |
9 | ## What is this book about?
10 |
11 | This book covers the following exciting features:
12 | * Become well versed in the detection engineering process
13 | * Build a detection engineering test lab
14 | * Discover how to maintain detections as code
15 | * Find out how threat intelligence can be used to drive detection development
16 | * Demonstrate the effectiveness of detection capabilities to business leadership
17 | * Limit the attackers’ ability to inflict damage by detecting malicious activity early
18 |
19 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1801076715) today!
20 |
21 |
23 |
24 | ## Instructions and Navigations
25 | All of the code is organized into folders. For example, Chapter 3.
26 |
27 | The code will look like the following:
28 | ```
29 | ES1_DATA=/path/to/large/disk/elasticdata/es01
30 | ES2_DATA=/path/to/large/disk/elasticdata/es02
31 | KIBANA_DATA=/path/to/large/disk/elasticdata/kibana_data
32 | ```
33 | Any command-line input or output is written as follows:
34 | ```
35 | $ docker --version
36 | Docker version v20.10.12, build 20.10.12-0ubuntu4
37 | ```
38 |
39 | **Following is what you need for this book:**
40 | This book is for security analysts and engineers seeking to improve their organization’s security posture by mastering the detection engineering lifecycle.
41 | To get started with this book, you’ll need a basic understanding of cybersecurity concepts, along with some experience with detection and alert capabilities.
42 |
43 | With the following software and hardware list you can run all code files present in the book (Chapter 1-12).
44 | ### Software and Hardware List
45 | | Software/hardware covered in the bookd | Operating system requirements |
46 | | ------------------------------------ | ----------------------------------- |
47 | | Docker | Windows or Linux |
48 | | VirtualBox | Windows or Linux |
49 |
50 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it]( https://packt.link/qt1nr).
51 |
52 | ### Related products
53 | * Incident Response Techniques for Ransomware Attacks [[Packt]](https://www.packtpub.com/product/incident-response-techniques-for-ransomware-attacks/9781803240442?utm_source=github&utm_medium=repository&utm_campaign=9781803240442) [[Amazon]](https://www.amazon.com/dp/180324044X)
54 |
55 | * Incident Response with Threat Intelligence [[Packt]](https://www.packtpub.com/product/incident-response-with-threat-intelligence/9781801072953?utm_source=github&utm_medium=repository&utm_campaign=9781801072953) [[Amazon]](https://www.amazon.com/dp/1801072957)
56 |
57 | ## Get to Know the Authors
58 | **Megan Roddie**
59 | is an experienced information security professional with a diverse background ranging from incident response to threat intelligence to her current role as a detection engineer. Additionally, Megan is a course author and instructor with the SANS Institute where she regularly publishes research on cloud incident response and forensics. Outside of the cyber security industry, Megan trains and competes as a high-level amateur Muay Thai fighter in Austin, TX.
60 |
61 | **Jason Deyalsingh**
62 | is an experienced consultant with over nine years of experience in the cyber security space. He has spent the last 5 years focused on digital forensics and incident response (DFIR). His current hobbies include playing with data and failing to learn Rust.
63 |
64 | **Gary J. Katz**
65 | is still trying to figure out what to do with his life while contemplating what its purpose really is. While not spiraling into this metaphysical black hole compounded by the plagues and insanity of this world, he sometimes thinks about cyber security problems and writes them down. These ruminations are, on occasion, captured in articles and books.
66 |
--------------------------------------------------------------------------------
/lab/esk/.env:
--------------------------------------------------------------------------------
1 | ELASTIC_PASSWORD=<>
2 | KIBANA_PASSWORD=<>
3 | STACK_VERSION=8.4.3
4 | CLUSTER_NAME=docker-cluster
5 | LICENSE=basic
6 | ES_PORT=9200
7 | KIBANA_PORT=5601
8 | MEM_LIMIT=1073741824
9 | XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=<>
10 | XPACK_SECURITY_ENCRYPTIONKEY=<>
11 | XPACK_REPORTING_ENCRYPTIONKEY=<>
12 |
--------------------------------------------------------------------------------
/lab/esk/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 |
3 | services:
4 | setup:
5 | image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
6 | volumes:
7 | - ../certs:/usr/share/elasticsearch/config/certs
8 | user: "0"
9 | command: >
10 | bash -c '
11 | if [ x${ELASTIC_PASSWORD} == x ]; then
12 | echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
13 | exit 1;
14 | elif [ x${KIBANA_PASSWORD} == x ]; then
15 | echo "Set the KIBANA_PASSWORD environment variable in the .env file";
16 | exit 1;
17 | fi;
18 | if [ ! -f config/certs/ca.zip ]; then
19 | echo "Creating CA";
20 | bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
21 | unzip config/certs/ca.zip -d config/certs;
22 | fi;
23 | if [ ! -f config/certs/certs.zip ]; then
24 | echo "Creating certs";
25 | echo -ne \
26 | "instances:\n"\
27 | " - name: es01\n"\
28 | " dns:\n"\
29 | " - es01\n"\
30 | " - localhost\n"\
31 | " ip:\n"\
32 | " - 127.0.0.1\n"\
33 | " - name: es02\n"\
34 | " dns:\n"\
35 | " - es02\n"\
36 | " - localhost\n"\
37 | " ip:\n"\
38 | " - 127.0.0.1\n"\
39 | > config/certs/instances.yml;
40 | bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
41 | unzip config/certs/certs.zip -d config/certs;
42 | fi;
43 | echo "Setting file permissions"
44 | chown -R root:root config/certs;
45 | find . -type d -exec chmod 750 \{\} \;;
46 | find . -type f -exec chmod 640 \{\} \;;
47 | echo "Waiting for Elasticsearch availability";
48 | until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
49 | echo "Setting kibana_system password";
50 | until curl -s -X POST --cacert config/certs/ca/ca.crt -u elastic:${ELASTIC_PASSWORD} -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
51 | echo "All done!";
52 | '
53 | healthcheck:
54 | test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
55 | interval: 1s
56 | timeout: 5s
57 | retries: 120
58 |
59 | es01:
60 | depends_on:
61 | setup:
62 | condition: service_healthy
63 | image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
64 | volumes:
65 | - ../certs:/usr/share/elasticsearch/config/certs
66 | ports:
67 | - ${ES_PORT}:9200
68 | environment:
69 | - node.name=es01
70 | - cluster.name=${CLUSTER_NAME}
71 | - cluster.initial_master_nodes=es01,es02
72 | - discovery.seed_hosts=es02
73 | - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
74 | - bootstrap.memory_lock=true
75 | - xpack.security.enabled=true
76 | - xpack.security.http.ssl.enabled=true
77 | - xpack.security.http.ssl.key=certs/es01/es01.key
78 | - xpack.security.http.ssl.certificate=certs/es01/es01.crt
79 | - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
80 | - xpack.security.http.ssl.verification_mode=certificate
81 | - xpack.security.transport.ssl.enabled=true
82 | - xpack.security.transport.ssl.key=certs/es01/es01.key
83 | - xpack.security.transport.ssl.certificate=certs/es01/es01.crt
84 | - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
85 | - xpack.security.transport.ssl.verification_mode=certificate
86 | - xpack.license.self_generated.type=${LICENSE}
87 | mem_limit: ${MEM_LIMIT}
88 | ulimits:
89 | memlock:
90 | soft: -1
91 | hard: -1
92 | healthcheck:
93 | test:
94 | [
95 | "CMD-SHELL",
96 | "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
97 | ]
98 | interval: 10s
99 | timeout: 10s
100 | retries: 120
101 |
102 | es02:
103 | depends_on:
104 | - es01
105 | image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
106 | volumes:
107 | - ../certs:/usr/share/elasticsearch/config/certs
108 | environment:
109 | - node.name=es02
110 | - cluster.name=${CLUSTER_NAME}
111 | - cluster.initial_master_nodes=es01,es02
112 | - discovery.seed_hosts=es01
113 | - bootstrap.memory_lock=true
114 | - xpack.security.enabled=true
115 | - xpack.security.http.ssl.enabled=true
116 | - xpack.security.http.ssl.key=certs/es02/es02.key
117 | - xpack.security.http.ssl.certificate=certs/es02/es02.crt
118 | - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
119 | - xpack.security.http.ssl.verification_mode=certificate
120 | - xpack.security.transport.ssl.enabled=true
121 | - xpack.security.transport.ssl.key=certs/es02/es02.key
122 | - xpack.security.transport.ssl.certificate=certs/es02/es02.crt
123 | - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
124 | - xpack.security.transport.ssl.verification_mode=certificate
125 | - xpack.license.self_generated.type=${LICENSE}
126 | mem_limit: ${MEM_LIMIT}
127 | ulimits:
128 | memlock:
129 | soft: -1
130 | hard: -1
131 | healthcheck:
132 | test:
133 | [
134 | "CMD-SHELL",
135 | "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
136 | ]
137 | interval: 10s
138 | timeout: 10s
139 | retries: 120
140 | kibana:
141 | depends_on:
142 | es01:
143 | condition: service_healthy
144 | es02:
145 | condition: service_healthy
146 | image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
147 | volumes:
148 | - ../certs:/usr/share/kibana/config/certs
149 | ports:
150 | - ${KIBANA_PORT}:5601
151 | environment:
152 | - SERVERNAME=kibana
153 | - ELASTICSEARCH_HOSTS=https://es01:9200
154 | - ELASTICSEARCH_USERNAME=kibana_system
155 | - ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
156 | - ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
157 | - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=${XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY}
158 | - XPACK_SECURITY_ENCRYPTIONKEY=${XPACK_SECURITY_ENCRYPTIONKEY}
159 | - XPACK_REPORTING_ENCRYPTIONKEY=${XPACK_REPORTING_ENCRYPTIONKEY}
160 | mem_limit: ${MEM_LIMIT}
161 | healthcheck:
162 | test:
163 | [
164 | "CMD-SHELL",
165 | "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
166 | ]
167 | interval: 10s
168 | timeout: 10s
169 | retries: 120
170 | networks:
171 | default:
172 | name: elastic-stack-network
173 | volumes:
174 | certs:
175 | driver: local
176 | esdata01:
177 | driver: local
178 | esdata02:
179 | driver: local
180 | kibanadata:
181 | driver: local
182 |
--------------------------------------------------------------------------------
/lab/fleet/.env:
--------------------------------------------------------------------------------
1 | FLEET_SERVER_SERVICE_TOKEN=<>
2 |
--------------------------------------------------------------------------------
/lab/fleet/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.6"
2 | services:
3 | fleet-server:
4 | image: docker.elastic.co/beats/elastic-agent:8.4.3
5 | container_name: fleet-server
6 | restart: always
7 | volumes:
8 | - ../certs:/certs
9 | ports: [8220:8220]
10 | user: root
11 | environment:
12 | - FLEET_SERVER_ENABLE=true
13 | - FLEET_SERVER_POLICY_NAME=fleet-server-policy
14 | - FLEET_SERVER_ELASTICSEARCH_HOST=https://es01:9200
15 | - FLEET_SERVER_SERVICE_TOKEN=${FLEET_SERVER_SERVICE_TOKEN}
16 | - FLEET_SERVER_ELASTICSEARCH_CA=/certs/ca/ca.crt
17 | - FLEET_INSECURE=true
18 | networks:
19 | default:
20 | name: elastic-stack-network
21 |
--------------------------------------------------------------------------------
/lab/readme.md:
--------------------------------------------------------------------------------
1 | # Elasticstack - docker deployment
2 |
3 |
4 |
5 |
6 | Before running docker-compose, make sure to execute the following command:
7 |
8 | ~~~bash
9 | sysctl -w vm.max_map_count=262144
10 | ~~~
11 |
12 |
13 | ### Windows and docker desktop
14 |
15 |
16 | #### requirements
17 | - requires: WSL 2
18 | - use a static IP address
19 |
20 | #### Procedure - elastic stack
21 |
22 | 1. Install docker desktop
23 | 2. install docker-compose [Other install scearios](https://docs.docker.com/compose/install/other/#on-windows-server)
24 | 3. copy docker-compose.yaml and .env to a separate folder
25 | 4. configure vm.max_map_count variable for docker wsl distribution
26 | ~~~powershell
27 | c:\progs\docker\elastic>wsl -l
28 | Windows Subsystem for Linux Distributions:
29 | Ubuntu (Default)
30 | podman-machine-default
31 | docker-desktop
32 | docker-desktop-data
33 | c:\progs\docker\elastic>wsl -d docker-desktop
34 | labhost8:/mnt/host/c/progs/docker/elastic# sysctl -w vm.max_map_count=262144
35 | vm.max_map_count = 262144
36 | ~~~
37 |
38 | 5. run docker-compose up -d
39 |
40 |
--------------------------------------------------------------------------------