group-based-policy/doc/source/devref/abstraction.rst
zhangdebo 3de52ec950 Replace Chinese quotes to English quotes
Change-Id: Ib76be11ae6208898140c1c64953356ce296ac67d
2018-02-12 10:41:23 +08:00

25 KiB

Group-Based Policy Abstraction

The OpenStack networking model of networks, ports, subnets, routers, and security groups provides the necessary building blocks to build a logical network topology for connectivity. However, it does not provide the right level of abstraction for an application administrator who understands the application's details (like application port numbers), but not the infrastructure details likes networks and routes. Not only that, the current abstraction puts the burden of maintaining the consistency of the network topology on the user. The lack of application developer/administrator focussed abstractions supported by a declarative model make it hard for those users to consume the existing connectivity layer.

The GBP framework complements the OpenStack networking model with the notion of policies that can be applied between groups of network endpoints. As users look beyond basic connectivity, richer network services with diverse implementations and network properties are naturally expressed as policies. Examples include service chaining, QoS, path properties, access control, etc.

The model allows application administrators to express their networking requirements using group and policy abstractions, with the specifics of policy enforcement and implementation left to the underlying policy driver. The main advantage of the abstractions described here is that they allow for an application-centric interface to OpenStack networking.

These abstractions achieve the following:

  • Show clear separation of concerns between application and infrastructure administrator.
    • The application administrator can then deal with a higher level abstraction that does not concern itself with networking specifics like networks/routers/etc.
    • The infrastructure administrator will deal with infrastructure specific policy abstractions and not have to understand application specific concerns like specific ports that have been opened or which of them expect to be limited to secure or insecure traffic. The infrastructure admin will also have ability to direct which technologies and approaches used in rendering. For example, if VLAN or VxLAN is used.
    • Allow the infrastructure admin to introduce connectivity constraints without the application administrator having to be aware of it (e.g. audit all traffic between two application tiers).
  • Allow for independent provider/consumer model with late binding and n-to-m relationships between them.
  • Allow for automatic orchestration that can respond to changes in policy or infrastructure without requiring human interaction to translate intent to specific actions.
  • Complement the governance model proposed in the OpenStack Congress project by making Policy Tags available for enforcement.

Terminology

Policy Target (PT): It is the smallest unit of resource abstraction at which policy can be applied.

Policy Target Group (PTG): A collection of policy targets.

Policy Rule Set (PRS): It defines how the application services provided by a PTG can be accessed. In effect it specifies how a PTG communicates with other PTGs. A Policy Rule Set consists of Policy Rules.

Policy Rule (PR): These are individual rules used to define the communication criteria between PTGs. Each rule contains a Filter, Classifier, and Action.

Policy Classifier: Characterizes the traffic that a particular Policy Rule acts on. Corresponding action is taken on traffic that satisfies this classification criteria.

Policy Action: The action that is taken for a matching Policy Rule defined in a Policy Rule Set.

L2 Policy (L2P): Used to define a L2 boundary and impose additional constraints (such as no broadcast) within that L2 boundary.

L3 Policy (L3P): Used to define a non-overlapping IP address space.

Network Service Policy (NSP): Used to define policies that are used for assigning resources in a PTG to be consumed by network services.

Resource Model

