Merge "Replace CRLF by LF"
This commit is contained in:
commit
9c797d08e4
@ -1,6 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- Support Tacker service to obtain an OAuth 2.0 access token from an
|
||||
external authorization server, and then use the access token to access
|
||||
related OpenStack services that uses the external_oauth2_token filter
|
||||
provided by the keystone middleware for permission authentication.
|
||||
---
|
||||
features:
|
||||
- Support Tacker service to obtain an OAuth 2.0 access token from an
|
||||
external authorization server, and then use the access token to access
|
||||
related OpenStack services that uses the external_oauth2_token filter
|
||||
provided by the keystone middleware for permission authentication.
|
||||
|
@ -1,11 +1,11 @@
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: oidc-cluster-admin-binding
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: User
|
||||
name: end-user
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: oidc-cluster-admin-binding
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: User
|
||||
name: end-user
|
||||
|
@ -1,12 +1,12 @@
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
IP.1 = 127.0.0.1
|
@ -1,35 +1,35 @@
|
||||
#
|
||||
# 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.
|
||||
import tacker.vnfm.lcm_user_data.utils as UserDataUtil
|
||||
|
||||
from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData
|
||||
|
||||
|
||||
class SampleUserData(AbstractUserData):
|
||||
@staticmethod
|
||||
def instantiate(base_hot_dict=None,
|
||||
vnfd_dict=None,
|
||||
inst_req_info=None,
|
||||
grant_info=None):
|
||||
api_param = UserDataUtil.get_diff_base_hot_param_from_api(
|
||||
base_hot_dict, inst_req_info)
|
||||
initial_param_dict = \
|
||||
UserDataUtil.create_initial_param_server_port_dict(base_hot_dict)
|
||||
vdu_flavor_dict = \
|
||||
UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict)
|
||||
vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict)
|
||||
cpd_vl_dict = UserDataUtil.create_network_dict(inst_req_info,
|
||||
initial_param_dict)
|
||||
final_param_dict = UserDataUtil.create_final_param_dict(
|
||||
initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict)
|
||||
return {**final_param_dict, **api_param}
|
||||
#
|
||||
# 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.
|
||||
import tacker.vnfm.lcm_user_data.utils as UserDataUtil
|
||||
|
||||
from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData
|
||||
|
||||
|
||||
class SampleUserData(AbstractUserData):
|
||||
@staticmethod
|
||||
def instantiate(base_hot_dict=None,
|
||||
vnfd_dict=None,
|
||||
inst_req_info=None,
|
||||
grant_info=None):
|
||||
api_param = UserDataUtil.get_diff_base_hot_param_from_api(
|
||||
base_hot_dict, inst_req_info)
|
||||
initial_param_dict = \
|
||||
UserDataUtil.create_initial_param_server_port_dict(base_hot_dict)
|
||||
vdu_flavor_dict = \
|
||||
UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict)
|
||||
vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict)
|
||||
cpd_vl_dict = UserDataUtil.create_network_dict(inst_req_info,
|
||||
initial_param_dict)
|
||||
final_param_dict = UserDataUtil.create_final_param_dict(
|
||||
initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict)
|
||||
return {**final_param_dict, **api_param}
|
||||
|
@ -1,72 +1,72 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF template definition
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
|
||||
node_types:
|
||||
Sample.VNF.Node:
|
||||
derived_from: tosca.nodes.nfv.VNF
|
||||
properties:
|
||||
descriptor_id:
|
||||
type: string
|
||||
default: '3b3c61e4-26b6-4686-80fc-e9ff83010c08'
|
||||
descriptor_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
provider:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Sample ] ]
|
||||
default: Sample
|
||||
product_name:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Node ] ]
|
||||
default: Node
|
||||
software_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '10.1' ] ]
|
||||
default: '10.1'
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Tacker ] ]
|
||||
default: [ Tacker ]
|
||||
flavour_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ ha, scalable ] ]
|
||||
default: ha
|
||||
flavour_description:
|
||||
type: string
|
||||
default: 'vnf'
|
||||
requirements:
|
||||
- VNF0_extnet0:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
relationship: tosca.relationships.nfv.VirtualLinksTo
|
||||
occurrences: [ 0, 1 ]
|
||||
- VNF1_extnet0:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
relationship: tosca.relationships.nfv.VirtualLinksTo
|
||||
occurrences: [ 0, 1 ]
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF template definition
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
|
||||
node_types:
|
||||
Sample.VNF.Node:
|
||||
derived_from: tosca.nodes.nfv.VNF
|
||||
properties:
|
||||
descriptor_id:
|
||||
type: string
|
||||
default: '3b3c61e4-26b6-4686-80fc-e9ff83010c08'
|
||||
descriptor_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
provider:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Sample ] ]
|
||||
default: Sample
|
||||
product_name:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Node ] ]
|
||||
default: Node
|
||||
software_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '10.1' ] ]
|
||||
default: '10.1'
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Tacker ] ]
|
||||
default: [ Tacker ]
|
||||
flavour_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ ha, scalable ] ]
|
||||
default: ha
|
||||
flavour_description:
|
||||
type: string
|
||||
default: 'vnf'
|
||||
requirements:
|
||||
- VNF0_extnet0:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
relationship: tosca.relationships.nfv.VirtualLinksTo
|
||||
occurrences: [ 0, 1 ]
|
||||
- VNF1_extnet0:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
relationship: tosca.relationships.nfv.VirtualLinksTo
|
||||
occurrences: [ 0, 1 ]
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
|
@ -1,31 +1,31 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF definitions
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- Common.yaml
|
||||
- df_ha.yaml
|
||||
- df_scalable.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
selected_flavour:
|
||||
type: string
|
||||
description: VNF deployment flavour selected by the consumer. Itis provided in the API.
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_id: { get_input: selected_flavour }
|
||||
flavour_description: 'vnf'
|
||||
descriptor_id: 75aaa9fa-9c79-dcf5-bda2-5b98a08c9f54
|
||||
provider: Sample
|
||||
product_name: Node
|
||||
software_version: '10.1'
|
||||
descriptor_version: '1.0'
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
requirements:
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF definitions
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- Common.yaml
|
||||
- df_ha.yaml
|
||||
- df_scalable.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
selected_flavour:
|
||||
type: string
|
||||
description: VNF deployment flavour selected by the consumer. Itis provided in the API.
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_id: { get_input: selected_flavour }
|
||||
flavour_description: 'vnf'
|
||||
descriptor_id: 75aaa9fa-9c79-dcf5-bda2-5b98a08c9f54
|
||||
provider: Sample
|
||||
product_name: Node
|
||||
software_version: '10.1'
|
||||
descriptor_version: '1.0'
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
requirements:
|
||||
|
@ -1,232 +1,232 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample VNF ha DF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- Common.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
configurable_properties:
|
||||
type: map
|
||||
|
||||
substitution_mappings:
|
||||
node_type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_id: ha
|
||||
requirements:
|
||||
VDU0_extnet: [ VDU0_extCP0, external_virtual_link ]
|
||||
VDU1_extnet: [ VDU1_extCP0, external_virtual_link ]
|
||||
VDU_extnet: [ VDU_extvCP, external_virtual_link ]
|
||||
RT_extnet: [ RT_extCP, external_virtual_link ]
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_description: 'ha'
|
||||
configurable_properties:
|
||||
is_autoscale_enabled: false
|
||||
is_autoheal_enabled: false
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
VDU_0:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_0
|
||||
description: VDU_0
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU_1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_1
|
||||
description: VDU_1
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU0_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_0
|
||||
- virtual_link: VDU_intnet0
|
||||
|
||||
VDU1_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_1
|
||||
- virtual_link: VDU_intnet0
|
||||
|
||||
VDU0_extCP0:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
VDU1_extCP0:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
VDU_intnet0:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 1000000
|
||||
min_bitrate_requirements:
|
||||
root: 100000
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l2_protocol_data:
|
||||
network_type: vxlan
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: '192.168.0.0/24'
|
||||
dhcp_enabled: true
|
||||
|
||||
RT_extCP:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
VDU_extvCP:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
groups:
|
||||
VDU_AntiAffinityGroup:
|
||||
type: tosca.groups.nfv.PlacementGroup
|
||||
members: [ VDU_0, VDU_1 ]
|
||||
|
||||
policies:
|
||||
- VDU_placement_policy:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
targets: [ VDU_AntiAffinityGroup ]
|
||||
properties:
|
||||
scope: nfvi_node
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample VNF ha DF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- Common.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
configurable_properties:
|
||||
type: map
|
||||
|
||||
substitution_mappings:
|
||||
node_type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_id: ha
|
||||
requirements:
|
||||
VDU0_extnet: [ VDU0_extCP0, external_virtual_link ]
|
||||
VDU1_extnet: [ VDU1_extCP0, external_virtual_link ]
|
||||
VDU_extnet: [ VDU_extvCP, external_virtual_link ]
|
||||
RT_extnet: [ RT_extCP, external_virtual_link ]
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_description: 'ha'
|
||||
configurable_properties:
|
||||
is_autoscale_enabled: false
|
||||
is_autoheal_enabled: false
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
VDU_0:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_0
|
||||
description: VDU_0
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU_1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_1
|
||||
description: VDU_1
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU0_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_0
|
||||
- virtual_link: VDU_intnet0
|
||||
|
||||
VDU1_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_1
|
||||
- virtual_link: VDU_intnet0
|
||||
|
||||
VDU0_extCP0:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
VDU1_extCP0:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
VDU_intnet0:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 1000000
|
||||
min_bitrate_requirements:
|
||||
root: 100000
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l2_protocol_data:
|
||||
network_type: vxlan
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: '192.168.0.0/24'
|
||||
dhcp_enabled: true
|
||||
|
||||
RT_extCP:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
VDU_extvCP:
|
||||
type: tosca.nodes.nfv.VnfExtCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
requirements:
|
||||
- internal_virtual_link: VDU_intnet0
|
||||
|
||||
groups:
|
||||
VDU_AntiAffinityGroup:
|
||||
type: tosca.groups.nfv.PlacementGroup
|
||||
members: [ VDU_0, VDU_1 ]
|
||||
|
||||
policies:
|
||||
- VDU_placement_policy:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
targets: [ VDU_AntiAffinityGroup ]
|
||||
properties:
|
||||
scope: nfvi_node
|
||||
|
@ -1,391 +1,391 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample VNF default DF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- Common.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
configurable_properties:
|
||||
type: map
|
||||
|
||||
substitution_mappings:
|
||||
node_type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_id: scalable
|
||||
requirements:
|
||||
VDU0_extnet: [ VDU0_CP1, external_virtual_link ]
|
||||
VDU1_extnet: [ VDU1_CP1, external_virtual_link ]
|
||||
VDU2_extnet: [ VDU2_CP1, external_virtual_link ]
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_description: 'scalable'
|
||||
configurable_properties:
|
||||
is_autoscale_enabled: false
|
||||
is_autoheal_enabled: false
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
VDU_0:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_0
|
||||
description: VDU_0
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU_1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_1
|
||||
description: VDU_1
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU_2:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_2
|
||||
description: VDU_2
|
||||
vdu_profile:
|
||||
min_number_of_instances: 0
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU0_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_0
|
||||
- virtual_link: int_net
|
||||
|
||||
VDU0_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_0
|
||||
|
||||
VDU1_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_1
|
||||
- virtual_link: int_net
|
||||
|
||||
VDU1_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_1
|
||||
|
||||
VDU2_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_2
|
||||
- virtual_link: int_net
|
||||
|
||||
VDU2_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_2
|
||||
|
||||
int_net:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 1000000
|
||||
min_bitrate_requirements:
|
||||
root: 100000
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l2_protocol_data:
|
||||
network_type: vxlan
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: '192.168.1.0/24'
|
||||
|
||||
groups:
|
||||
VDU_AntiAffinityGroup:
|
||||
type: tosca.groups.nfv.PlacementGroup
|
||||
members: [ VDU_0, VDU_1, VDU_2 ]
|
||||
|
||||
policies:
|
||||
- VDU_placement_policy:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
targets: [ VDU_AntiAffinityGroup ]
|
||||
properties:
|
||||
scope: nfvi_node
|
||||
|
||||
- vdu_scale:
|
||||
type: tosca.policies.nfv.ScalingAspects
|
||||
properties:
|
||||
aspects:
|
||||
VDU_2:
|
||||
name: VDU_2
|
||||
description: VDU_2
|
||||
max_scale_level: 1
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
- vdu_0_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_0 ]
|
||||
|
||||
- vdu_1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_1 ]
|
||||
|
||||
- vdu_2_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 0
|
||||
targets: [ VDU_2 ]
|
||||
|
||||
- vdu_2_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: VDU_2
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_2 ]
|
||||
|
||||
- instantiation_levels:
|
||||
type: tosca.policies.nfv.InstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
description: vdu-min structure
|
||||
scale_info:
|
||||
VDU_2:
|
||||
scale_level: 0
|
||||
r-node-max:
|
||||
description: vdu-max structure
|
||||
scale_info:
|
||||
VDU_2:
|
||||
scale_level: 1
|
||||
|
||||
- vdu_0_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
number_of_instances: 1
|
||||
r-node-max:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_0 ]
|
||||
|
||||
- vdu_1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
number_of_instances: 1
|
||||
r-node-max:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_1 ]
|
||||
|
||||
- vdu_2_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
number_of_instances: 0
|
||||
r-node-max:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_2 ]
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample VNF default DF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- Common.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
configurable_properties:
|
||||
type: map
|
||||
|
||||
substitution_mappings:
|
||||
node_type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_id: scalable
|
||||
requirements:
|
||||
VDU0_extnet: [ VDU0_CP1, external_virtual_link ]
|
||||
VDU1_extnet: [ VDU1_CP1, external_virtual_link ]
|
||||
VDU2_extnet: [ VDU2_CP1, external_virtual_link ]
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: Sample.VNF.Node
|
||||
properties:
|
||||
flavour_description: 'scalable'
|
||||
configurable_properties:
|
||||
is_autoscale_enabled: false
|
||||
is_autoheal_enabled: false
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
VDU_0:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_0
|
||||
description: VDU_0
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU_1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_1
|
||||
description: VDU_1
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU_2:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU_2
|
||||
description: VDU_2
|
||||
vdu_profile:
|
||||
min_number_of_instances: 0
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: sample_image
|
||||
version: '1.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
size: 1869 MB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: sample_flavor
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GB
|
||||
|
||||
VDU0_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_0
|
||||
- virtual_link: int_net
|
||||
|
||||
VDU0_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_0
|
||||
|
||||
VDU1_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_1
|
||||
- virtual_link: int_net
|
||||
|
||||
VDU1_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_1
|
||||
|
||||
VDU2_CP0:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_2
|
||||
- virtual_link: int_net
|
||||
|
||||
VDU2_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
order: 0
|
||||
bitrate_requirement: 1
|
||||
vnic_type: normal
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU_2
|
||||
|
||||
int_net:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 1000000
|
||||
min_bitrate_requirements:
|
||||
root: 100000
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l2_protocol_data:
|
||||
network_type: vxlan
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: '192.168.1.0/24'
|
||||
|
||||
groups:
|
||||
VDU_AntiAffinityGroup:
|
||||
type: tosca.groups.nfv.PlacementGroup
|
||||
members: [ VDU_0, VDU_1, VDU_2 ]
|
||||
|
||||
policies:
|
||||
- VDU_placement_policy:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
targets: [ VDU_AntiAffinityGroup ]
|
||||
properties:
|
||||
scope: nfvi_node
|
||||
|
||||
- vdu_scale:
|
||||
type: tosca.policies.nfv.ScalingAspects
|
||||
properties:
|
||||
aspects:
|
||||
VDU_2:
|
||||
name: VDU_2
|
||||
description: VDU_2
|
||||
max_scale_level: 1
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
- vdu_0_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_0 ]
|
||||
|
||||
- vdu_1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_1 ]
|
||||
|
||||
- vdu_2_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 0
|
||||
targets: [ VDU_2 ]
|
||||
|
||||
- vdu_2_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: VDU_2
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_2 ]
|
||||
|
||||
- instantiation_levels:
|
||||
type: tosca.policies.nfv.InstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
description: vdu-min structure
|
||||
scale_info:
|
||||
VDU_2:
|
||||
scale_level: 0
|
||||
r-node-max:
|
||||
description: vdu-max structure
|
||||
scale_info:
|
||||
VDU_2:
|
||||
scale_level: 1
|
||||
|
||||
- vdu_0_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
number_of_instances: 1
|
||||
r-node-max:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_0 ]
|
||||
|
||||
- vdu_1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
number_of_instances: 1
|
||||
r-node-max:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_1 ]
|
||||
|
||||
- vdu_2_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
r-node-min:
|
||||
number_of_instances: 0
|
||||
r-node-max:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU_2 ]
|
||||
|
@ -1,35 +1,35 @@
|
||||
#
|
||||
# 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.
|
||||
import tacker.vnfm.lcm_user_data.utils as UserDataUtil
|
||||
|
||||
from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData
|
||||
|
||||
|
||||
class SampleUserData(AbstractUserData):
|
||||
@staticmethod
|
||||
def instantiate(base_hot_dict=None,
|
||||
vnfd_dict=None,
|
||||
inst_req_info=None,
|
||||
grant_info=None):
|
||||
api_param = UserDataUtil.get_diff_base_hot_param_from_api(
|
||||
base_hot_dict, inst_req_info)
|
||||
initial_param_dict = \
|
||||
UserDataUtil.create_initial_param_server_port_dict(base_hot_dict)
|
||||
vdu_flavor_dict = \
|
||||
UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict)
|
||||
vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict)
|
||||
cpd_vl_dict = UserDataUtil.create_network_dict(inst_req_info,
|
||||
initial_param_dict)
|
||||
final_param_dict = UserDataUtil.create_final_param_dict(
|
||||
initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict)
|
||||
return {**final_param_dict, **api_param}
|
||||
#
|
||||
# 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.
|
||||
import tacker.vnfm.lcm_user_data.utils as UserDataUtil
|
||||
|
||||
from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData
|
||||
|
||||
|
||||
class SampleUserData(AbstractUserData):
|
||||
@staticmethod
|
||||
def instantiate(base_hot_dict=None,
|
||||
vnfd_dict=None,
|
||||
inst_req_info=None,
|
||||
grant_info=None):
|
||||
api_param = UserDataUtil.get_diff_base_hot_param_from_api(
|
||||
base_hot_dict, inst_req_info)
|
||||
initial_param_dict = \
|
||||
UserDataUtil.create_initial_param_server_port_dict(base_hot_dict)
|
||||
vdu_flavor_dict = \
|
||||
UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict)
|
||||
vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict)
|
||||
cpd_vl_dict = UserDataUtil.create_network_dict(inst_req_info,
|
||||
initial_param_dict)
|
||||
final_param_dict = UserDataUtil.create_final_param_dict(
|
||||
initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict)
|
||||
return {**final_param_dict, **api_param}
|
||||
|
@ -1,370 +1,370 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# 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.
|
||||
"""
|
||||
Auth for External Server OAuth2.0 authentication
|
||||
"""
|
||||
import time
|
||||
import uuid
|
||||
|
||||
import jwt.utils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import requests.auth
|
||||
|
||||
from keystoneauth1 import exceptions as ksa_exceptions
|
||||
from keystoneauth1.loading import session as session_loading
|
||||
|
||||
from tacker._i18n import _
|
||||
from tacker.common.exceptions import TackerException
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME = 'ext_oauth2_auth'
|
||||
_EXTERNAL_AUTH2_OPTS = [
|
||||
cfg.BoolOpt('use_ext_oauth2_auth', default=False,
|
||||
help='Set True to use external Oauth2.0 auth server.'),
|
||||
cfg.StrOpt('token_endpoint',
|
||||
help='The endpoint for access token API.'),
|
||||
cfg.StrOpt('scope',
|
||||
help='The scope that the access token can access.'),
|
||||
]
|
||||
_EXTERNAL_AUTH2_KEYSTONE_MIDDLEWARE_OPTS = [
|
||||
cfg.StrOpt('certfile',
|
||||
help='Required if identity server requires client '
|
||||
'certificate.'),
|
||||
cfg.StrOpt('keyfile',
|
||||
help='Required if identity server requires client '
|
||||
'private key.'),
|
||||
cfg.StrOpt('cafile',
|
||||
help='A PEM encoded Certificate Authority to use when '
|
||||
'verifying HTTPs connections. Defaults to system CAs.'),
|
||||
cfg.BoolOpt('insecure', default=False, help='Verify HTTPS connections.'),
|
||||
cfg.IntOpt('http_connect_timeout',
|
||||
help='Request timeout value for communicating with Identity '
|
||||
'API server.'),
|
||||
cfg.StrOpt('audience',
|
||||
help='The Audience should be the URL of the Authorization '
|
||||
"Server's Token Endpoint. The Authorization Server will "
|
||||
'verify that it is an intended audience for the token.'),
|
||||
cfg.StrOpt('auth_method',
|
||||
default='client_secret_basic',
|
||||
choices=('client_secret_basic', 'client_secret_post',
|
||||
'tls_client_auth', 'private_key_jwt',
|
||||
'client_secret_jwt'),
|
||||
help='The auth_method must use the authentication method '
|
||||
'specified by the Authorization Server.'),
|
||||
cfg.StrOpt('client_id',
|
||||
help='The OAuth 2.0 Client Identifier valid at the '
|
||||
'Authorization Server.'),
|
||||
cfg.StrOpt('client_secret',
|
||||
help='The OAuth 2.0 client secret. When the auth_method is '
|
||||
'client_secret_basic, client_secret_post, or '
|
||||
'client_secret_jwt, the value is used, and otherwise the '
|
||||
'value is ignored.'),
|
||||
cfg.StrOpt('jwt_key_file',
|
||||
help='The jwt_key_file must use the certificate key file which '
|
||||
'has been registered with the Authorization Server. '
|
||||
'When the auth_method is private_key_jwt, the value is '
|
||||
'used, and otherwise the value is ignored.'),
|
||||
cfg.StrOpt('jwt_algorithm',
|
||||
help='The jwt_algorithm must use the algorithm specified by '
|
||||
'the Authorization Server. When the auth_method is '
|
||||
'client_secret_jwt, this value is often set to HS256,'
|
||||
'when the auth_method is private_key_jwt, the value is '
|
||||
'often set to RS256, and otherwise the value is ignored.'),
|
||||
cfg.IntOpt('jwt_bearer_time_out', default=3600,
|
||||
help='This value is used to calculate the expiration time. If '
|
||||
'after the expiration time, the access token cannot be '
|
||||
'accepted. When the auth_method is client_secret_jwt or '
|
||||
'private_key_jwt, the value is used, and otherwise the '
|
||||
'value is ignored.'),
|
||||
]
|
||||
|
||||
|
||||
def config_opts():
|
||||
return [(_EXT_AUTH_CONFIG_GROUP_NAME,
|
||||
_EXTERNAL_AUTH2_OPTS + _EXTERNAL_AUTH2_KEYSTONE_MIDDLEWARE_OPTS)]
|
||||
|
||||
|
||||
cfg.CONF.register_opts(_EXTERNAL_AUTH2_OPTS,
|
||||
group=_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
|
||||
|
||||
class ExtOAuth2Auth(object):
|
||||
"""Construct an Auth to fetch an access token for HTTP access."""
|
||||
|
||||
def __init__(self):
|
||||
self._conf = cfg.CONF.ext_oauth2_auth
|
||||
# Check whether the configuration parameter has been registered
|
||||
if 'auth_method' not in self._conf:
|
||||
LOG.debug('The relevant config parameters are not registered '
|
||||
'and need to be registered before they can be used.')
|
||||
cfg.CONF.register_opts(_EXTERNAL_AUTH2_KEYSTONE_MIDDLEWARE_OPTS,
|
||||
group=_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
self.token_endpoint = self._get_config_option(
|
||||
'token_endpoint', is_required=True)
|
||||
self.auth_method = self._get_config_option(
|
||||
'auth_method', is_required=True)
|
||||
self.client_id = self._get_config_option(
|
||||
'client_id', is_required=True)
|
||||
self.scope = self._get_config_option(
|
||||
'scope', is_required=True)
|
||||
self.access_token = None
|
||||
|
||||
def _get_config_option(self, key, is_required):
|
||||
"""Read the value from config file by the config key."""
|
||||
try:
|
||||
value = getattr(self._conf, key)
|
||||
except cfg.NoSuchOptError:
|
||||
value = None
|
||||
if not value:
|
||||
if is_required:
|
||||
LOG.error('The value is required for option %s '
|
||||
'in group [%s]' % (key,
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME))
|
||||
raise TackerException(
|
||||
_('Configuration error. The parameter '
|
||||
'is not set for "%s" in group [%s].') % (
|
||||
key, _EXT_AUTH_CONFIG_GROUP_NAME))
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return value
|
||||
|
||||
def create_session(self, **kwargs):
|
||||
"""Create session for HTTP access."""
|
||||
kwargs.setdefault('cert', self._get_config_option(
|
||||
'certfile', is_required=False))
|
||||
kwargs.setdefault('key', self._get_config_option(
|
||||
'keyfile', is_required=False))
|
||||
kwargs.setdefault('cacert', self._get_config_option(
|
||||
'cafile', is_required=False))
|
||||
kwargs.setdefault('insecure', self._get_config_option(
|
||||
'insecure', is_required=False))
|
||||
kwargs.setdefault('timeout', self._get_config_option(
|
||||
'http_connect_timeout', is_required=False))
|
||||
kwargs.setdefault('user_agent', 'tacker service')
|
||||
sess = session_loading.Session().load_from_options(**kwargs)
|
||||
sess.auth = self
|
||||
return sess
|
||||
|
||||
def get_connection_params(self, session, **kwargs):
|
||||
"""Get connection params for HTTP access."""
|
||||
return {}
|
||||
|
||||
def invalidate(self):
|
||||
"""Invalidate the current authentication data."""
|
||||
self.access_token = None
|
||||
return True
|
||||
|
||||
def _get_token_by_client_secret_basic(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'client_secret_basic'.
|
||||
"""
|
||||
para = {
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
auth = requests.auth.HTTPBasicAuth(
|
||||
self.client_id, self._get_config_option(
|
||||
'client_secret', is_required=True))
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para,
|
||||
requests_auth=auth)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_client_secret_post(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'client_secret_post'.
|
||||
"""
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'client_secret': self._get_config_option(
|
||||
'client_secret', is_required=True),
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_tls_client_auth(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'tls_client_auth'.
|
||||
"""
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_private_key_jwt(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'private_key_jwt'.
|
||||
"""
|
||||
jwt_key_file = self._get_config_option(
|
||||
'jwt_key_file', is_required=True)
|
||||
with open(jwt_key_file, 'r') as jwt_file:
|
||||
jwt_key = jwt_file.read()
|
||||
ita = round(time.time())
|
||||
exp = ita + self._get_config_option(
|
||||
'jwt_bearer_time_out', is_required=True)
|
||||
alg = self._get_config_option('jwt_algorithm', is_required=True)
|
||||
client_assertion = jwt.encode(
|
||||
payload={
|
||||
'jti': str(uuid.uuid4()),
|
||||
'iat': str(ita),
|
||||
'exp': str(exp),
|
||||
'iss': self.client_id,
|
||||
'sub': self.client_id,
|
||||
'aud': self._get_config_option('audience', is_required=True)},
|
||||
headers={
|
||||
'typ': 'JWT',
|
||||
'alg': alg},
|
||||
key=jwt_key,
|
||||
algorithm=alg)
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'client_assertion_type':
|
||||
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
||||
'client_assertion': client_assertion,
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_client_secret_jwt(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'client_secret_jwt'.
|
||||
"""
|
||||
ita = round(time.time())
|
||||
exp = ita + self._get_config_option(
|
||||
'jwt_bearer_time_out', is_required=True)
|
||||
alg = self._get_config_option('jwt_algorithm', is_required=True)
|
||||
client_secret = self._get_config_option(
|
||||
'client_secret', is_required=True)
|
||||
client_assertion = jwt.encode(
|
||||
payload={
|
||||
'jti': str(uuid.uuid4()),
|
||||
'iat': str(ita),
|
||||
'exp': str(exp),
|
||||
'iss': self.client_id,
|
||||
'sub': self.client_id,
|
||||
'aud': self._get_config_option('audience', is_required=True)},
|
||||
headers={
|
||||
'typ': 'JWT',
|
||||
'alg': alg},
|
||||
key=client_secret,
|
||||
algorithm=alg)
|
||||
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'client_secret': client_secret,
|
||||
'client_assertion_type':
|
||||
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
||||
'client_assertion': client_assertion,
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def get_headers(self, session, **kwargs):
|
||||
"""Get an access token and add to request header for HTTP access."""
|
||||
if not self.access_token:
|
||||
try:
|
||||
if self.auth_method == 'tls_client_auth':
|
||||
http_response = self._get_token_by_tls_client_auth(session)
|
||||
elif self.auth_method == 'client_secret_post':
|
||||
http_response = self._get_token_by_client_secret_post(
|
||||
session)
|
||||
elif self.auth_method == 'client_secret_basic':
|
||||
http_response = self._get_token_by_client_secret_basic(
|
||||
session)
|
||||
elif self.auth_method == 'private_key_jwt':
|
||||
http_response = self._get_token_by_private_key_jwt(
|
||||
session)
|
||||
elif self.auth_method == 'client_secret_jwt':
|
||||
http_response = self._get_token_by_client_secret_jwt(
|
||||
session)
|
||||
else:
|
||||
LOG.error('The value is incorrect for option '
|
||||
'auth_method in group [%s]' %
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
raise TackerException(
|
||||
_('The configuration parameter for '
|
||||
'key "auth_method" in group [%s] is incorrect.') %
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
LOG.debug(http_response.text)
|
||||
if http_response.status_code != 200:
|
||||
LOG.error('The OAuth2.0 access token API returns an '
|
||||
'incorrect response. '
|
||||
'response_status: %s, response_text: %s' %
|
||||
(http_response.status_code,
|
||||
http_response.text))
|
||||
raise TackerException(_('Failed to get an access token.'))
|
||||
|
||||
access_token = http_response.json().get('access_token')
|
||||
if not access_token:
|
||||
LOG.error('Failed to get an access token: %s',
|
||||
http_response.text)
|
||||
raise TackerException(_('Failed to get an access token.'))
|
||||
self.access_token = access_token
|
||||
except (ksa_exceptions.ConnectFailure,
|
||||
ksa_exceptions.DiscoveryFailure,
|
||||
ksa_exceptions.RequestTimeout) as error:
|
||||
LOG.error('Unable to get an access token: %s', error)
|
||||
raise TackerException(
|
||||
_('The OAuth2.0 access token API service is '
|
||||
'temporarily unavailable.'))
|
||||
except TackerException:
|
||||
raise
|
||||
except Exception as error:
|
||||
LOG.error('Unable to get an access token: %s', error)
|
||||
raise TackerException(
|
||||
_('An exception occurred during the processing '
|
||||
'of getting an access token'))
|
||||
header = {'Authorization': f'Bearer {self.access_token}'}
|
||||
return header
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# 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.
|
||||
"""
|
||||
Auth for External Server OAuth2.0 authentication
|
||||
"""
|
||||
import time
|
||||
import uuid
|
||||
|
||||
import jwt.utils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import requests.auth
|
||||
|
||||
from keystoneauth1 import exceptions as ksa_exceptions
|
||||
from keystoneauth1.loading import session as session_loading
|
||||
|
||||
from tacker._i18n import _
|
||||
from tacker.common.exceptions import TackerException
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME = 'ext_oauth2_auth'
|
||||
_EXTERNAL_AUTH2_OPTS = [
|
||||
cfg.BoolOpt('use_ext_oauth2_auth', default=False,
|
||||
help='Set True to use external Oauth2.0 auth server.'),
|
||||
cfg.StrOpt('token_endpoint',
|
||||
help='The endpoint for access token API.'),
|
||||
cfg.StrOpt('scope',
|
||||
help='The scope that the access token can access.'),
|
||||
]
|
||||
_EXTERNAL_AUTH2_KEYSTONE_MIDDLEWARE_OPTS = [
|
||||
cfg.StrOpt('certfile',
|
||||
help='Required if identity server requires client '
|
||||
'certificate.'),
|
||||
cfg.StrOpt('keyfile',
|
||||
help='Required if identity server requires client '
|
||||
'private key.'),
|
||||
cfg.StrOpt('cafile',
|
||||
help='A PEM encoded Certificate Authority to use when '
|
||||
'verifying HTTPs connections. Defaults to system CAs.'),
|
||||
cfg.BoolOpt('insecure', default=False, help='Verify HTTPS connections.'),
|
||||
cfg.IntOpt('http_connect_timeout',
|
||||
help='Request timeout value for communicating with Identity '
|
||||
'API server.'),
|
||||
cfg.StrOpt('audience',
|
||||
help='The Audience should be the URL of the Authorization '
|
||||
"Server's Token Endpoint. The Authorization Server will "
|
||||
'verify that it is an intended audience for the token.'),
|
||||
cfg.StrOpt('auth_method',
|
||||
default='client_secret_basic',
|
||||
choices=('client_secret_basic', 'client_secret_post',
|
||||
'tls_client_auth', 'private_key_jwt',
|
||||
'client_secret_jwt'),
|
||||
help='The auth_method must use the authentication method '
|
||||
'specified by the Authorization Server.'),
|
||||
cfg.StrOpt('client_id',
|
||||
help='The OAuth 2.0 Client Identifier valid at the '
|
||||
'Authorization Server.'),
|
||||
cfg.StrOpt('client_secret',
|
||||
help='The OAuth 2.0 client secret. When the auth_method is '
|
||||
'client_secret_basic, client_secret_post, or '
|
||||
'client_secret_jwt, the value is used, and otherwise the '
|
||||
'value is ignored.'),
|
||||
cfg.StrOpt('jwt_key_file',
|
||||
help='The jwt_key_file must use the certificate key file which '
|
||||
'has been registered with the Authorization Server. '
|
||||
'When the auth_method is private_key_jwt, the value is '
|
||||
'used, and otherwise the value is ignored.'),
|
||||
cfg.StrOpt('jwt_algorithm',
|
||||
help='The jwt_algorithm must use the algorithm specified by '
|
||||
'the Authorization Server. When the auth_method is '
|
||||
'client_secret_jwt, this value is often set to HS256,'
|
||||
'when the auth_method is private_key_jwt, the value is '
|
||||
'often set to RS256, and otherwise the value is ignored.'),
|
||||
cfg.IntOpt('jwt_bearer_time_out', default=3600,
|
||||
help='This value is used to calculate the expiration time. If '
|
||||
'after the expiration time, the access token cannot be '
|
||||
'accepted. When the auth_method is client_secret_jwt or '
|
||||
'private_key_jwt, the value is used, and otherwise the '
|
||||
'value is ignored.'),
|
||||
]
|
||||
|
||||
|
||||
def config_opts():
|
||||
return [(_EXT_AUTH_CONFIG_GROUP_NAME,
|
||||
_EXTERNAL_AUTH2_OPTS + _EXTERNAL_AUTH2_KEYSTONE_MIDDLEWARE_OPTS)]
|
||||
|
||||
|
||||
cfg.CONF.register_opts(_EXTERNAL_AUTH2_OPTS,
|
||||
group=_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
|
||||
|
||||
class ExtOAuth2Auth(object):
|
||||
"""Construct an Auth to fetch an access token for HTTP access."""
|
||||
|
||||
def __init__(self):
|
||||
self._conf = cfg.CONF.ext_oauth2_auth
|
||||
# Check whether the configuration parameter has been registered
|
||||
if 'auth_method' not in self._conf:
|
||||
LOG.debug('The relevant config parameters are not registered '
|
||||
'and need to be registered before they can be used.')
|
||||
cfg.CONF.register_opts(_EXTERNAL_AUTH2_KEYSTONE_MIDDLEWARE_OPTS,
|
||||
group=_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
self.token_endpoint = self._get_config_option(
|
||||
'token_endpoint', is_required=True)
|
||||
self.auth_method = self._get_config_option(
|
||||
'auth_method', is_required=True)
|
||||
self.client_id = self._get_config_option(
|
||||
'client_id', is_required=True)
|
||||
self.scope = self._get_config_option(
|
||||
'scope', is_required=True)
|
||||
self.access_token = None
|
||||
|
||||
def _get_config_option(self, key, is_required):
|
||||
"""Read the value from config file by the config key."""
|
||||
try:
|
||||
value = getattr(self._conf, key)
|
||||
except cfg.NoSuchOptError:
|
||||
value = None
|
||||
if not value:
|
||||
if is_required:
|
||||
LOG.error('The value is required for option %s '
|
||||
'in group [%s]' % (key,
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME))
|
||||
raise TackerException(
|
||||
_('Configuration error. The parameter '
|
||||
'is not set for "%s" in group [%s].') % (
|
||||
key, _EXT_AUTH_CONFIG_GROUP_NAME))
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return value
|
||||
|
||||
def create_session(self, **kwargs):
|
||||
"""Create session for HTTP access."""
|
||||
kwargs.setdefault('cert', self._get_config_option(
|
||||
'certfile', is_required=False))
|
||||
kwargs.setdefault('key', self._get_config_option(
|
||||
'keyfile', is_required=False))
|
||||
kwargs.setdefault('cacert', self._get_config_option(
|
||||
'cafile', is_required=False))
|
||||
kwargs.setdefault('insecure', self._get_config_option(
|
||||
'insecure', is_required=False))
|
||||
kwargs.setdefault('timeout', self._get_config_option(
|
||||
'http_connect_timeout', is_required=False))
|
||||
kwargs.setdefault('user_agent', 'tacker service')
|
||||
sess = session_loading.Session().load_from_options(**kwargs)
|
||||
sess.auth = self
|
||||
return sess
|
||||
|
||||
def get_connection_params(self, session, **kwargs):
|
||||
"""Get connection params for HTTP access."""
|
||||
return {}
|
||||
|
||||
def invalidate(self):
|
||||
"""Invalidate the current authentication data."""
|
||||
self.access_token = None
|
||||
return True
|
||||
|
||||
def _get_token_by_client_secret_basic(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'client_secret_basic'.
|
||||
"""
|
||||
para = {
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
auth = requests.auth.HTTPBasicAuth(
|
||||
self.client_id, self._get_config_option(
|
||||
'client_secret', is_required=True))
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para,
|
||||
requests_auth=auth)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_client_secret_post(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'client_secret_post'.
|
||||
"""
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'client_secret': self._get_config_option(
|
||||
'client_secret', is_required=True),
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_tls_client_auth(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'tls_client_auth'.
|
||||
"""
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_private_key_jwt(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'private_key_jwt'.
|
||||
"""
|
||||
jwt_key_file = self._get_config_option(
|
||||
'jwt_key_file', is_required=True)
|
||||
with open(jwt_key_file, 'r') as jwt_file:
|
||||
jwt_key = jwt_file.read()
|
||||
ita = round(time.time())
|
||||
exp = ita + self._get_config_option(
|
||||
'jwt_bearer_time_out', is_required=True)
|
||||
alg = self._get_config_option('jwt_algorithm', is_required=True)
|
||||
client_assertion = jwt.encode(
|
||||
payload={
|
||||
'jti': str(uuid.uuid4()),
|
||||
'iat': str(ita),
|
||||
'exp': str(exp),
|
||||
'iss': self.client_id,
|
||||
'sub': self.client_id,
|
||||
'aud': self._get_config_option('audience', is_required=True)},
|
||||
headers={
|
||||
'typ': 'JWT',
|
||||
'alg': alg},
|
||||
key=jwt_key,
|
||||
algorithm=alg)
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'client_assertion_type':
|
||||
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
||||
'client_assertion': client_assertion,
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def _get_token_by_client_secret_jwt(self, session):
|
||||
"""Access the access token API.
|
||||
|
||||
Access the access token API to get an access token by
|
||||
the auth method 'client_secret_jwt'.
|
||||
"""
|
||||
ita = round(time.time())
|
||||
exp = ita + self._get_config_option(
|
||||
'jwt_bearer_time_out', is_required=True)
|
||||
alg = self._get_config_option('jwt_algorithm', is_required=True)
|
||||
client_secret = self._get_config_option(
|
||||
'client_secret', is_required=True)
|
||||
client_assertion = jwt.encode(
|
||||
payload={
|
||||
'jti': str(uuid.uuid4()),
|
||||
'iat': str(ita),
|
||||
'exp': str(exp),
|
||||
'iss': self.client_id,
|
||||
'sub': self.client_id,
|
||||
'aud': self._get_config_option('audience', is_required=True)},
|
||||
headers={
|
||||
'typ': 'JWT',
|
||||
'alg': alg},
|
||||
key=client_secret,
|
||||
algorithm=alg)
|
||||
|
||||
para = {
|
||||
'client_id': self.client_id,
|
||||
'client_secret': client_secret,
|
||||
'client_assertion_type':
|
||||
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
||||
'client_assertion': client_assertion,
|
||||
'scope': self.scope,
|
||||
'grant_type': 'client_credentials'
|
||||
}
|
||||
http_response = session.request(
|
||||
self.token_endpoint,
|
||||
'POST',
|
||||
authenticated=False,
|
||||
data=para)
|
||||
return http_response
|
||||
|
||||
def get_headers(self, session, **kwargs):
|
||||
"""Get an access token and add to request header for HTTP access."""
|
||||
if not self.access_token:
|
||||
try:
|
||||
if self.auth_method == 'tls_client_auth':
|
||||
http_response = self._get_token_by_tls_client_auth(session)
|
||||
elif self.auth_method == 'client_secret_post':
|
||||
http_response = self._get_token_by_client_secret_post(
|
||||
session)
|
||||
elif self.auth_method == 'client_secret_basic':
|
||||
http_response = self._get_token_by_client_secret_basic(
|
||||
session)
|
||||
elif self.auth_method == 'private_key_jwt':
|
||||
http_response = self._get_token_by_private_key_jwt(
|
||||
session)
|
||||
elif self.auth_method == 'client_secret_jwt':
|
||||
http_response = self._get_token_by_client_secret_jwt(
|
||||
session)
|
||||
else:
|
||||
LOG.error('The value is incorrect for option '
|
||||
'auth_method in group [%s]' %
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
raise TackerException(
|
||||
_('The configuration parameter for '
|
||||
'key "auth_method" in group [%s] is incorrect.') %
|
||||
_EXT_AUTH_CONFIG_GROUP_NAME)
|
||||
LOG.debug(http_response.text)
|
||||
if http_response.status_code != 200:
|
||||
LOG.error('The OAuth2.0 access token API returns an '
|
||||
'incorrect response. '
|
||||
'response_status: %s, response_text: %s' %
|
||||
(http_response.status_code,
|
||||
http_response.text))
|
||||
raise TackerException(_('Failed to get an access token.'))
|
||||
|
||||
access_token = http_response.json().get('access_token')
|
||||
if not access_token:
|
||||
LOG.error('Failed to get an access token: %s',
|
||||
http_response.text)
|
||||
raise TackerException(_('Failed to get an access token.'))
|
||||
self.access_token = access_token
|
||||
except (ksa_exceptions.ConnectFailure,
|
||||
ksa_exceptions.DiscoveryFailure,
|
||||
ksa_exceptions.RequestTimeout) as error:
|
||||
LOG.error('Unable to get an access token: %s', error)
|
||||
raise TackerException(
|
||||
_('The OAuth2.0 access token API service is '
|
||||
'temporarily unavailable.'))
|
||||
except TackerException:
|
||||
raise
|
||||
except Exception as error:
|
||||
LOG.error('Unable to get an access token: %s', error)
|
||||
raise TackerException(
|
||||
_('An exception occurred during the processing '
|
||||
'of getting an access token'))
|
||||
header = {'Authorization': f'Bearer {self.access_token}'}
|
||||
return header
|
||||
|
@ -1,62 +1,62 @@
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.2.5 (API version: 2.1.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class PerformanceInformationAvailableNotificationV2(
|
||||
base.TackerObject,
|
||||
base.TackerObjectDictCompat
|
||||
):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'notificationType': fields.StringField(nullable=False),
|
||||
'timeStamp': fields.DateTimeField(nullable=False),
|
||||
'pmJobId': fields.StringField(nullable=False),
|
||||
'objectType': fields.StringField(nullable=False),
|
||||
'objectInstanceId': fields.StringField(nullable=False),
|
||||
'subObjectInstanceIds': fields.ListOfStringsField(nullable=True),
|
||||
'_links': fields.ObjectField(
|
||||
'PerformanceInformationAvailableNotificationV2_Links',
|
||||
nullable=False),
|
||||
}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class PerformanceInformationAvailableNotificationV2_Links(
|
||||
base.TackerObject,
|
||||
base.TackerObjectDictCompat
|
||||
):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'objectInstance': fields.ObjectField(
|
||||
'NotificationLink', nullable=True),
|
||||
'pmJob': fields.ObjectField(
|
||||
'NotificationLink', nullable=False),
|
||||
'performanceReport': fields.ObjectField(
|
||||
'NotificationLink', nullable=False),
|
||||
}
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.2.5 (API version: 2.1.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class PerformanceInformationAvailableNotificationV2(
|
||||
base.TackerObject,
|
||||
base.TackerObjectDictCompat
|
||||
):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'notificationType': fields.StringField(nullable=False),
|
||||
'timeStamp': fields.DateTimeField(nullable=False),
|
||||
'pmJobId': fields.StringField(nullable=False),
|
||||
'objectType': fields.StringField(nullable=False),
|
||||
'objectInstanceId': fields.StringField(nullable=False),
|
||||
'subObjectInstanceIds': fields.ListOfStringsField(nullable=True),
|
||||
'_links': fields.ObjectField(
|
||||
'PerformanceInformationAvailableNotificationV2_Links',
|
||||
nullable=False),
|
||||
}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class PerformanceInformationAvailableNotificationV2_Links(
|
||||
base.TackerObject,
|
||||
base.TackerObjectDictCompat
|
||||
):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'objectInstance': fields.ObjectField(
|
||||
'NotificationLink', nullable=True),
|
||||
'pmJob': fields.ObjectField(
|
||||
'NotificationLink', nullable=False),
|
||||
'performanceReport': fields.ObjectField(
|
||||
'NotificationLink', nullable=False),
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.3.3 (API version: 2.0.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class VnfPmJobCriteriaV2(base.TackerObject, base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'performanceMetric': fields.ListOfStringsField(nullable=True),
|
||||
'performanceMetricGroup': fields.ListOfStringsField(nullable=True),
|
||||
'collectionPeriod': fields.IntegerField(nullable=False),
|
||||
'reportingPeriod': fields.IntegerField(nullable=False),
|
||||
'reportingBoundary': fields.DateTimeField(nullable=True),
|
||||
}
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.3.3 (API version: 2.0.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class VnfPmJobCriteriaV2(base.TackerObject, base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'performanceMetric': fields.ListOfStringsField(nullable=True),
|
||||
'performanceMetricGroup': fields.ListOfStringsField(nullable=True),
|
||||
'collectionPeriod': fields.IntegerField(nullable=False),
|
||||
'reportingPeriod': fields.IntegerField(nullable=False),
|
||||
'reportingBoundary': fields.DateTimeField(nullable=True),
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.2.12 (API version: 2.1.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class PmJobModificationsV2(base.TackerObject, base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'callbackUri': fields.StringField(nullable=True),
|
||||
'authentication': fields.ObjectField(
|
||||
'SubscriptionAuthentication', nullable=True),
|
||||
}
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.2.12 (API version: 2.1.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class PmJobModificationsV2(base.TackerObject, base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'callbackUri': fields.StringField(nullable=True),
|
||||
'authentication': fields.ObjectField(
|
||||
'SubscriptionAuthentication', nullable=True),
|
||||
}
|
||||
|
@ -1,65 +1,65 @@
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.2.10 (API version: 2.1.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class PerformanceReportV2(base.TackerPersistentObject,
|
||||
base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
# PerformanceReportV2 need 'id' and 'jobId'
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'jobId': fields.StringField(nullable=False),
|
||||
'entries': fields.ListOfObjectsField(
|
||||
'VnfPmReportV2_Entries', nullable=False),
|
||||
}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VnfPmReportV2_Entries(base.TackerObject, base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'objectType': fields.StringField(nullable=False),
|
||||
'objectInstanceId': fields.StringField(nullable=False),
|
||||
'subObjectInstanceId': fields.StringField(nullable=True),
|
||||
'performanceMetric': fields.StringField(nullable=False),
|
||||
'performanceValues': fields.ListOfObjectsField(
|
||||
'VnfPmReportV2_Entries_PerformanceValues', nullable=False),
|
||||
}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VnfPmReportV2_Entries_PerformanceValues(base.TackerObject,
|
||||
base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'timeStamp': fields.DateTimeField(nullable=False),
|
||||
'value': fields.StringField(nullable=False),
|
||||
'context': fields.KeyValuePairsField(nullable=True),
|
||||
}
|
||||
# Copyright (C) 2022 Fujitsu
|
||||
# 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.
|
||||
|
||||
from tacker.sol_refactored.objects import base
|
||||
from tacker.sol_refactored.objects import fields
|
||||
|
||||
|
||||
# NFV-SOL 003
|
||||
# - v3.3.1 6.5.2.10 (API version: 2.1.0)
|
||||
@base.TackerObjectRegistry.register
|
||||
class PerformanceReportV2(base.TackerPersistentObject,
|
||||
base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
# PerformanceReportV2 need 'id' and 'jobId'
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'jobId': fields.StringField(nullable=False),
|
||||
'entries': fields.ListOfObjectsField(
|
||||
'VnfPmReportV2_Entries', nullable=False),
|
||||
}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VnfPmReportV2_Entries(base.TackerObject, base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'objectType': fields.StringField(nullable=False),
|
||||
'objectInstanceId': fields.StringField(nullable=False),
|
||||
'subObjectInstanceId': fields.StringField(nullable=True),
|
||||
'performanceMetric': fields.StringField(nullable=False),
|
||||
'performanceValues': fields.ListOfObjectsField(
|
||||
'VnfPmReportV2_Entries_PerformanceValues', nullable=False),
|
||||
}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VnfPmReportV2_Entries_PerformanceValues(base.TackerObject,
|
||||
base.TackerObjectDictCompat):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'timeStamp': fields.DateTimeField(nullable=False),
|
||||
'value': fields.StringField(nullable=False),
|
||||
'context': fields.KeyValuePairsField(nullable=True),
|
||||
}
|
||||
|
@ -1,457 +1,457 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# 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.
|
||||
import base64
|
||||
import copy
|
||||
import os
|
||||
from unittest import mock
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from requests_mock.contrib import fixture as rm_fixture
|
||||
|
||||
from keystoneauth1 import exceptions as ksa_exceptions
|
||||
|
||||
from tacker.common.exceptions import TackerException
|
||||
from tacker import context
|
||||
from tacker.tests.unit import base
|
||||
|
||||
JWT_KEY_FILE = 'jwt_private.key'
|
||||
|
||||
|
||||
def _get_sample_key(name):
|
||||
filename = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"./sample_keys/", name)
|
||||
with open(filename, "r") as f:
|
||||
content = f.read()
|
||||
return content
|
||||
|
||||
|
||||
def get_mock_conf_effect(audience=None, token_endpoint=None,
|
||||
auth_method=None, client_id=None, client_secret=None,
|
||||
scope=None, jwt_key_file=None, jwt_algorithm=None,
|
||||
jwt_bearer_time_out=None, certfile=None, keyfile=None,
|
||||
cafile=None, http_connect_timeout=None, insecure=None):
|
||||
def mock_conf_key_effect(name):
|
||||
if name == 'keystone_authtoken':
|
||||
return MockConfig(conf=None)
|
||||
elif name == 'ext_oauth2_auth':
|
||||
config = {'use_ext_oauth2_auth': True}
|
||||
if audience:
|
||||
config['audience'] = audience
|
||||
if token_endpoint:
|
||||
config['token_endpoint'] = token_endpoint
|
||||
if auth_method:
|
||||
config['auth_method'] = auth_method
|
||||
if client_id:
|
||||
config['client_id'] = client_id
|
||||
if client_secret:
|
||||
config['client_secret'] = client_secret
|
||||
if scope:
|
||||
config['scope'] = scope
|
||||
if jwt_key_file:
|
||||
config['jwt_key_file'] = jwt_key_file
|
||||
if jwt_algorithm:
|
||||
config['jwt_algorithm'] = jwt_algorithm
|
||||
if jwt_bearer_time_out:
|
||||
config['jwt_bearer_time_out'] = jwt_bearer_time_out
|
||||
if certfile:
|
||||
config['certfile'] = certfile
|
||||
if keyfile:
|
||||
config['keyfile'] = keyfile
|
||||
if cafile:
|
||||
config['cafile'] = cafile
|
||||
if cafile:
|
||||
config['http_connect_timeout'] = http_connect_timeout
|
||||
if cafile:
|
||||
config['insecure'] = insecure
|
||||
return MockConfig(
|
||||
conf=config)
|
||||
else:
|
||||
return cfg.CONF._get(name)
|
||||
return mock_conf_key_effect
|
||||
|
||||
|
||||
class MockConfig(object):
|
||||
def __init__(self, conf=None):
|
||||
self.conf = conf
|
||||
|
||||
def __getattr__(self, name):
|
||||
if not self.conf or name not in self.conf:
|
||||
raise cfg.NoSuchOptError(f'not found {name}')
|
||||
return self.conf.get(name)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.conf
|
||||
|
||||
|
||||
class MockSession(object):
|
||||
def __init__(self, ):
|
||||
self.auth = None
|
||||
|
||||
|
||||
class TestExtOAuth2Auth(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestExtOAuth2Auth, self).setUp()
|
||||
self.requests_mock = self.useFixture(rm_fixture.Fixture())
|
||||
self.token_endpoint = 'http://demo/token_endpoint'
|
||||
self.auth_method = 'client_secret_post'
|
||||
self.client_id = 'test_client_id'
|
||||
self.client_secret = 'test_client_secret'
|
||||
self.scope = 'tacker_api'
|
||||
self.access_token = f'access_token_{str(uuid.uuid4())}'
|
||||
self.audience = 'http://demo/audience'
|
||||
self.jwt_bearer_time_out = 2800
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
def _get_access_token_response(self, request, context,
|
||||
auth_method=None,
|
||||
client_id=None,
|
||||
client_secret=None,
|
||||
scope=None,
|
||||
access_token=None,
|
||||
status_code=200,
|
||||
raise_error=None,
|
||||
resp=None
|
||||
):
|
||||
if raise_error:
|
||||
raise raise_error
|
||||
if auth_method == 'tls_client_auth':
|
||||
body = (f'client_id={client_id}&scope={scope}'
|
||||
f'&grant_type=client_credentials')
|
||||
self.assertEqual(request.text, body)
|
||||
elif auth_method == 'client_secret_post':
|
||||
body = (f'client_id={client_id}&client_secret={client_secret}'
|
||||
f'&scope={scope}&grant_type=client_credentials')
|
||||
self.assertEqual(request.text, body)
|
||||
elif auth_method == 'client_secret_basic':
|
||||
body = f'scope={scope}&grant_type=client_credentials'
|
||||
self.assertEqual(request.text, body)
|
||||
auth_basic = request._request.headers.get('Authorization')
|
||||
self.assertIsNotNone(auth_basic)
|
||||
|
||||
auth = 'Basic ' + base64.standard_b64encode(
|
||||
f'{client_id}:{client_secret}'.encode('ascii')).decode('ascii')
|
||||
self.assertEqual(auth_basic, auth)
|
||||
elif auth_method == 'private_key_jwt':
|
||||
self.assertIn(f'client_id={client_id}', request.text)
|
||||
self.assertIn(('client_assertion_type=urn%3Aietf%3Aparams%3A'
|
||||
'oauth%3Aclient-assertion-type%3Ajwt-bearer'),
|
||||
request.text)
|
||||
self.assertIn('client_assertion=', request.text)
|
||||
self.assertIn(f'scope={scope}', request.text)
|
||||
self.assertIn('grant_type=client_credentials', request.text)
|
||||
elif auth_method == 'client_secret_jwt':
|
||||
self.assertIn(f'client_id={client_id}', request.text)
|
||||
self.assertIn(('client_assertion_type=urn%3Aietf%3Aparams%3A'
|
||||
'oauth%3Aclient-assertion-type%3Ajwt-bearer'),
|
||||
request.text)
|
||||
self.assertIn('client_assertion=', request.text)
|
||||
self.assertIn(f'scope={scope}', request.text)
|
||||
self.assertIn('grant_type=client_credentials', request.text)
|
||||
if not access_token:
|
||||
access_token = f'access_token{str(uuid.uuid4())}'
|
||||
if not resp:
|
||||
if status_code == 200:
|
||||
response = {
|
||||
'access_token': access_token,
|
||||
'expires_in': 1800,
|
||||
'refresh_expires_in': 0,
|
||||
'token_type': 'Bearer',
|
||||
'not-before-policy': 0,
|
||||
'scope': scope
|
||||
}
|
||||
else:
|
||||
response = {'error': 'error_title',
|
||||
'error_description': 'error message'}
|
||||
else:
|
||||
response = copy.deepcopy(resp)
|
||||
context.status_code = status_code
|
||||
return response
|
||||
|
||||
def _get_default_mock_conf_effect(self):
|
||||
return get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
|
||||
def _check_authorization_header(self):
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
headers = auth_context.get_headers(session)
|
||||
bearer = f'Bearer {self.access_token}'
|
||||
self.assertIn('Authorization', headers)
|
||||
self.assertEqual(bearer, headers.get('Authorization'))
|
||||
return auth_context
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_init_without_token_endpoint(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint='',
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope
|
||||
)
|
||||
self.assertRaises(TackerException,
|
||||
context.generate_tacker_service_context)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_init_without_scope(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret)
|
||||
self.assertRaises(TackerException,
|
||||
context.generate_tacker_service_context)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_init_without_keystone_middleware_opts(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
self.assertRaises(TackerException,
|
||||
context.generate_tacker_service_context)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('keystoneauth1.loading.session.Session.load_from_options')
|
||||
def test_create_session(self, mock_load_from_options, mock_get_conf_key):
|
||||
certfile = f'/demo/certfile{str(uuid.uuid4())}'
|
||||
keyfile = f'/demo/keyfile{str(uuid.uuid4())}'
|
||||
cafile = f'/demo/cafile{str(uuid.uuid4())}'
|
||||
conf_insecure = True
|
||||
http_connect_timeout = 1000
|
||||
|
||||
def load_side_effect(**kwargs):
|
||||
self.assertEqual(conf_insecure, kwargs.get('insecure'))
|
||||
self.assertEqual(cafile, kwargs.get('cacert'))
|
||||
self.assertEqual(certfile, kwargs.get('cert'))
|
||||
self.assertEqual(keyfile, kwargs.get('key'))
|
||||
self.assertEqual(http_connect_timeout, kwargs.get('timeout'))
|
||||
return MockSession()
|
||||
mock_load_from_options.side_effect = load_side_effect
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='tls_client_auth',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope,
|
||||
certfile=certfile,
|
||||
keyfile=keyfile,
|
||||
cafile=cafile,
|
||||
insecure=conf_insecure,
|
||||
http_connect_timeout=http_connect_timeout)
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
auth_context.create_session()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_connection_params(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
params = auth_context.get_connection_params(session)
|
||||
self.assertDictEqual(params, {})
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_tls_client_auth(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='tls_client_auth',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='tls_client_auth',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope)
|
||||
auth_context = self._check_authorization_header()
|
||||
result = auth_context.invalidate()
|
||||
self.assertEqual(True, result)
|
||||
self.assertIsNone(auth_context.access_token)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_client_secret_post(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='client_secret_post',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token
|
||||
)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_post',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_client_secret_basic(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='client_secret_basic',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_basic',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open(read_data=_get_sample_key(
|
||||
JWT_KEY_FILE)))
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_private_key_jwt(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='private_key_jwt',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='private_key_jwt',
|
||||
client_id=self.client_id,
|
||||
audience=self.audience,
|
||||
jwt_key_file=f'/demo/jwt_key_file{str(uuid.uuid4())}',
|
||||
jwt_algorithm='RS256',
|
||||
jwt_bearer_time_out=self.jwt_bearer_time_out,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_client_secret_jwt(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='client_secret_jwt',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_jwt',
|
||||
client_id=self.client_id,
|
||||
audience=self.audience,
|
||||
client_secret=self.client_secret,
|
||||
jwt_algorithm='HS256',
|
||||
jwt_bearer_time_out=self.jwt_bearer_time_out,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_invalid_auth_method(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_other',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope
|
||||
)
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_connect_fail(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
raise_error=ksa_exceptions.RequestTimeout('connect time out.'))
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_is_not_200(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
status_code=201)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_not_include_access_token(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
status_code=200,
|
||||
resp={'error': 'invalid_client',
|
||||
'error_description': 'The client is not found.'})
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_unknown_error(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
raise_error=Exception('unknown error occurred.'))
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# 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.
|
||||
import base64
|
||||
import copy
|
||||
import os
|
||||
from unittest import mock
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from requests_mock.contrib import fixture as rm_fixture
|
||||
|
||||
from keystoneauth1 import exceptions as ksa_exceptions
|
||||
|
||||
from tacker.common.exceptions import TackerException
|
||||
from tacker import context
|
||||
from tacker.tests.unit import base
|
||||
|
||||
JWT_KEY_FILE = 'jwt_private.key'
|
||||
|
||||
|
||||
def _get_sample_key(name):
|
||||
filename = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"./sample_keys/", name)
|
||||
with open(filename, "r") as f:
|
||||
content = f.read()
|
||||
return content
|
||||
|
||||
|
||||
def get_mock_conf_effect(audience=None, token_endpoint=None,
|
||||
auth_method=None, client_id=None, client_secret=None,
|
||||
scope=None, jwt_key_file=None, jwt_algorithm=None,
|
||||
jwt_bearer_time_out=None, certfile=None, keyfile=None,
|
||||
cafile=None, http_connect_timeout=None, insecure=None):
|
||||
def mock_conf_key_effect(name):
|
||||
if name == 'keystone_authtoken':
|
||||
return MockConfig(conf=None)
|
||||
elif name == 'ext_oauth2_auth':
|
||||
config = {'use_ext_oauth2_auth': True}
|
||||
if audience:
|
||||
config['audience'] = audience
|
||||
if token_endpoint:
|
||||
config['token_endpoint'] = token_endpoint
|
||||
if auth_method:
|
||||
config['auth_method'] = auth_method
|
||||
if client_id:
|
||||
config['client_id'] = client_id
|
||||
if client_secret:
|
||||
config['client_secret'] = client_secret
|
||||
if scope:
|
||||
config['scope'] = scope
|
||||
if jwt_key_file:
|
||||
config['jwt_key_file'] = jwt_key_file
|
||||
if jwt_algorithm:
|
||||
config['jwt_algorithm'] = jwt_algorithm
|
||||
if jwt_bearer_time_out:
|
||||
config['jwt_bearer_time_out'] = jwt_bearer_time_out
|
||||
if certfile:
|
||||
config['certfile'] = certfile
|
||||
if keyfile:
|
||||
config['keyfile'] = keyfile
|
||||
if cafile:
|
||||
config['cafile'] = cafile
|
||||
if cafile:
|
||||
config['http_connect_timeout'] = http_connect_timeout
|
||||
if cafile:
|
||||
config['insecure'] = insecure
|
||||
return MockConfig(
|
||||
conf=config)
|
||||
else:
|
||||
return cfg.CONF._get(name)
|
||||
return mock_conf_key_effect
|
||||
|
||||
|
||||
class MockConfig(object):
|
||||
def __init__(self, conf=None):
|
||||
self.conf = conf
|
||||
|
||||
def __getattr__(self, name):
|
||||
if not self.conf or name not in self.conf:
|
||||
raise cfg.NoSuchOptError(f'not found {name}')
|
||||
return self.conf.get(name)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.conf
|
||||
|
||||
|
||||
class MockSession(object):
|
||||
def __init__(self, ):
|
||||
self.auth = None
|
||||
|
||||
|
||||
class TestExtOAuth2Auth(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestExtOAuth2Auth, self).setUp()
|
||||
self.requests_mock = self.useFixture(rm_fixture.Fixture())
|
||||
self.token_endpoint = 'http://demo/token_endpoint'
|
||||
self.auth_method = 'client_secret_post'
|
||||
self.client_id = 'test_client_id'
|
||||
self.client_secret = 'test_client_secret'
|
||||
self.scope = 'tacker_api'
|
||||
self.access_token = f'access_token_{str(uuid.uuid4())}'
|
||||
self.audience = 'http://demo/audience'
|
||||
self.jwt_bearer_time_out = 2800
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
def _get_access_token_response(self, request, context,
|
||||
auth_method=None,
|
||||
client_id=None,
|
||||
client_secret=None,
|
||||
scope=None,
|
||||
access_token=None,
|
||||
status_code=200,
|
||||
raise_error=None,
|
||||
resp=None
|
||||
):
|
||||
if raise_error:
|
||||
raise raise_error
|
||||
if auth_method == 'tls_client_auth':
|
||||
body = (f'client_id={client_id}&scope={scope}'
|
||||
f'&grant_type=client_credentials')
|
||||
self.assertEqual(request.text, body)
|
||||
elif auth_method == 'client_secret_post':
|
||||
body = (f'client_id={client_id}&client_secret={client_secret}'
|
||||
f'&scope={scope}&grant_type=client_credentials')
|
||||
self.assertEqual(request.text, body)
|
||||
elif auth_method == 'client_secret_basic':
|
||||
body = f'scope={scope}&grant_type=client_credentials'
|
||||
self.assertEqual(request.text, body)
|
||||
auth_basic = request._request.headers.get('Authorization')
|
||||
self.assertIsNotNone(auth_basic)
|
||||
|
||||
auth = 'Basic ' + base64.standard_b64encode(
|
||||
f'{client_id}:{client_secret}'.encode('ascii')).decode('ascii')
|
||||
self.assertEqual(auth_basic, auth)
|
||||
elif auth_method == 'private_key_jwt':
|
||||
self.assertIn(f'client_id={client_id}', request.text)
|
||||
self.assertIn(('client_assertion_type=urn%3Aietf%3Aparams%3A'
|
||||
'oauth%3Aclient-assertion-type%3Ajwt-bearer'),
|
||||
request.text)
|
||||
self.assertIn('client_assertion=', request.text)
|
||||
self.assertIn(f'scope={scope}', request.text)
|
||||
self.assertIn('grant_type=client_credentials', request.text)
|
||||
elif auth_method == 'client_secret_jwt':
|
||||
self.assertIn(f'client_id={client_id}', request.text)
|
||||
self.assertIn(('client_assertion_type=urn%3Aietf%3Aparams%3A'
|
||||
'oauth%3Aclient-assertion-type%3Ajwt-bearer'),
|
||||
request.text)
|
||||
self.assertIn('client_assertion=', request.text)
|
||||
self.assertIn(f'scope={scope}', request.text)
|
||||
self.assertIn('grant_type=client_credentials', request.text)
|
||||
if not access_token:
|
||||
access_token = f'access_token{str(uuid.uuid4())}'
|
||||
if not resp:
|
||||
if status_code == 200:
|
||||
response = {
|
||||
'access_token': access_token,
|
||||
'expires_in': 1800,
|
||||
'refresh_expires_in': 0,
|
||||
'token_type': 'Bearer',
|
||||
'not-before-policy': 0,
|
||||
'scope': scope
|
||||
}
|
||||
else:
|
||||
response = {'error': 'error_title',
|
||||
'error_description': 'error message'}
|
||||
else:
|
||||
response = copy.deepcopy(resp)
|
||||
context.status_code = status_code
|
||||
return response
|
||||
|
||||
def _get_default_mock_conf_effect(self):
|
||||
return get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
|
||||
def _check_authorization_header(self):
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
headers = auth_context.get_headers(session)
|
||||
bearer = f'Bearer {self.access_token}'
|
||||
self.assertIn('Authorization', headers)
|
||||
self.assertEqual(bearer, headers.get('Authorization'))
|
||||
return auth_context
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_init_without_token_endpoint(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint='',
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope
|
||||
)
|
||||
self.assertRaises(TackerException,
|
||||
context.generate_tacker_service_context)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_init_without_scope(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret)
|
||||
self.assertRaises(TackerException,
|
||||
context.generate_tacker_service_context)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_init_without_keystone_middleware_opts(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
self.assertRaises(TackerException,
|
||||
context.generate_tacker_service_context)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('keystoneauth1.loading.session.Session.load_from_options')
|
||||
def test_create_session(self, mock_load_from_options, mock_get_conf_key):
|
||||
certfile = f'/demo/certfile{str(uuid.uuid4())}'
|
||||
keyfile = f'/demo/keyfile{str(uuid.uuid4())}'
|
||||
cafile = f'/demo/cafile{str(uuid.uuid4())}'
|
||||
conf_insecure = True
|
||||
http_connect_timeout = 1000
|
||||
|
||||
def load_side_effect(**kwargs):
|
||||
self.assertEqual(conf_insecure, kwargs.get('insecure'))
|
||||
self.assertEqual(cafile, kwargs.get('cacert'))
|
||||
self.assertEqual(certfile, kwargs.get('cert'))
|
||||
self.assertEqual(keyfile, kwargs.get('key'))
|
||||
self.assertEqual(http_connect_timeout, kwargs.get('timeout'))
|
||||
return MockSession()
|
||||
mock_load_from_options.side_effect = load_side_effect
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='tls_client_auth',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope,
|
||||
certfile=certfile,
|
||||
keyfile=keyfile,
|
||||
cafile=cafile,
|
||||
insecure=conf_insecure,
|
||||
http_connect_timeout=http_connect_timeout)
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
auth_context.create_session()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_connection_params(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
params = auth_context.get_connection_params(session)
|
||||
self.assertDictEqual(params, {})
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_tls_client_auth(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='tls_client_auth',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='tls_client_auth',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope)
|
||||
auth_context = self._check_authorization_header()
|
||||
result = auth_context.invalidate()
|
||||
self.assertEqual(True, result)
|
||||
self.assertIsNone(auth_context.access_token)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_client_secret_post(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='client_secret_post',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token
|
||||
)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_post',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_client_secret_basic(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='client_secret_basic',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_basic',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open(read_data=_get_sample_key(
|
||||
JWT_KEY_FILE)))
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_private_key_jwt(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='private_key_jwt',
|
||||
client_id=self.client_id,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='private_key_jwt',
|
||||
client_id=self.client_id,
|
||||
audience=self.audience,
|
||||
jwt_key_file=f'/demo/jwt_key_file{str(uuid.uuid4())}',
|
||||
jwt_algorithm='RS256',
|
||||
jwt_bearer_time_out=self.jwt_bearer_time_out,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_client_secret_jwt(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method='client_secret_jwt',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_jwt',
|
||||
client_id=self.client_id,
|
||||
audience=self.audience,
|
||||
client_secret=self.client_secret,
|
||||
jwt_algorithm='HS256',
|
||||
jwt_bearer_time_out=self.jwt_bearer_time_out,
|
||||
scope=self.scope)
|
||||
self._check_authorization_header()
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_invalid_auth_method(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_effect(
|
||||
token_endpoint=self.token_endpoint,
|
||||
auth_method='client_secret_other',
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope
|
||||
)
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_connect_fail(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
raise_error=ksa_exceptions.RequestTimeout('connect time out.'))
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_is_not_200(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
status_code=201)
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_not_include_access_token(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
status_code=200,
|
||||
resp={'error': 'invalid_client',
|
||||
'error_description': 'The client is not found.'})
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_headers_unknown_error(self, mock_get_conf_key):
|
||||
def mock_resp(request, context):
|
||||
return self._get_access_token_response(
|
||||
request, context,
|
||||
auth_method=self.auth_method,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
scope=self.scope,
|
||||
access_token=self.access_token,
|
||||
raise_error=Exception('unknown error occurred.'))
|
||||
self.requests_mock.post(self.token_endpoint, json=mock_resp)
|
||||
mock_get_conf_key.side_effect = self._get_default_mock_conf_effect()
|
||||
auth_context = context.generate_tacker_service_context()
|
||||
session = auth_context.create_session()
|
||||
self.assertRaises(TackerException, auth_context.get_headers, session)
|
||||
|
@ -1,255 +1,255 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# 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.
|
||||
|
||||
from unittest import mock
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from requests_mock.contrib import fixture as rm_fixture
|
||||
|
||||
from tacker import context as t_context
|
||||
from tacker.keymgr.barbican_key_manager import BarbicanKeyManager
|
||||
from tacker.keymgr import exception
|
||||
from tacker.tests.unit import base
|
||||
|
||||
|
||||
def get_mock_conf_key_effect(barbican_endpoint=None):
|
||||
def mock_conf_key_effect(name):
|
||||
if name == 'ext_oauth2_auth':
|
||||
return MockConfig(
|
||||
conf={
|
||||
'use_ext_oauth2_auth': True,
|
||||
'token_endpoint': 'http://demo/token_endpoint',
|
||||
'auth_method': 'client_secret_post',
|
||||
'client_id': 'client_id',
|
||||
'client_secret': 'client_secret',
|
||||
'scope': 'client_secret'
|
||||
})
|
||||
elif name == 'key_manager':
|
||||
conf = {
|
||||
'api_class': 'tacker.keymgr.barbican_key_manager'
|
||||
'.BarbicanKeyManager',
|
||||
'barbican_version': 'v1',
|
||||
'barbican_endpoint': barbican_endpoint
|
||||
}
|
||||
return MockConfig(conf=conf)
|
||||
elif name == 'k8s_vim':
|
||||
return MockConfig(
|
||||
conf={
|
||||
'use_barbican': True
|
||||
})
|
||||
else:
|
||||
return cfg.CONF._get(name)
|
||||
|
||||
return mock_conf_key_effect
|
||||
|
||||
|
||||
class MockConfig(object):
|
||||
def __init__(self, conf=None):
|
||||
self.conf = conf
|
||||
|
||||
def __getattr__(self, name):
|
||||
if not self.conf and name not in self.conf:
|
||||
raise cfg.NoSuchOptError(f'not found {name}')
|
||||
return self.conf.get(name)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.conf
|
||||
|
||||
|
||||
class TestBarbicanKeyManager(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBarbicanKeyManager, self).setUp()
|
||||
self.requests_mock = self.useFixture(rm_fixture.Fixture())
|
||||
self.token_endpoint = 'http://demo/token_endpoint'
|
||||
self.auth_method = 'client_secret_post'
|
||||
self.client_id = 'test_client_id'
|
||||
self.client_secret = 'test_client_secret'
|
||||
self.scope = 'tacker_api'
|
||||
self.access_token = f'access_token_{str(uuid.uuid4())}'
|
||||
self.audience = 'http://demo/audience'
|
||||
self.jwt_bearer_time_out = 2800
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
def _mock_external_token_api(self):
|
||||
def mock_token_resp(request, context):
|
||||
response = {
|
||||
'access_token': self.access_token,
|
||||
'expires_in': 1800,
|
||||
'refresh_expires_in': 0,
|
||||
'token_type': 'Bearer',
|
||||
'not-before-policy': 0,
|
||||
'scope': 'tacker_api'
|
||||
}
|
||||
context.status_code = 200
|
||||
return response
|
||||
|
||||
self.requests_mock.post('http://demo/token_endpoint',
|
||||
json=mock_token_resp)
|
||||
|
||||
def _mock_barbican_get_version_resp(self):
|
||||
def mock_barbican_get_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 200
|
||||
response = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{
|
||||
"id": "v1",
|
||||
"status": "stable",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://demo/barbican/v1/"
|
||||
},
|
||||
{
|
||||
"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "https://docs.openstack.org/"}
|
||||
],
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/"
|
||||
"vnd.openstack.key-manager-v1+json"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return response
|
||||
return mock_barbican_get_resp
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('barbicanclient.base.validate_ref_and_return_uuid')
|
||||
def test_delete_ext_oauth2_auth(self, mock_validate, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='http://demo/barbican/')
|
||||
self._mock_external_token_api()
|
||||
mock_validate.return_value = True
|
||||
|
||||
def mock_barbican_delete_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 204
|
||||
return ''
|
||||
|
||||
def mock_barbican_get_for_check_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 200
|
||||
return {}
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican',
|
||||
json=self._mock_barbican_get_version_resp())
|
||||
|
||||
self.requests_mock.delete(
|
||||
'http://demo/barbican/v1/secrets/True',
|
||||
json=mock_barbican_delete_resp)
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican/v1/secrets/True',
|
||||
json=mock_barbican_get_for_check_resp)
|
||||
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
keymgr.delete(auth, 'test')
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('tacker.keymgr.barbican_key_manager.'
|
||||
'BarbicanKeyManager._retrieve_secret_uuid')
|
||||
def test_store_ext_oauth2_auth(self, mock_secret_uuid,
|
||||
mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='http://demo/barbican')
|
||||
secret_id = 'store_secret_uuid'
|
||||
mock_secret_uuid.return_value = secret_id
|
||||
self._mock_external_token_api()
|
||||
|
||||
def mock_barbican_post_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
response = {
|
||||
'name': 'AES key',
|
||||
'expiration': '2023-01-13T19:14:44.180394',
|
||||
'algorithm': 'aes',
|
||||
'bit_length': 256,
|
||||
'mode': 'cbc',
|
||||
'payload': 'YmVlcg==',
|
||||
'payload_content_type': 'application/octet-stream',
|
||||
'payload_content_encoding': 'base64'
|
||||
}
|
||||
context.status_code = 201
|
||||
return response
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican',
|
||||
json=self._mock_barbican_get_version_resp())
|
||||
|
||||
self.requests_mock.post('http://demo/barbican/v1/secrets/',
|
||||
json=mock_barbican_post_resp)
|
||||
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
result = keymgr.store(auth, 'test')
|
||||
self.assertEqual(result, secret_id)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('barbicanclient.base.validate_ref_and_return_uuid')
|
||||
def test_get_ext_oauth2_auth(self, mock_validate, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='http://demo/barbican/')
|
||||
self._mock_external_token_api()
|
||||
mock_validate.return_value = True
|
||||
|
||||
def mock_barbican_get_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 200
|
||||
response = {
|
||||
'id': 'test001'
|
||||
}
|
||||
return response
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican',
|
||||
json=self._mock_barbican_get_version_resp())
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican/v1/secrets/True',
|
||||
json=mock_barbican_get_resp)
|
||||
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
result = keymgr.get(auth, 'test001')
|
||||
self.assertEqual(result.secret_ref,
|
||||
'http://demo/barbican/v1/secrets/test001')
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_ext_oauth2_auth_no_endpoint(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='')
|
||||
self._mock_external_token_api()
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
self.assertRaises(exception.KeyManagerError, keymgr.get, auth, 'test')
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# 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.
|
||||
|
||||
from unittest import mock
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from requests_mock.contrib import fixture as rm_fixture
|
||||
|
||||
from tacker import context as t_context
|
||||
from tacker.keymgr.barbican_key_manager import BarbicanKeyManager
|
||||
from tacker.keymgr import exception
|
||||
from tacker.tests.unit import base
|
||||
|
||||
|
||||
def get_mock_conf_key_effect(barbican_endpoint=None):
|
||||
def mock_conf_key_effect(name):
|
||||
if name == 'ext_oauth2_auth':
|
||||
return MockConfig(
|
||||
conf={
|
||||
'use_ext_oauth2_auth': True,
|
||||
'token_endpoint': 'http://demo/token_endpoint',
|
||||
'auth_method': 'client_secret_post',
|
||||
'client_id': 'client_id',
|
||||
'client_secret': 'client_secret',
|
||||
'scope': 'client_secret'
|
||||
})
|
||||
elif name == 'key_manager':
|
||||
conf = {
|
||||
'api_class': 'tacker.keymgr.barbican_key_manager'
|
||||
'.BarbicanKeyManager',
|
||||
'barbican_version': 'v1',
|
||||
'barbican_endpoint': barbican_endpoint
|
||||
}
|
||||
return MockConfig(conf=conf)
|
||||
elif name == 'k8s_vim':
|
||||
return MockConfig(
|
||||
conf={
|
||||
'use_barbican': True
|
||||
})
|
||||
else:
|
||||
return cfg.CONF._get(name)
|
||||
|
||||
return mock_conf_key_effect
|
||||
|
||||
|
||||
class MockConfig(object):
|
||||
def __init__(self, conf=None):
|
||||
self.conf = conf
|
||||
|
||||
def __getattr__(self, name):
|
||||
if not self.conf and name not in self.conf:
|
||||
raise cfg.NoSuchOptError(f'not found {name}')
|
||||
return self.conf.get(name)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.conf
|
||||
|
||||
|
||||
class TestBarbicanKeyManager(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBarbicanKeyManager, self).setUp()
|
||||
self.requests_mock = self.useFixture(rm_fixture.Fixture())
|
||||
self.token_endpoint = 'http://demo/token_endpoint'
|
||||
self.auth_method = 'client_secret_post'
|
||||
self.client_id = 'test_client_id'
|
||||
self.client_secret = 'test_client_secret'
|
||||
self.scope = 'tacker_api'
|
||||
self.access_token = f'access_token_{str(uuid.uuid4())}'
|
||||
self.audience = 'http://demo/audience'
|
||||
self.jwt_bearer_time_out = 2800
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
def _mock_external_token_api(self):
|
||||
def mock_token_resp(request, context):
|
||||
response = {
|
||||
'access_token': self.access_token,
|
||||
'expires_in': 1800,
|
||||
'refresh_expires_in': 0,
|
||||
'token_type': 'Bearer',
|
||||
'not-before-policy': 0,
|
||||
'scope': 'tacker_api'
|
||||
}
|
||||
context.status_code = 200
|
||||
return response
|
||||
|
||||
self.requests_mock.post('http://demo/token_endpoint',
|
||||
json=mock_token_resp)
|
||||
|
||||
def _mock_barbican_get_version_resp(self):
|
||||
def mock_barbican_get_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 200
|
||||
response = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{
|
||||
"id": "v1",
|
||||
"status": "stable",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://demo/barbican/v1/"
|
||||
},
|
||||
{
|
||||
"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "https://docs.openstack.org/"}
|
||||
],
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/"
|
||||
"vnd.openstack.key-manager-v1+json"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return response
|
||||
return mock_barbican_get_resp
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('barbicanclient.base.validate_ref_and_return_uuid')
|
||||
def test_delete_ext_oauth2_auth(self, mock_validate, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='http://demo/barbican/')
|
||||
self._mock_external_token_api()
|
||||
mock_validate.return_value = True
|
||||
|
||||
def mock_barbican_delete_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 204
|
||||
return ''
|
||||
|
||||
def mock_barbican_get_for_check_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 200
|
||||
return {}
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican',
|
||||
json=self._mock_barbican_get_version_resp())
|
||||
|
||||
self.requests_mock.delete(
|
||||
'http://demo/barbican/v1/secrets/True',
|
||||
json=mock_barbican_delete_resp)
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican/v1/secrets/True',
|
||||
json=mock_barbican_get_for_check_resp)
|
||||
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
keymgr.delete(auth, 'test')
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('tacker.keymgr.barbican_key_manager.'
|
||||
'BarbicanKeyManager._retrieve_secret_uuid')
|
||||
def test_store_ext_oauth2_auth(self, mock_secret_uuid,
|
||||
mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='http://demo/barbican')
|
||||
secret_id = 'store_secret_uuid'
|
||||
mock_secret_uuid.return_value = secret_id
|
||||
self._mock_external_token_api()
|
||||
|
||||
def mock_barbican_post_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
response = {
|
||||
'name': 'AES key',
|
||||
'expiration': '2023-01-13T19:14:44.180394',
|
||||
'algorithm': 'aes',
|
||||
'bit_length': 256,
|
||||
'mode': 'cbc',
|
||||
'payload': 'YmVlcg==',
|
||||
'payload_content_type': 'application/octet-stream',
|
||||
'payload_content_encoding': 'base64'
|
||||
}
|
||||
context.status_code = 201
|
||||
return response
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican',
|
||||
json=self._mock_barbican_get_version_resp())
|
||||
|
||||
self.requests_mock.post('http://demo/barbican/v1/secrets/',
|
||||
json=mock_barbican_post_resp)
|
||||
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
result = keymgr.store(auth, 'test')
|
||||
self.assertEqual(result, secret_id)
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
@mock.patch('barbicanclient.base.validate_ref_and_return_uuid')
|
||||
def test_get_ext_oauth2_auth(self, mock_validate, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='http://demo/barbican/')
|
||||
self._mock_external_token_api()
|
||||
mock_validate.return_value = True
|
||||
|
||||
def mock_barbican_get_resp(request, context):
|
||||
auth_value = f'Bearer {self.access_token}'
|
||||
req_auth = request._request.headers.get('Authorization')
|
||||
self.assertEqual(auth_value, req_auth)
|
||||
context.status_code = 200
|
||||
response = {
|
||||
'id': 'test001'
|
||||
}
|
||||
return response
|
||||
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican',
|
||||
json=self._mock_barbican_get_version_resp())
|
||||
self.requests_mock.get(
|
||||
'http://demo/barbican/v1/secrets/True',
|
||||
json=mock_barbican_get_resp)
|
||||
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
result = keymgr.get(auth, 'test001')
|
||||
self.assertEqual(result.secret_ref,
|
||||
'http://demo/barbican/v1/secrets/test001')
|
||||
|
||||
@mock.patch('oslo_config.cfg.ConfigOpts.__getattr__')
|
||||
def test_get_ext_oauth2_auth_no_endpoint(self, mock_get_conf_key):
|
||||
mock_get_conf_key.side_effect = get_mock_conf_key_effect(
|
||||
barbican_endpoint='')
|
||||
self._mock_external_token_api()
|
||||
auth = t_context.generate_tacker_service_context()
|
||||
keymgr = BarbicanKeyManager(auth.token_endpoint)
|
||||
self.assertRaises(exception.KeyManagerError, keymgr.get, auth, 'test')
|
||||
|
Loading…
Reference in New Issue
Block a user