diff --git a/README.md b/README.md
index a4082a8..32ccb1d 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
[![Documentation](https://img.shields.io/badge/docs-view-green.svg)](https://documentation.wazuh.com)
[![Web](https://img.shields.io/badge/web-view-green.svg)](https://wazuh.com)
-This repository includes the template and scripts to set up an environment that includes:
+This repository contains CloudFormation templates and provision scripts to deploy both a Wazuh production-ready environment and a Wazuh demo environment in Amazon Web Services (AWS):
+
+## Production-ready environment:
* A VPC with two subnets, one for Wazuh servers, and another for Elastic Stack
* Wazuh managers cluster with two nodes, a master and a worker
@@ -13,97 +15,15 @@ This repository includes the template and scripts to set up an environment that
* A Kibana node that includes a local elasticsearch client node, and an Nginx for HTTP basic authentication
* Wazuh servers seat behind an internet-facing load balancer for agents to communicate with the cluster
* Kibana server seats behind an internet facing load balancer, that optionally loads an SSL Certificate for HTTPS
-* A Splunk Indexer instance with a Splunk app for Wazuh installed on it.
-* Six Wazuh agents installed on different operating systems: Red Hat 7, CentOS 7, Ubuntu, Debian, Amazon Linux and Windows.
-
-## Elasticsearch cluster configuration
-
-Elasticsearch data nodes are deployed as part of an auto scaling group, that scales based on CPU usage. Minimum number of nodes is 3, and maximum is 6.
-
-Elasticsearch instance types can be chosen from:
-
-* i3.large
-* i3.xlarge
-* i3.2xlarge
-* t2.large
-* t2.medium
-
-These instance types are recommended due to Elasticsearch disk requirements. Ephemeral disks are used for data storage.
-
-None of these instances are directly accessible from the Internet, although they can be reached jumping through the Kibana system, that has a public SSH service.
-
-## Kibana server configuration
-
-Kibana server runs an instance of Elasticsearch (acting as a client node), an instance of Kibana (with Wazuh plugin installed and configured), and an instance of Nginx (used to provide SSL encryption and basic HTTP authentication).
-
-Kibana instance types can be chosen from:
-
-* m5.large
-* m5.xlarge
-* m5.2xlarge
-* t2.large
-* t2.medium
-* r5.large
-
-These instance types are recommended due to Kibana and Elasticsearch memory requirements.
-
-In addition, the Kibana server takes care of:
-
-* Setting up wazuh-alerts template in Elasticsearch
-* Setting default index-pattern to wazuh-alerts
-* Setting default time-picker to 24 hours
-
-Kibana server is reachable from the Internet, directly via its own Elastic IP, or through an internet-facing load balancer. The load balancer can be used, optionally, to add a valid Amazon SSL Certificate for HTTPS communications.
-
-## Wazuh cluster configuration
-
-The Wazuh cluster deployed has one master node (providing API and registration server) and one worker node.
-
-Wazuh instance types can be chosen from:
-
-* m5.large
-* m5.xlarge
-* m5.2xlarge
-* t2.micro
-* t2.medium
-* t2.large
-
-These instance types are recommended for the managers, as they provide enough memory for Wazuh components.
+* Route53 DNS records for the loadbalancer, Wazuh and Elastic Stack nodes (optional).
-The Wazuh API, running on Wazuh master node, is automatically configured to use HTTPS protocol.
+## Demo environment:
-The Wazuh registration service (authd), running on Wazuh master node, is configured not to use source IP addresses. We assume that agents will connect through the Internet, and most likely several will use the same source IP (sitting behind a NAT). This service is configured automatically to require password authentication for new agents registration.
-
-Filebeat runs on both the Wazuh master node and the worker node, reading alerts and forwarding those to Elasticsearch nodes via the internal load balancer.
-
-New agents can make use of the Wazuh master public Elastic IP address for registration.
-
-Once registered, new agents can connect to the Wazuh cluster, via TCP, using the load balancer public IP address.
-
-## Optional DNS records
-
-A parent domain (e.g. mycompany.com) and subdomain (e.g. wazuh) can be specified. In this example, this is what would be used for communications:
-
-* wazuh.mycompany.com: domain name for access to Kibana WUI (via HTTPS). It also provides access via SSH (jumpbox to servers).
-* registration.wazuh.mycompany.com: domain name for agents registration.
-* data.wazuh.mycompany.com: domain name for agents communication with the cluster.
-
-An example of the installation of a new agent, on a Windows system (automatically registered and configured) using an MSI package would be:
-
- wazuh-agent-3.12.0-1.msi /q ADDRESS=“wazuh.mycompany.com” AUTHD_SERVER=“registration.wazuh.mycompany.com” PASSWORD=“mypassword” AGENT_NAME=“myhostname” PROTOCOL=“TCP”
-
-An example of the registration of a new agent on a Linux system would be:
-
- /var/ossec/bin/agent-auth -m registration.wazuh.mycompany.com -P mypassword -A myhostname
-
-Then, on the linux agent, the /var/ossec/etc/ossec.conf would include the configuration to connect to the managers:
-
-
- data.wazuh.mycompany.com
- 1514
- tcp
-
-
-## AWS environment created by cloud formation template
-
-![wazuh_template](images/wazuh_template-designer.png)
+* A VPC with two subnets, one for Wazuh servers, and another for Elastic Stack
+* Wazuh managers cluster with two nodes, a master and a worker
+* An Elasticsearch cluster with a minimum of 3 data nodes, auto-scalable to a maximum of 6 nodes
+* A Kibana node that includes a local elasticsearch client node, and an Nginx for HTTP basic authentication
+* Wazuh servers seat behind an internet-facing load balancer for agents to communicate with the cluster
+* Kibana server seats behind an internet facing load balancer, that optionally loads an SSL Certificate for HTTPS
+* A Splunk Indexer instance with a Splunk app for Wazuh installed on it.
+* Six Wazuh agents installed on different operating systems: Red Hat 7, CentOS 7, Ubuntu, Debian, Amazon Linux and Windows.
diff --git a/.gitignore b/demo/.gitignore
similarity index 100%
rename from .gitignore
rename to demo/.gitignore
diff --git a/demo/README.md b/demo/README.md
new file mode 100644
index 0000000..6be028c
--- /dev/null
+++ b/demo/README.md
@@ -0,0 +1,109 @@
+# Wazuh for Amazon AWS Cloudformation
+
+[![Slack](https://img.shields.io/badge/slack-join-blue.svg)](https://goo.gl/forms/M2AoZC4b2R9A9Zy12)
+[![Email](https://img.shields.io/badge/email-join-blue.svg)](https://groups.google.com/forum/#!forum/wazuh)
+[![Documentation](https://img.shields.io/badge/docs-view-green.svg)](https://documentation.wazuh.com)
+[![Web](https://img.shields.io/badge/web-view-green.svg)](https://wazuh.com)
+
+The template and scripts here set up an environment that includes:
+
+* A VPC with two subnets, one for Wazuh servers, and another for Elastic Stack
+* Wazuh managers cluster with two nodes, a master and a worker
+* An Elasticsearch cluster with a minimum of 3 data nodes, auto-scalable to a maximum of 6 nodes
+* A Kibana node that includes a local elasticsearch client node, and an Nginx for HTTP basic authentication
+* Wazuh servers seat behind an internet-facing load balancer for agents to communicate with the cluster
+* Kibana server seats behind an internet facing load balancer, that optionally loads an SSL Certificate for HTTPS
+* A Splunk Indexer instance with a Splunk app for Wazuh installed on it.
+* Six Wazuh agents installed on different operating systems: Red Hat 7, CentOS 7, Ubuntu, Debian, Amazon Linux and Windows.
+
+## Elasticsearch cluster configuration
+
+Elasticsearch data nodes are deployed as part of an auto scaling group, that scales based on CPU usage. Minimum number of nodes is 3, and maximum is 6.
+
+Elasticsearch instance types can be chosen from:
+
+* i3.large
+* i3.xlarge
+* i3.2xlarge
+* t2.large
+* t2.medium
+
+These instance types are recommended due to Elasticsearch disk requirements. Ephemeral disks are used for data storage.
+
+None of these instances are directly accessible from the Internet, although they can be reached jumping through the Kibana system, that has a public SSH service.
+
+## Kibana server configuration
+
+Kibana server runs an instance of Elasticsearch (acting as a client node), an instance of Kibana (with Wazuh plugin installed and configured), and an instance of Nginx (used to provide SSL encryption and basic HTTP authentication).
+
+Kibana instance types can be chosen from:
+
+* m5.large
+* m5.xlarge
+* m5.2xlarge
+* t2.large
+* t2.medium
+* r5.large
+
+These instance types are recommended due to Kibana and Elasticsearch memory requirements.
+
+In addition, the Kibana server takes care of:
+
+* Setting up wazuh-alerts template in Elasticsearch
+* Setting default index-pattern to wazuh-alerts
+* Setting default time-picker to 24 hours
+
+Kibana server is reachable from the Internet, directly via its own Elastic IP, or through an internet-facing load balancer. The load balancer can be used, optionally, to add a valid Amazon SSL Certificate for HTTPS communications.
+
+## Wazuh cluster configuration
+
+The Wazuh cluster deployed has one master node (providing API and registration server) and one worker node.
+
+Wazuh instance types can be chosen from:
+
+* m5.large
+* m5.xlarge
+* m5.2xlarge
+* t2.micro
+* t2.medium
+* t2.large
+
+These instance types are recommended for the managers, as they provide enough memory for Wazuh components.
+
+The Wazuh API, running on Wazuh master node, is automatically configured to use HTTPS protocol.
+
+The Wazuh registration service (authd), running on Wazuh master node, is configured not to use source IP addresses. We assume that agents will connect through the Internet, and most likely several will use the same source IP (sitting behind a NAT). This service is configured automatically to require password authentication for new agents registration.
+
+Filebeat runs on both the Wazuh master node and the worker node, reading alerts and forwarding those to Elasticsearch nodes via the internal load balancer.
+
+New agents can make use of the Wazuh master public Elastic IP address for registration.
+
+Once registered, new agents can connect to the Wazuh cluster, via TCP, using the load balancer public IP address.
+
+## Optional DNS records
+
+A parent domain (e.g. mycompany.com) and subdomain (e.g. wazuh) can be specified. In this example, this is what would be used for communications:
+
+* wazuh.mycompany.com: domain name for access to Kibana WUI (via HTTPS). It also provides access via SSH (jumpbox to servers).
+* registration.wazuh.mycompany.com: domain name for agents registration.
+* data.wazuh.mycompany.com: domain name for agents communication with the cluster.
+
+An example of the installation of a new agent, on a Windows system (automatically registered and configured) using an MSI package would be:
+
+ wazuh-agent-3.12.2-1.msi /q ADDRESS=“wazuh.mycompany.com” AUTHD_SERVER=“registration.wazuh.mycompany.com” PASSWORD=“mypassword” AGENT_NAME=“myhostname” PROTOCOL=“TCP”
+
+An example of the registration of a new agent on a Linux system would be:
+
+ /var/ossec/bin/agent-auth -m registration.wazuh.mycompany.com -P mypassword -A myhostname
+
+Then, on the linux agent, the /var/ossec/etc/ossec.conf would include the configuration to connect to the managers:
+
+
+ data.wazuh.mycompany.com
+ 1514
+ tcp
+
+
+## AWS demo environment diagram
+
+![wazuh_template](images/wazuh_template-designer.png)
diff --git a/deploy.sh b/demo/deploy.sh
similarity index 91%
rename from deploy.sh
rename to demo/deploy.sh
index 315a059..e5e276a 100755
--- a/deploy.sh
+++ b/demo/deploy.sh
@@ -29,7 +29,7 @@ fi
# Uploading template to S3
aws s3 cp $TEMPLATE_FILE s3://$BUCKET_NAME
# Getting the template URL
-URL="https://demo-cloudformation-templates.s3-us-west-1.amazonaws.com/wazuh_template.yml"
+URL="https://$BUCKET_NAME.s3-us-west-1.amazonaws.com/wazuh_template.yml"
echo "Template URL: $URL"
aws cloudformation create-stack --stack-name ${STACK_NAME} --template-url $URL --parameters file://$PARAMS_FILE --capabilities CAPABILITY_IAM --tags Key=service_name,Value=demo_info
diff --git a/elastic/wazuh_cf_bootstrap_elastic.sh b/demo/elastic/wazuh_cf_bootstrap_elastic.sh
similarity index 100%
rename from elastic/wazuh_cf_bootstrap_elastic.sh
rename to demo/elastic/wazuh_cf_bootstrap_elastic.sh
diff --git a/elastic/wazuh_cf_elastic.sh b/demo/elastic/wazuh_cf_elastic.sh
similarity index 100%
rename from elastic/wazuh_cf_elastic.sh
rename to demo/elastic/wazuh_cf_elastic.sh
diff --git a/elastic/wazuh_cf_kibana.sh b/demo/elastic/wazuh_cf_kibana.sh
similarity index 97%
rename from elastic/wazuh_cf_kibana.sh
rename to demo/elastic/wazuh_cf_kibana.sh
index 83b4a56..71d4253 100644
--- a/elastic/wazuh_cf_kibana.sh
+++ b/demo/elastic/wazuh_cf_kibana.sh
@@ -297,6 +297,18 @@ install_plugin(){
}
+
+optimize_kibana(){
+ systemctl stop kibana
+ echo "Optimizing app" >> /tmp/deploy.log
+ cd /usr/share/kibana
+ sudo -u kibana /usr/share/kibana/node/bin/node --no-warnings --max-old-space-size=2048 --max-http-header-size=65536 /usr/share/kibana/src/cli --optimize
+ cd /tmp
+ echo "App installed!" >> /tmp/deploy.log
+ systemctl start kibana
+}
+
+
add_api(){
echo "Adding Wazuh API" >> /tmp/deploy.log
sed -ie '/- default:/,+4d' /usr/share/kibana/optimize/wazuh/config/wazuh.yml
@@ -430,6 +442,7 @@ main(){
get_plugin_url
install_plugin
enable_kibana
+ optimize_kibana
start_kibana
sleep 60
add_api
diff --git a/images/wazuh_template-designer.png b/demo/images/wazuh_template-designer.png
similarity index 100%
rename from images/wazuh_template-designer.png
rename to demo/images/wazuh_template-designer.png
diff --git a/splunk/wazuh_cf_splunk.sh b/demo/splunk/wazuh_cf_splunk.sh
similarity index 100%
rename from splunk/wazuh_cf_splunk.sh
rename to demo/splunk/wazuh_cf_splunk.sh
diff --git a/wazuh/agents/wazuh_agent_amazon.sh b/demo/wazuh/agents/wazuh_agent_amazon.sh
similarity index 100%
rename from wazuh/agents/wazuh_agent_amazon.sh
rename to demo/wazuh/agents/wazuh_agent_amazon.sh
diff --git a/wazuh/agents/wazuh_agent_centos.sh b/demo/wazuh/agents/wazuh_agent_centos.sh
similarity index 100%
rename from wazuh/agents/wazuh_agent_centos.sh
rename to demo/wazuh/agents/wazuh_agent_centos.sh
diff --git a/wazuh/agents/wazuh_agent_rhel.sh b/demo/wazuh/agents/wazuh_agent_rhel.sh
similarity index 100%
rename from wazuh/agents/wazuh_agent_rhel.sh
rename to demo/wazuh/agents/wazuh_agent_rhel.sh
diff --git a/wazuh/agents/wazuh_cf_agent.sh b/demo/wazuh/agents/wazuh_cf_agent.sh
similarity index 100%
rename from wazuh/agents/wazuh_cf_agent.sh
rename to demo/wazuh/agents/wazuh_cf_agent.sh
diff --git a/wazuh/agents/wazuh_cf_agent_debian.sh b/demo/wazuh/agents/wazuh_cf_agent_debian.sh
similarity index 100%
rename from wazuh/agents/wazuh_cf_agent_debian.sh
rename to demo/wazuh/agents/wazuh_cf_agent_debian.sh
diff --git a/wazuh/agents/wazuh_cf_agent_ubuntu.sh b/demo/wazuh/agents/wazuh_cf_agent_ubuntu.sh
similarity index 100%
rename from wazuh/agents/wazuh_cf_agent_ubuntu.sh
rename to demo/wazuh/agents/wazuh_cf_agent_ubuntu.sh
diff --git a/wazuh/cluster/wazuh_cf_master.sh b/demo/wazuh/cluster/wazuh_cf_master.sh
similarity index 100%
rename from wazuh/cluster/wazuh_cf_master.sh
rename to demo/wazuh/cluster/wazuh_cf_master.sh
diff --git a/wazuh/cluster/wazuh_cf_worker.sh b/demo/wazuh/cluster/wazuh_cf_worker.sh
similarity index 100%
rename from wazuh/cluster/wazuh_cf_worker.sh
rename to demo/wazuh/cluster/wazuh_cf_worker.sh
diff --git a/wazuh_template.yml b/demo/wazuh_template.yml
similarity index 98%
rename from wazuh_template.yml
rename to demo/wazuh_template.yml
index c460f4c..abad351 100644
--- a/wazuh_template.yml
+++ b/demo/wazuh_template.yml
@@ -726,7 +726,7 @@ Resources:
group: root
/tmp/wazuh_cf_bootstrap_elastic.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/elastic/wazuh_cf_bootstrap_elastic.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/elastic/wazuh_cf_bootstrap_elastic.sh
mode: '000700'
owner: root
group: root
@@ -805,7 +805,7 @@ Resources:
group: root
/tmp/wazuh_cf_elastic.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/elastic/wazuh_cf_elastic.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/elastic/wazuh_cf_elastic.sh
mode: '000700'
owner: root
group: root
@@ -884,7 +884,7 @@ Resources:
group: root
/tmp/wazuh_cf_elastic.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/elastic/wazuh_cf_elastic.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/elastic/wazuh_cf_elastic.sh
mode: '000700'
owner: root
group: root
@@ -1111,7 +1111,7 @@ Resources:
group: root
/tmp/wazuh_cf_kibana.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/elastic/wazuh_cf_kibana.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/elastic/wazuh_cf_kibana.sh
mode: '000700'
owner: root
group: root
@@ -1188,7 +1188,7 @@ Resources:
group: root
/tmp/wazuh_cf_splunk.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/splunk/wazuh_cf_splunk.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/splunk/wazuh_cf_splunk.sh
mode: '000700'
owner: root
group: root
@@ -1282,7 +1282,7 @@ Resources:
group: root
/tmp/wazuh_cf_master.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/cluster/wazuh_cf_master.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/cluster/wazuh_cf_master.sh
mode: '000700'
owner: root
group: root
@@ -1371,7 +1371,7 @@ Resources:
group: root
/tmp/wazuh_cf_worker.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/cluster/wazuh_cf_worker.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/cluster/wazuh_cf_worker.sh
mode: '000700'
owner: root
group: root
@@ -1452,7 +1452,7 @@ Resources:
group: root
/tmp/wazuh_agent_amazon.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/agents/wazuh_agent_amazon.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/agents/wazuh_agent_amazon.sh
mode: '000700'
owner: root
group: root
@@ -1533,7 +1533,7 @@ Resources:
group: root
/tmp/wazuh_agent_centos.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/agents/wazuh_agent_centos.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/agents/wazuh_agent_centos.sh
mode: '000700'
owner: root
group: root
@@ -1707,7 +1707,7 @@ Resources:
group: root
/tmp/wazuh_agent_debian.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/agents/wazuh_cf_agent_debian.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/agents/wazuh_cf_agent_debian.sh
mode: '000700'
owner: root
group: root
@@ -1795,7 +1795,7 @@ Resources:
group: root
/tmp/wazuh_agent_ubuntu.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/agents/wazuh_cf_agent_ubuntu.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/agents/wazuh_cf_agent_ubuntu.sh
mode: '000700'
owner: root
group: root
@@ -1883,7 +1883,7 @@ Resources:
group: root
/tmp/wazuh_agent_rhel.sh:
source: !Sub >-
- https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/wazuh/agents/wazuh_agent_rhel.sh
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/demo/wazuh/agents/wazuh_agent_rhel.sh
mode: '000700'
owner: root
group: root
diff --git a/production/README.md b/production/README.md
new file mode 100644
index 0000000..4ca155d
--- /dev/null
+++ b/production/README.md
@@ -0,0 +1,178 @@
+# Wazuh for Amazon AWS Cloudformation
+
+[![Slack](https://img.shields.io/badge/slack-join-blue.svg)](https://goo.gl/forms/M2AoZC4b2R9A9Zy12)
+[![Email](https://img.shields.io/badge/email-join-blue.svg)](https://groups.google.com/forum/#!forum/wazuh)
+[![Documentation](https://img.shields.io/badge/docs-view-green.svg)](https://documentation.wazuh.com)
+[![Web](https://img.shields.io/badge/web-view-green.svg)](https://wazuh.com)
+
+The production environment has the following structure:
+
+* A VPC with two subnets, one for Wazuh servers, and another for Elastic Stack
+* Wazuh managers cluster with two nodes, a master and a worker
+* An Elasticsearch cluster with a minimum of 3 data nodes, auto-scalable to a maximum of 6 nodes
+* A Kibana node that includes a local elasticsearch client node, and an Nginx for HTTP basic authentication
+* Wazuh servers seat behind an internet-facing load balancer for agents to communicate with the cluster
+* Kibana server seats behind an internet facing load balancer, that optionally loads an SSL Certificate for HTTPS
+* Route53 DNS records for the loadbalancer, Wazuh and Elastic Stack nodes (optional).
+
+## Elasticsearch cluster configuration
+
+Elasticsearch data nodes are deployed as part of an auto scaling group, that scales based on CPU usage. Minimum number of nodes is 3, and maximum is 6.
+
+Elasticsearch instance types can be chosen from:
+
+* i3.large
+* i3.xlarge
+* i3.2xlarge
+* t2.large
+* t2.medium
+
+These instance types are recommended due to Elasticsearch disk requirements. Ephemeral disks are used for data storage.
+
+None of these instances are directly accessible from the Internet, although they can be reached jumping through the Kibana system, that has a public SSH service.
+
+## Kibana server configuration
+
+Kibana server runs an instance of Elasticsearch (acting as a client node), an instance of Kibana (with Wazuh plugin installed and configured), and an instance of Nginx (used to provide SSL encryption and basic HTTP authentication).
+
+Kibana instance types can be chosen from:
+
+* m5.large
+* m5.xlarge
+* m5.2xlarge
+* t2.large
+* t2.medium
+* r5.large
+
+These instance types are recommended due to Kibana and Elasticsearch memory requirements.
+
+In addition, the Kibana server takes care of:
+
+* Setting up wazuh-alerts template in Elasticsearch
+* Setting default index-pattern to wazuh-alerts
+* Setting default time-picker to 24 hours
+
+Kibana server is reachable from the Internet, directly via its own Elastic IP, or through an internet-facing load balancer. The load balancer can be used, optionally, to add a valid Amazon SSL Certificate for HTTPS communications.
+
+## Wazuh cluster configuration
+
+The Wazuh cluster deployed has one master node (providing API and registration server) and one worker node.
+
+Wazuh instance types can be chosen from:
+
+* m5.large
+* m5.xlarge
+* m5.2xlarge
+* t2.micro
+* t2.medium
+* t2.large
+
+These instance types are recommended for the managers, as they provide enough memory for Wazuh components.
+
+The Wazuh API, running on Wazuh master node, is automatically configured to use HTTPS protocol.
+
+The Wazuh registration service (authd), running on Wazuh master node, is configured not to use source IP addresses. We assume that agents will connect through the Internet, and most likely several will use the same source IP (sitting behind a NAT). This service is configured automatically to require password authentication for new agents registration.
+
+Filebeat runs on both the Wazuh master node and the worker node, reading alerts and forwarding those to Elasticsearch nodes via the internal load balancer.
+
+New agents can make use of the Wazuh master public Elastic IP address for registration.
+
+Once registered, new agents can connect to the Wazuh cluster, via TCP, using the load balancer public IP address.
+
+## Optional DNS records
+
+Optionally it is possible to deploy DNS records for the loadbalancer, Wazuh nodes and Elastic Stack nodes. The `EnableDNSRecord`, `Subdomain` and `HostedZoneName` parameters configure the related Route 53 settings.
+
+* `EnableDNSRecord` parameter enables/disables the DNS record usage.
+* `HostedZoneName` sets the parent domain for the loadbalancer and the instances.
+* The `Subdomain` parameter sets the subdomain name for the loadbalancer.
+* Elastic Stack nodes and Wazuh nodes subdomain names are hardcoded on the CloudFormation template.
+
+
+## Parameters template
+
+The following template contains an example list of parameters and value placeholders.
+
+```json
+[{
+ "ParameterKey": "ElasticWazuhVersion",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhInstanceType",
+ "ParameterValue": "t2.medium"
+},
+{
+ "ParameterKey": "InstallType",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "ElasticInstanceType",
+ "ParameterValue": "t2.large"
+},
+{
+ "ParameterKey": "KibanaInstanceType",
+ "ParameterValue": "t2.large"
+},
+{
+ "ParameterKey": "SshUsername",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "SshPassword",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhServerPort",
+ "ParameterValue": "1514"
+},
+{
+ "ParameterKey": "WazuhRegistrationPort",
+ "ParameterValue": "1515"
+},
+{
+ "ParameterKey": "WazuhRegistrationPassword",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhApiPort",
+ "ParameterValue": "55000"
+},
+{
+ "ParameterKey": "WazuhApiAdminUsername",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhApiAdminPassword",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "KeyPairName",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "AvailabilityZone",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "SSLCertificateARN",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "EnableDNSRecord",
+ "ParameterValue": "disabled"
+},
+{
+ "ParameterKey": "Subdomain",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "HostedZoneName",
+ "ParameterValue": ""
+}
+]
+```
+
+## AWS production environment diagram
+
+![wazuh_template](images/wazuh_template-designer.png)
\ No newline at end of file
diff --git a/production/deploy.sh b/production/deploy.sh
new file mode 100755
index 0000000..2942e8d
--- /dev/null
+++ b/production/deploy.sh
@@ -0,0 +1,37 @@
+# Deploy a CloudFormation Wazuh stack
+
+#!/bin/bash
+
+# Path of the parameters JSON file
+PARAMS_FILE='./parameters.json'
+
+# Path of the template file
+TEMPLATE_FILE='./wazuh_template.yml'
+
+# Stack name
+STACK_NAME=''
+
+# Bucket name
+BUCKET_NAME=''
+
+# If any file doesn't exist, then break the execution
+if ! [ -f "$PARAMS_FILE" ] || ! [ -f "$TEMPLATE_FILE" ]; then
+ echo "Missing template path or parameters file."
+ exit
+fi
+
+# Checking arguments
+if [ "$STACK_NAME" == "" ] || [ "$BUCKET_NAME" == "" ]; then
+ echo "Missing template path or parameters file."
+ exit
+fi
+
+# Uploading template to S3
+aws s3 cp $TEMPLATE_FILE s3://$BUCKET_NAME
+# Getting the template URL
+URL="https://$BUCKET_NAME.amazonaws.com/wazuh_template.yml"
+echo "Template URL: $URL"
+
+aws cloudformation create-stack --stack-name ${STACK_NAME} --template-url $URL --parameters file://$PARAMS_FILE --capabilities CAPABILITY_IAM --tags Key=service_name,Value=demo_info
+
+echo "Done"
diff --git a/production/elastic/wazuh_cf_bootstrap_elastic.sh b/production/elastic/wazuh_cf_bootstrap_elastic.sh
new file mode 100644
index 0000000..02b2bab
--- /dev/null
+++ b/production/elastic/wazuh_cf_bootstrap_elastic.sh
@@ -0,0 +1,256 @@
+#!/bin/bash
+# Install Elastic data node using Cloudformation template
+
+touch /tmp/deploy.log
+
+echo "Elasticsearch: Starting process." > /tmp/deploy.log
+ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2)
+ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2)
+elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1)
+wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2)
+eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2)
+elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1)
+wazuh_major=`echo $wazuh_version | cut -d'.' -f1`
+wazuh_minor=`echo $wazuh_version | cut -d'.' -f2`
+wazuh_patch=`echo $wazuh_version | cut -d'.' -f3`
+node_name=$(cat /tmp/wazuh_cf_settings | grep '^NodeName:' | cut -d' ' -f2)
+master_ip=$(cat /tmp/wazuh_cf_settings | grep '^MasterIp:' | cut -d' ' -f2)
+worker_ip=$(cat /tmp/wazuh_cf_settings | grep '^WorkerIp:' | cut -d' ' -f2)
+kibana_ip=$(cat /tmp/wazuh_cf_settings | grep '^KibanaIp:' | cut -d' ' -f2)
+
+TAG="v3.12.2"
+echo "Added env vars." >> /tmp/deploy.log
+echo "eth0_ip: $eth0_ip" >> /tmp/deploy.log
+
+check_root(){
+ # Check if running as root
+ if [[ $EUID -ne 0 ]]; then
+ echo "NOT running as root. Exiting" >> /tmp/deploy.log
+ echo "This script must be run as root"
+ exit 1
+ fi
+ echo "Running as root." >> /tmp/deploy.log
+}
+
+create_ssh_user(){
+ # Creating SSH user
+ if ! id -u ${ssh_username} > /dev/null 2>&1; then adduser ${ssh_username}; fi
+ echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers
+ usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username}
+ echo "Created SSH user." >> /tmp/deploy.log
+
+ sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config
+ systemctl restart sshd
+ echo "Started SSH service." >> /tmp/deploy.log
+}
+
+import_elk_repo(){
+# Configuring Elastic repository
+rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
+
+cat > /etc/yum.repos.d/elastic.repo << EOF
+[elasticsearch-${elastic_major_version}.x]
+name=Elasticsearch repository for ${elastic_major_version}.x packages
+baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum
+gpgcheck=1
+gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
+enabled=1
+autorefresh=1
+type=rpm-md
+EOF
+echo "Added Elasticsearch repo." >> /tmp/deploy.log
+}
+
+install_elasticsearch(){
+ echo "Installing Elasticsearch." >> /tmp/deploy.log
+ # Installing Elasticsearch
+ yum -y install elasticsearch-${elastic_version}
+ chkconfig --add elasticsearch
+ echo "Installed Elasticsearch." >> /tmp/deploy.log
+}
+
+configuring_elasticsearch(){
+echo "Configuring elasticsearch." >> /tmp/deploy.log
+
+# Creating data and logs directories
+mkdir -p /mnt/ephemeral/elasticsearch/lib
+mkdir -p /mnt/ephemeral/elasticsearch/log
+chown -R elasticsearch:elasticsearch /mnt/ephemeral/elasticsearch
+echo "Created volumes in ephemeral." >> /tmp/deploy.log
+
+cat > /etc/elasticsearch/elasticsearch.yml << EOF
+cluster.name: "wazuh_elastic"
+node.name: "node-$node_name"
+node.master: true
+path.data: /mnt/ephemeral/elasticsearch/lib
+path.logs: /mnt/ephemeral/elasticsearch/log
+cluster.initial_master_nodes:
+ - "10.0.2.123"
+ - "10.0.2.124"
+ - "10.0.2.125"
+EOF
+
+echo "network.host: $eth0_ip" >> /etc/elasticsearch/elasticsearch.yml
+
+# Calculating RAM for Elasticsearch
+ram_gb=$[$(free -g | awk '/^Mem:/{print $2}')+1]
+ram=$(( ${ram_gb} / 2 ))
+if [ $ram -eq "0" ]; then ram=1; fi
+echo "Setting RAM." >> /tmp/deploy.log
+
+# Configuring jvm.options
+cat > /etc/elasticsearch/jvm.options << EOF
+-Xms${ram}g
+-Xmx${ram}g
+-Dlog4j2.disable.jmx=true
+EOF
+echo "Setting JVM options." >> /tmp/deploy.log
+
+mkdir -p /etc/systemd/system/elasticsearch.service.d/
+echo '[Service]' > /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf
+echo 'LimitMEMLOCK=infinity' >> /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf
+
+# Allowing unlimited memory allocation
+echo 'elasticsearch soft memlock unlimited' >> /etc/security/limits.conf
+echo 'elasticsearch hard memlock unlimited' >> /etc/security/limits.conf
+echo "Setting memory lock options." >> /tmp/deploy.log
+echo "Setting permissions." >> /tmp/deploy.log
+enable_elasticsearch
+start_elasticsearch
+}
+
+load_template(){
+ echo "Loading template..." >> /tmp/deploy.log
+ until curl -XGET "https://$eth0_ip:9200" -k -u elastic:${ssh_password}; do
+ sleep 5
+ echo "Elasticsearch not ready yet..." >> /tmp/deploy.log
+ done
+
+ url_alerts_template="https://raw.githubusercontent.com/wazuh/wazuh/${TAG}/extensions/elasticsearch/7.x/wazuh-template.json"
+ alerts_template="/tmp/wazuh-template.json"
+ curl -Lo ${alerts_template} ${url_alerts_template}
+ curl -XPUT "https://${eth0_ip}:9200/_template/wazuh" -k -u elastic:${ssh_password} -H 'Content-Type: application/json' -d@${alerts_template}
+ curl -XDELETE "https://${eth0_ip}:9200/wazuh-alerts-*" -k -u elastic:${ssh_password}
+ # Correct owner for Elasticsearch directories
+ echo "Added template." >> /tmp/deploy.log
+}
+
+add_wazuh_user(){
+
+until curl -XGET "https://$eth0_ip:9200" -k -u elastic:${ssh_password}; do
+ sleep 5
+ echo "Elasticsearch not ready yet..." >> /tmp/deploy.log
+done
+user_config='/tmp/userconfig'
+cat > ${user_config} << EOF
+{
+ "password": "${ssh_password}",
+ "roles" : [ "superuser" ]
+}
+EOF
+ # Create wazuh user
+ curl -XPOST "https://$eth0_ip:9200/_security/user/wazuh" -k -u elastic:${ssh_password} -d@${user_config} -H 'Content-Type: application/json'
+
+}
+
+enable_elasticsearch(){
+ echo "Enabling elasticsearch..." >> /tmp/deploy.log
+ systemctl enable elasticsearch
+ if [ $? -eq0 ]; then
+ echo "Elasticsearch enabled." >> /tmp/deploy.log
+ else
+ echo "Could not enable Elasticsearch" >> /tmp/deploy.log
+ fi
+}
+
+start_elasticsearch(){
+ echo "Starting Elasticsearch and setting permissions" >> /tmp/deploy.log
+ chown elasticsearch:elasticsearch -R /etc/elasticsearch
+ chown elasticsearch:elasticsearch -R /usr/share/elasticsearch
+ chown elasticsearch:elasticsearch -R /var/lib/elasticsearch
+ systemctl daemon-reload
+ # Starting Elasticsearch
+ echo "daemon-reload." >> /tmp/deploy.log
+ systemctl restart elasticsearch
+ echo "Started elasticsearch service." >> /tmp/deploy.log
+ systemctl status elasticsearch >> /tmp/deploy.log
+}
+
+create_bootstrap_user(){
+ echo "Creating elk user with password $ssh_password" >> /tmp/deploy.log
+ echo $ssh_password | /usr/share/elasticsearch/bin/elasticsearch-keystore add -x 'bootstrap.password'
+ systemctl restart elasticsearch
+ sleep 60
+ echo 'Done' >> /tmp/deploy.log
+}
+
+set_security(){
+echo "Setting security in Elasticsearch bootstrap node" >> /tmp/deploy.log
+cat > /usr/share/elasticsearch/instances.yml << EOF
+instances:
+ - name: "wazuh-manager"
+ ip:
+ - "$master_ip"
+ - name: "wazuh-worker"
+ ip:
+ - "$worker_ip"
+ - name: "kibana"
+ ip:
+ - "$kibana_ip"
+ - name: "elastic-node2"
+ ip:
+ - "10.0.2.125"
+ - name: "elastic-node1"
+ ip:
+ - "10.0.2.123"
+ - name: "elasticsearch"
+ ip:
+ - "$eth0_ip"
+EOF
+/usr/share/elasticsearch/bin/elasticsearch-certutil cert ca --pem --in /usr/share/elasticsearch/instances.yml --out /usr/share/elasticsearch/certs.zip
+echo "Generated certs" >> /tmp/deploy.log
+cp /usr/share/elasticsearch/certs.zip /home/wazuh/
+chown wazuh:wazuh /home/wazuh/certs.zip
+cp /usr/share/elasticsearch/certs.zip .
+unzip certs.zip
+mkdir /etc/elasticsearch/certs/ca -p
+cp ca/ca.crt /etc/elasticsearch/certs/ca
+cp elasticsearch/elasticsearch.crt /etc/elasticsearch/certs
+chmod -R 770 /etc/elasticsearch/certs
+cp elasticsearch/elasticsearch.key /etc/elasticsearch/certs
+echo "xpack.security.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.transport.ssl.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.transport.ssl.verification_mode: certificate" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.transport.ssl.key: /etc/elasticsearch/certs/elasticsearch.key" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.transport.ssl.certificate: /etc/elasticsearch/certs/elasticsearch.crt" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.transport.ssl.certificate_authorities: [ "/etc/elasticsearch/certs/ca/ca.crt" ]" >> /etc/elasticsearch/elasticsearch.yml
+echo "# HTTP layer" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.http.ssl.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.http.ssl.verification_mode: certificate" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.http.ssl.key: /etc/elasticsearch/certs/elasticsearch.key" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.http.ssl.certificate: /etc/elasticsearch/certs/elasticsearch.crt" >> /etc/elasticsearch/elasticsearch.yml
+echo "xpack.security.http.ssl.certificate_authorities: [ "/etc/elasticsearch/certs/ca/ca.crt" ]" >> /etc/elasticsearch/elasticsearch.yml
+chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs
+echo "Starting elasticsearch"
+}
+
+disable_elk_repos(){
+ # Disable repositories
+ sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo
+}
+
+main(){
+ check_root
+ create_ssh_user
+ import_elk_repo
+ install_elasticsearch
+ configuring_elasticsearch
+ create_bootstrap_user
+ set_security
+ start_elasticsearch
+ #load_template
+ add_wazuh_user
+ disable_elk_repos
+}
+
+main
\ No newline at end of file
diff --git a/production/elastic/wazuh_cf_elastic.sh b/production/elastic/wazuh_cf_elastic.sh
new file mode 100644
index 0000000..5b03545
--- /dev/null
+++ b/production/elastic/wazuh_cf_elastic.sh
@@ -0,0 +1,206 @@
+#!/bin/bash
+# Install Elastic data node using Cloudformation template
+
+touch /tmp/deploy.log
+
+echo "Elasticsearch: Starting process." > /tmp/deploy.log
+ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2)
+ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2)
+elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1)
+wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2)
+eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2)
+elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1)
+wazuh_major=`echo $wazuh_version | cut -d'.' -f1`
+wazuh_minor=`echo $wazuh_version | cut -d'.' -f2`
+wazuh_patch=`echo $wazuh_version | cut -d'.' -f3`
+node_name=$(cat /tmp/wazuh_cf_settings | grep '^NodeName:' | cut -d' ' -f2)
+
+echo "Added env vars." >> /tmp/deploy.log
+echo "eth0_ip: $eth0_ip" >> /tmp/deploy.log
+
+check_root(){
+ # Check if running as root
+ if [[ $EUID -ne 0 ]]; then
+ echo "NOT running as root. Exiting" >> /tmp/deploy.log
+ echo "This script must be run as root"
+ exit 1
+ fi
+ echo "Running as root." >> /tmp/deploy.log
+}
+
+create_ssh_user(){
+ # Creating SSH user
+ if ! id -u ${ssh_username} > /dev/null 2>&1; then adduser ${ssh_username}; fi
+ echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers
+ usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username}
+ echo "Created SSH user." >> /tmp/deploy.log
+
+ sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config
+ systemctl restart sshd
+ echo "Started SSH service." >> /tmp/deploy.log
+}
+
+import_elk_repo(){
+# Configuring Elastic repository
+rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
+
+cat > /etc/yum.repos.d/elastic.repo << EOF
+[elasticsearch-${elastic_major_version}.x]
+name=Elasticsearch repository for ${elastic_major_version}.x packages
+baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum
+gpgcheck=1
+gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
+enabled=1
+autorefresh=1
+type=rpm-md
+EOF
+echo "Added Elasticsearch repo." >> /tmp/deploy.log
+}
+
+install_elasticsearch(){
+ echo "Installing Elasticsearch." >> /tmp/deploy.log
+ # Installing Elasticsearch
+ yum -y install elasticsearch-${elastic_version}
+ chkconfig --add elasticsearch
+ echo "Installed Elasticsearch." >> /tmp/deploy.log
+}
+
+configuring_elasticsearch(){
+# Creating data and logs directories
+mkdir -p /mnt/ephemeral/elasticsearch/lib
+mkdir -p /mnt/ephemeral/elasticsearch/log
+chown -R elasticsearch:elasticsearch /mnt/ephemeral/elasticsearch
+echo "Created volumes in ephemeral." >> /tmp/deploy.log
+
+cat > /etc/elasticsearch/elasticsearch.yml << EOF
+cluster.name: "wazuh_elastic"
+node.name: "node-$node_name"
+node.master: true
+path.data: /mnt/ephemeral/elasticsearch/lib
+path.logs: /mnt/ephemeral/elasticsearch/log
+discovery.seed_hosts:
+ - "10.0.2.123"
+ - "10.0.2.124"
+ - "10.0.2.125"
+
+EOF
+
+echo "network.host: $eth0_ip" >> /etc/elasticsearch/elasticsearch.yml
+
+# Calculating RAM for Elasticsearch
+ram_gb=$[$(free -g | awk '/^Mem:/{print $2}')+1]
+ram=$(( ${ram_gb} / 2 ))
+if [ $ram -eq "0" ]; then ram=1; fi
+echo "Setting RAM." >> /tmp/deploy.log
+
+# Configuring jvm.options
+cat > /etc/elasticsearch/jvm.options << EOF
+-Xms${ram}g
+-Xmx${ram}g
+-Dlog4j2.disable.jmx=true
+EOF
+echo "Setting JVM options." >> /tmp/deploy.log
+
+mkdir -p /etc/systemd/system/elasticsearch.service.d/
+echo '[Service]' > /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf
+echo 'LimitMEMLOCK=infinity' >> /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf
+
+# Allowing unlimited memory allocation
+echo 'elasticsearch soft memlock unlimited' >> /etc/security/limits.conf
+echo 'elasticsearch hard memlock unlimited' >> /etc/security/limits.conf
+echo "Setting memory lock options." >> /tmp/deploy.log
+echo "Setting permissions." >> /tmp/deploy.log
+# restarting elasticsearch after changes
+start_elasticsearch
+}
+
+set_security(){
+ echo "SET SECURITY." >> /tmp/deploy.log
+ # installing dependencies
+ mkdir /etc/elasticsearch/certs/ca -p
+ echo "Created certs directory." >> /tmp/deploy.log
+ amazon-linux-extras install epel -y
+ yum install -y sshpass
+ sleep 30
+ echo "Installed sshpass." >> /tmp/deploy.log
+ echo $ssh_password >> pass
+ while [ ! -f /home/wazuh/certs.zip ];do
+ sleep 2
+ echo "No certs yet, trying again in 2 secs..." >> /tmp/deploy.log
+ sshpass -f pass scp -o "StrictHostKeyChecking=no" wazuh@10.0.2.124:/home/wazuh/certs.zip /home/wazuh/ 2> /tmp/deploy.logerr.log
+ done
+ echo "Got certs.zip." >> /tmp/deploy.log
+ rm pass -f
+ cp /home/wazuh/certs.zip .
+ unzip certs.zip
+ echo "Unzipped certs.zip." >> /tmp/deploy.log
+ cp ca/ca.crt /etc/elasticsearch/certs/ca
+ cp elastic-node${node_name}/elastic-node${node_name}.crt /etc/elasticsearch/certs
+ cp elastic-node${node_name}/elastic-node${node_name}.key /etc/elasticsearch/certs
+ echo "xpack.security.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.verification_mode: certificate" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.key: /etc/elasticsearch/certs/elastic-node${node_name}.key" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.certificate: /etc/elasticsearch/certs/elastic-node${node_name}.crt" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.certificate_authorities: [ "/etc/elasticsearch/certs/ca/ca.crt" ]" >> /etc/elasticsearch/elasticsearch.yml
+ echo "# HTTP layer" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.verification_mode: certificate" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.key: /etc/elasticsearch/certs/elastic-node${node_name}.key" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.certificate: /etc/elasticsearch/certs/elastic-node${node_name}.crt" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.certificate_authorities: [ "/etc/elasticsearch/certs/ca/ca.crt" ]" >> /etc/elasticsearch/elasticsearch.yml
+ echo "Configured security." >> /tmp/deploy.log
+ chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs
+ echo "Changed permissions certs directory." >> /tmp/deploy.log
+}
+
+start_elasticsearch(){
+ echo "start_elasticsearch." >> /tmp/deploy.log
+ # Correct owner for Elasticsearch directories
+ chown elasticsearch:elasticsearch -R /etc/elasticsearch
+ chown elasticsearch:elasticsearch -R /usr/share/elasticsearch
+ chown elasticsearch:elasticsearch -R /var/lib/elasticsearch
+ systemctl daemon-reload
+ # Starting Elasticsearch
+ echo "daemon-reload." >> /tmp/deploy.log
+ systemctl restart elasticsearch
+ echo "done with starting elasticsearch service." >> /tmp/deploy.log
+}
+
+enable_elasticsearch(){
+ echo "Enabling elasticsearch..." >> /tmp/deploy.log
+ systemctl enable elasticsearch
+ if [ $? -eq0 ]; then
+ echo "Elasticsearch enabled." >> /tmp/deploy.log
+ else
+ echo "Could not enable Elasticsearch" >> /tmp/deploy.log
+ fi
+}
+
+disable_elk_repos(){
+ # Disable repositories
+ sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo
+}
+
+set_elk_password(){
+ echo "Creating elk user with password $ssh_password" >> /tmp/deploy.log
+ echo $ssh_password | /usr/share/elasticsearch/bin/elasticsearch-keystore add -x 'bootstrap.password'
+ systemctl restart elasticsearch
+ sleep 60
+ echo 'Done' >> /tmp/deploy.log
+}
+
+main(){
+ check_root
+ create_ssh_user
+ import_elk_repo
+ install_elasticsearch
+ configuring_elasticsearch
+ set_security
+ enable_elasticsearch
+ start_elasticsearch
+ disable_elk_repos
+ set_elk_password
+}
+
+main
\ No newline at end of file
diff --git a/production/elastic/wazuh_cf_kibana.sh b/production/elastic/wazuh_cf_kibana.sh
new file mode 100644
index 0000000..a21301d
--- /dev/null
+++ b/production/elastic/wazuh_cf_kibana.sh
@@ -0,0 +1,412 @@
+#!/bin/bash
+# Install Kibana instance using Cloudformation template
+# Support for Amazon Linux
+
+echo "Starting process." >> /tmp/deploy.log
+
+ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2)
+ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2)
+elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1)
+wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2)
+kibana_port=$(cat /tmp/wazuh_cf_settings | grep '^KibanaPort:' | cut -d' ' -f2)
+eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2)
+wazuh_master_ip=$(cat /tmp/wazuh_cf_settings | grep '^WazuhMasterIP:' | cut -d' ' -f2)
+wazuh_api_user=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminUsername:' | cut -d' ' -f2)
+wazuh_api_password=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminPassword:' | cut -d' ' -f2)
+wazuh_api_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiPort:' | cut -d' ' -f2)
+InstallType=$(cat /tmp/wazuh_cf_settings | grep '^InstallType:' | cut -d' ' -f2)
+wazuh_major=`echo $wazuh_version | cut -d'.' -f1`
+wazuh_minor=`echo $wazuh_version | cut -d'.' -f2`
+wazuh_patch=`echo $wazuh_version | cut -d'.' -f3`
+elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1)
+elastic_minor_version=$(echo ${elastic_version} | cut -d'.' -f2)
+elastic_patch_version=$(echo ${elastic_version} | cut -d'.' -f3)
+
+extract_certs(){
+ amazon-linux-extras install epel -y
+ yum install -y sshpass
+ echo $ssh_password >> pass
+
+ while [ ! -f /home/wazuh/certs.zip ]; do
+ sshpass -f pass scp -o "StrictHostKeyChecking=no" wazuh@10.0.2.124:/home/wazuh/certs.zip /home/wazuh/ 2> /dev/null
+ sleep 10
+ done
+ echo "Extract certs " >> /tmp/deploy.log
+ rm pass -f
+ cp /home/wazuh/certs.zip .
+ unzip certs.zip
+}
+
+
+check_root(){
+ echo "Checking root." >> /tmp/deploy.log
+ # Check if running as root
+ if [[ $EUID -ne 0 ]]; then
+ echo "NOT running as root. Exiting" >> /tmp/deploy.log
+ echo "This script must be run as root"
+ exit 1
+ fi
+ echo "Running as root." >> /tmp/deploy.log
+}
+
+create_ssh_user(){
+ # Creating SSH user
+ if ! id -u ${ssh_username} > /dev/null 2>&1; then adduser ${ssh_username}; fi
+ echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers
+ usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username}
+ echo "Created SSH user." >> /tmp/deploy.log
+ sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config
+ systemctl restart sshd
+ echo "Started SSH service." >> /tmp/deploy.log
+}
+
+await_kibana_ssl(){
+ echo "Waiting for Kibana service..." >> /tmp/deploy.log
+ until curl -XGET "https://$eth0_ip:5601" -k -u elastic:${ssh_password}; do
+ sleep 5
+ echo "Kibana not ready yet..." >> /tmp/deploy.log
+ done
+ echo "Kibana is up" >> /tmp/deploy.log
+}
+
+import_elk_repo(){
+# Configuring Elastic repository
+rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
+
+cat > /etc/yum.repos.d/elastic.repo << EOF
+[elasticsearch-${elastic_major_version}.x]
+name=Elasticsearch repository for ${elastic_major_version}.x packages
+baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum
+gpgcheck=1
+gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
+enabled=1
+autorefresh=1
+type=rpm-md
+EOF
+echo "Added Elasticsearch repo." >> /tmp/deploy.log
+}
+
+# Installing ELK coordinating only mode
+install_elasticsearch(){
+ echo "Installing Elasticsearch." >> /tmp/deploy.log
+ # Installing Elasticsearch
+ yum -y install elasticsearch-${elastic_version}
+ chkconfig --add elasticsearch
+ echo "Installed Elasticsearch." >> /tmp/deploy.log
+}
+
+configuring_elasticsearch(){
+mkdir -p /mnt/ephemeral/elasticsearch/lib
+mkdir -p /mnt/ephemeral/elasticsearch/log
+chown -R elasticsearch:elasticsearch /mnt/ephemeral/elasticsearch
+
+echo "Created volumes in ephemeral." >> /tmp/deploy.log
+cat > /etc/elasticsearch/elasticsearch.yml << EOF
+cluster.name: "wazuh_elastic"
+node.name: "coordinating_node"
+path.data: /mnt/ephemeral/elasticsearch/lib
+path.logs: /mnt/ephemeral/elasticsearch/log
+node.master: false
+node.data: false
+node.ingest: false
+discovery.seed_hosts:
+ - "10.0.2.123"
+ - "10.0.2.124"
+ - "10.0.2.125"
+EOF
+
+echo "network.host: $eth0_ip" >> /etc/elasticsearch/elasticsearch.yml
+
+# Calculating RAM for Elasticsearch
+ram_gb=$[$(free -g | awk '/^Mem:/{print $2}')+1]
+ram=$(( ${ram_gb} / 2 ))
+if [ $ram -eq "0" ]; then ram=1; fi
+echo "Setting RAM." >> /tmp/deploy.log
+
+# Configuring jvm.options
+cat > /etc/elasticsearch/jvm.options << EOF
+-Xms${ram}g
+-Xmx${ram}g
+-Dlog4j2.disable.jmx=true
+EOF
+echo "Setting JVM options." >> /tmp/deploy.log
+
+mkdir -p /etc/systemd/system/elasticsearch.service.d/
+echo '[Service]' > /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf
+echo 'LimitMEMLOCK=infinity' >> /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf
+
+# Allowing unlimited memory allocation
+echo 'elasticsearch soft memlock unlimited' >> /etc/security/limits.conf
+echo 'elasticsearch hard memlock unlimited' >> /etc/security/limits.conf
+echo "Setting memory lock options." >> /tmp/deploy.log
+echo "Setting permissions." >> /tmp/deploy.log
+# restarting elasticsearch after changes
+}
+
+set_security(){
+
+ mkdir -p /etc/elasticsearch/certs
+ cp /kibana/* /etc/elasticsearch/certs/ -R
+ cp /ca /etc/elasticsearch/certs/ -R
+ echo "xpack.security.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.verification_mode: certificate" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.key: "/etc/elasticsearch/certs/kibana.key"" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.certificate: /etc/elasticsearch/certs/kibana.crt" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.transport.ssl.certificate_authorities: [ "/etc/elasticsearch/certs/ca/ca.crt" ]" >> /etc/elasticsearch/elasticsearch.yml
+ echo "# HTTP layer" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.enabled: true" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.verification_mode: certificate" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.key: "/etc/elasticsearch/certs/kibana.key"" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.certificate: /etc/elasticsearch/certs/kibana.crt" >> /etc/elasticsearch/elasticsearch.yml
+ echo "xpack.security.http.ssl.certificate_authorities: [ "/etc/elasticsearch/certs/ca/ca.crt" ]" >> /etc/elasticsearch/elasticsearch.yml
+ echo "Configured security." >> /tmp/deploy.log
+ chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs
+ echo "Changed permissions certs directory." >> /tmp/deploy.log
+}
+
+create_bootstrap_user(){
+ echo "Creating elk user with password $ssh_password" >> /tmp/deploy.log
+ echo $ssh_password | /usr/share/elasticsearch/bin/elasticsearch-keystore add -x 'bootstrap.password'
+ systemctl restart elasticsearch
+ echo 'Done' >> /tmp/deploy.log
+}
+
+start_elasticsearch(){
+ echo "start_elasticsearch." >> /tmp/deploy.log
+ # Correct owner for Elasticsearch directories
+ chown elasticsearch:elasticsearch -R /etc/elasticsearch
+ chown elasticsearch:elasticsearch -R /usr/share/elasticsearch
+ chown elasticsearch:elasticsearch -R /var/lib/elasticsearch
+ systemctl daemon-reload
+ # Starting Elasticsearch
+ echo "daemon-reload." >> /tmp/deploy.log
+ systemctl restart elasticsearch
+ echo "done with starting elasticsearch service." >> /tmp/deploy.log
+}
+
+
+install_kibana(){
+# Installing Kibana
+yum -y install kibana-${elastic_version}
+chkconfig --add kibana
+echo "Kibana installed." >> /tmp/deploy.log
+}
+
+kibana_certs(){
+ mkdir /etc/kibana/certs/ca -p
+ cp ca/ca.crt /etc/kibana/certs/ca
+ cp kibana/kibana.crt /etc/kibana/certs
+ cp kibana/kibana.key /etc/kibana/certs
+ chown -R kibana: /etc/kibana/certs
+ chmod -R 770 /etc/kibana/certs
+ echo "# Elasticsearch from/to Kibana" >> /etc/kibana/kibana.yml
+ echo "elasticsearch.ssl.certificateAuthorities: ["/etc/kibana/certs/ca/ca.crt"]" >> /etc/kibana/kibana.yml
+ echo "elasticsearch.ssl.certificate: "/etc/kibana/certs/kibana.crt"" >> /etc/kibana/kibana.yml
+ echo "elasticsearch.ssl.key: "/etc/kibana/certs/kibana.key"" >> /etc/kibana/kibana.yml
+ echo "# Browser from/to Kibana" >> /etc/kibana/kibana.yml
+ echo "server.ssl.enabled: true" >> /etc/kibana/kibana.yml
+ echo "server.ssl.certificate: "/etc/kibana/certs/kibana.crt"" >> /etc/kibana/kibana.yml
+ echo "server.ssl.key: "/etc/kibana/certs/kibana.key"" >> /etc/kibana/kibana.yml
+}
+
+configure_kibana(){
+# Configuring kibana.yml
+cat > /etc/kibana/kibana.yml << EOF
+elasticsearch.hosts: ["https://$eth0_ip:9200"]
+server.port: 5601
+server.host: "$eth0_ip"
+xpack.security.enabled: true
+elasticsearch.username: "elastic"
+elasticsearch.password: "$ssh_password"
+EOF
+echo "Kibana.yml configured." >> /tmp/deploy.log
+
+# Allow Kibana to listen on privileged ports
+setcap 'CAP_NET_BIND_SERVICE=+eip' /usr/share/kibana/node/bin/node
+echo "Setcap executed" >> /tmp/deploy.log
+
+}
+
+
+get_plugin_url(){
+ if [[ ${InstallType} == 'packages' ]]
+ then
+ plugin_url="https://packages.wazuh.com/wazuhapp/wazuhapp-${wazuh_major}.${wazuh_minor}.${wazuh_patch}_${elastic_major_version}.${elastic_minor_version}.${elastic_patch_version}.zip"
+ elif [[ ${InstallType} == 'sources' ]]
+ then
+ BRANCH="3.12-7.6"
+ if [[ $BRANCH != "" ]]; then
+ yum install -y git
+ curl --silent --location https://rpm.nodesource.com/setup_10.x | bash -
+ # Installing NodeJS
+ yum -y install nodejs
+ npm install -g yarn@1.10.1
+ git clone https://github.com/wazuh/wazuh-kibana-app -b $BRANCH --single-branch --depth=1 app
+ cd app
+ yarn
+ yarn build 2> /dev/null
+ # This command returns several errors, we workaround this by executing it twice
+ yarn build 2> /dev/null
+ # The built backage is under /build
+ cd build
+ BUILD_SRC=$(pwd)
+ APP_FILE=$(ls *.zip)
+ else
+ echo 'Error: Unsupported Wazuh Plugin installation method' >> /tmp/deploy.log
+ fi
+ else
+ echo 'no repo' >> /tmp/stage
+ fi
+}
+
+install_plugin(){
+ echo "Installing app" >> /tmp/deploy.log
+ if [[ ${InstallType} != 'sources' ]] || [[ ${BRANCH} == "" ]]
+ then
+ cd /usr/share/kibana
+ sudo -u kibana /usr/share/kibana/bin/kibana-plugin install ${plugin_url}
+ else
+ cd /usr/share/kibana
+ sudo -u kibana /usr/share/kibana/bin/kibana-plugin install file://$BUILD_SRC/$APP_FILE
+ fi
+}
+
+optimize_kibana(){
+ systemctl stop kibana
+ echo "Optimizing app" >> /tmp/deploy.log
+ cd /usr/share/kibana
+ sudo -u kibana /usr/share/kibana/node/bin/node --no-warnings --max-old-space-size=2048 --max-http-header-size=65536 /usr/share/kibana/src/cli --optimize
+ cd /tmp
+ echo "App installed!" >> /tmp/deploy.log
+ systemctl start kibana
+}
+
+add_api(){
+echo "Adding Wazuh API" >> /tmp/deploy.log
+sed -ie '/- default:/,+4d' /usr/share/kibana/optimize/wazuh/config/wazuh.yml
+cat > /usr/share/kibana/optimize/wazuh/config/wazuh.yml << EOF
+hosts:
+ - default:
+ url: https://${wazuh_master_ip}
+ port: ${wazuh_api_port}
+ user: ${wazuh_api_user}
+ password: ${wazuh_api_password}
+EOF
+echo "Configured API" >> /tmp/deploy.log
+}
+
+enable_kibana(){
+ echo "Enabling Kibana..." >> /tmp/deploy.log
+ systemctl enable kibana
+ if [ $? -eq0 ]; then
+ echo "Kibana enabled." >> /tmp/deploy.log
+ else
+ echo "Could not enable Kibana" >> /tmp/deploy.log
+ fi
+}
+
+start_kibana(){
+ # Starting Kibana
+ systemctl restart kibana
+ await_kibana_ssl
+
+}
+
+kibana_optional_configs(){
+sleep 500
+echo "Configuring Kibana options" >> /tmp/deploy.log
+
+# Configuring default index pattern for Kibana
+default_index="/tmp/default_index.json"
+
+cat > ${default_index} << EOF
+{
+ "changes": {
+ "defaultIndex": "wazuh-alerts-3.x-*"
+ }
+}
+EOF
+
+await_kibana_ssl
+# Configuring Kibana TimePicker
+curl -XPOST "https://$eth0_ip:5601/api/kibana/settings" -k -u elastic:${ssh_password} -H "Content-Type: application/json" -H "kbn-xsrf: true" -d \
+'{"changes":{"timepicker:timeDefaults":"{\n \"from\": \"now-24h\",\n \"to\": \"now\",\n \"mode\": \"quick\"}"}}' >> /tmp/deploy.log
+echo "Set up default timepicker." >> /tmp/deploy.log
+
+curl -XPOST "https://$eth0_ip:5601/api/kibana/settings" -k -u elastic:${ssh_password} -H "Content-Type: application/json" -H "kbn-xsrf: true" -d@${default_index} >> /tmp/deploy.log
+rm -f ${default_index}
+echo "Set up default Index pattern." >> /tmp/deploy.log
+
+# Do not ask user to help providing usage statistics to Elastic
+curl -XPOST "https://$eth0_ip:5601/api/telemetry/v2/optIn" -k -u elastic:${ssh_password} -H "Content-Type: application/json" -H "kbn-xsrf: true" -d '{"enabled":false}' >> /tmp/deploy.log
+echo "Do not ask user to help providing usage statistics to Elastic" >> /tmp/deploy.log
+
+# Disable Elastic repository
+sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo
+echo "Configured Kibana" >> /tmp/deploy.log
+
+# Remove Montserrat font
+sed -i 's/@import\surl.*Montserrat.*/# Removed montserrat font/g' /usr/share/kibana/optimize/bundles/login.style.css
+
+}
+
+add_nginx(){
+
+echo "Installing NGINX..." >> /tmp/deploy.log
+# Install Nginx ang generate certificates
+sudo amazon-linux-extras install nginx1.12
+mkdir -p /etc/ssl/certs /etc/ssl/private
+openssl req -x509 -batch -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/kibana.key -out /etc/ssl/certs/kibana.pem
+echo "Installed NGINX." >> /tmp/deploy.log
+
+# Installing htpasswd (needed for Amazon Linux)
+yum install httpd-tools-2.4.33-2.amzn2.0.2.x86_64 -y
+
+# Configure Nginx
+cat > /etc/nginx/conf.d/kibana.conf << EOF
+server {
+ listen ${kibana_port} default_server;
+ listen [::]:${kibana_port};
+ access_log /var/log/nginx/nginx.access.log;
+ error_log /var/log/nginx/nginx.error.log;
+ location / {
+ proxy_pass https://$eth0_ip:5601/;
+ }
+}
+EOF
+
+# Starting Nginx
+systemctl restart nginx
+echo "Restarted NGINX..." >> /tmp/deploy.log
+
+}
+
+
+main(){
+ check_root
+ create_ssh_user
+ import_elk_repo
+ install_elasticsearch
+ extract_certs
+ configuring_elasticsearch
+ create_bootstrap_user
+ set_security
+ start_elasticsearch
+ install_kibana
+ configure_kibana
+ kibana_certs
+ get_plugin_url
+ install_plugin
+ enable_kibana
+ optimize_kibana
+ start_kibana
+ sleep 60
+ add_api
+ kibana_optional_configs
+ start_kibana
+ add_nginx
+ echo "Deploy finished" >> /tmp/deploy.log
+}
+
+main
\ No newline at end of file
diff --git a/production/images/wazuh_template-designer.png b/production/images/wazuh_template-designer.png
new file mode 100644
index 0000000..716da0f
Binary files /dev/null and b/production/images/wazuh_template-designer.png differ
diff --git a/production/parameters.json b/production/parameters.json
new file mode 100644
index 0000000..6b4fb15
--- /dev/null
+++ b/production/parameters.json
@@ -0,0 +1,78 @@
+
+[{
+ "ParameterKey": "ElasticWazuhVersion",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhInstanceType",
+ "ParameterValue": "t2.medium"
+},
+{
+ "ParameterKey": "InstallType",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "ElasticInstanceType",
+ "ParameterValue": "t2.large"
+},
+{
+ "ParameterKey": "KibanaInstanceType",
+ "ParameterValue": "t2.large"
+},
+{
+ "ParameterKey": "SshUsername",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "SshPassword",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhServerPort",
+ "ParameterValue": "1514"
+},
+{
+ "ParameterKey": "WazuhRegistrationPort",
+ "ParameterValue": "1515"
+},
+{
+ "ParameterKey": "WazuhRegistrationPassword",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhApiPort",
+ "ParameterValue": "55000"
+},
+{
+ "ParameterKey": "WazuhApiAdminUsername",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "WazuhApiAdminPassword",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "KeyPairName",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "AvailabilityZone",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "SSLCertificateARN",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "EnableDNSRecord",
+ "ParameterValue": "disabled"
+},
+{
+ "ParameterKey": "Subdomain",
+ "ParameterValue": ""
+},
+{
+ "ParameterKey": "HostedZoneName",
+ "ParameterValue": ""
+}
+]
diff --git a/production/wazuh/cluster/wazuh_cf_master.sh b/production/wazuh/cluster/wazuh_cf_master.sh
new file mode 100644
index 0000000..8a70963
--- /dev/null
+++ b/production/wazuh/cluster/wazuh_cf_master.sh
@@ -0,0 +1,283 @@
+#!/bin/bash
+# Install Wazuh master instance using Cloudformation template
+# Support for Amazon Linux
+touch /tmp/deploy.log
+echo "Starting process." > /tmp/deploy.log
+
+ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2)
+ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2)
+elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1)
+wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2)
+wazuh_server_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhServerPort:' | cut -d' ' -f2)
+wazuh_registration_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhRegistrationPort:' | cut -d' ' -f2)
+wazuh_registration_password=$(cat /tmp/wazuh_cf_settings | grep '^WazuhRegistrationPassword:' | cut -d' ' -f2)
+wazuh_api_user=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminUsername:' | cut -d' ' -f2)
+wazuh_api_password=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminPassword:' | cut -d' ' -f2)
+wazuh_api_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiPort:' | cut -d' ' -f2)
+wazuh_cluster_key=$(cat /tmp/wazuh_cf_settings | grep '^WazuhClusterKey:' | cut -d' ' -f2)
+elb_elastic=$(cat /tmp/wazuh_cf_settings | grep '^ElbElasticDNS:' | cut -d' ' -f2)
+eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2)
+InstallType=$(cat /tmp/wazuh_cf_settings | grep '^InstallType:' | cut -d' ' -f2)
+TAG='v3.12.2'
+
+echo "Added env vars." >> /tmp/deploy.log
+
+# Check if running as root
+if [[ $EUID -ne 0 ]]; then
+ echo "This script must be run as root"
+ exit 1
+fi
+
+# Creating SSH user
+adduser ${ssh_username}
+echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers
+usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username}
+sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config
+systemctl restart sshd
+
+echo "Created SSH user." >> /tmp/deploy.log
+
+if [[ ${InstallType} == 'packages' ]]
+then
+cat > /etc/yum.repos.d/wazuh.repo <<\EOF
+[wazuh_repo]
+gpgcheck=1
+gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH
+enabled=1
+name=Wazuh repository
+baseurl=https://packages.wazuh.com/3.x/yum/
+protect=1
+EOF
+elif [[ ${InstallType} == 'sources' ]]
+then
+
+ # Compile Wazuh manager from sources
+ BRANCH="3.12"
+
+ yum install make gcc policycoreutils-python automake autoconf libtool -y
+ curl -Ls https://github.com/wazuh/wazuh/archive/$BRANCH.tar.gz | tar zx
+ rm -f $BRANCH.tar.gz
+ cd wazuh-$BRANCH/src
+ make TARGET=agent DEBUG=1 -j8
+
+ USER_LANGUAGE="en" \
+ USER_NO_STOP="y" \
+ USER_INSTALL_TYPE="server" \
+ USER_DIR="/var/ossec" \
+ USER_ENABLE_EMAIL="n" \
+ USER_ENABLE_SYSCHECK="y" \
+ USER_ENABLE_ROOTCHECK="y" \
+ USER_ENABLE_OPENSCAP="n" \
+ USER_WHITE_LIST="n" \
+ USER_ENABLE_SYSLOG="n" \
+ USER_ENABLE_AUTHD="y" \
+ USER_AUTO_START="y" \
+ THREADS=2 \
+ ../install.sh
+ echo "Compiled wazuh" >> /tmp/deploy.log
+
+else
+ echo 'no repo' >> /tmp/stage
+fi
+
+# Configuring Elastic repository
+rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
+elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1)
+cat > /etc/yum.repos.d/elastic.repo << EOF
+[elasticsearch-${elastic_major_version}.x]
+name=Elasticsearch repository for ${elastic_major_version}.x packages
+baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum
+gpgcheck=1
+gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
+enabled=1
+autorefresh=1
+type=rpm-md
+EOF
+
+curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
+# Installing NodeJS
+yum -y install nodejs
+echo "Installed NodeJS." >> /tmp/deploy.log
+
+if [[ ${InstallType} != 'sources' ]]
+then
+
+ # Installing wazuh-manager
+ yum -y install wazuh-manager
+ chkconfig --add wazuh-manager
+ # Installing wazuh-api
+ yum -y install wazuh-api
+ chkconfig --add wazuh-api
+ echo "Installed Wazuh API." >> /tmp/deploy.log
+else
+ API_BRANCH="3.12"
+ npm config set user 0
+ curl -LO https://github.com/wazuh/wazuh-api/archive/$API_BRANCH.zip
+ unzip $API_BRANCH.zip
+ rm -f $API_BRANCH.zip
+ cd wazuh-api-$API_BRANCH
+ ./install_api.sh
+fi
+
+manager_config="/var/ossec/etc/ossec.conf"
+local_rules="/var/ossec/etc/rules/local_rules.xml"
+# Enable registration service (only for master node)
+
+echo "Installed wazuh manager package" >> /tmp/deploy.log
+
+
+# Change manager protocol to tcp, to be used by Amazon ELB
+sed -i "s/udp<\/protocol>/tcp<\/protocol>/" ${manager_config}
+
+# Set manager port for agent communications
+sed -i "s/1514<\/port>/${wazuh_server_port}<\/port>/" ${manager_config}
+
+# Configuring registration service
+sed -i '//,/<\/auth>/d' ${manager_config}
+
+cat >> ${manager_config} << EOF
+
+
+ no
+ ${wazuh_registration_port}
+ no
+ yes
+ 0
+ yes
+ yes
+ yes
+ HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH
+
+ no
+ /var/ossec/etc/sslmanager.cert
+ /var/ossec/etc/sslmanager.key
+ no
+
+
+EOF
+
+# Setting password for agents registration
+echo "${wazuh_registration_password}" > /var/ossec/etc/authd.pass
+echo "Set registration password." >> /tmp/deploy.log
+
+# Installing Python Cryptography module for the cluster
+pip install cryptography
+
+# Configuring cluster section
+sed -i '//,/<\/cluster>/d' ${manager_config}
+
+cat >> ${manager_config} << EOF
+
+
+ wazuh
+ wazuh-master
+ master
+ ${wazuh_cluster_key}
+ 1516
+ 0.0.0.0
+
+ ${eth0_ip}
+
+ no
+ no
+
+
+EOF
+
+# Disabling agent components and cleaning configuration file
+sed -i '//,/<\/wodle>/d' ${manager_config}
+sed -i '//,/<\/wodle>/d' ${manager_config}
+sed -i '//,/<\/ruleset>/d' ${manager_config}
+sed -i '//,/<\/wodle>/d' ${manager_config}
+sed -i '//,/<\/wodle>/d' ${manager_config}
+sed -i '//,/<\/localfile>/d' ${manager_config}
+sed -i '//d' ${manager_config}
+sed -i '//d' ${manager_config}
+sed -i '/^$/d' ${manager_config}
+
+# Restart wazuh-manager
+systemctl restart wazuh-manager
+systemctl enable wazuh-manager
+echo "Restarted Wazuh manager." >> /tmp/deploy.log
+
+# Configuring Wazuh API user and password
+cd /var/ossec/api/configuration/auth
+node htpasswd -b -c user ${wazuh_api_user} ${wazuh_api_password}
+
+# Enable Wazuh API SSL and configure listening port
+api_ssl_dir="/var/ossec/api/configuration/ssl"
+openssl req -x509 -batch -nodes -days 3650 -newkey rsa:2048 -keyout ${api_ssl_dir}/server.key -out ${api_ssl_dir}/server.crt
+sed -i "s/config.https = \"no\";/config.https = \"yes\";/" /var/ossec/api/configuration/config.js
+sed -i "s/config.port = \"55000\";/config.port = \"${wazuh_api_port}\";/" /var/ossec/api/configuration/config.js
+echo "Setting port and SSL to Wazuh API." >> /tmp/deploy.log
+
+# Restart wazuh-api
+systemctl restart wazuh-api
+echo "Restarted Wazuh API." >> /tmp/deploy.log
+
+# Installing Filebeat
+yum -y install filebeat-${elastic_version}
+echo "Installed Filebeat" >> /tmp/log
+
+# Configuring Filebeat
+wazuh_major=`echo $wazuh_version | cut -d'.' -f1`
+wazuh_minor=`echo $wazuh_version | cut -d'.' -f2`
+wazuh_patch=`echo $wazuh_version | cut -d'.' -f3`
+elastic_minor_version=$(echo ${elastic_version} | cut -d'.' -f2)
+elastic_patch_version=$(echo ${elastic_version} | cut -d'.' -f3)
+
+# Install Filebeat module
+curl -s "https://packages.wazuh.com/3.x/filebeat/wazuh-filebeat-0.1.tar.gz" | tar -xvz -C /usr/share/filebeat/module
+
+# Get Filebeat configuration file
+curl -so /etc/filebeat/filebeat.yml https://raw.githubusercontent.com/wazuh/wazuh/${TAG}/extensions/filebeat/7.x/filebeat.yml
+
+# Elasticsearch template
+curl -so /etc/filebeat/wazuh-template.json https://raw.githubusercontent.com/wazuh/wazuh/${TAG}/extensions/elasticsearch/7.x/wazuh-template.json
+
+# File permissions
+chmod go-w /etc/filebeat/filebeat.yml
+chmod go-w /etc/filebeat/wazuh-template.json
+
+# Point to Elasticsearch cluster
+sed -i "s|'http://YOUR_ELASTIC_SERVER_IP:9200'|'10.0.2.123','10.0.2.124','10.0.2.125'|" /etc/filebeat/filebeat.yml
+
+amazon-linux-extras install epel -y
+yum install -y sshpass
+chmod go-w /etc/filebeat/wazuh-template.json
+echo "output.elasticsearch.username: "elastic"" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.password: "$ssh_password"" >> /etc/filebeat/filebeat.yml
+mkdir -p /etc/filebeat/certs/ca
+amazon-linux-extras install epel -y
+yum install -y sshpass
+sleep 500
+echo $ssh_password >> pass
+sshpass -f pass scp -o "StrictHostKeyChecking=no" wazuh@10.0.2.124:/home/wazuh/certs.zip /home/wazuh/
+rm pass -f
+cp /home/wazuh/certs.zip .
+unzip certs.zip
+cp ca/ca.crt /etc/filebeat/certs/ca
+cp wazuh-manager/wazuh-manager.crt /etc/filebeat/certs
+cp wazuh-manager/wazuh-manager.key /etc/filebeat/certs
+chmod 770 -R /etc/filebeat/certs
+echo "output.elasticsearch.protocol: https" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.ssl.certificate: "/etc/filebeat/certs/wazuh-manager.crt"" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.ssl.key: "/etc/filebeat/certs/wazuh-manager.key"" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.ssl.certificate_authorities: ["/etc/filebeat/certs/ca/ca.crt"]" >> /etc/filebeat/filebeat.yml
+systemctl enable filebeat
+systemctl daemon-reload
+systemctl restart filebeat
+echo "Restarted Filebeat." >> /tmp/deploy.log
+
+
+# Load template in Easticsearch
+echo "Loading template..." >> /tmp/deploy.log
+until curl -XGET "https://10.0.2.123:9200" -k -u elastic:${ssh_password}; do
+ sleep 5
+ echo "Elasticsearch not ready yet..." >> /tmp/deploy.log
+done
+
+filebeat setup --index-management -E setup.template.json.enabled=false
+
+# Disable repositories
+sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo
diff --git a/production/wazuh/cluster/wazuh_cf_worker.sh b/production/wazuh/cluster/wazuh_cf_worker.sh
new file mode 100644
index 0000000..d501669
--- /dev/null
+++ b/production/wazuh/cluster/wazuh_cf_worker.sh
@@ -0,0 +1,194 @@
+#!/bin/bash
+# Install Wazuh worker instance using Cloudformation template
+# Support for Amazon Linux
+touch /tmp/log
+echo "Starting process." >> /tmp/log
+
+ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2)
+ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2)
+elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1)
+wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2)
+wazuh_server_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhServerPort:' | cut -d' ' -f2)
+wazuh_cluster_key=$(cat /tmp/wazuh_cf_settings | grep '^WazuhClusterKey:' | cut -d' ' -f2)
+wazuh_master_ip=$(cat /tmp/wazuh_cf_settings | grep '^WazuhMasterIP:' | cut -d' ' -f2)
+elb_elasticsearch=$(cat /tmp/wazuh_cf_settings | grep '^ElbElasticDNS:' | cut -d' ' -f2)
+InstallType=$(cat /tmp/wazuh_cf_settings | grep '^InstallType:' | cut -d' ' -f2)
+TAG='v3.12.2'
+
+# Check if running as root
+if [[ $EUID -ne 0 ]]; then
+ echo "This script must be run as root"
+ exit 1
+fi
+
+# Creating SSH user
+adduser ${ssh_username}
+echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers
+usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username}
+sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config
+systemctl restart sshd
+echo "Created SSH user." >> /tmp/log
+
+if [[ ${InstallType} == 'packages' ]]
+then
+cat > /etc/yum.repos.d/wazuh.repo <<\EOF
+[wazuh_repo]
+gpgcheck=1
+gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH
+enabled=1
+name=Wazuh repository
+baseurl=https://packages.wazuh.com/3.x/yum/
+protect=1
+EOF
+elif [[ ${InstallType} == 'sources' ]]
+then
+
+ # Compile Wazuh manager from sources
+ BRANCH="3.12"
+
+ yum install make gcc policycoreutils-python automake autoconf libtool -y
+ curl -Ls https://github.com/wazuh/wazuh/archive/$BRANCH.tar.gz | tar zx
+ rm -f $BRANCH.tar.gz
+ cd wazuh-$BRANCH/src
+ make TARGET=agent DEBUG=1 -j8
+
+ USER_LANGUAGE="en" \
+ USER_NO_STOP="y" \
+ USER_INSTALL_TYPE="server" \
+ USER_DIR="/var/ossec" \
+ USER_ENABLE_EMAIL="n" \
+ USER_ENABLE_SYSCHECK="y" \
+ USER_ENABLE_ROOTCHECK="y" \
+ USER_ENABLE_OPENSCAP="n" \
+ USER_WHITE_LIST="n" \
+ USER_ENABLE_SYSLOG="n" \
+ USER_ENABLE_AUTHD="y" \
+ USER_AUTO_START="y" \
+ THREADS=2 \
+ ../install.sh
+ echo "Compiled wazuh" >> /tmp/deploy.log
+
+else
+ echo 'no repo' >> /tmp/stage
+fi
+
+# Configuring Elastic repository
+rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
+elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1)
+cat > /etc/yum.repos.d/elastic.repo << EOF
+[elasticsearch-${elastic_major_version}.x]
+name=Elasticsearch repository for ${elastic_major_version}.x packages
+baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum
+gpgcheck=1
+gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
+enabled=1
+autorefresh=1
+type=rpm-md
+EOF
+
+# Installing wazuh-manager
+yum -y install wazuh-manager
+systemctl enable wazuh-manager
+chkconfig --add wazuh-manager
+manager_config="/var/ossec/etc/ossec.conf"
+# Install dependencies
+yum -y install openscap-scanner
+
+echo "Installed wazuh manager package" >> /tmp/log
+
+# Change manager protocol to tcp, to be used by Amazon ELB
+sed -i "s/udp<\/protocol>/tcp<\/protocol>/" ${manager_config}
+
+# Set manager ports for agents communication
+sed -i "s/1514<\/port>/${wazuh_server_port}<\/port>/" ${manager_config}
+
+# Installing Python Cryptography module for the cluster
+pip install cryptography
+echo "Installed cryptography with pip" >> /tmp/log
+
+# Configuring cluster section
+sed -i '//,/<\/cluster>/d' ${manager_config}
+
+cat >> ${manager_config} << EOF
+
+
+ wazuh
+ wazuh-worker
+ worker
+ ${wazuh_cluster_key}
+ 1516
+ 0.0.0.0
+
+ ${wazuh_master_ip}
+
+ no
+ no
+
+
+EOF
+
+# Restart for receiving cluster data
+systemctl restart wazuh-manager
+# Wait for cluster information to be received (rules,lists...)
+sleep 60
+
+echo "Cluster configuration" >> /tmp/log
+
+# Restart wazuh-manager
+systemctl restart wazuh-manager
+
+# Installing Filebeat
+yum -y install filebeat-${elastic_version}
+echo "Installed Filebeat" >> /tmp/log
+
+# Configuring Filebeat
+wazuh_major=`echo $wazuh_version | cut -d'.' -f1`
+wazuh_minor=`echo $wazuh_version | cut -d'.' -f2`
+wazuh_patch=`echo $wazuh_version | cut -d'.' -f3`
+elastic_minor_version=$(echo ${elastic_version} | cut -d'.' -f2)
+elastic_patch_version=$(echo ${elastic_version} | cut -d'.' -f3)
+
+# Install Filebeat module
+curl -s "https://packages.wazuh.com/3.x/filebeat/wazuh-filebeat-0.1.tar.gz" | tar -xvz -C /usr/share/filebeat/module
+
+# Get Filebeat configuration file
+curl -so /etc/filebeat/filebeat.yml https://raw.githubusercontent.com/wazuh/wazuh/${TAG}/extensions/filebeat/7.x/filebeat.yml
+
+# Elasticsearch template
+curl -so /etc/filebeat/wazuh-template.json https://raw.githubusercontent.com/wazuh/wazuh/${TAG}/extensions/elasticsearch/7.x/wazuh-template.json
+
+# File permissions
+chmod go-w /etc/filebeat/filebeat.yml
+chmod go-w /etc/filebeat/wazuh-template.json
+
+# Point to Elasticsearch cluster
+sed -i "s|'http://YOUR_ELASTIC_SERVER_IP:9200'|'10.0.2.123','10.0.2.124','10.0.2.125'|" /etc/filebeat/filebeat.yml
+
+# Filebeat security
+echo "output.elasticsearch.username: "elastic"" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.password: "$ssh_password"" >> /etc/filebeat/filebeat.yml
+
+# Create certs folder
+mkdir -p /etc/filebeat/certs/ca
+
+amazon-linux-extras install epel -y
+yum install -y sshpass
+sleep 500
+echo $ssh_password >> pass
+sshpass -f pass scp -o "StrictHostKeyChecking=no" wazuh@10.0.2.124:/home/wazuh/certs.zip /home/wazuh/
+rm pass -f
+cp /home/wazuh/certs.zip .
+unzip certs.zip
+cp ca/ca.crt /etc/filebeat/certs/ca
+cp wazuh-worker/wazuh-worker.crt /etc/filebeat/certs
+cp wazuh-worker/wazuh-worker.key /etc/filebeat/certs
+chmod 770 -R /etc/filebeat/certs
+echo "output.elasticsearch.protocol: https" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.ssl.certificate: "/etc/filebeat/certs/wazuh-worker.crt"" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.ssl.key: "/etc/filebeat/certs/wazuh-worker.key"" >> /etc/filebeat/filebeat.yml
+echo "output.elasticsearch.ssl.certificate_authorities: ["/etc/filebeat/certs/ca/ca.crt"]" >> /etc/filebeat/filebeat.yml
+systemctl enable filebeat
+echo "Enabled Filebeat" >> /tmp/log
+systemctl restart filebeat
+echo "Started Filebeat" >> /tmp/log
+echo "Done" >> /tmp/log
\ No newline at end of file
diff --git a/production/wazuh_template.yml b/production/wazuh_template.yml
new file mode 100644
index 0000000..1155b07
--- /dev/null
+++ b/production/wazuh_template.yml
@@ -0,0 +1,1231 @@
+AWSTemplateFormatVersion: 2010-09-09
+Description: Provides production ready environment with a Wazuh cluster of two nodes, Elasticsearch cluster of three nodes with xpack security and SSL enabled.
+Mappings:
+ RegionMap:
+ us-east-1:
+ HVM64: ami-0c6b1d09930fac512
+ us-east-2:
+ HVM64: ami-0ebbf2179e615c338
+ us-west-1:
+ HVM64: ami-015954d5e5548d13b
+ us-west-2:
+ HVM64: ami-0cb72367e98845d43
+ ca-central-1:
+ HVM64: ami-08a9b721ecc5b0a53
+ eu-west-1:
+ HVM64: ami-030dbca661d402413
+ eu-west-2:
+ HVM64: ami-0009a33f033d8b7b6
+ eu-west-3:
+ HVM64: ami-0ebb3a801d5fb8b9b
+ ap-northeast-1:
+ HVM64: ami-00d101850e971728d
+ ap-northeast-2:
+ HVM64: ami-08ab3f7e72215fe91
+ ap-southeast-1:
+ HVM64: ami-0b5a47f8865280111
+ ap-southeast-2:
+ HVM64: ami-0fb7513bcdc525c3b
+ ap-south-1:
+ HVM64: ami-00e782930f1c3dbc7
+ sa-east-1:
+ HVM64: ami-058141e091292ecf0
+ SubnetConfig:
+ WazuhVpc:
+ CIDR: 10.0.0.0/16
+ SubnetWazuh:
+ CIDR: 10.0.0.0/24
+ SubnetElasticsearch:
+ CIDR: 10.0.2.0/24
+
+Metadata:
+ AWS::CloudFormation::Interface:
+ ParameterGroups:
+ -
+ Label:
+ default: "Installation method"
+ Parameters:
+ - InstallType
+ -
+ Label:
+ default: "DNS records details"
+ Parameters:
+ - EnableDNSRecord
+ - HostedZoneName
+ - Subdomain
+ -
+ Label:
+ default: "AWS environment"
+ Parameters:
+ - AvailabilityZone
+ - KeyPairName
+ -
+ Label:
+ default: "Version and instance types"
+ Parameters:
+ - ElasticWazuhVersion
+ - WazuhInstanceType
+ - ElasticInstanceType
+ - KibanaInstanceType
+ - SshUsername
+ - SshPassword
+ -
+ Label:
+ default: "Wazuh configuration"
+ Parameters:
+ - WazuhServerPort
+ - WazuhRegistrationPort
+ - WazuhRegistrationPassword
+ - WazuhApiPort
+ - WazuhApiAdminUsername
+ - WazuhApiAdminPassword
+ - WazuhClusterKey
+ -
+ Label:
+ default: "Kibana configuration"
+ Parameters:
+ - KibanaPort
+ -
+ Label:
+ default: "SSL Certificate"
+ Parameters:
+ - SSLCertificateARN
+
+Parameters:
+
+ # DNS records details
+ HostedZoneName:
+ Description: HostedZoneName
+ Type: String
+ Subdomain:
+ Description: Subdomain name
+ Type: String
+ EnableDNSRecord:
+ Default: disabled
+ Description: If enabled deploy DNS records for each node and the common LB.
+ ConstraintDescription: Only enabled or disabled.
+ AllowedValues:
+ - enabled
+ - disabled
+ Type: String
+
+ # AWS environment
+ AvailabilityZone:
+ Description: Select an availability zone for the VPC
+ Type: 'List'
+ KeyPairName:
+ Description: Existing EC2 key pair for SSH access
+ Type: 'AWS::EC2::KeyPair::KeyName'
+ SshUsername:
+ Default: wazuh
+ Description: SSH username
+ Type: String
+ MinLength: '5'
+ MaxLength: '32'
+ AllowedPattern: '[a-zA-Z0-9]*'
+ ConstraintDescription: Only alphanumeric characters. Minimum length 5. Maximum length 32.
+ SshPassword:
+ Description: SSH Password
+ NoEcho: 'True'
+ Type: String
+ MinLength: '8'
+ MaxLength: '64'
+ AllowedPattern: '[a-zA-Z0-9]*'
+ ConstraintDescription: Only alphanumeric characters. Minimum length 8. Maximum length 64.
+
+ # Version and instance types
+ ElasticWazuhVersion:
+ AllowedValues:
+ - 6.5.0_3.7.0
+ - 6.5.1_3.7.1
+ - 6.5.2_3.7.1
+ - 6.5.3_3.7.2
+ - 6.5.4_3.7.2
+ - 6.6.2_3.9.0
+ - 6.7.0_3.9.0
+ - 6.7.1_3.9.0
+ - 6.8.0_3.9.1
+ - 7.1.0_3.9.1
+ - 7.1.1_3.9.2
+ - 7.2.0_3.9.3
+ - 7.2.0_3.9.4
+ - 7.3.0_3.9.4
+ - 7.3.0_3.9.5
+ - 7.3.2_3.10.0
+ - 7.3.2_3.10.2
+ - 7.3.2_3.11.0
+ - 7.4.2_3.11.0
+ - 7.5.0_3.11.0
+ - 7.5.1_3.11.0
+ - 7.5.1_3.11.1
+ - 7.5.1_3.11.2
+ - 7.5.2_3.11.3
+ - 7.6.1_3.11.4
+ - 7.6.1_3.12.0
+ - 7.6.2_3.12.2
+ ConstraintDescription: Format is ElasticVersion_WazuhVersion
+ Default: 7.6.2_3.12.2
+ Description: Elastic and Wazuh versions to be installed
+ Type: String
+ WazuhInstanceType:
+ AllowedValues:
+ - t2.micro
+ - t2.medium
+ - t2.large
+ - m5.large
+ - m5.xlarge
+ - m5.2xlarge
+
+ ConstraintDescription: Must contain valid instance type
+ Default: t2.medium
+ Description: Type of EC2 instance for Wazuh instance
+ Type: String
+ InstallType:
+ AllowedValues:
+ - packages
+ - sources
+ ConstraintDescription: Must contain valid install type
+ Default: packages
+ Description: Select between packages or sources install
+ Type: String
+ ElasticInstanceType:
+ AllowedValues:
+ - t2.medium
+ - t2.large
+ - m5d.large
+ - i3.large
+ - i3.xlarge
+ - i3.2xlarge
+
+ ConstraintDescription: Must contain valid instance type
+ Default: t2.medium
+ Description: Type of EC2 instance for Elastic instance
+ Type: String
+ KibanaInstanceType:
+ AllowedValues:
+ - t2.medium
+ - t2.large
+ - m5.large
+ - m5d.large
+ - m5.xlarge
+ - m5.2xlarge
+ - r5.large
+
+ ConstraintDescription: Must contain valid instance type
+ Default: t2.medium
+ Description: Type of EC2 instance for Kibana instance
+ Type: String
+
+ # Wazuh configuration
+ WazuhServerPort:
+ Default: '1514'
+ Description: Port for agents connection with Wazuh server
+ Type: String
+ WazuhRegistrationPort:
+ Default: '1515'
+ Description: Port for agents registration with Wazuh server
+ Type: String
+ WazuhRegistrationPassword:
+ Description: Password for Wazuh agents registration
+ NoEcho: 'True'
+ Type: String
+ MinLength: '1'
+ MaxLength: '48'
+ AllowedPattern: '[a-zA-Z0-9]*'
+ ConstraintDescription: Only alphanumeric characters
+ WazuhApiPort:
+ Default: '55000'
+ Description: Port for Wazuh server API
+ Type: String
+ WazuhApiAdminUsername:
+ Default: admin
+ Description: Admin username for Wazuh API
+ Type: String
+ MinLength: '1'
+ MaxLength: '16'
+ AllowedPattern: '[a-zA-Z0-9]*'
+ ConstraintDescription: Only alphanumeric characters
+ WazuhApiAdminPassword:
+ Description: Admin password for Wazuh API
+ NoEcho: 'True'
+ Type: String
+ MinLength: '1'
+ MaxLength: '48'
+ AllowedPattern: '[a-zA-Z0-9]*'
+ ConstraintDescription: Only alphanumeric characters
+ WazuhClusterKey:
+ Description: Key used for Wazuh servers cluster
+ Default: 'abcdefghijklmnopqrstuvwxyz012345'
+ Type: String
+ MinLength: '32'
+ MaxLength: '32'
+ AllowedPattern: '[a-zA-Z0-9]*'
+ ConstraintDescription: Any alphanumeric string of 32 characters
+ # Kibana configuration
+ KibanaPort:
+ Default: '443'
+ Description: Port for Kibana WUI
+ Type: String
+ SSLCertificateARN:
+ Description: 'Used for HTTPS access to WUI. Existent certificate, identified by its Amazon Resource Name (ARN).'
+ Type: String
+
+Conditions:
+ HasSslCert: !Not [!Equals [!Ref SSLCertificateARN, ""]]
+ EnableDNSRecords: !Not [!Equals [!Ref EnableDNSRecord, "disabled"]]
+
+Resources:
+
+ # Network resources
+ WazuhVpc:
+ Type: 'AWS::EC2::VPC'
+ Properties:
+ CidrBlock: !FindInMap
+ - SubnetConfig
+ - WazuhVpc
+ - CIDR
+ EnableDnsSupport: 'true'
+ EnableDnsHostnames: 'true'
+ Tags:
+ - Key: Application
+ Value: !Ref 'AWS::StackId'
+ - Key: Name
+ Value: !Ref 'AWS::StackName'
+ SubnetWazuh:
+ Type: 'AWS::EC2::Subnet'
+ Properties:
+ VpcId: !Ref WazuhVpc
+ AvailabilityZone: !Select [ "0", !Ref AvailabilityZone ]
+ CidrBlock: !FindInMap
+ - SubnetConfig
+ - SubnetWazuh
+ - CIDR
+ Tags:
+ - Key: Application
+ Value: !Ref 'AWS::StackId'
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-SubnetWazuh'
+ SubnetElasticsearch:
+ Type: 'AWS::EC2::Subnet'
+ Properties:
+ VpcId: !Ref WazuhVpc
+ AvailabilityZone: !Select [ "0", !Ref AvailabilityZone ]
+ CidrBlock: !FindInMap
+ - SubnetConfig
+ - SubnetElasticsearch
+ - CIDR
+ Tags:
+ - Key: Application
+ Value: !Ref 'AWS::StackId'
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-SubnetElasticsearch'
+
+ # Internet access and routing
+ InternetGateway:
+ Type: 'AWS::EC2::InternetGateway'
+ Properties:
+ Tags:
+ - Key: Application
+ Value: !Ref 'AWS::StackId'
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-InternetGateway'
+ GatewayToInternet:
+ Type: 'AWS::EC2::VPCGatewayAttachment'
+ Properties:
+ VpcId: !Ref WazuhVpc
+ InternetGatewayId: !Ref InternetGateway
+ PublicRouteTable:
+ Type: 'AWS::EC2::RouteTable'
+ Properties:
+ VpcId: !Ref WazuhVpc
+ Tags:
+ - Key: Application
+ Value: !Ref 'AWS::StackId'
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-PublicRouteTable'
+ PublicRoute:
+ Type: 'AWS::EC2::Route'
+ DependsOn: GatewayToInternet
+ Properties:
+ RouteTableId: !Ref PublicRouteTable
+ DestinationCidrBlock: 0.0.0.0/0
+ GatewayId: !Ref InternetGateway
+ SubnetWazuhPublicRouteTable:
+ Type: 'AWS::EC2::SubnetRouteTableAssociation'
+ Properties:
+ SubnetId: !Ref SubnetWazuh
+ RouteTableId: !Ref PublicRouteTable
+ SubnetElasticPublicRouteTable:
+ Type: 'AWS::EC2::SubnetRouteTableAssociation'
+ Properties:
+ SubnetId: !Ref SubnetElasticsearch
+ RouteTableId: !Ref PublicRouteTable
+
+ # Security groups
+ ElasticSecurityGroup:
+ Type: 'AWS::EC2::SecurityGroup'
+ Properties:
+ GroupDescription: Elasticsearch security group
+ VpcId: !Ref WazuhVpc
+ SecurityGroupIngress:
+ - IpProtocol: tcp
+ FromPort: 22
+ ToPort: 22
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: 9200
+ ToPort: 9400
+ CidrIp: !FindInMap
+ - SubnetConfig
+ - WazuhVpc
+ - CIDR
+ Tags:
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-ElasticSecurityGroup'
+ KibanaSecurityGroup:
+ Type: 'AWS::EC2::SecurityGroup'
+ Properties:
+ GroupDescription: Kibana security group
+ VpcId: !Ref WazuhVpc
+ SecurityGroupIngress:
+ - IpProtocol: tcp
+ FromPort: 22
+ ToPort: 22
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: !Ref KibanaPort
+ ToPort: !Ref KibanaPort
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: 9200
+ ToPort: 9400
+ CidrIp: !FindInMap
+ - SubnetConfig
+ - WazuhVpc
+ - CIDR
+ Tags:
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-KibanaSecurityGroup'
+ WazuhSecurityGroup:
+ Type: 'AWS::EC2::SecurityGroup'
+ Properties:
+ GroupDescription: Wazuh security group
+ VpcId: !Ref WazuhVpc
+ SecurityGroupIngress:
+ - IpProtocol: tcp
+ FromPort: 22
+ ToPort: 22
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: 3389
+ ToPort: 3389
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: 80
+ ToPort: 80
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: icmp
+ FromPort: -1
+ ToPort: -1
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: !Ref WazuhServerPort
+ ToPort: !Ref WazuhServerPort
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: !Ref WazuhRegistrationPort
+ ToPort: !Ref WazuhRegistrationPort
+ CidrIp: 0.0.0.0/0
+ - IpProtocol: tcp
+ FromPort: 1516
+ ToPort: 1516
+ CidrIp: !FindInMap
+ - SubnetConfig
+ - WazuhVpc
+ - CIDR
+ - IpProtocol: tcp
+ FromPort: !Ref WazuhApiPort
+ ToPort: !Ref WazuhApiPort
+ CidrIp: !FindInMap
+ - SubnetConfig
+ - WazuhVpc
+ - CIDR
+ Tags:
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-WazuhSecurityGroup'
+
+ # Elasticsearch load balancer
+ ElbElasticSecurityGroup:
+ Type: 'AWS::EC2::SecurityGroup'
+ Properties:
+ GroupDescription: ELB Elasticsearch security group
+ VpcId: !Ref WazuhVpc
+ SecurityGroupIngress:
+ - IpProtocol: tcp
+ FromPort: 9200
+ ToPort: 9200
+ CidrIp: !FindInMap
+ - SubnetConfig
+ - WazuhVpc
+ - CIDR
+ Tags:
+ - Key: Name
+ Value: !Sub '${AWS::StackName}-ElbElasticSecurityGroup'
+
+ # Wazuh registration Listener for Network Load Balancer
+ ElasticBootstrap:
+ Type: AWS::EC2::Instance
+ Metadata:
+ 'AWS::CloudFormation::Init':
+ configSets:
+ ElasticInstallationSet:
+ - Elasticfiles
+ - ElasticInstall
+ Elasticfiles:
+ files:
+ /tmp/wazuh_cf_settings:
+ content: !Sub |
+ SshUsername: ${SshUsername}
+ SshPassword: ${SshPassword}
+ Elastic_Wazuh: ${ElasticWazuhVersion}
+ MasterIp: ${WazuhMasterInstance.PrivateIp}
+ WorkerIp: ${WazuhWorkerInstance.PrivateIp}
+ KibanaIp: ${KibanaInstance.PrivateIp}
+ NodeName: 3
+ mode: '000600'
+ owner: root
+ group: root
+ /tmp/wazuh_cf_bootstrap_elastic.sh:
+ source: !Sub >-
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/production/elastic/wazuh_cf_bootstrap_elastic.sh
+ mode: '000700'
+ owner: root
+ group: root
+ ElasticInstall:
+ commands:
+ 01_RunInstallationScript:
+ command: /tmp/wazuh_cf_bootstrap_elastic.sh
+ Properties:
+ ImageId: !FindInMap
+ - "RegionMap"
+ - Ref: "AWS::Region"
+ - HVM64
+ InstanceType: !Ref ElasticInstanceType
+ IamInstanceProfile: !Ref InstanceProfile
+ KeyName: !Ref KeyPairName
+ BlockDeviceMappings:
+ - DeviceName: /dev/xvda
+ Ebs:
+ VolumeSize: 50
+ VolumeType: gp2
+ NetworkInterfaces:
+ - AssociatePublicIpAddress: "true"
+ DeviceIndex: "0"
+ GroupSet:
+ - Ref: "ElasticSecurityGroup"
+ SubnetId:
+ Ref: "SubnetElasticsearch"
+ PrivateIpAddress: "10.0.2.124"
+ Tags:
+ - Key: Name
+ Value: ElasticBootstrap
+ UserData:
+ Fn::Base64: !Sub |
+ #!/bin/bash -xe
+ /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource ElasticBootstrap --configsets ElasticInstallationSet --region ${AWS::Region}
+ /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ElasticBootstrap --region ${AWS::Region}
+ DependsOn: GatewayToInternet
+ ElasticBootstrapEth0:
+ Type: AWS::EC2::NetworkInterface
+ Properties:
+ SubnetId: !Ref SubnetElasticsearch
+ GroupSet: [!Ref 'ElasticSecurityGroup']
+ ElasticBootstrapEIP:
+ Type: AWS::EC2::EIP
+ Properties:
+ Domain: vpc
+ Tags:
+ - Key: Name
+ Value: !Sub 'ElasticBootstrapEIP-${AWS::StackName}'
+ ElasticBootstrapEIPAssociation:
+ Type: 'AWS::EC2::EIPAssociation'
+ Properties:
+ NetworkInterfaceId: !Ref ElasticBootstrapEth0
+ AllocationId: !GetAtt
+ - ElasticBootstrapEIP
+ - AllocationId
+
+ ElasticMasterB:
+ Type: AWS::EC2::Instance
+ Metadata:
+ 'AWS::CloudFormation::Init':
+ configSets:
+ ElasticInstallationSet:
+ - Elasticfiles
+ - ElasticInstall
+ Elasticfiles:
+ files:
+ /tmp/wazuh_cf_settings:
+ content: !Sub |
+ SshUsername: ${SshUsername}
+ SshPassword: ${SshPassword}
+ Elastic_Wazuh: ${ElasticWazuhVersion}
+ NodeName: 1
+ mode: '000600'
+ owner: root
+ group: root
+ /tmp/wazuh_cf_elastic.sh:
+ source: !Sub >-
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/production/elastic/wazuh_cf_elastic.sh
+ mode: '000700'
+ owner: root
+ group: root
+ ElasticInstall:
+ commands:
+ 01_RunInstallationScript:
+ command: /tmp/wazuh_cf_elastic.sh
+ Properties:
+ ImageId: !FindInMap
+ - "RegionMap"
+ - Ref: "AWS::Region"
+ - HVM64
+ InstanceType: !Ref ElasticInstanceType
+ IamInstanceProfile: !Ref InstanceProfile
+ KeyName: !Ref KeyPairName
+ BlockDeviceMappings:
+ - DeviceName: /dev/xvda
+ Ebs:
+ VolumeSize: 50
+ VolumeType: gp2
+ NetworkInterfaces:
+ - AssociatePublicIpAddress: "true"
+ DeviceIndex: "0"
+ GroupSet:
+ - Ref: "ElasticSecurityGroup"
+ SubnetId:
+ Ref: "SubnetElasticsearch"
+ PrivateIpAddress: "10.0.2.123"
+ Tags:
+ - Key: Name
+ Value: ElasticMasterB
+ UserData:
+ Fn::Base64: !Sub |
+ #!/bin/bash -xe
+ /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource ElasticMasterB --configsets ElasticInstallationSet --region ${AWS::Region}
+ /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ElasticMasterB --region ${AWS::Region}
+ DependsOn: GatewayToInternet
+ ElasticMasterBEth0:
+ Type: AWS::EC2::NetworkInterface
+ Properties:
+ SubnetId: !Ref SubnetElasticsearch
+ GroupSet: [!Ref 'ElasticSecurityGroup']
+ ElasticMasterBEIP:
+ Type: AWS::EC2::EIP
+ Properties:
+ Domain: vpc
+ Tags:
+ - Key: Name
+ Value: !Sub 'ElasticMasterBEIP-${AWS::StackName}'
+ ElasticMasterBEIPAssociation:
+ Type: 'AWS::EC2::EIPAssociation'
+ Properties:
+ NetworkInterfaceId: !Ref ElasticMasterBEth0
+ AllocationId: !GetAtt
+ - ElasticMasterBEIP
+ - AllocationId
+
+ ElasticMasterC:
+ Type: AWS::EC2::Instance
+ Metadata:
+ 'AWS::CloudFormation::Init':
+ configSets:
+ ElasticInstallationSet:
+ - Elasticfiles
+ - ElasticInstall
+ Elasticfiles:
+ files:
+ /tmp/wazuh_cf_settings:
+ content: !Sub |
+ SshUsername: ${SshUsername}
+ SshPassword: ${SshPassword}
+ Elastic_Wazuh: ${ElasticWazuhVersion}
+ NodeName: 2
+ mode: '000600'
+ owner: root
+ group: root
+ /tmp/wazuh_cf_elastic.sh:
+ source: !Sub >-
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/production/elastic/wazuh_cf_elastic.sh
+ mode: '000700'
+ owner: root
+ group: root
+ ElasticInstall:
+ commands:
+ 01_RunInstallationScript:
+ command: /tmp/wazuh_cf_elastic.sh
+ Properties:
+ ImageId: !FindInMap
+ - "RegionMap"
+ - Ref: "AWS::Region"
+ - HVM64
+ InstanceType: !Ref ElasticInstanceType
+ IamInstanceProfile: !Ref InstanceProfile
+ KeyName: !Ref KeyPairName
+ BlockDeviceMappings:
+ - DeviceName: /dev/xvda
+ Ebs:
+ VolumeSize: 50
+ VolumeType: gp2
+ NetworkInterfaces:
+ - AssociatePublicIpAddress: "true"
+ DeviceIndex: "0"
+ GroupSet:
+ - Ref: "ElasticSecurityGroup"
+ SubnetId:
+ Ref: "SubnetElasticsearch"
+ PrivateIpAddress: "10.0.2.125"
+ Tags:
+ - Key: Name
+ Value: ElasticMasterC
+ UserData:
+ Fn::Base64: !Sub |
+ #!/bin/bash -xe
+ /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource ElasticMasterC --configsets ElasticInstallationSet --region ${AWS::Region}
+ /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ElasticMasterC --region ${AWS::Region}
+ DependsOn: GatewayToInternet
+ ElasticMasterCEth0:
+ Type: AWS::EC2::NetworkInterface
+ Properties:
+ SubnetId: !Ref SubnetElasticsearch
+ GroupSet: [!Ref 'ElasticSecurityGroup']
+ ElasticMasterCEIP:
+ Type: AWS::EC2::EIP
+ Properties:
+ Domain: vpc
+ Tags:
+ - Key: Name
+ Value: !Sub 'ElasticMasterCEIP-${AWS::StackName}'
+ ElasticMasterCEIPAssociation:
+ Type: 'AWS::EC2::EIPAssociation'
+ Properties:
+ NetworkInterfaceId: !Ref ElasticMasterCEth0
+ AllocationId: !GetAtt
+ - ElasticMasterCEIP
+ - AllocationId
+
+ # Wazuh Network Load Balancer
+ WazuhNetworkLoadBalancer:
+ Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+ Properties:
+ Name: !Sub '${AWS::StackName}-Wazuh'
+ Scheme: internet-facing
+ Subnets:
+ - !Ref SubnetWazuh
+ Type: network
+ Tags:
+ - Key: Name
+ Value: nlbwazuh
+ # Wazuh Network Load Balancer route53 record
+ LbRecord:
+ Type: AWS::Route53::RecordSet
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', [!Ref 'Subdomain', ., !Ref 'HostedZoneName']]
+ Comment: DNS name for the Wazuh load balancer
+ Type: A
+ AliasTarget:
+ HostedZoneId: !GetAtt 'WazuhNetworkLoadBalancer.CanonicalHostedZoneID'
+ DNSName: !GetAtt 'WazuhNetworkLoadBalancer.DNSName'
+ # Deployed nodes route53 records
+ ElasticBootstrapRecord:
+ Type: 'AWS::Route53::RecordSet'
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', ['ElasticBootstrap', ., !Ref 'HostedZoneName']]
+ Type: A
+ TTL: '600'
+ ResourceRecords:
+ - !GetAtt ElasticBootstrap.PublicIp
+ ElasticMasterBRecord:
+ Type: 'AWS::Route53::RecordSet'
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', ['ElasticMasterB', ., !Ref 'HostedZoneName']]
+ Type: A
+ TTL: '600'
+ ResourceRecords:
+ - !GetAtt ElasticMasterB.PublicIp
+ ElasticMasterCRecord:
+ Type: 'AWS::Route53::RecordSet'
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', ['ElasticMasterC', ., !Ref 'HostedZoneName']]
+ Type: A
+ TTL: '600'
+ ResourceRecords:
+ - !GetAtt ElasticMasterC.PublicIp
+ KibanaInstanceRecord:
+ Type: 'AWS::Route53::RecordSet'
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', ['KibanaInstance', ., !Ref 'HostedZoneName']]
+ Type: A
+ TTL: '600'
+ ResourceRecords:
+ - !GetAtt KibanaInstance.PublicIp
+ WazuhMasterInstanceRecord:
+ Type: 'AWS::Route53::RecordSet'
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', ['WazuhMasterInstance', ., !Ref 'HostedZoneName']]
+ Type: A
+ TTL: '600'
+ ResourceRecords:
+ - !GetAtt WazuhMasterInstance.PublicIp
+ WazuhWorkerInstanceRecord:
+ Type: 'AWS::Route53::RecordSet'
+ Condition: EnableDNSRecords
+ Properties:
+ HostedZoneName: !Ref 'HostedZoneName'
+ Name: !Join ['', ['WazuhWorkerInstance', ., !Ref 'HostedZoneName']]
+ Type: A
+ TTL: '600'
+ ResourceRecords:
+ - !GetAtt WazuhWorkerInstance.PublicIp
+
+ # Wazuh registration Target Group for Network Load Balancer
+ RegistrationTG:
+ Type: AWS::ElasticLoadBalancingV2::TargetGroup
+ Properties:
+ Name: !Sub '${AWS::StackName}-registrationTG'
+ Port: !Ref WazuhRegistrationPort
+ Protocol: TCP
+ VpcId: !Ref WazuhVpc
+ TargetGroupAttributes:
+ - Key: deregistration_delay.timeout_seconds
+ Value: 600
+ Targets:
+ - Id: !Ref WazuhMasterInstance
+ Port: !Ref WazuhRegistrationPort
+ Tags:
+ - Key: Name
+ Value: registrationTG
+
+ # TLS Target Group for Network Load Balancer
+ TLSTargetGroup:
+ Type: AWS::ElasticLoadBalancingV2::TargetGroup
+ Condition: HasSslCert
+ Properties:
+ Name: !Sub '${AWS::StackName}-TLSTargetGroup'
+ Port: !Ref KibanaPort
+ Protocol: TCP
+ VpcId: !Ref WazuhVpc
+ TargetGroupAttributes:
+ - Key: deregistration_delay.timeout_seconds
+ Value: 600
+ Targets:
+ - Id: !Ref KibanaInstance
+ Port: !Ref KibanaPort
+ Tags:
+ - Key: Name
+ Value: TLSTargetGroup
+
+ # Wazuh registration Listener for Network Load Balancer
+ RegistrationListener:
+ Type: AWS::ElasticLoadBalancingV2::Listener
+ Properties:
+ DefaultActions:
+ - Type: forward
+ TargetGroupArn: !Ref RegistrationTG
+ LoadBalancerArn: !Ref WazuhNetworkLoadBalancer
+ Port: !Ref WazuhRegistrationPort
+ Protocol: TCP
+
+ # Reporting Target Group for Wazuh master and worker nodes
+ ReportingTG:
+ Type: AWS::ElasticLoadBalancingV2::TargetGroup
+ Properties:
+ Name: !Sub '${AWS::StackName}-reportingTG'
+ Port: !Ref WazuhServerPort
+ Protocol: TCP
+ VpcId: !Ref WazuhVpc
+ TargetGroupAttributes:
+ - Key: deregistration_delay.timeout_seconds
+ Value: 600
+ Targets:
+ - Id: !Ref WazuhMasterInstance
+ Port: !Ref WazuhServerPort
+ - Id: !Ref WazuhWorkerInstance
+ Port: !Ref WazuhServerPort
+ Tags:
+ - Key: Name
+ Value: reportingTG
+
+ # Reporting Listener for Network LB.
+ ReportingListener:
+ Type: AWS::ElasticLoadBalancingV2::Listener
+ Properties:
+ DefaultActions:
+ - Type: forward
+ TargetGroupArn: !Ref ReportingTG
+ LoadBalancerArn: !Ref WazuhNetworkLoadBalancer
+ Port: '1514'
+ Protocol: TCP
+
+ # Listener for Kibana WUI
+ TLSListener:
+ Type: AWS::ElasticLoadBalancingV2::Listener
+ Condition: HasSslCert
+ Properties:
+ DefaultActions:
+ - Type: forward
+ TargetGroupArn: !Ref TLSTargetGroup
+ LoadBalancerArn: !Ref WazuhNetworkLoadBalancer
+ Port: !Ref KibanaPort
+ Protocol: TLS
+ Certificates:
+ - CertificateArn: !Ref SSLCertificateARN
+
+ # IAM role and profile
+ InstanceRole:
+ Type: 'AWS::IAM::Role'
+ Properties:
+ AssumeRolePolicyDocument:
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - ec2.amazonaws.com
+ - cloudformation.amazonaws.com
+ Action:
+ - 'sts:AssumeRole'
+ Policies:
+ - PolicyName: !Sub '${AWS::StackName}-GetCloudformation'
+ PolicyDocument:
+ Statement:
+ - Action:
+ - 'cloudformation:DescribeStack*'
+ - 'cloudformation:DescribeStackResource*'
+ - 'cloudformation:List*'
+ Resource: '*'
+ Effect: Allow
+ - PolicyName: !Sub '${AWS::StackName}-DescribeInstances'
+ PolicyDocument:
+ Statement:
+ - Action:
+ - 'ec2:DescribeInstances'
+ Resource: '*'
+ Effect: Allow
+ InstanceProfile:
+ Type: 'AWS::IAM::InstanceProfile'
+ Properties:
+ Roles:
+ - !Ref InstanceRole
+
+ # Kibana instance
+ KibanaInstance:
+ Type: AWS::EC2::Instance
+ Metadata:
+ 'AWS::CloudFormation::Init':
+ configSets:
+ KibanaInstallationSet:
+ - KibanaFiles
+ - KibanaInstall
+ KibanaFiles:
+ files:
+ /tmp/wazuh_cf_settings:
+ content: !Sub |
+ SshUsername: ${SshUsername}
+ SshPassword: ${SshPassword}
+ Elastic_Wazuh: ${ElasticWazuhVersion}
+ KibanaPort: ${KibanaPort}
+ WazuhApiAdminUsername: ${WazuhApiAdminUsername}
+ WazuhApiAdminPassword: ${WazuhApiAdminPassword}
+ WazuhApiPort: ${WazuhApiPort}
+ WazuhMasterIP: ${WazuhMasterInstance.PrivateIp}
+ InstallType: ${InstallType}
+ mode: '000600'
+ owner: root
+ group: root
+ /tmp/wazuh_cf_kibana.sh:
+ source: !Sub >-
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/production/elastic/wazuh_cf_kibana.sh
+ mode: '000700'
+ owner: root
+ group: root
+ KibanaInstall:
+ commands:
+ 01_RunInstallationScript:
+ command: /tmp/wazuh_cf_kibana.sh
+ Properties:
+ ImageId: !FindInMap
+ - "RegionMap"
+ - Ref: "AWS::Region"
+ - HVM64
+ InstanceType: !Ref KibanaInstanceType
+ IamInstanceProfile: !Ref InstanceProfile
+ KeyName: !Ref KeyPairName
+ NetworkInterfaces:
+ - AssociatePublicIpAddress: "true"
+ DeviceIndex: "0"
+ GroupSet:
+ - Ref: "KibanaSecurityGroup"
+ SubnetId:
+ Ref: "SubnetElasticsearch"
+ Tags:
+ - Key: Name
+ Value: WazuhKibana
+ UserData:
+ Fn::Base64: !Sub |
+ #!/bin/bash -xe
+ /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource KibanaInstance --configsets KibanaInstallationSet --region ${AWS::Region}
+ /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource KibanaInstance --region ${AWS::Region}
+ DependsOn: GatewayToInternet
+ KibanaEth0:
+ Type: AWS::EC2::NetworkInterface
+ Properties:
+ SubnetId: !Ref SubnetElasticsearch
+ GroupSet: [!Ref 'KibanaSecurityGroup']
+ KibanaEIP:
+ Type: AWS::EC2::EIP
+ Properties:
+ Domain: vpc
+ Tags:
+ - Key: Name
+ Value: !Sub 'KibanaEIP-${AWS::StackName}'
+ KibanaEIPAssociation:
+ Type: 'AWS::EC2::EIPAssociation'
+ Properties:
+ NetworkInterfaceId: !Ref KibanaEth0
+ AllocationId: !GetAtt
+ - KibanaEIP
+ - AllocationId
+
+ # Wazuh master instance
+ WazuhMasterInstance:
+ Type: AWS::EC2::Instance
+ Metadata:
+ 'AWS::CloudFormation::Init':
+ configSets:
+ WazuhInstallationSet:
+ - WazuhFiles
+ - WazuhInstall
+ WazuhFiles:
+ files:
+ /tmp/wazuh_cf_settings:
+ content: !Sub |
+ SshUsername: ${SshUsername}
+ SshPassword: ${SshPassword}
+ Elastic_Wazuh: ${ElasticWazuhVersion}
+ WazuhApiAdminUsername: ${WazuhApiAdminUsername}
+ WazuhApiAdminPassword: ${WazuhApiAdminPassword}
+ WazuhApiPort: ${WazuhApiPort}
+ WazuhServerPort: ${WazuhServerPort}
+ WazuhRegistrationPort: ${WazuhRegistrationPort}
+ WazuhRegistrationPassword: ${WazuhRegistrationPassword}
+ WazuhClusterKey: ${WazuhClusterKey}
+ InstallType: ${InstallType}
+ mode: '000600'
+ owner: root
+ group: root
+ /tmp/wazuh_cf_master.sh:
+ source: !Sub >-
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/production/wazuh/cluster/wazuh_cf_master.sh
+ mode: '000700'
+ owner: root
+ group: root
+ WazuhInstall:
+ commands:
+ 01_RunInstallationScript:
+ command: /tmp/wazuh_cf_master.sh
+ Properties:
+ ImageId: !FindInMap
+ - "RegionMap"
+ - Ref: "AWS::Region"
+ - HVM64
+ InstanceType: !Ref WazuhInstanceType
+ IamInstanceProfile: !Ref InstanceProfile
+ KeyName: !Ref KeyPairName
+ BlockDeviceMappings:
+ - DeviceName: /dev/xvda
+ Ebs:
+ VolumeSize: 50
+ VolumeType: gp2
+ NetworkInterfaces:
+ - AssociatePublicIpAddress: "true"
+ DeviceIndex: "0"
+ GroupSet:
+ - Ref: "WazuhSecurityGroup"
+ SubnetId:
+ Ref: "SubnetWazuh"
+ Tags:
+ - Key: Name
+ Value: WazuhMaster
+ UserData:
+ Fn::Base64: !Sub |
+ #!/bin/bash -xe
+ /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WazuhMasterInstance --configsets WazuhInstallationSet --region ${AWS::Region}
+ /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WazuhMasterInstance --region ${AWS::Region}
+ DependsOn: GatewayToInternet
+ WazuhMasterEth0:
+ Type: AWS::EC2::NetworkInterface
+ Properties:
+ SubnetId: !Ref SubnetWazuh
+ GroupSet: [!Ref 'WazuhSecurityGroup']
+ WazuhMasterEIP:
+ Type: AWS::EC2::EIP
+ Properties:
+ Domain: vpc
+ Tags:
+ - Key: Name
+ Value: !Sub 'MasterEIP-${AWS::StackName}'
+ WazuhMasterEIPAssociation:
+ Type: 'AWS::EC2::EIPAssociation'
+ Properties:
+ NetworkInterfaceId: !Ref WazuhMasterEth0
+ AllocationId: !GetAtt
+ - WazuhMasterEIP
+ - AllocationId
+
+ # Wazuh worker instance
+ WazuhWorkerInstance:
+ Type: AWS::EC2::Instance
+ Metadata:
+ 'AWS::CloudFormation::Init':
+ configSets:
+ WazuhInstallationSet:
+ - WazuhFiles
+ - WazuhInstall
+ WazuhFiles:
+ files:
+ /tmp/wazuh_cf_settings:
+ content: !Sub |
+ SshUsername: ${SshUsername}
+ SshPassword: ${SshPassword}
+ Elastic_Wazuh: ${ElasticWazuhVersion}
+ WazuhServerPort: ${WazuhServerPort}
+ WazuhClusterKey: ${WazuhClusterKey}
+ WazuhMasterIP: ${WazuhMasterInstance.PrivateIp}
+ InstallType: ${InstallType}
+ mode: '000600'
+ owner: root
+ group: root
+ /tmp/wazuh_cf_worker.sh:
+ source: !Sub >-
+ https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/v3.12.2_7.6.2/production/wazuh/cluster/wazuh_cf_worker.sh
+ mode: '000700'
+ owner: root
+ group: root
+ WazuhInstall:
+ commands:
+ 01_RunInstallationScript:
+ command: /tmp/wazuh_cf_worker.sh
+ Properties:
+ ImageId: !FindInMap
+ - "RegionMap"
+ - Ref: "AWS::Region"
+ - HVM64
+ InstanceType: !Ref WazuhInstanceType
+ IamInstanceProfile: !Ref InstanceProfile
+ KeyName: !Ref KeyPairName
+ BlockDeviceMappings:
+ - DeviceName: /dev/xvda
+ Ebs:
+ VolumeSize: 50
+ VolumeType: gp2
+ NetworkInterfaces:
+ - NetworkInterfaceId: !Ref WazuhWorkerEth0
+ DeviceIndex: 0
+ Tags:
+ - Key: Name
+ Value: WazuhWorker
+ UserData:
+ Fn::Base64: !Sub |
+ #!/bin/bash -xe
+ /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WazuhWorkerInstance --configsets WazuhInstallationSet --region ${AWS::Region}
+ /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WazuhWorkerInstance --region ${AWS::Region}
+ DependsOn: GatewayToInternet
+ WazuhWorkerEth0:
+ Type: AWS::EC2::NetworkInterface
+ Properties:
+ SubnetId: !Ref SubnetWazuh
+ GroupSet: [!Ref 'WazuhSecurityGroup']
+ WazuhWorkerEIP:
+ Type: AWS::EC2::EIP
+ Properties:
+ Domain: vpc
+ Tags:
+ - Key: Name
+ Value: !Sub 'WorkerEIP-${AWS::StackName}'
+ WazuhWorkerEIPAssociation:
+ Type: 'AWS::EC2::EIPAssociation'
+ Properties:
+ NetworkInterfaceId: !Ref WazuhWorkerEth0
+ AllocationId: !GetAtt
+ - WazuhWorkerEIP
+ - AllocationId
+Outputs:
+ ElasticBootstrapIp:
+ Description: Elastic Bootstrap IP
+ Value: !GetAtt
+ - ElasticBootstrap
+ - PublicIp
+ ElasticMasterB:
+ Description: Elastic masterB IP
+ Value: !GetAtt
+ - ElasticMasterB
+ - PublicIp
+ ElasticMasterC:
+ Description: Elastic masterC IP
+ Value: !GetAtt
+ - ElasticMasterC
+ - PublicIp
+ WazuhMasterInstance:
+ Description: Wazuh master IP
+ Value: !GetAtt
+ - WazuhMasterInstance
+ - PublicIp
+ WazuhWorkerInstance:
+ Description: Wazuh worker IP
+ Value: !GetAtt
+ - WazuhWorkerInstance
+ - PublicIp
+ KibanaInstance:
+ Description: Kibana instance IP
+ Value: !GetAtt
+ - KibanaInstance
+ - PublicIp
+ ElasticBootstrapDNS:
+ Description: Elastic Bootstrap DNS
+ Value: !Ref ElasticBootstrapRecord
+ Condition: EnableDNSRecords
+ ElasticMasterBDNS:
+ Description: Elastic master B DNS
+ Value: !Ref ElasticMasterBRecord
+ Condition: EnableDNSRecords
+ ElasticMasterCDNS:
+ Description: Elastic master C IP
+ Value: !Ref ElasticMasterCRecord
+ Condition: EnableDNSRecords
+ WazuhMasterInstanceDNS:
+ Description: Wazuh Master DNS
+ Value: !Ref WazuhMasterInstanceRecord
+ Condition: EnableDNSRecords
+ WazuhWorkerInstanceDNS:
+ Description: Wazuh Worker DNS
+ Value: !Ref WazuhWorkerInstanceRecord
+ Condition: EnableDNSRecords
+ KibanaInstanceDNS:
+ Description: Kibana instance DNS
+ Value: !Ref KibanaInstanceRecord
+ Condition: EnableDNSRecords
+ LoadBalancerDNS:
+ Description: Load balancer DNS
+ Value: !Ref LbRecord
+ Condition: EnableDNSRecords