cloud-8.x-2.0-beta1/modules/cloud_service_providers/aws_cloud/src/Form/Ec2/SecurityGroupEditForm.php

modules/cloud_service_providers/aws_cloud/src/Form/Ec2/SecurityGroupEditForm.php
<?php

namespace Drupal\aws_cloud\Form\Ec2;

use Drupal\Core\Form\FormStateInterface;
use Drupal\aws_cloud\Entity\Ec2\SecurityGroup;
use Drupal\aws_cloud\Plugin\Field\FieldType\IpPermission;

use Aws\Result;

/**
 * Form controller for the CloudScripting entity edit forms.
 *
 * @ingroup aws_cloud
 */
class SecurityGroupEditForm extends AwsCloudContentForm {

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::buildForm().
   */
  public function buildForm(array $form, FormStateInterface $form_state, $cloud_context = '') {
    $this->ec2Service->setCloudContext($cloud_context);

    /* @var $entity \Drupal\aws_cloud\Entity\Ec2\SecurityGroup */
    $form = parent::buildForm($form, $form_state);

    $entity = $this->entity;

    $weight = -50;

    $form['security_group'] = [
      '#type' => 'details',
      '#title' => $this->t('Security Group'),
      '#open' => TRUE,
      '#weight' => $weight++,
    ];

    $form['security_group']['name'] = [
      '#type'          => 'textfield',
      '#title'         => $this->t('Name'),
      '#maxlength'     => 255,
      '#size'          => 60,
      '#default_value' => $entity->label(),
      '#required'      => TRUE,
    ];

    $form['security_group']['group_id'] = [
      '#type'          => 'item',
      '#title'         => $this->getItemTitle($this->t('ID')),
      '#markup'        => $entity->getGroupId(),
    ];

    $form['security_group']['group_name'] = [
      '#type'          => 'item',
      '#title'         => $this->getItemTitle($this->t('Security Group Name')),
      '#markup'        => $entity->getGroupName(),
    ];

    $form['security_group']['description'] = [
      '#type'          => 'item',
      '#title'         => $this->getItemTitle($this->t('Description')),
      '#markup'        => $entity->getDescription(),
    ];

    $form['security_group']['vpc_id'] = [
      '#type'          => 'item',
      '#title'         => $this->getItemTitle($this->t('VPC ID')),
      '#markup'        => $entity->getVpcId(),
    ];

    $form['security_group']['created'] = [
      '#type'          => 'item',
      '#title'         => $this->getItemTitle($this->t('Created')),
      '#markup'        => $this->dateFormatter->format($entity->created(), 'short'),
    ];

    // Put all rules into HTML5 details.
    $form['rules'] = [
      '#type' => 'details',
      '#title' => $this->t('Rules'),
      '#open' => FALSE,
      '#weight' => $weight++,
    ];

    $form['rules'][] = $form['ip_permission'];

    if (!empty($entity->getVpcId())) {
      $form['rules'][] = $form['outbound_permission'];

    }
    unset($form['ip_permission']);
    unset($form['outbound_permission']);

    $this->addOthersFieldset($form, $weight++, $cloud_context);

    $form['#attached']['library'][] = 'aws_cloud/aws_cloud_security_groups';

    if (isset($form['actions'])) {
      $form['actions']['submit']['#weight'] = $weight++;
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    // Call copyFormItemValues() to ensure the form array is intact.
    $this->copyFormItemValues($form);

    $this->trimTextfields($form, $form_state);

    $entity = $this->entity;

    $this->ec2Service->setCloudContext($entity->getCloudContext());
    if ($entity->save()) {

      $this->setTagsInAws($entity->getGroupId(), [
        SecurityGroup::TAG_CREATED_BY_UID => $entity->getOwner()->id(),
        'Name' => $entity->getName(),
      ]);

      // Fetch the most up to date security group data from Ec2.
      $existing_group = $this->ec2Service->describeSecurityGroups([
        'GroupIds' => [$entity->getGroupId()],
      ]);

      // Update the inbound permissions.
      $inbound_result = $this->updateInboundPermissions($existing_group);

      // Update the outbound permissions.  This only applies to
      // VPC security groups.
      $outbound_result = TRUE;
      if (!empty($entity->getVpcId())) {
        $outbound_result = $this->updateOutboundPermissions($existing_group);
      }

      if (!$inbound_result && !$outbound_result) {
        $this->messenger->addError($this->t("Inbound and Outbound Rules couldn't be saved because of the error from AWS."));
      }
      elseif (!$inbound_result) {
        $this->messenger->addError($this->t("Inbound Rules couldn't be saved because of the error from AWS."));
      }
      elseif (!$outbound_result) {
        $this->messenger->addError($this->t("Outbound Rules couldn't be saved because of the error from AWS."));
      }

      // Have the system refresh the security group.
      $this->ec2Service->updateSecurityGroups([
        'GroupIds' => [$this->entity->getGroupId()],
      ], FALSE);

      if (count($this->messenger->messagesByType('error')) === 0) {
        // Check API calls, see if the permissions updates were
        // successful or not.
        $this->validateAuthorize($entity);
        $form_state->setRedirect('entity.aws_cloud_security_group.canonical', [
          'cloud_context' => $entity->getCloudContext(),
          'aws_cloud_security_group' => $entity->id(),
        ]);
      }
    }
    else {
      $this->messenger->addError($this->t('Unable to update security group.'));
    }

    if (count($this->messenger->messagesByType('error')) > 0) {
      $form_state->setRebuild();
    }

  }

  /**
   * Helper method to update the inbound permissions.
   *
   * @param \Aws\Result $existing_group
   *   Existing group.
   */
  protected function updateInboundPermissions(Result $existing_group) {
    $permissions = [];

    if (isset($existing_group['SecurityGroups']) && isset($existing_group['SecurityGroups'][0]['IpPermissions'])) {
      $security_group = $this->formatIpPermissionForRevoke($existing_group['SecurityGroups'][0]['IpPermissions']);

      if (count($security_group) > 0) {
        // Delete the existing permissions.
        $this->ec2Service->revokeSecurityGroupIngress([
          'GroupId' => $this->entity->getGroupId(),
          'IpPermissions' => $security_group,
        ]);
      }
    }

    // Setup the ip_permissions array.
    $iterator = $this->entity->getIpPermission()->getIterator();
    while ($iterator->valid()) {
      // Add the permission to the IpPermissions objects.
      $permissions['IpPermissions'][] = $this->formatIpPermissionForAuthorize($iterator->current());
      $iterator->next();
    }

    // Re-add the permissions if they are specified.
    if (isset($permissions['IpPermissions']) && count($permissions['IpPermissions'])) {
      // Setup permissions array for AuthorizeSecurityGroupIngress.
      $permissions['GroupId'] = $this->entity->getGroupId();
      $this->ec2Service->authorizeSecurityGroupIngress($permissions);

      if (count($this->messenger->messagesByType('error')) >= 1) {
        if (count($existing_group['SecurityGroups'][0]['IpPermissions']) > 0) {
          // If the error occurs, resave rules of AWS resource.
          $existing_permissions = [];
          $existing_permissions['GroupId'] = $this->entity->getGroupId();
          foreach ($existing_group['SecurityGroups'][0]['IpPermissions'] as $permission) {
            foreach ($permission as $key => $value) {
              if ($value !== 0 && $value !== FALSE && empty($value)) {
                unset($permission[$key]);
              }
            }
            $existing_permissions['IpPermissions'][] = $permission;
          }
          $this->ec2Service->authorizeSecurityGroupIngress($existing_permissions);
        }
        return FALSE;
      }
    }
    return TRUE;
  }

  /**
   * Helper method to update the outbound permissions.
   *
   * @param \Aws\Result $existing_group
   *   Existing group.
   */
  protected function updateOutboundPermissions(Result $existing_group) {
    $permissions = [];
    if (isset($existing_group['SecurityGroups']) && isset($existing_group['SecurityGroups'][0]['IpPermissionsEgress'])) {
      $security_group = $this->formatIpPermissionForRevoke($existing_group['SecurityGroups'][0]['IpPermissionsEgress']);

      if (count($security_group) > 0) {
        // Delete the existing egress permissions.
        $this->ec2Service->revokeSecurityGroupEgress([
          'GroupId' => $this->entity->getGroupId(),
          'IpPermissions' => $security_group,
        ]);
      }
    }
    // Setup the ip_permissions array.
    $iterator = $this->entity->getOutboundPermission()->getIterator();
    while ($iterator->valid()) {
      // Add the permission to the IPPermissions objects.
      $permissions['IpPermissions'][] = $this->formatIpPermissionForAuthorize($iterator->current(), TRUE);
      $iterator->next();
    }

    if (isset($permissions['IpPermissions']) && count($permissions['IpPermissions'])) {
      $error_count = count($this->messenger->messagesByType('error'));
      // Setup permissions array for AuthorizeSecurityGroupIngress.
      $permissions['GroupId'] = $this->entity->getGroupId();
      $this->ec2Service->authorizeSecurityGroupEgress($permissions);

      if (count($this->messenger->messagesByType('error')) > $error_count) {
        if (count($existing_group['SecurityGroups'][0]['IpPermissionsEgress']) > 0) {
          // If the error occurs, resave rules of AWS resource.
          $existing_permissions = [];
          $existing_permissions['GroupId'] = $this->entity->getGroupId();
          foreach ($existing_group['SecurityGroups'][0]['IpPermissionsEgress'] as $permission) {
            foreach ($permission as $key => $value) {
              if ($value !== 0 && $value !== FALSE && empty($value)) {
                unset($permission[$key]);
              }
            }
            $existing_permissions['IpPermissions'][] = $permission;
          }
          $this->ec2Service->authorizeSecurityGroupEgress($existing_permissions);
        }
        return FALSE;
      }
    }
    return TRUE;
  }

  /**
   * Format the IpPermission object.
   *
   * Format returned from the DescribeSecurityGroup
   * Amazon EC2 API call.  This method unset array objects that have no values.
   *
   * @param array $security_group
   *   The security group.
   *
   * @return array
   *   Formatted IpPermission object.
   */
  protected function formatIpPermissionForRevoke(array $security_group) {
    foreach ($security_group as $key => $group) {
      if (!isset($group['IpRanges']) || count($group['IpRanges']) == 0) {
        unset($security_group[$key]['IpRanges']);
      }
      if (!isset($group['Ipv6Ranges']) || count($group['Ipv6Ranges']) == 0) {
        unset($security_group[$key]['Ipv6Ranges']);
      }
      if (!isset($group['UserIdGroupPairs']) || count($group['UserIdGroupPairs']) == 0) {
        unset($security_group[$key]['UserIdGroupPairs']);
      }
      if (!isset($group['PrefixListIds']) || count($group['PrefixListIds']) == 0) {
        unset($security_group[$key]['PrefixListIds']);
      }
      if (isset($group['UserIdGroupPairs']) && count($group['UserIdGroupPairs']) > 0) {
        // Loop them and unset GroupName.
        foreach ($group['UserIdGroupPairs'] as $pair_keys => $pairs) {
          unset($security_group[$key]['UserIdGroupPairs'][$pair_keys]['GroupName']);
        }
      }
    }
    return $security_group;
  }

  /**
   * Format the IpPermission object.
   *
   * Format the IpPermission object for use with
   * the AuthorizeSecurityGroup[Ingress and Egress] Amazon EC2 API call.
   *
   * @param \Drupal\aws_cloud\Plugin\Field\FieldType\IpPermission $ip_permission
   *   The IP permission object.
   * @param bool $outbound
   *   The flag whether the data is outbound.
   *
   * @return array
   *   The permission.
   */
  protected  function formatIpPermissionForAuthorize(IpPermission $ip_permission, $outbound = FALSE) {
    $permission = [
      'FromPort' => (int) $ip_permission->from_port,
      'ToPort' => (int) $ip_permission->to_port,
      'IpProtocol' => $ip_permission->ip_protocol,
    ];
    if ($ip_permission->source == 'ip4') {
      $permission['IpRanges'][]['CidrIp'] = $ip_permission->cidr_ip;
    }
    else {
      if ($ip_permission->source == 'ip6') {
        $permission['Ipv6Ranges'][]['CidrIpv6'] = $ip_permission->cidr_ip_v6;
      }
      else {
        $group = [];
        // Use GroupID if nondefault VPC or EC2-Classic.
        // For other permissions, use Group Name.
        $vpc_id = $this->entity->getVpcId();
        if (!$outbound && $this->entity->isDefaultVpc() == TRUE || !isset($vpc_id)) {
          $security_groups = $this->entityTypeManager
            ->getStorage('aws_cloud_security_group')
            ->loadByProperties([
              'group_id' => $ip_permission->group_id,
            ]);
          if (!empty($security_groups)) {
            $security_group = reset($security_groups);
            $group['GroupName'] = $security_group->getGroupName();
          }
        }
        else {
          $group['GroupId'] = $ip_permission->group_id;
        }
        $group['UserId'] = $ip_permission->user_id;
        $group['PeeringStatus'] = $ip_permission->peering_status;
        $group['VpcId'] = $ip_permission->vpc_id;
        $group['VpcPeeringConnectionId'] = $ip_permission->peering_connection_id;

        $permission['UserIdGroupPairs'][] = $group;
      }
    }
    return $permission;
  }

  /**
   * Verify the authorize call was successful.
   *
   * Since EC2 does not return any error codes from any of the authorize
   * API calls, the only way to verify is to count the permissions array
   * from the current entity,  and the entity that is newly updated from
   * the updateSecurityGroups API call.
   *
   * @param \Drupal\aws_cloud\Entity\Ec2\SecurityGroup $group
   *   The security group.
   */
  protected function validateAuthorize(SecurityGroup $group) {
    /* @var \Drupal\aws_cloud\Entity\Ec2\SecurityGroup $updated_group */
    $updated_group = SecurityGroup::load($group->id());

    if ($group->getIpPermission()->count() !== $updated_group->getIpPermission()->count()) {
      $this->messenger->addError(
        $this->t('Error updating inbound permissions for security group @name', [
          '@name' => $this->entity->label(),
        ])
      );
    }

    if (!empty($group->getVpcId())) {
      if ($group->getOutboundPermission()->count() !== $updated_group->getOutboundPermission()->count()) {
        $this->messenger->addError(
          $this->t('Error updating outbound permissions for security group @name', [
            '@name' => $this->entity->label(),
          ])
        );
      }
    }

    if (count($this->messenger->messagesByType('error')) === 0) {
      // No errors, success.
      $this->messenger->addMessage(
        $this->t('The AWS Cloud Security Group "@name" has been saved.', [
          '@name' => $this->entity->label(),
        ])
      );
    }

  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc