diff options
author | Tibor Král <tibor.kral@pantheon.tech> | 2018-11-14 18:20:02 +0100 |
---|---|---|
committer | Tibor Král <tibor.kral@pantheon.tech> | 2019-01-16 10:07:28 +0100 |
commit | 26589d440f332fe52238fa258d7d7b58df43eee5 (patch) | |
tree | dd3eaa8cf5cc3bd9fcfbff1239227c784ce935e7 | |
parent | 8ad4f38beb1350d1cd62d11a9a15ac78ee0623f9 (diff) |
HC2VPP-87: Expose IPSEC management
Change-Id: Ib13a2cdba5a0902581c455de67cc0ee64d20598d
Signed-off-by: Tibor Král <tibor.kral@pantheon.tech>
41 files changed, 7301 insertions, 0 deletions
diff --git a/ipsec/Ipsec_postman_collection.json b/ipsec/Ipsec_postman_collection.json new file mode 100644 index 000000000..cbe0759d3 --- /dev/null +++ b/ipsec/Ipsec_postman_collection.json @@ -0,0 +1,486 @@ +{ + "info": { + "_postman_id": "d17abd36-ad9a-4b5f-bb10-fe09c412dbe6", + "name": "IPsec", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Add Sad Entry - ESP", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"sad-entries\": [\n\t\t{\n\t\t\t\"sa-id\":10,\n\t\t\t\"spi\": 1001,\n\t\t\t\"anti-replay-window\": 88,\n\t\t\t\"direction\": \"outbound\",\n\t\t\t\"security-protocol\": \"esp\",\n\t\t\t\"esp\": {\n\t\t\t\t\"authentication\" : {\n\t\t\t\t\t\"hmac-sha1-96\" : {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"encryption\" : {\n\t\t\t\t\t\"aes-128-cbc\": {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"source-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.3\"\n\t\t\t},\n\t\t\t\"destination-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.2\"\n\t\t\t}\n\t\t}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1001/outbound", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ipsec", + "sad", + "sad-entries", + "1001", + "outbound" + ] + } + }, + "response": [] + }, + { + "name": "Add Sad Entry - ESP inbound", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"sad-entries\": [\n\t\t{\n\t\t\t\"sa-id\":20,\n\t\t\t\"spi\": 1002,\n\t\t\t\"anti-replay-window\": 88,\n\t\t\t\"direction\": \"inbound\",\n\t\t\t\"security-protocol\": \"esp\",\n\t\t\t\"esp\": {\n\t\t\t\t\"authentication\" : {\n\t\t\t\t\t\"hmac-sha1-96\" : {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"encryption\" : {\n\t\t\t\t\t\"aes-128-cbc\": {\n\t\t\t\t\t\t\"key-str\" : \"0123456789012345\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"source-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.3\"\n\t\t\t},\n\t\t\t\"destination-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.2\"\n\t\t\t}\n\t\t}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1002/inbound", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ipsec", + "sad", + "sad-entries", + "1002", + "inbound" + ] + } + }, + "response": [] + }, + { + "name": "Add Sad Entry- AH", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"sad-entries\": [\n\t\t{\n\t\t\t\"sa-id\":50,\n\t\t\t\"spi\": 1005,\n\t\t\t\"anti-replay-window\": 55,\n\t\t\t\"direction\": \"inbound\",\n\t\t\t\"security-protocol\": \"ah\",\n\t\t\t\"ah\": {\n\t\t\t\t\"hmac-sha1-96\" : {\n\t\t\t\t\t\"key-str\" : \"0123456789055555\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"source-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.5\"\n\t\t\t},\n\t\t\t\"destination-address\": {\n\t\t\t\t\"ipv4-address\": \"192.168.100.55\"\n\t\t\t}\n\t\t}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1005/inbound", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ipsec", + "sad", + "sad-entries", + "1005", + "inbound" + ] + } + }, + "response": [] + }, + { + "name": "Add SPD", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"spd\": [\n\t\t{\n\t\t\t\"spd-id\":10,\n\t\t\t\"spd-entries\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\":\"testEntry1\",\n\t\t\t\t\t\"priority\":10,\n\t\t\t\t\t\"direction\":\"inbound\",\n\t\t\t\t\t\"operation\":\"bypass\",\n\t\t\t\t\t\"laddr-start\":\"192.168.4.4\",\n\t\t\t\t\t\"laddr-stop\":\"192.168.4.4\",\n\t\t\t\t\t\"raddr-start\":\"192.168.3.3\",\n\t\t\t\t\t\"raddr-stop\":\"192.168.3.3\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"name\":\"testEntry2\",\n\t\t\t\t\t\"priority\":100,\n\t\t\t\t\t\"direction\":\"outbound\",\n\t\t\t\t\t\"operation\":\"discard\",\n\t\t\t\t\t\"laddr-start\":\"192.168.5.5\",\n\t\t\t\t\t\"laddr-stop\":\"192.168.5.5\",\n\t\t\t\t\t\"raddr-start\":\"192.168.6.6\",\n\t\t\t\t\t\"raddr-stop\":\"192.168.6.6\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/spd/10", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ipsec", + "spd", + "10" + ] + } + }, + "response": [] + }, + { + "name": "Add Ikev2 profile SHARED-KEY", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"policy\": [\n\t\t{\n\t\t\t\"name\":\"testPolicy\",\n\t\t\t\"lifetime\": 0,\n\t\t\t\"connection-type\":\"both\",\n\t\t\t\"description\": \"policy profile named testPolicy\",\n\t\t\t\"authentication\": {\n\t\t\t\t\"preshared-key\":\"true\"\n\t\t\t},\n\t\t\t\"pre-shared-key\":\"Vpp0123456789123\",\n\t\t\t\"traffic-selectors\": [\n\t\t\t\t{\n\t\t\t\t\t\"ts-name\":\"ts1\",\n\t\t\t\t\t\"protocol\":0,\n\t\t\t\t\t\"local-address-low\":\"192.168.124.0\",\n\t\t\t\t\t\"local-address-high\":\"192.168.124.255\",\n\t\t\t\t\t\"local-port-low\":0,\n\t\t\t\t\t\"local-port-high\":65535\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicy", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ikev2", + "policy", + "testPolicy" + ] + } + }, + "response": [] + }, + { + "name": "Add Ikev2 profile RSA", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"policy\": [\n\t\t{\n\t\t\t\"name\":\"testPolicyRsa\",\n\t\t\t\"lifetime\": 0,\n\t\t\t\"connection-type\":\"both\",\n\t\t\t\"description\": \"policy profile named testPolicyRsa\",\n\t\t\t\"authentication\": {\n\t\t\t\t\"rsa-signature\":\"true\"\n\t\t\t},\n\t\t\t\"certificate\":\"/home/localadmin/certs/server-cert.pem\"\n\t\t}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicyRsa", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ikev2", + "policy", + "testPolicyRsa" + ] + } + }, + "response": [] + }, + { + "name": "Add Ikev2 profile local ID FQDN", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"identity\": {\n\t\t\"local\": {\n\t\t\t\"fqdn-string\":\"vpp.home\"\n\t\t}\n\t}\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicy/identity", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ikev2", + "policy", + "testPolicy", + "identity" + ] + } + }, + "response": [] + }, + { + "name": "Add Ikev2 profile remote ID IPv4", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"identity\": {\n\t\t\"remote\": {\n\t\t\t\"ipv4-address\":\"192.168.123.20\"\n\t\t}\n\t}\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/policy/testPolicy/identity", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ikev2", + "policy", + "testPolicy", + "identity" + ] + } + }, + "response": [] + }, + { + "name": "Show SAD 1001 outbound - config", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/sad/sad-entries/1001/outbound", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ipsec", + "sad", + "sad-entries", + "1001", + "outbound" + ] + } + }, + "response": [] + }, + { + "name": "Show IPSEC - oper", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/operational/hc2vpp-ietf-ipsec:ipsec-state/", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "operational", + "hc2vpp-ietf-ipsec:ipsec-state", + "" + ] + } + }, + "response": [] + }, + { + "name": "Show IPSEC - oper SPD", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/operational/hc2vpp-ietf-ipsec:ipsec-state/spd/10/spd-interfaces/", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "operational", + "hc2vpp-ietf-ipsec:ipsec-state", + "spd", + "10", + "spd-interfaces", + "" + ] + } + }, + "response": [] + }, + { + "name": "Show IPSEC Config", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ipsec/", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ipsec", + "" + ] + } + }, + "response": [] + }, + { + "name": "Show Ikev2", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"relay\": [\n\t\t{\n\t\t\t\"address-family\": \"vpp-fib-table-management:ipv4\",\n\t\t\t\"rx-vrf-id\": 0,\n\t\t\t\"server-address\": \"1.2.3.4\",\n\t\t\t\"gateway-address\": \"5.6.7.8\"}\n\t]\n}\n" + }, + "url": { + "raw": "http://localhost:8183/restconf/config/hc2vpp-ietf-ipsec:ikev2/", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8183", + "path": [ + "restconf", + "config", + "hc2vpp-ietf-ipsec:ikev2", + "" + ] + } + }, + "response": [] + } + ] +}
\ No newline at end of file diff --git a/ipsec/ipsec-api/pom.xml b/ipsec/ipsec-api/pom.xml new file mode 100644 index 000000000..169f55cf5 --- /dev/null +++ b/ipsec/ipsec-api/pom.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2019 PANTHEON.tech. + + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <parent> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>api-parent</artifactId> + <version>1.19.01-SNAPSHOT</version> + <relativePath>../../common/api-parent</relativePath> + </parent> + + <modelVersion>4.0.0</modelVersion> + <groupId>io.fd.hc2vpp.ipsec</groupId> + <artifactId>ipsec-api</artifactId> + <name>${project.artifactId}</name> + <version>1.19.01-SNAPSHOT</version> + <packaging>bundle</packaging> + + <properties> + <naming.context.version>1.19.01-SNAPSHOT</naming.context.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-yang-types-20130715</artifactId> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-inet-types-2013-07-15</artifactId> + </dependency> + <dependency> + <groupId>io.fd.hc2vpp.v3po</groupId> + <artifactId>v3po-api</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> diff --git a/ipsec/ipsec-api/src/main/yang/hc2vpp-ietf-ipsec@2018-12-14.yang b/ipsec/ipsec-api/src/main/yang/hc2vpp-ietf-ipsec@2018-12-14.yang new file mode 100644 index 000000000..6df2c6588 --- /dev/null +++ b/ipsec/ipsec-api/src/main/yang/hc2vpp-ietf-ipsec@2018-12-14.yang @@ -0,0 +1,3679 @@ +module hc2vpp-ietf-ipsec { + namespace "urn:ietf:params:xml:ns:yang:ietf-ipsec"; + prefix "eipsec"; + + import ietf-inet-types { + prefix inet; + } + + import ietf-yang-types { + prefix yang; + } + + organization "Ericsson AB. + Huawei Technologies India Pvt Ltd."; + + contact "Web: <http://www.ericsson.com>"; + + description + "This YANG module defines the configuration and operational + state data for Internet Protocol Security (IPSec) on + IETF draft. + Copyright (c) 2016 Ericsson AB. + All rights reserved."; + + revision 2018-12-14 { + description + "HC2VPP modifications for use case with VPP. + See https://jira.fd.io/browse/HC2VPP-399"; + } + + revision 2016-03-09 { + description + "Third revision. + Fix YANG compiling error because it used internal + data model econtext and should be removed in the + draft. + Fix warnings. + Run validation on + http://www.netconfcentral.org/yangdumpresults"; + reference + "Update since second revision."; + } + revision 2015-09-13 { + description + "Second revision."; + reference + "updates since initial revision. + combining: + draft-tran-ipecme-yang-ipsec-00. + draft-wang-ipsecme-ike-yang-00. + draft-wang-ipsecme-ipsec-yang-00."; + } + revision 2015-05-14 { + description + "Initial revision."; + reference + "May 14, 2015 draft-tran-ipecme-yang-ipsec-00. + May 22, 2015 draft-wang-ipsecme-ike-yang-00. + June 15, 2015 draft-wang-ipsecme-ipsec-yang-00."; + } + /*--------------------*/ + /* Feature */ + /*--------------------*/ + + feature ikev1 { + description + "Feature IKEv1"; + } + + feature ike-proposal-state { + description + "IKEv2 Proposal Operational State"; + } + + feature ike-policy-state { + description + "IKEv1 Policy Operational State"; + } + + feature ikev1-state { + description + "IKEv1 Operational State"; + } + + feature ike-reauth-failure { + description + "IKEv1 Reauthorization Failure"; + } + + feature ike-rekey-failure { + description + "IKEv1 Rekey Failure"; + } + + + feature ikev2 { + description + "Feature IKEv2"; + + } + + feature ikev2-global { + description + "Feature IKEv2 Global Parameters"; + + } + + feature ikev2-peer { + description + "Feature IKEv2 Peer"; + + } + + feature ikev2-proposal { + description + "Feature IKEv2 Proposal"; + + } + + feature ikev2-policy { + description + "Feature IKEv2 Policy"; + + } + + feature ikev2-proposal-state { + description + "IKEv2 Proposal Operational State"; + } + + feature ikev2-state { + description + "IKEv2 Operational State"; + } + + feature ipsec { + description + "Feature IPsec"; + + } + + feature ipsec-acl { + description + "Feature IPsec ACL"; + + } + feature ipsec-sad { + description + "Feature IPsec SAD"; + + } + + feature ipsec-proposal { + description + "Feature IPsec Proposal"; + + } + + feature ipsec-spd { + description + "Feature IPsec SPD"; + + } + + feature ipsec-policy-state { + description + "IPsec Policy Operational State"; + } + + feature ipsec-proposal-state { + description + "IPsec Proposal Operational State"; + } + + feature ipsec-alarms-state { + description + "IPsec Alarm State Operational State"; + } + + feature ipsec-sa-ah-state { + description + "IPsec SA AH Operational State"; + } + + feature ipsec-sa-state { + description + "IPsec SA Operational State"; + } + + feature ipsec-tunnel { + description + "IPsec Tunnel"; + } + + feature ipsec-local-address-range { + description + "IPsec Local Address Range"; + } + + feature ipsec-remote-address-range { + description + "IPsec Remote Address Range"; + } + + feature ipsec-next-protocol-range { + description + "IPsec Next Protocol Range"; + } + + feature ipsec-local-port-range { + description + "IPsec Local Port Range"; + } + + feature ipsec-remote-port-range { + description + "IPsec Remote Port Range"; + } + + feature ipsec-ah-authentication { + description + "IPsec AH Authentication"; + } + + feature ipsec-esp-integrity { + description + "IPsec ESP Integrity"; + } + + feature ipsec-esp-encrypt { + description + "IPsec ESP encryption"; + } + + feature ipsec-stat { + description + "IPsec Stats"; + } + + feature ipsec-state { + description + "IPsec Operational State"; + } + + feature ipsec-rekey-failure { + description + "IPsec Rekey Failure"; + } + + feature ipsec-redundancy { + description + "IPsec Redundancy State"; + } + + feature sad { + description + "Security Association (SA) Database"; + } + + feature spd { + description + "Security Policy Database"; + } + + feature ipsec-global-stats { + description + "IPsec Global Stats"; + } + + feature clear-ipsec-group { + description + "Clear IPsec group"; + } + + feature clear-ike-group { + description + "Clear IKE group"; + } + + feature clear-ikev2-group { + description + "Clear IKEv2 group"; + } + + feature reset-ipv4 { + description + "Reset IPv4"; + } + + feature reset-ipv6 { + description + "Reset IPv6"; + } + + feature reset-global { + description + "Reset Global"; + } + + feature peer-authentication-failure { + description + "Peer Authentication Failure"; + } + /*--------------------*/ + /* Typedefs */ + /*--------------------*/ + + typedef authentication-method-t { + type enumeration { + enum psk { + value 0; + description + "Pre-Sharing Keys."; + } + enum certificate { + value 1; + description + "Certificate."; + } + } + description + "Available authentication methods."; + } + + /* IKEv2 Exchange Types (ET) */ + typedef ikev2-exchange-type-t { + type enumeration { + enum ikev2-et-ike-sa-init { + value 34; + description + "ikev2-et-ike-sa-init - RFC 7296."; + } + enum ikev2-et-ike-auth { + value 35; + description + "ikev2-et-ike-auth - RFC 7296."; + } + enum ikev2-et-create-child-sa { + value 36; + description + "ikev2-et-create-child-sa - RFC 7296."; + } + enum ikev2-et-informational { + value 37; + description + "ikev2-et-informational - RFC 7296."; + } + enum ikev2-et-ike-session-resume { + value 38; + description + "ikev2-et-ike-session-resume - RFC 7296."; + } + enum ikev2-et-gsa-auth { + value 39; + description + "ikev2-et-gsa-auth - RFC 7296."; + } + enum ikev2-et-gsa-registration { + value 40; + description + "ikev2-et-gsa-registration - RFC 7296."; + } + enum ikev2-et-gsa-rekey { + value 41; + description + "ikev2-et-gsa-rekey - RFC 7296."; + } + } + description + "IKEv2 Exchange Types (ET)."; + } + + /* Transform Type Values (TTV), RFC 7296 */ + typedef transform-type-value-t { + type enumeration { + enum ttv-reserved-0 { + value 0; + description + "ttv-reserved-0 - Transform Type Value Reserved "+ + "(RFC 7296)."; + } + enum ttv-encr { + value 1; + description + "ttv-encr - Transform Type Value 1, + Encryption Algorithm "+ + "(ENCR) used in IKE and ESP."; + } + enum ttv-prf { + value 2; + description + "ttv-prf - Transform Type Value 2, "+ + "Pseudo-Random Function(PRF) used in IKE."; + } + enum ttv-integ { + value 3; + description + "ttv-integ - Transform Type Value 3, Integrity Algorithm"+ + " (INTEG) used in IKE, AH, optional ESP."; + } + enum ttv-dh { + value 4; + description + "ttv-dh - Transform Type Value 4, Diffie-Hellman (DH) "+ + "used in IKE, optional AH and ESP."; + } + enum ttv-esn { + value 5; + description + "ttv-esn - Transform Type Value 5, Extended Sequence "+ + "Numbers (ESN) used in AH and ESP."; + } + } + description + "Transform Type Values (RFC 7296)."; + } + + /* IKEv2 Transform Attribute Types (TAT) */ + typedef ikev2-transform-attribute-type-t { + type enumeration { + enum ikev2-tat-reserved-0 { + value 0; + description + "ikev2-tat-reserved-0 - IKEv2 Transform Attribute "+ + "Type Reserved-0 (RFC 7296)."; + } + enum ikev2-tat-reserved-1 { + value 1; + description + "ikev2-tat-reserved-1 - IKEv2 Transform Attribute "+ + "Type Reserved-1 (RFC 7296)."; + } + enum ikev2-tat-reserved-13 { + value 13; + description + "ikev2-tat-reserved-13 - IKEv2 Transform Attribute "+ + "Type Reserved-13 (RFC 7296)."; + } + enum ikev2-tat-key-length { + value 41; + description + "ikev2-tat-key-length - IKEv2 Transform Attribute "+ + "Type KEY LENGTH (in bits) (RFC 7296)."; + } + } + description + "IKEv2 Transform Attribute Types (TAT) (RFC 7296)."; + } + + /* Transform Type 1 (Encryption Algorithm Transform IDs) */ + typedef ike-encryption-algorithm-t { + type enumeration { + enum encr-reserved-0 { + value 0; + description + "encr-reserved-0 --> RFC_5996."; + } + enum encr-des-iv4 { + value 1; + description + "encr-des-iv4 --> RFC_5996."; + } + enum encr-des { + value 2; + description + "encr-des --> RFC_5996."; + } + enum encr-3des { + value 3; + description + "encr-3des --> RFC_5996."; + } + enum encr-rc5 { + value 4; + description + "encr-rc5 --> RFC_5996."; + } + enum encr-idea { + value 5; + description + "encr-idea --> RFC_5996."; + } + enum encr-cast { + value 6; + description + "encr-cast --> RFC_5996."; + } + enum encr-blowfish { + value 7; + description + "encr-blowfish --> RFC_5996."; + } + enum encr-3idea { + value 8; + description + "encr-3idea --> RFC_5996."; + } + enum encr-des-iv32 { + value 9; + description + "encr-des-iv32 --> RFC_5996."; + } + enum encr-reserved-10 { + value 10; + description + "encr-reserved-10 --> RFC_5996."; + } + enum encr-null { + value 11; + description + "encr-null --> RFC_5996."; + } + enum encr-aes-cbc { + value 12; + description + "encr-aes-cbc --> RFC_5996."; + } + enum encr-aes-ctr { + value 13; + description + "encr-aes-ctr --> RFC_5996."; + } + enum encr-aes-ccm-8 { + value 14; + description + "encr-aes-ccm-8 --> RFC_5996."; + } + enum encr-aes-ccm-12 { + value 15; + description + "encr-aes-ccm-12 --> RFC_5996."; + } + enum encr-aes-ccm-16 { + value 16; + description + "encr-aes-ccm-16 --> RFC_5996."; + } + enum encr-reserved-17 { + value 17; + description + "encr-reserved-17 --> RFC_5996."; + } + enum encr-aes-gcm-8-icv { + value 18; + description + "encr-aes-gcm-8-icv --> RFC_5996."; + } + enum encr-aes-gcm-12-icv { + value 19; + description + "encr-aes-gcm-12-icv --> RFC_5996."; + } + enum encr-aes-gcm-16-icv { + value 20; + description + "encr-aes-gcm-16-icv--> RFC_5996."; + } + enum encr-null-auth-aes-gmac { + value 21; + description + "encr-null-auth-aes-gmac --> RFC_5996."; + } + enum encr-ieee-p1619-xts-aes { + value 22; + description + "encr-ieee-p1619-xts-aes --> Reserved for "+ + "IEEE P1619 XTS-AES."; + } + enum encr-camellia-cbc { + value 23; + description + "encr-camellia-cbc --> RFC_5996."; + } + enum encr-camellia-ctr { + value 24; + description + "encr-camellia-ctr --> RFC_5996."; + } + enum encr-camellia-ccm-8-icv { + value 25; + description + "encr-camellia-ccm-8-icv --> RFC_5996."; + } + enum encr-camellia-ccm-12-icv { + value 26; + description + "encr-camellia-ccm-12-icv --> RFC_5996."; + } + enum encr-camellia-ccm-16-icv { + value 27; + description + "encr-camellia-ccm-16-icv --> RFC_5996."; + } + enum encr-aes-cbc-128 { + value 1024; + description + "encr-aes-cbc-128 --> RFC_5996."; + } + enum encr-aes-cbc-192 { + value 1025; + description + "encr-aes-cbc-192 --> RFC_5996."; + } + enum encr-aes-cbc-256 { + value 1026; + description + "encr-aes-cbc-256 --> RFC_5996."; + } + enum encr-blowfish-128 { + value 1027; + description + "encr-blowfish-128 --> RFC_5996."; + } + enum encr-blowfish-192 { + value 1028; + description + "encr-blowfish-192 --> RFC_5996."; + } + enum encr-blowfish-256 { + value 1029; + description + "encr-blowfish-256 --> RFC_5996."; + } + enum encr-blowfish-448 { + value 1030; + description + "encr-blowfish-448 --> RFC_5996."; + } + enum encr-camellia-128 { + value 1031; + description + "encr-camellia-128 --> RFC_5996."; + } + enum encr-camellia-192 { + value 1032; + description + "encr-camellia-192 --> RFC_5996."; + } + enum encr-camellia-256 { + value 1033; + description + "encr-camellia-256 --> RFC_5996."; + } + } + description + "Transform Type 1 - Internet Key Exchange (IKE) "+ + "encryption algorithms."; + } + + /* Transform Type 2 (Pseudo-Random Function PRF) */ + typedef pseudo-random-function-t { + type enumeration { + enum prf-reserved-0 { + value 0; + description + "prf-reserved-0 --> RFC_2104."; + } + enum prf-hmac-md5 { + value 1; + description + "prf-hmac-md5 --> RFC_2104."; + } + enum prf-hmac-sha1 { + value 2; + description + "prf-hmac-sha1 --> RFC2104."; + } + enum prf-hmac-tiger { + value 3; + description + "prf-hmac-tiger --> RFC2104."; + } + enum prf-aes128-xcbc { + value 4; + description + "prf-aes128-xcbc --> RFC_4434."; + } + enum prf-hmac-sha2-256 { + value 5; + description + "prf-hmac-sha2-256 --> RFC_4434."; + } + enum prf-hmac-sha2-384 { + value 6; + description + "prf-hmac-sha2-384 --> RFC_4434."; + } + enum prf-hmac-sha2-512 { + value 7; + description + "prf-hmac-sha2-512 --> RFC_4434."; + } + enum prf-aes128-cmac { + value 8; + description + "prf-aes128-cmac --> RFC_4615."; + } + } + description + "Available Pseudo-Random Functions (PRF)."; + } + + /* Transform Type 3 (Integrity Algorithm) */ + typedef ike-integrity-algorithm-t { + type enumeration { + enum auth-none { + value 0; + description + "auth-none --> RFC_5996."; + } + enum auth-hmac-md5-96 { + value 1; + description + "auth-hmac-md5-96 --> RFC_5996."; + } + enum auth-hmac-sha1-96 { + value 2; + description + "auth-hmac-sha1-96 --> RFC_5996."; + } + enum auth-des-mac { + value 3; + description + "auth-des-mac --> RFC_5996."; + } + enum auth-kpdk-md5 { + value 4; + description + "auth-kpdk-md5 --> RFC_5996."; + } + enum auth-aes-xcbc-96 { + value 5; + description + "auth-aes-xcbc-96 --> RFC_5996."; + } + enum auth-hmac-md5-128 { + value 6; + description + "auth-hmac-md5-128 --> RFC_5996."; + } + enum auth-hmac-sha1-160 { + value 7; + description + "auth-hmac-sha1-160 --> RFC_5996."; + } + enum auth-aes-cmac-96 { + value 8; + description + "auth-aes-cmac-96 --> RFC_5996."; + } + enum auth-aes-128-gmac { + value 9; + description + "auth-aes-128-gmac --> RFC_5996."; + } + enum auth-aes-192-gmac { + value 10; + description + "auth-aes-192-gmac --> RFC_5996."; + } + enum auth-aes-256-gmac { + value 11; + description + "auth-aes-256-gmac --> RFC_5996."; + } + enum auth-hmac-sha2-256-128 { + value 12; + description + "auth-hmac-sha2-256-128 --> RFC_5996."; + } + enum auth-hmac-sha2-384-192 { + value 13; + description + "auth-hmac-sha2-384-192 --> RFC_5996."; + } + enum auth-hmac-sha2-512-256 { + value 14; + description + "auth-hmac-sha2-512-256 --> RFC_5996."; + } + enum auth-hmac-sha2-256-96 { + value 1024; + description + "auth-hmac-sha2-256-96."; + } + } + description + "Transform Type 3 - Internet Key Exchange (IKE) "+ + "Integrity Algorithms."; + } + + /* Transform Type 4 (Diffie-Hellman Group) */ + typedef diffie-hellman-group-t { + type enumeration { + enum group-none { + value 0; + description + "group-none --> RFC_5996."; + } + enum modp-768-group-1 { + value 1; + description + "modp-768-group-1 --> RFC_5996."; + } + enum modp-1024-group-2 { + value 2; + description + "modp-1024-group-2 --> RFC_5996."; + } + enum modp-1536-group-5 { + value 5; + description + "modp-1536-group-5 --> RFC_3526."; + } + enum modp-2048-group-14 { + value 14; + description + "modp-2048-group-14 --> RFC_3526."; + } + enum modp-3072-group-15 { + value 15; + description + "modp-3072-group-15 --> RFC_3526."; + } + enum modp-4096-group-16 { + value 16; + description + "modp-4096-group-16 --> RFC_3526."; + } + enum modp-6144-group-17 { + value 17; + description + "modp-6144-group-17 --> RFC_3526."; + } + enum modp-8192-group-18 { + value 18; + description + "modp-8192-group-18 --> RFC_3526."; + } + enum recp-256-group-19 { + value 19; + description + "recp-256-group-19 --> RFC_6989. 256-bit"+ + " Random ECP Group."; + } + enum recp-384-group-20 { + value 20; + description + "recp-384-group-20 --> RFC_6989. 384-bit"+ + " Random ECP Group."; + } + enum recp-521-group-21 { + value 21; + description + "recp-521-group-21 --> RFC_6989. 521-bit"+ + " Random ECP Group."; + } + enum modp-1024-160-pos-group-22 { + value 22; + description + "modp-1024-160-pos-group-22 --> RFC_6989."+ + " 1024-bit MODP Group with"+ + " 160-bit Prime Order Subgroup (POS)."; + } + enum modp-2048-224-pos-group-23 { + value 23; + description + "modp-2048-224-pos-group-23 --> RFC_6989."+ + " 2048-bit MODP Group with"+ + " 224-bit Prime Order Subgroup (POS)."; + } + enum modp-2048-256-pos-group-24 { + value 24; + description + "modp-2048-256-pos-group-24 --> RFC_6989."+ + " 2048-bit MODP Group with"+ + " 256-bit Prime Order Subgroup (POS)."; + } + enum recp-192-group-25 { + value 25; + description + "recp-192-group-25 --> RFC_6989."+ + " 192-bit Random ECP Group."; + } + enum recp-224-group-26 { + value 26; + description + "recp-224-group-26 --> RFC_6989."+ + " 224-bit Random ECP Group."; + } + } + description + "Diffie-Hellman Groups (RFC 5996)."; + } + + + /* Transform Type 5 (Extended Sequence Numbers + Transform ESN IDs) */ + typedef extended-sequence-number-t { + type enumeration { + enum esn-none { + value 0; + description + "esn-none - Extended Sequence Number None --> RFC_7296."; + } + enum esn-1 { + value 1; + description + "esn-1 - Extended Sequence Number --> RFC_7296."; + } + } + description + "Extended Sequence Number (RFC 7296)."; + } + + + typedef connection-type-t { + type enumeration { + enum initiator-only { + value 0; + description + "initiator-only: ME will act as initiator for"+ + " bringing up IKEv2"+ + " session with its IKE peer."; + } + enum responder-only { + value 1; + description + "responder-only: ME will act as responder for"+ + " bringing up IKEv2"+ + " session with its IKE peer."; + } + enum both { + value 2; + description + "both: ME can act as initiator or responder."; + } + } + description + "Connection type for IKE session."; + } + + typedef transport-protocol-name-t { + type enumeration { + enum tcp { + value 1; + description + "Transmission Control Protocol (TCP) Transport Protocol."; + } + enum udp { + value 2; + description + "User Datagram Protocol (UDP) Transport Protocol"; + } + enum sctp { + value 3; + description + "Stream Control Transmission Protocol (SCTP) Transport "+ + "Protocol"; + } + enum icmp { + value 4; + description + "Internet Control Message Protocol (ICMP) Transport "+ + "Protocol"; + } + } + description + "Enumeration of well known transport protocols."; + } + + typedef preshared-key-t { + type string; + description + "Derived string used as Pre-Shared Key."; + } + + typedef pad-type-t { + type enumeration { + enum dns-name { + value 1; + description + "DNS name (specific or partial)"; + } + enum distinguished-name { + value 2; + description + "Distinguished Name (complete or sub-tree constrained)"; + } + enum rfc-822 { + value 3; + description + "RFC 822 email address (complete or partially qualified)"; + } + enum ipv4-range { + value 4; + description + "IPv4 Address Range"; + } + enum ipv6-range { + value 5; + description + "IPv6 Address Range"; + } + enum key-id { + value 6; + description + "Key ID (exact match only)"; + } + } + description + "PAD Type"; + } + + + /*-------------------------------------------------- */ + /* draft-wang-ipsecme-ipsec-yang-00: ietf-ipsec-type */ + /*-------------------------------------------------- */ + typedef ipsec-mode { + type enumeration { + enum "transport" { + description + "Transport mode"; + } + enum "tunnel" { + description + "Tunnel mode"; + } + } + description + "type define of ipsec mode"; + } + + typedef ipsec-protocol { + type enumeration { + enum "ah" { + description + "AH Protocol"; + } + enum "esp" { + description + "ESP Protocol"; + } + } + description + "type define of ipsec security protocol"; + } + + typedef ipsec-spi { + type uint32 { + range "1..max"; + } + description + "SPI"; + } + + typedef ipsec-spd-name { + type enumeration { + enum id_rfc_822_addr { + description + "Fully qualified user name string."; + } + enum id_fqdn { + description + "Fully qualified DNS name."; + } + enum id_der_asn1_dn { + description + "X.500 distinguished name."; + } + enum id_key { + description + "IKEv2 Key ID."; + } + } + description + "IPsec SPD name type"; + } + + typedef ipsec-traffic-direction { + type enumeration { + enum inbound { + description + "Inbound traffic"; + } + enum outbound { + description + "Outbound traffic"; + } + } + description + "IPsec traffic direction"; + } + + typedef ipsec-spd-operation { + type enumeration { + enum protect { + description + "PROTECT the traffic with IPsec"; + } + enum bypass { + description + "BYPASS the traffic"; + } + enum discard { + description + "DISCARD the traffic"; + } + } + description + "The operation when traffic matches IPsec security policy"; + } + + + /*---------------------------------------------------- */ + /* draft-wang-ipsecme-ipsec-yang-00: ietf-ipsec-crypto */ + /*---------------------------------------------------- */ + typedef ipsec-authentication-algorithm { + type enumeration { + enum "null" { + value 0; + description + "null"; + } + enum "md5" { + value 1; + description + "MD5 authentication algorithm"; + } + enum "sha1" { + value 2; + description + "SHA1 authentication algorithm"; + } + enum "sha2-256" { + value 3; + description + "SHA2-256 authentication algorithm"; + } + enum "sha2-384" { + value 4; + description + "SHA2-384 authentication algorithm"; + } + enum "sha2-512" { + value 5; + description + "SHA2-512 authentication algorithm"; + } + } + description + "typedef for ipsec authentication algorithm"; + } + + typedef ipsec-encryption-algorithm { + type enumeration { + enum "null" { + description + "null"; + } + enum "des" { + description + "DES encryption algorithm"; + } + enum "3des" { + description + "3DES encryption algorithm"; + } + enum "aes-128" { + description + "AES-128 encryption algorithm"; + } + enum "aes-192" { + description + "AES-192 encryption algorithm"; + } + enum "aes-256" { + description + "AES-256 encryption algorithm"; + } + } + description + "typedef for ipsec encryption algorithm"; + } + + /*-------------------------------------------------- */ + /* draft-wang-ipsecme-ike-yang-00: ietf-ipsec-type */ + /*-------------------------------------------------- */ + typedef ike-integrity-algorithm { + type enumeration { + enum "hmac-md5-96" { + description + "HMAC-MD5-96 Integrity Algorithm"; + } + enum "hmac-sha1-96" { + description + "HMAC-SHA1-96 Integrity Algorithm"; + } + enum "hmac-sha2-256" { + description + "HMAC-SHA2-256 Integrity Algorithm"; + } + enum "hmac-sha2-384" { + description + "HMAC-SHA2-384 Integrity Algorithm"; + } + enum "hmac-sha2-512" { + description + "HMAC-SHA2-512 Integrity Algorithm"; + } + } + description + "typedef for ike integrity algorithm."; + } + + typedef ike-encryption-algorithm { + type enumeration { + enum "des-cbc" { + description + "DES-CBC Encryption algorithm"; + } + enum "3des-cbc" { + description + "3DES-CBC Encryption algorithm"; + } + enum "aes-cbc-128" { + description + "AES-CBC-128 Encryption algorithm"; + } + enum "aes-cbc-192" { + description + "AES-CBC-192 Encryption algorithm"; + } + enum "aes-cbc-256" { + description + "AES-CBC-256 Encryption algorithm"; + } + } + description + "typedef for ike encryption algorithm."; + } + + typedef ike-prf-algorithm { + type enumeration { + enum "hmac-md5-96" { + description + "HMAC-MD5-96 PRF Algorithm"; + } + enum "hmac-sha1-96" { + description + "HMAC-SHA1-96 PRF Algorithm"; + } + enum "hmac-sha2-256" { + description + "HMAC-SHA2-256 PRF Algorithm"; + } + enum "hmac-sha2-384" { + description + "HMAC-SHA2-384 PRF Algorithm"; + } + enum "hmac-sha2-512" { + description + "HMAC-SHA2-512 PRF Algorithm"; + } + } + description + "typedef for ike prf algorithm."; + } + + typedef ike-dh-group { + type enumeration { + enum "dh-group-none" { + description + "None Diffie-Hellman group"; + } + enum "dh-group-1" { + description + "768 bits Diffie-Hellman group"; + } + enum "dh-group-2" { + description + "1024 bits Diffie-Hellman group"; + } + enum "dh-group-5" { + description + "1536 bits Diffie-Hellman group"; + } + enum "dh-group-14" { + description + "2048 bits Diffie-Hellman group"; + } + } + description + "typedef for ike dh group"; + } + + + typedef ike-peer-name-ref { + type leafref { + path "/ikev2/ike-peer/ike-peer-entries/peer-name"; + } + description "reference to ike peer name"; + } + + typedef ike-proposal-number-ref { + type leafref { + path "/ikev2/proposal/name"; + } + description "reference to ike proposal name"; + } + + typedef ipsec-proposal-name-ref{ + type leafref { + path "/ipsec/proposal/ipsec-proposal/name"; + } + description "reference to ike proposal name"; + } + + typedef ike-auth-method { + type enumeration { + enum pre-share { + description + "Select pre-shared key message as the + authentication method"; + } + enum rsa-digital-signature { + description + "Select rsa digital signature as the + authentication method"; + } + enum dss-digital-signature { + description + "Select dss digital signature as the + authentication method"; + } + } + description "IKE authentication methods"; + } + + /*--------------------*/ + /* grouping */ + /*--------------------*/ + + /* The following groupings are used in both configuration data + and operational state data */ + grouping name-grouping { + description + "This grouping provides a leaf identifying the name."; + leaf name { + type string; + description + "Name of a identifying."; + } + leaf description { + type string; + description + "Specify the description."; + } + } + + grouping sequence-number-grouping { + description + "This grouping provides a leaf identifying + a sequence number."; + leaf sequence-number { + type uint32 { + range "1..4294967295"; + } + description + "Specify the sequence number."; + } + } + + grouping description-grouping { + description + "description for free use."; + leaf description { + type string; + description + "description for free use."; + } + } + + grouping traffic-selector-grouping { + description + "Traffic selector to be used for SA negotiation."; + leaf traffic-selector-id { + type string; + mandatory true; + description + "Traffic selector identifier."; + } + leaf protocol-name { + type transport-protocol-name-t; + description + "Specifies the protocol selector."; + } + leaf address-range { + type string; + mandatory true; + description + "Specifies the IPv4 or IPv6 address range."; + } + } + + + + grouping ike-general-proposal-grouping { + description + "IKE proposal."; + leaf name { + type string; + mandatory true; + description + "IKE Proposal identify."; + } + leaf description { + type string; + description + "Specify the description."; + } + + leaf dh-group { + type diffie-hellman-group-t; + mandatory true; + description + "Specifies a Diffie-Hellman group."; + } + container encryption { + description + "Specify IKE Proposal encryption configuration"; + leaf algorithm { + type ike-encryption-algorithm-t; + description + "Specifies an Encryption Algorithm."; + } + } + } + + grouping ike-proposal-grouping { + description + "Configure the IKE Proposal"; + uses ike-general-proposal-grouping; + + leaf lifetime { + type uint32; + mandatory true; + description + "Configure lifetime for IKE SAs + 0: for no timeout. + 300 .. 99999999: IKE SA lifetime in seconds."; + } + container authentication { + description + "Specify IKE Proposal authentication configuration"; + leaf algorithm { + type ike-integrity-algorithm-t; + description + "Specify the authentication algorithm"; + } + leaf preshared-key { + type empty; + description + "Use pre-shared key based authentication"; + } + leaf rsa-signature { + type empty; + description + "Use signature based authentication by using + PKI certificates"; + } + } + } + + grouping ikev2-proposal-grouping { + description + "Holds an IKEv2 transform proposal used during "+ + "IKEv2 SA negotiation. Multiple IKEv2 Transforms "+ + " can be proposed during an IKEv2 session initiation "+ + "in an ordered list."; + uses ike-general-proposal-grouping; + + leaf pseudo-random-function { + type pseudo-random-function-t; + mandatory true; + description + "Specifies Pseudo Random Function for IKEv2 key exchange"; + } + container authentication { + description + "Specify IKEv2 Proposal authentication configuration"; + leaf algorithm { + type ike-integrity-algorithm-t; + description + "Specify the authentication algorithm"; + } + } + } + + grouping ipsec-proposal-grouping { + description + "Configure IPSec Proposal"; + leaf name { + type string; + mandatory true; + description + "IPSec proposal identifier."; + } + leaf ah { + type ike-integrity-algorithm-t; + description + "Configure Authentication Header (AH)."; + } + container esp { + description + "Configure Encapsulating Security Payload (ESP)."; + leaf authentication { + type ike-integrity-algorithm-t; + description + "Configure ESP authentication"; + } + leaf encryption { + type ike-encryption-algorithm-t; + description + "Configure ESP encryption"; + } + } + leaf ip-comp{ + type empty; + description + "Enable IPSec proposal IP-COMP which uses the IP Payload "+ + "compression protocol to compress IP Security (IPSec) "+ + "packets before encryption"; + } + container lifetime { + description + "Configure lifetime for IPSEC SAs"; + leaf kbytes { + type uint32 { + range "128..2147483647"; + } + description + "Enter lifetime kbytes for IPSEC SAs"; + } + leaf seconds { + type uint32 { + range "300..99999999"; + } + description + "Enter lifetime seconds for IPSEC SAs + 0: lifetime of 0 for no timeout + 300..99999999: IPSec SA lifetime in seconds"; + } + } + } + + grouping identity-grouping { + description + "Identification type. It is an union identity, "+ + "possible type as follows: "+ + "a) ID_FQDN: A fully-qualified domain name string. "+ + " An example of a ID_FQDN is, example.com. "+ + " The string MUST not contain any terminators "+ + "(e.g., NULL, CR, etc.). "+ + "b) ID_RFC822_ADDR: A fully-qualified RFC822 email "+ + " address string, An example of a ID_RFC822_ADDR is, "+ + " jsmith@example.com. The string MUST not contain "+ + " any terminators. "+ + "c) ID_IPV4_ADDR: A single four (4) octet IPv4 address. "+ + "d) ID_IPV6_ADDR: A single sixteen (16) octet IPv6 address. "+ + "e) DN_X509: Distinguished name in the X.509 tradition."; + choice identity { + description + "Choice of identity."; + leaf ipv4-address { + type inet:ipv4-address; + description + "Specifies the identity as a single four (4) + octet IPv4 address. + An example is, 10.10.10.10. "; + } + leaf ipv6-address { + type inet:ipv6-address; + description + "Specifies the identity as a single sixteen (16) "+ + "octet IPv6 address. "+ + "An example is, "+ + "FF01::101, 2001:DB8:0:0:8:800:200C:417A ."; + } + leaf fqdn-string { + type inet:domain-name; + description + "Specifies the identity as a Fully-Qualified + Domain Name (FQDN) string. + An example is: example.com. + The string MUST not contain any terminators + (e.g., NULL, CR, etc.)."; + } + leaf rfc822-address-string { + type string; + description + "Specifies the identity as a fully-qualified RFC822 + email address string. + An example is, jsmith@example.com. + The string MUST not contain any terminators + (e.g., NULL, CR, etc.)."; + } + leaf dnX509 { + type string; + description + "Specifies the identity as a distinguished name + in the X.509 tradition."; + } + } + } /* grouping identity-grouping */ + + grouping ike-general-policy-profile-grouping { + description + "IKE policy."; + leaf connection-type { + type connection-type-t; + mandatory true; + description + "Specify the IKE connection type"; + } + leaf pre-shared-key { + type union { + type string { + length "16"; + } + /* TODO HC2VPP-399: Removed length from hex-string which caused + failures when building using ODL yangtools + */ + type yang:hex-string; + } + description + "Specify IKE pre-shared-key value"; + } + leaf validate-certificate-identity { + type empty; + description + "Validate Remote-ID payload against the + ID's available in the certificate"; + } + list seq { + key seq-id; + description + "list of sequence of policy."; + leaf seq-id { + type uint32 { + range "1..429496729"; + } + description + "Sequence Number"; + } + leaf proposal { + type leafref { + path "/eipsec:ikev1/eipsec:proposal"+ + "/eipsec:name"; + } + description + "IKE Proposal reference."; + } + } + container identity { + description + "Specify IKE identity value"; + container local { + description + "Specify the identity of the local IP Security (IPSec) + tunnel endpoint in an Internet Key Exchange (IKE) + policy to use when negotiating IKE request with a + remote peer."; + uses identity-grouping; + } + container remote { + description + "Specify the identity of the remote IP Security (IPSec) + tunnel endpoint in an + Internet Key Exchange (IKE) policy to use when + negotiating IKE request with a remote peer."; + uses identity-grouping; + } + } + } + + grouping ike-policy-mode-grouping { + description + "IKE Policy Mode"; + container mode { + description + "Specify IKE mode configuration"; + leaf aggressive { + type empty; + description + "Set IKE Aggressive mode"; + } + leaf main { + type empty; + description + "Set IKE Main mode"; + } + } + } + + grouping ike-policy-profile-grouping { + description + "Configure IKE policy"; + leaf name { + type string; + mandatory true; + description + "Specify an IKE policy name"; + } + uses ike-policy-mode-grouping; + uses ike-general-policy-profile-grouping; + } + + grouping ikev2-policy-profile-grouping { + description + "Common information for multiple IKE sessions + to be instantiated on a managed element.; + One or more Ikev2Session instances might refer + to this instance."; + leaf name { + type string; + mandatory true; + description + "Value component of the RDN."; + } + container authentication { + description + "Specify IKE Proposal authentication configuration"; + leaf preshared-key { + type empty; + description + "Use pre-shared key based authentication"; + } + leaf rsa-signature { + type empty; + description + "Use signature based authentication by using + PKI certificates"; + } + } + leaf lifetime { + type uint32; + mandatory true; + description + "Configure lifetime for IKE SAs + 0: for no timeout. + 300 .. 99999999: IKE SA lifetime in seconds."; + } + + container address-allocation { + must "../connection-type = 'responder-only'" { + description + "address-allocation can be configured only with + responder-only in ike2 policy"; + } + leaf aaa { + type empty; + description + "IRAC address allocation by AAA"; + } + description + "Specify IKE IRAS address allocation option"; + } + + uses ike-general-policy-profile-grouping; + + leaf description { + type string; + description + "Specify the description."; + } + } + + grouping ipsec-policy-grouping { + description + "Holds configuration information for IPSec policies."; + leaf name { + type string; + mandatory true; + description + "IPSec Policy Identification"; + } + leaf description { + type string; + description + "Specify the description."; + } + + leaf anti-replay-window { + type uint32 { + range "0 | 32..1024"; + } + description + "Configure replay window size + 0: to disable anti-replay-window + 32..1024: IPSec anti-replay-window size in multiple of 32"; + } + container perfect-forward-secrecy { + description + "Configure Perfect Forward Secrecy (PFS) for IPSec Policy"; + leaf dh-group { + type diffie-hellman-group-t; + description + "Configure Diffie-Hellman group for + perfect-forward-secrecy"; + } + } + list seq { + key seq-id; + description + "Specify IPSEC proposal sequence number"; + leaf seq-id { + type uint32; + description + "Sequence ID"; + } + leaf description { + type string; + description + "Specify the description."; + } + + leaf proposal { + type leafref { + path "/eipsec:ipsec/"+ + "eipsec:proposal/eipsec:ipsec-proposal/eipsec:name"; + } + description + "IKE proposal reference."; + } + } + } + + grouping key-string-grouping { + description + "Configure key for authentication algorithm"; + leaf key-str { + type union { + type string { + length "16"; + } + /* TODO HC2VPP-399: Removed length from hex-string which caused + failures when building using ODL yangtools + */ + type yang:hex-string; + } + description + "Key string input is either string value (length of 16) + or hexadecimal (length of 40)"; + } + } + + grouping ipsec-sa-ah-grouping { + description + "Configure Authentication Header (AH) for + Security Association (SA)"; + container ah { + description + "Configure Authentication Header (AH) for SA"; + choice authentication-algorithm { + description + "choice for authentication algorithm to set for AH"; + case hmac-aes-xcbc { + container hmac-aes-xcbc { + description + "Set the authentication algorithm to hmac-aes-xcbc"; + uses key-string-grouping; + } + } + case hmac-md5-96 { + container hmac-md5-96 { + description + "Set the authentication algorithm to hmac-md5-96"; + uses key-string-grouping; + } + } + case hmac-sha1-96 { + container hmac-sha1-96 { + description + "Set the authentication algorithm to hmac-sha1-96"; + uses key-string-grouping; + } + } + case key-string { + container key-string { + description + "Configure key for authentication algorithm"; + uses key-string-grouping; + } + } + } + } + } + + grouping ipsec-sa-esp-grouping { + description + "Configure IPSec Encapsulation Security Payload (ESP)"; + container esp { + description + "Set IPSec Encapsulation Security Payloer (ESP)"; + container authentication { + description + "Configure authentication for IPSec + Encapsulation Secutiry Payload (ESP)"; + choice authentication-algorithm { + description + "choice for authentication algorithm to set"; + case hmac-aes-xcbc { + container hmac-aes-xcbc { + description + "Set the authentication algorithm to hmac-aes-xcbc"; + uses key-string-grouping; + } + } + case hmac-md5-96 { + container hmac-md5-96 { + description + "Set the authentication algorithm to hmac-md5-96"; + uses key-string-grouping; + } + } + case hmac-sha1-96 { + container hmac-sha1-96 { + description + "Set the authentication algorithm to hmac-sha1-96"; + uses key-string-grouping; + } + } + case key-string { + container key-string { + description + "Configure key for authentication algorithm"; + uses key-string-grouping; + } + } + } + } + container encryption { + description + "Configure encryption for IPSec + Encapsulation Secutiry Payload (ESP)"; + choice encryption-algorithm { + description + "type of encryption"; + case des3-cbc { + container des3-cbd { + description + "Set the encryption algorithm to des3-cbc"; + uses key-string-grouping; + } + } + case aes-128-cbc { + container aes-128-cbc { + description + "Set the encryption algorithm to aes-128-cbc"; + uses key-string-grouping; + } + } + case aes-192-cbc { + container aes-192-cbc { + description + "Set the encryption algorithm to aes-192-cbc"; + uses key-string-grouping; + } + } + case aes-256-cbc { + container aes-256-cbc { + description + "Set the encryption algorithm to aes-256-cbc"; + uses key-string-grouping; + } + } + case des-cbc { + container des-cbc { + description + "Set the encryption algorithm to des-cbc"; + uses key-string-grouping; + } + } + case key-string { + container key-string { + description + "Configure key for encryption algorithm"; + uses key-string-grouping; + } + } + } + } + } + } + + grouping ipsec-acl-dest-grouping { + description + "IPSEC ACL destination."; + /* For destination */ + choice dest-address { + description + "destination address."; + case dest-ipv4-address { + leaf destination-ipv4-address { + type inet:ipv4-address; + description + "Destination IPv4 Address A.B.C.D/0..32."; + } + } + case dest-any { + leaf dest-any { + type empty; + description + "Match Any Destination IPv4 Address."; + } + } + } + } + + grouping ipsec-acl-seq-protocol-number-grouping { + description + "IPSec ACL Sequence protocol number."; + leaf number { + type uint16 { + range "0..255"; + } + description + "Specify protocol number."; + } + choice argument { + description + "Source IPv4 address."; + case source-ipv4-address { + leaf source-ipv4-address { + type inet:ipv4-address; + description + "Source IPv4 Address A.B.C.D/0..32."; + } + } + case any { + /* For source */ + leaf source-any { + type empty; + description + "Match Any Source IPv4 Address."; + } + } + } + } + + grouping ipsec-acl-seq-ip-address-grouping { + description + "IPSec ACL Sequence IP Address."; + leaf source-ipv4-address { + type inet:ipv4-address; + description + "Source is IPv4 Address A.B.C.D/0..32."; + } + } + + grouping ipsec-acl-seq-any-grouping { + description + "IPSec ACL Sequence Any."; + leaf any { + type empty; + description + "Source is Any."; + } + } + + grouping ipsec-acl-seq-tcp-grouping { + description + "IPSec ACL Sequence TCP."; + leaf tcp { + type empty; + description + "Source is TCP protocol."; + } + } + + grouping ipsec-acl-seq-udp-grouping { + description + "IPSec ACL Sequence for UDP."; + leaf udp { + type empty; + description + "Source is UDP protocol."; + } + } + + grouping ipsec-acl-grouping { + description + "IPSec ACL"; + list access-list { + if-feature ipsec-acl; + key "name sequence-number"; + uses name-grouping; + uses sequence-number-grouping; + description + "Configure the IPSec access-list."; + choice protocol { + description + "IPSec ACL protocol."; + case number { + uses ipsec-acl-seq-protocol-number-grouping; + } + case source-ipv4-address { + uses ipsec-acl-seq-ip-address-grouping; + } + case any { + uses ipsec-acl-seq-any-grouping; + } + case tcp { + uses ipsec-acl-seq-tcp-grouping; + } + case udp { + uses ipsec-acl-seq-udp-grouping; + } + } + uses ipsec-acl-dest-grouping; + } + } + + grouping ipsec-df-bit-grouping { + description + "IPSec Dont Fragment (DF) bit for IP header."; + container df-bit { + description + "Configure Don't Fragment (DF) bit for IP Header."; + leaf clear { + type empty; + description + "Clear DF bit for outer IP header."; + } + leaf propagate { + type empty; + description + "Propagate DF bit for outer IP header."; + } + leaf set { + type empty; + description + "Set DF bit for outer IP header."; + } + } + } + + grouping ipsec-profile-grouping { + description + "IPSec profile."; + list profile { + key "name"; + uses name-grouping; + uses ipsec-df-bit-grouping; + description + "Configure the IPSec Profile."; + leaf mtu { + type uint32 { + range "256..1600"; + } + description + "Set the MTU."; + } + list seq { + key "sequence-number"; + uses sequence-number-grouping; + description + "IPSec Access List sequence number."; + leaf policy { + type leafref { + //TODO: fixed path (HC2VPP-399) + path "/eipsec:ipsec/eipsec:spd/"+ + "eipsec:spd-entries/eipsec:name"; + } + description + "Specify IPSec policy name."; + } + } + } + } + + grouping ip-address-grouping { + description + "IP Address grouping"; + + choice ip-address { + description + "Choice of IPv4 or IPv6."; + leaf ipv4-address { + type inet:ipv4-address; + description + "Specifies the identity as a single four (4) + octet IPv4 address. + An example is, 10.10.10.10. "; + } + leaf ipv6-address { + type inet:ipv6-address; + description + "Specifies the identity as a single sixteen (16) "+ + "octet IPv6 address. "+ + "An example is, "+ + "FF01::101, 2001:DB8:0:0:8:800:200C:417A ."; + } + } + } + + grouping ipsec-sa-grouping { + description + "Configure Security Association (SA)"; + leaf spi { + type uint32; + description + "Specify Security Parameter Index"; + } + leaf anti-replay-window { + type uint16 { + range "0 | 32..1024"; + } + description + "Specify replay window size"; + } + leaf ip-comp { + type empty; + description + "Enables IPCOMP, which uses the IP payload compression + protocol to compress IP security (IPsec) packets + before encryption"; + } + + container local-peer { + description + "Specify the local peer IP address"; + uses ip-address-grouping; + } + container remote-peer { + description + "Specify the remote peer IP address"; + uses ip-address-grouping; + } + leaf sa-mode { + type ipsec-mode; + description + "SA Mode: tunnel or transport mode"; + } + leaf security-protocol { + type ipsec-protocol; + description + "Security protocol of IPsec SA: Either AH or ESP."; + } + leaf sequence-number { + type uint64; + description + "Current sequence number of IPsec packet."; + } + leaf sequence-number-overflow-flag { + type boolean; + description + "The flag indicating whether overflow of the sequence + number counter should prevent transmission of additional + packets on the SA, or whether rollover is permitted."; + } + leaf path-mtu { + type uint16; + description + "maximum size of an IPsec packet that can be transmitted + without fragmentation"; + } + container life-time { + leaf life-time-in-seconds { + type uint32; + description + "SA life time in seconds"; + } + leaf remain-life-time-in-seconds { + type uint32; + description + "Remain SA life time in seconds"; + } + leaf life-time-in-byte { + type uint32; + description + "SA life time in bytes"; + } + leaf remain-life-time-in-byte { + type uint32; + description + "Remain SA life time in bytes"; + } + description + "SA life time information"; + } + leaf upper-protocol { + type string; + description + "Upper-layer protocol to be used"; + } + leaf direction { + type ipsec-traffic-direction; + description + "It indicates whether the SA is inbound SA or + out bound SA."; + } + container source-address { + description + "Specify the source IP address and + port of protected traffic"; + uses ip-address-grouping; + leaf port-number { + type uint32; + description + "port of protected traffic"; + } + } + container destination-address { + description + "Specify the destination IP address and + port of protected traffic"; + uses ip-address-grouping; + leaf port-number { + type uint32; + description + "port of protected traffic"; + } + } + leaf nat-traversal-flag { + type boolean; + description + "Whether the SA is used to protect traffic that needs + nat traversal"; + } + uses ipsec-sa-ah-grouping; + uses ipsec-sa-esp-grouping; + } + + + /* draft-wang-ipsecme-ike-yang-00 */ + grouping ipsec-common-configuration { + choice df-flag { + default copy; + case set { + leaf set { + type empty; + description + "Set the df bit when encapsulate IPsec tunnel."; + } + } + case clear { + leaf clear { + type empty; + description + "Clear the df bit when encapsulate IPsec tunnel."; + } + } + case copy { + leaf copy { + type empty; + description + "Copy the inner IP header df bit."; + } + } + description + "It indicates how to process the df bit when encapsulate + IPsec tunnel."; + } + leaf stateful-frag-check { + type boolean; + default false; + description "Whether stateful fragment checking applies."; + } + leaf life-time-kb { + type uint32; + units "KB"; + default 2000000; + description "IPsec SA Life time in KB."; + } + leaf life-time-second { + type uint32; + units "Second"; + default 18400; + description "IPsec SA Life time in Seconds"; + } + choice anti-replay { + default enable; + case enable { + leaf enable { + type empty; + description "Enable Anti-replay"; + } + choice anti-replay-windows-size { + case size-32; + case size-64; + case size-128; + case size-256; + case size-512; + case size-1024; + default size-1024; + description "It indicate the size of anti-replay window"; + } + } + case disable { + leaf disable { + type empty; + description "Disable Anti-replay"; + } + } + description "Whether enable or disable anti-replay"; + } + leaf inbound-dscp { + type uint16 { + range "0..63"; + } + default 0; + description "Inbound DSCP value"; + } + leaf outbound-dscp { + type uint16 { + range "0..63"; + } + default 0; + description "Outbound DSCP value"; + } + description "Common IPsec configurations"; + } + + /*--------------------*/ + /* Configuration Data */ + /*--------------------*/ + container ikev1 { + if-feature ikev1; + description + "Configuration IPSec IKEv1"; + /* The following is for <configure> */ + list proposal { + key "name"; + uses ike-proposal-grouping; + description + "Configure IKE proposal"; + } + leaf keepalive { + type empty; + description + "Enables sending Dead Peer Detection (DPD) messages "+ + "to Internet Key Exchange (IKE) peers."; + } + list policy { + key "name"; + uses ike-policy-profile-grouping; + description + "Configure IKE Policy Profile."; + } + } + + container ikev2 { + if-feature ikev2; + description + "Configuration IPSec IKEv2"; + /* The following is for <configure> */ + /* draft-wang-ipsecme-ike-yang-00 */ + container ike-global-configuration { + if-feature ikev2-global; + description "Global IKE configurations"; + uses ipsec-common-configuration; + leaf local-name { + type string; + description + "Global local name configuration, if it is not configed, + ip address will be used as default. If configing special + local name for special peer, it will overwrite the global + name configuration when negotion with that peer."; + } + leaf nat-keepalive-interval { + type uint16 { + range "5..300"; + } + units "Seconds"; + default 20; + description "Global nat keepalive interval"; + } + leaf dpd-interval { + type uint16 { + range "10..3600"; + } + units "Seconds"; + default 30; + description "Global DPD interval"; + } + } + container ike-peer { + if-feature ikev2-peer; + description "IKE peer information"; + list ike-peer-entries { + key "peer-name"; + description "IKE peer information"; + leaf peer-name { + type string; + mandatory true; + description "Name of IKE peer"; + } + leaf ike-proposal-number { + type ike-proposal-number-ref; + description "IKE proposal number referenced by IKE peer"; + } + leaf PresharedKey { + type string; + description "Preshare key"; + } + leaf nat-traversal { + type boolean; + default false; + description "Enable/Disable nat traversal"; + } + choice local-id-type { + default ip; + case ip { + leaf ip { + type empty; + description "IP address"; + } + } + case fqdn { + leaf fqdn { + type empty; + description "Fully Qualifed Domain name "; + } + } + case dn { + leaf dn { + type empty; + description "Domain name"; + } + } + case user_fqdn { + leaf user_fqdn { + type empty; + description "User FQDN"; + } + } + description "Local ID type"; + } + leaf local-id { + type string; + description + "Local ID Name. When IP is used as local ID type, + it is ignored. If it is not configurated, + global local name will be used."; + } + leaf remote-id { + type "string"; + description "ID of IKE peer"; + } + leaf low-remote-address { + type inet:ip-address; + description "Low range of remote address"; + } + leaf high-remote-address { + type inet:ip-address; + description "High range of remote address"; + } + leaf certificate { + type string; + description "Certificate file name"; + } + leaf auth-address-begin { + type inet:ip-address; + description + "The begin range of authenticated peer address"; + } + leaf auth-address-end { + type inet:ip-address; + description + "The end range of authenticated peer address"; + } + } + }//End of IKEPeerEntries + + + list proposal { + if-feature ikev2-proposal; + key "name"; + uses ikev2-proposal-grouping; + description + "Configure IKEv2 proposal"; + } + list policy { + if-feature ikev2-policy; + key "name"; + uses ikev2-policy-profile-grouping; + description + "IKEv2 Policy Profile"; + } + } + + container ipsec { + if-feature ipsec; + description + "Configuration IPsec"; + container sad { + if-feature ipsec-sad; + description + "Configure the IPSec Security Association Database (SAD)"; + list sad-entries { + key "spi direction"; + description + "Configure IPsec Security Association Database(SAD)"; + uses ipsec-sa-grouping; + } + } + container proposal { + if-feature ipsec-proposal; + description + "IPSec Proposal Profile"; + list ipsec-proposal { + key "name"; + uses ipsec-proposal-grouping; + description + "Configure the IP Security (IPSec) proposal"; + } + } + /* + TODO HC2VPP-399: modified spd container to list to support multiple spds for VPP + */ + list spd { + key "spd-id"; + if-feature ipsec-spd; + description + "List of Security Policy Databases (SPD)"; + leaf spd-id { + type int32; + } + list spd-entries { + key "name"; + ordered-by user; + uses ipsec-policy-grouping; + description + "Specify an IPSec policy name"; + } + } + container pad { + description + "Configure Peer Authorization Database (PAD)"; + list pad-entries { + key "pad-type pad-id"; + ordered-by user; + uses identity-grouping; + description + "Peer Authorization Database (PAD)"; + leaf pad-id { + type uint32; + description + "PAD identity"; + } + leaf pad-type { + type pad-type-t; + description + " PAD type"; + } + leaf ike-peer-name { + type string; + description + "IKE Peer Name"; + } + container peer-authentication { + description + "Specify IKE peer authentication configuration"; + leaf algorithm { + type ike-integrity-algorithm-t; + description + "Specify the authentication algorithm"; + } + leaf preshared-key { + type empty; + description + "Use pre-shared key based authentication"; + } + leaf rsa-signature { + type empty; + description + "Use signature based authentication by using + PKI certificates"; + } + } + } + } + } + + + + /*--------------------------*/ + /* Operational State Data */ + /*--------------------------*/ + grouping ike-proposal-state-components { + description + "IKE Proposal operational state"; + list proposal { + if-feature ike-proposal-state; + description + "Operational data for IKE Proposal"; + leaf name { + type string { + length "1..50"; + } + description + "Name of the IKE proposal."; + } + leaf lifetime { + type uint32; + units "seconds"; + description + "lifetime"; + } + leaf encryption { + type ike-encryption-algorithm-t; + description + "Encryption algorithm"; + } + leaf dh-group { + type diffie-hellman-group-t; + description + "Diffie-Hellman group."; + } + leaf authentication { + type ike-integrity-algorithm-t; + description + "authentication"; + } + } + } + + grouping ike-policy-state-grouping { + description + "IKE Policy State."; + list policy { + if-feature ike-policy-state; + description + "Operational data for IKE policy"; + leaf name { + type string { + length "1..50"; + } + description + "Name of the IKE Policy."; + } + leaf description { + type string; + description + "Description for IKE Policy."; + } + leaf mode { + type enumeration { + enum aggressive { + description + "Aggressive mode."; + } + enum main { + description + "Main mode."; + } + } + description + "IKE policy mode."; + } + leaf connection-type { + type connection-type-t; + description + "IKE policy connection type."; + } + leaf local-identity { + type inet:ipv4-address-no-zone; + description + "IP address of the local identity."; + } + leaf remote-identity { + type inet:ipv4-address-no-zone; + description + "IP address of the remote identity."; + } + leaf pre-shared-key { + type string; + description + "Pre-shared key"; + } + leaf seq { + type uint32; + description + "sequence number"; + } + leaf proposal { + type string; + description + "proposal name"; + } + } + } + + grouping ikev2-proposal-state-components { + description + "IKEv2 Operational state"; + list proposal { + if-feature ikev2-proposal-state; + description + "IKEv2 proposal operational data"; + leaf name { + type string; + description + "Name of IKEv2 Proposal."; + } + leaf pseudo-random-function { + type pseudo-random-function-t; + description + "Pseudo Random Function for IKEv2."; + } + leaf authentication { + type ike-integrity-algorithm-t; + description + "authentication"; + } + leaf encryption { + type ike-encryption-algorithm-t; + description + "Encryption algorithm"; + } + leaf dh-group { + type diffie-hellman-group-t; + mandatory true; + description + "Diffie-Hellman group."; + } + } + } + + grouping ipsec-policy-state-grouping { + description + "IPSec operational state"; + list policy { + if-feature ipsec-policy-state; + description + "IPSec policy operational data"; + leaf name { + type string; + description + "IPSec Policy name."; + } + leaf anti-replay-window { + type uint32; + description + "replay window size"; + } + leaf perfect-forward-secrecy { + type diffie-hellman-group-t; + description + "Diffie-Hellman group for perfect-forward-secrecy"; + } + list seq { + description + "Sequence number"; + leaf seq-id { + type uint32; + description + "Sequence number"; + } + leaf proposal-name { + type string; + description + "IPSec proposal name"; + } + } + } + } + grouping ipsec-proposal-state-grouping { + description + "IPSec proposal operational data"; + list proposal { + if-feature ipsec-proposal-state; + description + "IPSec proposal operational data"; + leaf name { + type string; + description + "IPSec Proposal name"; + } + leaf ah { + type ike-integrity-algorithm-t; + description + "Authentication Header (AH)."; + } + container esp { + description + "Encapsulating Security Payload (ESP)."; + leaf authentication { + type ike-integrity-algorithm-t; + description + "ESP authentication"; + } + leaf encryption { + type ike-encryption-algorithm-t; + description + "ESP encryption"; + } + } + leaf ip-comp{ + type empty; + description + "IPSec proposal IP-COMP which uses the IP Payload "+ + "compression protocol to compress IP Security (IPSec) "+ + "packets before encryption"; + } + container lifetime { + description + "lifetime for IPSEC SAs"; + leaf kbytes { + type uint32; + description + "lifetime kbytes for IPSEC SAs"; + + } + leaf seconds { + type uint32; + description + "lifetime seconds for IPSEC SAs"; + } + } + } + } + + grouping ipsec-alarms-state-grouping { + description + "IPSec alarms operational data"; + leaf hold-down { + if-feature ipsec-alarms-state; + type uint32; + description + "Hold-down value"; + } + } + + grouping ipsec-sa-ah-state-grouping { + description + "IPSec SA's AH operational data"; + + leaf spi { + if-feature ipsec-sa-ah-state; + type uint32; + description + "Security Parameter Index (SPI) value"; + } + leaf description { + if-feature ipsec-sa-ah-state; + type string; + description + "the description."; + } + leaf authentication-algorithm { + if-feature ipsec-sa-ah-state; + type ike-integrity-algorithm-t; + description + "Authentication algorithm"; + } + leaf encryption-algorithm { + if-feature ipsec-sa-ah-state; + type ike-encryption-algorithm-t; + description + "Encryption algorithm"; + } + } + + grouping ipsec-sa-state-grouping { + description + "IPSec Security Association Operational data"; + list sa { + if-feature ipsec-sa-state; + description + "IPSec SA operational data"; + leaf name { + type string; + description + "Specify IPSec Security Association (SA) name"; + } + leaf anti-replay-window { + type uint16; + description + "replay window size"; + } + leaf ip-comp { + type empty; + description + "Enables IPCOMP, which uses the IP payload compression + protocol to compress IP security (IPsec) packets before + encryption"; + } + uses ipsec-sa-ah-state-grouping; + } + } + + /* draft-wang-ipsecme-ipsec-yang-00 */ + grouping ipsec-tunnel-mode-info { + description + "common infomations when using IPsec tunnel mode"; + leaf local-address { + if-feature ipsec-tunnel; + type string; + description + "Local address of IPsec tunnel mode"; + } + leaf remote-address { + if-feature ipsec-tunnel; + type string; + description + "Remote address of IPsec tunnel mode"; + } + leaf bypass-df { + if-feature ipsec-tunnel; + type enumeration { + enum "set" { + description + "Set the df bit"; + } + enum "clear" { + description + "Clear the df bit"; + } + enum "copy" { + description + "Copy the df bit from inner header"; + } + } + description + "This flag indicates how to process tunnel mode df flag"; + } + leaf dscp-flag { + if-feature ipsec-tunnel; + type boolean; + description + "This flag indicate whether bypass DSCP or map to + unprotected DSCP values (array) if needed to + restrict bypass of DSCP values."; + } + leaf stateful-frag-check-flag { + if-feature ipsec-tunnel; + type boolean; + description + "This flag indicates whether stateful fragment checking + will be used."; + } + } + grouping traffic-selector { + description + "IPsec traffic selector information"; + leaf local-address-low { + if-feature ipsec-local-address-range; + type inet:ip-address; + description + "Low range of local address"; + } + leaf local-address-high { + if-feature ipsec-local-address-range; + type inet:ip-address; + description + "High range of local address"; + } + leaf remote-address-low { + if-feature ipsec-remote-address-range; + type inet:ip-address; + description + "Low range of remote address"; + } + leaf remote-address-high { + if-feature ipsec-remote-address-range; + type inet:ip-address; + description + "High range of remote address"; + } + leaf next-protocol-low { + if-feature ipsec-next-protocol-range; + type uint16; + description + "Low range of next protocol"; + } + leaf next-protocol-high { + if-feature ipsec-next-protocol-range; + type uint16; + description + "High range of next protocol"; + } + leaf local-port-low { + if-feature ipsec-local-port-range; + type inet:port-number; + description + "Low range of local port"; + } + leaf local-port-high { + if-feature ipsec-local-port-range; + type inet:port-number; + description + "High range of local port"; + } + leaf remote-port-high { + if-feature ipsec-remote-port-range; + type inet:port-number; + description + "Low range of remote port"; + } + leaf remote-port-low { + if-feature ipsec-remote-port-range; + type inet:port-number; + description + "High range of remote port"; + } + } + grouping ipsec-algorithm-info { + description + "IPsec algorithm information used by SPD and SAD"; + leaf ah-auth-algorithm { + if-feature ipsec-ah-authentication; + type ipsec-authentication-algorithm; + description + "Authentication algorithm used by AH"; + } + leaf esp-integrity-algorithm { + if-feature ipsec-esp-integrity; + type ipsec-authentication-algorithm; + description + "Integrity algorithm used by ESP"; + } + leaf esp-encrypt-algorithm { + if-feature ipsec-esp-encrypt; + type ipsec-encryption-algorithm; + description + "Encryption algorithm used by ESP"; + } + } + grouping ipsec-stat { + leaf inbound-packets { + if-feature ipsec-stat; + type uint64; + config false; + description "Inbound Packet count"; + } + leaf outbound-packets { + if-feature ipsec-stat; + type uint64; + config false; + description "Outbound Packet count"; + } + leaf inbound-bytes { + if-feature ipsec-stat; + type uint64; + config false; + description "Inbound Packet bytes"; + } + leaf outbound-bytes { + if-feature ipsec-stat; + type uint64; + config false; + description "Outbound Packet bytes"; + } + leaf inbound-drop-packets { + if-feature ipsec-stat; + type uint64; + config false; + description "Inbound dropped packets count"; + } + leaf outbound-drop-packets { + if-feature ipsec-stat; + type uint64; + config false; + description "Outbound dropped packets count"; + } + container dropped-packet-detail { + if-feature ipsec-stat; + description "The detail information of dropped packets"; + leaf sa-non-exist { + type uint64; + config false; + description + "The dropped packets counts caused by SA non-exist."; + } + leaf queue-full { + type uint64; + config false; + description + "The dropped packets counts caused by full processing + queue"; + } + leaf auth-failure { + type uint64; + config false; + description + "The dropped packets counts caused by authentication + failure"; + } + leaf malform { + type uint64; + config false; + description "The dropped packets counts of malform"; + } + leaf replay { + type uint64; + config false; + description "The dropped packets counts of replay"; + } + leaf large-packet { + type uint64; + config false; + description "The dropped packets counts of too large"; + } + leaf invalid-sa { + type uint64; + config false; + description "The dropped packets counts of invalid SA"; + } + leaf policy-deny { + type uint64; + config false; + description + "The dropped packets counts of denyed by policy"; + } + leaf other-reason { + type uint64; + config false; + description + "The dropped packets counts of other reason"; + } + } + description "IPsec statistics information"; + } + + + container ike-state { + if-feature ikev1-state; + config "false"; + uses ike-proposal-state-components; + uses ike-policy-state-grouping; + description + "Contain the operational data for IKE."; + } + container ikev2-state { + if-feature ikev2-state; + config "false"; + uses ikev2-proposal-state-components; + uses ike-policy-state-grouping; + description + "Contain the operational data for IKEv2."; + } + container ipsec-state { + if-feature ipsec-state; + config "false"; + uses ipsec-policy-state-grouping; + uses ipsec-proposal-state-grouping; + uses ipsec-alarms-state-grouping; + uses ipsec-sa-state-grouping; + container redundancy { + if-feature ipsec-redundancy; + description + "Configure redundancy for IPSec"; + leaf inter-chassis { + type empty; + description + "Set redundancy at chassis level"; + } + } + + description + "Contain the operational data for IPSec."; + } + + /* draft-wang-ipsecme-ipsec-yang-00 */ + container sad { + if-feature sad; + config false; + description + "The IPsec SA database"; + list sad-entries { + key "spi security-protocol direction"; + description + "The SA entries information"; + leaf spi { + type ipsec-spi; + description + "Security parameter index of SA entry."; + } + leaf security-protocol { + type ipsec-protocol; + description + "Security protocol of IPsec SA."; + } + leaf direction { + type ipsec-traffic-direction; + description + "It indicates whether the SA is inbound SA or + out bound SA."; + } + leaf sa-type { + type enumeration { + enum "manual" { + description + "Manual IPsec SA"; + } + enum "isakmp" { + description + "ISAKMP IPsec SA"; + } + } + description + "It indicates whether the SA is created by manual + or by dynamic protocol."; + } + leaf sequence-number { + type uint64; + description + "Current sequence number of IPsec packet."; + } + leaf sequence-number-overflow-flag { + type boolean; + description + "The flag indicating whether overflow of the sequence + number counter should prevent transmission of additional + packets on the SA, or whether rollover is permitted."; + } + leaf anti-replay-enable-flag { + type boolean; + description + "It indicates whether anti-replay is enable or disable."; + } + leaf anti-replay-window-size { + type uint64; + description + "The size of anti-replay window."; + } + uses ipsec-algorithm-info; + container life-time { + leaf life-time-in-seconds { + type uint32; + description + "SA life time in seconds"; + } + leaf remain-life-time-in-seconds { + type uint32; + description + "Remain SA life time in seconds"; + } + leaf life-time-in-byte { + type uint32; + description + "SA life time in bytes"; + } + leaf remain-life-time-in-byte { + type uint32; + description + "Remain SA life time in bytes"; + } + description + "SA life time information"; + } + leaf protocol-mode { + type ipsec-mode; + description + "It indicates whether tunnel mode or transport mode + will be used."; + } + container tunnel-mode-process-info { + when "../protocol-mode = 'tunnel'" { + description + "External information of SA when SA works in + tunnel mode."; + } + uses ipsec-tunnel-mode-info; + description + "External information of SA when SA works in + tunnel mode."; + } + leaf-list dscp { + type uint8 { + range "0..63"; + } + description + "When traffic matchs SPD, the DSCP values used to + filter traffic"; + } + leaf path-mtu { + type uint16; + description + "Path MTU valie"; + } + leaf nat-traversal-flag { + type boolean; + description + "Whether the SA is used to protect traffic that needs + nat traversal"; + } + } + } + container spd { + if-feature spd; + config false; + description + "IPsec security policy database information"; + list spd-entries { + description + "IPsec SPD entry information"; + list name { + description + "SPD name information."; + leaf name-type { + type ipsec-spd-name; + description + "SPD name type."; + } + leaf name-string { + when "../name-type = 'id_rfc_822_addr' or ../name-type = + 'id_fqdn'" { + description + "when name type is id_rfc_822_addr or id_fqdn, the + name are saved in string"; + } + type string; + description + "SPD name content"; + } + leaf name-binary { + when "../name-type = 'id_der_asn1_dn' or ../name-type = + 'id_key'" { + description + "when name type is id_der_asn1_dn or id_key, the name + are saved in binary"; + } + type binary; + description + "SPD name content"; + } + } + leaf pfp-flag { + type boolean; + description + "populate from packet flag"; + } + list traffic-selector { + min-elements 1; + uses traffic-selector; + description + "Traffic selectors of SAD entry"; + } + leaf operation { + type ipsec-spd-operation; + description + "It indicates how to process the traffic when it matches + the security policy."; + } + container protect-operation { + when "../operation = 'protect'" { + description + "How to protect the traffic when the SPD operation + is protect"; + } + leaf spd-ipsec-mode { + type ipsec-mode; + description + "It indicates which mode is chosen when the traffic need + be protected by IPsec."; + } + leaf esn-flag { + type boolean; + description + "It indicates whether ESN is used."; + } + leaf spd-ipsec-protocol { + type ipsec-protocol; + description + "It indicates which protocol (AH or ESP) is chosen."; + } + container tunnel-mode-additional { + when "../spd-ipsec-mode = 'tunnel'" { + description + "Additional informations when choose tunnel mode"; + } + uses ipsec-tunnel-mode-info; + description + "When use tunnel mode, the additional information of + SPD."; + } + list spd-algorithm { + min-elements 1; + uses ipsec-algorithm-info; + description + "Algorithms defined in SPD, ordered by decreasing + priority."; + } + description + "How to protect the traffic when the SPD operation is + protect"; + } + } + } + + container ipsec-global-statistics { + if-feature ipsec-global-stats; + config false; + description "IPsec global statistics"; + container ipv4 { + description "IPsec statistics of IPv4"; + uses ipsec-stat; + } + container ipv6 { + description "IPsec statistics of IPv6"; + uses ipsec-stat; + } + container global { + description "IPsec statistics of global"; + uses ipsec-stat; + } + } + + + /*--------------------*/ + /* RPC */ + /*--------------------*/ + rpc clear-ipsec-group { + if-feature clear-ipsec-group; + description + "RPC for clear ipsec states"; + input { + leaf alarm-hold-down { + type uint8; + description + "IPSec alarm hold-down"; + } + leaf ipsec-policy-name { + type leafref { + path "/eipsec:ipsec/eipsec:spd/"+ + "eipsec:spd-entries/eipsec:name"; + } + description + "IPSec Policy name."; + } + } + } + + rpc clear-ike-group { + if-feature clear-ike-group; + description + "RPC for clear IKE states"; + input { + leaf proposal { + type leafref { + path "/eipsec:ikev1/eipsec:proposal/"+ + "eipsec:name"; + } + description + "IPSec IKE Proposal name."; + } + } + } + + rpc clear-ikev2-group { + if-feature clear-ikev2-group; + description + "RPC for clear IKEv2 states"; + input { + leaf proposal { + type leafref { + path "/eipsec:ikev2/eipsec:proposal/"+ + "eipsec:name"; + } + description + "IPSec IKEv2 Proposal name."; + } + } + } + + /* draft-wang-ipsecme-ipsec-yang-00 */ + rpc reset-ipv4 { + if-feature reset-ipv4; + description "Reset IPsec IPv4 statistics"; + input { + leaf ipv4 { + type empty; + description "Reset IPsec IPv4 statistics"; + } + } + output { + leaf status { + type string; + description "Operation status"; + } + } + } + rpc reset-ipv6 { + if-feature reset-ipv6; + description "Reset IPsec IPv6 statistics"; + input { + leaf ipv6 { + type empty; + description "Reset IPsec IPv6 statistics"; + } + } + output { + leaf status { + type string; + description "Operation status"; + } + } + } + rpc reset-global { + if-feature reset-global; + description "Reset IPsec global statistics"; + input { + leaf ipv6 { + type empty; + description "Reset IPsec global statistics"; + } + } + output { + leaf status { + type string; + description "Operation status"; + } + } + } + + notification dpd-failure{ + description "IKE peer DPD detect failure"; + leaf peer-id { + type string; + description "Peer ID"; + } + } + + notification peer-authentication-failure { + if-feature peer-authentication-failure; + description "Peer authentication fail when negotication"; + leaf peer-id { + type string; + description "The ID of remote peer"; + } + } + + notification ike-reauth-failure { + if-feature ike-reauth-failure; + description "IKE peer reauthentication fail"; + leaf peer-id { + type string; + description "The ID of remote peer"; + } + } + + notification ike-rekey-failure { + if-feature ike-rekey-failure; + description "IKE SA rekey failure"; + leaf peer-id { + type string; + description "The ID of remote peer"; + } + leaf old-i-spi { + type uint64; + description "old SPI"; + } + leaf old-r-spi { + type uint64; + description "old SPI"; + } + } + + notification ipsec-rekey-failure { + if-feature ipsec-rekey-failure; + description "IPsec SA rekey failure"; + leaf peer-id { + type string; + description "The ID of remote peer"; + } + leaf old-inbound-spi { + type ipsec-spi; + description "old inbound SPI"; + } + leaf old-outbound-spi { + type ipsec-spi; + description "old outbound SPI"; + } + } +} /* module ericsson-ipsec */ diff --git a/ipsec/ipsec-api/src/main/yang/vpp-ipsec@2018-12-13.yang b/ipsec/ipsec-api/src/main/yang/vpp-ipsec@2018-12-13.yang new file mode 100644 index 000000000..72ade372a --- /dev/null +++ b/ipsec/ipsec-api/src/main/yang/vpp-ipsec@2018-12-13.yang @@ -0,0 +1,147 @@ +module vpp-ipsec { + yang-version 1; + namespace "http://fd.io/hc2vpp/yang/vpp-ipsec"; + prefix "vpp-ipsec"; + + import hc2vpp-ietf-ipsec { + prefix "hc2vpp-ietf-ipsec"; + } + + import ietf-inet-types { + prefix inet; + } + + import yang-ext { + prefix "ext"; + } + + import ietf-interfaces { + prefix "if"; + } + + revision "2018-12-13" { + description "Initial revision of ipsec model"; + } + + grouping vpp-ipsec-spd-entry-grouping { + description + "common information when using IPsec tunnel mode"; + leaf spi { + type int32; + } + + leaf priority { + type int32; + } + + leaf direction { + type hc2vpp-ietf-ipsec:ipsec-traffic-direction; + } + + leaf is-ipv6 { + type boolean; + } + + leaf operation { + type hc2vpp-ietf-ipsec:ipsec-spd-operation; + } + + leaf protect-sa-id { + type int32; + } + + leaf laddr-start { + type inet:ip-address; + } + + leaf laddr-stop { + type inet:ip-address; + } + + leaf raddr-start { + type inet:ip-address; + } + + leaf raddr-stop { + type inet:ip-address; + } + } + + grouping spd-interfaces-grouping { + container spd-interfaces { + list interface { + key "interface-ref"; + + leaf interface-ref { + type if:interface-ref; + } + } + } + } + + grouping ikev2-policy-aug-grouping { + leaf certificate { + type string; + description "Local file with RSA signature"; + } + + list traffic-selectors { + key "ts-name"; + description "List of traffic selectors of profile"; + leaf ts-name { + type string; + } + uses hc2vpp-ietf-ipsec:traffic-selector; + leaf protocol { + type uint8; + description "Protocol. If zero not relevant."; + } + } + } + + augment /hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:sad/hc2vpp-ietf-ipsec:sad-entries { + ext:augment-identifier "ipsec-sad-entries-augmentation"; + leaf sa-id { + type int32; + } + } + + augment /hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:ike-global-configuration { + ext:augment-identifier "ipsec-ike-global-conf-augmentation"; + leaf local-key-file { + type string; + description "Local file with RSA signature"; + } + } + + augment /hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:policy { + ext:augment-identifier "ipsec-ikev2-policy-augmentation"; + uses ikev2-policy-aug-grouping; + } + + augment /hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:spd { + ext:augment-identifier "ipsec-spd-enabled-interfaces-augmentation"; + uses spd-interfaces-grouping; + } + + augment /hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:spd/hc2vpp-ietf-ipsec:spd-entries { + ext:augment-identifier "ipsec-spd-entries-augmentation"; + uses vpp-ipsec-spd-entry-grouping; + } + + augment /hc2vpp-ietf-ipsec:ipsec-state { + ext:augment-identifier "ipsec-state-spd-augmentation"; + list spd { + key "spd-id"; + + leaf spd-id { + type int32; + } + list spd-entries { + uses vpp-ipsec-spd-entry-grouping; + } + + uses spd-interfaces-grouping; + } + } +} diff --git a/ipsec/ipsec-impl/pom.xml b/ipsec/ipsec-impl/pom.xml new file mode 100644 index 000000000..9cf3dd97a --- /dev/null +++ b/ipsec/ipsec-impl/pom.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2019 PANTHEON.tech. + + 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. +--> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>vpp-impl-parent</artifactId> + <relativePath>../../vpp-common/vpp-impl-parent</relativePath> + <version>1.19.01-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <groupId>io.fd.hc2vpp.ipsec</groupId> + <artifactId>ipsec-impl</artifactId> + <name>${project.artifactId}</name> + <version>1.19.01-SNAPSHOT</version> + <packaging>bundle</packaging> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>ipsec-api</artifactId> + <version>${project.version}</version> + </dependency> + + <!--VPP common--> + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>translate-api</artifactId> + </dependency> + + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>translate-spi</artifactId> + </dependency> + + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>cfg-init</artifactId> + </dependency> + + <!-- Translation --> + <dependency> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>vpp-translate-utils</artifactId> + </dependency> + + <!-- DI --> + <dependency> + <groupId>com.google.inject</groupId> + <artifactId>guice</artifactId> + </dependency> + <dependency> + <groupId>net.jmob</groupId> + <artifactId>guice.conf</artifactId> + </dependency> + <dependency> + <groupId>com.google.inject.extensions</groupId> + <artifactId>guice-multibindings</artifactId> + </dependency> + <!-- Testing dependencies--> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.inject.extensions</groupId> + <artifactId>guice-testlib</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>vpp-translate-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.fd.honeycomb.infra</groupId> + <artifactId>test-tools</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>RELEASE</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java new file mode 100644 index 000000000..36dd8ae85 --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/IpsecModule.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec; + +import com.google.inject.AbstractModule; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import io.fd.hc2vpp.common.translate.util.MultiNamingContext; +import io.fd.hc2vpp.ipsec.read.IpsecReaderFactory; +import io.fd.hc2vpp.ipsec.write.IpsecWriterFactory; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.write.WriterFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Module class instantiating IpSec plugin components. + */ +public class IpsecModule extends AbstractModule { + + private static final Logger LOG = LoggerFactory.getLogger(IpsecModule.class); + private static final String SAD_ENTRIES_MAPPING = "sad-entries-mapping"; + + @Override + protected void configure() { + LOG.info("Installing IPSec module"); + + bind(MultiNamingContext.class).toInstance(new MultiNamingContext(SAD_ENTRIES_MAPPING, 1)); + LOG.info("Injecting writers factories"); + final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); + writerFactoryBinder.addBinding().to(IpsecWriterFactory.class).in(Singleton.class); + + LOG.info("Injecting readers factories"); + final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class); + readerFactoryBinder.addBinding().to(IpsecReaderFactory.class).in(Singleton.class); + + LOG.info("Module IPSec successfully configured"); + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java new file mode 100644 index 000000000..e148022e8 --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecReaderFactory.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.read; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import io.fd.honeycomb.translate.impl.read.GenericInitListReader; +import io.fd.honeycomb.translate.impl.read.GenericReader; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Factory producing readers for IpSec plugin's data. + */ +public final class IpsecReaderFactory implements ReaderFactory { + + private static final InstanceIdentifier<IpsecState> IPSEC_STATE_ID = InstanceIdentifier.create(IpsecState.class); + private FutureJVppCore vppApi; + + @Inject + public IpsecReaderFactory(final FutureJVppCore vppApi) { + this.vppApi = vppApi; + } + + @Override + public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { + registry.subtreeAdd(Sets + .newHashSet(InstanceIdentifier.create(IpsecState.class).child(Sa.class), + InstanceIdentifier.create(IpsecState.class).augmentation(IpsecStateSpdAugmentation.class) + .child(Spd.class)), new GenericReader<>(IPSEC_STATE_ID, + new IpsecStateCustomizer(vppApi))); + registry.addStructuralReader(IPSEC_STATE_ID.augmentation(IpsecStateSpdAugmentation.class), + IpsecStateSpdAugmentationBuilder.class); + registry.subtreeAdd(Sets + .newHashSet(InstanceIdentifier.create(Spd.class).child(SpdEntries.class)), + new GenericInitListReader<>( + IPSEC_STATE_ID.augmentation(IpsecStateSpdAugmentation.class).child(Spd.class), + new IpsecStateSpdCustomizer(vppApi))); + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java new file mode 100644 index 000000000..4755c7a82 --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizer.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.read; + +import com.google.common.base.Optional; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.vpp.jvpp.core.dto.IpsecSaDetails; +import io.fd.vpp.jvpp.core.dto.IpsecSaDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.IpsecSaDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.LinkedList; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeEncryptionAlgorithmT; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeIntegrityAlgorithmT; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecStateBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.SaBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class IpsecStateCustomizer extends FutureJVppCustomizer + implements JvppReplyConsumer, InitializingReaderCustomizer<IpsecState, IpsecStateBuilder>, Ipv4Translator, + Ipv6Translator { + + private final DumpCacheManager<IpsecSaDetailsReplyDump, Void> ipsecSaDetailsReplyDumpManager; + + public IpsecStateCustomizer(final FutureJVppCore vppApi) { + super(vppApi); + this.ipsecSaDetailsReplyDumpManager = + new DumpCacheManager.DumpCacheManagerBuilder<IpsecSaDetailsReplyDump, Void>() + .withExecutor(new IpsecStateCustomizer.IpsecStateSaDetailsDumpExecutor(vppApi)) + .acceptOnly(IpsecSaDetailsReplyDump.class) + .build(); + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<IpsecState> id, + @Nonnull final IpsecState readValue, @Nonnull final ReadContext ctx) { + return Initialized.create(id, readValue); + } + + @Nonnull + @Override + public IpsecStateBuilder getBuilder(@Nonnull final InstanceIdentifier<IpsecState> id) { + return new IpsecStateBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<IpsecState> id, + @Nonnull final IpsecStateBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + final Optional<IpsecSaDetailsReplyDump> dumpSa = + ipsecSaDetailsReplyDumpManager.getDump(id, ctx.getModificationCache()); + + if (dumpSa.isPresent()) { + LinkedList<Sa> listSa = new LinkedList<>(); + IpsecSaDetailsReplyDump reply = dumpSa.get(); + for (IpsecSaDetails details : reply.ipsecSaDetails) { + SaBuilder saBuilder = new SaBuilder(); + saBuilder.setSpi(Integer.toUnsignedLong(details.spi)) + .setAntiReplayWindow(Long.valueOf(details.replayWindow).intValue()) + .setAuthenticationAlgorithm(IkeIntegrityAlgorithmT.forValue(details.integAlg)) + .setEncryptionAlgorithm(IkeEncryptionAlgorithmT.forValue(details.cryptoAlg)); + listSa.add(saBuilder.build()); + } + builder.setSa(listSa); + } + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final IpsecState readValue) { + IpsecStateBuilder ipsecParentBuilder = (IpsecStateBuilder) parentBuilder; + ipsecParentBuilder.setHoldDown(readValue.getHoldDown()) + .setPolicy(readValue.getPolicy()) + .setProposal(readValue.getProposal()) + .setRedundancy(readValue.getRedundancy()) + .setSa(readValue.getSa()) + .addAugmentation(IpsecStateSpdAugmentation.class, + readValue.augmentation(IpsecStateSpdAugmentation.class)); + } + + static final class IpsecStateSaDetailsDumpExecutor + implements EntityDumpExecutor<IpsecSaDetailsReplyDump, Void>, JvppReplyConsumer { + + private final FutureJVppCore jvpp; + + IpsecStateSaDetailsDumpExecutor(final FutureJVppCore jvpp) { + this.jvpp = jvpp; + } + + @Nonnull + @Override + public IpsecSaDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params) + throws ReadFailedException { + IpsecSaDump dump = new IpsecSaDump(); + dump.saId = -1; + return getReplyForRead(jvpp.ipsecSaDump(dump).toCompletableFuture(), identifier); + } + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java new file mode 100644 index 000000000..45f54cdb8 --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizer.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.read; + +import com.google.common.base.Optional; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.vpp.jvpp.core.dto.IpsecSpdDetails; +import io.fd.vpp.jvpp.core.dto.IpsecSpdDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.IpsecSpdDump; +import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetails; +import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.IpsecSpdsDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdKey; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecSpdOperation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecTrafficDirection; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IpsecStateSpdCustomizer extends FutureJVppCustomizer + implements JvppReplyConsumer, InitializingListReaderCustomizer<Spd, SpdKey, SpdBuilder>, Ipv4Translator, + Ipv6Translator { + + private static final Logger LOG = LoggerFactory.getLogger(IpsecStateSpdCustomizer.class); + private final DumpCacheManager<IpsecSpdDetailsReplyDump, Void> ipsecSpdDetailsReplyDumpManager; + private final DumpCacheManager<IpsecSpdsDetailsReplyDump, Void> ipsecSpdsReplyDumpManager; + + public IpsecStateSpdCustomizer(final FutureJVppCore vppApi) { + super(vppApi); + IpsecStateSpdsReplyDumpExecutor spdsExecutor = + new IpsecStateSpdCustomizer.IpsecStateSpdsReplyDumpExecutor(vppApi); + this.ipsecSpdsReplyDumpManager = new DumpCacheManager.DumpCacheManagerBuilder<IpsecSpdsDetailsReplyDump, Void>() + .withExecutor(spdsExecutor) + .acceptOnly(IpsecSpdsDetailsReplyDump.class) + .build(); + + this.ipsecSpdDetailsReplyDumpManager = + new DumpCacheManager.DumpCacheManagerBuilder<IpsecSpdDetailsReplyDump, Void>() + .withExecutor( + new IpsecStateSpdCustomizer.IpsecStateSpdDetailsDumpExecutor(vppApi, spdsExecutor)) + .acceptOnly(IpsecSpdDetailsReplyDump.class) + .build(); + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Spd> id, + @Nonnull final Spd readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(id, readValue); + } + + @Nonnull + @Override + public SpdBuilder getBuilder(@Nonnull final InstanceIdentifier<Spd> id) { + return new SpdBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final SpdBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + SpdKey key = id.firstKeyOf(Spd.class); + builder.withKey(key); + builder.setSpdId(key.getSpdId()); + Optional<IpsecSpdDetailsReplyDump> spdDump = + ipsecSpdDetailsReplyDumpManager.getDump(id, ctx.getModificationCache()); + if (spdDump.isPresent()) { + List<SpdEntries> spdEntries = + spdDump.get().ipsecSpdDetails.stream().map(details -> translateDetailToEntry(details)) + .collect(Collectors.toList()); + builder.setSpdEntries(spdEntries); + } + } + + @Nonnull + @Override + public List<SpdKey> getAllIds(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final ReadContext context) + throws ReadFailedException { + List<SpdKey> spdKeys = new LinkedList<>(); + Optional<IpsecSpdsDetailsReplyDump> spdsDump = + ipsecSpdsReplyDumpManager.getDump(id, context.getModificationCache()); + if (spdsDump.isPresent()) { + spdKeys = spdsDump.get().ipsecSpdsDetails.stream().map(details -> new SpdKey(details.spdId)) + .collect(Collectors.toList()); + } + + LOG.debug("SPDs found in VPP: {}", spdKeys); + return spdKeys; + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Spd> readData) { + ((IpsecStateSpdAugmentationBuilder) builder).setSpd(readData); + } + + private SpdEntries translateDetailToEntry(final IpsecSpdDetails details) { + + SpdEntriesBuilder builder = new SpdEntriesBuilder(); + builder.setDirection(IpsecTrafficDirection.forValue(details.isOutbound)) + .setIsIpv6(ByteDataTranslator.INSTANCE.byteToBoolean(details.isIpv6)) + .setPriority(details.priority); + switch (details.policy) { + case 0: + builder.setOperation(IpsecSpdOperation.Bypass); + break; + case 1: + builder.setOperation(IpsecSpdOperation.Discard); + break; + case 3: + builder.setOperation(IpsecSpdOperation.Protect); + builder.setProtectSaId(details.saId); + break; + } + + if (builder.isIsIpv6()) { + processIpv6AddressRanges(builder, details); + } else { + processIpv4AddressRanges(builder, details); + } + + return builder.build(); + } + + private void processIpv4AddressRanges(final SpdEntriesBuilder builder, final IpsecSpdDetails details) { + if (details.localStartAddr != null && details.localStartAddr.length > 0) { + builder.setLaddrStart(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv4AddressNoZone(details.localStartAddr)).stringValue())); + } + if (details.localStopAddr != null && details.localStopAddr.length > 0) { + builder.setLaddrStop(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv4AddressNoZone(details.localStopAddr)).stringValue())); + } + if (details.remoteStartAddr != null && details.remoteStartAddr.length > 0) { + builder.setRaddrStart(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv4AddressNoZone(details.remoteStartAddr)).stringValue())); + } + if (details.remoteStopAddr != null && details.remoteStopAddr.length > 0) { + builder.setRaddrStop(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv4AddressNoZone(details.remoteStopAddr)).stringValue())); + } + } + + private void processIpv6AddressRanges(final SpdEntriesBuilder builder, final IpsecSpdDetails details) { + if (details.localStartAddr != null && details.localStartAddr.length > 0) { + builder.setLaddrStart(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv6AddressNoZone(details.localStartAddr)).stringValue())); + } + if (details.localStopAddr != null && details.localStopAddr.length > 0) { + builder.setLaddrStop(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv6AddressNoZone(details.localStopAddr)).stringValue())); + } + if (details.remoteStartAddr != null && details.remoteStartAddr.length > 0) { + builder.setRaddrStart(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv6AddressNoZone(details.remoteStartAddr)).stringValue())); + } + if (details.remoteStopAddr != null && details.remoteStopAddr.length > 0) { + builder.setRaddrStop(IpAddressBuilder.getDefaultInstance( + new IpAddressNoZone(arrayToIpv6AddressNoZone(details.remoteStopAddr)).stringValue())); + } + } + + public static class IpsecStateSpdDetailsDumpExecutor + implements EntityDumpExecutor<IpsecSpdDetailsReplyDump, Void>, JvppReplyConsumer { + private FutureJVppCore jvpp; + private IpsecStateSpdsReplyDumpExecutor spdsDumpExecutor; + + public IpsecStateSpdDetailsDumpExecutor( + final FutureJVppCore vppApi, final IpsecStateSpdsReplyDumpExecutor spdsDumpExecutor) { + this.jvpp = vppApi; + this.spdsDumpExecutor = spdsDumpExecutor; + } + + @Nonnull + @Override + public IpsecSpdDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params) + throws ReadFailedException { + IpsecSpdDetailsReplyDump fullReplyDump = new IpsecSpdDetailsReplyDump(); + fullReplyDump.ipsecSpdDetails = new LinkedList<>(); + + Optional<IpsecSpdsDetailsReplyDump> spdsReply = + Optional.of(spdsDumpExecutor.executeDump(identifier, params)); + IpsecSpdsDetailsReplyDump spdDump = spdsReply.get(); + for (IpsecSpdsDetails spdsDetail : spdDump.ipsecSpdsDetails) { + IpsecSpdDump dump = new IpsecSpdDump(); + dump.spdId = spdsDetail.spdId; + dump.saId = -1; + IpsecSpdDetailsReplyDump reply = + getReplyForRead(jvpp.ipsecSpdDump(dump).toCompletableFuture(), identifier); + fullReplyDump.ipsecSpdDetails.addAll(reply.ipsecSpdDetails); + } + + return fullReplyDump; + } + } + + private class IpsecStateSpdsReplyDumpExecutor implements EntityDumpExecutor<IpsecSpdsDetailsReplyDump, Void> { + private final FutureJVppCore jvpp; + + public IpsecStateSpdsReplyDumpExecutor( + final FutureJVppCore vppApi) { + this.jvpp = vppApi; + } + + @Nonnull + @Override + public IpsecSpdsDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params) + throws ReadFailedException { + return getReplyForRead(jvpp.ipsecSpdsDump(new IpsecSpdsDump()).toCompletableFuture(), identifier); + } + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java new file mode 100644 index 000000000..6886b9b5d --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizer.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKey; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Ikev2GlobalConfigurationCustomizer extends FutureJVppCustomizer + implements WriterCustomizer<IkeGlobalConfiguration>, JvppReplyConsumer { + public Ikev2GlobalConfigurationCustomizer(final FutureJVppCore vppApi) { + super(vppApi); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id, + @Nonnull final IkeGlobalConfiguration dataAfter, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + IpsecIkeGlobalConfAugmentation fileAUg = dataAfter.augmentation(IpsecIkeGlobalConfAugmentation.class); + if (fileAUg != null) { + if (fileAUg.getLocalKeyFile() != null) { + Ikev2SetLocalKey request = new Ikev2SetLocalKey(); + request.keyFile = fileAUg.getLocalKeyFile().getBytes(); + getReplyForWrite(getFutureJVpp().ikev2SetLocalKey(request).toCompletableFuture(), id); + } + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id, + @Nonnull final IkeGlobalConfiguration dataBefore, + @Nonnull final IkeGlobalConfiguration dataAfter, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + writeCurrentAttributes(id, dataAfter, writeContext); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<IkeGlobalConfiguration> id, + @Nonnull final IkeGlobalConfiguration dataBefore, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + // VPP doesn't support deletion of local key file + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java new file mode 100644 index 000000000..300ea6b8e --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizer.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDel; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuth; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTs; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.nio.ByteBuffer; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeGeneralPolicyProfileGrouping; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Ikev2PolicyCustomizer extends FutureJVppCustomizer + implements ListWriterCustomizer<Policy, PolicyKey>, JvppReplyConsumer, ByteDataTranslator, Ipv4Translator { + + public Ikev2PolicyCustomizer(final FutureJVppCore vppApi) { + super(vppApi); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel(); + request.isAdd = BYTE_TRUE; + request.name = dataAfter.getName().getBytes(); + getReplyForWrite(getFutureJVpp().ikev2ProfileAddDel(request).toCompletableFuture(), id); + addAuthorization(dataAfter, id); + addTrafficSelectors(dataAfter, id); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel(); + request.isAdd = BYTE_FALSE; + request.name = dataBefore.getName().getBytes(); + getReplyForWrite(getFutureJVpp().ikev2ProfileAddDel(request).toCompletableFuture(), id); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> id, @Nonnull final Policy dataBefore, + @Nonnull final Policy dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + addAuthorization(dataAfter, id); + addTrafficSelectors(dataAfter, id); + } + + private void addTrafficSelectors(final Policy dataAfter, final InstanceIdentifier<Policy> id) + throws WriteFailedException { + IpsecIkev2PolicyAugmentation aug = dataAfter.augmentation(IpsecIkev2PolicyAugmentation.class); + if (aug == null) { + return; + } + if (aug.getTrafficSelectors() != null) { + for (TrafficSelectors selector : aug.getTrafficSelectors()) { + Ikev2ProfileSetTs addTsRequest = new Ikev2ProfileSetTs(); + if (selector.getLocalAddressHigh() != null && selector.getLocalAddressLow() != null) { + addTsRequest.isLocal = BYTE_TRUE; + addTsRequest.startAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressLow().getIpv4Address().getValue())) + .getInt(); + addTsRequest.endAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressHigh().getIpv4Address().getValue())) + .getInt(); + if (selector.getLocalPortHigh() != null && selector.getLocalPortLow() != null) { + addTsRequest.startPort = selector.getLocalPortLow().getValue().shortValue(); + addTsRequest.endPort = selector.getLocalPortHigh().getValue().shortValue(); + } + } else if (selector.getRemoteAddressHigh() != null && selector.getRemoteAddressLow() != null) { + addTsRequest.isLocal = BYTE_FALSE; + addTsRequest.startAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressLow().getIpv4Address().getValue())) + .getInt(); + addTsRequest.endAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressHigh().getIpv4Address().getValue())) + .getInt(); + if (selector.getRemotePortHigh() != null && selector.getRemotePortLow() != null) { + addTsRequest.startPort = selector.getRemotePortLow().getValue().shortValue(); + addTsRequest.endPort = selector.getRemotePortHigh().getValue().shortValue(); + } + } + if (selector.getProtocol() != null) { + addTsRequest.proto = selector.getProtocol().byteValue(); + } + if (dataAfter.getName() != null) { + addTsRequest.name = dataAfter.getName().getBytes(); + } + getReplyForWrite(getFutureJVpp().ikev2ProfileSetTs(addTsRequest).toCompletableFuture(), id); + } + } + } + + private void addAuthorization(final Policy data, final InstanceIdentifier<Policy> id) + throws WriteFailedException { + Authentication auth = data.getAuthentication(); + if (auth != null) { + if (auth.isPresharedKey() != null && data.getPreSharedKey() != null) { + setProfilePreSharedKeyAuth(data.key().getName(), data.getPreSharedKey(), id); + } else if (auth.isRsaSignature() != null) { + IpsecIkev2PolicyAugmentation aug = data.augmentation(IpsecIkev2PolicyAugmentation.class); + if (aug != null && aug.getCertificate() != null) { + setProfileRSAAuth(data.key().getName(), aug.getCertificate(), id); + } + } + } + } + + private void setProfileRSAAuth(final String name, final String fileName, final InstanceIdentifier<Policy> id) + throws WriteFailedException { + Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth(); + request.name = name.getBytes(); + request.data = fileName.getBytes(); + request.authMethod = BYTE_TRUE; + getReplyForWrite(getFutureJVpp().ikev2ProfileSetAuth(request).toCompletableFuture(), id); + } + + private void setProfilePreSharedKeyAuth(final String name, + final IkeGeneralPolicyProfileGrouping.PreSharedKey preSharedKey, + final InstanceIdentifier<Policy> id) throws WriteFailedException { + final Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth(); + request.authMethod = BYTE_FALSE; + if (preSharedKey.getHexString() != null) { + request.isHex = BYTE_TRUE; + } + request.data = preSharedKey.stringValue().getBytes(); + request.name = name.getBytes(); + getReplyForWrite(getFutureJVpp().ikev2ProfileSetAuth(request).toCompletableFuture(), id); + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java new file mode 100644 index 000000000..4c11f1633 --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizer.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetId; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.FqdnString; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.identity.Rfc822AddressString; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Ikev2PolicyIdentityCustomizer extends FutureJVppCustomizer + implements WriterCustomizer<Identity>, JvppReplyConsumer, ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + public Ikev2PolicyIdentityCustomizer(final FutureJVppCore vppApi) { + super(vppApi); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id, + @Nonnull final Identity dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + String name = id.firstKeyOf(Policy.class).getName(); + if (dataAfter.getLocal() != null) { + setProfileId(id, name, dataAfter.getLocal().getIdentity(), true); + } + + if (dataAfter.getRemote() != null) { + setProfileId(id, name, dataAfter.getRemote().getIdentity(), false); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id, + @Nonnull final Identity dataBefore, + @Nonnull final Identity dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + writeCurrentAttributes(id, dataAfter, writeContext); + } + + private void setProfileId(final InstanceIdentifier<Identity> id, + final String profileName, + final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.Identity data, + final boolean isLocalId) throws WriteFailedException { + final Ikev2ProfileSetId request = new Ikev2ProfileSetId(); + request.name = profileName.getBytes(); + transformIdentityToRequest(data, request); + request.isLocal = isLocalId + ? BYTE_TRUE + : BYTE_FALSE; + getReplyForWrite(getFutureJVpp().ikev2ProfileSetId(request).toCompletableFuture(), id); + } + + private void transformIdentityToRequest( + final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.identity.grouping.Identity + identityData, final Ikev2ProfileSetId request) { + if (identityData instanceof Ipv4Address) { + request.idType = 1; + request.data = ipv4AddressNoZoneToArray(((Ipv4Address) identityData).getIpv4Address().getValue()); + } else if (identityData instanceof FqdnString) { + request.idType = 2; + request.data = ((FqdnString) identityData).getFqdnString().getValue().getBytes(); + } else if (identityData instanceof Rfc822AddressString) { + request.idType = 3; + request.data = ((Rfc822AddressString) identityData).getRfc822AddressString().getBytes(); + } else if (identityData instanceof Ipv6Address) { + request.idType = 5; + request.data = ipv6AddressNoZoneToArray(((Ipv6Address) identityData).getIpv6Address()); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Identity> id, + @Nonnull final Identity dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + // VPP doesn't support deletion of Ikev2 Profile ID + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java new file mode 100644 index 000000000..d7bbee32d --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizer.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.MultiNamingContext; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntry; +import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntryReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSadEntriesAugmentation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.ip.address.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ip.address.grouping.ip.address.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.Ah; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.AuthenticationAlgorithm; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.Esp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacMd596; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacSha196; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.EncryptionAlgorithm; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes128Cbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes192Cbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes256Cbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.DesCbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IpsecSadEntryCustomizer extends FutureJVppCustomizer + implements ListWriterCustomizer<SadEntries, SadEntriesKey>, + JvppReplyConsumer, ByteDataTranslator, Ipv6Translator, Ipv4Translator { + + private static final Logger LOG = LoggerFactory.getLogger(IpsecSadEntryCustomizer.class); + private MultiNamingContext sadEntryMapping; + + IpsecSadEntryCustomizer(final FutureJVppCore vppApi, final MultiNamingContext sadEntryMapping) { + super(vppApi); + this.sadEntryMapping = sadEntryMapping; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id, + @Nonnull final SadEntries dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + addDelEntry(id, dataAfter, writeContext, true); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id, + @Nonnull final SadEntries dataBefore, + @Nonnull final SadEntries dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + writeCurrentAttributes(id, dataAfter, writeContext); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<SadEntries> id, + @Nonnull final SadEntries dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + addDelEntry(id, dataBefore, writeContext, false); + } + + private void addDelEntry(final InstanceIdentifier<SadEntries> id, + final SadEntries dataAfter, + final WriteContext writeContext, boolean adding) throws WriteFailedException { + final IpsecSadAddDelEntry entry = new IpsecSadAddDelEntry(); + IpsecSadEntriesAugmentation augment = dataAfter.augmentation(IpsecSadEntriesAugmentation.class); + if (augment != null && augment.getSaId() != null) { + entry.sadId = augment.getSaId(); + } + if (dataAfter.getSpi() != null) { + entry.spi = dataAfter.getSpi().intValue(); + } + if (dataAfter.getAntiReplayWindow() != null) { + entry.useAntiReplay = dataAfter.getAntiReplayWindow() > 0 + ? BYTE_TRUE + : BYTE_FALSE; + } + + if (dataAfter.getSaMode() != null) { + entry.isTunnel = Integer.valueOf(dataAfter.getSaMode().getIntValue()).byteValue(); + } + entry.isAdd = adding + ? ByteDataTranslator.BYTE_TRUE + : ByteDataTranslator.BYTE_FALSE; + if (dataAfter.getEsp() != null) { + entry.protocol = 1; + fillEspAuthentication(entry, dataAfter.getEsp()); + fillEspEncryption(entry, dataAfter.getEsp()); + + } else if (dataAfter.getAh() != null) { + entry.protocol = 0; + fillAhAuthentication(entry, dataAfter.getAh()); + } + + fillAddresses(entry, dataAfter); + + LOG.debug("IPSec config change id={} request={}", id, entry); + final CompletionStage<IpsecSadAddDelEntryReply> ipsecSadEntryAddDellReplyFuture = + getFutureJVpp().ipsecSadAddDelEntry(entry); + getReplyForWrite(ipsecSadEntryAddDellReplyFuture.toCompletableFuture(), id); + if (adding) { + sadEntryMapping.addChild(dataAfter.key().getDirection().getName(), entry.sadId, + String.valueOf(dataAfter.key().getSpi()), writeContext.getMappingContext()); + } else { + sadEntryMapping + .removeChild(dataAfter.key().getDirection().getName(), String.valueOf(dataAfter.key().getSpi()), + writeContext.getMappingContext()); + } + } + + private void fillAhAuthentication(IpsecSadAddDelEntry targetEntry, Ah data) { + //0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512 + AuthenticationAlgorithm authAlg = data.getAuthenticationAlgorithm(); + if (authAlg != null) { + String integKey; + if (authAlg instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596) { + integKey = + ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596) authAlg) + .getHmacMd596().getKeyStr().stringValue(); + targetEntry.integrityAlgorithm = 1; + } else if (authAlg instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196) { + integKey = + ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196) authAlg) + .getHmacSha196().getKeyStr().stringValue(); + targetEntry.integrityAlgorithm = 2; + } else { + targetEntry.integrityAlgorithm = 0; + return; + } + targetEntry.integrityKey = integKey.getBytes(); + } + } + + private void fillEspAuthentication(IpsecSadAddDelEntry targetEntry, Esp data) { + //0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512 + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication + authAlg = data.getAuthentication(); + if (authAlg != null) { + String integKey; + if (authAlg.getAuthenticationAlgorithm() instanceof HmacMd596) { + integKey = ((HmacMd596) authAlg.getAuthenticationAlgorithm()).getHmacMd596().getKeyStr().stringValue(); + targetEntry.integrityAlgorithm = 1; + } else if (authAlg.getAuthenticationAlgorithm() instanceof HmacSha196) { + integKey = + ((HmacSha196) authAlg.getAuthenticationAlgorithm()).getHmacSha196().getKeyStr().stringValue(); + targetEntry.integrityAlgorithm = 2; + } else { + targetEntry.integrityAlgorithm = 0; + return; + } + targetEntry.integrityKey = integKey.getBytes(); + } + } + + private void fillEspEncryption(IpsecSadAddDelEntry targetEntry, Esp data) { + //0 = Null, 1 = AES-CBC-128, 2 = AES-CBC-192, 3 = AES-CBC-256, 4 = 3DES-CBC + if (data.getEncryption() != null && data.getEncryption().getEncryptionAlgorithm() != null) { + String cryptoKey = ""; + EncryptionAlgorithm encrAlg = data.getEncryption().getEncryptionAlgorithm(); + if (encrAlg instanceof Aes128Cbc) { + cryptoKey = ((Aes128Cbc) encrAlg).getAes128Cbc().getKeyStr().stringValue(); + targetEntry.cryptoAlgorithm = 1; + } else if (encrAlg instanceof Aes192Cbc) { + cryptoKey = ((Aes192Cbc) encrAlg).getAes192Cbc().getKeyStr().stringValue(); + targetEntry.cryptoAlgorithm = 2; + } else if (encrAlg instanceof Aes256Cbc) { + cryptoKey = ((Aes256Cbc) encrAlg).getAes256Cbc().getKeyStr().stringValue(); + targetEntry.cryptoAlgorithm = 3; + } else if (encrAlg instanceof DesCbc) { + cryptoKey = ((DesCbc) encrAlg).getDesCbc().getKeyStr().stringValue(); + targetEntry.cryptoAlgorithm = 4; + } else { + targetEntry.cryptoAlgorithm = 0; + return; + } + targetEntry.cryptoKey = cryptoKey.getBytes(); + } + } + + private void fillAddresses(IpsecSadAddDelEntry targetEntry, SadEntries data) { + if (data.getSourceAddress() != null && data.getSourceAddress().getIpAddress() != null) { + IpAddress sourceAddr = data.getSourceAddress().getIpAddress(); + if (sourceAddr instanceof Ipv4Address) { + Ipv4Address ipv4 = (Ipv4Address) sourceAddr; + targetEntry.isTunnelIpv6 = 0; + targetEntry.tunnelSrcAddress = ipv4AddressNoZoneToArray(ipv4.getIpv4Address().getValue()); + } else if (sourceAddr instanceof Ipv6Address) { + Ipv6Address ipv6 = (Ipv6Address) sourceAddr; + targetEntry.isTunnelIpv6 = 1; + targetEntry.tunnelSrcAddress = ipv6AddressNoZoneToArray(ipv6.getIpv6Address()); + } + } + + if (data.getDestinationAddress() != null && data.getDestinationAddress().getIpAddress() != null) { + IpAddress destAddr = data.getDestinationAddress().getIpAddress(); + + if (destAddr instanceof Ipv4Address) { + Ipv4Address ipv4 = (Ipv4Address) destAddr; + targetEntry.isTunnelIpv6 = 0; + targetEntry.tunnelDstAddress = ipv4AddressNoZoneToArray(ipv4.getIpv4Address().getValue()); + } else if (destAddr instanceof Ipv6Address) { + Ipv6Address ipv6 = (Ipv6Address) destAddr; + targetEntry.isTunnelIpv6 = 1; + targetEntry.tunnelDstAddress = ipv6AddressNoZoneToArray(ipv6.getIpv6Address()); + } + } + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java new file mode 100644 index 000000000..771cf676a --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizer.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDel; +import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntry; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class IpsecSpdCustomizer extends FutureJVppCustomizer + implements ListWriterCustomizer<Spd, SpdKey>, JvppReplyConsumer, ByteDataTranslator, + Ipv6Translator, Ipv4Translator { + + public IpsecSpdCustomizer(final FutureJVppCore vppApi) { + super(vppApi); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + IpsecSpdAddDel spdCreate = new IpsecSpdAddDel(); + spdCreate.isAdd = ByteDataTranslator.BYTE_TRUE; + spdCreate.spdId = dataAfter.getSpdId(); + getReplyForWrite(getFutureJVpp().ipsecSpdAddDel(spdCreate).toCompletableFuture(), id); + if (dataAfter.getSpdEntries() != null) { + for (SpdEntries entry : dataAfter.getSpdEntries()) { + addSpdEntry(id, dataAfter.getSpdId(), entry); + } + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + IpsecSpdAddDel spdDelete = new IpsecSpdAddDel(); + spdDelete.isAdd = ByteDataTranslator.BYTE_FALSE; + spdDelete.spdId = dataBefore.getSpdId(); + getReplyForWrite(getFutureJVpp().ipsecSpdAddDel(spdDelete).toCompletableFuture(), id); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Spd> id, @Nonnull final Spd dataBefore, + @Nonnull final Spd dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (dataAfter.getSpdEntries() != null) { + for (SpdEntries entry : dataAfter.getSpdEntries()) { + addSpdEntry(id, dataAfter.getSpdId(), entry); + } + } + } + + private void addSpdEntry(final InstanceIdentifier<Spd> id, int spdId, final SpdEntries entry) + throws WriteFailedException { + IpsecSpdAddDelEntry request = new IpsecSpdAddDelEntry(); + request.spdId = spdId; + request.isAdd = ByteDataTranslator.BYTE_TRUE; + IpsecSpdEntriesAugmentation entryAug = entry.augmentation(IpsecSpdEntriesAugmentation.class); + if (entryAug == null) { + return; + } + + if (entryAug.isIsIpv6() != null) { + request.isIpv6 = (byte) (entryAug.isIsIpv6() + ? 1 + : 0); + } + if (entryAug.getDirection() != null) { + request.isOutbound = (byte) entryAug.getDirection().getIntValue(); + } + + if (entryAug.getPriority() != null) { + request.priority = entryAug.getPriority(); + } + + if (entryAug.getOperation() != null) { + final String operation = entryAug.getOperation().getName(); + if (operation.equalsIgnoreCase("bypass")) { + request.policy = (byte) 0; + } else if (operation.equalsIgnoreCase("discard")) { + request.policy = (byte) 1; + } else if (operation.equalsIgnoreCase("protect")) { + request.policy = (byte) 3; + } + } + + if (entryAug.getLaddrStart() != null) { + if (entryAug.getLaddrStart().getIpv4Address() != null) { + request.localAddressStart = + ipv4AddressNoZoneToArray(entryAug.getLaddrStart().getIpv4Address().getValue()); + } else if (entryAug.getLaddrStart().getIpv6Address() != null) { + request.localAddressStart = ipv6AddressNoZoneToArray(entryAug.getLaddrStart().getIpv6Address()); + } + } + if (entryAug.getLaddrStop() != null) { + if (entryAug.getLaddrStop().getIpv4Address() != null) { + request.localAddressStop = + ipv4AddressNoZoneToArray(entryAug.getLaddrStop().getIpv4Address().getValue()); + } else if (entryAug.getLaddrStop().getIpv6Address() != null) { + request.localAddressStop = ipv6AddressNoZoneToArray(entryAug.getLaddrStop().getIpv6Address()); + } + } + if (entryAug.getRaddrStop() != null) { + if (entryAug.getRaddrStop().getIpv4Address() != null) { + request.remoteAddressStop = + ipv4AddressNoZoneToArray(entryAug.getRaddrStop().getIpv4Address().getValue()); + } else if (entryAug.getRaddrStop().getIpv6Address() != null) { + request.remoteAddressStop = ipv6AddressNoZoneToArray(entryAug.getRaddrStop().getIpv6Address()); + } + } + + if (entryAug.getRaddrStart() != null) { + if (entryAug.getRaddrStart().getIpv4Address() != null) { + request.remoteAddressStart = + ipv4AddressNoZoneToArray(entryAug.getRaddrStart().getIpv4Address().getValue()); + } else if (entryAug.getRaddrStart().getIpv6Address() != null) { + request.remoteAddressStart = ipv6AddressNoZoneToArray(entryAug.getRaddrStart().getIpv6Address()); + } + } + getReplyForWrite(getFutureJVpp().ipsecSpdAddDelEntry(request).toCompletableFuture(), id); + } +} diff --git a/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java new file mode 100644 index 000000000..8b164ac74 --- /dev/null +++ b/ipsec/ipsec-impl/src/main/java/io/fd/hc2vpp/ipsec/write/IpsecWriterFactory.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import io.fd.hc2vpp.common.translate.util.MultiNamingContext; +import io.fd.honeycomb.translate.impl.write.GenericListWriter; +import io.fd.honeycomb.translate.impl.write.GenericWriter; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSadEntriesAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.identity.Local; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.identity.Remote; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Sad; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.Ah; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.Esp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Encryption; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.md5._96.HmacMd596; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.sha1._96.HmacSha196; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._128.cbc.Aes128Cbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._192.cbc.Aes192Cbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._256.cbc.Aes256Cbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.des.cbc.DesCbc; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.grouping.DestinationAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.grouping.SourceAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Factory producing writers for IpSec plugin's data. + */ +public final class IpsecWriterFactory implements WriterFactory { + + private static final InstanceIdentifier<Ikev2> IKE2_ID = InstanceIdentifier.create(Ikev2.class); + private static final InstanceIdentifier<Ipsec> IPSEC_ID = InstanceIdentifier.create(Ipsec.class); + private static final InstanceIdentifier<Sad> SAD_ID = IPSEC_ID.child(Sad.class); + private static final InstanceIdentifier<SadEntries> SAD_ENTRIES_ID = SAD_ID.child(SadEntries.class); + private static final InstanceIdentifier<Spd> SPD_ID = IPSEC_ID.child(Spd.class); + + private final FutureJVppCore vppApi; + private MultiNamingContext sadEntriesMapping; + + @Inject + public IpsecWriterFactory(final FutureJVppCore vppApi, final MultiNamingContext sadEntriesMappingContext) { + this.vppApi = vppApi; + this.sadEntriesMapping = sadEntriesMappingContext; + } + + @Override + public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(SadEntries.class).child(SourceAddress.class), + InstanceIdentifier.create(SadEntries.class).child(DestinationAddress.class), + InstanceIdentifier.create(SadEntries.class).child(Ah.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.sha1._96.HmacSha196.class), + InstanceIdentifier.create(SadEntries.class).child(Ah.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.md5._96.HmacMd596.class), + InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Authentication.class) + .child(HmacSha196.class), + InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Authentication.class) + .child(HmacMd596.class), + InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class) + .child(Aes128Cbc.class), + InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class) + .child(Aes192Cbc.class), + InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class) + .child(Aes256Cbc.class), + InstanceIdentifier.create(SadEntries.class).child(Esp.class).child(Encryption.class) + .child(DesCbc.class), + InstanceIdentifier.create(SadEntries.class).augmentation(IpsecSadEntriesAugmentation.class)), + new GenericListWriter<>(SAD_ENTRIES_ID, new IpsecSadEntryCustomizer(vppApi, sadEntriesMapping))); + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Spd.class).child(SpdEntries.class), + InstanceIdentifier.create(Spd.class).child(SpdEntries.class) + .augmentation(IpsecSpdEntriesAugmentation.class)), + new GenericListWriter<>(SPD_ID, new IpsecSpdCustomizer(vppApi))); + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(IkeGlobalConfiguration.class) + .augmentation(IpsecIkeGlobalConfAugmentation.class)), + new GenericWriter<>(IKE2_ID.child(IkeGlobalConfiguration.class), + new Ikev2GlobalConfigurationCustomizer(vppApi))); + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Policy.class).child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication.class), + InstanceIdentifier.create(Policy.class).augmentation(IpsecIkev2PolicyAugmentation.class), + InstanceIdentifier.create(Policy.class).augmentation(IpsecIkev2PolicyAugmentation.class) + .child(TrafficSelectors.class)), + new GenericListWriter<>(IKE2_ID.child(Policy.class), new Ikev2PolicyCustomizer(vppApi))); + registry.subtreeAdd(Sets.newHashSet(InstanceIdentifier.create(Identity.class).child(Local.class), + InstanceIdentifier.create(Identity.class).child(Remote.class)), + new GenericWriter<>(IKE2_ID.child(Policy.class).child(Identity.class), + new Ikev2PolicyIdentityCustomizer(vppApi))); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java new file mode 100644 index 000000000..42817d42a --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.empty; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import io.fd.hc2vpp.ipsec.read.IpsecReaderFactory; +import io.fd.hc2vpp.ipsec.write.IpsecWriterFactory; +import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder; +import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.util.YangDAG; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.HashSet; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; + +public class IpsecModuleTest { + + @Bind + @Mock + private FutureJVppCore futureJVppCore; + + @Inject + private Set<WriterFactory> writerFactories = new HashSet<>(); + + @Inject + private Set<ReaderFactory> readerFactories = new HashSet<>(); + + @Before + public void setUp() { + initMocks(this); + Guice.createInjector(new IpsecModule(), BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testWriterFactories() throws Exception { + assertThat(writerFactories, is(not(empty()))); + final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(new YangDAG()); + writerFactories.stream().forEach(factory -> factory.init(registryBuilder)); + assertNotNull(registryBuilder.build()); + assertEquals(1, writerFactories.size()); + assertTrue(writerFactories.iterator().next() instanceof IpsecWriterFactory); + } + + @Test + public void testReaderFactories() throws Exception { + assertThat(readerFactories, is(not(empty()))); + final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder(new YangDAG()); + readerFactories.stream().forEach(factory -> factory.init(registryBuilder)); + assertNotNull(registryBuilder.build()); + assertEquals(1, readerFactories.size()); + assertTrue(readerFactories.iterator().next() instanceof IpsecReaderFactory); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java new file mode 100644 index 000000000..bce8a982a --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.helpers; + +import com.google.common.collect.ImmutableSet; +import io.fd.honeycomb.test.tools.annotations.InjectablesProcessor; +import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider; +import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext; + +public interface SchemaContextTestHelper extends InjectablesProcessor { + + @SchemaContextProvider + default ModuleInfoBackedContext getSchemaContext() { + return provideSchemaContextFor(ImmutableSet.of( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.$YangModuleInfoImpl + .getInstance(), + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.$YangModuleInfoImpl + .getInstance() + )); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java new file mode 100644 index 000000000..9b8f9157f --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.read; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.IpsecSaDetails; +import io.fd.vpp.jvpp.core.dto.IpsecSaDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.IpsecSaDump; +import java.util.LinkedList; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecStateBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.state.grouping.Sa; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class IpsecStateCustomizerTest extends ReaderCustomizerTest<IpsecState, IpsecStateBuilder> + implements ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static InstanceIdentifier<IpsecState> IPSEC_STATE_ID = InstanceIdentifier.create(IpsecState.class); + private static final String LOCAL_ADDR_START = "192.168.11.1"; + private static final String REMOTE_ADDR_START = "192.168.22.1"; + private static final String TUNNEL_SRC_ADDR = LOCAL_ADDR_START; + private static final String TUNNEL_DST_ADDR = REMOTE_ADDR_START; + private static final int REPLY_WINDOW = 88; + private static final int SA_ID = 10; + private static final int SPI = 1001; + private static final int CRYPTO_ALG = 1; + private static final String CRYPTO_KEY = "123456789"; + private static final int INTEG_ALG = 2; + private static final String INTEG_KEY = "987654321"; + private static final int PROTOCOL = 1; + private static final int LAST_SEQ_INB = 8; + private static final int HOLD_DOWN = 88; + + public IpsecStateCustomizerTest() { + super(IpsecState.class, IpsecStateBuilder.class); + } + + @Override + protected ReaderCustomizer<IpsecState, IpsecStateBuilder> initCustomizer() { + return new IpsecStateCustomizer(api); + } + + @Override + protected void setUp() throws Exception { + final IpsecSaDetailsReplyDump saDetailsReply = new IpsecSaDetailsReplyDump(); + LinkedList<IpsecSaDetails> saDetails = new LinkedList<>(); + IpsecSaDetails saDetail = new IpsecSaDetails(); + saDetail.spi = SPI; + saDetail.saId = SA_ID; + saDetail.cryptoAlg = CRYPTO_ALG; + saDetail.cryptoKey = CRYPTO_KEY.getBytes(); + saDetail.integAlg = INTEG_ALG; + saDetail.integKey = INTEG_KEY.getBytes(); + saDetail.isTunnel = BYTE_TRUE; + saDetail.isTunnelIp6 = BYTE_FALSE; + saDetail.protocol = PROTOCOL; + saDetail.lastSeqInbound = LAST_SEQ_INB; + saDetail.replayWindow = REPLY_WINDOW; + saDetail.useAntiReplay = BYTE_TRUE; + saDetail.tunnelSrcAddr = ipv4AddressNoZoneToArray(TUNNEL_SRC_ADDR); + saDetail.tunnelDstAddr = ipv4AddressNoZoneToArray(TUNNEL_DST_ADDR); + saDetails.add(saDetail); + saDetailsReply.ipsecSaDetails = saDetails; + IpsecSaDump saDump = new IpsecSaDump(); + saDump.saId = SA_ID; + when(api.ipsecSaDump(any())).thenReturn(future(saDetailsReply)); + } + + @Test + public void testReadSa() throws ReadFailedException { + final IpsecStateBuilder builder = new IpsecStateBuilder(); + getCustomizer().readCurrentAttributes(IPSEC_STATE_ID, builder, ctx); + assertEquals(builder.getSa().size(), 1); + Sa sa = builder.getSa().get(0); + assertEquals(sa.getAntiReplayWindow().intValue(), REPLY_WINDOW); + assertEquals(sa.getAuthenticationAlgorithm().getIntValue(), INTEG_ALG); + assertEquals(sa.getEncryptionAlgorithm().getIntValue(), CRYPTO_ALG); + assertEquals(sa.getSpi().intValue(), SPI); + } + + @Test + public void testMerge() throws Exception { + final IpsecStateBuilder parentBuilder = new IpsecStateBuilder(); + final IpsecStateBuilder builderForNewdata = new IpsecStateBuilder(); + builderForNewdata.setHoldDown(new Long(HOLD_DOWN)); + getCustomizer().merge(parentBuilder, builderForNewdata.build()); + assertEquals(parentBuilder.getHoldDown().intValue(), HOLD_DOWN); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java new file mode 100644 index 000000000..bf08fa8c3 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.read; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.vpp.jvpp.core.dto.IpsecSpdDetails; +import io.fd.vpp.jvpp.core.dto.IpsecSpdDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetails; +import io.fd.vpp.jvpp.core.dto.IpsecSpdsDetailsReplyDump; +import java.util.LinkedList; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecStateSpdAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.Spd; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.SpdKey; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ipsec.state.spd.SpdEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecState; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class IpsecStateSpdCustomizerTest extends ReaderCustomizerTest<Spd, SpdBuilder> + implements ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static InstanceIdentifier<Spd> SPD_IID = InstanceIdentifier.create(IpsecState.class) + .augmentation(IpsecStateSpdAugmentation.class).child(Spd.class, new SpdKey(10)); + + private static final String LOCAL_ADDR_START = "192.168.11.1"; + private static final String LOCAL_ADDR_END = "192.168.11.255"; + private static final short PORT_START = 0; + private static final short PORT_END = Short.MAX_VALUE; + private static final int POLICY_PROTECT = 3; + private static final int SPD_ID = 10; + private static final int SA_ID = 10; + private static final int PROTOCOL = 1; + private static final int PRIORITY = 100; + + public IpsecStateSpdCustomizerTest() { + super(Spd.class, SpdBuilder.class); + } + + @Override + protected ReaderCustomizer<Spd, SpdBuilder> initCustomizer() { + return new IpsecStateSpdCustomizer(api); + } + + @Override + protected void setUp() throws Exception { + final IpsecSpdDetailsReplyDump spdDetailsReply = new IpsecSpdDetailsReplyDump(); + LinkedList<IpsecSpdDetails> spdDetails = new LinkedList<>(); + IpsecSpdDetails spdDetail = new IpsecSpdDetails(); + spdDetail.isIpv6 = BYTE_FALSE; + spdDetail.isOutbound = BYTE_TRUE; + spdDetail.spdId = SPD_ID; + spdDetail.protocol = PROTOCOL; + spdDetail.localStartAddr = ipv4AddressNoZoneToArray(LOCAL_ADDR_START); + spdDetail.localStopAddr = ipv4AddressNoZoneToArray(LOCAL_ADDR_END); + spdDetail.localStartPort = PORT_START; + spdDetail.localStopPort = PORT_END; + spdDetail.policy = POLICY_PROTECT; + spdDetail.saId = SA_ID; + spdDetail.priority = PRIORITY; + spdDetails.add(spdDetail); + spdDetailsReply.ipsecSpdDetails = spdDetails; + when(api.ipsecSpdDump(any())).thenReturn(future(spdDetailsReply)); + + IpsecSpdsDetailsReplyDump spdsReply = new IpsecSpdsDetailsReplyDump(); + IpsecSpdsDetails spdsDetail = new IpsecSpdsDetails(); + spdsDetail.spdId = SPD_ID; + spdsReply.ipsecSpdsDetails.add(spdsDetail); + when(api.ipsecSpdsDump(any())).thenReturn(future(spdsReply)); + } + + @Test + public void testReadSpd() throws ReadFailedException { + final SpdBuilder builder = new SpdBuilder(); + getCustomizer().readCurrentAttributes(SPD_IID, builder, ctx); + assertEquals(builder.getSpdEntries().size(), 1); + SpdEntries spdEntries = builder.getSpdEntries().get(0); + assertEquals(spdEntries.getDirection().getName(), "outbound"); + assertEquals(spdEntries.getPriority().intValue(), PRIORITY); + } + + @Test + public void testMerge() throws Exception { + final IpsecStateSpdAugmentationBuilder parentBuilder = new IpsecStateSpdAugmentationBuilder(); + final IpsecStateSpdAugmentationBuilder builderForNewData = new IpsecStateSpdAugmentationBuilder(); + SpdBuilder spdBuilder = new SpdBuilder(); + spdBuilder.setSpdId(SPD_ID); + getCustomizer().merge(parentBuilder, spdBuilder.build()); + assertEquals(parentBuilder.getSpd().size(), 1); + assertEquals(parentBuilder.getSpd().get(0).getSpdId().intValue(), SPD_ID); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java new file mode 100644 index 000000000..cf9e8b102 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.write.WriterCustomizerTest; +import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKey; +import io.fd.vpp.jvpp.core.dto.Ikev2SetLocalKeyReply; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkeGlobalConfAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfiguration; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.IkeGlobalConfigurationBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Ikev2GlobalConfigurationCustomizerTest extends WriterCustomizerTest + implements SchemaContextTestHelper { + InstanceIdentifier<IkeGlobalConfiguration> IID = InstanceIdentifier.create(Ikev2.class) + .child(IkeGlobalConfiguration.class); + private Ikev2GlobalConfigurationCustomizer customizer; + private static final String LOCAL_KEY_FILE = "/home/localadmin/certs/client-key.pem"; + + @Override + protected void setUpTest() throws Exception { + customizer = new Ikev2GlobalConfigurationCustomizer(api); + when(api.ikev2SetLocalKey(any())).thenReturn(future(new Ikev2SetLocalKeyReply())); + } + + @Test + public void testWrite() throws WriteFailedException { + IkeGlobalConfigurationBuilder dataAfterBuilder = new IkeGlobalConfigurationBuilder(); + IpsecIkeGlobalConfAugmentationBuilder augBuilder = new IpsecIkeGlobalConfAugmentationBuilder(); + augBuilder.setLocalKeyFile(LOCAL_KEY_FILE); + dataAfterBuilder.addAugmentation(IpsecIkeGlobalConfAugmentation.class, augBuilder.build()); + customizer.writeCurrentAttributes(IID, dataAfterBuilder.build(), writeContext); + Ikev2SetLocalKey request = new Ikev2SetLocalKey(); + request.keyFile = LOCAL_KEY_FILE.getBytes(); + verify(api).ikev2SetLocalKey(request); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java new file mode 100644 index 000000000..0c7b65f1b --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.write.WriterCustomizerTest; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper; +import io.fd.honeycomb.test.tools.HoneycombTestRunner; +import io.fd.honeycomb.test.tools.annotations.InjectTestData; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDel; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileAddDelReply; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuth; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetAuthReply; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTs; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetTsReply; +import java.nio.ByteBuffer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecIkev2PolicyAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.ikev2.policy.aug.grouping.TrafficSelectors; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.policy.profile.grouping.Authentication; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +@RunWith(HoneycombTestRunner.class) +public class Ikev2PolicyCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper, + ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static final String IKEV2_PATH = "/hc2vpp-ietf-ipsec:ikev2"; + private Ikev2PolicyCustomizer customizer; + + @Override + protected void setUpTest() throws Exception { + customizer = new Ikev2PolicyCustomizer(api); + when(api.ikev2ProfileAddDel(any())).thenReturn(future(new Ikev2ProfileAddDelReply())); + when(api.ikev2ProfileSetTs(any())).thenReturn(future(new Ikev2ProfileSetTsReply())); + when(api.ikev2ProfileSetAuth(any())).thenReturn(future(new Ikev2ProfileSetAuthReply())); + } + + @Test + public void testWrite(@InjectTestData(resourcePath = "/ikev2/addIkev2Profile.json", id = IKEV2_PATH) Ikev2 ikev2) + throws WriteFailedException { + Policy policy = ikev2.getPolicy().get(0); + customizer.writeCurrentAttributes(getId(policy.getName()), policy, writeContext); + Ikev2ProfileAddDel profileAddrequest = new Ikev2ProfileAddDel(); + profileAddrequest.isAdd = BYTE_TRUE; + profileAddrequest.name = policy.getName().getBytes(); + + verify(api).ikev2ProfileAddDel(profileAddrequest); + verify(api).ikev2ProfileSetTs(translateTStoRequest(policy.augmentation(IpsecIkev2PolicyAugmentation.class) + .getTrafficSelectors().get(0), policy.getName())); + verify(api).ikev2ProfileSetAuth(translateAuthToRequest(policy)); + } + + @Test + public void testUpdate( + @InjectTestData(resourcePath = "/ikev2/addDelProfile_before.json", id = IKEV2_PATH) Ikev2 ikev2Before, + @InjectTestData(resourcePath = "/ikev2/addDelProfile_after.json", id = IKEV2_PATH) Ikev2 ikev2After) + throws WriteFailedException { + final Policy before = ikev2Before.getPolicy().get(0); + final Policy after = ikev2After.getPolicy().get(0); + customizer.updateCurrentAttributes(getId(before.getName()), before, after, writeContext); + + verify(api, times(0)).ikev2ProfileAddDel(any()); + verify(api).ikev2ProfileSetTs(translateTStoRequest(after.augmentation(IpsecIkev2PolicyAugmentation.class) + .getTrafficSelectors().get(0), after.getName())); + verify(api).ikev2ProfileSetAuth(translateAuthToRequest(after)); + } + + @Test + public void testDelete(@InjectTestData(resourcePath = "/ikev2/addIkev2Profile.json", id = IKEV2_PATH) Ikev2 ikev2) + throws WriteFailedException { + Policy policy = ikev2.getPolicy().get(0); + customizer.deleteCurrentAttributes(getId(policy.getName()), policy, writeContext); + final Ikev2ProfileAddDel request = new Ikev2ProfileAddDel(); + request.name = policy.getName().getBytes(); + request.isAdd = BYTE_FALSE; + verify(api).ikev2ProfileAddDel(request); + verify(api, times(0)).ikev2ProfileSetTs(any()); + verify(api, times(0)).ikev2ProfileSetAuth(any()); + } + + private InstanceIdentifier<Policy> getId(final String name) { + return InstanceIdentifier.create(Ikev2.class).child(Policy.class, new PolicyKey(name)); + } + + private Ikev2ProfileSetTs translateTStoRequest(final TrafficSelectors selector, final String policyName) { + Ikev2ProfileSetTs addTsRequest = new Ikev2ProfileSetTs(); + if (selector.getLocalAddressHigh() != null && selector.getLocalAddressLow() != null) { + addTsRequest.isLocal = ByteDataTranslator.BYTE_TRUE; + addTsRequest.startAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressLow().getIpv4Address().getValue())).getInt(); + addTsRequest.endAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getLocalAddressHigh().getIpv4Address().getValue())) + .getInt(); + if (selector.getLocalPortHigh() != null && selector.getLocalPortLow() != null) { + addTsRequest.startPort = selector.getLocalPortLow().getValue().shortValue(); + addTsRequest.endPort = selector.getLocalPortHigh().getValue().shortValue(); + } + } else if (selector.getRemoteAddressHigh() != null && selector.getRemoteAddressLow() != null) { + addTsRequest.isLocal = ByteDataTranslator.BYTE_FALSE; + addTsRequest.startAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressLow().getIpv4Address().getValue())) + .getInt(); + addTsRequest.endAddr = ByteBuffer + .wrap(ipv4AddressNoZoneToArray(selector.getRemoteAddressHigh().getIpv4Address().getValue())) + .getInt(); + if (selector.getRemotePortHigh() != null && selector.getRemotePortLow() != null) { + addTsRequest.startPort = selector.getRemotePortLow().getValue().shortValue(); + addTsRequest.endPort = selector.getRemotePortHigh().getValue().shortValue(); + } + } + if (selector.getProtocol() != null) { + addTsRequest.proto = selector.getProtocol().byteValue(); + } + if (policyName != null) { + addTsRequest.name = policyName.getBytes(); + } + return addTsRequest; + } + + private Ikev2ProfileSetAuth translateAuthToRequest(Policy policy) { + final Ikev2ProfileSetAuth request = new Ikev2ProfileSetAuth(); + Authentication auth = policy.getAuthentication(); + if (auth != null) { + request.name = policy.getName().getBytes(); + if (auth.isPresharedKey() != null && policy.getPreSharedKey() != null) { + request.authMethod = ByteDataTranslator.BYTE_FALSE; + if (policy.getPreSharedKey().getHexString() != null) { + request.isHex = ByteDataTranslator.BYTE_TRUE; + } + request.data = policy.getPreSharedKey().stringValue().getBytes(); + } else if (auth.isRsaSignature() != null) { + IpsecIkev2PolicyAugmentation aug = policy.augmentation(IpsecIkev2PolicyAugmentation.class); + if (aug != null && aug.getCertificate() != null) { + request.data = aug.getCertificate().getBytes(); + request.authMethod = ByteDataTranslator.BYTE_TRUE; + } + } + } + return request; + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java new file mode 100644 index 000000000..bb8f0d762 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.write.WriterCustomizerTest; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper; +import io.fd.honeycomb.test.tools.HoneycombTestRunner; +import io.fd.honeycomb.test.tools.annotations.InjectTestData; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetId; +import io.fd.vpp.jvpp.core.dto.Ikev2ProfileSetIdReply; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ikev2; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ike.general.policy.profile.grouping.Identity; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.Policy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ikev2.PolicyKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +@RunWith(HoneycombTestRunner.class) +public class Ikev2PolicyIdentityCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper, + ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static final String POLICY_NAME = "testPolicy"; + private static final String IPV4_TYPE_DATA = "192.168.123.22"; + private static final String IPV6_TYPE_DATA = "2001:DB8:0:0:8:800:200C:417A"; + private static final String FQDN_TYPE_DATA = "vpp.home"; + private static final String RFC822_TYPE_DATA = "rfc822@example.com"; + private static final String IDENTITY_PATH = + "/hc2vpp-ietf-ipsec:ikev2/hc2vpp-ietf-ipsec:policy[hc2vpp-ietf-ipsec:name='" + POLICY_NAME + + "']/hc2vpp-ietf-ipsec:identity"; + private Ikev2PolicyIdentityCustomizer customizer; + + @Override + protected void setUpTest() throws Exception { + customizer = new Ikev2PolicyIdentityCustomizer(api); + when(api.ikev2ProfileSetId(any())).thenReturn(future(new Ikev2ProfileSetIdReply())); + } + + @Test + public void testWriteLocalIpv4( + @InjectTestData(resourcePath = "/ikev2/identity/identity_local_ipv4.json", id = IDENTITY_PATH) Identity identity) + throws WriteFailedException { + customizer.writeCurrentAttributes(getId(), identity, writeContext); + Ikev2ProfileSetId request = new Ikev2ProfileSetId(); + request.name = POLICY_NAME.getBytes(); + request.idType = (byte) 1; + request.isLocal = BYTE_TRUE; + request.data = ipv4AddressNoZoneToArray(IPV4_TYPE_DATA); + verify(api).ikev2ProfileSetId(request); + } + + @Test + public void testWriteRemoteFqdn( + @InjectTestData(resourcePath = "/ikev2/identity/identity_remote_fqdn.json", id = IDENTITY_PATH) Identity identity) + throws WriteFailedException { + customizer.writeCurrentAttributes(getId(), identity, writeContext); + Ikev2ProfileSetId request = new Ikev2ProfileSetId(); + request.name = POLICY_NAME.getBytes(); + request.idType = (byte) 2; + request.isLocal = BYTE_FALSE; + request.data = FQDN_TYPE_DATA.getBytes(); + verify(api).ikev2ProfileSetId(request); + } + + @Test + public void testWriteLocalIpv6( + @InjectTestData(resourcePath = "/ikev2/identity/identity_remote_ipv6.json", id = IDENTITY_PATH) Identity identity) + throws WriteFailedException { + customizer.writeCurrentAttributes(getId(), identity, writeContext); + Ikev2ProfileSetId request = new Ikev2ProfileSetId(); + request.name = POLICY_NAME.getBytes(); + request.idType = (byte) 5; + request.isLocal = BYTE_FALSE; + request.data = ipv6AddressNoZoneToArray(new Ipv6Address(IPV6_TYPE_DATA)); + verify(api).ikev2ProfileSetId(request); + } + + @Test + public void testUpdate( + @InjectTestData(resourcePath = "/ikev2/identity/identity_local_ipv4.json", id = IDENTITY_PATH) Identity before, + @InjectTestData(resourcePath = "/ikev2/identity/identity_local_rfc822.json", id = IDENTITY_PATH) Identity after) + throws WriteFailedException { + customizer.updateCurrentAttributes(getId(), before, after, writeContext); + Ikev2ProfileSetId request = new Ikev2ProfileSetId(); + request.name = POLICY_NAME.getBytes(); + request.idType = (byte) 3; + request.isLocal = BYTE_TRUE; + request.data = RFC822_TYPE_DATA.getBytes(); + verify(api).ikev2ProfileSetId(request); + } + + private InstanceIdentifier<Identity> getId() { + return InstanceIdentifier.create(Ikev2.class).child(Policy.class, new PolicyKey(POLICY_NAME)) + .child(Identity.class); + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java new file mode 100644 index 000000000..912f50f27 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.write.WriterCustomizerTest; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.MultiNamingContext; +import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper; +import io.fd.honeycomb.test.tools.HoneycombTestRunner; +import io.fd.honeycomb.test.tools.annotations.InjectTestData; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntry; +import io.fd.vpp.jvpp.core.dto.IpsecSadAddDelEntryReply; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeEncryptionAlgorithmT; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IkeIntegrityAlgorithmT; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.IpsecTrafficDirection; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.KeyStringGrouping; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Sad; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.AhBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.AuthenticationAlgorithm; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.EspBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Authentication; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.AuthenticationBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.Encryption; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.EncryptionBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacMd596Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.HmacSha196Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes128CbcBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes192CbcBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.Aes256CbcBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.DesCbcBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sad.SadEntriesKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +@RunWith(HoneycombTestRunner.class) +public class IpsecSadEntryCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper, + ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static final String SAD_PATH = "/hc2vpp-ietf-ipsec:ipsec/hc2vpp-ietf-ipsec:sad"; + private static final InstanceIdentifier<Sad> SAD_IID = + InstanceIdentifier.create(Ipsec.class).child(Sad.class); + private static final String INTEG_KEY = "0123456789012346"; + private static final String CRYPTO_KEY = "9876543210987654"; + private static final String TNL_SRC_ADDR = "192.168.1.1"; + private static final String TNL_DST_ADDR = "192.168.1.2"; + private static final int SPI_1002 = 1002; + private static final int SAD_ID = 10; + + private IpsecSadEntryCustomizer customizer; + @Mock + private MultiNamingContext namingCntext; + + @Override + protected void setUpTest() throws Exception { + customizer = new IpsecSadEntryCustomizer(api, namingCntext); + when(api.ipsecSadAddDelEntry(any())).thenReturn(future(new IpsecSadAddDelEntryReply())); + } + + @Test + public void testWrite(@InjectTestData(resourcePath = "/sadEntries/addDelSadEntry.json", id = SAD_PATH) Sad sad) + throws WriteFailedException { + final SadEntries data = sad.getSadEntries().get(0); + final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry(); + request.isAdd = BYTE_TRUE; + request.spi = SPI_1002; + request.sadId = SAD_ID; + request.isTunnel = BYTE_TRUE; + request.isTunnelIpv6 = BYTE_FALSE; + request.integrityKey = INTEG_KEY.getBytes(); + request.cryptoKey = CRYPTO_KEY.getBytes(); + request.useAntiReplay = 0; + request.tunnelSrcAddress = ipv4AddressNoZoneToArray(TNL_SRC_ADDR); + request.tunnelDstAddress = ipv4AddressNoZoneToArray(TNL_DST_ADDR); + + // ESP + request.protocol = BYTE_TRUE; //0 = AH, 1 = ESP + // - auth MD5-96 + // - crypto Aes-Cbc-128 + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596, + IkeEncryptionAlgorithmT.EncrAesCbc128, request); + // - crypto Aes-Cbc-192 + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596, + IkeEncryptionAlgorithmT.EncrAesCbc192, request); + // - crypto Aes-Cbc-256 + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596, + IkeEncryptionAlgorithmT.EncrAesCbc256, request); + // - crypto DesCbc + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacMd596, + IkeEncryptionAlgorithmT.EncrDes, request); + + // - auth SHA1-96 + // - crypto Aes-Cbc-128 + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196, + IkeEncryptionAlgorithmT.EncrAesCbc128, request); + // - crypto Aes-Cbc-192 + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196, + IkeEncryptionAlgorithmT.EncrAesCbc192, request); + // - crypto Aes-Cbc-256 + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196, + IkeEncryptionAlgorithmT.EncrAesCbc256, request); + // - crypto DesCbc + testEspAuthEncrCombination(data, IkeIntegrityAlgorithmT.AuthHmacSha196, + IkeEncryptionAlgorithmT.EncrDes, request); + + // AH + request.protocol = BYTE_FALSE; + request.cryptoAlgorithm = 0; + request.cryptoKey = null; + request.cryptoKeyLength = 0; + // - auth SHA1-96 + testAhAuthorization(data, IkeIntegrityAlgorithmT.AuthHmacSha196, request); + // - auth MD5-96 + testAhAuthorization(data, IkeIntegrityAlgorithmT.AuthHmacMd596, request); + } + + @Test + public void testUpdate( + @InjectTestData(resourcePath = "/sadEntries/addDelSadEntry_Ipv6_before.json", id = SAD_PATH) Sad relaysBefore, + @InjectTestData(resourcePath = "/sadEntries/addDelSadEntry_Ipv6_after.json", id = SAD_PATH) Sad relayAfter) + throws WriteFailedException { + final SadEntries before = relaysBefore.getSadEntries().get(0); + final SadEntries after = relayAfter.getSadEntries().get(0); + final Long spi = after.getSpi(); + customizer.updateCurrentAttributes(getId(IpsecTrafficDirection.Outbound, spi), before, after, writeContext); + final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry(); + request.isAdd = BYTE_TRUE; + request.spi = SPI_1002; + request.sadId = SAD_ID; + request.protocol = BYTE_FALSE; + request.isTunnel = BYTE_FALSE; + request.isTunnelIpv6 = BYTE_TRUE; + request.integrityAlgorithm = 1; + request.integrityKey = INTEG_KEY.getBytes(); + request.useAntiReplay = BYTE_TRUE; + request.tunnelSrcAddress = ipv6AddressNoZoneToArray(Ipv6Address.getDefaultInstance("2001::11")); + request.tunnelDstAddress = ipv6AddressNoZoneToArray(Ipv6Address.getDefaultInstance("2001::12")); + verify(api).ipsecSadAddDelEntry(request); + } + + @Test + public void testDelete(@InjectTestData(resourcePath = "/sadEntries/delSadEntry.json", id = SAD_PATH) Sad sad) + throws WriteFailedException { + final SadEntries data = sad.getSadEntries().get(0); + final Long spi = data.getSpi(); + customizer.deleteCurrentAttributes(getId(IpsecTrafficDirection.Outbound, spi), data, writeContext); + final IpsecSadAddDelEntry request = new IpsecSadAddDelEntry(); + request.isAdd = BYTE_FALSE; + request.spi = SPI_1002; + request.sadId = SAD_ID; + verify(api).ipsecSadAddDelEntry(request); + } + + private InstanceIdentifier<SadEntries> getId(final IpsecTrafficDirection direction, final Long spi) { + return SAD_IID.child(SadEntries.class, new SadEntriesKey(direction, spi)); + } + + private void testAhAuthorization(final SadEntries otherData, final IkeIntegrityAlgorithmT authAlg, + final IpsecSadAddDelEntry request) throws WriteFailedException { + SadEntriesBuilder builder = new SadEntriesBuilder(otherData); + builder.setEsp(null); + AhBuilder ahBuilder = new AhBuilder(); + ahBuilder.setAuthenticationAlgorithm(getAhAuthentication(authAlg)); + builder.setAh(ahBuilder.build()); + customizer.writeCurrentAttributes(getId(IpsecTrafficDirection.Outbound, Integer.toUnsignedLong(SPI_1002)), + builder.build(), writeContext); + verify(api).ipsecSadAddDelEntry(request); + } + + private void testEspAuthEncrCombination(final SadEntries otherData, final IkeIntegrityAlgorithmT authAlg, + final IkeEncryptionAlgorithmT encrAlg, final IpsecSadAddDelEntry request) + throws WriteFailedException { + SadEntriesBuilder builder = new SadEntriesBuilder(otherData); + builder.setAh(null); + EspBuilder espBuilder = new EspBuilder(); + espBuilder.setAuthentication(getEspAuthentication(authAlg)) + .setEncryption(getEspEncryption(encrAlg)); + builder.setEsp(espBuilder.build()); + customizer.writeCurrentAttributes(getId(IpsecTrafficDirection.Outbound, Integer.toUnsignedLong(SPI_1002)), + builder.build(), writeContext); + + if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc128) { + request.cryptoAlgorithm = 1; + } else if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc192) { + request.cryptoAlgorithm = 2; + } else if (encrAlg == IkeEncryptionAlgorithmT.EncrAesCbc256) { + request.cryptoAlgorithm = 3; + } else if (encrAlg == IkeEncryptionAlgorithmT.EncrDes) { + request.cryptoAlgorithm = 4; + } else { + request.cryptoAlgorithm = 0; + } + + if (authAlg == IkeIntegrityAlgorithmT.AuthHmacMd596) { + request.integrityAlgorithm = 1; + } else if (authAlg == IkeIntegrityAlgorithmT.AuthHmacSha196) { + request.integrityAlgorithm = 2; + } else { + request.integrityAlgorithm = 0; + } + + verify(api).ipsecSadAddDelEntry(request); + } + + private Encryption getEspEncryption(IkeEncryptionAlgorithmT alg) { + if (alg == IkeEncryptionAlgorithmT.EncrAesCbc128) { + return new EncryptionBuilder().setEncryptionAlgorithm(new Aes128CbcBuilder(). + setAes128Cbc( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._128.cbc.Aes128CbcBuilder() + .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY)) + .build()).build()).build(); + } else if (alg == IkeEncryptionAlgorithmT.EncrAesCbc192) { + return new EncryptionBuilder().setEncryptionAlgorithm(new Aes192CbcBuilder(). + setAes192Cbc( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._192.cbc.Aes192CbcBuilder() + .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY)) + .build()).build()).build(); + } else if (alg == IkeEncryptionAlgorithmT.EncrAesCbc256) { + return new EncryptionBuilder().setEncryptionAlgorithm(new Aes256CbcBuilder(). + setAes256Cbc( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.aes._256.cbc.Aes256CbcBuilder() + .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY)) + .build()).build()).build(); + } else if (alg == IkeEncryptionAlgorithmT.EncrDes) { + return new EncryptionBuilder().setEncryptionAlgorithm(new DesCbcBuilder().setDesCbc( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.encryption.encryption.algorithm.des.cbc.DesCbcBuilder() + .setKeyStr(new KeyStringGrouping.KeyStr(CRYPTO_KEY)) + .build()).build()).build(); + } + + return null; + } + + private Authentication getEspAuthentication(IkeIntegrityAlgorithmT alg) { + if (alg == IkeIntegrityAlgorithmT.AuthHmacSha196) { + return new AuthenticationBuilder().setAuthenticationAlgorithm(new HmacSha196Builder().setHmacSha196( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.sha1._96.HmacSha196Builder() + .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build()).build(); + } else if (alg == IkeIntegrityAlgorithmT.AuthHmacMd596) { + return new AuthenticationBuilder().setAuthenticationAlgorithm(new HmacMd596Builder().setHmacMd596( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.esp.grouping.esp.authentication.authentication.algorithm.hmac.md5._96.HmacMd596Builder() + .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build()).build(); + } + return null; + } + + private AuthenticationAlgorithm getAhAuthentication(IkeIntegrityAlgorithmT alg) { + if (alg == IkeIntegrityAlgorithmT.AuthHmacSha196) { + return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacSha196Builder() + .setHmacSha196( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.sha1._96.HmacSha196Builder() + .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build(); + } else if (alg == IkeIntegrityAlgorithmT.AuthHmacMd596) { + return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.HmacMd596Builder() + .setHmacMd596( + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.sa.ah.grouping.ah.authentication.algorithm.hmac.md5._96.HmacMd596Builder() + .setKeyStr(new KeyStringGrouping.KeyStr(INTEG_KEY)).build()).build(); + } + return null; + } +} diff --git a/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java new file mode 100644 index 000000000..a4b294002 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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. + */ + +package io.fd.hc2vpp.ipsec.write; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.hc2vpp.common.test.write.WriterCustomizerTest; +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.ipsec.helpers.SchemaContextTestHelper; +import io.fd.honeycomb.test.tools.HoneycombTestRunner; +import io.fd.honeycomb.test.tools.annotations.InjectTestData; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDel; +import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntry; +import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelEntryReply; +import io.fd.vpp.jvpp.core.dto.IpsecSpdAddDelReply; +import java.util.Collections; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.ipsec.rev181213.IpsecSpdEntriesAugmentation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.Ipsec; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.Spd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.SpdKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipsec.rev181214.ipsec.spd.SpdEntriesBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +@RunWith(HoneycombTestRunner.class) +public class IpsecSpdCustomizerTest extends WriterCustomizerTest implements SchemaContextTestHelper, + ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static final int SPD_ID = 10; + private static final String IPSEC_PATH = "/hc2vpp-ietf-ipsec:ipsec"; + private IpsecSpdCustomizer customizer; + + @Override + protected void setUpTest() throws Exception { + customizer = new IpsecSpdCustomizer(api); + when(api.ipsecSpdAddDel(any())).thenReturn(future(new IpsecSpdAddDelReply())); + when(api.ipsecSpdAddDelEntry(any())).thenReturn(future(new IpsecSpdAddDelEntryReply())); + } + + @Test + public void testWrite(@InjectTestData(resourcePath = "/spdEntries/addDelSpd.json", id = IPSEC_PATH) Ipsec ipsec) + throws WriteFailedException { + Spd spd = ipsec.getSpd().get(0); + customizer.writeCurrentAttributes(getSpdId(SPD_ID), spd, writeContext); + final IpsecSpdAddDel createSpdRequest = new IpsecSpdAddDel(); + createSpdRequest.isAdd = BYTE_TRUE; + createSpdRequest.spdId = SPD_ID; + + verify(api).ipsecSpdAddDel(createSpdRequest); + verify(api).ipsecSpdAddDelEntry(translateSpdEntry(spd.getSpdEntries().get(0), SPD_ID, true)); + verify(api).ipsecSpdAddDelEntry(translateSpdEntry(spd.getSpdEntries().get(1), SPD_ID, true)); + } + + @Test + public void testUpdate( + @InjectTestData(resourcePath = "/spdEntries/addDelSpd_before.json", id = IPSEC_PATH) Ipsec ipsecBefore, + @InjectTestData(resourcePath = "/spdEntries/addDelSpd_after.json", id = IPSEC_PATH) Ipsec ipsecAfter) + throws WriteFailedException { + Spd before = ipsecBefore.getSpd().get(0); + Spd after = ipsecAfter.getSpd().get(0); + customizer.updateCurrentAttributes(getSpdId(SPD_ID), before, after, writeContext); + verify(api).ipsecSpdAddDelEntry(translateSpdEntry(after.getSpdEntries().get(0), SPD_ID, true)); + } + + @Test + public void testDelete() + throws WriteFailedException { + SpdBuilder spdBuilder = new SpdBuilder(); + spdBuilder.setSpdId(SPD_ID) + .withKey(new SpdKey(SPD_ID)) + .setSpdEntries(Collections.singletonList(new SpdEntriesBuilder().build())); + customizer.deleteCurrentAttributes(getSpdId(SPD_ID), spdBuilder.build(), writeContext); + IpsecSpdAddDel request = new IpsecSpdAddDel(); + request.spdId = SPD_ID; + request.isAdd = BYTE_FALSE; + verify(api).ipsecSpdAddDel(request); + } + + private InstanceIdentifier<Spd> getSpdId(final int spdId) { + return InstanceIdentifier.create(Ipsec.class).child(Spd.class, new SpdKey(spdId)); + } + + private IpsecSpdAddDelEntry translateSpdEntry(final SpdEntries entry, int spdId, boolean isAdd) { + IpsecSpdAddDelEntry request = new IpsecSpdAddDelEntry(); + request.spdId = spdId; + request.isAdd = isAdd + ? BYTE_TRUE + : BYTE_FALSE; + IpsecSpdEntriesAugmentation aug = entry.augmentation(IpsecSpdEntriesAugmentation.class); + if (aug != null) { + if (aug.isIsIpv6() != null) { + request.isIpv6 = (byte) (aug.isIsIpv6() + ? 1 + : 0); + } + + if (aug.getDirection() != null) { + request.isOutbound = (byte) aug.getDirection().getIntValue(); + } + + if (aug.getPriority() != null) { + request.priority = aug.getPriority(); + } + + if (aug.getOperation() != null) { + final String operation = aug.getOperation().getName(); + if (operation.equalsIgnoreCase("bypass")) { + request.policy = (byte) 0; + } else if (operation.equalsIgnoreCase("discard")) { + request.policy = (byte) 1; + } else if (operation.equalsIgnoreCase("protect")) { + request.policy = (byte) 3; + } + } + + if (aug.getLaddrStart() != null) { + if (aug.getLaddrStart().getIpv4Address() != null) { + request.localAddressStart = + ipv4AddressNoZoneToArray(aug.getLaddrStart().getIpv4Address().getValue()); + } else if (aug.getLaddrStart().getIpv6Address() != null) { + request.localAddressStart = ipv6AddressNoZoneToArray(aug.getLaddrStart().getIpv6Address()); + } + } + + if (aug.getLaddrStop() != null) { + if (aug.getLaddrStop().getIpv4Address() != null) { + request.localAddressStop = ipv4AddressNoZoneToArray(aug.getLaddrStop().getIpv4Address().getValue()); + } else if (aug.getLaddrStop().getIpv6Address() != null) { + request.localAddressStop = ipv6AddressNoZoneToArray(aug.getLaddrStop().getIpv6Address()); + } + } + + if (aug.getRaddrStop() != null) { + if (aug.getRaddrStop().getIpv4Address() != null) { + request.remoteAddressStop = + ipv4AddressNoZoneToArray(aug.getRaddrStop().getIpv4Address().getValue()); + } else if (aug.getRaddrStop().getIpv6Address() != null) { + request.remoteAddressStop = ipv6AddressNoZoneToArray(aug.getRaddrStop().getIpv6Address()); + } + } + + if (aug.getRaddrStart() != null) { + if (aug.getRaddrStart().getIpv4Address() != null) { + request.remoteAddressStart = + ipv4AddressNoZoneToArray(aug.getRaddrStart().getIpv4Address().getValue()); + } else if (aug.getRaddrStart().getIpv6Address() != null) { + request.remoteAddressStart = ipv6AddressNoZoneToArray(aug.getRaddrStart().getIpv6Address()); + } + } + } + return request; + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json new file mode 100644 index 000000000..ac5f8c797 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_after.json @@ -0,0 +1,25 @@ +{ + "ikev2": { + "policy": [ + { + "name": "testPolicy", + "lifetime": 0, + "connection-type": "both", + "authentication" : { + "rsa-signature" : "true" + }, + "certificate": "/home/localadmin/certs/server-cert.pem", + "traffic-selectors": [ + { + "ts-name":"TS1", + "protocol":0, + "remote-address-low":"192.168.124.0", + "remote-address-high":"192.168.124.255", + "remote-port-low":0, + "remote-port-high":65535 + } + ] + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json new file mode 100644 index 000000000..3dfa39345 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/addDelProfile_before.json @@ -0,0 +1,25 @@ +{ + "ikev2": { + "policy": [ + { + "name": "testPolicy", + "lifetime": 0, + "connection-type": "both", + "authentication" : { + "preshared-key" : "true" + }, + "pre-shared-key": "0123456789012345", + "traffic-selectors": [ + { + "ts-name":"TS1", + "protocol":0, + "local-address-low":"192.168.124.0", + "local-address-high":"192.168.124.255", + "local-port-low":0, + "local-port-high":65535 + } + ] + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json b/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json new file mode 100644 index 000000000..3dfa39345 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/addIkev2Profile.json @@ -0,0 +1,25 @@ +{ + "ikev2": { + "policy": [ + { + "name": "testPolicy", + "lifetime": 0, + "connection-type": "both", + "authentication" : { + "preshared-key" : "true" + }, + "pre-shared-key": "0123456789012345", + "traffic-selectors": [ + { + "ts-name":"TS1", + "protocol":0, + "local-address-low":"192.168.124.0", + "local-address-high":"192.168.124.255", + "local-port-low":0, + "local-port-high":65535 + } + ] + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json new file mode 100644 index 000000000..f068bd78b --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_ipv4.json @@ -0,0 +1,8 @@ +{ + "identity" : { + "local": + { + "ipv4-address": "192.168.123.22" + } + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json new file mode 100644 index 000000000..6e152d9c4 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_local_rfc822.json @@ -0,0 +1,8 @@ +{ + "identity" : { + "local": + { + "rfc822-address-string": "rfc822@example.com" + } + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json new file mode 100644 index 000000000..514f84116 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_fqdn.json @@ -0,0 +1,8 @@ +{ + "identity" : { + "remote": + { + "fqdn-string": "vpp.home" + } + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json new file mode 100644 index 000000000..0674d357f --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/ikev2/identity/identity_remote_ipv6.json @@ -0,0 +1,8 @@ +{ + "identity" : { + "remote": + { + "ipv6-address": "2001:DB8:0:0:8:800:200C:417A" + } + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json new file mode 100644 index 000000000..c522ba2de --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry.json @@ -0,0 +1,32 @@ +{ + "sad": { + "sad-entries": [ + { + "spi": 1002, + "direction": "outbound", + "sa-id": 10, + "security-protocol": "esp", + "sa-mode": "tunnel", + "esp": { + "authentication": { + "hmac-sha1-96": { + "key-str": "0123456789012346" + } + }, + "encryption": { + "aes-128-cbc": { + "key-str": "9876543210987654" + } + } + }, + "source-address": { + "ipv4-address": "192.168.1.1" + }, + "destination-address": { + "ipv4-address": "192.168.1.2" + }, + "anti-replay-window": 0 + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json new file mode 100644 index 000000000..fa618a391 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_after.json @@ -0,0 +1,25 @@ +{ + "sad": { + "sad-entries": [ + { + "spi": 1002, + "direction": "inbound", + "sa-id": 10, + "security-protocol": "ah", + "sa-mode": "transport", + "ah": { + "hmac-md5-96": { + "key-str": "0123456789012346" + } + }, + "source-address": { + "ipv6-address": "2001::11" + }, + "destination-address": { + "ipv6-address": "2001::12" + }, + "anti-replay-window": 32 + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json new file mode 100644 index 000000000..a88a14600 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/addDelSadEntry_Ipv6_before.json @@ -0,0 +1,32 @@ +{ + "sad": { + "sad-entries": [ + { + "spi": 1002, + "direction": "outbound", + "sa-id": 10, + "security-protocol": "esp", + "sa-mode": "tunnel", + "esp": { + "authentication": { + "hmac-sha1-96": { + "key-str": "0123456789012346" + } + }, + "encryption": { + "aes-128-cbc": { + "key-str": "9876543210987654" + } + } + }, + "source-address": { + "ipv6-address": "2001::1" + }, + "destination-address": { + "ipv6-address": "2001::10" + }, + "anti-replay-window": 32 + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json b/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json new file mode 100644 index 000000000..23998d60f --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/sadEntries/delSadEntry.json @@ -0,0 +1,11 @@ +{ + "sad": { + "sad-entries": [ + { + "spi": 1002, + "direction": "outbound", + "sa-id": 10 + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json new file mode 100644 index 000000000..85fe81d0d --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd.json @@ -0,0 +1,31 @@ +{ + "ipsec" : { + "spd": [ + { + "spd-id": 10, + "spd-entries": [ + { + "name": "test", + "priority":100, + "direction":"outbound", + "operation":"bypass", + "laddr-start":"192.168.124.0", + "laddr-stop":"192.168.124.255", + "raddr-start":"192.168.125.0", + "raddr-stop":"192.168.125.255" + }, + { + "name": "TestSPDEntryIpv6", + "priority":100, + "direction":"inbound", + "operation":"bypass", + "laddr-start":"2001::1", + "laddr-stop":"2001::100", + "raddr-start":"2001::101", + "raddr-stop":"2001::200" + } + ] + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json new file mode 100644 index 000000000..600dde46a --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_after.json @@ -0,0 +1,21 @@ +{ + "ipsec" : { + "spd": [ + { + "spd-entries": [ + { + "name": "TestSPDEntryUpdate", + "priority":80, + "direction":"inbound", + "operation":"bypass", + "laddr-start":"2001::1", + "laddr-stop":"2001::100", + "raddr-start":"2001::101", + "raddr-stop":"2001::200" + } + ], + "spd-id": 10 + } + ] + } +} diff --git a/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json new file mode 100644 index 000000000..be14bd6f9 --- /dev/null +++ b/ipsec/ipsec-impl/src/test/resources/spdEntries/addDelSpd_before.json @@ -0,0 +1,21 @@ +{ + "ipsec" : { + "spd": [ + { + "spd-entries": [ + { + "name": "TestSPDEntryUpdate", + "priority":100, + "direction":"outbound", + "operation":"discard", + "laddr-start":"192.168.124.0", + "laddr-stop":"192.168.124.255", + "raddr-start":"192.168.125.0", + "raddr-stop":"192.168.125.255" + } + ], + "spd-id": 10 + } + ] + } +} diff --git a/ipsec/pom.xml b/ipsec/pom.xml new file mode 100644 index 000000000..471ade96e --- /dev/null +++ b/ipsec/pom.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2019 PANTHEON.tech. + + 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. +--> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>io.fd.hc2vpp.common</groupId> + <artifactId>hc2vpp-parent</artifactId> + <version>1.19.01-SNAPSHOT</version> + <relativePath>../common/hc2vpp-parent</relativePath> + </parent> + + <groupId>io.fd.hc2vpp.ipsec</groupId> + <artifactId>ipsec-aggregator</artifactId> + <version>1.19.01-SNAPSHOT</version> + <name>${project.artifactId}</name> + <packaging>pom</packaging> + <modelVersion>4.0.0</modelVersion> + <prerequisites> + <maven>3.1.1</maven> + </prerequisites> + <description>Aggregator for Hc2vpp IPSec plugin</description> + + <modules> + <module>ipsec-api</module> + <module>ipsec-impl</module> + </modules> + + <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build --> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> +</project> @@ -57,5 +57,6 @@ <module>bgp</module> <module>mpls</module> <module>srv6</module> + <module>ipsec</module> </modules> </project> diff --git a/vpp-integration/minimal-distribution/pom.xml b/vpp-integration/minimal-distribution/pom.xml index 286bfda47..ef3e37e99 100644 --- a/vpp-integration/minimal-distribution/pom.xml +++ b/vpp-integration/minimal-distribution/pom.xml @@ -67,6 +67,7 @@ io.fd.hc2vpp.policer.PolicerModule, io.fd.hc2vpp.mpls.MplsModule, io.fd.hc2vpp.srv6.Srv6Module, + io.fd.hc2vpp.ipsec.IpsecModule <!-- Nsh module by default disabled, because it needs vpp-nsh plugin, which is not part of vpp codebase.--> // io.fd.hc2vpp.vppnsh.impl.VppNshModule, <!-- iOAM module by default disabled, because it needs ioam plugin (not part of vpp codebase.)--> @@ -191,5 +192,10 @@ <artifactId>bgp-prefix-sid</artifactId> <version>${hc2vpp.bgp.version}</version> </dependency> + <dependency> + <groupId>io.fd.hc2vpp.ipsec</groupId> + <artifactId>ipsec-impl</artifactId> + <version>${project.version}</version> + </dependency> </dependencies> </project> |