RESOURCE_ATTRIBUTE_MAP = {
   POLICY_TARGETS: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None}, 'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None}, 'default': '',
                'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True, 'is_visible': True},
       'policy_target_group_id': {'allow_post': True, 'allow_put': True,
                                  'validate': {'type:uuid_or_none': None},
                                  'required': True, 'is_visible': True},
       'cluster_id': {'allow_post': True, 'allow_put': True,
                      'validate': {'type:string': None},
                      'default': '', 'is_visible': True}
   },
   POLICY_TARGET_GROUPS: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None}, 'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True, 'is_visible': True},
       'policy_targets': {'allow_post': False, 'allow_put': False,
                          'validate': {'type:uuid_list': None},
                          'convert_to': attr.convert_none_to_empty_list,
                          'default': None, 'is_visible': True},
       'l2_policy_id': {'allow_post': True, 'allow_put': True,
                        'validate': {'type:uuid_or_none': None},
                        'default': None, 'is_visible': True},
       'provided_policy_rule_sets': {'allow_post': True, 'allow_put': True,
                                     'validate': {'type:dict_or_none': None},
                                     'convert_to':
                                     attr.convert_none_to_empty_dict,
                                     'default': None, 'is_visible': True},
       'consumed_policy_rule_sets': {'allow_post': True, 'allow_put': True,
                                     'validate': {'type:dict_or_none': None},
                                     'convert_to':
                                     attr.convert_none_to_empty_dict,
                                     'default': None, 'is_visible': True},
       'network_service_policy_id': {'allow_post': True, 'allow_put': True,
                                     'validate': {'type:uuid_or_none': None},
                                     'default': None, 'is_visible': True},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
       'service_management': {'allow_post': True, 'allow_put': True,
                              'default': False,
                              'convert_to': attr.convert_to_boolean,
                              'is_visible': True, 'required_by_policy': True,
                              'enforce_policy': True},
   },
   L2_POLICIES: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None}, 'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True, 'is_visible': True},
       'policy_target_groups': {'allow_post': False, 'allow_put': False,
                                'validate': {'type:uuid_list': None},
                                'convert_to': attr.convert_none_to_empty_list,
                                'default': None, 'is_visible': True},
       'l3_policy_id': {'allow_post': True, 'allow_put': True,
                        'validate': {'type:uuid_or_none': None},
                        'default': None, 'is_visible': True,
                        'required': True},
       'inject_default_route': {'allow_post': True, 'allow_put': True,
                                'default': True, 'is_visible': True,
                                'convert_to': attr.convert_to_boolean,
                                'required': False},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
                   'required': False},
   },
   L3_POLICIES: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None}, 'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True, 'is_visible': True},
       'ip_version': {'allow_post': True, 'allow_put': False,
                      'convert_to': attr.convert_to_int,
                      'validate': {'type:values': [4, 6]},
                      'default': 4, 'is_visible': True},
       'ip_pool': {'allow_post': True, 'allow_put': False,
                   'validate': {'type:subnet': None},
                   'default': '10.0.0.0/8', 'is_visible': True},
       'subnet_prefix_length': {'allow_post': True, 'allow_put': True,
                                'convert_to': attr.convert_to_int,
                                # for ipv4 legal values are 2 to 30
                                # for ipv6 legal values are 2 to 127
                                'default': 24, 'is_visible': True},
       'l2_policies': {'allow_post': False, 'allow_put': False,
                       'validate': {'type:uuid_list': None},
                       'convert_to': attr.convert_none_to_empty_list,
                       'default': None, 'is_visible': True},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
       'external_segments': {
           'allow_post': True, 'allow_put': True, 'default': None,
           'validate': {'type:external_dict': None},
           'convert_to': attr.convert_none_to_empty_dict, 'is_visible': True},
   },
   POLICY_CLASSIFIERS: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None},
              'is_visible': True, 'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True,
                     'is_visible': True},
       'protocol': {'allow_post': True, 'allow_put': True,
                    'is_visible': True, 'default': None,
                    'convert_to': convert_protocol},
       'port_range': {'allow_post': True, 'allow_put': True,
                      'validate': {'type:gbp_port_range': None},
                      'convert_to': convert_port_to_string,
                      'default': None, 'is_visible': True},
       'direction': {'allow_post': True, 'allow_put': True,
                     'validate': {'type:values': gp_supported_directions},
                     'default': gp_constants.GP_DIRECTION_BI,
                     'is_visible': True},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
   },
   POLICY_ACTIONS: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None},
              'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True,
                     'is_visible': True},
       'action_type': {'allow_post': True, 'allow_put': False,
                       'convert_to': convert_action_to_case_insensitive,
                       'validate': {'type:values': gp_supported_actions},
                       'is_visible': True, 'default': 'allow'},
       'action_value': {'allow_post': True, 'allow_put': True,
                        'validate': {'type:uuid_or_none': None},
                        'default': None, 'is_visible': True},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
   },
   POLICY_RULES: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None},
              'is_visible': True, 'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True, 'is_visible': True},
       'enabled': {'allow_post': True, 'allow_put': True,
                   'default': True, 'convert_to': attr.convert_to_boolean,
                   'is_visible': True},
       'policy_classifier_id': {'allow_post': True, 'allow_put': True,
                                'validate': {'type:uuid': None},
                                'is_visible': True, 'required': True},
       'policy_actions': {'allow_post': True, 'allow_put': True,
                          'default': None, 'is_visible': True,
                          'validate': {'type:uuid_list': None},
                          'convert_to': attr.convert_none_to_empty_list},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
   },
   POLICY_RULE_SETS: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None},
              'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '',
                'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True,
                     'is_visible': True},
       'parent_id': {'allow_post': False, 'allow_put': False,
                     'validate': {'type:uuid': None},
                     'is_visible': True},
       'child_policy_rule_sets': {'allow_post': True, 'allow_put': True,
                                  'default': None, 'is_visible': True,
                                  'validate': {'type:uuid_list': None},
                                  'convert_to':
                                  attr.convert_none_to_empty_list},
       'policy_rules': {'allow_post': True, 'allow_put': True,
                        'default': None, 'validate': {'type:uuid_list': None},
                        'convert_to': attr.convert_none_to_empty_list,
                        'is_visible': True},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
   },
   NETWORK_SERVICE_POLICIES: {
       'id': {'allow_post': False, 'allow_put': False,
              'validate': {'type:uuid': None}, 'is_visible': True,
              'primary_key': True},
       'name': {'allow_post': True, 'allow_put': True,
                'validate': {'type:gbp_resource_name': None},
                'default': '', 'is_visible': True},
       'description': {'allow_post': True, 'allow_put': True,
                       'validate': {'type:string': None},
                       'is_visible': True, 'default': ''},
       'tenant_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:string': None},
                     'required_by_policy': True, 'is_visible': True},
       'policy_target_groups': {'allow_post': False, 'allow_put': False,
                                'validate': {'type:uuid_list': None},
                                'convert_to': attr.convert_none_to_empty_list,
                                'default': None, 'is_visible': True},
       'network_service_params': {'allow_post': True, 'allow_put': False,
                                  'validate':
                                  {'type:network_service_params': None},
                                  'default': None, 'is_visible': True},
       attr.SHARED: {'allow_post': True, 'allow_put': True,
                     'default': False, 'convert_to': attr.convert_to_boolean,
                     'is_visible': True, 'required_by_policy': True,
                     'enforce_policy': True},
   }

