Skip to content

Commit

Permalink
[VM/Network] Update template-based creates to use secureString when a…
Browse files Browse the repository at this point in the history
…ppropriate (Azure#5336)

* Update admin-password to use securestring.

* Resolve conflicts.

* Add another recording.

* Fix run_tests. Fix broken ExpressRoute test. Update project files for test folder adjustment.
  • Loading branch information
tjprescott authored Jan 19, 2018
1 parent 1633844 commit 03a2163
Show file tree
Hide file tree
Showing 15 changed files with 4,232 additions and 3,292 deletions.
410 changes: 223 additions & 187 deletions azure-cli.pyproj

Large diffs are not rendered by default.

444 changes: 258 additions & 186 deletions azure-cli2017.pyproj

Large diffs are not rendered by default.

72 changes: 70 additions & 2 deletions src/azure-cli-core/azure/cli/core/commands/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# --------------------------------------------------------------------------------------------

import argparse
from collections import OrderedDict
import json
import re
from six import string_types

Expand All @@ -22,8 +24,74 @@
logger = get_logger(__name__)


class ArmTemplateBuilder(object):

def __init__(self):
template = OrderedDict()
template['$schema'] = \
'https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#'
template['contentVersion'] = '1.0.0.0'
template['parameters'] = {}
template['variables'] = {}
template['resources'] = []
template['outputs'] = {}
self.template = template
self.parameters = OrderedDict()

def add_resource(self, resource):
self.template['resources'].append(resource)

def add_variable(self, key, value):
self.template['variables'][key] = value

def add_parameter(self, key, value):
self.template['parameters'][key] = value

def add_secure_parameter(self, key, value, description=None):
param = {
"type": "securestring",
"metadata": {
"description": description or 'Secure {}'.format(key)
}
}
self.template['parameters'][key] = param
self.parameters[key] = {'value': value}

def add_id_output(self, key, provider, property_type, property_name):
new_output = {
key: {
'type': 'string',
'value': "[resourceId('{}/{}', '{}')]".format(
provider, property_type, property_name)
}
}
self.template['outputs'].update(new_output)

def add_output(self, key, property_name, provider=None, property_type=None,
output_type='string', path=None):

if provider and property_type:
value = "[reference(resourceId('{provider}/{type}', '{property}'),providers('{provider}', '{type}').apiVersions[0])".format( # pylint: disable=line-too-long
provider=provider, type=property_type, property=property_name)
else:
value = "[reference('{}')".format(property_name)
value = '{}.{}]'.format(value, path) if path else '{}]'.format(value)
new_output = {
key: {
'type': output_type,
'value': value
}
}
self.template['outputs'].update(new_output)

def build(self):
return json.loads(json.dumps(self.template))

def build_parameters(self):
return json.loads(json.dumps(self.parameters))


def handle_long_running_operation_exception(ex):
import json
import azure.cli.core.telemetry as telemetry

telemetry.set_exception(
Expand Down Expand Up @@ -53,7 +121,7 @@ def handle_long_running_operation_exception(ex):


def deployment_validate_table_format(result):
from collections import OrderedDict

if result.get('error', None):
error_result = OrderedDict()
error_result['result'] = result['error']['code']
Expand Down
4 changes: 2 additions & 2 deletions src/command_modules/azure-cli-network/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Release History

2.0.22
++++++

* minor fixes
* `application-gateway create`: `--cert-password` protected using secureString.
* `vpn-connection create`: `--shared-key` and `--authorization-key` protected using secureString.

2.0.21
++++++
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ def load_arguments(self, _):
c.argument('http_settings_cookie_based_affinity', cookie_based_affinity_type, help='Enable or disable HTTP settings cookie-based affinity.')
c.argument('http_settings_protocol', http_protocol_type, help='The HTTP settings protocol.')
c.argument('enable_http2', arg_type=get_three_state_flag(positive_label='Enabled', negative_label='Disabled'), options_list=['--http2'], help='Use HTTP2 for the application gateway.', min_api='2017-10-01')
c.ignore('public_ip_address_type', 'frontend_type', 'subnet_type')

with self.argument_context('network application-gateway create') as c:
c.argument('validate', help='Generate and validate the ARM template without creating any resources.', action='store_true')
c.argument('routing_rule_type', arg_group='Gateway', help='The request routing rule type.', arg_type=get_enum_type(ApplicationGatewayRequestRoutingRuleType))
public_ip_help = get_folded_parameter_help_string('public IP address', allow_none=True, allow_new=True, default_none=True)
c.argument('public_ip_address', help=public_ip_help, completer=get_resource_name_completion_list('Microsoft.Network/publicIPAddresses'), arg_group='Network')
c.ignore('public_ip_address_type', 'frontend_type', 'subnet_type')
subnet_help = get_folded_parameter_help_string('subnet', other_required_option='--vnet-name', allow_new=True)
c.argument('subnet', help=subnet_help, completer=subnet_completion_list, arg_group='Network')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,6 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from collections import OrderedDict
import json


class ArmTemplateBuilder(object):
def __init__(self):
template = OrderedDict()
template['$schema'] = \
'https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#'
template['contentVersion'] = '1.0.0.0'
template['parameters'] = {}
template['variables'] = {}
template['resources'] = []
template['outputs'] = {}
self.template = template

def add_resource(self, resource):
self.template['resources'].append(resource)

def add_variable(self, key, value):
self.template['variables'][key] = value

def add_parameter(self, key, value):
self.template['parameters'][key] = value

def add_id_output(self, key, provider, property_type, property_name):
new_output = {
key: {
'type': 'string',
'value': "[resourceId('{}/{}', '{}')]".format(
provider, property_type, property_name)
}
}
self.template['outputs'].update(new_output)

def add_output(self, key, property_name, provider=None, property_type=None,
output_type='string', path=None):

if provider and property_type:
template = "[reference(resourceId('{provider}/{type}', '{property}')," \
"providers('{provider}', '{type}').apiVersions[0])"
value = template.format(provider=provider, type=property_type, property=property_name)
else:
value = "[reference('{}')".format(property_name)
value = '{}.{}]'.format(value, path) if path else '{}]'.format(value)
new_output = {
key: {
'type': output_type,
'value': value
}
}
self.template['outputs'].update(new_output)

def build(self):
return json.loads(json.dumps(self.template))


def _build_frontend_ip_config(cmd, name, public_ip_id=None, subnet_id=None, private_ip_address=None,
private_ip_allocation=None, zone=None):
Expand Down Expand Up @@ -137,9 +81,10 @@ def _ag_subresource_id(_type, name):
'name': ssl_cert_name,
'properties': {
'data': cert_data,
'password': cert_password
}
}
if cert_password:
ssl_cert['properties']['password'] = "[parameters('certPassword')]"

backend_http_settings = {
'name': http_settings_name,
Expand Down Expand Up @@ -289,15 +234,18 @@ def build_vpn_connection_resource(cmd, name, location, tags, gateway1, gateway2,
enable_bgp, routing_weight, shared_key, use_policy_based_traffic_selectors):
vpn_properties = {
'virtualNetworkGateway1': {'id': gateway1},
'authorizationKey': authorization_key,
'enableBgp': enable_bgp,
'connectionType': vpn_type,
'routingWeight': routing_weight
}
if authorization_key:
vpn_properties['authorizationKey'] = "[parameters('authorizationKey')]"
if cmd.supported_api_version(min_api='2017-03-01'):
vpn_properties['usePolicyBasedTrafficSelectors'] = use_policy_based_traffic_selectors

# add scenario specific properties
if shared_key:
shared_key = "[parameters('sharedKey')]"
if vpn_type == 'IPSec':
vpn_properties.update({
'localNetworkGateway2': {'id': gateway2},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ def create_application_gateway(cmd, application_gateway_name, resource_group_nam
public_ip_address_type=None, subnet_type=None, validate=False,
connection_draining_timeout=0, enable_http2=None):
from azure.cli.core.util import random_string
from azure.cli.command_modules.network._template_builder import \
(ArmTemplateBuilder, build_application_gateway_resource, build_public_ip_resource,
build_vnet_resource)
from azure.cli.core.commands.arm import ArmTemplateBuilder
from azure.cli.command_modules.network._template_builder import (
build_application_gateway_resource, build_public_ip_resource, build_vnet_resource)

DeploymentProperties = cmd.get_models('DeploymentProperties', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES)
IPAllocationMethod = cmd.get_models('IPAllocationMethod')
Expand Down Expand Up @@ -199,13 +199,16 @@ def create_application_gateway(cmd, application_gateway_name, resource_group_nam
application_gateway_name))
master_template.add_resource(app_gateway_resource)
master_template.add_output('applicationGateway', application_gateway_name, output_type='object')
if cert_password:
master_template.add_secure_parameter('certPassword', cert_password)

template = master_template.build()
parameters = master_template.build_parameters()

# deploy ARM template
deployment_name = 'ag_deploy_' + random_string(32)
client = get_mgmt_service_client(cmd.cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES).deployments
properties = DeploymentProperties(template=template, parameters={}, mode='incremental')
properties = DeploymentProperties(template=template, parameters=parameters, mode='incremental')
if validate:
_log_pprint_template(template)
return client.validate(resource_group_name, deployment_name, properties)
Expand Down Expand Up @@ -1505,9 +1508,9 @@ def create_load_balancer(cmd, load_balancer_name, resource_group_name, location=
public_ip_address_type=None, subnet_type=None, validate=False,
no_wait=False, sku=None, frontend_ip_zone=None, public_ip_zone=None):
from azure.cli.core.util import random_string
from azure.cli.command_modules.network._template_builder import \
(ArmTemplateBuilder, build_load_balancer_resource, build_public_ip_resource,
build_vnet_resource)
from azure.cli.core.commands.arm import ArmTemplateBuilder
from azure.cli.command_modules.network._template_builder import (
build_load_balancer_resource, build_public_ip_resource, build_vnet_resource)

DeploymentProperties = cmd.get_models('DeploymentProperties', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES)
IPAllocationMethod = cmd.get_models('IPAllocationMethod')
Expand Down Expand Up @@ -3145,8 +3148,8 @@ def create_vpn_connection(cmd, resource_group_name, connection_name, vnet_gatewa
:param bool validate: Display and validate the ARM template but do not create any resources.
"""
from azure.cli.core.util import random_string
from azure.cli.command_modules.network._template_builder import \
ArmTemplateBuilder, build_vpn_connection_resource
from azure.cli.core.commands.arm import ArmTemplateBuilder
from azure.cli.command_modules.network._template_builder import build_vpn_connection_resource

client = network_client_factory(cmd.cli_ctx).virtual_network_gateway_connections
DeploymentProperties = cmd.get_models('DeploymentProperties', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES)
Expand All @@ -3161,13 +3164,18 @@ def create_vpn_connection(cmd, resource_group_name, connection_name, vnet_gatewa
use_policy_based_traffic_selectors)
master_template.add_resource(vpn_connection_resource)
master_template.add_output('resource', connection_name, output_type='object')
if shared_key:
master_template.add_secure_parameter('sharedKey', shared_key)
if authorization_key:
master_template.add_secure_parameter('authorizationKey', authorization_key)

template = master_template.build()
parameters = master_template.build_parameters()

# deploy ARM template
deployment_name = 'vpn_connection_deploy_' + random_string(32)
client = get_mgmt_service_client(cmd.cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES).deployments
properties = DeploymentProperties(template=template, parameters={}, mode='incremental')
properties = DeploymentProperties(template=template, parameters=parameters, mode='incremental')
if validate:
_log_pprint_template(template)
return client.validate(resource_group_name, deployment_name, properties)
Expand Down
Loading

0 comments on commit 03a2163

Please sign in to comment.