Begin of restructuring ...

- deprecate old release
- set virtual version
- we need tpot user / group, adding to installer
- tweaking
- do not use the dev branch, it will break stuff
This commit is contained in:
Marco Ochse
2023-06-13 23:59:09 +02:00
parent c807c7cd17
commit 2c4eaf0794
159 changed files with 6534 additions and 156 deletions

10
_deprecated/cloud/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Ansible
*.retry
# Terraform
**/.terraform
**/terraform.*
# OpenStack clouds
**/clouds.yaml
**/secure.yaml

View File

@ -0,0 +1,257 @@
# T-Pot Ansible
Here you can find a ready-to-use solution for your automated T-Pot deployment using [Ansible](https://www.ansible.com/).
It consists of an Ansible Playbook with multiple roles, which is reusable for all [OpenStack](https://www.openstack.org/) based clouds (e.g. Open Telekom Cloud, Orange Cloud, Telefonica Open Cloud, OVH) out of the box.
Apart from that you can easily adapt the deploy role to use other [cloud providers](https://docs.ansible.com/ansible/latest/scenario_guides/cloud_guides.html). Check out [Ansible Galaxy](https://galaxy.ansible.com/search?keywords=&order_by=-relevance&page=1&deprecated=false&type=collection&tags=cloud) for more cloud collections.
The Playbook first creates all resources (security group, network, subnet, router), deploys one (or more) new servers and then installs and configures T-Pot on them.
This example showcases the deployment on our own OpenStack based Public Cloud Offering [Open Telekom Cloud](https://open-telekom-cloud.com/en).
# Table of contents
- [Preparation of Ansible Master](#ansible-master)
- [Ansible Installation](#ansible)
- [OpenStack Collection Installation](#collection)
- [Agent Forwarding](#agent-forwarding)
- [Preparations in Open Telekom Cloud Console](#preparation)
- [Create new project](#project)
- [Create API user](#api-user)
- [Import Key Pair](#key-pair)
- [Clone Git Repository](#clone-git)
- [Settings and recommended values](#settings)
- [clouds.yaml](#clouds-yaml)
- [Ansible remote user](#remote-user)
- [Number of instances to deploy](#number)
- [Instance settings](#instance-settings)
- [User password](#user-password)
- [Configure `tpot.conf.dist`](#tpot-conf)
- [Optional: Custom `ews.cfg`](#ews-cfg)
- [Optional: Custom HPFEEDS](#hpfeeds)
- [Deploying a T-Pot](#deploy)
- [Further documentation](#documentation)
<a name="ansible-master"></a>
# Preparation of Ansible Master
You can either run the Ansible Playbook locally on your Linux or macOS machine or you can use an ECS (Elastic Cloud Server) on Open Telekom Cloud, which I did.
I used Ubuntu 18.04 for my Ansible Master Server, but other OSes are fine too.
Ansible works over the SSH Port, so you don't have to add any special rules to your Security Group.
<a name="ansible"></a>
## Ansible Installation
:warning: Ansible 2.10 or newer is required!
Example for Ubuntu 18.04:
At first we update the system:
`sudo apt update`
`sudo apt dist-upgrade`
Then we need to add the repository and install Ansible:
`sudo apt-add-repository --yes --update ppa:ansible/ansible`
`sudo apt install ansible`
For other OSes and Distros have a look at the official [Ansible Documentation](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html).
If your OS does not offer a recent version of Ansible (>= 2.10) you should consider [installing Ansible with pip](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-ansible-with-pip).
In short (if you already have Python3/pip3 installed):
```
pip3 install ansible
```
<a name="collection"></a>
## OpenStack Collection Installation
For interacting with OpenStack resources in Ansible, you need to install the collection from Ansible Galaxy:
`ansible-galaxy collection install openstack.cloud`
<a name="agent-forwarding"></a>
## Agent Forwarding
If you run the Ansible Playbook remotely on your Ansible Master Server, Agent Forwarding must be enabled in order to let Ansible connect to newly created machines.
- On Linux or macOS:
- Create or edit `~/.ssh/config`
```
Host ANSIBLE_MASTER_IP
ForwardAgent yes
```
- On Windows using Putty:
![Putty Agent Forwarding](doc/putty_agent_forwarding.png)
<a name="preparation"></a>
# Preparations in Open Telekom Cloud Console
(You can skip this if you have already set up a project and an API account with key pair)
(Just make sure you know the naming for everything, as you need to configure the Ansible variables.)
Before we can start deploying, we have to prepare the Open Telekom Cloud tenant.
For that, go to the [Web Console](https://auth.otc.t-systems.com/authui/login) and log in with an admin user.
<a name="project"></a>
## Create new project
I strongly advise you to create a separate project for the T-Pots in your tenant.
In my case I named it `tpot`.
![Create new project](doc/otc_1_project.gif)
<a name="api-user"></a>
## Create API user
The next step is to create a new user account, which is restricted to the project.
This ensures that the API access is limited to that project.
![Create API user](doc/otc_2_user.gif)
<a name="key-pair"></a>
## Import Key Pair
:warning: Now log in with the newly created API user account and select your project.
![Login as API user](doc/otc_3_login.gif)
Import your SSH public key.
![Import SSH Public Key](doc/otc_4_import_key.gif)
<a name="clone-git"></a>
# Clone Git Repository
Clone the `tpotce` repository to your Ansible Master:
`git clone https://github.com/telekom-security/tpotce.git`
All Ansible related files are located in the [`cloud/ansible/openstack`](openstack) folder.
<a name="settings"></a>
# Settings and recommended values
You can configure all aspects of your Elastic Cloud Server and T-Pot before using the Playbook:
<a name="clouds-yaml"></a>
## clouds.yaml
Located at [`openstack/clouds.yaml`](openstack/clouds.yaml).
Enter your Open Telekom Cloud API user credentials here (username, password, project name, user domain name):
```
clouds:
open-telekom-cloud:
profile: otc
auth:
project_name: eu-de_your_project
username: your_api_user
password: your_password
user_domain_name: OTC-EU-DE-000000000010000XXXXX
```
You can also perform different authentication methods like sourcing OpenStack OS_* environment variables or providing an inline dictionary.
For more information have a look in the [openstack.cloud.server](https://docs.ansible.com/ansible/latest/collections/openstack/cloud/server_module.html) Ansible module documentation.
If you already have your own `clouds.yaml` file or have multiple clouds in there, you can specify which one to use in the `openstack/my_os_cloud.yaml` file:
```
# Enter the name of your cloud to use from clouds.yaml
cloud: open-telekom-cloud
```
<a name="remote-user"></a>
## Ansible remote user
You may have to adjust the `remote_user` in the Ansible Playbook under [`openstack/deploy_tpot.yaml`](openstack/deploy_tpot.yaml) depending on your Debian base image (e.g. on Open Telekom Cloud the default Debian user is `linux`).
<a name="number"></a>
## Number of instances to deploy
You can adjust the number of VMs/T-Pots that you want to create in [`openstack/deploy_tpot.yaml`](openstack/deploy_tpot.yaml):
```
loop: "{{ range(0, 1) }}"
```
One instance is set as the default, increase to your liking.
<a name="instance-settings"></a>
## Instance settings
Located at [`openstack/roles/create_vm/vars/main.yaml`](openstack/roles/create_vm/vars/main.yaml).
Here you can customize your virtual machine specifications:
- Choose an availability zone. For Open Telekom Cloud reference see [here](https://docs.otc.t-systems.com/en-us/endpoint/index.html).
- Change the OS image (For T-Pot we need Debian)
- (Optional) Change the volume size
- Specify your key pair (:warning: Mandatory)
- (Optional) Change the instance type (flavor)
`s3.medium.8` corresponds to 1 vCPU and 8GB of RAM and is the minimum required flavor.
A full list of Open Telekom Cloud flavors can be found [here](https://docs.otc.t-systems.com/en-us/usermanual/ecs/en-us_topic_0177512565.html).
```
availability_zone: eu-de-03
image: Standard_Debian_10_latest
volume_size: 128
key_name: your-KeyPair
flavor: s3.medium.8
```
<a name="user-password"></a>
## User password
Located at [`openstack/roles/install/vars/main.yaml`](openstack/roles/install/vars/main.yaml).
Here you can set the password for your Debian user (**you should definitely change that**).
```
user_password: LiNuXuSeRPaSs#
```
<a name="tpot-conf"></a>
## Configure `tpot.conf.dist`
The file is located in [`iso/installer/tpot.conf.dist`](/iso/installer/tpot.conf.dist).
Here you can choose:
- between the various T-Pot editions
- a username for the web interface
- a password for the web interface (**you should definitely change that**)
<a name="ews-cfg"></a>
## Optional: Custom `ews.cfg`
Enable this by uncommenting the role in the [deploy_tpot.yaml](openstack/deploy_tpot.yaml) playbook.
```
# - custom_ews
```
You can use a custom config file for `ewsposter`.
e.g. when you have your own credentials for delivering data to our [Sicherheitstacho](https://sicherheitstacho.eu/start/main).
You can find the `ews.cfg` template file here: [`openstack/roles/custom_ews/templates/ews.cfg`](openstack/roles/custom_ews/templates/ews.cfg) and adapt it for your needs.
For setting custom credentials, these settings would be relevant for you (the rest of the file can stay as is):
```
[MAIN]
...
contact = your_email_address
...
[EWS]
...
username = your_username
token = your_token
...
```
<a name="hpfeeds"></a>
## Optional: Custom HPFEEDS
Enable this by uncommenting the role in the [deploy_tpot.yaml](openstack/deploy_tpot.yaml) playbook.
```
# - custom_hpfeeds
```
You can specify custom HPFEEDS in [`openstack/roles/custom_hpfeeds/files/hpfeeds.cfg`](openstack/roles/custom_hpfeeds/files/hpfeeds.cfg).
That file contains the defaults (turned off) and you can adapt it for your needs, e.g. for SISSDEN:
```
myENABLE=true
myHOST=hpfeeds.sissden.eu
myPORT=10000
myCHANNEL=t-pot.events
myCERT=/opt/ewsposter/sissden.pem
myIDENT=your_user
mySECRET=your_secret
myFORMAT=json
```
<a name="deploy"></a>
# Deploying a T-Pot :honey_pot::honeybee:
Now, after configuring everything, we can finally start deploying T-Pots!
Go to the [`openstack`](openstack) folder and run the Ansible Playbook with:
`ansible-playbook deploy_tpot.yaml`
(Yes, it is as easy as that :smile:)
If you are running on a machine which asks for a sudo password, you can use:
`ansible-playbook --ask-become-pass deploy_tpot.yaml`
The Playbook will first install required packages on the Ansible Master and then deploy one (or more) new server instances.
After that, T-Pot gets installed and configured on them, optionally custom configs are applied and finally it reboots.
Once this is done, you can proceed with connecting/logging in to the T-Pot according to the [documentation](https://github.com/telekom-security/tpotce#ssh-and-web-access).
<a name="documentation"></a>
# Further documentation
- [Ansible Documentation](https://docs.ansible.com/ansible/latest/)
- [openstack.cloud.server Create/Delete Compute Instances from OpenStack](https://docs.ansible.com/ansible/latest/collections/openstack/cloud/server_module.html)
- [Open Telekom Cloud Help Center](https://docs.otc.t-systems.com/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,6 @@
[defaults]
host_key_checking = false
[ssh_connection]
scp_if_ssh = true
ssh_args = -o ServerAliveInterval=60

View File

@ -0,0 +1,30 @@
- name: Check host prerequisites
hosts: localhost
become: yes
roles:
- check
- name: Deploy instances
hosts: localhost
vars_files: my_os_cloud.yaml
tasks:
- name: Create security group and network
ansible.builtin.include_role:
name: create_net
- name: Create one or more instances
ansible.builtin.include_role:
name: create_vm
loop: "{{ range(0, 1) }}"
loop_control:
extended: yes
- name: Install T-Pot
hosts: tpot
remote_user: linux
become: yes
gather_facts: no
roles:
- install
# - custom_ews
# - custom_hpfeeds
- reboot

View File

@ -0,0 +1,2 @@
# Enter the name of your cloud to use from clouds.yaml
cloud: open-telekom-cloud

View File

@ -0,0 +1,2 @@
collections:
- name: openstack.cloud

View File

@ -0,0 +1,19 @@
- name: Install dependencies
ansible.builtin.package:
name:
- gcc
- python3-dev
- python3-setuptools
- python3-pip
state: present
- name: Install openstacksdk
ansible.builtin.pip:
name: openstacksdk
executable: pip3
- name: Check if agent forwarding is enabled
ansible.builtin.fail:
msg: Please enable agent forwarding to allow Ansible to connect to the remote host!
ignore_errors: yes
failed_when: lookup('env','SSH_AUTH_SOCK') == ""

View File

@ -0,0 +1,33 @@
- name: Create security group
openstack.cloud.security_group:
cloud: "{{ cloud }}"
name: sg-tpot-ansible
description: Security Group for T-Pot
- name: Add rules to security group
openstack.cloud.security_group_rule:
cloud: "{{ cloud }}"
security_group: sg-tpot-ansible
remote_ip_prefix: 0.0.0.0/0
- name: Create network
openstack.cloud.network:
cloud: "{{ cloud }}"
name: network-tpot-ansible
- name: Create subnet
openstack.cloud.subnet:
cloud: "{{ cloud }}"
network_name: network-tpot-ansible
name: subnet-tpot-ansible
cidr: 192.168.0.0/24
dns_nameservers:
- 100.125.4.25
- 100.125.129.199
- name: Create router
openstack.cloud.router:
cloud: "{{ cloud }}"
name: router-tpot-ansible
interfaces:
- subnet-tpot-ansible

View File

@ -0,0 +1,24 @@
- name: Generate T-Pot name
ansible.builtin.set_fact:
tpot_name: "t-pot-ansible-{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=6') }}"
- name: Create instance {{ ansible_loop.index }} of {{ ansible_loop.length }}
openstack.cloud.server:
cloud: "{{ cloud }}"
name: "{{ tpot_name }}"
availability_zone: "{{ availability_zone }}"
image: "{{ image }}"
boot_from_volume: yes
volume_size: "{{ volume_size }}"
key_name: "{{ key_name }}"
auto_ip: yes
flavor: "{{ flavor }}"
security_groups: sg-tpot-ansible
network: network-tpot-ansible
register: tpot
- name: Add instance to inventory
ansible.builtin.add_host:
hostname: "{{ tpot_name }}"
ansible_host: "{{ tpot.server.public_v4 }}"
groups: tpot

View File

@ -0,0 +1,5 @@
availability_zone: eu-de-03
image: Standard_Debian_10_latest
volume_size: 128
key_name: your-KeyPair
flavor: s3.medium.8

View File

@ -0,0 +1,13 @@
- name: Copy ews configuration file
ansible.builtin.template:
src: ews.cfg
dest: /data/ews/conf
owner: root
group: root
mode: 0644
- name: Patching tpot.yml with custom ews configuration file
ansible.builtin.lineinfile:
path: /opt/tpot/etc/tpot.yml
insertafter: "/opt/ewsposter/ews.ip"
line: " - /data/ews/conf/ews.cfg:/opt/ewsposter/ews.cfg"

View File

@ -0,0 +1,137 @@
[MAIN]
homedir = /opt/ewsposter/
spooldir = /opt/ewsposter/spool/
logdir = /opt/ewsposter/log/
del_malware_after_send = false
send_malware = true
sendlimit = 500
contact = your_email_address
proxy =
ip =
[EWS]
ews = true
username = your_username
token = your_token
rhost_first = https://community.sicherheitstacho.eu/ews-0.1/alert/postSimpleMessage
rhost_second = https://community.sicherheitstacho.eu/ews-0.1/alert/postSimpleMessage
ignorecert = false
[HPFEED]
hpfeed = %(EWS_HPFEEDS_ENABLE)s
host = %(EWS_HPFEEDS_HOST)s
port = %(EWS_HPFEEDS_PORT)s
channels = %(EWS_HPFEEDS_CHANNELS)s
ident = %(EWS_HPFEEDS_IDENT)s
secret= %(EWS_HPFEEDS_SECRET)s
# path/to/certificate for tls broker - or "false" for non-tls broker
tlscert = %(EWS_HPFEEDS_TLSCERT)s
# hpfeeds submission format: "ews" (xml) or "json"
hpfformat = %(EWS_HPFEEDS_FORMAT)s
[EWSJSON]
json = false
jsondir = /data/ews/json/
[GLASTOPFV3]
glastopfv3 = true
nodeid = glastopfv3-{{ ansible_hostname }}
sqlitedb = /data/glastopf/db/glastopf.db
malwaredir = /data/glastopf/data/files/
[GLASTOPFV2]
glastopfv2 = false
nodeid =
mysqlhost =
mysqldb =
mysqluser =
mysqlpw =
malwaredir =
[KIPPO]
kippo = false
nodeid =
mysqlhost =
mysqldb =
mysqluser =
mysqlpw =
malwaredir =
[COWRIE]
cowrie = true
nodeid = cowrie-{{ ansible_hostname }}
logfile = /data/cowrie/log/cowrie.json
[DIONAEA]
dionaea = true
nodeid = dionaea-{{ ansible_hostname }}
malwaredir = /data/dionaea/binaries/
sqlitedb = /data/dionaea/log/dionaea.sqlite
[HONEYTRAP]
honeytrap = true
nodeid = honeytrap-{{ ansible_hostname }}
newversion = true
payloaddir = /data/honeytrap/attacks/
attackerfile = /data/honeytrap/log/attacker.log
[RDPDETECT]
rdpdetect = false
nodeid =
iptableslog =
targetip =
[EMOBILITY]
eMobility = false
nodeid = emobility-{{ ansible_hostname }}
logfile = /data/emobility/log/centralsystemEWS.log
[CONPOT]
conpot = true
nodeid = conpot-{{ ansible_hostname }}
logfile = /data/conpot/log/conpot*.json
[ELASTICPOT]
elasticpot = true
nodeid = elasticpot-{{ ansible_hostname }}
logfile = /data/elasticpot/log/elasticpot.log
[SURICATA]
suricata = true
nodeid = suricata-{{ ansible_hostname }}
logfile = /data/suricata/log/eve.json
[MAILONEY]
mailoney = true
nodeid = mailoney-{{ ansible_hostname }}
logfile = /data/mailoney/log/commands.log
[RDPY]
rdpy = true
nodeid = rdpy-{{ ansible_hostname }}
logfile = /data/rdpy/log/rdpy.log
[VNCLOWPOT]
vnclowpot = true
nodeid = vnclowpot-{{ ansible_hostname }}
logfile = /data/vnclowpot/log/vnclowpot.log
[HERALDING]
heralding = true
nodeid = heralding-{{ ansible_hostname }}
logfile = /data/heralding/log/auth.csv
[CISCOASA]
ciscoasa = true
nodeid = ciscoasa-{{ ansible_hostname }}
logfile = /data/ciscoasa/log/ciscoasa.log
[TANNER]
tanner = true
nodeid = tanner-{{ ansible_hostname }}
logfile = /data/tanner/log/tanner_report.json
[GLUTTON]
glutton = true
nodeid = glutton-{{ ansible_hostname }}
logfile = /data/glutton/log/glutton.log

View File

@ -0,0 +1,8 @@
myENABLE=false
myHOST=host
myPORT=port
myCHANNEL=channels
myCERT=false
myIDENT=user
mySECRET=secret
myFORMAT=json

View File

@ -0,0 +1,12 @@
- name: Copy hpfeeds configuration file
ansible.builtin.copy:
src: hpfeeds.cfg
dest: /data/ews/conf
owner: tpot
group: tpot
mode: 0770
register: config
- name: Applying hpfeeds settings
ansible.builtin.command: /opt/tpot/bin/hpfeeds_optin.sh --conf=/data/ews/conf/hpfeeds.cfg
when: config.changed == true

View File

@ -0,0 +1,48 @@
- name: Waiting for SSH connection
ansible.builtin.wait_for_connection:
- name: Gathering facts
ansible.builtin.setup:
- name: Cloning T-Pot install directory
ansible.builtin.git:
repo: "https://github.com/telekom-security/tpotce.git"
dest: /root/tpot
- name: Prepare to set user password
ansible.builtin.set_fact:
user_name: "{{ ansible_user }}"
user_salt: "s0mew1ck3dTpoT"
no_log: true
- name: Changing password for user {{ user_name }}
ansible.builtin.user:
name: "{{ ansible_user }}"
password: "{{ user_password | password_hash('sha512', user_salt) }}"
state: present
shell: /bin/bash
- name: Copy T-Pot configuration file
ansible.builtin.copy:
src: ../../../../../../iso/installer/tpot.conf.dist
dest: /root/tpot.conf
owner: root
group: root
mode: 0644
- name: Install T-Pot on instance - be patient, this might take 15 to 30 minutes depending on the connection speed.
ansible.builtin.command: /root/tpot/iso/installer/install.sh --type=auto --conf=/root/tpot.conf
- name: Delete T-Pot configuration file
ansible.builtin.file:
path: /root/tpot.conf
state: absent
- name: Change unattended-upgrades to take default action
ansible.builtin.blockinfile:
dest: /etc/apt/apt.conf.d/50unattended-upgrades
block: |
Dpkg::Options {
"--force-confdef";
"--force-confold";
}

View File

@ -0,0 +1 @@
user_password: LiNuXuSeRPaSs#

View File

@ -0,0 +1,16 @@
- name: Finally rebooting T-Pot
ansible.builtin.command: shutdown -r now
async: 1
poll: 0
- name: Next login options
ansible.builtin.debug:
msg:
- "***** SSH Access:"
- "***** ssh {{ ansible_user }}@{{ ansible_host }} -p 64295"
- ""
- "***** Web UI:"
- "***** https://{{ ansible_host }}:64297"
- ""
- "***** Admin UI:"
- "***** https://{{ ansible_host }}:64294"

View File

@ -0,0 +1,129 @@
# T-Pot Terraform
This [Terraform](https://www.terraform.io/) configuration can be used to launch a virtual machine, bootstrap any dependencies and install T-Pot in a single step.
Configuration for Amazon Web Services (AWS) and Open Telekom Cloud (OTC) is currently included.
This can easily be extended to support other [Terraform providers](https://registry.terraform.io/browse/providers?category=public-cloud%2Ccloud-automation%2Cinfrastructure).
[Cloud-init](https://cloudinit.readthedocs.io/en/latest/) is used to bootstrap the instance and install T-Pot on startup.
# Table of Contents
- [What get's created](#what-created)
- [Amazon Web Services (AWS)](#what-created-aws)
- [Open Telekom Cloud (OTC)](#what-created-otc)
- [Prerequisites](#pre)
- [Amazon Web Services (AWS)](#pre-aws)
- [Open Telekom Cloud (OTC)](#pre-otc)
- [Terraform Variables](#variables)
- [Common configuration items](#variables-common)
- [Amazon Web Services (AWS)](#variables-aws)
- [Open Telekom Cloud (OTC)](#variables-otc)
- [Initialising](#initialising)
- [Applying the Configuration](#applying)
- [Connecting to the Instance](#connecting)
<a name="what-created"></a>
## What get's created
<a name="what-created-aws"></a>
### Amazon Web Services (AWS)
* EC2 instance:
* t3.large (2 vCPUs, 8 GB RAM)
* 128 GB disk
* Debian 10
* Public IP
* Security Group:
* TCP/UDP ports <= 64000 open to the Internet
* TCP ports 64294, 64295 and 64297 open to a chosen administrative IP
<a name="what-created-otc"></a>
### Open Telekom Cloud (OTC)
* ECS instance:
* s3.medium.8 (1 vCPU, 8 GB RAM)
* 128 GB disk
* Debian 10
* Public EIP
* Security Group
* All TCP/UDP ports are open to the Internet
* Virtual Private Cloud (VPC) and Subnet
<a name="pre"></a>
## Prerequisites
* [Terraform](https://www.terraform.io/) 0.13
<a name="pre-aws"></a>
### Amazon Web Services (AWS)
* AWS Account
* Existing VPC: VPC ID needs to be specified in `aws/variables.tf`
* Existing subnet: Subnet ID needs to be specified in `aws/variables.tf`
* Existing SSH key pair: Key name needs to be specified in `aws/variables.tf`
* AWS Authentication credentials should be [set using environment variables](https://www.terraform.io/docs/providers/aws/index.html#environment-variables)
<a name="pre-otc"></a>
### Open Telekom Cloud (OTC)
* OTC Account
* Existing SSH key pair: Key name needs to be specified in `otc/variables.tf`
* OTC Authentication credentials (Username, Password, Project Name, User Domain Name) can be set in the `otc/clouds.yaml` file
<a name="variables"></a>
## Terraform Variables
<a name="variables-common"></a>
### Common configuration items
These variables exist in `aws/variables.tf` and `otc/variables.tf` respectively.
Settings for cloud-init:
* `timezone` - Set the Server's timezone
* `linux_password`- Set a password for the Linux Operating System user (which is also used on the Admin UI)
Settings for T-Pot:
* `tpot_flavor` - Set the flavor of the T-Pot (Available flavors are listed in the variable's description)
* `web_user` - Set a username for the T-Pot Kibana Dasboard
* `web_password` - Set a password for the T-Pot Kibana Dashboard
<a name="variables-aws"></a>
### Amazon Web Services (AWS)
In `aws/variables.tf`, you can change the additional variables:
* `admin_ip` - source IP address(es) that you will use to administer the system. Connections to TCP ports 64294, 64295 and 64297 will be allowed from this IP only. Multiple IPs or CIDR blocks can be specified in the format: `["127.0.0.1/32", "192.168.0.0/24"]`
* `ec2_vpc_id` - Specify an existing VPC ID
* `ec2_subnet_id` - Specify an existing Subnet ID
* `ec2_region`
* `ec2_ssh_key_name` - Specify an existing SSH key pair
* `ec2_instance_type`
<a name="variables-otc"></a>
### Open Telekom Cloud (OTC)
In `otc/variables.tf`, you can change the additional variables:
* `ecs_flavor`
* `ecs_disk_size`
* `availability_zone`
* `key_pair` - Specify an existing SSH key pair
* `eip_size`
... and some more, but these are the most relevant.
<a name="initialising"></a>
## Initialising
The [`terraform init`](https://www.terraform.io/docs/commands/init.html) command is used to initialize a working directory containing Terraform configuration files.
```
$ cd aws
$ terraform init
```
OR
```
$ cd otc
$ terraform init
```
<a name="applying"></a>
## Applying the Configuration
The [`terraform apply`](https://www.terraform.io/docs/commands/apply.html) command is used to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a [`terraform plan`](https://www.terraform.io/docs/commands/plan.html) execution plan.
```
$ terraform apply
```
This will create your infrastructure and start a Cloud Server. On startup, the Server gets bootstrapped with cloud-init and will install T-Pot. Once this is done, the server will reboot.
If you want the remove the built infrastructure, you can run [`terraform destroy`](https://www.terraform.io/docs/commands/destroy.html) to delete it.
<a name="connecting"></a>
## Connecting to the Instance
When the installation is completed, you can proceed with connecting/logging in to the T-Pot according to the [documentation](https://github.com/telekom-security/tpotce#ssh-and-web-access).

View File

@ -0,0 +1,20 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "3.26.0"
constraints = "3.26.0"
hashes = [
"h1:0i78FItlPeiomd+4ThZrtm56P5K33k7/6dnEe4ZePI0=",
"zh:26043eed36d070ca032cf04bc980c654a25821a8abc0c85e1e570e3935bbfcbb",
"zh:2fe68f3f78d23830a04d7fac3eda550eef1f627dfc130486f70a65dc5c254300",
"zh:3d66484c608c64678e639db25d63872783ce60363a1246e30317f21c9c23b84b",
"zh:46ffd755cfd4cf94fe66342797b5afdcef010a24e126c67fee141b357d393535",
"zh:5e96f24357e945c9067cf5e032ad1d003609629c956c2f9f642fefe714e74587",
"zh:60c27aca36bb63bf3e865c2193be80ca83b376581d00f9c220af4b013e163c4d",
"zh:896f0f22d19d41e71b22f9240b261714c3915b165ddefeb771e7734d69dc47ea",
"zh:90de9966cb2fd3e2f326df291595e55d2dd2d90e7d6dd085c2c8691dce82bdb4",
"zh:ad05a91a88ceb1d6de5a568f7cc0b0e5bc0a79f3da70bc28c1e7f3750e362d58",
"zh:e8c63f59c6465329e1f3357498face3dd7ef10a033df3c366a33aa9e94b46c01",
]
}

View File

@ -0,0 +1,66 @@
provider "aws" {
region = var.ec2_region
}
resource "aws_security_group" "tpot" {
name = "T-Pot"
description = "T-Pot Honeypot"
vpc_id = var.ec2_vpc_id
ingress {
from_port = 0
to_port = 64000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 0
to_port = 64000
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 64294
to_port = 64294
protocol = "tcp"
cidr_blocks = var.admin_ip
}
ingress {
from_port = 64295
to_port = 64295
protocol = "tcp"
cidr_blocks = var.admin_ip
}
ingress {
from_port = 64297
to_port = 64297
protocol = "tcp"
cidr_blocks = var.admin_ip
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "T-Pot"
}
}
resource "aws_instance" "tpot" {
ami = var.ec2_ami[var.ec2_region]
instance_type = var.ec2_instance_type
key_name = var.ec2_ssh_key_name
subnet_id = var.ec2_subnet_id
tags = {
Name = "T-Pot Honeypot"
}
root_block_device {
volume_type = "gp2"
volume_size = 128
delete_on_termination = true
}
user_data = templatefile("../cloud-init.yaml", { timezone = var.timezone, password = var.linux_password, tpot_flavor = var.tpot_flavor, web_user = var.web_user, web_password = var.web_password })
vpc_security_group_ids = [aws_security_group.tpot.id]
associate_public_ip_address = true
}

View File

@ -0,0 +1,12 @@
output "Admin_UI" {
value = "https://${aws_instance.tpot.public_dns}:64294/"
}
output "SSH_Access" {
value = "ssh -i {private_key_file} -p 64295 admin@${aws_instance.tpot.public_dns}"
}
output "Web_UI" {
value = "https://${aws_instance.tpot.public_dns}:64297/"
}

View File

@ -0,0 +1,93 @@
variable "admin_ip" {
default = ["127.0.0.1/32"]
description = "admin IP addresses in CIDR format"
}
variable "ec2_vpc_id" {
description = "ID of AWS VPC"
default = "vpc-XXX"
}
variable "ec2_subnet_id" {
description = "ID of AWS VPC subnet"
default = "subnet-YYY"
}
variable "ec2_region" {
description = "AWS region to launch servers"
default = "eu-west-1"
}
variable "ec2_ssh_key_name" {
default = "default"
}
# https://aws.amazon.com/ec2/instance-types/
# t3.large = 2 vCPU, 8 GiB RAM
variable "ec2_instance_type" {
default = "t3.large"
}
# Refer to https://wiki.debian.org/Cloud/AmazonEC2Image/Bullseye
variable "ec2_ami" {
type = map(string)
default = {
"af-south-1" = "ami-0c372f041acae6d49"
"ap-east-1" = "ami-079b8d011d4655385"
"ap-northeast-1" = "ami-08dbbf1c0485a4aa8"
"ap-northeast-2" = "ami-0269fe7d013b8e2dd"
"ap-northeast-3" = "ami-0848d1e5fb6e3e3da"
"ap-south-1" = "ami-020d429f17c9f1d0a"
"ap-southeast-1" = "ami-09625a221230d9fe6"
"ap-southeast-2" = "ami-03cbc6cddb06af2c2"
"ca-central-1" = "ami-09125623b02302014"
"eu-central-1" = "ami-00c36c60f07e21791"
"eu-north-1" = "ami-052bea934e2d9dbfe"
"eu-south-1" = "ami-04e2bb16d37324719"
"eu-west-1" = "ami-0f87948fe2cf1b2a4"
"eu-west-2" = "ami-02ed1bc837487d535"
"eu-west-3" = "ami-080efd2add7e29430"
"me-south-1" = "ami-0dbde382c834c4a72"
"sa-east-1" = "ami-0a0792814cb068077"
"us-east-1" = "ami-05dd1b6e7ef6f8378"
"us-east-2" = "ami-04dd0542609808c50"
"us-west-1" = "ami-07af5f877b3db9f73"
"us-west-2" = "ami-0d0d8694ba492c02b"
}
}
## cloud-init configuration ##
variable "timezone" {
default = "UTC"
}
variable "linux_password" {
#default = "LiNuXuSeRPaSs#"
description = "Set a password for the default user"
validation {
condition = length(var.linux_password) > 0
error_message = "Please specify a password for the default user."
}
}
## These will go in the generated tpot.conf file ##
variable "tpot_flavor" {
default = "STANDARD"
description = "Specify your tpot flavor [STANDARD, HIVE, HIVE_SENSOR, INDUSTRIAL, LOG4J, MEDICAL, MINI, SENSOR]"
}
variable "web_user" {
default = "webuser"
description = "Set a username for the web user"
}
variable "web_password" {
#default = "w3b$ecret"
description = "Set a password for the web user"
validation {
condition = length(var.web_password) > 0
error_message = "Please specify a password for the web user."
}
}

View File

@ -0,0 +1,9 @@
terraform {
required_version = ">= 0.13"
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.26.0"
}
}
}

View File

@ -0,0 +1,9 @@
provider "aws" {
alias = "eu-west-2"
region = "eu-west-2"
}
provider "aws" {
alias = "us-west-1"
region = "us-west-1"
}

View File

@ -0,0 +1,27 @@
module "eu-west-2" {
source = "./modules/multi-region"
ec2_vpc_id = "vpc-xxxxxxxx"
ec2_subnet_id = "subnet-xxxxxxxx"
ec2_region = "eu-west-2"
tpot_name = "T-Pot Honeypot"
linux_password = var.linux_password
web_password = var.web_password
providers = {
aws = aws.eu-west-2
}
}
module "us-west-1" {
source = "./modules/multi-region"
ec2_vpc_id = "vpc-xxxxxxxx"
ec2_subnet_id = "subnet-xxxxxxxx"
ec2_region = "us-west-1"
tpot_name = "T-Pot Honeypot"
linux_password = var.linux_password
web_password = var.web_password
providers = {
aws = aws.us-west-1
}
}

View File

@ -0,0 +1,69 @@
variable "ec2_vpc_id" {}
variable "ec2_subnet_id" {}
variable "ec2_region" {}
variable "linux_password" {}
variable "web_password" {}
variable "tpot_name" {}
resource "aws_security_group" "tpot" {
name = "T-Pot"
description = "T-Pot Honeypot"
vpc_id = var.ec2_vpc_id
ingress {
from_port = 0
to_port = 64000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 0
to_port = 64000
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 64294
to_port = 64294
protocol = "tcp"
cidr_blocks = var.admin_ip
}
ingress {
from_port = 64295
to_port = 64295
protocol = "tcp"
cidr_blocks = var.admin_ip
}
ingress {
from_port = 64297
to_port = 64297
protocol = "tcp"
cidr_blocks = var.admin_ip
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "T-Pot"
}
}
resource "aws_instance" "tpot" {
ami = var.ec2_ami[var.ec2_region]
instance_type = var.ec2_instance_type
key_name = var.ec2_ssh_key_name
subnet_id = var.ec2_subnet_id
tags = {
Name = var.tpot_name
}
root_block_device {
volume_type = "gp2"
volume_size = 128
delete_on_termination = true
}
user_data = templatefile("../cloud-init.yaml", { timezone = var.timezone, password = var.linux_password, tpot_flavor = var.tpot_flavor, web_user = var.web_user, web_password = var.web_password })
vpc_security_group_ids = [aws_security_group.tpot.id]
associate_public_ip_address = true
}

View File

@ -0,0 +1,12 @@
output "Admin_UI" {
value = "https://${aws_instance.tpot.public_dns}:64294/"
}
output "SSH_Access" {
value = "ssh -i {private_key_file} -p 64295 admin@${aws_instance.tpot.public_dns}"
}
output "Web_UI" {
value = "https://${aws_instance.tpot.public_dns}:64297/"
}

View File

@ -0,0 +1,57 @@
variable "admin_ip" {
default = ["127.0.0.1/32"]
description = "admin IP addresses in CIDR format"
}
variable "ec2_ssh_key_name" {
default = "default"
}
# https://aws.amazon.com/ec2/instance-types/
variable "ec2_instance_type" {
default = "t3.xlarge"
}
# Refer to https://wiki.debian.org/Cloud/AmazonEC2Image/Bullseye
variable "ec2_ami" {
type = map(string)
default = {
"af-south-1" = "ami-0c372f041acae6d49"
"ap-east-1" = "ami-079b8d011d4655385"
"ap-northeast-1" = "ami-08dbbf1c0485a4aa8"
"ap-northeast-2" = "ami-0269fe7d013b8e2dd"
"ap-northeast-3" = "ami-0848d1e5fb6e3e3da"
"ap-south-1" = "ami-020d429f17c9f1d0a"
"ap-southeast-1" = "ami-09625a221230d9fe6"
"ap-southeast-2" = "ami-03cbc6cddb06af2c2"
"ca-central-1" = "ami-09125623b02302014"
"eu-central-1" = "ami-00c36c60f07e21791"
"eu-north-1" = "ami-052bea934e2d9dbfe"
"eu-south-1" = "ami-04e2bb16d37324719"
"eu-west-1" = "ami-0f87948fe2cf1b2a4"
"eu-west-2" = "ami-02ed1bc837487d535"
"eu-west-3" = "ami-080efd2add7e29430"
"me-south-1" = "ami-0dbde382c834c4a72"
"sa-east-1" = "ami-0a0792814cb068077"
"us-east-1" = "ami-05dd1b6e7ef6f8378"
"us-east-2" = "ami-04dd0542609808c50"
"us-west-1" = "ami-07af5f877b3db9f73"
"us-west-2" = "ami-0d0d8694ba492c02b"
}
}
## cloud-init configuration ##
variable "timezone" {
default = "UTC"
}
## These will go in the generated tpot.conf file ##
variable "tpot_flavor" {
default = "STANDARD"
description = "Specify your tpot flavor [STANDARD, HIVE, HIVE_SENSOR, INDUSTRIAL, LOG4J, MEDICAL, MINI, SENSOR]"
}
variable "web_user" {
default = "webuser"
description = "Set a username for the web user"
}

View File

@ -0,0 +1,9 @@
terraform {
required_version = ">= 0.13"
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.72.0"
}
}
}

View File

@ -0,0 +1,7 @@
output "eu-west-2_Web_UI" {
value = module.eu-west-2.Web_UI
}
output "us-west-1_Web_UI" {
value = module.us-west-1.Web_UI
}

View File

@ -0,0 +1,19 @@
variable "linux_password" {
#default = "LiNuXuSeRP4Ss!"
description = "Set a password for the default user"
validation {
condition = length(var.linux_password) > 0
error_message = "Please specify a password for the default user."
}
}
variable "web_password" {
#default = "w3b$ecret20"
description = "Set a password for the web user"
validation {
condition = length(var.web_password) > 0
error_message = "Please specify a password for the web user."
}
}

View File

@ -0,0 +1,26 @@
#cloud-config
timezone: ${timezone}
packages:
- git
runcmd:
- curl -sS --retry 5 https://github.com
- git clone https://github.com/telekom-security/tpotce /root/tpot
- /root/tpot/iso/installer/install.sh --type=auto --conf=/root/tpot.conf
- rm /root/tpot.conf
- /sbin/shutdown -r now
password: ${password}
chpasswd:
expire: false
write_files:
- content: |
# tpot configuration file
myCONF_TPOT_FLAVOR='${tpot_flavor}'
myCONF_WEB_USER='${web_user}'
myCONF_WEB_PW='${web_password}'
owner: root:root
path: /root/tpot.conf
permissions: '0600'

View File

@ -0,0 +1,38 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/random" {
version = "3.1.0"
constraints = "~> 3.1.0"
hashes = [
"h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=",
"zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc",
"zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626",
"zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff",
"zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2",
"zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992",
"zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427",
"zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc",
"zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f",
"zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b",
"zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7",
"zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a",
]
}
provider "registry.terraform.io/opentelekomcloud/opentelekomcloud" {
version = "1.23.6"
constraints = "~> 1.23.4"
hashes = [
"h1:B/1Md957jWaDgFqsJDzmJc75KwL0eC/PCVuZ8HV5xSc=",
"zh:1aa79010869d082157fb44fc83c3bff4e40938ec0ca916f704d974c7f7ca39e4",
"zh:3155b8366828ce50231f69962b55df1e2261ed63c44bb64e2c950dd68769df1b",
"zh:4a909617aa96a6d8aead14f56996ad94e0a1cae9d28e8df1ddae19c2095ed337",
"zh:4f71046719632b4b90f88d29d8ba88915ee6ad66cd9d7ebe84a7459013e5003a",
"zh:67e4d10b2db79ad78ae2ec8d9dfac53c4721028f97f4436a7aa45e80b1beefd3",
"zh:7f12541fc5a3513e5522ff2bd5fee17d1e67bfe64f9ef59d03863fc7389e12ce",
"zh:86fadabfc8307cf6084a412ffc9c797ec94932d08bc663a3fcebf98101e951f6",
"zh:98744b39c2bfe3e8e6f929f750a689971071b257f3f066f669f93c8e0b76d179",
"zh:c363d41debb060804e2c6bd9cb50b4e8daa37362299e3ea74e187265cd85f2ca",
]
}

View File

@ -0,0 +1,68 @@
data "opentelekomcloud_images_image_v2" "debian" {
name = "Standard_Debian_10_latest"
}
resource "opentelekomcloud_networking_secgroup_v2" "secgroup_1" {
name = var.secgroup_name
description = var.secgroup_desc
}
resource "opentelekomcloud_networking_secgroup_rule_v2" "secgroup_rule_1" {
direction = "ingress"
ethertype = "IPv4"
remote_ip_prefix = "0.0.0.0/0"
security_group_id = opentelekomcloud_networking_secgroup_v2.secgroup_1.id
}
resource "opentelekomcloud_vpc_v1" "vpc_1" {
name = var.vpc_name
cidr = var.vpc_cidr
}
resource "opentelekomcloud_vpc_subnet_v1" "subnet_1" {
name = var.subnet_name
cidr = var.subnet_cidr
vpc_id = opentelekomcloud_vpc_v1.vpc_1.id
gateway_ip = var.subnet_gateway_ip
dns_list = ["100.125.4.25", "100.125.129.199"]
}
resource "random_id" "tpot" {
byte_length = 6
prefix = var.ecs_prefix
}
resource "opentelekomcloud_ecs_instance_v1" "ecs_1" {
name = random_id.tpot.b64_url
image_id = data.opentelekomcloud_images_image_v2.debian.id
flavor = var.ecs_flavor
vpc_id = opentelekomcloud_vpc_v1.vpc_1.id
nics {
network_id = opentelekomcloud_vpc_subnet_v1.subnet_1.id
}
system_disk_size = var.ecs_disk_size
system_disk_type = "SAS"
security_groups = [opentelekomcloud_networking_secgroup_v2.secgroup_1.id]
availability_zone = var.availability_zone
key_name = var.key_pair
user_data = templatefile("../cloud-init.yaml", { timezone = var.timezone, password = var.linux_password, tpot_flavor = var.tpot_flavor, web_user = var.web_user, web_password = var.web_password })
}
resource "opentelekomcloud_vpc_eip_v1" "eip_1" {
publicip {
type = "5_bgp"
}
bandwidth {
name = "bandwidth-${random_id.tpot.b64_url}"
size = var.eip_size
share_type = "PER"
}
}
resource "opentelekomcloud_compute_floatingip_associate_v2" "fip_1" {
floating_ip = opentelekomcloud_vpc_eip_v1.eip_1.publicip.0.ip_address
instance_id = opentelekomcloud_ecs_instance_v1.ecs_1.id
}

View File

@ -0,0 +1,11 @@
output "Admin_UI" {
value = "https://${opentelekomcloud_vpc_eip_v1.eip_1.publicip.0.ip_address}:64294"
}
output "SSH_Access" {
value = "ssh -p 64295 linux@${opentelekomcloud_vpc_eip_v1.eip_1.publicip.0.ip_address}"
}
output "Web_UI" {
value = "https://${opentelekomcloud_vpc_eip_v1.eip_1.publicip.0.ip_address}:64297"
}

View File

@ -0,0 +1,3 @@
provider "opentelekomcloud" {
cloud = "open-telekom-cloud"
}

View File

@ -0,0 +1,98 @@
## cloud-init configuration ##
variable "timezone" {
default = "UTC"
}
variable "linux_password" {
#default = "LiNuXuSeRPaSs#"
description = "Set a password for the default user"
validation {
condition = length(var.linux_password) > 0
error_message = "Please specify a password for the default user."
}
}
## Security Group ##
variable "secgroup_name" {
default = "sg-tpot"
}
variable "secgroup_desc" {
default = "Security Group for T-Pot"
}
## Virtual Private Cloud ##
variable "vpc_name" {
default = "vpc-tpot"
}
variable "vpc_cidr" {
default = "192.168.0.0/16"
}
## Subnet ##
variable "subnet_name" {
default = "subnet-tpot"
}
variable "subnet_cidr" {
default = "192.168.0.0/24"
}
variable "subnet_gateway_ip" {
default = "192.168.0.1"
}
## Elastic Cloud Server ##
variable "ecs_prefix" {
default = "tpot-"
}
variable "ecs_flavor" {
default = "s3.medium.8"
}
variable "ecs_disk_size" {
default = "128"
}
variable "availability_zone" {
default = "eu-de-03"
}
variable "key_pair" {
#default = ""
description = "Specify your SSH key pair"
validation {
condition = length(var.key_pair) > 0
error_message = "Please specify a Key Pair."
}
}
## Elastic IP ##
variable "eip_size" {
default = "100"
}
## These will go in the generated tpot.conf file ##
variable "tpot_flavor" {
default = "STANDARD"
description = "Specify your tpot flavor [STANDARD, HIVE, HIVE_SENSOR, INDUSTRIAL, LOG4J, MEDICAL, MINI, SENSOR]"
}
variable "web_user" {
default = "webuser"
description = "Set a username for the web user"
}
variable "web_password" {
#default = "w3b$ecret"
description = "Set a password for the web user"
validation {
condition = length(var.web_password) > 0
error_message = "Please specify a password for the web user."
}
}

View File

@ -0,0 +1,13 @@
terraform {
required_version = ">= 0.13"
required_providers {
opentelekomcloud = {
source = "opentelekomcloud/opentelekomcloud"
version = "~> 1.23.4"
}
random = {
source = "hashicorp/random"
version = "~> 3.1.0"
}
}
}