The following defines the mapping to Neutron resources using attribute extension:

EXTENDED_ATTRIBUTES_2_0 = {
  gp.POLICY_TARGETS: {
      'port_id': {'allow_post': True, 'allow_put': False,
                  'validate': {'type:uuid_or_none': None},
                  'is_visible': True, 'default': None},
      'fixed_ips': {'allow_post': True, 'allow_put': True,
                    'default': attr.ATTR_NOT_SPECIFIED,
                    'convert_list_to': attr.convert_kvp_list_to_dict,
                    'validate': {'type:fixed_ips': None},
                    'enforce_policy': True,
                    'is_visible': True},
  },
  gp.POLICY_TARGET_GROUPS: {
      'subnets': {'allow_post': True, 'allow_put': True,
                  'validate': {'type:uuid_list': None},
                  'convert_to': attr.convert_none_to_empty_list,
                  'is_visible': True, 'default': None},
  },
  gp.L2_POLICIES: {
      'network_id': {'allow_post': True, 'allow_put': False,
                     'validate': {'type:uuid_or_none': None},
                     'is_visible': True, 'default': None},
  },
  gp.L3_POLICIES: {
      'routers': {'allow_post': True, 'allow_put': True,
                  'validate': {'type:uuid_list': None},
                  'convert_to': attr.convert_none_to_empty_list,
                  'is_visible': True, 'default': None},
  }
}
All resources have the following common attributes:
  • id - standard object uuid
  • name - optional name
  • description - optional annotation

The ip_pool in L2Policies is a supernet used for implicitly assigning subnets to PTGs.

The subnet_prefix_length in L2Policies is the default subnet length used when implicitly assigning a subnet to a PTG.

The way ip_pool and subnet_prefix_length work is as follows: When creating L3Policy a default ip_pool and default_subnet_prefix_length are created. If a user creates a PTG, a subnet will be pulled from ip_pool using default_subnet_prefix_length.

The protocol in PolicyClassifier supports names "tcp", "icmp", "udp" and protocol numbers 0 to 255 are supported.

The port range in PolicyClassifier port range can be a single port number or a range (separated by a colon).

The direction in PolicyClassifier direction can be "in", "out", or "bi".

The type in PolicyAction type can be "allow" or "redirect".

The value in PolicyAction is used only in the case of "redirect" and corresponds to a service_chain_spec.

The default route injection in VMs can be controlled by using the inject_default_route in the L2Policies. This is set to True by default. When set to False, the default route propagation is suppressed for all the PTGs belonging to a specific L2Policy. This is useful in the cases when a VM is associated with more than one PTG, and we want it to get a specific default route and suppress others.

NetworkServiceParams
  • type - Is one of "ip_single", "ip_pool", "string"
  • name - A user-defined string, e.g. vip
  • value - String, e.g. self_subnet or external_subnet when the type is ip_single or ip_pool; a string value when the type is string The type and value are validated, the name is treated as a literal. The name of the param is chosen by the service chain implementation, and as such is validated by the service chain provider. The supported types are: ip_single, ip_pool, string. The supported values are: self_subnet and external_subnet, but the values are not validated when the tpye is 'string'. Valid combinations are: ip_single, self_subnet: Allocate a single IP addr from ptg subnet, e.g. VIP (in the private network) ip_single, external_subnet: Allocate a single floating-ip addr, e.g. Public address for the VIP ip_pool, external_subnet: Allocate a floating-ip for every PT in PTG

Database models

Database Objects to support Group-Based Policy:

+----------+        +-------------+
|          |        |             |
|  Policy  |        |  Policy     |
|  Target  |1      *|  Rule       |
|  Groups  +-------->  Sets       |
|  (PTG)   |        |  (PRS)      |
|          |        |             |
+----------+        +-------------+
     1|                   1|
      |                    |
      |*                   |*
+-----v----+        +------v------+       +-------------+
|          |        |             |       |             |
|  Policy  |        |  Policy     |1     *| Policy      |
|  Targets |        |  Rules      +-------> Actions     |
|  (PT)    |        |  (PR)       |       | (PA)        |
|          |        |             |       |             |
+----------+        +-------------+       +-------------+
                          1|
                           |
                           |1
                    +------v------+
                    |             |
                    | Policy      |
                    | Classifiers |
                    | (PC)        |
                    |             |
                    +-------------+

 * [0..n]

Internals

The GBP plugin class is located at gbpservice/neutron/services/grouppolicy/plugin.py:GroupPolicyPlugin. The GBP plugin driver that maps resources to Neutron is located at gbpservice/neutron/services/grouppolicy/drivers/resource_mapping.py:ResourceMappingDriver.