From 26589d440f332fe52238fa258d7d7b58df43eee5 Mon Sep 17 00:00:00 2001 From: Tibor Král Date: Wed, 14 Nov 2018 18:20:02 +0100 Subject: HC2VPP-87: Expose IPSEC management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib13a2cdba5a0902581c455de67cc0ee64d20598d Signed-off-by: Tibor Král --- .../java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java | 83 ++++++ .../ipsec/helpers/SchemaContextTestHelper.java | 35 +++ .../ipsec/read/IpsecStateCustomizerTest.java | 113 ++++++++ .../ipsec/read/IpsecStateSpdCustomizerTest.java | 116 +++++++++ .../Ikev2GlobalConfigurationCustomizerTest.java | 60 +++++ .../ipsec/write/Ikev2PolicyCustomizerTest.java | 167 ++++++++++++ .../write/Ikev2PolicyIdentityCustomizerTest.java | 119 +++++++++ .../ipsec/write/IpsecSadEntryCustomizerTest.java | 287 +++++++++++++++++++++ .../hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java | 175 +++++++++++++ 9 files changed, 1155 insertions(+) create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/IpsecModuleTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/helpers/SchemaContextTestHelper.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateCustomizerTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/read/IpsecStateSpdCustomizerTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2GlobalConfigurationCustomizerTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyCustomizerTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/Ikev2PolicyIdentityCustomizerTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSadEntryCustomizerTest.java create mode 100644 ipsec/ipsec-impl/src/test/java/io/fd/hc2vpp/ipsec/write/IpsecSpdCustomizerTest.java (limited to 'ipsec/ipsec-impl/src/test/java/io/fd') 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 writerFactories = new HashSet<>(); + + @Inject + private Set 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 + implements ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static InstanceIdentifier 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 initCustomizer() { + return new IpsecStateCustomizer(api); + } + + @Override + protected void setUp() throws Exception { + final IpsecSaDetailsReplyDump saDetailsReply = new IpsecSaDetailsReplyDump(); + LinkedList 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 + implements ByteDataTranslator, Ipv4Translator, Ipv6Translator { + + private static InstanceIdentifier 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 initCustomizer() { + return new IpsecStateSpdCustomizer(api); + } + + @Override + protected void setUp() throws Exception { + final IpsecSpdDetailsReplyDump spdDetailsReply = new IpsecSpdDetailsReplyDump(); + LinkedList 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 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 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 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_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 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 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; + } +} -- cgit 1.2.3-korg