/src/Network/Network/AzureFirewall/NatRule/NewAzureFirewallNatRuleCommand.cs

https://github.com/Azure/azure-powershell · C# · 184 lines · 141 code · 25 blank · 18 comment · 23 complexity · 620e1093d0db3a31f78c8c86b0d5eada MD5 · raw file

  1. // ----------------------------------------------------------------------------------
  2. //
  3. // Copyright Microsoft Corporation
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. // ----------------------------------------------------------------------------------
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Linq;
  17. using System.Management.Automation;
  18. using System.Text.RegularExpressions;
  19. using Microsoft.Azure.Commands.Network.Models;
  20. using MNM = Microsoft.Azure.Management.Network.Models;
  21. namespace Microsoft.Azure.Commands.Network
  22. {
  23. [Cmdlet(VerbsCommon.New, ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "FirewallNatRule", SupportsShouldProcess = true), OutputType(typeof(PSAzureFirewallNatRule))]
  24. public class NewAzureFirewallNatRuleCommand : AzureFirewallBaseCmdlet
  25. {
  26. [Parameter(
  27. Mandatory = true,
  28. HelpMessage = "The name of the NAT Rule")]
  29. [ValidateNotNullOrEmpty]
  30. public virtual string Name { get; set; }
  31. [Parameter(
  32. Mandatory = false,
  33. HelpMessage = "The description of the rule")]
  34. [ValidateNotNullOrEmpty]
  35. public string Description { get; set; }
  36. [Parameter(
  37. Mandatory = false,
  38. HelpMessage = "The source addresses of the rule")]
  39. public string[] SourceAddress { get; set; }
  40. [Parameter(
  41. Mandatory = false,
  42. HelpMessage = "The source ipgroup of the rule")]
  43. public string[] SourceIpGroup { get; set; }
  44. [Parameter(
  45. Mandatory = true,
  46. HelpMessage = "The destination addresses of the rule")]
  47. [ValidateNotNullOrEmpty]
  48. public string[] DestinationAddress { get; set; }
  49. [Parameter(
  50. Mandatory = true,
  51. HelpMessage = "The destination ports of the rule")]
  52. [ValidateNotNullOrEmpty]
  53. public string[] DestinationPort { get; set; }
  54. [Parameter(
  55. Mandatory = true,
  56. HelpMessage = "The protocols of the rule")]
  57. [ValidateSet(
  58. MNM.AzureFirewallNetworkRuleProtocol.Any,
  59. MNM.AzureFirewallNetworkRuleProtocol.TCP,
  60. MNM.AzureFirewallNetworkRuleProtocol.UDP,
  61. IgnoreCase = false)]
  62. public string[] Protocol { get; set; }
  63. [Parameter(
  64. Mandatory = false,
  65. HelpMessage = "The translated address for this NAT rule")]
  66. [ValidateNotNullOrEmpty]
  67. public string TranslatedAddress { get; set; }
  68. [Parameter(
  69. Mandatory = false,
  70. HelpMessage = "The translated FQDN for this NAT rule")]
  71. [ValidateNotNullOrEmpty]
  72. public string TranslatedFqdn { get; set; }
  73. [Parameter(
  74. Mandatory = true,
  75. HelpMessage = "The translated port for this NAT rule")]
  76. [ValidateNotNullOrEmpty]
  77. public string TranslatedPort { get; set; }
  78. public override void Execute()
  79. {
  80. base.Execute();
  81. // Add some validation based on the type of RuleCollection (SNAT will be supported later)
  82. // if (MNM.AzureFirewallNatRCActionType.Dnat.Equals(ActionType))
  83. {
  84. // One of SourceAddress or SourceIpGroup must be present
  85. if ((SourceAddress == null) && (SourceIpGroup == null))
  86. {
  87. throw new ArgumentException("Either SourceAddress or SourceIpGroup is required.");
  88. }
  89. if (DestinationAddress.Length != 1)
  90. {
  91. throw new ArgumentException("Only one destination address is accepted.", nameof(DestinationAddress));
  92. }
  93. if (DestinationPort.Length != 1)
  94. {
  95. throw new ArgumentException("Only one destination port is accepted.", nameof(DestinationPort));
  96. }
  97. ValidateIsSingleIpNotRange(DestinationAddress.Single());
  98. if (TranslatedAddress != null)
  99. {
  100. ValidateIsSingleIpNotRange(TranslatedAddress);
  101. }
  102. if (TranslatedFqdn != null)
  103. {
  104. ValidateIsFqdn(TranslatedFqdn);
  105. }
  106. // Only one of TranslatedAddress or TranslatedFqdn is allowed
  107. if ((TranslatedAddress != null) && (TranslatedFqdn != null))
  108. {
  109. throw new ArgumentException("Both TranslatedAddress and TranslatedFqdn not allowed");
  110. }
  111. // One of TranslatedAddress or TranslatedFqdn must be present
  112. if ((TranslatedAddress == null) && (TranslatedFqdn == null))
  113. {
  114. throw new ArgumentException("Either TranslatedAddress or TranslatedFqdn is required");
  115. }
  116. ValidateIsSinglePortNotRange(DestinationPort.Single());
  117. ValidateIsSinglePortNotRange(TranslatedPort);
  118. }
  119. var natRule = new PSAzureFirewallNatRule
  120. {
  121. Name = this.Name,
  122. Description = this.Description,
  123. Protocols = this.Protocol?.ToList(),
  124. SourceAddresses = this.SourceAddress?.ToList(),
  125. SourceIpGroups = this.SourceIpGroup?.ToList(),
  126. DestinationAddresses = this.DestinationAddress?.ToList(),
  127. DestinationPorts = this.DestinationPort?.ToList(),
  128. TranslatedAddress = this.TranslatedAddress,
  129. TranslatedFqdn = this.TranslatedFqdn,
  130. TranslatedPort = this.TranslatedPort
  131. };
  132. WriteObject(natRule);
  133. }
  134. private void ValidateIsSingleIpNotRange(string ipStr)
  135. {
  136. var singleIpRegEx = new Regex("^((\\d){1,3}\\.){3}((\\d){1,3})$");
  137. if (!singleIpRegEx.IsMatch(ipStr))
  138. {
  139. throw new ArgumentException($"Invalid value {ipStr}. Only a single IPv4 value is accepted (e.g. 10.1.2.3).");
  140. }
  141. }
  142. private void ValidateIsSinglePortNotRange(string portStr)
  143. {
  144. uint parsed;
  145. if (!uint.TryParse(portStr, out parsed))
  146. {
  147. throw new ArgumentException($"Invalid value {portStr}. Only a single port value is accepted (e.g. 8080).");
  148. }
  149. }
  150. private void ValidateIsFqdn(string fqdn)
  151. {
  152. var fqdnRegEx = new Regex("^[a-zA-Z0-9]+(([a-zA-Z0-9_\\-]*[a-zA-Z0-9]+)*\\.)*(?:[a-zA-Z0-9]{2,})$");
  153. if (!fqdnRegEx.IsMatch(fqdn))
  154. {
  155. throw new ArgumentException($"Invalid value {fqdn}.");
  156. }
  157. }
  158. }
  159. }