Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • tfs/controller
1 result
Show changes
Commits on Source (84)
Showing
with 357 additions and 328 deletions
......@@ -168,5 +168,8 @@ delete_local_deployment.sh
local_docker_deployment.sh
local_k8s_deployment.sh
# asdf configuration
.tool-versions
# Other logs
**/logs/*.log.*
......@@ -42,6 +42,8 @@ spec:
value: "0.5"
- name: MONITORED_KPIS_TIME_INTERVAL_AGG
value: "60"
- name: TEST_ML_MODEL
value: "0"
readinessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:10001"]
......
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
#
# 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.
apiVersion: apps/v1
kind: Deployment
metadata:
name: teservice
spec:
selector:
matchLabels:
app: teservice
template:
metadata:
annotations:
config.linkerd.io/skip-inbound-ports: "4189"
labels:
app: teservice
spec:
terminationGracePeriodSeconds: 5
shareProcessNamespace: true
containers:
- name: server
image: labs.etsi.org:5050/tfs/controller/te:latest
imagePullPolicy: Always
ports:
- containerPort: 10030
env:
- name: ERLANG_LOGGER_LEVEL
value: "debug"
- name: ERLANG_COOKIE
value: "tfte-unsafe-cookie"
- name: ERLANG_NODE_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ERLANG_NODE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
readinessProbe:
exec:
command: ["/tfte/bin/tfte", "status"]
livenessProbe:
exec:
command: ["/tfte/bin/tfte", "status"]
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 700m
memory: 1024Mi
---
apiVersion: v1
kind: Service
metadata:
name: teservice
spec:
type: ClusterIP
selector:
app: teservice
ports:
- name: grpc
protocol: TCP
port: 10030
targetPort: 10030
- name: pcep
protocol: TCP
port: 4189
targetPort: 4189
......@@ -34,6 +34,9 @@ export TFS_COMPONENTS="context device pathcomp service slice compute webui load_
# Uncomment to activate L3 CyberSecurity
#export TFS_COMPONENTS="${TFS_COMPONENTS} l3_attackmitigator l3_centralizedattackdetector"
# Uncomment to activate TE
#export TFS_COMPONENTS="${TFS_COMPONENTS} te"
# Set the tag you want to use for your images.
export TFS_IMAGE_TAG="dev"
......
......@@ -3,5 +3,8 @@ src/*/*
# used to prevent breaking symbolic links from source code folders
!src/*/.gitignore
!src/python/__init__.py
!src/erlang/rebar.config
!src/erlang/rebar.lock
!src/erlang/src/tfpb.app.src
uml/generated
......@@ -273,6 +273,7 @@ enum ServiceTypeEnum {
SERVICETYPE_L3NM = 1;
SERVICETYPE_L2NM = 2;
SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 3;
SERVICETYPE_TE = 4;
}
enum ServiceStatusEnum {
......
#!/bin/bash -eu
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
#
# 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.
set -e
FORCE=0
DEFAULT_ACTION="generate"
usage() {
echo "Usage: $0 [-f] [clean|generate]" 1>&2
echo "Options:"
echo " -f: Force regeneration of all protocol buffers"
exit 1;
}
while getopts "fc" o; do
case "${o}" in
f)
FORCE=1
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
ACTION=${1:-$DEFAULT_ACTION}
cd $(dirname $0)
ROOT=$(pwd)
ERLANG_PROTO_DIR="$ROOT/src/erlang"
BUILD_CHECK="$ERLANG_PROTO_DIR/.generated"
tfpb_clean() {
rm -f "$BUILD_CHECK"
rm -rf "$ERLANG_PROTO_DIR/src/"*.erl
rm -rf "$ERLANG_PROTO_DIR/src/erlang/_build"
}
tfpb_generate() {
if [[ -f "$BUILD_CHECK" && $FORCE != 1 ]]; then
echo "Protocol buffer code for Erlang already generated, use -f to force"
exit 0
fi
tfpb_clean
mkdir -p "$ERLANG_PROTO_DIR"
cd "$ERLANG_PROTO_DIR"
rebar3 compile
rebar3 grpc gen
rebar3 compile
touch "$BUILD_CHECK"
echo "Protocol buffer code for Erlang generated"
}
case "$ACTION" in
clean) tfpb_clean;;
generate) tfpb_generate;;
*) usage;;
esac
......@@ -13,15 +13,14 @@
// limitations under the License.
syntax = "proto3";
package l3_attackmitigator;
import "context.proto";
import "l3_centralizedattackdetector.proto";
service L3Attackmitigator{
// Perform Mitigation
rpc PerformMitigation (L3AttackmitigatorOutput) returns (context.Empty) {}
// Get Mitigation
rpc PerformMitigation (L3AttackmitigatorOutput) returns (l3_centralizedattackdetector.StatusMessage) {}
rpc GetMitigation (context.Empty) returns (context.Empty) {}
// Get Configured ACL Rules
rpc GetConfiguredACLRules (context.Empty) returns (ACLRules) {}
}
......
......@@ -13,18 +13,23 @@
// limitations under the License.
syntax = "proto3";
package l3_centralizedattackdetector;
import "context.proto";
service L3Centralizedattackdetector {
// Analyze single input to the ML model in the CAD component
rpc AnalyzeConnectionStatistics (L3CentralizedattackdetectorMetrics) returns (Empty) {}
rpc AnalyzeConnectionStatistics (L3CentralizedattackdetectorMetrics) returns (StatusMessage) {}
// Analyze a batch of inputs to the ML model in the CAD component
rpc AnalyzeBatchConnectionStatistics (L3CentralizedattackdetectorBatchInput) returns (Empty) {}
rpc AnalyzeBatchConnectionStatistics (L3CentralizedattackdetectorBatchInput) returns (StatusMessage) {}
// Get the list of features used by the ML model in the CAD component
rpc GetFeaturesIds (Empty) returns (AutoFeatures) {}
rpc GetFeaturesIds (context.Empty) returns (AutoFeatures) {}
// Sets the list of attack IPs in order to be used to compute the prediction accuracy of the
// ML model in the CAD component in case of testing the ML model.
rpc SetAttackIPs (AttackIPs) returns (context.Empty) {}
}
message Feature {
......@@ -63,6 +68,10 @@ message L3CentralizedattackdetectorBatchInput {
repeated L3CentralizedattackdetectorMetrics metrics = 1;
}
message Empty {
message StatusMessage {
string message = 1;
}
message AttackIPs {
repeated string attack_ips = 1;
}
\ No newline at end of file
*
!rebar.config
!rebar.lock
!src/
!src/tfpb.app.src
% Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
%
% 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.
{erl_opts, [debug_info]}.
{deps, [grpcbox]}.
{grpc, [{protos, "../.."},
{gpb_opts, [{i, "../.."}, {strbin, true}, {descriptor, true}, {module_name_suffix, "_pb"}]}]}.
{plugins, [grpcbox_plugin]}.
{"1.2.0",
[{<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},1},
{<<"chatterbox">>,{pkg,<<"ts_chatterbox">>,<<"0.12.0">>},1},
{<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},1},
{<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1},
{<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.15.0">>},0},
{<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},2}]}.
[
{pkg_hash,[
{<<"acceptor_pool">>, <<"43C20D2ACAE35F0C2BCD64F9D2BDE267E459F0F3FD23DAB26485BF518C281B21">>},
{<<"chatterbox">>, <<"4E54F199E15C0320B85372A24E35554A2CCFC4342E0B7CD8DAED9A04F9B8EF4A">>},
{<<"ctx">>, <<"8FF88B70E6400C4DF90142E7F130625B82086077A45364A78D208ED3ED53C7FE">>},
{<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>},
{<<"grpcbox">>, <<"97C7126296A091602D372EBF5860A04F7BC795B45B33A984CAD2B8E362774FD8">>},
{<<"hpack">>, <<"17670F83FF984AE6CD74B1C456EDDE906D27FF013740EE4D9EFAA4F1BF999633">>}]},
{pkg_hash_ext,[
{<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>},
{<<"chatterbox">>, <<"6478C161BC60244F41CD5847CC3ACCD26D997883E9F7FACD36FF24533B2FA579">>},
{<<"ctx">>, <<"A14ED2D1B67723DBEBBE423B28D7615EB0BDCBA6FF28F2D1F1B0A7E1D4AA5FC2">>},
{<<"gproc">>, <<"580ADAFA56463B75263EF5A5DF4C86AF321F68694E7786CB057FD805D1E2A7DE">>},
{<<"grpcbox">>, <<"161ABE9E17E7D1982EFA6488ADEAA13C3E847A07984A6E6B224E553368918647">>},
{<<"hpack">>, <<"06F580167C4B8B8A6429040DF36CC93BBA6D571FAEAEC1B28816523379CBB23A">>}]}
].
%% Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
%%
%% 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.
{application, tfpb,
[{description, "Teraflow Erlang Protocol Buffers"},
{vsn, "0.1.0"},
{registered, []},
{applications, [kernel, stdlib, grpcbox]},
{env, []},
{modules, []},
{licenses, ["Apache 2.0"]},
{links, []}
]}.
......@@ -56,6 +56,7 @@ class ServiceNameEnum(Enum):
OPTICALATTACKDETECTOR = 'opticalattackdetector'
OPTICALATTACKMITIGATOR = 'opticalattackmitigator'
CACHING = 'caching'
TE = 'te'
# Used for test and debugging only
DLT_GATEWAY = 'dltgateway'
......@@ -80,6 +81,7 @@ DEFAULT_SERVICE_GRPC_PORTS = {
ServiceNameEnum.OPTICALATTACKMANAGER .value : 10005,
ServiceNameEnum.INTERDOMAIN .value : 10010,
ServiceNameEnum.PATHCOMP .value : 10020,
ServiceNameEnum.TE .value : 10030,
# Used for test and debugging only
ServiceNameEnum.DLT_GATEWAY .value : 50051,
......
......@@ -21,6 +21,7 @@ class ORM_ServiceTypeEnum(enum.Enum):
L3NM = ServiceTypeEnum.SERVICETYPE_L3NM
L2NM = ServiceTypeEnum.SERVICETYPE_L2NM
TAPI_CONNECTIVITY_SERVICE = ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE
TE = ServiceTypeEnum.SERVICETYPE_TE
grpc_to_enum__service_type = functools.partial(
grpc_to_enum, ServiceTypeEnum, ORM_ServiceTypeEnum)
# l3_attackmitigator
- Receives packages and process it with TSTAT
- Functions: ReportSummarizeKpi(KpiList)
# L3 Attack Mitigator
Receives detected attacks from the Centralized Attack Detector component and performs the necessary mitigations.
## Functions:
- PerformMitigation(L3AttackmitigatorOutput) -> StatusMessage
- GetMitigation(Empty) -> Empty
- GetConfiguredACLRules(Empty) -> ACLRules
......@@ -15,17 +15,12 @@
import grpc, logging
from common.Constants import ServiceNameEnum
from common.Settings import get_service_host, get_service_port_grpc
from common.proto.context_pb2 import Empty
from common.proto.l3_attackmitigator_pb2 import L3AttackmitigatorOutput, ACLRules
from common.proto.l3_attackmitigator_pb2_grpc import L3AttackmitigatorStub
from common.proto.l3_centralizedattackdetector_pb2 import StatusMessage
from common.tools.client.RetryDecorator import retry, delay_exponential
from common.proto.l3_attackmitigator_pb2_grpc import (
L3AttackmitigatorStub,
)
from common.proto.l3_attackmitigator_pb2 import (
L3AttackmitigatorOutput, ACLRules
)
from common.proto.context_pb2 import (
Empty
)
from common.tools.grpc.Tools import grpc_message_to_json_string
LOGGER = logging.getLogger(__name__)
MAX_RETRIES = 15
......@@ -37,7 +32,7 @@ class l3_attackmitigatorClient:
if not host: host = get_service_host(ServiceNameEnum.L3_AM)
if not port: port = get_service_port_grpc(ServiceNameEnum.L3_AM)
self.endpoint = "{}:{}".format(host, port)
LOGGER.debug("Creating channel to {}...".format(self.endpoint))
LOGGER.debug("Creating channel to {:s}...".format(self.endpoint))
self.channel = None
self.stub = None
self.connect()
......@@ -54,23 +49,22 @@ class l3_attackmitigatorClient:
self.stub = None
@RETRY_DECORATOR
def PerformMitigation(self, request: L3AttackmitigatorOutput) -> Empty:
LOGGER.debug('PerformMitigation request: {}'.format(request))
def PerformMitigation(self, request: L3AttackmitigatorOutput) -> StatusMessage:
LOGGER.debug('PerformMitigation request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.PerformMitigation(request)
LOGGER.debug('PerformMitigation result: {}'.format(response))
LOGGER.debug('PerformMitigation result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def GetMitigation(self, request: Empty) -> Empty:
LOGGER.debug('GetMitigation request: {}'.format(request))
LOGGER.debug('GetMitigation request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.GetMitigation(request)
LOGGER.debug('GetMitigation result: {}'.format(response))
LOGGER.debug('GetMitigation result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def GetConfiguredACLRules(self, request: Empty) -> ACLRules:
LOGGER.debug('GetConfiguredACLRules request: {}'.format(request))
LOGGER.debug('GetConfiguredACLRules request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.GetConfiguredACLRules(request)
LOGGER.debug('GetConfiguredACLRules result: {}'.format(response))
LOGGER.debug('GetConfiguredACLRules result: {:s}'.format(grpc_message_to_json_string(response)))
return response
......@@ -11,5 +11,3 @@
# 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.
# no extra dependency
......@@ -13,33 +13,39 @@
# limitations under the License.
from __future__ import print_function
import grpc
import logging
import time
from common.proto.l3_centralizedattackdetector_pb2 import Empty
from common.proto.l3_attackmitigator_pb2_grpc import L3AttackmitigatorServicer
from common.proto.l3_attackmitigator_pb2 import ACLRules
from common.proto.context_pb2 import (
ServiceId,
ConfigActionEnum,
)
from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method
from common.proto.acl_pb2 import AclForwardActionEnum, AclLogActionEnum, AclRuleTypeEnum
from common.proto.context_pb2 import ConfigActionEnum, Service, ServiceId, ConfigRule
from common.proto.context_pb2 import ConfigActionEnum, Empty, Service, ServiceId
from common.proto.l3_attackmitigator_pb2 import ACLRules, L3AttackmitigatorOutput
from common.proto.l3_attackmitigator_pb2_grpc import L3AttackmitigatorServicer
from common.proto.l3_centralizedattackdetector_pb2 import StatusMessage
from common.tools.grpc.Tools import grpc_message_to_json_string
from context.client.ContextClient import ContextClient
from service.client.ServiceClient import ServiceClient
from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method
LOGGER = logging.getLogger(__name__)
METRICS_POOL = MetricsPool('l3_attackmitigator', 'RPC')
METRICS_POOL = MetricsPool("l3_attackmitigator", "RPC")
class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
def __init__(self):
LOGGER.info("Creating Attack Mitigator Service")
"""
Initializes the Attack Mitigator service.
Args:
None.
Returns:
None.
"""
LOGGER.info("Creating Attack Mitigator service")
self.last_value = -1
self.last_tag = 0
......@@ -60,6 +66,23 @@ class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
src_port: str,
dst_port: str,
) -> None:
"""
Configures an ACL rule to block undesired TCP traffic.
Args:
context_uuid (str): The UUID of the context.
service_uuid (str): The UUID of the service.
device_uuid (str): The UUID of the device.
endpoint_uuid (str): The UUID of the endpoint.
src_ip (str): The source IP address.
dst_ip (str): The destination IP address.
src_port (str): The source port.
dst_port (str): The destination port.
Returns:
None.
"""
# Create ServiceId
service_id = ServiceId()
service_id.context_id.context_uuid.uuid = context_uuid
......@@ -107,29 +130,41 @@ class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
acl_entry.action.forward_action = AclForwardActionEnum.ACLFORWARDINGACTION_DROP
acl_entry.action.log_action = AclLogActionEnum.ACLLOGACTION_NOLOG
LOGGER.info("ACL Rule Set: %s", grpc_message_to_json_string(acl_rule_set))
LOGGER.info("ACL Config Rule: %s", grpc_message_to_json_string(acl_config_rule))
LOGGER.info(f"ACL Rule Set: {grpc_message_to_json_string(acl_rule_set)}")
LOGGER.info(f"ACL Config Rule: {grpc_message_to_json_string(acl_config_rule)}")
# Add the ACLRuleSet to the list of configured ACLRuleSets
self.configured_acl_config_rules.append(acl_config_rule)
LOGGER.info(service_request)
# Update the Service with the new ACL RuleSet
service_reply: ServiceId = self.service_client.UpdateService(service_request)
service_reply = self.service_client.UpdateService(service_request)
LOGGER.info("Service reply: %s", grpc_message_to_json_string(service_reply))
LOGGER.info(f"Service reply: {grpc_message_to_json_string(service_reply)}")
if service_reply != service_request.service_id: # pylint: disable=no-member
raise Exception("Service update failed. Wrong ServiceId was returned")
@safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
def PerformMitigation(self, request, context):
def PerformMitigation(self, request : L3AttackmitigatorOutput, context : grpc.ServicerContext) -> StatusMessage:
"""
Performs mitigation on an attack by configuring an ACL rule to block undesired TCP traffic.
Args:
request (L3AttackmitigatorOutput): The request message containing the attack mitigation information.
context (Empty): The context of the request.
Returns:
StatusMessage: A response with a message indicating that the attack mitigation information
was received and processed.
"""
last_value = request.confidence
last_tag = request.tag
LOGGER.info(
"Attack Mitigator received attack mitigation information. Prediction confidence: %s, Predicted class: %s",
last_value,
last_tag,
f"Attack Mitigator received attack mitigation information. Prediction confidence: {last_value}, Predicted class: {last_tag}"
)
ip_o = request.ip_o
......@@ -141,21 +176,23 @@ class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
counter = 0
service_id = request.service_id
LOGGER.info("Service Id.:\n{}".format(grpc_message_to_json_string(service_id)))
LOGGER.info(f"Service Id.: {grpc_message_to_json_string(service_id)}")
LOGGER.info("Retrieving service from Context")
while sentinel:
try:
service = self.context_client.GetService(service_id)
sentinel = False
except Exception as e:
counter = counter + 1
LOGGER.debug("Waiting 2 seconds", counter, e)
LOGGER.debug(f"Waiting 2 seconds for service to be available (attempt: {counter})")
time.sleep(2)
LOGGER.info(f"Service with Service Id.: {grpc_message_to_json_string(service_id)}\n{grpc_message_to_json_string(service)}")
LOGGER.info(
f"Service with Service Id.: {grpc_message_to_json_string(service_id)}\n{grpc_message_to_json_string(service)}"
)
LOGGER.info("Adding new rule to the service to block the attack")
self.configure_acl_rule(
context_uuid=service_id.context_id.context_uuid.uuid,
service_uuid=service_id.service_uuid.uuid,
......@@ -167,8 +204,8 @@ class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
dst_port=port_d,
)
LOGGER.info("Service with new rule:\n{}".format(grpc_message_to_json_string(service)))
LOGGER.info("Updating service with the new rule")
self.service_client.UpdateService(service)
service = self.context_client.GetService(service_id)
......@@ -178,10 +215,21 @@ class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
)
)
return Empty(message=f"OK, received values: {last_tag} with confidence {last_value}.")
return StatusMessage(message=f"OK, received values: {last_tag} with confidence {last_value}.")
@safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
def GetConfiguredACLRules(self, request, context):
def GetConfiguredACLRules(self, request : Empty, context : grpc.ServicerContext) -> ACLRules:
"""
Returns the configured ACL rules.
Args:
request (Empty): The request message.
context (Empty): The context of the RPC call.
Returns:
acl_rules (ACLRules): The configured ACL rules.
"""
acl_rules = ACLRules()
for acl_config_rule in self.configured_acl_config_rules:
......
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
#
# 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 __future__ import print_function
import logging
from common.proto.l3_centralizedattackdetector_pb2 import (
Empty
)
from common.proto.l3_attackmitigator_pb2_grpc import (
L3AttackmitigatorServicer,
)
from common.proto.context_pb2 import (
Service, ServiceId, ServiceConfig, ServiceTypeEnum, ServiceStatusEnum, ServiceStatus, Context, ContextId, Uuid,
Timestamp, ConfigRule, ConfigRule_Custom, ConfigActionEnum, Device, DeviceId, DeviceConfig,
DeviceOperationalStatusEnum, DeviceDriverEnum, EndPoint, Link, LinkId, EndPoint, EndPointId, Topology, TopologyId
)
from common.proto.context_pb2_grpc import (
ContextServiceStub
)
from common.proto.service_pb2_grpc import (
ServiceServiceStub
)
from datetime import datetime
import grpc
LOGGER = logging.getLogger(__name__)
CONTEXT_CHANNEL = "192.168.165.78:1010"
SERVICE_CHANNEL = "192.168.165.78:3030"
class l3_attackmitigatorServiceServicerImpl(L3AttackmitigatorServicer):
def GetNewService(self, service_id):
service = Service()
service_id_obj = self.GenerateServiceId(service_id)
service.service_id.CopyFrom(service_id_obj)
service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM
service_status = ServiceStatus()
service_status.service_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE
service.service_status.CopyFrom(service_status)
timestamp = Timestamp()
timestamp.timestamp = datetime.timestamp(datetime.now())
service.timestamp.CopyFrom(timestamp)
return service
def GetNewContext(self, service_id):
context = Context()
context_id = ContextId()
uuid = Uuid()
uuid.uuid = service_id
context_id.context_uuid.CopyFrom(uuid)
context.context_id.CopyFrom(context_id)
return context
def GetNewDevice(self, service_id):
device = Device()
device_id = DeviceId()
uuid = Uuid()
uuid.uuid = service_id
device_id.device_uuid.CopyFrom(uuid)
device.device_type="test"
device.device_id.CopyFrom(device_id)
device.device_operational_status = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED
return device
def GetNewLink(self, service_id):
link = Link()
link_id = LinkId()
uuid = Uuid()
uuid.uuid = service_id
link_id.link_uuid.CopyFrom(uuid)
link.link_id.CopyFrom(link_id)
return link
def GetNewTopology(self,context_id, device_id, link_id):
topology = Topology()
topology_id = TopologyId()
topology_id.context_id.CopyFrom(context_id)
uuid = Uuid()
uuid.uuid = "test_crypto"
topology_id.topology_uuid.CopyFrom(uuid)
topology.topology_id.CopyFrom(topology_id)
topology.device_ids.extend([device_id])
topology.link_ids.extend([link_id])
return topology
def GetNewEndpoint(self, topology_id, device_id, uuid_name):
endpoint = EndPoint()
endpoint_id = EndPointId()
endpoint_id.topology_id.CopyFrom(topology_id)
endpoint_id.device_id.CopyFrom(device_id)
uuid = Uuid()
uuid.uuid = uuid_name
endpoint_id.endpoint_uuid.CopyFrom(uuid)
endpoint.endpoint_id.CopyFrom(endpoint_id)
endpoint.endpoint_type = "test"
return endpoint
def __init__(self):
LOGGER.debug("Creating Servicer...")
self.last_value = -1
self.last_tag = 0
"""
context = self.GetNewContext("test_crypto")
print(context, flush=True)
print(self.SetContext(context))
service = self.GetNewService("test_crypto")
print("This is the new service", self.CreateService(service), flush = True)
ip_o = "127.0.0.1"
ip_d = "127.0.0.2"
port_o = "123"
port_d = "124"
service_id = self.GenerateServiceId("test_crypto")
config_rule = self.GetConfigRule(ip_o, ip_d, port_o, port_d)
service = self.GetService(service_id)
print("Service obtained from id", service, flush=True)
config_rule = self.GetConfigRule(ip_o, ip_d, port_o, port_d)
#service_config = service.service_config
#service_config.append(config_rule)
service_config = ServiceConfig()
service_config.config_rules.extend([config_rule])
service.service_config.CopyFrom(service_config)
device = self.GetNewDevice("test_crypto")
print("New device", device, flush=True)
device_id = self.SetDevice(device)
link = self.GetNewLink("test_crypto")
print("New link", link, flush=True)
link_id = self.SetLink(link)
topology = self.GetNewTopology(context.context_id, device.device_id, link.link_id)
print("New topology", topology, flush=True)
topology_id = self.SetTopology(topology)
endpoint = self.GetNewEndpoint(topology.topology_id, device.device_id, "test_crypto")
print("New endpoint", endpoint, flush=True)
link.link_endpoint_ids.extend([endpoint.endpoint_id])
self.SetLink(link)
print("Service with new rule", service, flush=True)
self.UpdateService(service)
service2 = self.GetService(service_id)
print("Service obtained from id after updating", service2, flush=True)
"""
def GenerateRuleValue(self, ip_o, ip_d, port_o, port_d):
value = {
'ipv4:source-address': ip_o,
'ipv4:destination-address': ip_d,
'transport:source-port': port_o,
'transport:destination-port': port_d,
'forwarding-action': 'DROP',
}
return value
def GetConfigRule(self, ip_o, ip_d, port_o, port_d):
config_rule = ConfigRule()
config_rule_custom = ConfigRule_Custom()
config_rule.action = ConfigActionEnum.CONFIGACTION_SET
config_rule_custom.resource_key = 'test'
config_rule_custom.resource_value = str(self.GenerateRuleValue(ip_o, ip_d, port_o, port_d))
config_rule.custom.CopyFrom(config_rule_custom)
return config_rule
def GenerateServiceId(self, service_id):
service_id_obj = ServiceId()
context_id = ContextId()
uuid = Uuid()
uuid.uuid = service_id
context_id.context_uuid.CopyFrom(uuid)
service_id_obj.context_id.CopyFrom(context_id)
service_id_obj.service_uuid.CopyFrom(uuid)
return service_id_obj
def SendOutput(self, request, context):
# SEND CONFIDENCE TO MITIGATION SERVER
print("Server received mitigation values...", request.confidence, flush=True)
last_value = request.confidence
last_tag = request.tag
ip_o = request.ip_o
ip_d = request.ip_d
port_o = request.port_o
port_d = request.port_d
service_id = self.GenerateServiceId(request.service_id)
config_rule = self.GetConfigRule(ip_o, ip_d, port_o, port_d)
service = GetService(service_id)
print(service)
#service.config_rules.append(config_rule)
#UpdateService(service)
# RETURN OK TO THE CALLER
return Empty(
message=f"OK, received values: {last_tag} with confidence {last_value}."
)
def SetDevice(self, device):
with grpc.insecure_channel(CONTEXT_CHANNEL) as channel:
stub = ContextServiceStub(channel)
return stub.SetDevice(device)
def SetLink(self, link):
with grpc.insecure_channel(CONTEXT_CHANNEL) as channel:
stub = ContextServiceStub(channel)
return stub.SetLink(link)
def SetTopology(self, link):
with grpc.insecure_channel(CONTEXT_CHANNEL) as channel:
stub = ContextServiceStub(channel)
return stub.SetTopology(link)
def GetService(self, service_id):
with grpc.insecure_channel(CONTEXT_CHANNEL) as channel:
stub = ContextServiceStub(channel)
return stub.GetService(service_id)
def SetContext(self, context):
with grpc.insecure_channel(CONTEXT_CHANNEL) as channel:
stub = ContextServiceStub(channel)
return stub.SetContext(context)
def UpdateService(self, service):
with grpc.insecure_channel(SERVICE_CHANNEL) as channel:
stub = ServiceServiceStub(channel)
stub.UpdateService(service)
def CreateService(self, service):
with grpc.insecure_channel(SERVICE_CHANNEL) as channel:
stub = ServiceServiceStub(channel)
stub.CreateService(service)
def GetMitigation(self, request, context):
# GET OR PERFORM MITIGATION STRATEGY
logging.debug("")
print("Returing mitigation strategy...")
k = self.last_value * 2
return Empty(
message=f"Mitigation with double confidence = {k}"
)