@@ -57,47 +57,6 @@ resource "null_resource" "bastion_ssh_configure" {
57
57
aws_route_table_association . vpc_bastion_rt_associate
58
58
]
59
59
60
- # Host Private Key apply file permissions
61
- provisioner "remote-exec" {
62
- inline = [
63
- " echo 'Create ${ var . module_var_bastion_user } without sudoer'" ,
64
- " sudo su - root -c 'useradd --create-home ${ var . module_var_bastion_user } '" ,
65
- " sudo su - root -c 'mkdir -p /home/${ var . module_var_bastion_user } /.ssh'" ,
66
- " sudo su - root -c 'touch /home/${ var . module_var_bastion_user } /.ssh/authorized_keys'" ,
67
- " sudo su - root -c 'echo \" ${ var . module_var_bastion_public_ssh_key } \" > /home/${ var . module_var_bastion_user } /.ssh/authorized_keys'" ,
68
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'rhel' ] ; then sudo su - root -c 'chown -R ${ var . module_var_bastion_user } :${ var . module_var_bastion_user } /home/${ var . module_var_bastion_user } /.ssh' ; fi" ,
69
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles_sap' ] ; then sudo su - root -c 'chown -R ${ var . module_var_bastion_user } :users /home/${ var . module_var_bastion_user } /.ssh' ; fi" ,
70
- " sudo su - root -c 'chmod 700 /home/${ var . module_var_bastion_user } /.ssh'" ,
71
- " sudo su - root -c 'chmod 600 /home/${ var . module_var_bastion_user } /.ssh/authorized_keys'" ,
72
- " echo '${ var . module_var_bastion_user } is created'" ,
73
- " echo 'Installing firewalld'" ,
74
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'rhel' ] ; then echo 'RHEL detected, yum install firewalld' && yum --assumeyes --debuglevel=1 install firewalld ; fi" ,
75
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles_sap' ] ; then echo 'SLES detected, zypper install --no-confirm firewalld' && zypper install --no-confirm firewalld ; fi" ,
76
- " echo 'Activate firewalld'" ,
77
- " sudo su - root -c 'systemctl start firewalld'" ,
78
- " sudo su - root -c 'systemctl enable firewalld'" ,
79
- " echo 'Changing SSH Port to within IANA Dynamic Ports range'" ,
80
- " sudo su - root -c 'sed -i \" s/#Port 22/Port ${ var . module_var_bastion_ssh_port } /\" /etc/ssh/sshd_config'" ,
81
- " if [ $(getenforce) = 'Enforcing' ]; then echo 'SELinux status as enforcing/enabled detected, inform SELinux about port change' && sudo su - root -c 'semanage port -a -t ssh_port_t -p tcp ${ var . module_var_bastion_ssh_port } '; fi" ,
82
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'rhel' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '=\" 8') ]; then echo 'RHEL 8.x detected, adding port to firewall-cmd' && sudo su - root -c 'firewall-cmd --add-port ${ var . module_var_bastion_ssh_port } /tcp' && sudo su - root -c 'firewall-cmd --add-port ${ var . module_var_bastion_ssh_port } /tcp --permanent' ; fi" ,
83
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'rhel' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '=\" 8') ]; then echo 'RHEL 8.x detected, amending /etc/ssh/ssh_config to permit AllowTcpForwarding' && sudo su - root -c 'sed -i \" s/#AllowTcpForwarding yes/AllowTcpForwarding yes/\" /etc/ssh/sshd_config' ; fi" ,
84
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles_sap' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '=\" 15') ]; then echo 'SLES 15.x detected, adding port to firewall-cmd' && sudo su - root -c 'firewall-cmd --add-port ${ var . module_var_bastion_ssh_port } /tcp' && sudo su - root -c 'firewall-cmd --add-port ${ var . module_var_bastion_ssh_port } /tcp --permanent' ; fi" ,
85
- " if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\" ') = 'sles_sap' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '=\" 15') ]; then echo 'SLES 15.x detected, amending /etc/ssh/ssh_config to permit AllowTcpForwarding' && sudo su - root -c 'sed -i \" s/#AllowTcpForwarding yes/AllowTcpForwarding yes/\" /etc/ssh/sshd_config' ; fi" ,
86
- " echo 'Removing Root SSH Login for Bastion from Public IP'" ,
87
- " sudo su - root -c 'sed -i \" s/PermitRootLogin yes/PermitRootLogin no/\" /etc/ssh/sshd_config'" ,
88
- " echo 'Allowing only Root SSH Login for Bastion from Private IP range of the VPC Subnet (i.e. login to root on Bastion from Host/s only)'" ,
89
- " sudo su - root -c 'echo \" Match Address ${ data . aws_subnet . vpc_subnet . cidr_block } \" >> /etc/ssh/sshd_config'" ,
90
- " sudo su - root -c 'echo \" PermitRootLogin yes\" >> /etc/ssh/sshd_config'" ,
91
- " echo 'Reload sshd service after sshd_config changes'" ,
92
- " sudo su - root -c 'systemctl restart sshd'" ,
93
- " echo 'SSH Port now listening on...'" ,
94
- " sudo su - root -c 'netstat -tlpn | grep ssh' || echo 'netstat not found, ignoring command'" , // Use else command to avoid Terraform breaking error "executing "/tmp/terraform_xxxxxxxxxx.sh": Process exited with status 1". REPLACE WITH: ss -tunlp | grep ssh
95
- " echo 'Disable ec2-user'" ,
96
- " sudo mv /home/ec2-user/.ssh/authorized_keys /home/ec2-user/.ssh/disabled_keys" ,
97
- " echo 'Disabled the ec2-user'"
98
- ]
99
- }
100
-
101
60
connection {
102
61
type = " ssh"
103
62
user = " ec2-user"
@@ -107,7 +66,153 @@ resource "null_resource" "bastion_ssh_configure" {
107
66
# Required when using RHEL 8.x because /tmp is set with noexec
108
67
# Path must already exist and must not use Bash shell special variable, e.g. cannot use $HOME/terraform/tmp/
109
68
# https://www.terraform.io/language/resources/provisioners/connection#executing-scripts-using-ssh-scp
110
- script_path = " /home/ec2-user/terraform_tmp_remote_exec_inline.sh"
69
+ # script_path = "/home/ec2-user/terraform_tmp_remote_exec_inline.sh"
70
+ }
71
+
72
+ # Path must already exist and must not use Bash shell special variable, e.g. cannot use $HOME/file.sh
73
+ # "By default, OpenSSH's scp implementation runs in the remote user's home directory and so you can specify a relative path to upload into that home directory"
74
+ # https://www.terraform.io/language/resources/provisioners/file#destination-paths
75
+ provisioner "file" {
76
+ destination = " bastion_script.sh"
77
+ content = << EOT
78
+ #!/bin/bash
79
+ echo '---- Sleep 20s to ensure bastion host is ready -----' && sleep 20
80
+
81
+ echo 'Create ${ var . module_var_bastion_user } without sudoer'
82
+ useradd --create-home ${ var . module_var_bastion_user }
83
+ mkdir -p /home/${ var . module_var_bastion_user } /.ssh
84
+
85
+ /bin/cp -f /home/ec2-user/.ssh/authorized_keys /home/${ var . module_var_bastion_user } /.ssh/authorized_keys
86
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'rhel' ]; then chown -R ${ var . module_var_bastion_user } :${ var . module_var_bastion_user } /home/${ var . module_var_bastion_user } /.ssh ; fi
87
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'sles_sap' ]; then chown -R ${ var . module_var_bastion_user } :users /home/${ var . module_var_bastion_user } /.ssh ; fi
88
+ chmod 750 /home/${ var . module_var_bastion_user } /.ssh
89
+ chmod 600 /home/${ var . module_var_bastion_user } /.ssh/authorized_keys
90
+ echo '${ var . module_var_bastion_user } is created'
91
+
92
+ echo 'Changing SSH Port to within IANA Dynamic Ports range'
93
+ sed -i 's/#Port 22/Port ${ var . module_var_bastion_ssh_port } /' /etc/ssh/sshd_config
94
+
95
+ echo 'Enable SSH AllowTcpForwarding'
96
+ sed -i 's/#AllowTcpForwarding yes/AllowTcpForwarding yes/' /etc/ssh/sshd_config
97
+
98
+ echo 'Removing Root SSH Login for Bastion from Public IP'
99
+ sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
100
+ sed -i 's/#PermitRootLogin/PermitRootLogin/' /etc/ssh/sshd_config
101
+ echo 'Allow SSH Login to root user only from the Bastion's private Subnet range (i.e. no root login using Public IP)'
102
+ echo 'Match Address ${ data . aws_subnet . vpc_subnet . cidr_block } ' >> /etc/ssh/sshd_config
103
+ echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
104
+
105
+ echo 'Reload sshd service after sshd_config changes'
106
+ systemctl restart sshd
107
+
108
+ echo 'SSH Port now listening on...'
109
+ # Use else command to avoid Terraform breaking error "executing "/tmp/terraform_xxxxxxxxxx.sh": Process exited with status 1". REPLACE WITH: ss -tunlp | grep ssh
110
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'rhel' ]; then yum --assumeyes --debuglevel=1 install net-tools ; fi
111
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'sles_sap' ]; then zypper install --no-confirm net-tools ; fi
112
+ netstat -tlpn | grep ssh || echo 'netstat not found, ignoring command'
113
+
114
+ echo 'Amending SELinux if present'
115
+ if [ $(getenforce) = 'Enforcing' ]; then echo 'SELinux status as enforcing/enabled detected, inform SELinux about port change' && semanage port -a -t ssh_port_t -p tcp ${ var . module_var_bastion_ssh_port } ; fi
116
+
117
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'rhel' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '="7') ]; then
118
+ echo 'RHEL 7.x detected, use firewalld and iptables'
119
+ echo 'RHEL detected, yum install firewalld'
120
+ yum --assumeyes --debuglevel=1 install firewalld
121
+ echo 'Activate firewalld'
122
+ systemctl start firewalld
123
+ systemctl enable firewalld
124
+ echo 'Allow new SSH Port'
125
+ firewall-cmd --add-port ${ var . module_var_bastion_ssh_port } /tcp
126
+ firewall-cmd --add-port ${ var . module_var_bastion_ssh_port } /tcp --permanent
127
+ firewall-cmd --reload
128
+ # Detection of Primary Network Interface
129
+ # Find network adapter - identify the adapter, by showing which is used for the Default Gateway route
130
+ # If statement to catch RHEL installations with route table multiple default entries
131
+ # https://serverfault.com/questions/47915/how-do-i-get-the-default-gateway-in-linux-given-the-destination
132
+ ACTIVE_NETWORK_ADAPTER=$(ip route show default 0.0.0.0/0 | awk '/default/ && !/metric/ {print $5}')
133
+ CURRENT_IP=$(ip -oneline address show $ACTIVE_NETWORK_ADAPTER | sed -n 's/.*inet \(.*\)\/.*/\1/p')
134
+ # Drop SSH Port 22 and ICMP Ping connection attempts
135
+ # Append rule to iptables chain
136
+ iptables --append INPUT --protocol tcp --dport 22 --in-interface $ACTIVE_NETWORK_ADAPTER --destination $CURRENT_IP --jump DROP
137
+ iptables --append INPUT --protocol udp --dport 22 --in-interface $ACTIVE_NETWORK_ADAPTER --destination $CURRENT_IP --jump DROP
138
+ iptables --append INPUT --protocol icmp --icmp-type echo-request --in-interface $ACTIVE_NETWORK_ADAPTER --destination $CURRENT_IP --jump DROP
139
+ fi
140
+
141
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'rhel' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '="8\|="9') ]; then
142
+ echo 'RHEL 8.x/9.x detected, use nftables'
143
+ echo 'Ensure firewalld is disabled (nftables (Netfilter service is auto disabled when firewalld enabled)'
144
+ systemctl stop firewalld
145
+ systemctl disable firewalld
146
+ systemctl mask firewalld
147
+
148
+ echo 'Ensure nftables installed, and install'
149
+ yum --assumeyes --debuglevel=1 install nftables
150
+ systemctl start nftables
151
+ systemctl enable nftables
152
+ # Checking status will cause Terraform session to break, so grep active line to confirm running
153
+ sudo systemctl status nftables | grep "Loaded:"
154
+ sudo systemctl status nftables | grep "Active:"
155
+
156
+ echo 'Create Table with family as "inet" (for both ip and ip6 families)'
157
+ nft add table inet ssh_drop_table
158
+
159
+ echo 'Create Table Chain with type as "filter" and hook as "prerouting" (for inet, hooks are prerouting,input,forward,output,postrouting,ingress)'
160
+ nft add chain inet ssh_drop_table ssh_drop_filter_chain { type filter hook prerouting priority 0 \; }
161
+
162
+ # Use background (& suffix) to avoid lock-out of current script
163
+ echo 'Create Rule inside Table Chain (add to end of chain, or insert to top of chain)'
164
+ nft add rule inet ssh_drop_table ssh_drop_filter_chain icmp type { echo-request, echo-reply } log prefix \"[iptables_SSHDROP] \" drop
165
+ nft add rule inet ssh_drop_table ssh_drop_filter_chain icmpv6 type { echo-request, echo-reply } log prefix \"[iptables_SSHDROP] \" drop
166
+ nohup bash -c 'sleep 5; nft add rule inet ssh_drop_table ssh_drop_filter_chain tcp dport 22 log prefix \"[iptables_SSHDROP] \" drop' &>/dev/null & disown
167
+ nohup bash -c 'sleep 5; nft add rule inet ssh_drop_table ssh_drop_filter_chain udp dport 22 log prefix \"[iptables_SSHDROP] \" drop' &>/dev/null & disown
168
+
169
+ # Show tables
170
+ # nft list ruleset
171
+ fi
172
+
173
+ if [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'sles' ] || [ $(grep ^ID= /etc/os-release | cut -d '=' -f2 | tr -d '\"') = 'sles_sap' ] && [ $(grep ^VERSION_ID= /etc/os-release | grep '="15') ]; then
174
+ echo 'SLES 15.x detected, use nftables'
175
+ echo 'Ensure firewalld is disabled (nftables (Netfilter service is auto disabled when firewalld enabled)'
176
+ systemctl stop firewalld
177
+ systemctl disable firewalld
178
+ systemctl mask firewalld
179
+
180
+ echo 'Ensure nftables installed, and install'
181
+ zypper install --no-confirm nftables
182
+ systemctl start nftables
183
+ systemctl enable nftables
184
+ # Checking status will cause Terraform session to break, so grep active line to confirm running
185
+ sudo systemctl status nftables | grep "Loaded:"
186
+ sudo systemctl status nftables | grep "Active:"
187
+
188
+ echo 'Create Table with family as "inet" (for both ip and ip6 families)'
189
+ nft add table inet ssh_drop_table
190
+
191
+ echo 'Create Table Chain with type as "filter" and hook as "prerouting" (for inet, hooks are prerouting,input,forward,output,postrouting,ingress)'
192
+ nft add chain inet ssh_drop_table ssh_drop_filter_chain { type filter hook prerouting priority 0 \; }
193
+
194
+ # Use background (& suffix) to avoid lock-out of current script
195
+ echo 'Create Rule inside Table Chain (add to end of chain, or insert to top of chain)'
196
+ nft add rule inet ssh_drop_table ssh_drop_filter_chain icmp type { echo-request, echo-reply } log prefix \"[iptables_SSHDROP] \" drop
197
+ nft add rule inet ssh_drop_table ssh_drop_filter_chain icmpv6 type { echo-request, echo-reply } log prefix \"[iptables_SSHDROP] \" drop
198
+ nohup bash -c 'sleep 5; nft add rule inet ssh_drop_table ssh_drop_filter_chain tcp dport 22 log prefix \"[iptables_SSHDROP] \" drop' &>/dev/null & disown
199
+ nohup bash -c 'sleep 5; nft add rule inet ssh_drop_table ssh_drop_filter_chain udp dport 22 log prefix \"[iptables_SSHDROP] \" drop' &>/dev/null & disown
200
+
201
+ # Show tables
202
+ # nft list ruleset
203
+ fi
204
+
205
+ echo 'Disable ec2-user'
206
+ sudo mv /home/ec2-user/.ssh/authorized_keys /home/ec2-user/.ssh/disabled_keys
207
+ echo 'Disabled the ec2-user'
208
+
209
+ EOT
210
+ }
211
+
212
+ provisioner "remote-exec" {
213
+ inline = [
214
+ " chmod +x /home/ec2-user/bastion_script.sh ; sudo su - root -c 'bash /home/ec2-user/bastion_script.sh'"
215
+ ]
111
216
}
112
217
113
218
}
0 commit comments