248 lines
9.1 KiB
Python
248 lines
9.1 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2014 Google LLC. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""Command for creating firewall rules."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
from googlecloudsdk.api_lib.compute import base_classes
|
|
from googlecloudsdk.api_lib.compute import firewalls_utils
|
|
from googlecloudsdk.api_lib.compute import utils as compute_api
|
|
from googlecloudsdk.api_lib.util import apis
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.calliope import exceptions
|
|
from googlecloudsdk.command_lib.compute import resource_manager_tags_utils
|
|
from googlecloudsdk.command_lib.compute.firewall_rules import flags
|
|
from googlecloudsdk.command_lib.compute.networks import flags as network_flags
|
|
from googlecloudsdk.core.console import progress_tracker
|
|
import six
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.GA)
|
|
@base.UniverseCompatible
|
|
class Create(base.CreateCommand):
|
|
"""Create a Compute Engine firewall rule."""
|
|
|
|
FIREWALL_RULE_ARG = None
|
|
NETWORK_ARG = None
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
messages = apis.GetMessagesModule('compute',
|
|
compute_api.COMPUTE_GA_API_VERSION)
|
|
parser.display_info.AddFormat(flags.DEFAULT_LIST_FORMAT)
|
|
cls.FIREWALL_RULE_ARG = flags.FirewallRuleArgument()
|
|
cls.FIREWALL_RULE_ARG.AddArgument(parser, operation_type='create')
|
|
cls.NETWORK_ARG = network_flags.NetworkArgumentForOtherResource(
|
|
'The network to which this rule is attached.', required=False)
|
|
firewalls_utils.AddCommonArgs(
|
|
parser,
|
|
for_update=False,
|
|
with_egress_support=True,
|
|
with_service_account=True)
|
|
firewalls_utils.AddArgsForServiceAccount(parser, for_update=False)
|
|
flags.AddEnableLogging(parser)
|
|
flags.AddLoggingMetadata(parser, messages)
|
|
parser.display_info.AddCacheUpdater(flags.FirewallsCompleter)
|
|
|
|
def _CreateFirewall(self, holder, args):
|
|
client = holder.client
|
|
|
|
if args.rules and args.allow:
|
|
raise firewalls_utils.ArgumentValidationError(
|
|
'Can NOT specify --rules and --allow in the same request.')
|
|
|
|
if bool(args.action) ^ bool(args.rules):
|
|
raise firewalls_utils.ArgumentValidationError(
|
|
'Must specify --rules with --action.')
|
|
|
|
allowed = firewalls_utils.ParseRules(args.allow, client.messages,
|
|
firewalls_utils.ActionType.ALLOW)
|
|
|
|
network_ref = self.NETWORK_ARG.ResolveAsResource(args, holder.resources)
|
|
firewall_ref = self.FIREWALL_RULE_ARG.ResolveAsResource(
|
|
args, holder.resources)
|
|
|
|
firewall = client.messages.Firewall(
|
|
allowed=allowed,
|
|
name=firewall_ref.Name(),
|
|
description=args.description,
|
|
network=network_ref.SelfLink(),
|
|
sourceRanges=args.source_ranges,
|
|
sourceTags=args.source_tags,
|
|
targetTags=args.target_tags)
|
|
|
|
if args.disabled is not None:
|
|
firewall.disabled = args.disabled
|
|
|
|
firewall.direction = None
|
|
if args.direction and args.direction in ['EGRESS', 'OUT']:
|
|
firewall.direction = (
|
|
client.messages.Firewall.DirectionValueValuesEnum.EGRESS)
|
|
else:
|
|
firewall.direction = (
|
|
client.messages.Firewall.DirectionValueValuesEnum.INGRESS)
|
|
|
|
firewall.priority = args.priority
|
|
firewall.destinationRanges = args.destination_ranges
|
|
|
|
allowed = []
|
|
denied = []
|
|
if not args.action:
|
|
allowed = firewalls_utils.ParseRules(
|
|
args.allow, client.messages, firewalls_utils.ActionType.ALLOW)
|
|
elif args.action == 'ALLOW':
|
|
allowed = firewalls_utils.ParseRules(
|
|
args.rules, client.messages, firewalls_utils.ActionType.ALLOW)
|
|
elif args.action == 'DENY':
|
|
denied = firewalls_utils.ParseRules(
|
|
args.rules, client.messages, firewalls_utils.ActionType.DENY)
|
|
firewall.allowed = allowed
|
|
firewall.denied = denied
|
|
|
|
firewall.sourceServiceAccounts = args.source_service_accounts
|
|
firewall.targetServiceAccounts = args.target_service_accounts
|
|
|
|
if args.IsSpecified('logging_metadata') and not args.enable_logging:
|
|
raise exceptions.InvalidArgumentException(
|
|
'--logging-metadata',
|
|
'cannot toggle logging metadata if logging is not enabled.',
|
|
)
|
|
|
|
if args.IsSpecified('enable_logging'):
|
|
log_config = client.messages.FirewallLogConfig(enable=args.enable_logging)
|
|
if args.IsSpecified('logging_metadata'):
|
|
log_config.metadata = flags.GetLoggingMetadataArg(
|
|
client.messages
|
|
).GetEnumForChoice(args.logging_metadata)
|
|
firewall.logConfig = log_config
|
|
|
|
if args.IsSpecified(
|
|
'resource_manager_tags'
|
|
):
|
|
firewall.params = self._CreateFirewallParams(
|
|
client.messages, args.resource_manager_tags
|
|
)
|
|
|
|
return firewall, firewall_ref.project
|
|
|
|
def _CreateFirewallParams(self, messages, resource_manager_tags):
|
|
resource_manager_tags_map = (
|
|
resource_manager_tags_utils.GetResourceManagerTags(
|
|
resource_manager_tags
|
|
)
|
|
)
|
|
params = messages.FirewallParams
|
|
additional_properties = [
|
|
params.ResourceManagerTagsValue.AdditionalProperty(key=key, value=value)
|
|
for key, value in sorted(six.iteritems(resource_manager_tags_map))
|
|
]
|
|
return params(
|
|
resourceManagerTags=params.ResourceManagerTagsValue(
|
|
additionalProperties=additional_properties
|
|
)
|
|
)
|
|
|
|
def Run(self, args):
|
|
"""Issues requests necessary for adding firewall rules."""
|
|
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
|
|
client = holder.client
|
|
|
|
firewall, project = self._CreateFirewall(holder, args)
|
|
request = client.messages.ComputeFirewallsInsertRequest(
|
|
firewall=firewall, project=project)
|
|
with progress_tracker.ProgressTracker(
|
|
'Creating firewall',
|
|
autotick=False
|
|
) as tracker:
|
|
return client.MakeRequests([(client.apitools_client.firewalls, 'Insert',
|
|
request)], progress_tracker=tracker)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.BETA)
|
|
class BetaCreate(Create):
|
|
"""Create a Compute Engine firewall rule."""
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
messages = apis.GetMessagesModule('compute',
|
|
compute_api.COMPUTE_BETA_API_VERSION)
|
|
parser.display_info.AddFormat(flags.DEFAULT_LIST_FORMAT)
|
|
cls.FIREWALL_RULE_ARG = flags.FirewallRuleArgument()
|
|
cls.FIREWALL_RULE_ARG.AddArgument(parser, operation_type='create')
|
|
cls.NETWORK_ARG = network_flags.NetworkArgumentForOtherResource(
|
|
'The network to which this rule is attached.', required=False)
|
|
firewalls_utils.AddCommonArgs(
|
|
parser,
|
|
for_update=False,
|
|
with_egress_support=True,
|
|
with_service_account=True)
|
|
firewalls_utils.AddArgsForServiceAccount(parser, for_update=False)
|
|
flags.AddEnableLogging(parser)
|
|
flags.AddLoggingMetadata(parser, messages)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
|
|
class AlphaCreate(BetaCreate):
|
|
"""Create a Compute Engine firewall rule."""
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
messages = apis.GetMessagesModule('compute',
|
|
compute_api.COMPUTE_ALPHA_API_VERSION)
|
|
parser.display_info.AddFormat(flags.DEFAULT_LIST_FORMAT)
|
|
cls.FIREWALL_RULE_ARG = flags.FirewallRuleArgument()
|
|
cls.FIREWALL_RULE_ARG.AddArgument(parser, operation_type='create')
|
|
cls.NETWORK_ARG = network_flags.NetworkArgumentForOtherResource(
|
|
'The network to which this rule is attached.', required=False)
|
|
firewalls_utils.AddCommonArgs(
|
|
parser,
|
|
for_update=False,
|
|
with_egress_support=True,
|
|
with_service_account=True)
|
|
firewalls_utils.AddArgsForServiceAccount(parser, for_update=False)
|
|
flags.AddEnableLogging(parser)
|
|
flags.AddLoggingMetadata(parser, messages)
|
|
|
|
|
|
Create.detailed_help = {
|
|
'brief': 'Create a Compute Engine firewall rule.',
|
|
'DESCRIPTION': """
|
|
*{command}* is used to create firewall rules to allow/deny
|
|
incoming/outgoing traffic.
|
|
""",
|
|
'EXAMPLES': """
|
|
To create a firewall rule allowing incoming TCP traffic on port 8080, run:
|
|
|
|
$ {command} example-service --allow=tcp:8080
|
|
--description="Allow incoming traffic on TCP port 8080" --direction=INGRESS
|
|
|
|
To create a firewall rule that allows TCP traffic through port 80 and
|
|
determines a list of specific IP address blocks that are allowed to make
|
|
inbound connections, run:
|
|
|
|
$ {command} tcp-rule --allow=tcp:80
|
|
--source-ranges="10.0.0.0/22,10.0.0.0/14" --description="Narrowing TCP traffic"
|
|
|
|
To list existing firewall rules, run:
|
|
|
|
$ gcloud compute firewall-rules list
|
|
|
|
For more detailed examples see
|
|
[](https://cloud.google.com/vpc/docs/using-firewalls)
|
|
""",
|
|
}
|