mirror of
https://github.com/trailofbits/algo.git
synced 2025-08-02 10:53:01 +02:00
GCP: Refactoring, remove deprecated modules
This commit is contained in:
parent
d7f8f9363f
commit
5a16e2474d
5 changed files with 197 additions and 215 deletions
|
@ -1,139 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# Copyright 2013 Google Inc.
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|
||||||
'status': ['preview'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
---
|
|
||||||
module: gce_region_facts
|
|
||||||
version_added: "5.3"
|
|
||||||
short_description: Gather facts about GCE regions.
|
|
||||||
description:
|
|
||||||
- Gather facts about GCE regions.
|
|
||||||
options:
|
|
||||||
service_account_email:
|
|
||||||
version_added: "1.6"
|
|
||||||
description:
|
|
||||||
- service account email
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
aliases: []
|
|
||||||
pem_file:
|
|
||||||
version_added: "1.6"
|
|
||||||
description:
|
|
||||||
- path to the pem file associated with the service account email
|
|
||||||
This option is deprecated. Use 'credentials_file'.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
aliases: []
|
|
||||||
credentials_file:
|
|
||||||
version_added: "2.1.0"
|
|
||||||
description:
|
|
||||||
- path to the JSON file associated with the service account email
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
aliases: []
|
|
||||||
project_id:
|
|
||||||
version_added: "1.6"
|
|
||||||
description:
|
|
||||||
- your GCE project ID
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
aliases: []
|
|
||||||
requirements:
|
|
||||||
- "python >= 2.6"
|
|
||||||
- "apache-libcloud >= 0.13.3, >= 0.17.0 if using JSON credentials"
|
|
||||||
author: "Jack Ivanov (@jackivanov)"
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = '''
|
|
||||||
# Gather facts about all regions
|
|
||||||
- gce_region_facts:
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = '''
|
|
||||||
regions:
|
|
||||||
returned: on success
|
|
||||||
description: >
|
|
||||||
Each element consists of a dict with all the information related
|
|
||||||
to that region.
|
|
||||||
type: list
|
|
||||||
sample: "[{
|
|
||||||
"name": "asia-east1",
|
|
||||||
"status": "UP",
|
|
||||||
"zones": [
|
|
||||||
{
|
|
||||||
"name": "asia-east1-a",
|
|
||||||
"status": "UP"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "asia-east1-b",
|
|
||||||
"status": "UP"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "asia-east1-c",
|
|
||||||
"status": "UP"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}]"
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
from libcloud.compute.types import Provider
|
|
||||||
from libcloud.compute.providers import get_driver
|
|
||||||
from libcloud.common.google import GoogleBaseError, QuotaExceededError, ResourceExistsError, ResourceNotFoundError
|
|
||||||
_ = Provider.GCE
|
|
||||||
HAS_LIBCLOUD = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_LIBCLOUD = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.gce import gce_connect, unexpected_error_msg
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
module = AnsibleModule(
|
|
||||||
argument_spec=dict(
|
|
||||||
service_account_email=dict(),
|
|
||||||
pem_file=dict(type='path'),
|
|
||||||
credentials_file=dict(type='path'),
|
|
||||||
project_id=dict(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not HAS_LIBCLOUD:
|
|
||||||
module.fail_json(msg='libcloud with GCE support (0.17.0+) required for this module')
|
|
||||||
|
|
||||||
gce = gce_connect(module)
|
|
||||||
|
|
||||||
changed = False
|
|
||||||
gce_regions = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
regions = gce.ex_list_regions()
|
|
||||||
for r in regions:
|
|
||||||
gce_region = {}
|
|
||||||
gce_region['name'] = r.name
|
|
||||||
gce_region['status'] = r.status
|
|
||||||
gce_region['zones'] = []
|
|
||||||
for z in r.zones:
|
|
||||||
gce_zone = {}
|
|
||||||
gce_zone['name'] = z.name
|
|
||||||
gce_zone['status'] = z.status
|
|
||||||
gce_region['zones'].append(gce_zone)
|
|
||||||
gce_regions.append(gce_region)
|
|
||||||
json_output = { 'regions': gce_regions }
|
|
||||||
module.exit_json(changed=False, results=json_output)
|
|
||||||
except ResourceNotFoundError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
93
library/gcp_compute_location_info.py
Normal file
93
library/gcp_compute_location_info.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Documentation
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ["preview"], 'supported_by': 'community'}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Imports
|
||||||
|
################################################################################
|
||||||
|
from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest
|
||||||
|
import json
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Main
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module = GcpModule(argument_spec=dict(filters=dict(type='list', elements='str'), scope=dict(required=True, type='str')))
|
||||||
|
|
||||||
|
if module._name == 'gcp_compute_image_facts':
|
||||||
|
module.deprecate("The 'gcp_compute_image_facts' module has been renamed to 'gcp_compute_regions_info'", version='2.13')
|
||||||
|
|
||||||
|
if not module.params['scopes']:
|
||||||
|
module.params['scopes'] = ['https://www.googleapis.com/auth/compute']
|
||||||
|
|
||||||
|
items = fetch_list(module, collection(module), query_options(module.params['filters']))
|
||||||
|
if items.get('items'):
|
||||||
|
items = items.get('items')
|
||||||
|
else:
|
||||||
|
items = []
|
||||||
|
return_value = {'resources': items}
|
||||||
|
module.exit_json(**return_value)
|
||||||
|
|
||||||
|
|
||||||
|
def collection(module):
|
||||||
|
return "https://www.googleapis.com/compute/v1/projects/{project}/{scope}".format(**module.params)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_list(module, link, query):
|
||||||
|
auth = GcpSession(module, 'compute')
|
||||||
|
response = auth.get(link, params={'filter': query})
|
||||||
|
return return_if_object(module, response)
|
||||||
|
|
||||||
|
|
||||||
|
def query_options(filters):
|
||||||
|
if not filters:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
if len(filters) == 1:
|
||||||
|
return filters[0]
|
||||||
|
else:
|
||||||
|
queries = []
|
||||||
|
for f in filters:
|
||||||
|
# For multiple queries, all queries should have ()
|
||||||
|
if f[0] != '(' and f[-1] != ')':
|
||||||
|
queries.append("(%s)" % ''.join(f))
|
||||||
|
else:
|
||||||
|
queries.append(f)
|
||||||
|
|
||||||
|
return ' '.join(queries)
|
||||||
|
|
||||||
|
|
||||||
|
def return_if_object(module, response):
|
||||||
|
# If not found, return nothing.
|
||||||
|
if response.status_code == 404:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# If no content, return nothing.
|
||||||
|
if response.status_code == 204:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
module.raise_for_status(response)
|
||||||
|
result = response.json()
|
||||||
|
except getattr(json.decoder, 'JSONDecodeError', ValueError) as inst:
|
||||||
|
module.fail_json(msg="Invalid JSON response with error: %s" % inst)
|
||||||
|
|
||||||
|
if navigate_hash(result, ['error', 'errors']):
|
||||||
|
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -2,60 +2,83 @@
|
||||||
- name: Build python virtual environment
|
- name: Build python virtual environment
|
||||||
import_tasks: venv.yml
|
import_tasks: venv.yml
|
||||||
|
|
||||||
|
- name: Include prompts
|
||||||
|
import_tasks: prompts.yml
|
||||||
|
|
||||||
|
- name: Network configured
|
||||||
|
gcp_compute_network:
|
||||||
|
auth_kind: serviceaccount
|
||||||
|
service_account_file: "{{ credentials_file_path }}"
|
||||||
|
project: "{{ project_id }}"
|
||||||
|
name: algovpn
|
||||||
|
auto_create_subnetworks: true
|
||||||
|
routing_config:
|
||||||
|
routing_mode: REGIONAL
|
||||||
|
register: gcp_compute_network
|
||||||
|
|
||||||
|
- name: Firewall configured
|
||||||
|
gcp_compute_firewall:
|
||||||
|
auth_kind: serviceaccount
|
||||||
|
service_account_file: "{{ credentials_file_path }}"
|
||||||
|
project: "{{ project_id }}"
|
||||||
|
name: algovpn
|
||||||
|
network: "{{ gcp_compute_network }}"
|
||||||
|
direction: INGRESS
|
||||||
|
allowed:
|
||||||
|
- ip_protocol: udp
|
||||||
|
ports:
|
||||||
|
- '500'
|
||||||
|
- '4500'
|
||||||
|
- '{{ wireguard_port|string }}'
|
||||||
|
- ip_protocol: tcp
|
||||||
|
ports:
|
||||||
|
- '22'
|
||||||
|
- ip_protocol: icmp
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: Include prompts
|
- name: External IP allocated
|
||||||
import_tasks: prompts.yml
|
gcp_compute_address:
|
||||||
|
auth_kind: serviceaccount
|
||||||
- name: Network configured
|
service_account_file: "{{ credentials_file_path }}"
|
||||||
gce_net:
|
project: "{{ project_id }}"
|
||||||
name: "{{ algo_server_name }}"
|
name: "{{ algo_server_name }}"
|
||||||
fwname: "{{ algo_server_name }}-fw"
|
region: "{{ algo_region }}"
|
||||||
allowed: "udp:500,4500,{{ wireguard_port }};tcp:22"
|
register: gcp_compute_address
|
||||||
state: "present"
|
|
||||||
mode: auto
|
|
||||||
src_range: 0.0.0.0/0
|
|
||||||
service_account_email: "{{ service_account_email }}"
|
|
||||||
credentials_file: "{{ credentials_file_path }}"
|
|
||||||
project_id: "{{ project_id }}"
|
|
||||||
|
|
||||||
- block:
|
- name: Set External IP as a fact
|
||||||
- name: External IP allocated
|
set_fact:
|
||||||
gce_eip:
|
external_ip: "{{ gcp_compute_address.address }}"
|
||||||
service_account_email: "{{ service_account_email }}"
|
when: cloud_providers.gce.external_static_ip
|
||||||
credentials_file: "{{ credentials_file_path }}"
|
|
||||||
project_id: "{{ project_id }}"
|
|
||||||
name: "{{ algo_server_name }}"
|
|
||||||
region: "{{ algo_region.split('-')[0:2] | join('-') }}"
|
|
||||||
state: present
|
|
||||||
register: gce_eip
|
|
||||||
|
|
||||||
- name: Set External IP as a fact
|
- name: Instance created
|
||||||
set_fact:
|
gcp_compute_instance:
|
||||||
external_ip: "{{ gce_eip.address }}"
|
auth_kind: serviceaccount
|
||||||
when: cloud_providers.gce.external_static_ip
|
service_account_file: "{{ credentials_file_path }}"
|
||||||
|
project: "{{ project_id }}"
|
||||||
- name: "Creating a new instance..."
|
name: "{{ algo_server_name }}"
|
||||||
gce:
|
zone: "{{ algo_zone }}"
|
||||||
instance_names: "{{ algo_server_name }}"
|
machine_type: "{{ cloud_providers.gce.size }}"
|
||||||
zone: "{{ algo_region }}"
|
disks:
|
||||||
external_ip: "{{ external_ip | default('ephemeral') }}"
|
- auto_delete: true
|
||||||
machine_type: "{{ cloud_providers.gce.size }}"
|
boot: true
|
||||||
image: "{{ cloud_providers.gce.image }}"
|
initialize_params:
|
||||||
service_account_email: "{{ service_account_email }}"
|
source_image: "projects/ubuntu-os-cloud/global/images/family/{{ cloud_providers.gce.image }}"
|
||||||
credentials_file: "{{ credentials_file_path }}"
|
metadata:
|
||||||
project_id: "{{ project_id }}"
|
ssh-keys: "ubuntu:{{ ssh_public_key_lookup }}"
|
||||||
metadata:
|
user-data: |
|
||||||
ssh-keys: "ubuntu:{{ ssh_public_key_lookup }}"
|
#!/bin/bash
|
||||||
user-data: |
|
sudo apt-get remove -y --purge sshguard
|
||||||
#!/bin/bash
|
network_interfaces:
|
||||||
sudo apt-get remove -y --purge sshguard
|
- network: "{{ gcp_compute_network }}"
|
||||||
network: "{{ algo_server_name }}"
|
access_configs:
|
||||||
tags:
|
- name: "{{ algo_server_name }}"
|
||||||
|
nat_ip: "{{ gcp_compute_address|default(None) }}"
|
||||||
|
type: ONE_TO_ONE_NAT
|
||||||
|
tags:
|
||||||
|
items:
|
||||||
- "environment-algo"
|
- "environment-algo"
|
||||||
register: google_vm
|
register: gcp_compute_instance
|
||||||
|
|
||||||
- set_fact:
|
- set_fact:
|
||||||
cloud_instance_ip: "{{ google_vm.instance_data[0].public_ip }}"
|
cloud_instance_ip: "{{ gcp_compute_instance.networkInterfaces[0].accessConfigs[0].natIP }}"
|
||||||
ansible_ssh_user: ubuntu
|
ansible_ssh_user: ubuntu
|
||||||
environment:
|
|
||||||
PYTHONPATH: "{{ gce_venv }}/lib/python2.7/site-packages/"
|
|
||||||
|
|
|
@ -21,36 +21,32 @@
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: Get regions
|
- name: Get regions
|
||||||
gce_region_facts:
|
gcp_compute_location_info:
|
||||||
service_account_email: "{{ credentials_file_lookup.client_email }}"
|
auth_kind: serviceaccount
|
||||||
credentials_file: "{{ credentials_file_path }}"
|
service_account_file: "{{ credentials_file_path }}"
|
||||||
project_id: "{{ credentials_file_lookup.project_id }}"
|
project: "{{ project_id }}"
|
||||||
register: _gce_regions
|
scope: regions
|
||||||
|
filters: status=UP
|
||||||
|
register: gcp_compute_regions_info
|
||||||
|
|
||||||
- name: Set facts about the regions
|
- name: Set facts about the regions
|
||||||
set_fact:
|
set_fact:
|
||||||
gce_regions: >-
|
gce_regions: >-
|
||||||
[{%- for region in _gce_regions.results.regions | sort(attribute='name') -%}
|
[{%- for region in gcp_compute_regions_info.resources | sort(attribute='name') -%}
|
||||||
{% if region.status == "UP" %}
|
'{{ region.name }}'{% if not loop.last %},{% endif %}
|
||||||
{% for zone in region.zones | sort(attribute='name') %}
|
|
||||||
{% if zone.status == "UP" %}
|
|
||||||
'{{ zone.name }}'
|
|
||||||
{% endif %}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}{% if not loop.last %},{% endif %}
|
|
||||||
{%- endfor -%}]
|
{%- endfor -%}]
|
||||||
|
|
||||||
- name: Set facts about the default region
|
- name: Set facts about the default region
|
||||||
set_fact:
|
set_fact:
|
||||||
default_region: >-
|
default_region: >-
|
||||||
{% for region in gce_regions %}
|
{% for region in gce_regions %}
|
||||||
{%- if region == "us-east1-b" %}{{ loop.index }}{% endif %}
|
{%- if region == "us-east1" %}{{ loop.index }}{% endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
||||||
- pause:
|
- pause:
|
||||||
prompt: |
|
prompt: |
|
||||||
What region should the server be located in?
|
What region should the server be located in?
|
||||||
(https://cloud.google.com/compute/docs/regions-zones/)
|
(https://cloud.google.com/compute/docs/regions-zones/#locations)
|
||||||
{% for r in gce_regions %}
|
{% for r in gce_regions %}
|
||||||
{{ loop.index }}. {{ r }}
|
{{ loop.index }}. {{ r }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -60,8 +56,24 @@
|
||||||
register: _gce_region
|
register: _gce_region
|
||||||
when: region is undefined
|
when: region is undefined
|
||||||
|
|
||||||
- set_fact:
|
- name: Set region as a fact
|
||||||
|
set_fact:
|
||||||
algo_region: >-
|
algo_region: >-
|
||||||
{% if region is defined %}{{ region }}
|
{% if region is defined %}{{ region }}
|
||||||
{%- elif _gce_region.user_input %}{{ gce_regions[_gce_region.user_input | int -1 ] }}
|
{%- elif _gce_region.user_input %}{{ gce_regions[_gce_region.user_input | int -1 ] }}
|
||||||
{%- else %}{{ gce_regions[default_region | int - 1] }}{% endif %}
|
{%- else %}{{ gce_regions[default_region | int - 1] }}{% endif %}
|
||||||
|
|
||||||
|
- name: Get zones
|
||||||
|
gcp_compute_location_info:
|
||||||
|
auth_kind: serviceaccount
|
||||||
|
service_account_file: "{{ credentials_file_path }}"
|
||||||
|
project: "{{ project_id }}"
|
||||||
|
scope: zones
|
||||||
|
filters:
|
||||||
|
- "name={{ algo_region }}-*"
|
||||||
|
- "status=UP"
|
||||||
|
register: gcp_compute_zone_info
|
||||||
|
|
||||||
|
- name: Set random available zone as a fact
|
||||||
|
set_fact:
|
||||||
|
algo_zone: "{{ (gcp_compute_zone_info.resources | random(seed=algo_server_name + algo_region + project_id) ).name }}"
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
---
|
---
|
||||||
- name: Clean up the environment
|
|
||||||
file:
|
|
||||||
dest: "{{ gce_venv }}"
|
|
||||||
state: absent
|
|
||||||
when: clean_environment
|
|
||||||
|
|
||||||
- name: Install requirements
|
- name: Install requirements
|
||||||
pip:
|
pip:
|
||||||
name:
|
name:
|
||||||
- apache-libcloud
|
- requests>=2.18.4
|
||||||
|
- google-auth>=1.3.0
|
||||||
state: latest
|
state: latest
|
||||||
virtualenv: "{{ gce_venv }}"
|
|
||||||
virtualenv_python: python2.7
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue