Skip to content

Commit 7232b58

Browse files
authored
Merge pull request #93 from sean-freeman/bastion_boolean
sap_vm_provision: bastion boolean
2 parents ed85a54 + 9fd28b8 commit 7232b58

File tree

18 files changed

+288
-75
lines changed

18 files changed

+288
-75
lines changed

roles/sap_vm_provision/PLATFORM_GUIDANCE.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ Table of Contents:
55
- [Recommended Infrastructure Platform authorizations](#recommended-infrastructure-platform-authorizations)
66
- [Recommended Infrastructure Platform configuration](#recommended-infrastructure-platform-configuration)
77

8+
## Key note - Connectivity
9+
10+
The Ansible Control Node AKA Controller (i.e. device where Ansible Playbook is executed), must be able to directly call the platform's API endpoints. For example:
11+
12+
- AWS EC2 API endpoint `ec2.us-east-1.amazonaws.com`
13+
- VMware vSphere REST API endpoint `<VMware vCenter Server Appliance hostnamee>.:443`
14+
15+
By default, a Cloud account will use Public internet endpoints which should be accessible in most cases. The Cloud account may utilise Private endpoints for security, as would an On-Premise Hypervisor. Examples include:
16+
17+
- running an Ansible Playbook from a personal laptop, then the personal laptop acts as the Ansible Control Node and can access the platform's APIs using a Client-to-Site VPN Client (such as OpenVPN Connect) to provision Virtual Machines for deploying SAP software
18+
- running an Ansible Playbook from an existing host (e.g. VM) inside the platform's private network, then the existing host acts as the Ansible Control Node and can access the platform's APIs to provision Virtual Machines for deploying SAP software
19+
20+
The subsequent provisioned Virtual Machine, must be accessible too - this can utilise a Bastion for SSH Proxy connection, which is common for Cloud IaaS.
21+
22+
The Ansible Control Node AKA Controller (i.e. device where Ansible Playbook is executed), must be able to SSH to the Ansible Target Node (i.e. Virtual Machine) using:
23+
24+
- DEFAULT: SSH Proxy connection from Ansible control node, via Bastion host, to target node (`sap_vm_provision_bastion_execution: true`); with SSH Private Keys for the host and the bastion (`sap_vm_provision_ssh_host_private_key_file_path: "/path"` and `sap_vm_provision_ssh_bastion_private_key_file_path: "/path"`)
25+
- Direct SSH connection from Ansible control node to target node (`sap_vm_provision_bastion_execution: false`); with SSH Private Key for the host (`sap_vm_provision_ssh_host_private_key_file_path: "/path"`).
26+
827

928
## Required resources when Ansible provisioning VMs
1029

@@ -118,7 +137,7 @@ See below for the drop-down list of required environment resources on an Infrast
118137
- `private_key`: Use the private ssh key at the location defined by `sap_vm_provision_ssh_host_private_key_file_path`.
119138
- `private_key_data`: use the private ssh key provided in `sap_vm_provision_ssh_host_private_key_data` and write it to the location defined in `sap_vm_provision_ssh_host_private_key_file_path`.
120139

121-
- Optional: Execution host with access to OpenShift cluster.
140+
- Optional: Ansible Control Node host with access to OpenShift cluster.
122141

123142
- Native Kubernetes with KubeVirt has not been tested.
124143

@@ -474,8 +493,6 @@ The VM Template must be prepared with cloud-init. This process is subjective to
474493
- [cloud-init documentation - Reference - Datasources - VMware](https://cloudinit.readthedocs.io/en/latest/reference/datasources/vmware.html)
475494

476495

477-
In addition, the provisioned Virtual Machine must be accessible from the Ansible Controller (i.e. device where Ansible Playbook for SAP is executed must be able to reach the provisioned host).
478-
479496
When VMware vCenter and vSphere clusters with VMware NSX virtualized network overlays using Segments (e.g. 192.168.0.0/16) connected to Tier-0/Tier-1 Gateways (which are bound to the backbone network subnet, e.g. 10.0.0.0/8), it is recommended to:
480497
- Use DHCP Server and attach to Subnet for the target VM. For example, create DHCP Server (e.g. NSX > Networking > Networking Profiles > DHCP Profile), set DHCP in the Gateway (e.g. NSX > Networking > Gateway > Edit > DHCP Config), then set for the Subnet (e.g. NSX > Networking > Segment > <<selected subnet>> > Set DHCP Config) which the VMware VM Template is attached to; this allows subsequent cloned VMs to obtain an IPv4 Address
481498
- Use DNAT configuration for any VMware NSX Segments (e.g. NSX-T Policy NAT Rule)

roles/sap_vm_provision/defaults/main.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ sap_vm_provision_group_anydb_secondary: anydb_secondary
3030
# Only for use when 'ansible' is value provided for variable sap_vm_provision_iac_type
3131
####
3232

33+
# For security purposes, assume usage of SSH Proxy connection from Ansible control node, via Bastion host to the Target host/s:
34+
# - This is a common pattern for Cloud IaaS, using a Bastion for connectivity
35+
# - When using VPN or in On-Premise/Hosted Datacenters, this can be disabled if there is direct connectivity
36+
sap_vm_provision_bastion_execution: true
37+
3338
sap_vm_provision_bastion_public_ip: ""
3439

3540
sap_vm_provision_bastion_ssh_port: 50222

roles/sap_vm_provision/tasks/platform_ansible/aws_ec2_vs/execute_main.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@
5353
# # AWS_SECRET_ACCESS_KEY: "{{ sap_vm_provision_aws_secret_access_key }}"
5454
# AWS_REGION: "{{ sap_vm_provision_aws_region }}"
5555

56+
- name: Set fact when using Bastion SSH Proxy connection from Ansible control node to target node/s
57+
ansible.builtin.set_fact:
58+
__ssh_args_bastion: -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
59+
when:
60+
- sap_vm_provision_bastion_execution
61+
- sap_vm_provision_bastion_user is defined or not sap_vm_provision_bastion_user == ''
62+
- sap_vm_provision_bastion_public_ip is defined or not sap_vm_provision_bastion_public_ip == ''
63+
- sap_vm_provision_bastion_ssh_port is defined or not sap_vm_provision_bastion_ssh_port == ''
64+
- sap_vm_provision_ssh_bastion_private_key_file_path is defined or not sap_vm_provision_ssh_bastion_private_key_file_path == ''
65+
5666
- name: Add hosts provisioned to the Ansible Inventory
5767
register: __sap_vm_provision_task_provision_host_all_add
5868
no_log: "{{ __sap_vm_provision_no_log }}"
@@ -62,7 +72,7 @@
6272
ansible_host: "{{ add_item[0].instances[0].private_ip_address }}"
6373
ansible_user: "root"
6474
ansible_ssh_private_key_file: "{{ sap_vm_provision_ssh_host_private_key_file_path }}"
65-
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
75+
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no {{ __ssh_args_bastion if __ssh_args_bastion is defined else '' }}
6676
loop: "{{ ansible_play_hosts | map('extract', hostvars, 'register_provisioned_host_all') }}"
6777
loop_control:
6878
label: "{{ add_item[0].host_node }}"

roles/sap_vm_provision/tasks/platform_ansible/aws_ec2_vs/execute_provision.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,22 @@
167167
delegate_to: "{{ provisioned_private_ip }}"
168168
delegate_facts: true
169169
ansible.builtin.set_fact:
170-
delegate_sap_vm_provision_bastion_user: "{{ sap_vm_provision_bastion_user }}"
171-
delegate_sap_vm_provision_bastion_public_ip: "{{ sap_vm_provision_bastion_public_ip }}"
172-
delegate_sap_vm_provision_bastion_ssh_port: "{{ sap_vm_provision_bastion_ssh_port }}"
173-
delegate_sap_vm_provision_ssh_bastion_private_key_file_path: "{{ sap_vm_provision_ssh_bastion_private_key_file_path }}"
174170
delegate_sap_vm_provision_ssh_host_private_key_file_path: "{{ sap_vm_provision_ssh_host_private_key_file_path }}"
175-
delegate_private_ip: "{{ __sap_vm_provision_task_provision_host_single.instances[0].private_ip_address }}"
176-
delegate_hostname: "{{ inventory_hostname }}"
177-
delegate_sap_vm_provision_dns_root_domain_name: "{{ sap_vm_provision_dns_root_domain }}"
171+
# delegate_private_ip: "{{ __sap_vm_provision_task_provision_host_single.instances[0].private_ip_address }}"
172+
# delegate_hostname: "{{ inventory_hostname }}"
173+
# delegate_sap_vm_provision_dns_root_domain_name: "{{ sap_vm_provision_dns_root_domain }}"
174+
175+
- name: Copy facts to delegate host - when using Bastion SSH Proxy connection from Ansible control node to target node/s
176+
delegate_to: "{{ provisioned_private_ip }}"
177+
delegate_facts: true
178+
ansible.builtin.set_fact:
179+
delegate_ssh_args_bastion: -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
180+
when:
181+
- sap_vm_provision_bastion_execution
182+
- sap_vm_provision_bastion_user is defined or not sap_vm_provision_bastion_user == ''
183+
- sap_vm_provision_bastion_public_ip is defined or not sap_vm_provision_bastion_public_ip == ''
184+
- sap_vm_provision_bastion_ssh_port is defined or not sap_vm_provision_bastion_ssh_port == ''
185+
- sap_vm_provision_ssh_bastion_private_key_file_path is defined or not sap_vm_provision_ssh_bastion_private_key_file_path == ''
178186

179187

180188
### begin block, parameters will be applied to each task within the block
@@ -186,7 +194,7 @@
186194
delegate_facts: true
187195
vars:
188196
ansible_ssh_private_key_file: "{{ delegate_sap_vm_provision_ssh_host_private_key_file_path }}"
189-
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ delegate_sap_vm_provision_bastion_user }}@{{ delegate_sap_vm_provision_bastion_public_ip }} -p {{ delegate_sap_vm_provision_bastion_ssh_port }} -i {{ delegate_sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
197+
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no {{ delegate_ssh_args_bastion if delegate_ssh_args_bastion is defined else '' }}
190198
block:
191199

192200
- name: Wait until SSH connection is available

roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_main.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@
101101
# GCP_AUTH_KIND: "serviceaccount"
102102
# GCP_SERVICE_ACCOUNT_FILE: "{{ sap_vm_provision_gcp_credentials_json }}"
103103

104+
- name: Set fact when using Bastion SSH Proxy connection from Ansible control node to target node/s
105+
ansible.builtin.set_fact:
106+
__ssh_args_bastion: -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
107+
when:
108+
- sap_vm_provision_bastion_execution
109+
- sap_vm_provision_bastion_user is defined or not sap_vm_provision_bastion_user == ''
110+
- sap_vm_provision_bastion_public_ip is defined or not sap_vm_provision_bastion_public_ip == ''
111+
- sap_vm_provision_bastion_ssh_port is defined or not sap_vm_provision_bastion_ssh_port == ''
112+
- sap_vm_provision_ssh_bastion_private_key_file_path is defined or not sap_vm_provision_ssh_bastion_private_key_file_path == ''
113+
104114
- name: Add hosts provisioned to the Ansible Inventory
105115
register: __sap_vm_provision_task_provision_host_all_add
106116
ansible.builtin.add_host:
@@ -109,7 +119,7 @@
109119
ansible_host: "{{ add_item[0].networkInterfaces[0].networkIP }}"
110120
ansible_user: "root"
111121
ansible_ssh_private_key_file: "{{ sap_vm_provision_ssh_host_private_key_file_path }}"
112-
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
122+
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no {{ __ssh_args_bastion if __ssh_args_bastion is defined else '' }}
113123
loop: "{{ ansible_play_hosts | map('extract', hostvars, 'register_provisioned_host_all') }}"
114124
loop_control:
115125
label: "{{ add_item[0].host_node }}"

roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,22 @@
150150
delegate_to: "{{ provisioned_private_ip }}"
151151
delegate_facts: true
152152
ansible.builtin.set_fact:
153-
delegate_sap_vm_provision_bastion_user: "{{ sap_vm_provision_bastion_user }}"
154-
delegate_sap_vm_provision_bastion_public_ip: "{{ sap_vm_provision_bastion_public_ip }}"
155-
delegate_sap_vm_provision_bastion_ssh_port: "{{ sap_vm_provision_bastion_ssh_port }}"
156-
delegate_sap_vm_provision_ssh_bastion_private_key_file_path: "{{ sap_vm_provision_ssh_bastion_private_key_file_path }}"
157153
delegate_sap_vm_provision_ssh_host_private_key_file_path: "{{ sap_vm_provision_ssh_host_private_key_file_path }}"
158-
delegate_private_ip: "{{ __sap_vm_provision_task_provision_host_single.networkInterfaces[0].networkIP }}"
159-
delegate_hostname: "{{ inventory_hostname }}"
160-
delegate_sap_vm_provision_dns_root_domain_name: "{{ sap_vm_provision_dns_root_domain }}"
154+
# delegate_private_ip: "{{ __sap_vm_provision_task_provision_host_single.networkInterfaces[0].networkIP }}"
155+
# delegate_hostname: "{{ inventory_hostname }}"
156+
# delegate_sap_vm_provision_dns_root_domain_name: "{{ sap_vm_provision_dns_root_domain }}"
157+
158+
- name: Copy facts to delegate host - when using Bastion SSH Proxy connection from Ansible control node to target node/s
159+
delegate_to: "{{ provisioned_private_ip }}"
160+
delegate_facts: true
161+
ansible.builtin.set_fact:
162+
delegate_ssh_args_bastion: -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
163+
when:
164+
- sap_vm_provision_bastion_execution
165+
- sap_vm_provision_bastion_user is defined or not sap_vm_provision_bastion_user == ''
166+
- sap_vm_provision_bastion_public_ip is defined or not sap_vm_provision_bastion_public_ip == ''
167+
- sap_vm_provision_bastion_ssh_port is defined or not sap_vm_provision_bastion_ssh_port == ''
168+
- sap_vm_provision_ssh_bastion_private_key_file_path is defined or not sap_vm_provision_ssh_bastion_private_key_file_path == ''
161169

162170

163171
### begin block, parameters will be applied to each task within the block
@@ -169,7 +177,7 @@
169177
delegate_facts: true
170178
vars:
171179
ansible_ssh_private_key_file: "{{ delegate_sap_vm_provision_ssh_host_private_key_file_path }}"
172-
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ delegate_sap_vm_provision_bastion_user }}@{{ delegate_sap_vm_provision_bastion_public_ip }} -p {{ delegate_sap_vm_provision_bastion_ssh_port }} -i {{ delegate_sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
180+
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no {{ delegate_ssh_args_bastion if delegate_ssh_args_bastion is defined else '' }}
173181
block:
174182

175183
# Required as state: present on Ansible Module gcp_compute_instance does not allow for waiting until VM has booted

roles/sap_vm_provision/tasks/platform_ansible/ibmcloud_powervs/execute_main.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@
269269
IC_REGION: "{{ sap_vm_provision_ibmcloud_powervs_region }}"
270270
IC_ZONE: "{{ sap_vm_provision_ibmcloud_powervs_location }}" # Required only for IBM Power VS, to set IBM Power VS location
271271

272+
- name: Set fact when using Bastion SSH Proxy connection from Ansible control node to target node/s
273+
ansible.builtin.set_fact:
274+
__ssh_args_bastion: -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
275+
when:
276+
- sap_vm_provision_bastion_execution
277+
- sap_vm_provision_bastion_user is defined or not sap_vm_provision_bastion_user == ''
278+
- sap_vm_provision_bastion_public_ip is defined or not sap_vm_provision_bastion_public_ip == ''
279+
- sap_vm_provision_bastion_ssh_port is defined or not sap_vm_provision_bastion_ssh_port == ''
280+
- sap_vm_provision_ssh_bastion_private_key_file_path is defined or not sap_vm_provision_ssh_bastion_private_key_file_path == ''
281+
272282
- name: Add hosts provisioned to the Ansible Inventory
273283
register: __sap_vm_provision_task_provision_host_all_add
274284
ansible.builtin.add_host:
@@ -277,7 +287,7 @@
277287
ansible_host: "{{ add_item[0].resource.networks[0].ip }}"
278288
ansible_user: "root"
279289
ansible_ssh_private_key_file: "{{ sap_vm_provision_ssh_host_private_key_file_path }}"
280-
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ sap_vm_provision_bastion_user }}@{{ sap_vm_provision_bastion_public_ip }} -p {{ sap_vm_provision_bastion_ssh_port }} -i {{ sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
290+
ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no {{ __ssh_args_bastion if __ssh_args_bastion is defined else '' }}
281291
loop: "{{ ansible_play_hosts | map('extract', hostvars, 'register_provisioned_host_all') }}"
282292
loop_control:
283293
label: "{{ add_item[0].host_node }}"

0 commit comments

Comments
 (0)