DR AAF CADI integration 14/82814/6
authorefiacor <fiachra.corcoran@est.tech>
Tue, 26 Mar 2019 14:29:01 +0000 (14:29 +0000)
committerefiacor <fiachra.corcoran@est.tech>
Tue, 26 Mar 2019 14:29:01 +0000 (14:29 +0000)
Change-Id: I01548882f813e4029dddf7ddee2af12472163761
Issue-ID: DMAAP-1016
Signed-off-by: efiacor <fiachra.corcoran@est.tech>
54 files changed:
datarouter-docker-compose/src/main/resources/database/sql_init_01.sql
datarouter-docker-compose/src/main/resources/docker-compose.yml
datarouter-docker-compose/src/main/resources/node_data/aaf_certs/org.onap.dmaap-dr.keyfile [new file with mode: 0755]
datarouter-docker-compose/src/main/resources/node_data/node.properties
datarouter-docker-compose/src/main/resources/prov_data/aaf_certs/org.onap.dmaap-dr.keyfile [new file with mode: 0755]
datarouter-docker-compose/src/main/resources/prov_data/addSubscriber.txt
datarouter-docker-compose/src/main/resources/prov_data/provserver.properties
datarouter-node/aaf_certs/org.onap.dmaap-dr.keyfile [new file with mode: 0755]
datarouter-node/pom.xml
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DRNodeCadiFilter.java [new file with mode: 0644]
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DeliveryTask.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DestInfo.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/IsFrom.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/LogManager.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfigManager.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeMain.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServlet.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/PathUtil.java [new file with mode: 0644]
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/ProvData.java
datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/SubnetMatcher.java
datarouter-node/src/main/resources/drNodeCadi.properties [new file with mode: 0644]
datarouter-node/src/main/resources/node.properties
datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DRNodeCadiFilterTest.java [new file with mode: 0644]
datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DeliveryQueueTest.java
datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DeliveryTest.java
datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeConfigTest.java
datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServletTest.java
datarouter-prov/aaf_certs/org.onap.dmaap-dr.keyfile [new file with mode: 0755]
datarouter-prov/pom.xml
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/BaseServlet.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServlet.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/FeedServlet.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/Main.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscribeServlet.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServlet.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Feed.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Subscription.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DB.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilter.java [new file with mode: 0644]
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/LogfileLoader.java
datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/PasswordProcessor.java [new file with mode: 0644]
datarouter-prov/src/main/resources/drProvCadi.properties [new file with mode: 0644]
datarouter-prov/src/main/resources/misc/sql_init_01.sql
datarouter-prov/src/main/resources/provserver.properties
datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DRFeedsServletTest.java
datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/DrServletTestBase.java
datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/FeedServletTest.java
datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscribeServletTest.java
datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/SubscriptionServletTest.java
datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilterTest.java [new file with mode: 0644]
datarouter-prov/src/test/resources/create.sql
datarouter-prov/src/test/resources/h2Database.properties
pom.xml

index 14c59a6..83dfd0b 100644 (file)
@@ -4,7 +4,7 @@ CREATE TABLE FEEDS (
     FEEDID         INT UNSIGNED NOT NULL PRIMARY KEY,
     GROUPID        INT(10) UNSIGNED NOT NULL DEFAULT 0,
     NAME           VARCHAR(255) NOT NULL,
-    VERSION        VARCHAR(20) NOT NULL,
+    VERSION        VARCHAR(20) NULL,
     DESCRIPTION    VARCHAR(1000),
     BUSINESS_DESCRIPTION VARCHAR(1000) DEFAULT NULL,
     AUTH_CLASS     VARCHAR(32) NOT NULL,
@@ -16,13 +16,14 @@ CREATE TABLE FEEDS (
     DELETED        BOOLEAN DEFAULT FALSE,
     LAST_MOD       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED      BOOLEAN DEFAULT FALSE,
-    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    AAF_INSTANCE   VARCHAR(256)
 );
 
 CREATE TABLE FEED_ENDPOINT_IDS (
     FEEDID        INT UNSIGNED NOT NULL,
-    USERID        VARCHAR(20) NOT NULL,
-    PASSWORD      VARCHAR(32) NOT NULL
+    USERID        VARCHAR(60) NOT NULL,
+    PASSWORD      VARCHAR(100) NOT NULL
 );
 
 CREATE TABLE FEED_ENDPOINT_ADDRS (
@@ -35,8 +36,9 @@ CREATE TABLE SUBSCRIPTIONS (
     FEEDID                      INT UNSIGNED NOT NULL,
     GROUPID                     INT(10) UNSIGNED NOT NULL DEFAULT 0,
     DELIVERY_URL                VARCHAR(256),
-    DELIVERY_USER               VARCHAR(20),
-    DELIVERY_PASSWORD           VARCHAR(32),
+    FOLLOW_REDIRECTS            TINYINT(1) NOT NULL DEFAULT 0,
+    DELIVERY_USER               VARCHAR(60),
+    DELIVERY_PASSWORD           VARCHAR(100),
     DELIVERY_USE100             BOOLEAN DEFAULT FALSE,
     METADATA_ONLY               BOOLEAN DEFAULT FALSE,
     SUBSCRIBER                  VARCHAR(8) NOT NULL,
@@ -45,8 +47,9 @@ CREATE TABLE SUBSCRIPTIONS (
     LAST_MOD                    TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED                   BOOLEAN DEFAULT FALSE,
     PRIVILEGED_SUBSCRIBER       BOOLEAN DEFAULT FALSE,
+    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     DECOMPRESS                  BOOLEAN DEFAULT FALSE,
-    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    AAF_INSTANCE                VARCHAR(256)
 
 );
 
@@ -89,7 +92,7 @@ CREATE TABLE LOG_RECORDS (
 CREATE TABLE INGRESS_ROUTES (
     SEQUENCE  INT UNSIGNED NOT NULL,
     FEEDID    INT UNSIGNED NOT NULL,
-    USERID    VARCHAR(20),
+    USERID    VARCHAR(50),
     SUBNET    VARCHAR(44),
     NODESET   INT UNSIGNED NOT NULL
 );
@@ -144,6 +147,6 @@ INSERT INTO PARAMETERS VALUES
     ('PROV_MAXFEED_COUNT',  '10000'),
     ('PROV_MAXSUB_COUNT',   '100000'),
     ('PROV_REQUIRE_CERT', 'false'),
-    ('PROV_REQUIRE_SECURE', 'false'),
+    ('PROV_REQUIRE_SECURE', 'true'),
     ('_INT_VALUES', 'LOGROLL_INTERVAL|PROV_MAXFEED_COUNT|PROV_MAXSUB_COUNT|DELIVERY_INIT_RETRY_INTERVAL|DELIVERY_MAX_RETRY_INTERVAL|DELIVERY_RETRY_RATIO|DELIVERY_MAX_AGE|DELIVERY_FILE_PROCESS_INTERVAL')
     ;
index 8784ee6..bd4726a 100644 (file)
@@ -68,7 +68,7 @@ services:
   datarouter-subscriber:
     image: nexus3.onap.org:10001/onap/dmaap/datarouter-subscriber
     container_name: subscriber-node
-    hostname: subscriber.com
+    hostname: dmaap-dr-subscriber
     ports:
     - "7070:7070"
     volumes:
@@ -76,7 +76,7 @@ services:
     networks:
       testing_net:
         aliases:
-        - subscriber.com
+        - dmaap-dr-subscriber
 
   mariadb_container:
     image: mariadb:10.2.14
diff --git a/datarouter-docker-compose/src/main/resources/node_data/aaf_certs/org.onap.dmaap-dr.keyfile b/datarouter-docker-compose/src/main/resources/node_data/aaf_certs/org.onap.dmaap-dr.keyfile
new file mode 100755 (executable)
index 0000000..85bfa61
--- /dev/null
@@ -0,0 +1,27 @@
+j4IkjDmzOE_ZdHuN_cePYmySXrhmqM4WuGp86_RTiBlJ1TTvUaP_SOSZOqH0fxjk32gRvxJ01_iO
+mLtbQ-wZKk-fwCK_o6xrXJcN0G_Y8VGK2OMeqypm98ji25CSMvTdFLaohdPJwiRNMdmwwyF5q1Od
+pKviCISBlQ49ytwy3Mv0x7aV3kjkDWSgpx9TiMbWoAKlddcdQMUTEMh0CT0nLGv9uhwmRQ4I8UuE
+IzvR1Rit9HayMlXFND6n0IWggYqtAeRV-8wDrI2rAXGOrfLF0RC5-c0Wd0N000BWXvsT_nCYBCM6
+ffA5eAKCJmOVjJFzQTRXJq7Zhwij0CtEPgqqaipKUQhHaft9xeKXW3SPhREIn75F2u2uCcU1sNmd
+ytAk7yBPwdEcCQD-KVE9ZB3_57H0WIEr45SpU5ZePJkt2YV85H2Tlc_hGK18gTAcvGqDO3qELmV5
+SBHX5X_ZNL93mOkt37R0SGRdMZVIPJXNTgl4fGAsapvU7Y7sGMYrf2Ea0D-3hctk-aOKuuPEI1Ug
+0lqKjghJdvHYRFbm4C_7H-ai7UcBuixBd54Mp-hyBX-gjnFZuMHazFX2toKNe9RgDXIavHzTfF-l
+8fjdQpTplc2ECLINf-X6gs7w0zPYv04kLKixwlFff4ZocoxelGDEBlYYGNNxQBZvQtUX_dZetXF1
+VPNnwTB7Sp0fqaXR2aVaZNFSZYeL7VdxkiT0becNRa9QE9s2gU7oO_KTE8JyAiJyO-ojAvSUi-p_
+rq2Ivmab_L4t6GwMpv-EmRcntUQ_PM4s_XvJL2RmmSPWoNvbgCS0IilpYi2CPnEEgxqX37-Unx8m
+tYoNkiN-j9rA3Hr4EjEhrbOLf2wAh6RUeULerBpLKnf0Ans6UhjT7XVDaNvzxtAE-GrUCKHQ0ml2
+P_vzDBlGKobaRo-WQzQA-mZKGo1W4Q-qwFdusUflgfJ7iTrvw62jn30f4xGZcaP5Oa-9JvdZJggW
+1UvAM-85LdjGTxuI9KXbqRLWZk46B-UF7mDOce6dbRXjY48bZWIHEXcpzPQg6QA02cO10TN5K89V
+qXeCnz03ePf0u6YhMAOt5xiUvJpd1y_WI0jh4SH2dT26SegcuRTVLnEG0aL6ClypObwj3FLB1Pek
+UESqziiG4mQf_rzBAdPqcjbP8oeM2-mz09VYNyUOQ-7gk6bMAMWVqBx0uDxgIwUzr2UMbahB2Kg6
+9V7yE7obAKZa8x5oMiDGnvgjL9QeHwhUsNbwhhgqTDnB10vj4gh8RkNK8OsxQ53Nofj2PQZfY0GJ
+a6It7DCmnAgQ9N51RvCeodmmK9Zh3n_zoxt8gA-eV8zbidXZYQwYWx6ai7ooP7yol2bE_TLDDY9l
+_oYO_db73wSmqgTvoAdmrQGO4NI_g2iYN-Gd4XK4V_xgYPKyY5tHNSd4OKr_UuYiSioyNxE4IK1t
+zWyJ3tUXAyeq_ZjUDjabsnGnxmgujShRfK-rBh_1AapY3Oh99-aehETtcXihUmFX4lohowniWTA3
+MF1MMlRM5N1phF7xFgkAaZJfkQ-inqgWYvQ9XuW0LfumN4QeO8KnfknukSSgZ86PYTrgJKDIOKWn
+UYsxSoE_U02WxQThW8ayrFtKRLGR2x9bMaKzaON0tfltwyQO7ttsKlSyORIWVrGO48CyEDxpDs8U
+RDvN_SgFq1gWarCKLL0HDUdLGMfimZP7sPfVEKkprMlDp_gpx7kD7SaB1m7xuNjhBd-6I3gqSR7g
+lizTgKmuGalPRGorxX72vlTEYqLtgNWok6e9qjMGhEYCf02li6Ksoxp4ZejN_9S1-FGlcuq3SE9f
+Pm0HckGtPJ8u3u2mmLpT1QzzS0RG3XJU5kNJvZcSEG0GOsU7OnWTXoZnleFJvEoQrOuQeZJLyuxn
+mnmd49xrTirtxkLB83L8HQdAHvY5Phx8LbR9NJYvkH1MIEbBrrfUUx-x_llROOAYdPxvtpYcMkSt
+ApZwRgyvaBiwUirWbnlpmf8QV1MYMlZeBbbqPZIC4eaqcxOSmZa8ox4aR3XQg9zjCxm_jXdE
\ No newline at end of file
index 98b7137..62b0f82 100644 (file)
@@ -3,7 +3,6 @@
 # * org.onap.dmaap
 # * ===========================================================================
 # * Copyright ï¿½ 2017 AT&T Intellectual Property. All rights reserved.
-# * Modifications Copyright (C) 2018 Nokia. All rights reserved.
 # * ===========================================================================
 # * Licensed under the Apache License, Version 2.0 (the "License");
 # * you may not use this file except in compliance with the License.
 # *
 #-------------------------------------------------------------------------------
 #
-#    Configuration parameters fixed at startup for the DataRouter node
+#    Configuration parameters set at startup for the DataRouter node
 #
 #    URL to retrieve dynamic configuration
-#
-#ProvisioningURL:    ${DRTR_PROV_INTURL}
-ProvisioningURL=https://dmaap-dr-prov:8443/internal/prov
-
+ProvisioningURL = https://dmaap-dr-prov:8443/internal/prov
 #
 #    URL to upload PUB/DEL/EXP logs
-#
-#LogUploadURL:    ${DRTR_LOG_URL}
-LogUploadURL=https://dmaap-dr-prov:8443/internal/logs
-
+LogUploadURL = https://dmaap-dr-prov:8443/internal/logs
 #
 #    The port number for http as seen within the server
-#
-#IntHttpPort:    ${DRTR_NODE_INTHTTPPORT:-8080}
-IntHttpPort=8080
+IntHttpPort = 8080
 #
 #    The port number for https as seen within the server
-#
-IntHttpsPort=8443
+IntHttpsPort = 8443
 #
 #    The external port number for https taking port mapping into account
+ExtHttpsPort = 443
 #
-ExtHttpsPort=443
-#
-#    The minimum interval between fetches of the dynamic configuration
-#    from the provisioning server
-#
-MinProvFetchInterval=10000
+#    The minimum interval between fetches of the dynamic configuration from the provisioning server
+MinProvFetchInterval = 10000
 #
 #    The minimum interval between saves of the redirection data file
-#
-MinRedirSaveInterval=10000
+MinRedirSaveInterval = 10000
 #
 #    The path to the directory where log files are stored
-#
-LogDir=/opt/app/datartr/logs
+LogDir = /opt/app/datartr/logs
 #
 #    The retention interval (in days) for log files
-#
-LogRetention=30
+LogRetention = 30
 #
 #    The path to the directories where data and meta data files are stored
-#
-SpoolDir=/opt/app/datartr/spool
+SpoolDir = /opt/app/datartr/spool
 #
 #    The path to the redirection data file
-#
-#RedirectionFile:    etc/redirections.dat
+RedirectionFile = etc/redirections.dat
 #
 #    The type of keystore for https
-KeyStoreType:    jks
+KeyStoreType = jks
 #
 #    The path to the keystore for https
-#
-KeyStoreFile:/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
+KeyStoreFile = /opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
 #
 #    The password for the https keystore
-#
 KeyStorePassword=]3V)($O&.Mv]W{f8^]6SxGNL
 #
 #    The password for the private key in the https keystore
-#
 KeyPassword=]3V)($O&.Mv]W{f8^]6SxGNL
 #
 #    The type of truststore for https
-#
-TrustStoreType=jks
+TrustStoreType = jks
 #
 #    The path to the truststore for https
-#
-TrustStoreFile=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
+TrustStoreFile = /opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
 #
 #    The password for the https truststore
-#
 TrustStorePassword=(Rd,&{]%ePdp}4JZjqoJ2G+g
 #
 #    The path to the file used to trigger an orderly shutdown
-#
-QuiesceFile=etc/SHUTDOWN
+QuiesceFile = etc/SHUTDOWN
 #
 #    The key used to generate passwords for node to node transfers
+NodeAuthKey = Node123!
+#
+#    DR_NODE DEFAULT ENABLED TLS PROTOCOLS
+NodeHttpsProtocols = TLSv1.1|TLSv1.2
+#
+#    AAF type to generate permission string
+AAFType = org.onap.dmaap-dr.feed
+#
+#    AAF default instance to generate permission string - default should be legacy
+AAFInstance = legacy
+#
+#    AAF action to generate permission string - default should be publish
+AAFAction = publish
+#
+#    AAF URL to connect to AAF server
+AafUrl = https://aaf-onap-test.osaaf.org:8095
 #
-NodeAuthKey=Node123!
+#    AAF CADI enabled flag
+CadiEnabled = false
 
diff --git a/datarouter-docker-compose/src/main/resources/prov_data/aaf_certs/org.onap.dmaap-dr.keyfile b/datarouter-docker-compose/src/main/resources/prov_data/aaf_certs/org.onap.dmaap-dr.keyfile
new file mode 100755 (executable)
index 0000000..a586a72
--- /dev/null
@@ -0,0 +1,27 @@
+VDu7g5rP2-JMemc6RwP0HqM4ILJnuja8R_bzdCG1u0_Z2EQJN_7ZNPDb28V6JCDF-59sX10_i9vT
+-nw77ViAuwJO7ffSut8ipVhESeQxTokZsErzMFpeJZDhMM16W5LLtxwUs_tgh_EQIJSc-WcFUNYS
+NagugzjmNE5-hUosLgnt7mZ1nX4zFER9Nq1ce0EQS--kAB9rxcRmoywPlBlHvPmP_caiwpa1SzJp
+gbFF6smyLEWhjDhJkgvM_4FwaQCbJBVGcy2a3Lc9orHsz9S1RJTZ9CExhasM0qEp3kk0fMEFE9k6
+TomOpUBGizLfHPpg18KtXyM8zErj8qdS0KMwaCKtwGzCWw08MF5rVZrMYWLKDMOs8U2ESU7x28nV
+KSrAsR11QD7vX4PTVTfjEpcHSGe-9nPD7TckY8_O-9l67v_OUW1Fw4MSESCN0RtT7ZlNYwDV0syA
+X94rv1Y45N41tfX76jz8PDB9G-PF36BtkICJWK24zwuQDgpkURhCLPYzvBhPmCPyQil810X9s_bX
+icmV2cSN3oYQRz5dNSjUYH1CDt9edAJt4p2PQhM3A2xXyw1FVvbAIYA7iF-3qYG9csroBzsCcS5C
+hX8929jZHQWU5pygtpedEWhX__tnSrd-xIpxPnhOxrb-lNLva5JGKauU2DrGoLd_7RTwbuRdCiQo
+uGFtYOtjLciPz81oEEpXQTReeSnvGyGiZNxRrKWMEmq-biyQd4DuRVmTDuLAG4rd92QWS6qUz0uf
+9TtJiYlN3mNkxz3ahEGWLKR79rH9juJ3xqpcF-Rb7Y1bmiCDBv3DVVFiYIpwQuto1iSIYabL34Ql
+QqX65E1c3uvPksN6Nl1nvAVxSKM94wAFsMiA9Rp8AN9pDSxtj7D3kZCG8I0YaIxF_s-OeJtr1RPx
+ifv8vrwN23GUQCmpGBbyNXNe6zz-hz_HJdAsBr6WjLny9LQkeYszHGF-OL5ps6K5gHBRV0Ui1C7H
+Gj7egsjnV_Lu5MpBxhTrquDrZKK3t38kf0zrV-zfSGzJlGbLS91h8bR-7FAZiNEzgXPWYi26w81i
+W3Csx4oqsfKswp0pO80rggkFf9LL9pjCkSUTTVyF-toa9kY2h7JsVtqntP4Mjagp4Tnj01988kne
+Mj8SLm2mJySTLdH5Hi4arKW943iCqYjEaZ7wXFNJSZ6vvBm3KC1XX6C0DjRrgQoKIHw_4JcGhvOU
+P5LdpBT1AOcE8lIKrGGq8hyfJKLVUMec-NkzAT2aIl0YJoUcJv4fs-lKccGL4FDrq5y_yvD3xQ6v
+xt7KTanFxntqLYmM72Y2eFwJGlDEHhm0SejAV64-odksA_zMLLuYwkq_KSj0If9AVpRXz7KzIj9P
+9y-WMfAWKFfIyqGWXt5sYdMTQPG4qKCcFQBx3T0E6kiQMBuOZz0dR032eFPMexrymEowjosr2jt3
+ib8rFxmPMyyUWoV1iBafFMLf5PN2oapTq76gqeQQGGwpmYJB8cWlS1Eq_ZbzZpK2PSwX-fC6NSf3
+KtOV_r2VI3e_V6csnWTY8nxCJj9FlQCvLOzp964DNsBeUwDpsD7T_pgQy0THgAnq32ZtDvQfgeUE
+TUJC7oQeOEY7QBWjbZkumds51j7oTlsp2dPForlHwBk_2Nd5VCwVRNa1QMS8WcghLYbUCX5zeplc
+u2bopHn9GD614gt7f7wysDgTGegOCAuMoL7wA9TXN4BSfAF9mwpdtRFE4lT3N1xmfhKt9rM6Lu8T
+RGvBOmTOTT5IwJrrE5mpvmESw05sHUcCZ9ENv-VhoeC3Ffk9uXqrDggQgaDs9XcXqzEPBp9wDPTt
+UJpbtBGECSSTuXAZyUh3I0WFz96kVuHmQpDYVTpy1sxPjmgjgKyhu_6jLGSsYpVBH063n7KSKVdF
+ROKojZN4-FsBlPhoOhNEd7x1OBfgCG79HKGk33jhESObZkPIrcTc17jiE-ud2D1B1_Fl-OJNR7Vh
+GIk4WMZrH9NeVwDuIgBxF74plqg6tSl0Cdd4m7e3Drsq-wRfsU2gNTo5oL-2SgbsO5n3ubQf
\ No newline at end of file
index 45e1273..ccb55f6 100644 (file)
 # *
 #-------------------------------------------------------------------------------
 {
-                "delivery" :
-
-                {
-                                "url" : "http://172.100.0.3:7070/",
-                                "user" : "datarouter",
-                                "password" : "datarouter",
-                                "use100" : true
-                },
-                "metadataOnly" : false,
-                "suspend" : false,
-                "groupid" : 29,
-                "subscriber" : "sg481n"
+"delivery" :
+    {
+        "url" : "http://172.100.0.3:7070/",
+        "user" : "datarouter",
+        "password" : "datarouter",
+        "use100" : true
+    },
+"metadataOnly" : false,
+"suspend" : false,
+"groupid" : 29,
+"subscriber" : "sg481n"
 }
index 7e38f28..21b9bc4 100755 (executable)
@@ -43,8 +43,27 @@ org.onap.dmaap.datarouter.provserver.logretention        = 30
 # relaxation to accommodate OOM kubernetes deploy
 org.onap.dmaap.datarouter.provserver.isaddressauthenabled = false
 
+#Localhost address config
+org.onap.dmaap.datarouter.provserver.localhost = 127.0.0.1
+
 # Database access
 org.onap.dmaap.datarouter.db.driver   = org.mariadb.jdbc.Driver
 org.onap.dmaap.datarouter.db.url      = jdbc:mariadb://datarouter-mariadb:3306/datarouter
 org.onap.dmaap.datarouter.db.login    = datarouter
 org.onap.dmaap.datarouter.db.password = datarouter
+
+# PROV - DEFAULT ENABLED TLS PROTOCOLS
+org.onap.dmaap.datarouter.provserver.https.include.protocols = TLSv1.1|TLSv1.2
+
+# AAF config
+org.onap.dmaap.datarouter.provserver.cadi.enabled = false
+
+org.onap.dmaap.datarouter.provserver.passwordencryption   = PasswordEncryptionKey#@$%^&1234#
+org.onap.dmaap.datarouter.provserver.aaf.feed.type        = org.onap.dmaap-dr.feed
+org.onap.dmaap.datarouter.provserver.aaf.sub.type         = org.onap.dmaap-dr.sub
+org.onap.dmaap.datarouter.provserver.aaf.instance         = legacy
+org.onap.dmaap.datarouter.provserver.aaf.action.publish   = publish
+org.onap.dmaap.datarouter.provserver.aaf.action.subscribe = subscribe
+
+# AAF URL to connect to AAF server
+org.onap.dmaap.datarouter.provserver.cadi.aaf.url = https://aaf-onap-test.osaaf.org:8095
\ No newline at end of file
diff --git a/datarouter-node/aaf_certs/org.onap.dmaap-dr.keyfile b/datarouter-node/aaf_certs/org.onap.dmaap-dr.keyfile
new file mode 100755 (executable)
index 0000000..85bfa61
--- /dev/null
@@ -0,0 +1,27 @@
+j4IkjDmzOE_ZdHuN_cePYmySXrhmqM4WuGp86_RTiBlJ1TTvUaP_SOSZOqH0fxjk32gRvxJ01_iO
+mLtbQ-wZKk-fwCK_o6xrXJcN0G_Y8VGK2OMeqypm98ji25CSMvTdFLaohdPJwiRNMdmwwyF5q1Od
+pKviCISBlQ49ytwy3Mv0x7aV3kjkDWSgpx9TiMbWoAKlddcdQMUTEMh0CT0nLGv9uhwmRQ4I8UuE
+IzvR1Rit9HayMlXFND6n0IWggYqtAeRV-8wDrI2rAXGOrfLF0RC5-c0Wd0N000BWXvsT_nCYBCM6
+ffA5eAKCJmOVjJFzQTRXJq7Zhwij0CtEPgqqaipKUQhHaft9xeKXW3SPhREIn75F2u2uCcU1sNmd
+ytAk7yBPwdEcCQD-KVE9ZB3_57H0WIEr45SpU5ZePJkt2YV85H2Tlc_hGK18gTAcvGqDO3qELmV5
+SBHX5X_ZNL93mOkt37R0SGRdMZVIPJXNTgl4fGAsapvU7Y7sGMYrf2Ea0D-3hctk-aOKuuPEI1Ug
+0lqKjghJdvHYRFbm4C_7H-ai7UcBuixBd54Mp-hyBX-gjnFZuMHazFX2toKNe9RgDXIavHzTfF-l
+8fjdQpTplc2ECLINf-X6gs7w0zPYv04kLKixwlFff4ZocoxelGDEBlYYGNNxQBZvQtUX_dZetXF1
+VPNnwTB7Sp0fqaXR2aVaZNFSZYeL7VdxkiT0becNRa9QE9s2gU7oO_KTE8JyAiJyO-ojAvSUi-p_
+rq2Ivmab_L4t6GwMpv-EmRcntUQ_PM4s_XvJL2RmmSPWoNvbgCS0IilpYi2CPnEEgxqX37-Unx8m
+tYoNkiN-j9rA3Hr4EjEhrbOLf2wAh6RUeULerBpLKnf0Ans6UhjT7XVDaNvzxtAE-GrUCKHQ0ml2
+P_vzDBlGKobaRo-WQzQA-mZKGo1W4Q-qwFdusUflgfJ7iTrvw62jn30f4xGZcaP5Oa-9JvdZJggW
+1UvAM-85LdjGTxuI9KXbqRLWZk46B-UF7mDOce6dbRXjY48bZWIHEXcpzPQg6QA02cO10TN5K89V
+qXeCnz03ePf0u6YhMAOt5xiUvJpd1y_WI0jh4SH2dT26SegcuRTVLnEG0aL6ClypObwj3FLB1Pek
+UESqziiG4mQf_rzBAdPqcjbP8oeM2-mz09VYNyUOQ-7gk6bMAMWVqBx0uDxgIwUzr2UMbahB2Kg6
+9V7yE7obAKZa8x5oMiDGnvgjL9QeHwhUsNbwhhgqTDnB10vj4gh8RkNK8OsxQ53Nofj2PQZfY0GJ
+a6It7DCmnAgQ9N51RvCeodmmK9Zh3n_zoxt8gA-eV8zbidXZYQwYWx6ai7ooP7yol2bE_TLDDY9l
+_oYO_db73wSmqgTvoAdmrQGO4NI_g2iYN-Gd4XK4V_xgYPKyY5tHNSd4OKr_UuYiSioyNxE4IK1t
+zWyJ3tUXAyeq_ZjUDjabsnGnxmgujShRfK-rBh_1AapY3Oh99-aehETtcXihUmFX4lohowniWTA3
+MF1MMlRM5N1phF7xFgkAaZJfkQ-inqgWYvQ9XuW0LfumN4QeO8KnfknukSSgZ86PYTrgJKDIOKWn
+UYsxSoE_U02WxQThW8ayrFtKRLGR2x9bMaKzaON0tfltwyQO7ttsKlSyORIWVrGO48CyEDxpDs8U
+RDvN_SgFq1gWarCKLL0HDUdLGMfimZP7sPfVEKkprMlDp_gpx7kD7SaB1m7xuNjhBd-6I3gqSR7g
+lizTgKmuGalPRGorxX72vlTEYqLtgNWok6e9qjMGhEYCf02li6Ksoxp4ZejN_9S1-FGlcuq3SE9f
+Pm0HckGtPJ8u3u2mmLpT1QzzS0RG3XJU5kNJvZcSEG0GOsU7OnWTXoZnleFJvEoQrOuQeZJLyuxn
+mnmd49xrTirtxkLB83L8HQdAHvY5Phx8LbR9NJYvkH1MIEbBrrfUUx-x_llROOAYdPxvtpYcMkSt
+ApZwRgyvaBiwUirWbnlpmf8QV1MYMlZeBbbqPZIC4eaqcxOSmZa8ox4aR3XQg9zjCxm_jXdE
\ No newline at end of file
index 3e75e88..9c82ff3 100755 (executable)
             <artifactId>commons-lang3</artifactId>
             <version>3.0</version>
         </dependency>
+        <dependency>
+            <groupId>org.onap.aaf.authz</groupId>
+            <artifactId>aaf-cadi-aaf</artifactId>
+            <version>${aaf-cadi-aaf.version}</version>
+        </dependency>
     </dependencies>
     <profiles>
         <profile>
diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DRNodeCadiFilter.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DRNodeCadiFilter.java
new file mode 100644 (file)
index 0000000..b012259
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dmaap.datarouter.node;
+
+import org.apache.log4j.Logger;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.filter.CadiFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+
+public class DRNodeCadiFilter extends CadiFilter {
+    private static Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.node.NodeServlet");
+
+    DRNodeCadiFilter(boolean init, PropAccess access) throws ServletException {
+        super(init, access);
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        HttpServletRequest httpRequest = (HttpServletRequest) request;
+        String path = httpRequest.getPathInfo();
+        if (!(path.startsWith("/internal"))) {
+            if (!(httpRequest.getMethod().equalsIgnoreCase("POST"))) {
+                if (httpRequest.getMethod().equalsIgnoreCase("DELETE") && path.startsWith("/delete")) {
+                    chain.doFilter(request, response);
+                } else {
+                    String feedId = getFeedId(request, response);
+                    String aafDbInstance = NodeConfigManager.getInstance().getAafInstance(feedId);
+                    if (aafDbInstance != null && !aafDbInstance.equals("") && !aafDbInstance.equalsIgnoreCase("legacy")) {
+                        logger.info("DRNodeCadiFilter - doFilter: FeedId - " + feedId + ":" + "AAF Instance -" + aafDbInstance);
+                        super.doFilter(request, response, chain);
+                    } else {
+                        logger.info("DRNodeCadiFilter - doFilter: FeedId - " + feedId + ":" + "Legacy Feed");
+                        chain.doFilter(request, response);
+                    }
+                }
+            }
+        } else {
+            chain.doFilter(request, response);
+        }
+    }
+
+    private String getFeedId(ServletRequest request, ServletResponse response) {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+        String fileid = req.getPathInfo();
+        if (fileid == null) {
+            logger.info("NODE0105 Rejecting bad URI for PUT " + req.getPathInfo() + " from " + req.getRemoteAddr());
+            try {
+                resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Invalid request URI.  Expecting <feed-publishing-url>/<fileid>.");
+            } catch (IOException e) {
+                logger.error("NODE0541 DRNodeCadiFilter.getFeedId: ", e);
+            }
+            return null;
+        }
+        String feedid = "";
+
+        if (fileid.startsWith("/publish/")) {
+            fileid = fileid.substring(9);
+            int i = fileid.indexOf('/');
+            if (i == -1 || i == fileid.length() - 1) {
+                logger.info("NODE0105 Rejecting bad URI for PUT (publish) of " + req.getPathInfo() + " from " + req.getRemoteAddr());
+                try {
+                    resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Invalid request URI.  Expecting <feed-publishing-url>/<fileid>.  Possible missing fileid.");
+                } catch (IOException e) {
+                    logger.error("NODE0542 DRNodeCadiFilter.getFeedId: ", e);
+                }
+                return null;
+            }
+            feedid = fileid.substring(0, i);
+        }
+        return feedid;
+    }
+
+}
index a3af88f..b64396b 100644 (file)
@@ -64,6 +64,7 @@ public class DeliveryTask implements Runnable, Comparable<DeliveryTask> {
     private String feedid;
     private String subid;
     private int attempts;
+    private boolean followRedirects;
     private String[][] hdrs;
     private String newInvocationId;
 
@@ -81,6 +82,7 @@ public class DeliveryTask implements Runnable, Comparable<DeliveryTask> {
         this.pubid = pubid;
         destInfo = deliveryTaskHelper.getDestinationInfo();
         subid = destInfo.getSubId();
+        this.followRedirects = destInfo.isFollowRedirects();
         feedid = destInfo.getLogData();
         spool = destInfo.getSpool();
         String dfn = spool + "/" + pubid;
@@ -125,7 +127,7 @@ public class DeliveryTask implements Runnable, Comparable<DeliveryTask> {
                 hdrv.add(new String[]{h, v});
             }
         } catch (Exception e) {
-            loggerDeliveryTask.error("Exception "+e.getStackTrace(),e);
+            loggerDeliveryTask.error("Exception "+ Arrays.toString(e.getStackTrace()), e);
         }
         hdrs = hdrv.toArray(new String[hdrv.size()][]);
         url = deliveryTaskHelper.getDestURL(fileid);
@@ -245,7 +247,7 @@ public class DeliveryTask implements Runnable, Comparable<DeliveryTask> {
             }
             deliveryTaskHelper.reportStatus(this, rc, xpubid, rmsg);
         } catch (Exception e) {
-            loggerDeliveryTask.error("Exception " + e.getStackTrace(), e);
+            loggerDeliveryTask.error("Exception " + Arrays.toString(e.getStackTrace()), e);
             deliveryTaskHelper.reportException(this, e);
         }
     }
@@ -324,7 +326,7 @@ public class DeliveryTask implements Runnable, Comparable<DeliveryTask> {
         } catch (ProtocolException pe) {
             deliveryTaskHelper.reportDeliveryExtra(this, -1L);
             // Rcvd error instead of 100-continue
-            loggerDeliveryTask.error("Exception " + pe.getStackTrace(), pe);
+            loggerDeliveryTask.error("Exception " + Arrays.toString(pe.getStackTrace()), pe);
         }
         return outputStream;
     }
@@ -409,4 +411,11 @@ public class DeliveryTask implements Runnable, Comparable<DeliveryTask> {
     public String getFeedId() {
         return (feedid);
     }
+
+    /**
+     * Get the followRedirects for this delivery task
+     */
+    public boolean getFollowRedirects() {
+        return(followRedirects);
+    }
 }
index 7375352..8aa339f 100644 (file)
@@ -39,7 +39,8 @@ public class DestInfo {
     private boolean use100;
     private boolean privilegedSubscriber;
     private boolean decompress;
-
+    private boolean followRedirects;
+    private String aafInstance;
     /**
      * Create a destination information object.
      *
@@ -53,9 +54,10 @@ public class DestInfo {
      * @param    metaonly    Is this a metadata only delivery?
      * @param    use100    Should I use expect 100-continue?
      * @param    privilegedSubscriber   Can we wait to receive a file processed acknowledgement before deleting file
+     * @param    followRedirects Is follow redirect of destination enabled?
      * @param    decompress     To see if the they want there information compressed or decompressed
      */
-    public DestInfo(String name, String spool, String subid, String logdata, String url, String authuser, String authentication, boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean decompress) {
+    public DestInfo(String name, String spool, String subid, String logdata, String url, String authuser, String authentication, boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean followRedirects, boolean decompress) {
         this.name = name;
         this.spool = spool;
         this.subid = subid;
@@ -66,6 +68,7 @@ public class DestInfo {
         this.metaonly = metaonly;
         this.use100 = use100;
         this.privilegedSubscriber = privilegedSubscriber;
+        this.followRedirects = followRedirects;
         this.decompress = decompress;
     }
 
@@ -87,6 +90,7 @@ public class DestInfo {
         this.metaonly = subscription.isMetaDataOnly();
         this.use100 = subscription.isUsing100();
         this.privilegedSubscriber = subscription.isPrivilegedSubscriber();
+        this.followRedirects = subscription.getFollowRedirect();
         this.decompress = subscription.isDecompress();
     }
 
@@ -185,6 +189,15 @@ public class DestInfo {
         return (privilegedSubscriber);
     }
 
+    /**
+    * Should I follow redirects?
+    *
+    * @return True if I should.
+    */
+    public boolean isFollowRedirects() {
+        return (followRedirects);
+    }
+
     /**
      * Should i decompress the file before sending it on
      *
index 35ba095..b8db030 100644 (file)
@@ -26,6 +26,7 @@ package org.onap.dmaap.datarouter.node;
 
 import org.apache.log4j.Logger;
 
+import java.io.IOException;
 import java.util.*;
 import java.net.*;
 
@@ -62,24 +63,37 @@ public class IsFrom {
         long now = System.currentTimeMillis();
         if (now > nextcheck) {
             nextcheck = now + 10000;
-            Vector<String> v = new Vector<>();
+            ArrayList<String> hostAddrArray = new ArrayList<>();
             try {
                 InetAddress[] addrs = InetAddress.getAllByName(fqdn);
-                for (InetAddress a : addrs) {
-                    v.add(a.getHostAddress());
+                for (InetAddress addr : addrs) {
+                    hostAddrArray.add(addr.getHostAddress());
                 }
             } catch (UnknownHostException e) {
                 logger.debug("IsFrom: UnknownHostEx: " + e.toString(), e);
             }
-            ips = v.toArray(new String[v.size()]);
+            ips = hostAddrArray.toArray(new String[0]);
             logger.info("IsFrom: DNS ENTRIES FOR FQDN " + fqdn + " : " + Arrays.toString(ips));
         }
-        for (String s : ips) {
-            if (s.equals(ip) || s.equals(System.getenv("DMAAP_DR_PROV_SERVICE_HOST"))) {
-                return (true);
+        for (String ipAddr : ips) {
+            if (ipAddr.equals(ip)) {
+                return true;
             }
         }
-        return (false);
+        return false;
+    }
+
+    synchronized boolean isReachable(String ip) {
+        try {
+            if (InetAddress.getByName(ip).isReachable(1000)) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            logger.debug("IsFrom: UnknownHostEx: " + e.toString(), e);
+        } catch (IOException e) {
+            logger.debug("IsFrom: Failed to parse IP : " + ip + " : " + e.toString(), e);
+        }
+        return false;
     }
 
     /**
index 032c6ce..3fa5dc2 100644 (file)
@@ -104,8 +104,7 @@ public class LogManager extends TimerTask {
 
         public Uploader() {
             dq = new DeliveryQueue(this,
-                new DestInfo("LogUpload", uploaddir, null, null, null, config.getMyName(), config.getMyAuth(), false,
-                    false, false, false));
+                new DestInfo("LogUpload", uploaddir, null, null, null, config.getMyName(), config.getMyAuth(), false, false, false, false, false));
             setDaemon(true);
             setName("Log Uploader");
             start();
index 5577e52..791eee1 100644 (file)
 package org.onap.dmaap.datarouter.node;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Vector;
+import org.apache.log4j.Logger;
 
 /**
  * Processed configuration for this node.
@@ -37,7 +39,7 @@ import java.util.Vector;
  * discarded.
  */
 public class NodeConfig {
-
+    private static Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.node.NodeConfig");
     /**
      * Raw configuration entry for a data router node
      */
@@ -104,6 +106,12 @@ public class NodeConfig {
         private String id;
         private String logdata;
         private String status;
+        private String createdDate;
+        /*
+         * AAF changes: TDP EPIC US# 307413
+         * Passing aafInstance from to identify legacy/AAF feeds
+         */
+        private String aafInstance;
 
         /**
          * Construct a feed configuration entry.
@@ -113,10 +121,27 @@ public class NodeConfig {
          * @param status The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or
          * null if it is valid.
          */
-        public ProvFeed(String id, String logdata, String status) {
+        public ProvFeed(String id, String logdata, String status, String createdDate, String aafInstance) {
             this.id = id;
             this.logdata = logdata;
             this.status = status;
+            this.createdDate = createdDate;
+            this.aafInstance = aafInstance;
+        }
+
+        /**
+         * Get the created date of the data feed.
+         */
+        public String getCreatedDate()
+        {
+            return(createdDate);
+        }
+
+        /**
+         * Get the aafInstance of the data feed.
+         */
+        public String getAafInstance() {
+            return aafInstance;
         }
 
         /**
@@ -232,6 +257,7 @@ public class NodeConfig {
         private boolean metaonly;
         private boolean use100;
         private boolean privilegedSubscriber;
+        private boolean followRedirect;
         private boolean decompress;
 
         /**
@@ -246,10 +272,10 @@ public class NodeConfig {
          * @param metaonly Is this a meta data only subscription?
          * @param use100 Should we send Expect: 100-continue?
          * @param privilegedSubscriber Can we wait to receive a delete file call before deleting file
+         * @param followRedirect Is follow redirect of destination enabled?
          * @param decompress To see if they want their information compressed or decompressed
          */
-        public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials,
-                boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean decompress) {
+        public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials, boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean followRedirect, boolean decompress) {
             this.subid = subid;
             this.feedid = feedid;
             this.url = url;
@@ -258,6 +284,7 @@ public class NodeConfig {
             this.metaonly = metaonly;
             this.use100 = use100;
             this.privilegedSubscriber = privilegedSubscriber;
+            this.followRedirect = followRedirect;
             this.decompress = decompress;
         }
 
@@ -319,10 +346,18 @@ public class NodeConfig {
 
         /**
          * Should i decompress the file before sending it on
-         */
+        */
         public boolean isDecompress() {
             return (decompress);
         }
+
+        /**
+         *  New field is added - FOLLOW_REDIRECTS feature iTrack:DATARTR-17 - 1706
+         *     Get the followRedirect of this destination
+         */
+        boolean getFollowRedirect() {
+            return(followRedirect);
+        }
     }
 
     /**
@@ -348,7 +383,12 @@ public class NodeConfig {
             this.feedid = feedid;
             this.subnet = subnet;
             this.user = user;
-            this.nodes = nodes;
+            //Sonar fix
+            if(nodes == null) {
+                this.nodes = new String[0];
+            } else {
+                this.nodes = Arrays.copyOf(nodes, nodes.length);
+            }
         }
 
         /**
@@ -480,6 +520,8 @@ public class NodeConfig {
         Hashtable<String, String> authusers = new Hashtable<String, String>();
         Redirection[] redirections;
         Target[] targets;
+        String createdDate;
+        String aafInstance;
     }
 
     private Hashtable<String, String> params = new Hashtable<>();
@@ -510,24 +552,24 @@ public class NodeConfig {
         Vector<DestInfo> destInfos = new Vector<>();
         myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey);
         for (ProvNode pn : pd.getNodes()) {
-            String cn = pn.getCName();
-            if (nodeinfo.get(cn) != null) {
+            String cName = pn.getCName();
+            if (nodeinfo.get(cName) != null) {
                 continue;
             }
-            String auth = NodeUtils.getNodeAuthHdr(cn, nodeauthkey);
-            DestInfo di = new DestInfo("n:" + cn, spooldir + "/n/" + cn, null, "n2n-" + cn,
-                    "https://" + cn + ":" + port + "/internal/publish", cn, myauth, false, true, false, false);
+            String auth = NodeUtils.getNodeAuthHdr(cName, nodeauthkey);
+            DestInfo di = new DestInfo("n:" + cName, spooldir + "/n/" + cName, null, "n2n-" + cName,
+                    "https://" + cName + ":" + port + "/internal/publish", cName, myauth, false, true, false, false, false);
             (new File(di.getSpool())).mkdirs();
             destInfos.add(di);
-            nodeinfo.put(cn, di);
-            nodes.put(auth, new IsFrom(cn));
+            nodeinfo.put(cName, di);
+            nodes.put(auth, new IsFrom(cName));
         }
-        PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[nodeinfo.size()]), pd.getHops());
-        Hashtable<String, Vector<Redirection>> rdtab = new Hashtable<String, Vector<Redirection>>();
+        PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[0]), pd.getHops());
+        Hashtable<String, Vector<Redirection>> rdtab = new Hashtable<>();
         for (ProvForceIngress pfi : pd.getForceIngress()) {
             Vector<Redirection> v = rdtab.get(pfi.getFeedId());
             if (v == null) {
-                v = new Vector<Redirection>();
+                v = new Vector<>();
                 rdtab.put(pfi.getFeedId(), v);
             }
             Redirection r = new Redirection();
@@ -538,16 +580,16 @@ public class NodeConfig {
             r.nodes = pfi.getNodes();
             v.add(r);
         }
-        Hashtable<String, Hashtable<String, String>> pfutab = new Hashtable<String, Hashtable<String, String>>();
+        Hashtable<String, Hashtable<String, String>> pfutab = new Hashtable<>();
         for (ProvFeedUser pfu : pd.getFeedUsers()) {
             Hashtable<String, String> t = pfutab.get(pfu.getFeedId());
             if (t == null) {
-                t = new Hashtable<String, String>();
+                t = new Hashtable<>();
                 pfutab.put(pfu.getFeedId(), t);
             }
             t.put(pfu.getCredentials(), pfu.getUser());
         }
-        Hashtable<String, String> egrtab = new Hashtable<String, String>();
+        Hashtable<String, String> egrtab = new Hashtable<>();
         for (ProvForceEgress pfe : pd.getForceEgress()) {
             if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) {
                 continue;
@@ -558,7 +600,7 @@ public class NodeConfig {
         for (ProvFeedSubnet pfs : pd.getFeedSubnets()) {
             Vector<SubnetMatcher> v = pfstab.get(pfs.getFeedId());
             if (v == null) {
-                v = new Vector<SubnetMatcher>();
+                v = new Vector<>();
                 pfstab.put(pfs.getFeedId(), v);
             }
             v.add(new SubnetMatcher(pfs.getCidr()));
@@ -584,6 +626,7 @@ public class NodeConfig {
                 sididx = Integer.parseInt(subId);
                 sididx -= sididx % 100;
             } catch (Exception e) {
+                logger.error("NODE0517 Exception NodeConfig: "+e);
             }
             String subscriptionDirectory = sididx + "/" + subId;
             DestInfo destinationInfo = new DestInfo("s:" + subId,
@@ -603,7 +646,7 @@ public class NodeConfig {
             }
             sb.append(' ').append(subId);
         }
-        alldests = destInfos.toArray(new DestInfo[destInfos.size()]);
+        alldests = destInfos.toArray(new DestInfo[0]);
         for (ProvFeed pfx : pd.getFeeds()) {
             String fid = pfx.getId();
             Feed f = feeds.get(fid);
@@ -612,13 +655,19 @@ public class NodeConfig {
             }
             f = new Feed();
             feeds.put(fid, f);
+            f.createdDate = pfx.getCreatedDate();
             f.loginfo = pfx.getLogData();
             f.status = pfx.getStatus();
+            /*
+             * AAF changes: TDP EPIC US# 307413
+             * Passing aafInstance from ProvFeed to identify legacy/AAF feeds
+             */
+            f.aafInstance = pfx.getAafInstance();
             Vector<SubnetMatcher> v1 = pfstab.get(fid);
             if (v1 == null) {
                 f.subnets = new SubnetMatcher[0];
             } else {
-                f.subnets = v1.toArray(new SubnetMatcher[v1.size()]);
+                f.subnets = v1.toArray(new SubnetMatcher[0]);
             }
             Hashtable<String, String> h1 = pfutab.get(fid);
             if (h1 == null) {
@@ -629,7 +678,7 @@ public class NodeConfig {
             if (v2 == null) {
                 f.redirections = new Redirection[0];
             } else {
-                f.redirections = v2.toArray(new Redirection[v2.size()]);
+                f.redirections = v2.toArray(new Redirection[0]);
             }
             StringBuffer sb = feedTargets.get(fid);
             if (sb == null) {
@@ -687,7 +736,7 @@ public class NodeConfig {
                 }
             }
         }
-        return (tv.toArray(new Target[tv.size()]));
+        return (tv.toArray(new Target[0]));
     }
 
     /**
@@ -743,6 +792,32 @@ public class NodeConfig {
         return provSubscription.isPrivilegedSubscriber();
     }
 
+    /**
+     * Check whether publication is allowed for AAF Feed.
+     * @param feedid The ID of the feed being requested.
+     * @param ip The requesting IP address
+     */
+    public String isPublishPermitted(String feedid, String ip) {
+        Feed f = feeds.get(feedid);
+        String nf = "Feed does not exist";
+        if (f != null) {
+            nf = f.status;
+        }
+        if (nf != null) {
+            return(nf);
+        }
+        if (f.subnets.length == 0) {
+            return(null);
+        }
+        byte[] addr = NodeUtils.getInetAddress(ip);
+        for (SubnetMatcher snm: f.subnets) {
+            if (snm.matches(addr)) {
+                return(null);
+            }
+        }
+        return("Publisher not permitted for this feed");
+    }
+
     /**
      * Get authenticated user
      */
@@ -750,6 +825,16 @@ public class NodeConfig {
         return (feeds.get(feedid).authusers.get(credentials));
     }
 
+    /**
+     * AAF changes: TDP EPIC US# 307413
+     * Check AAF_instance for feed ID
+     * @param feedid   The ID of the feed specified
+     */
+    public String getAafInstance(String feedid) {
+        Feed f = feeds.get(feedid);
+        return f.aafInstance;
+    }
+
     /**
      * Check if the request should be redirected to a different ingress node
      */
@@ -810,6 +895,16 @@ public class NodeConfig {
         return (f.targets);
     }
 
+    /**
+     * Get the creation date for a feed
+     * @param feedid The feed ID
+     * @return the timestamp of creation date of feed id passed
+     */
+    public String getCreatedDate(String feedid) {
+        Feed f = feeds.get(feedid);
+        return(f.createdDate);
+    }
+
     /**
      * Get the feed ID for a subscription
      *
index d98c47a..8011c63 100644 (file)
@@ -26,6 +26,10 @@ package org.onap.dmaap.datarouter.node;
 
 import com.att.eelf.configuration.EELFLogger;
 import com.att.eelf.configuration.EELFManager;
+import org.apache.log4j.Logger;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.dmaap.datarouter.node.eelf.EelfMsgs;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStreamReader;
@@ -33,8 +37,6 @@ import java.io.Reader;
 import java.net.URL;
 import java.util.Properties;
 import java.util.Timer;
-import org.apache.log4j.Logger;
-import org.onap.dmaap.datarouter.node.eelf.EelfMsgs;
 
 
 /**
@@ -95,32 +97,54 @@ public class NodeConfigManager implements DeliveryQueueHelper {
     private String eventlogsuffix;
     private String eventloginterval;
     private boolean followredirects;
+    private String [] enabledprotocols;
+    private String aafType;
+    private String aafInstance;
+    private String aafAction;
+    private String aafURL;
+    private boolean cadiEnabled;
 
 
     /**
      * Get the default node configuration manager
      */
     public static NodeConfigManager getInstance() {
-        return (base);
+        return base;
     }
 
     /**
      * Initialize the configuration of a Data Router node
      */
     private NodeConfigManager() {
-        Properties p = new Properties();
+
+        Properties drNodeProperties = new Properties();
         try {
-            p.load(new FileInputStream(System
+            logger.info("NODE0301 Loading local config file node.properties");
+            drNodeProperties.load(new FileInputStream(System
                     .getProperty("org.onap.dmaap.datarouter.node.properties", "/opt/app/datartr/etc/node.properties")));
         } catch (Exception e) {
-
             NodeUtils.setIpAndFqdnForEelf("NodeConfigManager");
             eelflogger.error(EelfMsgs.MESSAGE_PROPERTIES_LOAD_ERROR);
             logger.error("NODE0301 Unable to load local configuration file " + System
-                            .getProperty("org.onap.dmaap.datarouter.node.properties", "/opt/app/datartr/etc/node.properties"),
-                    e);
+                            .getProperty("org.onap.dmaap.datarouter.node.properties", "/opt/app/datartr/etc/node.properties"), e);
         }
-        provurl = p.getProperty("ProvisioningURL", "https://feeds-drtr.web.att.com/internal/prov");
+        provurl = drNodeProperties.getProperty("ProvisioningURL", "https://dmaap-dr-prov:8443/internal/prov");
+        /*
+         * START - AAF changes: TDP EPIC US# 307413
+         * Pull AAF settings from node.properties
+         */
+        aafType = drNodeProperties.getProperty("AAFType", "org.onap.dmaap-dr.feed");
+        aafInstance = drNodeProperties.getProperty("AAFInstance", "legacy");
+        aafAction = drNodeProperties.getProperty("AAFAction", "publish");
+        aafURL = drNodeProperties.getProperty("AafUrl", "https://aaf-onap-test.osaaf.org:8095");
+        cadiEnabled = Boolean.parseBoolean(drNodeProperties.getProperty("CadiEnabled", "false"));
+        /*
+         * END - AAF changes: TDP EPIC US# 307413
+         * Pull AAF settings from node.properties
+         */
+        //Disable and enable protocols*/
+        enabledprotocols = ((drNodeProperties.getProperty("NodeHttpsProtocols")).trim()).split("\\|");
+
         try {
             provhost = (new URL(provurl)).getHost();
         } catch (Exception e) {
@@ -130,14 +154,14 @@ public class NodeConfigManager implements DeliveryQueueHelper {
             System.exit(1);
         }
         logger.info("NODE0303 Provisioning server is " + provhost);
-        eventlogurl = p.getProperty("LogUploadURL", "https://feeds-drtr.web.att.com/internal/logs");
+        eventlogurl = drNodeProperties.getProperty("LogUploadURL", "https://feeds-drtr.web.att.com/internal/logs");
         provcheck = new IsFrom(provhost);
-        gfport = Integer.parseInt(p.getProperty("IntHttpPort", "8080"));
-        svcport = Integer.parseInt(p.getProperty("IntHttpsPort", "8443"));
-        port = Integer.parseInt(p.getProperty("ExtHttpsPort", "443"));
-        long minpfinterval = Long.parseLong(p.getProperty("MinProvFetchInterval", "10000"));
-        long minrsinterval = Long.parseLong(p.getProperty("MinRedirSaveInterval", "10000"));
-        spooldir = p.getProperty("SpoolDir", "spool");
+        gfport = Integer.parseInt(drNodeProperties.getProperty("IntHttpPort", "8080"));
+        svcport = Integer.parseInt(drNodeProperties.getProperty("IntHttpsPort", "8443"));
+        port = Integer.parseInt(drNodeProperties.getProperty("ExtHttpsPort", "443"));
+        long minpfinterval = Long.parseLong(drNodeProperties.getProperty("MinProvFetchInterval", "10000"));
+        long minrsinterval = Long.parseLong(drNodeProperties.getProperty("MinRedirSaveInterval", "10000"));
+        spooldir = drNodeProperties.getProperty("SpoolDir", "spool");
         File fdir = new File(spooldir + "/f");
         fdir.mkdirs();
         for (File junk : fdir.listFiles()) {
@@ -145,26 +169,26 @@ public class NodeConfigManager implements DeliveryQueueHelper {
                 junk.delete();
             }
         }
-        logdir = p.getProperty("LogDir", "logs");
+        logdir = drNodeProperties.getProperty("LogDir", "logs");
         (new File(logdir)).mkdirs();
-        logretention = Long.parseLong(p.getProperty("LogRetention", "30")) * 86400000L;
+        logretention = Long.parseLong(drNodeProperties.getProperty("LogRetention", "30")) * 86400000L;
         eventlogprefix = logdir + "/events";
         eventlogsuffix = ".log";
-        String redirfile = p.getProperty("RedirectionFile", "etc/redirections.dat");
-        kstype = p.getProperty("KeyStoreType", "jks");
-        ksfile = p.getProperty("KeyStoreFile", "etc/keystore");
-        kspass = p.getProperty("KeyStorePassword", "changeme");
-        kpass = p.getProperty("KeyPassword", "changeme");
-        tstype = p.getProperty("TrustStoreType", "jks");
-        tsfile = p.getProperty("TrustStoreFile");
-        tspass = p.getProperty("TrustStorePassword", "changeme");
+        String redirfile = drNodeProperties.getProperty("RedirectionFile", "etc/redirections.dat");
+        kstype = drNodeProperties.getProperty("KeyStoreType", "jks");
+        ksfile = drNodeProperties.getProperty("KeyStoreFile", "etc/keystore");
+        kspass = drNodeProperties.getProperty("KeyStorePassword", "changeme");
+        kpass = drNodeProperties.getProperty("KeyPassword", "changeme");
+        tstype = drNodeProperties.getProperty("TrustStoreType", "jks");
+        tsfile = drNodeProperties.getProperty("TrustStoreFile");
+        tspass = drNodeProperties.getProperty("TrustStorePassword", "changeme");
         if (tsfile != null && tsfile.length() > 0) {
             System.setProperty("javax.net.ssl.trustStoreType", tstype);
             System.setProperty("javax.net.ssl.trustStore", tsfile);
             System.setProperty("javax.net.ssl.trustStorePassword", tspass);
         }
-        nak = p.getProperty("NodeAuthKey", "Node123!");
-        quiesce = new File(p.getProperty("QuiesceFile", "etc/SHUTDOWN"));
+        nak = drNodeProperties.getProperty("NodeAuthKey", "Node123!");
+        quiesce = new File(drNodeProperties.getProperty("QuiesceFile", "etc/SHUTDOWN"));
         myname = NodeUtils.getCanonicalName(kstype, ksfile, kspass);
         if (myname == null) {
             NodeUtils.setIpAndFqdnForEelf("NodeConfigManager");
@@ -253,7 +277,7 @@ public class NodeConfigManager implements DeliveryQueueHelper {
 
     private void fetchconfig() {
         try {
-            System.out.println("provurl:: " + provurl);
+            logger.info("NodeConfigMan.fetchConfig: provurl:: " + provurl);
             Reader r = new InputStreamReader((new URL(provurl)).openStream());
             config = new NodeConfig(new ProvData(r), myname, spooldir, port, nak);
             localconfig();
@@ -263,6 +287,7 @@ public class NodeConfigManager implements DeliveryQueueHelper {
                 try {
                     rr.run();
                 } catch (Exception e) {
+                    logger.error("NODE0518 Exception fetchconfig: " + e);
                 }
             }
         } catch (Exception e) {
@@ -278,12 +303,12 @@ public class NodeConfigManager implements DeliveryQueueHelper {
      * fetch the provisioning data, ignore the request.  If the data has been fetched very recently (default 10
      * seconds), wait a while before fetching again.
      */
-    public synchronized void gofetch(String remoteaddr) {
-        if (provcheck.isFrom(remoteaddr)) {
-            logger.info("NODE0307 Received configuration fetch request from provisioning server " + remoteaddr);
+    public synchronized void gofetch(String remoteAddr) {
+        if (provcheck.isReachable(remoteAddr)) {
+            logger.info("NODE0307 Received configuration fetch request from provisioning server " + remoteAddr);
             pfetcher.request();
         } else {
-            logger.info("NODE0308 Received configuration fetch request from unexpected server " + remoteaddr);
+            logger.info("NODE0308 Received configuration fetch request from unexpected server " + remoteAddr);
         }
     }
 
@@ -344,6 +369,17 @@ public class NodeConfigManager implements DeliveryQueueHelper {
         return (config.isDeletePermitted(subId));
     }
 
+    /**
+     * Check whether publication is allowed for AAF Feed.
+     *
+     * @param feedid The ID of the feed being requested
+     * @param ip The requesting IP address
+     * @return True if the IP and credentials are valid for the specified feed.
+     */
+    public String isPublishPermitted(String feedid, String ip) {
+        return(config.isPublishPermitted(feedid, ip));
+    }
+        
     /**
      * Check who the user is given the feed ID and the offered credentials.
      *
@@ -355,6 +391,15 @@ public class NodeConfigManager implements DeliveryQueueHelper {
         return (config.getAuthUser(feedid, credentials));
     }
 
+    /**
+     * AAF changes: TDP EPIC US# 307413
+     * Check AAF_instance for feed ID in NodeConfig
+     * @param feedid The ID of the feed specified
+     */
+    public String getAafInstance(String feedid) {
+        return(config.getAafInstance(feedid));
+    }
+
     /**
      * Check if the publish request should be sent to another node based on the feedid, user, and source IP address.
      *
@@ -460,6 +505,23 @@ public class NodeConfigManager implements DeliveryQueueHelper {
         return (false);
     }
 
+    /**
+     * Set up redirection on receipt of a 3XX from a target URL
+     */
+    public boolean handleRedirectionSubLevel(DeliveryTask task, DestInfo destinfo, String redirto, String fileid) {
+        fileid = "/" + fileid;
+        String subid = destinfo.getSubId();
+        String purl = destinfo.getURL();
+        if (task.getFollowRedirects() && subid != null && redirto.endsWith(fileid)) {
+            redirto = redirto.substring(0, redirto.length() - fileid.length());
+            if (!redirto.equals(purl)) {
+                rdmgr.redirect(subid, purl, redirto);
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Handle unreachable target URL
      */
@@ -529,6 +591,15 @@ public class NodeConfigManager implements DeliveryQueueHelper {
         return (config.getTargets(feedid));
     }
 
+    /**
+     * Get the creation date for a feed
+     * @param feedid The feed ID
+     * @return the timestamp of creation date of feed id passed
+     */
+    public String getCreatedDate(String feedid) {
+        return(config.getCreatedDate(feedid));
+    }
+
     /**
      * Get the spool directory for temporary files
      */
@@ -697,6 +768,16 @@ public class NodeConfigManager implements DeliveryQueueHelper {
         return (fdpstop);
     }
 
+    /**
+     * Disable and enable protocols
+     * */
+    public String[] getEnabledprotocols() {
+        return enabledprotocols;
+    }
+    public void setEnabledprotocols(String[] enabledprotocols) {
+        this.enabledprotocols = enabledprotocols.clone();
+    }
+
     /**
      * Get the spool directory for a subscription
      */
@@ -716,4 +797,59 @@ public class NodeConfigManager implements DeliveryQueueHelper {
             return (null);
         }
     }
+
+    public String getAafType() {
+        return aafType;
+    }
+    public void setAafType(String aafType) {
+        this.aafType = aafType;
+    }
+    public String getAafInstance() {
+        return aafInstance;
+    }
+    public void setAafInstance(String aafInstance) {
+        this.aafInstance = aafInstance;
+    }
+    public String getAafAction() {
+        return aafAction;
+    }
+    public void setAafAction(String aafAction) {
+        this.aafAction = aafAction;
+    }
+    /*
+     * Get aafURL from SWM variable
+     * */
+    public String getAafURL() {
+        return aafURL;
+    }
+    public void setAafURL(String aafURL) {
+        this.aafURL = aafURL;
+    }
+
+    public boolean getCadiEnabeld() {
+        return cadiEnabled;
+    }
+    public void setCadiEnabled(boolean cadiEnabled) {
+        this.cadiEnabled = cadiEnabled;
+    }
+
+    /**
+     * Builds the permissions string to be verified
+     *
+     * @param aafInstance The aaf instance
+     * @return The permissions
+     */
+    protected String getPermission(String aafInstance) {
+        try {
+            String type = getAafType();
+            String action = getAafAction();
+            if (aafInstance == null || aafInstance.equals("")) {
+                aafInstance = getAafInstance();
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            logger.error("NODE0543 NodeConfigManager.getPermission: ", e);
+        }
+        return null;
+    }
 }
index d25531a..7ff33ff 100644 (file)
 
 package org.onap.dmaap.datarouter.node;
 
-import java.util.Arrays;
 import org.apache.log4j.Logger;
 import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.server.*;
+import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.onap.aaf.cadi.PropAccess;
+
+import javax.servlet.DispatcherType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.EnumSet;
+import java.util.Properties;
 
 /**
  * The main starting point for the Data Router node
@@ -47,6 +48,18 @@ public class NodeMain {
 
     private static Logger nodeMainLogger = Logger.getLogger("org.onap.dmaap.datarouter.node.NodeMain");
 
+    class Inner {
+        InputStream getCadiProps() {
+            InputStream in = null;
+            try {
+                in = getClass().getClassLoader().getResourceAsStream("drNodeCadi.properties");
+            } catch (Exception e) {
+                nodeMainLogger.error("Exception in Inner.getCadiProps() method " + e.getMessage());
+            }
+            return in;
+        }
+    }
+
     private static class WaitForConfig implements Runnable {
 
         private NodeConfigManager localNodeConfigManager;
@@ -67,8 +80,8 @@ public class NodeMain {
                     wait();
                 } catch (Exception exception) {
                     nodeMainLogger
-                        .debug("NodeMain: waitForConfig exception. Exception Message:- " + exception.toString(),
-                            exception);
+                            .debug("NodeMain: waitForConfig exception. Exception Message:- " + exception.toString(),
+                                    exception);
                 }
             }
             localNodeConfigManager.deregisterConfigTask(this);
@@ -89,8 +102,8 @@ public class NodeMain {
     /**
      * Start the data router.
      * <p>
-     * The location of the node configuration file can be set using the org.onap.dmaap.datarouter.node.ConfigFile system
-     * property.  By default, it is "etc/node.properties".
+     * The location of the node configuration file can be set using the org.onap.dmaap.datarouter.node.properties system
+     * property.  By default, it is "/opt/app/datartr/etc/node.properties".
      */
     public static void main(String[] args) throws Exception {
         nodeMainLogger.info("NODE0001 Data Router Node Starting");
@@ -100,15 +113,15 @@ public class NodeMain {
         (new WaitForConfig(nodeConfigManager)).waitForConfig();
         delivery = new Delivery(nodeConfigManager);
         new LogManager(nodeConfigManager);
+
         Server server = new Server();
+
         // HTTP configuration
         HttpConfiguration httpConfiguration = new HttpConfiguration();
         httpConfiguration.setRequestHeaderSize(2048);
 
         // HTTP connector
-        ServletContextHandler ctxt;
-        try (ServerConnector httpServerConnector = new ServerConnector(server,
-            new HttpConnectionFactory(httpConfiguration))) {
+        try (ServerConnector httpServerConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration))) {
             httpServerConnector.setPort(nodeConfigManager.getHttpPort());
             httpServerConnector.setIdleTimeout(2000);
 
@@ -118,10 +131,23 @@ public class NodeMain {
             sslContextFactory.setKeyStorePath(nodeConfigManager.getKSFile());
             sslContextFactory.setKeyStorePassword(nodeConfigManager.getKSPass());
             sslContextFactory.setKeyManagerPassword(nodeConfigManager.getKPass());
-            /* Skip SSLv3 Fixes */
+
+            //SP-6 : Fixes for SDV scan to exclude/remove DES/3DES ciphers are taken care by upgrading jdk in descriptor.xml
+            sslContextFactory.setExcludeCipherSuites(
+                    "SSL_RSA_WITH_DES_CBC_SHA",
+                    "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+                    "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+                    "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+                    "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                    "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                    "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
+            );
+
             sslContextFactory.addExcludeProtocols("SSLv3");
-            nodeMainLogger.info("Excluded protocols node-" + Arrays.toString(sslContextFactory.getExcludeProtocols()));
-            /* End of SSLv3 Fixes */
+            sslContextFactory.setIncludeProtocols(nodeConfigManager.getEnabledprotocols());
+            nodeMainLogger.info("NODE00004 Unsupported protocols node server:-" + String.join(",", sslContextFactory.getExcludeProtocols()));
+            nodeMainLogger.info("NODE00004 Supported protocols node server:-" + String.join(",", sslContextFactory.getIncludeProtocols()));
+            nodeMainLogger.info("NODE00004 Unsupported ciphers node server:-" + String.join(",", sslContextFactory.getExcludeCipherSuites()));
 
             HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration);
             httpsConfiguration.setRequestHeaderSize(8192);
@@ -133,21 +159,47 @@ public class NodeMain {
 
             // HTTPS connector
             try (ServerConnector httpsServerConnector = new ServerConnector(server,
-                new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
-                new HttpConnectionFactory(httpsConfiguration))) {
+                    new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
+                    new HttpConnectionFactory(httpsConfiguration))) {
+
                 httpsServerConnector.setPort(nodeConfigManager.getHttpsPort());
-                httpsServerConnector.setIdleTimeout(500000);
+                httpsServerConnector.setIdleTimeout(3600000);
                 httpsServerConnector.setAcceptQueueSize(2);
 
+                //Context Handler
+                ServletContextHandler servletContextHandler = new ServletContextHandler(0);
+                servletContextHandler.setContextPath("/");
+                servletContextHandler.addServlet(new ServletHolder(new NodeServlet(delivery)), "/*");
+
+                //CADI Filter activation check
+                if (nodeConfigManager.getCadiEnabeld()) {
+                    Properties cadiProperties = new Properties();
+                    try {
+                        Inner obj = new NodeMain().new Inner();
+                        InputStream in = obj.getCadiProps();
+                        cadiProperties.load(in);
+                    } catch (IOException e1) {
+                        nodeMainLogger.error("NODE00005 Exception in NodeMain.Main() loading CADI properties " + e1.getMessage());
+                    }
+                    cadiProperties.setProperty("aaf_locate_url", nodeConfigManager.getAafURL());
+                    nodeMainLogger.info("NODE00005  aaf_url set to - " + cadiProperties.getProperty("aaf_url"));
+
+                    PropAccess access = new PropAccess(cadiProperties);
+                    servletContextHandler.addFilter(new FilterHolder(new DRNodeCadiFilter(true, access)), "/*", EnumSet.of(DispatcherType.REQUEST));
+                }
+
+                server.setHandler(servletContextHandler);
                 server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector});
             }
         }
-        ctxt = new ServletContextHandler(0);
-        ctxt.setContextPath("/");
-        server.setHandler(ctxt);
-        ctxt.addServlet(new ServletHolder(new NodeServlet(delivery)), "/*");
-        nodeMainLogger.info("NODE0005 Data Router Node Activating Service");
-        server.start();
+
+        try {
+            server.start();
+            nodeMainLogger.info("NODE00006 Node Server started-" + server.getState());
+        } catch (Exception e) {
+            nodeMainLogger.info("NODE00006 Jetty failed to start. Reporting will we unavailable", e);
+        }
         server.join();
+        nodeMainLogger.info("NODE00007 Node Server joined - " + server.getState());
     }
 }
index 7988879..93e901f 100644 (file)
@@ -26,25 +26,24 @@ package org.onap.dmaap.datarouter.node;
 
 import com.att.eelf.configuration.EELFLogger;
 import com.att.eelf.configuration.EELFManager;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
+import org.apache.log4j.Logger;
+import org.onap.dmaap.datarouter.node.eelf.EelfMsgs;
+import org.slf4j.MDC;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Enumeration;
 import java.util.regex.Pattern;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.log4j.Logger;
+
+import static org.onap.dmaap.datarouter.node.NodeUtils.sendResponseError;
+
 import org.jetbrains.annotations.Nullable;
-import org.onap.dmaap.datarouter.node.eelf.EelfMsgs;
-import org.slf4j.MDC;
 
 import static org.onap.dmaap.datarouter.node.NodeUtils.*;
 
@@ -64,9 +63,8 @@ public class NodeServlet extends HttpServlet {
     private static Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.node.NodeServlet");
     private static NodeConfigManager config;
     private static Pattern MetaDataPattern;
-    //Adding EELF Logger Rally:US664892
-    private static EELFLogger eelflogger = EELFManager.getInstance()
-            .getLogger(NodeServlet.class);
+    private static EELFLogger eelflogger = EELFManager.getInstance().getLogger(NodeServlet.class);
+    private boolean isAAFFeed = false;
     private final Delivery delivery;
 
     static {
@@ -88,6 +86,7 @@ public class NodeServlet extends HttpServlet {
     /**
      * Get the NodeConfigurationManager
      */
+    @Override
     public void init() {
         config = NodeConfigManager.getInstance();
         logger.info("NODE0101 Node Servlet Configured");
@@ -97,14 +96,15 @@ public class NodeServlet extends HttpServlet {
         if (config.isShutdown() || !config.isConfigured()) {
             sendResponseError(resp, HttpServletResponse.SC_SERVICE_UNAVAILABLE, logger);
             logger.info("NODE0102 Rejecting request: Service is being quiesced");
-            return (true);
+            return true;
         }
-        return (false);
+        return false;
     }
 
     /**
      * Handle a GET for /internal/fetchProv
      */
+    @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
         NodeUtils.setIpAndFqdnForEelf("doGet");
         NodeUtils.setRequestIdAndInvocationId(req);
@@ -149,12 +149,13 @@ public class NodeServlet extends HttpServlet {
     /**
      * Handle all PUT requests
      */
+    @Override
     protected void doPut(HttpServletRequest req, HttpServletResponse resp) {
         NodeUtils.setIpAndFqdnForEelf("doPut");
         NodeUtils.setRequestIdAndInvocationId(req);
         eelflogger.info(EelfMsgs.ENTRY);
         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader("X-DMAAP-DR-ON-BEHALF-OF"),
-                    getIdFromPath(req) + "");
+                getIdFromPath(req) + "");
         try {
             common(req, resp, true);
         } catch (IOException ioe) {
@@ -166,6 +167,7 @@ public class NodeServlet extends HttpServlet {
     /**
      * Handle all DELETE requests
      */
+    @Override
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) {
         NodeUtils.setIpAndFqdnForEelf("doDelete");
         NodeUtils.setRequestIdAndInvocationId(req);
@@ -215,6 +217,27 @@ public class NodeServlet extends HttpServlet {
                 return;
             }
             feedid = fileid.substring(0, i);
+
+            if (config.getCadiEnabeld()) {
+                String path = req.getPathInfo();
+                if (!path.startsWith("/internal") && feedid != null) {
+                    String aafInstance = config.getAafInstance(feedid);
+                    if (!(aafInstance.equalsIgnoreCase("legacy"))) {
+                        isAAFFeed = true;
+                        String permission = config.getPermission(aafInstance);
+                        logger.info("NodeServlet.common() permission string - " + permission);
+                        //Check in CADI Framework API if user has AAF permission or not
+                        if (!req.isUserInRole(permission)) {
+                            String message = "AAF disallows access to permission string - " + permission;
+                            logger.info("NODE0106 Rejecting unauthenticated PUT or DELETE of " + req.getPathInfo() + " from " + req.getRemoteAddr());
+                            resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);
+                            eelflogger.info(EelfMsgs.EXIT);
+                            return;
+                        }
+                    }
+                }
+            }
+
             fileid = fileid.substring(i + 1);
             pubid = config.getPublishId();
             xpubid = req.getHeader("X-DMAAP-DR-PUBLISH-ID");
@@ -228,6 +251,7 @@ public class NodeServlet extends HttpServlet {
             }
             fileid = fileid.substring(18);
             pubid = req.getHeader("X-DMAAP-DR-PUBLISH-ID");
+            user = "datartr";   // SP6 : Added usr as datartr to avoid null entries for internal routing
             targets = config.parseRouting(req.getHeader("X-DMAAP-DR-ROUTING"));
         } else {
             logger.info("NODE0105 Rejecting bad URI for PUT or DELETE of " + req.getPathInfo() + " from " + req
@@ -257,17 +281,34 @@ public class NodeServlet extends HttpServlet {
         String logurl = "https://" + hp + "/internal/publish/" + fileid;
         if (feedid != null) {
             logurl = "https://" + hp + "/publish/" + feedid + "/" + fileid;
-            String reason = config.isPublishPermitted(feedid, credentials, ip);
-            if (reason != null) {
-                logger.info(
-                        "NODE0111 Rejecting unauthorized publish attempt to feed " + feedid + " fileid " + fileid
-                                + " from "
-                                + ip + " reason " + reason);
-                resp.sendError(HttpServletResponse.SC_FORBIDDEN, reason);
-                eelflogger.info(EelfMsgs.EXIT);
-                return;
+            //Cadi code starts
+            if (!isAAFFeed) {
+                String reason = config.isPublishPermitted(feedid, credentials, ip);
+                if (reason != null) {
+                    logger.info("NODE0111 Rejecting unauthorized publish attempt to feed " + PathUtil.cleanString(feedid) + " fileid " + PathUtil.cleanString(fileid) + " from " + PathUtil.cleanString(ip) + " reason " + PathUtil.cleanString(reason));
+                    resp.sendError(HttpServletResponse.SC_FORBIDDEN, reason);
+                    eelflogger.info(EelfMsgs.EXIT);
+                    return;
+                }
+                user = config.getAuthUser(feedid, credentials);
+            } else {
+                String reason = config.isPublishPermitted(feedid, ip);
+                if (reason != null) {
+                    logger.info("NODE0111 Rejecting unauthorized publish attempt to feed " + PathUtil.cleanString(feedid) + " fileid " + PathUtil.cleanString(fileid) + " from " + PathUtil.cleanString(ip) + " reason   Invalid AAF user- " + PathUtil.cleanString(reason));
+                    String message = "Invalid AAF user- " + PathUtil.cleanString(reason);
+                    logger.info("NODE0106 Rejecting unauthenticated PUT or DELETE of " + PathUtil.cleanString(req.getPathInfo()) + " from " + PathUtil.cleanString(req.getRemoteAddr()));
+                    resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);
+                    return;
+                }
+                if ((req.getUserPrincipal() != null) && (req.getUserPrincipal().getName() != null)) {
+                    String userName = req.getUserPrincipal().getName();
+                    String[] attid = userName.split("@");
+                    user = attid[0];
+                } else {
+                    user = "AAFUser";
+                }
             }
-            user = config.getAuthUser(feedid, credentials);
+            //Cadi code Ends
             String newnode = config.getIngressNode(feedid, user, ip);
             if (newnode != null) {
                 String port = "";
@@ -276,17 +317,17 @@ public class NodeServlet extends HttpServlet {
                     port = ":" + iport;
                 }
                 String redirto = "https://" + newnode + port + "/publish/" + feedid + "/" + fileid;
-                logger.info(
-                        "NODE0108 Redirecting publish attempt for feed " + feedid + " user " + user + " ip " + ip
-                                + " to "
-                                + redirto);
-                resp.sendRedirect(redirto);
+                logger.info("NODE0108 Redirecting publish attempt for feed " + PathUtil.cleanString(feedid) + " user " + PathUtil.cleanString(user) + " ip " + PathUtil.cleanString(ip) + " to " + PathUtil.cleanString(redirto));  //Fortify scan fixes - log forging
+                resp.sendRedirect(PathUtil.cleanString(redirto));         //Fortify scan fixes-open redirect - 2 issues
                 eelflogger.info(EelfMsgs.EXIT);
                 return;
             }
             resp.setHeader("X-DMAAP-DR-PUBLISH-ID", pubid);
         }
-        String fbase = config.getSpoolDir() + "/" + pubid;
+        if (req.getPathInfo().startsWith("/internal/publish/")) {
+            feedid = req.getHeader("X-DMAAP-DR-FEED-ID");
+        }
+        String fbase = PathUtil.cleanString(config.getSpoolDir() + "/" + pubid);  //Fortify scan fixes-Path manipulation
         File data = new File(fbase);
         File meta = new File(fbase + ".M");
         OutputStream dos = null;
@@ -323,17 +364,13 @@ public class NodeServlet extends HttpServlet {
                         }
                         if ("x-dmaap-dr-meta".equals(hnlc)) {
                             if (hv.length() > 4096) {
-                                logger.info(
-                                        "NODE0109 Rejecting publish attempt with metadata too long for feed " + feedid
-                                                + " user " + user + " ip " + ip);
+                                logger.info("NODE0109 Rejecting publish attempt with metadata too long for feed " + PathUtil.cleanString(feedid) + " user " + PathUtil.cleanString(user) + " ip " + PathUtil.cleanString(ip));  //Fortify scan fixes - log forging
                                 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Metadata too long");
                                 eelflogger.info(EelfMsgs.EXIT);
                                 return;
                             }
                             if (!MetaDataPattern.matcher(hv.replaceAll("\\\\.", "X")).matches()) {
-                                logger.info(
-                                        "NODE0109 Rejecting publish attempt with malformed metadata for feed " + feedid
-                                                + " user " + user + " ip " + ip);
+                                logger.info("NODE0109 Rejecting publish attempt with malformed metadata for feed " + PathUtil.cleanString(feedid) + " user " + PathUtil.cleanString(user) + " ip " + PathUtil.cleanString(ip));  //Fortify scan fixes - log forging
                                 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Malformed metadata");
                                 eelflogger.info(EelfMsgs.EXIT);
                                 return;
@@ -343,10 +380,10 @@ public class NodeServlet extends HttpServlet {
                     }
                 }
             }
-            if(!hasRequestIdHeader){
+            if (!hasRequestIdHeader) {
                 mx.append("X-ONAP-RequestID\t").append(MDC.get("RequestId")).append('\n');
             }
-            if(!hasInvocationIdHeader){
+            if (!hasInvocationIdHeader) {
                 mx.append("X-InvocationID\t").append(MDC.get("InvocationId")).append('\n');
             }
             mx.append("X-DMAAP-DR-RECEIVED\t").append(rcvd).append('\n');
@@ -368,9 +405,9 @@ public class NodeServlet extends HttpServlet {
                 try {
                     exlen = Long.parseLong(req.getHeader("Content-Length"));
                 } catch (Exception e) {
+                    logger.error("NODE0529 Exception common: " + e);
                 }
-                StatusLog.logPubFail(pubid, feedid, logurl, req.getMethod(), ctype, exlen, data.length(), ip, user,
-                        ioe.getMessage());
+                StatusLog.logPubFail(pubid, feedid, logurl, req.getMethod(), ctype, exlen, data.length(), ip, user, ioe.getMessage());
                 eelflogger.info(EelfMsgs.EXIT);
                 throw ioe;
             }
@@ -381,7 +418,7 @@ public class NodeServlet extends HttpServlet {
                     // TODO: unknown destination
                     continue;
                 }
-                String dbase = di.getSpool() + "/" + pubid;
+                String dbase = PathUtil.cleanString(di.getSpool() + "/" + pubid);  //Fortify scan fixes-Path Manipulation
                 Files.createLink(Paths.get(dbase), dpath);
                 mw = new FileWriter(meta);
                 mw.write(metadata);
@@ -393,13 +430,25 @@ public class NodeServlet extends HttpServlet {
 
             }
             resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
-            resp.getOutputStream().close();
-            StatusLog.logPub(pubid, feedid, logurl, req.getMethod(), ctype, data.length(), ip, user,
-                    HttpServletResponse.SC_NO_CONTENT);
+            try {
+                resp.getOutputStream().close();
+            } catch (IOException ioe) {
+                long exlen = -1;
+                try {
+                    exlen = Long.parseLong(req.getHeader("Content-Length"));
+                } catch (Exception e) {
+                    logger.debug("NODE00000 Exception common: " + e);
+                }
+                StatusLog.logPubFail(pubid, feedid, logurl, req.getMethod(), ctype, exlen, data.length(), ip, user, ioe.getMessage());
+                //Fortify scan fixes - log forging
+                logger.info("NODE0110 IO Exception while closing IO stream " + PathUtil.cleanString(feedid) + " user " + PathUtil.cleanString(user) + " ip " + PathUtil.cleanString(ip) + " " + ioe.toString(), ioe);
+
+                throw ioe;
+            }
+
+            StatusLog.logPub(pubid, feedid, logurl, req.getMethod(), ctype, data.length(), ip, user, HttpServletResponse.SC_NO_CONTENT);
         } catch (IOException ioe) {
-            logger.info(
-                    "NODE0110 IO Exception receiving publish attempt for feed " + feedid + " user " + user + " ip " + ip
-                            + " " + ioe.toString(), ioe);
+            logger.info("NODE0110 IO Exception receiving publish attempt for feed " + feedid + " user " + user + " ip " + ip + " " + ioe.toString(), ioe);
             eelflogger.info(EelfMsgs.EXIT);
             throw ioe;
         } finally {
@@ -407,27 +456,32 @@ public class NodeServlet extends HttpServlet {
                 try {
                     is.close();
                 } catch (Exception e) {
+                    logger.error("NODE0530 Exception common: " + e);
                 }
             }
             if (dos != null) {
                 try {
                     dos.close();
                 } catch (Exception e) {
+                    logger.error("NODE0531 Exception common: " + e);
                 }
             }
             if (mw != null) {
                 try {
                     mw.close();
                 } catch (Exception e) {
+                    logger.error("NODE0532 Exception common: " + e);
                 }
             }
             try {
                 data.delete();
             } catch (Exception e) {
+                logger.error("NODE0533 Exception common: " + e);
             }
             try {
                 meta.delete();
             } catch (Exception e) {
+                logger.error("NODE0534 Exception common: " + e);
             }
         }
     }
@@ -448,7 +502,7 @@ public class NodeServlet extends HttpServlet {
             int subId = Integer.parseInt(subscriptionId);
             pubid = fileid.substring(i + 1);
             String errorMessage = "Unable to delete files (" + pubid + ", " + pubid + ".M) from DR Node: "
-                            + config.getMyName() + ".";
+                    + config.getMyName() + ".";
             int subIdDir = subId - (subId % 100);
             if (!isAuthorizedToDelete(resp, subscriptionId, errorMessage)) {
                 return;
diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/PathUtil.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/PathUtil.java
new file mode 100644 (file)
index 0000000..a403441
--- /dev/null
@@ -0,0 +1,88 @@
+/**\r
+ * -\r
+ * ============LICENSE_START=======================================================\r
+ * Copyright (C) 2019 Nordix Foundation.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * <p>\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * <p>\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * <p>\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+package org.onap.dmaap.datarouter.node;\r
+\r
+/**\r
+ * FORTIFY SCAN FIXES\r
+ * <p>This Utility is used for Fortify fixes. It Validates the path url formed from\r
+ *  the string passed in the request parameters.</p>\r
+ *\r
+ */\r
+class PathUtil {\r
+\r
+    /**\r
+     * This method takes String as the parameter and return the filtered path string.\r
+     * @param aString String to clean\r
+     * @return A cleaned String\r
+     */\r
+    static String cleanString(String aString) {\r
+        if (aString == null) return null;\r
+        String cleanString = "";\r
+        for (int i = 0; i < aString.length(); ++i) {\r
+            cleanString += cleanChar(aString.charAt(i));\r
+        }\r
+        return cleanString;\r
+    }\r
+\r
+    /**\r
+     * This method filters the valid special characters in path string.\r
+     * @param aChar The char to be cleaned\r
+     * @return The cleaned char\r
+     */\r
+    private static char cleanChar(char aChar) {\r
+        // 0 - 9\r
+        for (int i = 48; i < 58; ++i) {\r
+            if (aChar == i) return (char) i;\r
+        }\r
+        // 'A' - 'Z'\r
+        for (int i = 65; i < 91; ++i) {\r
+            if (aChar == i) return (char) i;\r
+        }\r
+        // 'a' - 'z'\r
+        for (int i = 97; i < 123; ++i) {\r
+            if (aChar == i) return (char) i;\r
+        }\r
+        // other valid characters\r
+        switch (aChar) {\r
+            case '/':\r
+                return '/';\r
+            case '.':\r
+                return '.';\r
+            case '-':\r
+                return '-';\r
+            case ':':\r
+                return ':';\r
+            case '?':\r
+                return '?';\r
+            case '&':\r
+                return '&';\r
+            case '=':\r
+                return '=';\r
+            case '#':\r
+                return '#';\r
+            case '_':\r
+                return '_';\r
+            case ' ':\r
+                return ' ';\r
+        }\r
+        return '%';\r
+    }\r
+}\r
index 77c5e99..a9c5c6f 100644 (file)
@@ -135,7 +135,17 @@ public class ProvData {
                     String fid = gvas(jfeed, "feedid");
                     String fname = gvas(jfeed, "name");
                     String fver = gvas(jfeed, "version");
-                    pfv.add(new NodeConfig.ProvFeed(fid, fname + "//" + fver, stat));
+                    String createdDate = gvas(jfeed, "created_date");
+                    /*
+                     * START - AAF changes
+                     * TDP EPIC US# 307413
+                     * Passing aafInstance to ProvFeed from feeds json passed by prov to identify legacy/AAF feeds
+                     */
+                    String aafInstance = gvas(jfeed, "aaf_instance");
+                    pfv.add(new NodeConfig.ProvFeed(fid, fname + "//" + fver, stat,createdDate, aafInstance));
+                    /*
+                     * END - AAF changes
+                     */
                     JSONObject jauth = jfeed.optJSONObject("authorization");
                     if (jauth == null) {
                         continue;
@@ -175,7 +185,8 @@ public class ProvData {
                     boolean use100 = jdel.getBoolean("use100");
                     boolean privilegedSubscriber = jsub.getBoolean("privilegedSubscriber");
                     boolean decompress = jsub.getBoolean("decompress");
-                    psv.add(new NodeConfig.ProvSubscription(sid, fid, delurl, id, NodeUtils.getAuthHdr(id, password), monly, use100, privilegedSubscriber, decompress));
+                    boolean followRedirect = jsub.getBoolean("follow_redirect");
+                    psv.add(new NodeConfig.ProvSubscription(sid, fid, delurl, id, NodeUtils.getAuthHdr(id, password), monly, use100, privilegedSubscriber, followRedirect, decompress));
                 }
             }
             JSONObject jparams = jcfg.optJSONObject("parameters");
index 2e83e22..6f74df4 100644 (file)
@@ -24,8 +24,6 @@
 
 package org.onap.dmaap.datarouter.node;
 
-import java.net.*;
-
 /**
  * Compare IP addresses as byte arrays to a subnet specified as a CIDR
  */
diff --git a/datarouter-node/src/main/resources/drNodeCadi.properties b/datarouter-node/src/main/resources/drNodeCadi.properties
new file mode 100644 (file)
index 0000000..8dfcab1
--- /dev/null
@@ -0,0 +1,23 @@
+cadi_x509_issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US
+cadi_keyfile=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.keyfile
+cadi_keystore=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
+cadi_keystore_password=]3V)($O&.Mv]W{f8^]6SxGNL
+cadi_key_password=]3V)($O&.Mv]W{f8^]6SxGNL
+cadi_alias=dmaap-dr-node@dmaap-dr.onap.org
+cadi_truststore=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
+cadi_truststore_password=(Rd,&{]%ePdp}4JZjqoJ2G+g
+
+aaf_env=DEV
+aaf_locate_url=https://aaf-onap-test.osaaf.org:8095
+aaf_oauth2_introspect_url=https://AAF_LOCATE_URL/AAF_NS.introspect:2.1/introspect
+aaf_oauth2_token_url=https://AAF_LOCATE_URL/AAF_NS.token:2.1/token
+aaf_url=https://AAF_LOCATE_URL/AAF_NS.service:2.1
+cadi_protocols=TLSv1.1,TLSv1.2
+cm_url=https://AAF_LOCATE_URL/AAF_NS.cm:2.1
+fs_url=https://AAF_LOCATE_URL/AAF_NS.fs.2.1
+gui_url=https://AAF_LOCATE_URL/AAF_NS.gui.2.1
+
+cadi_latitude=53.423
+cadi_longitude=7.940
+
+cadi_loglevel=DEBUG
\ No newline at end of file
index 8b5568b..27e91c9 100644 (file)
 # *
 #-------------------------------------------------------------------------------
 #
-#    Configuration parameters fixed at startup for the DataRouter node
+#    Configuration parameters set at startup for the DataRouter node
 #
 #    URL to retrieve dynamic configuration
-#
-#ProvisioningURL:    ${DRTR_PROV_INTURL}
-ProvisioningURL=https://dmaap-dr-prov:8443/internal/prov
-
+ProvisioningURL = https://dmaap-dr-prov:8443/internal/prov
 #
 #    URL to upload PUB/DEL/EXP logs
-#
-#LogUploadURL:    ${DRTR_LOG_URL}
-LogUploadURL=https://dmaap-dr-prov:8443/internal/logs
-
+LogUploadURL = https://dmaap-dr-prov:8443/internal/logs
 #
 #    The port number for http as seen within the server
-#
-#IntHttpPort:    ${DRTR_NODE_INTHTTPPORT:-8080}
-IntHttpPort=8080
+IntHttpPort = 8080
 #
 #    The port number for https as seen within the server
-#
-IntHttpsPort=8443
+IntHttpsPort = 8443
 #
 #    The external port number for https taking port mapping into account
+ExtHttpsPort = 443
 #
-ExtHttpsPort=443
-#
-#    The minimum interval between fetches of the dynamic configuration
-#    from the provisioning server
-#
-MinProvFetchInterval=10000
+#    The minimum interval between fetches of the dynamic configuration from the provisioning server
+MinProvFetchInterval = 10000
 #
 #    The minimum interval between saves of the redirection data file
-#
-MinRedirSaveInterval=10000
+MinRedirSaveInterval = 10000
 #
 #    The path to the directory where log files are stored
-#
-LogDir=/opt/app/datartr/logs
+LogDir = /opt/app/datartr/logs
 #
 #    The retention interval (in days) for log files
-#
-LogRetention=30
+LogRetention = 30
 #
 #    The path to the directories where data and meta data files are stored
-#
-SpoolDir=/opt/app/datartr/spool
+SpoolDir = /opt/app/datartr/spool
 #
 #    The path to the redirection data file
-#
-#RedirectionFile:    etc/redirections.dat
+RedirectionFile = etc/redirections.dat
 #
 #    The type of keystore for https
-KeyStoreType:    jks
+KeyStoreType = jks
 #
 #    The path to the keystore for https
-#
-KeyStoreFile:/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
+KeyStoreFile = /opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
 #
 #    The password for the https keystore
-#
 KeyStorePassword=]3V)($O&.Mv]W{f8^]6SxGNL
 #
 #    The password for the private key in the https keystore
-#
 KeyPassword=]3V)($O&.Mv]W{f8^]6SxGNL
 #
 #    The type of truststore for https
-#
-TrustStoreType=jks
+TrustStoreType = jks
 #
 #    The path to the truststore for https
-#
-#TrustStoreFile=/usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts
-TrustStoreFile=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
+TrustStoreFile = /opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
 #
 #    The password for the https truststore
-#
 TrustStorePassword=(Rd,&{]%ePdp}4JZjqoJ2G+g
 #
 #    The path to the file used to trigger an orderly shutdown
-#
-QuiesceFile=etc/SHUTDOWN
+QuiesceFile = etc/SHUTDOWN
 #
 #    The key used to generate passwords for node to node transfers
+NodeAuthKey = Node123!
+#
+#    DR_NODE DEFAULT ENABLED TLS PROTOCOLS
+NodeHttpsProtocols = TLSv1.1|TLSv1.2
+#
+#    AAF type to generate permission string
+AAFType = org.onap.dmaap-dr.feed
+#
+#    AAF default instance to generate permission string - default should be legacy
+AAFInstance = legacy
+#
+#    AAF action to generate permission string - default should be publish
+AAFAction = publish
+#
+#    AAF URL to connect to AAF server
+AafUrl = https://aaf-onap-test.osaaf.org:8095
 #
-NodeAuthKey=Node123!
+#    AAF CADI enabled flag
+CadiEnabled = false
 
diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DRNodeCadiFilterTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DRNodeCadiFilterTest.java
new file mode 100644 (file)
index 0000000..f6737b1
--- /dev/null
@@ -0,0 +1,121 @@
+/**-\r
+ * ============LICENSE_START=======================================================\r
+ *  Copyright (C) 2019 Nordix Foundation.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.dmaap.datarouter.node;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.junit.runner.RunWith;\r
+import org.mockito.Mock;\r
+import org.onap.aaf.cadi.PropAccess;\r
+import org.onap.aaf.cadi.filter.CadiFilter;\r
+import org.powermock.api.mockito.PowerMockito;\r
+import org.powermock.api.support.membermodification.MemberMatcher;\r
+import org.powermock.core.classloader.annotations.PrepareForTest;\r
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;\r
+import org.powermock.modules.junit4.PowerMockRunner;\r
+\r
+import javax.servlet.FilterChain;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import java.io.IOException;\r
+\r
+import static org.mockito.Mockito.*;\r
+\r
+@SuppressStaticInitializationFor("org.onap.dmaap.datarouter.node.NodeConfigManager")\r
+@PrepareForTest({CadiFilter.class})\r
+@RunWith(PowerMockRunner.class)\r
+public class DRNodeCadiFilterTest\r
+{\r
+\r
+    @Mock\r
+    private PropAccess access;\r
+\r
+    @Mock\r
+    private HttpServletRequest request;\r
+\r
+    @Mock\r
+    private HttpServletResponse response;\r
+\r
+    @Mock\r
+    private FilterChain chain;\r
+\r
+    private DRNodeCadiFilter cadiFilter;\r
+\r
+\r
+    @Before\r
+    public void setUp() throws ServletException {\r
+        cadiFilter = new DRNodeCadiFilter(false, access);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_Called_And_Method_Is_GET_And_AAF_DB_Instance_Is_NULL_Then_Chain_doFilter_Called() throws Exception {\r
+        PowerMockito.mockStatic(NodeConfigManager.class);\r
+        NodeConfigManager config = mock(NodeConfigManager.class);\r
+\r
+        PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config);\r
+        PowerMockito.when(config.getAafInstance("/other/5")).thenReturn("legacy");\r
+        when(request.getPathInfo()).thenReturn("/publish/5");\r
+        when(request.getMethod()).thenReturn("GET");\r
+        cadiFilter.doFilter(request,response,chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_Called_And_Method_Is_GET_And_Path_Includes_Internal_Then_Chain_doFilter_Called() throws Exception {\r
+        PowerMockito.mockStatic(NodeConfigManager.class);\r
+        NodeConfigManager config = mock(NodeConfigManager.class);\r
+\r
+        PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config);\r
+        PowerMockito.when(config.getAafInstance("/other/5")).thenReturn("legacy");\r
+        when(request.getPathInfo()).thenReturn("/internal/5");\r
+        when(request.getMethod()).thenReturn("GET");\r
+        cadiFilter.doFilter(request,response,chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_Called_And_Method_Is_GET_And_AAF_DB_Is_Not_Null_Then_Super_doFilter_Called() throws Exception {\r
+        PowerMockito.mockStatic(NodeConfigManager.class);\r
+        NodeConfigManager config = mock(NodeConfigManager.class);\r
+\r
+        PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config);\r
+        PowerMockito.when(config.getAafInstance("5")).thenReturn("EXISTS");\r
+        when(request.getPathInfo()).thenReturn("/publish/5/fileId");\r
+        when(request.getMethod()).thenReturn("GET");\r
+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));\r
+        cadiFilter.doFilter(request,response,chain);\r
+        verify(chain, times(0)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_getFileid_Called_And_SendError_Fails_Then_Throw_IOException_And_Call_chain_doFilter() throws Exception {\r
+        PowerMockito.mockStatic(NodeConfigManager.class);\r
+        NodeConfigManager config = mock(NodeConfigManager.class);\r
+\r
+        PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config);\r
+        when(request.getPathInfo()).thenReturn("/publish/5");\r
+        when(request.getMethod()).thenReturn("DELETE");\r
+        doThrow(new IOException()).when(response).sendError(HttpServletResponse.SC_NOT_FOUND, "Invalid request URI.  Expecting <feed-publishing-url>/<fileid>.  Possible missing fileid.");\r
+        cadiFilter.doFilter(request,response,chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+    }\r
+}\r
index 97904a5..9a3d82e 100644 (file)
@@ -22,6 +22,7 @@
  ******************************************************************************/
 
 package org.onap.dmaap.datarouter.node;
+
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.junit.Before;
 import org.junit.Test;
@@ -29,12 +30,10 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.powermock.modules.junit4.PowerMockRunner;
 
-import static org.junit.Assert.*;
 import java.io.File;
 
-
-
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
 
 @RunWith(PowerMockRunner.class)
 public class DeliveryQueueTest {
@@ -55,7 +54,7 @@ public class DeliveryQueueTest {
     }
 
     @Test
-    public void Given_New_DeliveryQueue_Directory_Is_Created_As_Defined_By_DestInfo() throws Exception {
+    public void Given_New_DeliveryQueue_Directory_Is_Created_As_Defined_By_DestInfo() {
         when(destInfo.getSpool()).thenReturn("tmp");
         File file = new File("tmp");
         assertTrue(file.exists());
@@ -63,14 +62,14 @@ public class DeliveryQueueTest {
     }
 
     @Test
-    public void Given_Delivery_Task_Failed_And_Resume_Time_Not_Reached_Return_Null() throws Exception{
+    public void Given_Delivery_Task_Failed_And_Resume_Time_Not_Reached_Return_Null() throws Exception {
         FieldUtils.writeField(deliveryQueue,"failed",true,true);
         FieldUtils.writeField(deliveryQueue,"resumetime",System.currentTimeMillis()*2,true);
         assertNull(deliveryQueue.peekNext());
     }
 
     @Test
-    public void Given_Delivery_Task_Return_Next_Delivery_Task_Id() throws Exception{
+    public void Given_Delivery_Task_Return_Next_Delivery_Task_Id() throws Exception {
         prepareFiles();
         when(destInfo.getSpool()).thenReturn(dirPath);
         deliveryQueue = new DeliveryQueue(deliveryQueueHelper, destInfo);
@@ -81,19 +80,19 @@ public class DeliveryQueueTest {
     }
 
     @Test
-    public void Given_Delivery_Task_Cancel_And_FileId_Is_Null_Return_Zero() throws Exception{
+    public void Given_Delivery_Task_Cancel_And_FileId_Is_Null_Return_Zero() {
         long rc = deliveryQueue.cancelTask("123.node.datarouternew.com");
         assertEquals(0, rc);
     }
 
-    private void prepareFiles() throws Exception{
+    private void prepareFiles() throws Exception {
         createFolder(dirPath);
         createFile(FileName1, dirPath);
         String[] files = new String[2];
         files[0] = dirPath + FileName1;
     }
 
-    private void createFolder(String dirName) throws Exception{
+    private void createFolder(String dirName) throws Exception {
         String dirPath = dirName;
 
         File newDirectory = new File(dirPath);
@@ -101,13 +100,13 @@ public class DeliveryQueueTest {
         if (isCreated) {
             System.out.println("1. Successfully created directories, path: " + newDirectory.getCanonicalPath());
         } else if (newDirectory.exists()) {
-            System.out.printf("1. Directory path already exist, path: " + newDirectory.getCanonicalPath());
+            System.out.print("1. Directory path already exist, path: " + newDirectory.getCanonicalPath());
         } else {
             System.out.println("1. Unable to create directory");
         }
     }
 
-    private void createFile( String file, String dir) throws Exception{
+    private void createFile(String file, String dir) throws Exception {
         String FileName = file;
         String dirPath = dir;
 
index 4ca907f..efa43e1 100644 (file)
@@ -97,7 +97,7 @@ public class DeliveryTest {
 
   private DestInfo[] createDestInfoObjects() {
     DestInfo[] destInfos = new DestInfo[1];
-    DestInfo destInfo = new DestInfo("node.datarouternew.com", "spool/s/0/1", "1", "logs/", "/subs/1", "user1", "Basic dXNlcjE6cGFzc3dvcmQx", false, true, false, false);
+    DestInfo destInfo = new DestInfo("node.datarouternew.com", "spool/s/0/1", "1", "logs/", "/subs/1", "user1", "Basic dXNlcjE6cGFzc3dvcmQx", false, true, false, false, false);
     destInfos[0] = destInfo;
     return destInfos;
   }
index 4b614d5..7dddd67 100644 (file)
@@ -193,6 +193,7 @@ public class NodeConfigTest {
         endpointAddrs.put("172.0.0.1");
         auth.put("endpoint_addrs", endpointAddrs);
         feed.put("authorization", auth);
+        feed.put("aaf_instance", "legacy");
         feeds.put(feed);
         provData.put("feeds", feeds);
     }
@@ -211,6 +212,7 @@ public class NodeConfigTest {
         delivery.put("use100", true);
         subscription.put("delivery", delivery);
         subscription.put("privilegedSubscriber", false);
+        subscription.put("follow_redirect", false);
         subscription.put("decompress", false);
         subscriptions.put(subscription);
         provData.put("subscriptions", subscriptions);
index 065565d..99e34c6 100644 (file)
@@ -59,7 +59,9 @@ public class NodeServletTest {
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
+
+    private NodeConfigManager config = mock(NodeConfigManager.class);
 
     @Before
     public void setUp() throws Exception {
@@ -215,6 +217,17 @@ public class NodeServletTest {
         verifyEnteringExitCalled(listAppender);
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_PUT_On_Publish_On_AAF_Feed_And_Cadi_Enabled_And_No_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(config.getCadiEnabeld()).thenReturn(true);
+        when(config.getAafInstance("1")).thenReturn("*");
+        when(request.getPathInfo()).thenReturn("/publish/1/fileName");
+        setHeadersForValidRequest(true);
+        nodeServlet.doPut(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
+        verifyEnteringExitCalled(listAppender);
+    }
+
     @Test
     public void Given_Request_Is_HTTP_DELETE_On_Publish_With_Meta_Data_Malformed_Then_Bad_Request_Response_Is_Generated() throws Exception {
         when(request.getPathInfo()).thenReturn("/publish/1/fileName");
@@ -286,7 +299,6 @@ public class NodeServletTest {
     }
 
     private void setUpConfig() throws IllegalAccessException {
-        NodeConfigManager config = mock(NodeConfigManager.class);
         PowerMockito.mockStatic(NodeConfigManager.class);
         when(config.isShutdown()).thenReturn(false);
         when(config.isConfigured()).thenReturn(true);
diff --git a/datarouter-prov/aaf_certs/org.onap.dmaap-dr.keyfile b/datarouter-prov/aaf_certs/org.onap.dmaap-dr.keyfile
new file mode 100755 (executable)
index 0000000..a586a72
--- /dev/null
@@ -0,0 +1,27 @@
+VDu7g5rP2-JMemc6RwP0HqM4ILJnuja8R_bzdCG1u0_Z2EQJN_7ZNPDb28V6JCDF-59sX10_i9vT
+-nw77ViAuwJO7ffSut8ipVhESeQxTokZsErzMFpeJZDhMM16W5LLtxwUs_tgh_EQIJSc-WcFUNYS
+NagugzjmNE5-hUosLgnt7mZ1nX4zFER9Nq1ce0EQS--kAB9rxcRmoywPlBlHvPmP_caiwpa1SzJp
+gbFF6smyLEWhjDhJkgvM_4FwaQCbJBVGcy2a3Lc9orHsz9S1RJTZ9CExhasM0qEp3kk0fMEFE9k6
+TomOpUBGizLfHPpg18KtXyM8zErj8qdS0KMwaCKtwGzCWw08MF5rVZrMYWLKDMOs8U2ESU7x28nV
+KSrAsR11QD7vX4PTVTfjEpcHSGe-9nPD7TckY8_O-9l67v_OUW1Fw4MSESCN0RtT7ZlNYwDV0syA
+X94rv1Y45N41tfX76jz8PDB9G-PF36BtkICJWK24zwuQDgpkURhCLPYzvBhPmCPyQil810X9s_bX
+icmV2cSN3oYQRz5dNSjUYH1CDt9edAJt4p2PQhM3A2xXyw1FVvbAIYA7iF-3qYG9csroBzsCcS5C
+hX8929jZHQWU5pygtpedEWhX__tnSrd-xIpxPnhOxrb-lNLva5JGKauU2DrGoLd_7RTwbuRdCiQo
+uGFtYOtjLciPz81oEEpXQTReeSnvGyGiZNxRrKWMEmq-biyQd4DuRVmTDuLAG4rd92QWS6qUz0uf
+9TtJiYlN3mNkxz3ahEGWLKR79rH9juJ3xqpcF-Rb7Y1bmiCDBv3DVVFiYIpwQuto1iSIYabL34Ql
+QqX65E1c3uvPksN6Nl1nvAVxSKM94wAFsMiA9Rp8AN9pDSxtj7D3kZCG8I0YaIxF_s-OeJtr1RPx
+ifv8vrwN23GUQCmpGBbyNXNe6zz-hz_HJdAsBr6WjLny9LQkeYszHGF-OL5ps6K5gHBRV0Ui1C7H
+Gj7egsjnV_Lu5MpBxhTrquDrZKK3t38kf0zrV-zfSGzJlGbLS91h8bR-7FAZiNEzgXPWYi26w81i
+W3Csx4oqsfKswp0pO80rggkFf9LL9pjCkSUTTVyF-toa9kY2h7JsVtqntP4Mjagp4Tnj01988kne
+Mj8SLm2mJySTLdH5Hi4arKW943iCqYjEaZ7wXFNJSZ6vvBm3KC1XX6C0DjRrgQoKIHw_4JcGhvOU
+P5LdpBT1AOcE8lIKrGGq8hyfJKLVUMec-NkzAT2aIl0YJoUcJv4fs-lKccGL4FDrq5y_yvD3xQ6v
+xt7KTanFxntqLYmM72Y2eFwJGlDEHhm0SejAV64-odksA_zMLLuYwkq_KSj0If9AVpRXz7KzIj9P
+9y-WMfAWKFfIyqGWXt5sYdMTQPG4qKCcFQBx3T0E6kiQMBuOZz0dR032eFPMexrymEowjosr2jt3
+ib8rFxmPMyyUWoV1iBafFMLf5PN2oapTq76gqeQQGGwpmYJB8cWlS1Eq_ZbzZpK2PSwX-fC6NSf3
+KtOV_r2VI3e_V6csnWTY8nxCJj9FlQCvLOzp964DNsBeUwDpsD7T_pgQy0THgAnq32ZtDvQfgeUE
+TUJC7oQeOEY7QBWjbZkumds51j7oTlsp2dPForlHwBk_2Nd5VCwVRNa1QMS8WcghLYbUCX5zeplc
+u2bopHn9GD614gt7f7wysDgTGegOCAuMoL7wA9TXN4BSfAF9mwpdtRFE4lT3N1xmfhKt9rM6Lu8T
+RGvBOmTOTT5IwJrrE5mpvmESw05sHUcCZ9ENv-VhoeC3Ffk9uXqrDggQgaDs9XcXqzEPBp9wDPTt
+UJpbtBGECSSTuXAZyUh3I0WFz96kVuHmQpDYVTpy1sxPjmgjgKyhu_6jLGSsYpVBH063n7KSKVdF
+ROKojZN4-FsBlPhoOhNEd7x1OBfgCG79HKGk33jhESObZkPIrcTc17jiE-ud2D1B1_Fl-OJNR7Vh
+GIk4WMZrH9NeVwDuIgBxF74plqg6tSl0Cdd4m7e3Drsq-wRfsU2gNTo5oL-2SgbsO5n3ubQf
\ No newline at end of file
index 44f70f5..284a8ca 100755 (executable)
                 </exclusion>\r
             </exclusions>\r
         </dependency>\r
+        <dependency>\r
+            <groupId>org.onap.aaf.authz</groupId>\r
+            <artifactId>aaf-cadi-aaf</artifactId>\r
+            <version>${aaf-cadi-aaf.version}</version>\r
+        </dependency>\r
     </dependencies>\r
     <profiles>\r
         <profile>\r
index 2d4f85f..50ec1b4 100755 (executable)
 
 package org.onap.dmaap.datarouter.provisioning;
 
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
-
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
-import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
-import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
-
-
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.security.cert.X509Certificate;
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-
 import org.apache.commons.lang3.StringUtils;
 import org.apache.log4j.Logger;
+import org.json.JSONArray;
+import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONTokener;
 import org.onap.dmaap.datarouter.authz.Authorizer;
 import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
 import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;
-import org.onap.dmaap.datarouter.provisioning.beans.Deleteable;
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;
-import org.onap.dmaap.datarouter.provisioning.beans.Group;
-import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
-import org.onap.dmaap.datarouter.provisioning.beans.NodeClass;
-import org.onap.dmaap.datarouter.provisioning.beans.Parameters;
-import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
-import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
+import org.onap.dmaap.datarouter.provisioning.beans.*;
 import org.onap.dmaap.datarouter.provisioning.utils.DB;
+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;
 import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
-import org.json.JSONException;
 import org.slf4j.MDC;
-import org.slf4j.Marker;
-import org.slf4j.MarkerFactory;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.UUID;
-import java.util.regex.Pattern;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Multipart;
-import javax.mail.Session;
-import javax.mail.Transport;
-import javax.mail.internet.AddressException;
+
+import javax.mail.*;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMultipart;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
+import java.security.cert.X509Certificate;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+import static com.att.eelf.configuration.Configuration.*;
 
 /**
  * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
@@ -98,6 +72,24 @@ import javax.mail.internet.MimeMultipart;
 public class BaseServlet extends HttpServlet implements ProvDataProvider {
 
     public static final String BEHALF_HEADER = "X-DMAAP-DR-ON-BEHALF-OF";
+
+    public static final String EXCLUDE_AAF_HEADER = "X-EXCLUDE-AAF";
+
+    private static final String AAF_CADI_FEED_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.feed.type";
+    private static final String AAF_CADI_SUB_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.sub.type";
+    private static final String AAF_INSTANCE = "org.onap.dmaap.datarouter.provserver.aaf.instance";
+    private static final String AAF_CADI_FEED = "org.onap.dmaap-dr.feed";
+    private static final String AAF_CADI_SUB = "org.onap.dmaap-dr.sub";
+
+    static final String CREATE_PERMISSION = "create";
+    static final String EDIT_PERMISSION = "edit";
+    static final String DELETE_PERMISSION = "delete";
+    static final String PUBLISH_PERMISSION = "publish";
+    static final String SUSPEND_PERMISSION = "suspend";
+    static final String RESTORE_PERMISSION = "restore";
+    static final String SUBSCRIBE_PERMISSION = "subscribe";
+    static final String APPROVE_SUB_PERMISSION = "approveSub";
+
     static final String FEED_BASECONTENT_TYPE = "application/vnd.dmaap-dr.feed";
     public static final String FEED_CONTENT_TYPE = "application/vnd.dmaap-dr.feed; version=2.0";
     public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-full; version=2.0";
@@ -110,7 +102,9 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
 
     //Adding groups functionality, ...1610
     static final String GROUP_BASECONTENT_TYPE = "application/vnd.dmaap-dr.group";
-    static final String GROUPFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.group-full; version=2.0";
+    static final String GROUP_CONTENT_TYPE = "application/vnd.dmaap-dr.group; version=2.0";
+    public static final String GROUPFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.group-full; version=2.0";
+    public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.fegrouped-list; version=1.0";
 
 
     public static final String LOGLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.log-list; version=1.0";
@@ -172,6 +166,10 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
      * Array of nodes names and/or FQDNs
      */
     private static String[] nodes = new String[0];
+    /**
+     * [DATARTR-27] Poke all the DR nodes : Array of nodes names and/or FQDNs
+     */
+    private static String[] drnodes = new String[0];
     /**
      * Array of node IP addresses
      */
@@ -196,10 +194,12 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
      * The current number of subscriptions in the system
      */
     static int activeSubs = 0;
+
     /**
      * The domain used to generate a FQDN from the "bare" node names
      */
     private static String provDomain = "web.att.com";
+
     /**
      * The standard FQDN of the provisioning server in this Data Router ecosystem
      */
@@ -210,7 +210,8 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
      */
     private static String activeProvName = "feeds-drtr.web.att.com";
 
-    private static String staticRoutingNodes = STATIC_ROUTING_NODES; //Adding new param for static Routing - Rally:US664862-1610
+    //Adding new param for static Routing - Rally:US664862-1610
+    private static String staticRoutingNodes = STATIC_ROUTING_NODES;
 
     /**
      * This logger is used to log provisioning events
@@ -239,7 +240,10 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
 
     //DMAAP-597 (Tech Dept) REST request source IP auth relaxation to accommodate OOM kubernetes deploy
     private static String isAddressAuthEnabled = (new DB()).getProperties()
-        .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
+            .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
+
+    static String isCadiEnabled = (new DB()).getProperties()
+            .getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false");
 
     /**
      * Initialize data common to all the provisioning server servlets.
@@ -277,7 +281,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         }
     }
 
-    int getIdFromPath(HttpServletRequest req) {
+    public static int getIdFromPath(HttpServletRequest req) {
         String path = req.getPathInfo();
         if (path == null || path.length() < 2) {
             return -1;
@@ -308,6 +312,36 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         return jo;
     }
 
+    /**
+     * This method encrypt/decrypt the key in the JSON passed by user request inside the authorisation header object in request before logging the JSON.
+     *
+     * @param jo-      the JSON passed in http request.
+     * @param maskKey- the key to be masked in the JSON passed.
+     * @param action-  whether to mask the key or unmask it in a JSON passed.
+     * @return the JSONObject, or null if the stream cannot be parsed.
+     */
+    public static JSONObject maskJSON(JSONObject jo, String maskKey, boolean action) {
+        if (!jo.isNull("authorization")) {
+            JSONObject j2 = jo.getJSONObject("authorization");
+            JSONArray ja = j2.getJSONArray("endpoint_ids");
+            for (int i = 0; i < ja.length(); i++) {
+                if ((!ja.getJSONObject(i).isNull(maskKey))) {
+                    String password = ja.getJSONObject(i).get(maskKey).toString();
+                    try {
+                        if (action) {
+                            ja.getJSONObject(i).put(maskKey, PasswordProcessor.encrypt(password));
+                        } else {
+                            ja.getJSONObject(i).put(maskKey, PasswordProcessor.decrypt(password));
+                        }
+                    } catch (JSONException | GeneralSecurityException e) {
+                        intlogger.info("Error reading JSON while masking: " + e);
+                    }
+                }
+            }
+        }
+        return jo;
+    }
+
     /**
      * Check if the remote host is authorized to perform provisioning. Is the request secure? Is it coming from an
      * authorized IP address or network (configured via PROV_AUTH_ADDRESSES)? Does it have a valid client certificate
@@ -324,7 +358,6 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         if (requireSecure && !request.isSecure()) {
             return "Request must be made over an HTTPS connection.";
         }
-
         // Is remote IP authorized?
         String remote = request.getRemoteAddr();
         try {
@@ -337,12 +370,12 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
                 return "Unauthorized address: " + remote;
             }
         } catch (UnknownHostException e) {
+            intlogger.error("PROV0051 BaseServlet.isAuthorizedForProvisioning: ", e);
             return "Unauthorized address: " + remote;
         }
-
         // Does remote have a valid certificate?
         if (requireCert) {
-            X509Certificate certs[] = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
+            X509Certificate[] certs = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
             if (certs == null || certs.length == 0) {
                 return "Client certificate is missing.";
             }
@@ -353,7 +386,6 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
                 return "No authorized certificate found.";
             }
         }
-
         // No problems!
         return null;
     }
@@ -365,7 +397,6 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
      * @return true iff authorized
      */
     boolean isAuthorizedForInternal(HttpServletRequest request) {
-
         try {
             if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
                 return true;
@@ -388,7 +419,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
                 return true;
             }
         } catch (UnknownHostException e) {
-            // ignore
+            intlogger.error("PROV0052 BaseServlet.isAuthorizedForInternal: ", e);
         }
         return false;
     }
@@ -397,7 +428,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
      * Check if an IP address matches a network address.
      *
      * @param ip the IP address
-     * @param s the network address; a bare IP address may be matched also
+     * @param s  the network address; a bare IP address may be matched also
      * @return true if they intersect
      */
     private static boolean addressMatchesNetwork(InetAddress ip, String s) {
@@ -416,8 +447,8 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
             }
             if (mlen > 0) {
                 byte[] masks = {
-                    (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
-                    (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
+                        (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
+                        (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
                 };
                 byte mask = masks[mlen % 8];
                 for (n = mlen / 8; n < b1.length; n++) {
@@ -432,6 +463,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
                 }
             }
         } catch (UnknownHostException e) {
+            intlogger.error("PROV0053 BaseServlet.addressMatchesNetwork: ", e);
             return false;
         }
         return true;
@@ -441,7 +473,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
      * Something has changed in the provisioning data. Start the timers that will cause the pre-packaged JSON string to
      * be regenerated, and cause nodes and the other provisioning server to be notified.
      */
-    public static void provisioningDataChanged() {
+    static void provisioningDataChanged() {
         long now = System.currentTimeMillis();
         Poker p = Poker.getPoker();
         p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
@@ -450,7 +482,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
     /**
      * Something in the parameters has changed, reload all parameters from the DB.
      */
-    public static void provisioningParametersChanged() {
+    static void provisioningParametersChanged() {
         Map<String, String> map = Parameters.getParameters();
         requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
         requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
@@ -461,15 +493,16 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         maxSubs = getInt(map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);
         pokeTimer1 = getInt(map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);
         pokeTimer2 = getInt(map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);
+        /**
+         * The domain used to generate a FQDN from the "bare" node names
+         */
         provDomain = getString(map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);
         provName = getString(map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);
         activeProvName = getString(map, Parameters.PROV_ACTIVE_NAME, provName);
-        staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
-            ""); //Adding new param for static Routing - Rally:US664862-1610
         initialActivePod = getString(map, Parameters.ACTIVE_POD, "");
         initialStandbyPod = getString(map, Parameters.STANDBY_POD, "");
         staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
-            ""); //Adding new param for static Routing - Rally:US664862-1610
+                ""); //Adding new param for static Routing - Rally:US664862-1610
         activeFeeds = Feed.countActiveFeeds();
         activeSubs = Subscription.countActiveSubscriptions();
         try {
@@ -491,6 +524,9 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
             }
         }
 
+        //[DATARTR-27] Poke all the DR nodes: assigning DR Nodes
+        drnodes = nodes.clone();
+
         //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .
         List<String> filterNodes = new ArrayList<>();
         for (String node : nodes) {
@@ -498,7 +534,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
                 filterNodes.add(node);
             }
         }
-        nodes = filterNodes.toArray(new String[filterNodes.size()]);
+        nodes = filterNodes.toArray(new String[0]);
 
         nodeAddresses = na;
         NodeClass.setNodes(nodes);        // update NODES table
@@ -535,17 +571,11 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
     private void loadMailProperties() {
         if (mailprops == null) {
             mailprops = new Properties();
-            InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE);
-            try {
+            try (InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE)) {
                 mailprops.load(inStream);
             } catch (IOException e) {
                 intlogger.fatal("PROV9003 Opening properties: " + e.getMessage());
                 System.exit(1);
-            } finally {
-                try {
-                    inStream.close();
-                } catch (IOException e) {
-                }
             }
         }
     }
@@ -602,18 +632,16 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
             msg.addRecipients(Message.RecipientType.TO, addressTo);
             msg.setSubject(mailprops.get("com.att.dmaap.datarouter.mail.subject").toString());
             htmlPart.setContent(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
-                .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
+                    .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
             mp.addBodyPart(htmlPart);
             msg.setContent(mp);
 
             System.out.println(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
-                .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
+                    .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
 
             Transport.send(msg);
             intlogger.info("HTTPS relaxation mail is sent to - : " + email);
 
-        } catch (AddressException e) {
-            intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
         } catch (MessagingException e) {
             intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
         }
@@ -636,6 +664,16 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         return nodes;
     }
 
+    /**
+     * [DATARTR-27] Poke all the DR nodes
+     * Get an array of all node names in the DR network.
+     *
+     * @return an array of Strings
+     */
+    public static String[] getDRNodes() {
+        return drnodes;
+    }
+
     /**
      * Get an array of all node InetAddresses in the DR network.
      *
@@ -981,7 +1019,7 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         setMDC(req, "X-InvocationID", "InvocationId");
     }
 
-    void setMDC(HttpServletRequest req, String headerName, String keyName) {
+    private void setMDC(HttpServletRequest req, String headerName, String keyName) {
         String mdcId = req.getHeader(headerName);
         if (StringUtils.isBlank(mdcId)) {
             mdcId = UUID.randomUUID().toString();
@@ -1004,4 +1042,95 @@ public class BaseServlet extends HttpServlet implements ProvDataProvider {
         }
 
     }
+
+    /*
+     * AAF changes: TDP EPIC US# 307413
+     * @Method - getFeedPermission - Forming permission string for feed part to check AAF access in CADI Framework
+     * @Params - aafInstance Passing aafInstance as it's used in permission string
+     * @Params - userAction Passing CONST values to set different actions in permission string
+     */
+    String getFeedPermission(String aafInstance, String userAction) {
+        try {
+            Properties props = (new DB()).getProperties();
+            String type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
+            String action;
+            switch (userAction) {
+                case CREATE_PERMISSION:
+                    action = CREATE_PERMISSION;
+                    break;
+                case EDIT_PERMISSION:
+                    action = EDIT_PERMISSION;
+                    break;
+                case DELETE_PERMISSION:
+                    action = DELETE_PERMISSION;
+                    break;
+                case PUBLISH_PERMISSION:
+                    action = PUBLISH_PERMISSION;
+                    break;
+                case SUSPEND_PERMISSION:
+                    action = SUSPEND_PERMISSION;
+                    break;
+                case RESTORE_PERMISSION:
+                    action = RESTORE_PERMISSION;
+                    break;
+                default:
+                    action = "*";
+            }
+            if (aafInstance == null || aafInstance.equals("")) {
+                aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            intlogger.error("PROV7005 BaseServlet.getFeedPermission: ", e);
+        }
+        return null;
+    }
+
+    /*
+     * AAF changes: TDP EPIC US# 307413
+     * @Method - getSubscriberPermission - Forming permission string for subscription part to check AAF access in CADI Framework
+     * @Params - aafInstance Passing aafInstance as it's used in permission string
+     * @Params - userAction Passing CONST values to set different actions in permission string
+     */
+    String getSubscriberPermission(String aafInstance, String userAction) {
+        try {
+            Properties props = (new DB()).getProperties();
+            String type = props.getProperty(AAF_CADI_SUB_TYPE, AAF_CADI_SUB);
+            String action;
+            switch (userAction) {
+                case SUBSCRIBE_PERMISSION:
+                    action = SUBSCRIBE_PERMISSION;
+                    type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
+                    break;
+                case EDIT_PERMISSION:
+                    action = EDIT_PERMISSION;
+                    break;
+                case DELETE_PERMISSION:
+                    action = DELETE_PERMISSION;
+                    break;
+                case RESTORE_PERMISSION:
+                    action = RESTORE_PERMISSION;
+                    break;
+                case SUSPEND_PERMISSION:
+                    action = SUSPEND_PERMISSION;
+                    break;
+                case PUBLISH_PERMISSION:
+                    action = PUBLISH_PERMISSION;
+                    break;
+                case APPROVE_SUB_PERMISSION:
+                    action = APPROVE_SUB_PERMISSION;
+                    type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
+                    break;
+                default:
+                    action = "*";
+            }
+            if (aafInstance == null || aafInstance.equals("")) {
+                aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
+            }
+            return type + "|" + aafInstance + "|" + action;
+        } catch (Exception e) {
+            intlogger.error("PROV7005 BaseServlet.getSubscriberPermission: ", e);
+        }
+        return null;
+    }
 }
index 895eba0..9bc9162 100644 (file)
 
 package org.onap.dmaap.datarouter.provisioning;
 
-import java.io.IOException;
-import java.io.InvalidObjectException;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
 import org.json.JSONObject;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
@@ -38,8 +33,11 @@ import org.onap.dmaap.datarouter.provisioning.beans.Feed;
 import org.onap.dmaap.datarouter.provisioning.eelf.EelfMsgs;
 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;
 
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.util.List;
 
 import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
 
@@ -55,7 +53,7 @@ public class DRFeedsServlet extends ProxyServlet {
 
     //Adding EELF Logger Rally:US664892
     private static EELFLogger eelflogger = EELFManager.getInstance()
-        .getLogger(DRFeedsServlet.class);
+            .getLogger(DRFeedsServlet.class);
 
     /**
      * DELETE on the &lt;drFeedsURL&gt; -- not supported.
@@ -109,8 +107,8 @@ public class DRFeedsServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
-            String path = req
-                    .getRequestURI(); // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            String path = req.getRequestURI();
             if (path != null && !path.equals("/")) {
                 message = "Bad URL.";
                 elr.setMessage(message);
@@ -236,8 +234,8 @@ public class DRFeedsServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
-            String path = req
-                    .getRequestURI(); // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
+            String path = req.getRequestURI();
             if (path != null && !path.equals("/")) {
                 message = "Bad URL.";
                 elr.setMessage(message);
@@ -257,16 +255,6 @@ public class DRFeedsServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (!aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
-            }
             JSONObject jo = getJSONfromInput(req);
             if (jo == null) {
                 message = "Badly formed JSON";
@@ -288,7 +276,7 @@ public class DRFeedsServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
                 return;
             }
-            Feed feed = null;
+            Feed feed;
             try {
                 feed = new Feed(jo);
             } catch (InvalidObjectException e) {
@@ -299,6 +287,60 @@ public class DRFeedsServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
+
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - No legacy user check as all new users will be AAF users
+             */
+            String aafInstance = feed.getAafInstance();
+            if (Boolean.parseBoolean(isCadiEnabled)) {
+                if ((aafInstance == null || aafInstance.equals("") || (aafInstance.equalsIgnoreCase("legacy")) && req.getHeader(EXCLUDE_AAF_HEADER).equalsIgnoreCase("true"))) {
+                    // Check with the Authorizer
+                    AuthorizationResponse aresp = authz.decide(req);
+                    if (!aresp.isAuthorized()) {
+                        message = "Policy Engine disallows access.";
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                } else {
+                    if (req.getHeader(EXCLUDE_AAF_HEADER).equalsIgnoreCase("true")) {
+                        message = "DRFeedsServlet.doPost() -Invalid request exclude_AAF should not be true if passing AAF_Instance value= " + aafInstance;
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                    String permission = getFeedPermission(aafInstance, BaseServlet.CREATE_PERMISSION);
+                    eventlogger.info("DRFeedsServlet.doPost().. Permission String - " + permission);
+                    if (!req.isUserInRole(permission)) {
+                        message = "AAF disallows access to permission - " + permission;
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                }
+            } else {
+                AuthorizationResponse aresp = authz.decide(req);
+                if (!aresp.isAuthorized()) {
+                    message = "Policy Engine disallows access.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            }
+            /*
+             * END - AAF changes
+             */
+
             feed.setPublisher(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header
 
             // Check if this feed already exists
index e64f2c6..4ab3ef4 100644 (file)
@@ -107,17 +107,37 @@ public class FeedServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (! aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - check on permissions based on Legacy/AAF users to allow to delete/remove feed
+             */
+            String aafInstance = feed.getAafInstance();
+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {
+                AuthorizationResponse aresp = authz.decide(req);
+                if (! aresp.isAuthorized()) {
+                    message = "Policy Engine disallows access.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            } else {
+                String permission = getFeedPermission(aafInstance, BaseServlet.DELETE_PERMISSION);
+                eventlogger.info("FeedServlet.doDelete().. Permission String - " + permission);
+                if (!req.isUserInRole(permission)) {
+                    message = "AAF disallows access to permission - " + permission;
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
             }
-
+            /*
+             * END - AAF changes
+             */
             // Delete FEED table entry (set DELETED flag)
             feed.setDeleted(true);
             if (doUpdate(feed)) {
@@ -286,7 +306,7 @@ public class FeedServlet extends ProxyServlet {
             }
             if (intlogger.isDebugEnabled())
                 intlogger.debug(jo.toString());
-            Feed feed = null;
+            Feed feed;
             try {
                 feed = new Feed(jo);
             } catch (InvalidObjectException e) {
@@ -317,24 +337,50 @@ public class FeedServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
                 return;
             }
-            if (!oldFeed.getVersion().equals(feed.getVersion())) {
-                message = "The version of the feed may not be updated.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
-                return;
+            //  US DSCDR-19 for DCAE if version is not null, version can't be changed
+            if ((oldFeed.getVersion() != null) && (feed.getVersion() != null)) {
+                if (!oldFeed.getVersion().equals(feed.getVersion())) {
+                    message = "The version of the feed may not be updated.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
+                    return;
+                }
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (! aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
+
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - check on permissions based on Legacy/AAF users to allow feed edit/update/modify
+             */
+            String aafInstance = feed.getAafInstance();
+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {
+                // Check with the Authorizer
+                AuthorizationResponse aresp = authz.decide(req);
+                if (!aresp.isAuthorized()) {
+                    message = "Policy Engine disallows access.";
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            } else {
+                String permission = getFeedPermission(aafInstance, BaseServlet.EDIT_PERMISSION);
+                eventlogger.info("FeedServlet.doPut().. Permission String - " + permission);
+                if (!req.isUserInRole(permission)) {
+                    message = "AAF disallows access to permission - " + permission;
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
             }
+            /*
+             * END - AAF changes
+             */
 
             // Update FEEDS table entries
             if (doUpdate(feed)) {
index 651d731..1bd3cbf 100644 (file)
 
 package org.onap.dmaap.datarouter.provisioning;
 
-import java.security.*;
-import java.util.*;
-
 import org.apache.log4j.Logger;
 import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.NCSARequestLog;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.*;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.server.handler.DefaultHandler;
 import org.eclipse.jetty.server.handler.HandlerCollection;
 import org.eclipse.jetty.server.handler.RequestLogHandler;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.onap.dmaap.datarouter.provisioning.utils.DB;
-import org.onap.dmaap.datarouter.provisioning.utils.LogfileLoader;
-import org.onap.dmaap.datarouter.provisioning.utils.PurgeLogDirTask;
-import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.dmaap.datarouter.provisioning.utils.*;
 
 import javax.servlet.DispatcherType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Security;
+import java.util.EnumSet;
+import java.util.Properties;
+import java.util.Timer;
 
 /**
  * <p>
@@ -87,18 +81,31 @@ public class Main {
     /**
      * The truststore to use if none is specified
      */
-    public static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
-    public static final String KEYSTORE_TYPE_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.type";
-    public static final String KEYSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.path";
-    public static final String KEYSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.password";
-    public static final String TRUSTSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.path";
-    public static final String TRUSTSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.password";
+    static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
+    static final String KEYSTORE_TYPE_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.type";
+    static final String KEYSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.path";
+    static final String KEYSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.password";
+    static final String TRUSTSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.path";
+    static final String TRUSTSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.password";
+    public static final Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
 
     /**
      * The one and only {@link Server} instance in this JVM
      */
     private static Server server;
 
+    class Inner {
+        InputStream getCadiProps() {
+            InputStream in = null;
+            try {
+                in = getClass().getClassLoader().getResourceAsStream("drProvCadi.properties");
+            } catch (Exception e) {
+                intlogger.error("Exception in Main.getCadiProps() method ", e);
+            }
+            return in;
+        }
+    }
+
     /**
      * Starts the Data Router Provisioning server.
      *
@@ -106,29 +113,19 @@ public class Main {
      * @throws Exception if Jetty has a problem starting
      */
     public static void main(String[] args) throws Exception {
-        Security.setProperty("networkaddress.cache.ttl", "4");
-        Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
+        // Get prov properties
+        Properties provProperties = (new DB()).getProperties();
 
         // Check DB is accessible and contains the expected tables
         if (!checkDatabase()) {
             System.exit(1);
         }
 
-        logger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
+        intlogger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
 
-        // Get properties
-        Properties p = (new DB()).getProperties();
-        int httpPort = Integer.parseInt(p.getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080"));
-        int httpsPort = Integer.parseInt(p.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443"));
-
-        // HTTP configuration
-        HttpConfiguration httpConfiguration = new HttpConfiguration();
-        httpConfiguration.setSecureScheme("https");
-        httpConfiguration.setSecurePort(httpsPort);
-        httpConfiguration.setOutputBufferSize(32768);
-        httpConfiguration.setRequestHeaderSize(2048);
-        httpConfiguration.setSendServerVersion(true);
-        httpConfiguration.setSendDateHeader(false);
+        Security.setProperty("networkaddress.cache.ttl", "4");
+        int httpPort = Integer.parseInt(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080"));
+        int httpsPort = Integer.parseInt(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443"));
 
         // Server's thread pool
         QueuedThreadPool queuedThreadPool = new QueuedThreadPool();
@@ -138,121 +135,155 @@ public class Main {
 
         // The server itself
         server = new Server(queuedThreadPool);
+        server.setStopAtShutdown(true);
+        server.setStopTimeout(5000);
+        server.setDumpAfterStart(false);
+        server.setDumpBeforeStop(false);
+
+        // Request log configuration
+        NCSARequestLog ncsaRequestLog = new NCSARequestLog();
+        ncsaRequestLog.setFilename(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
+        ncsaRequestLog.setFilenameDateFormat("yyyyMMdd");
+        ncsaRequestLog.setRetainDays(90);
+        ncsaRequestLog.setAppend(true);
+        ncsaRequestLog.setExtended(false);
+        ncsaRequestLog.setLogCookies(false);
+        ncsaRequestLog.setLogTimeZone("GMT");
+
+        RequestLogHandler requestLogHandler = new RequestLogHandler();
+        requestLogHandler.setRequestLog(ncsaRequestLog);
+        server.setRequestLog(ncsaRequestLog);
+
+        // HTTP configuration
+        HttpConfiguration httpConfiguration = new HttpConfiguration();
+        httpConfiguration.setSecureScheme("https");
+        httpConfiguration.setSecurePort(httpsPort);
+        httpConfiguration.setOutputBufferSize(32768);
+        httpConfiguration.setRequestHeaderSize(8192);
+        httpConfiguration.setResponseHeaderSize(8192);
+        httpConfiguration.setSendServerVersion(true);
+        httpConfiguration.setSendDateHeader(false);
 
-        // HTTP connector
-        HandlerCollection hc;
-        try (ServerConnector httpServerConnector = new ServerConnector(server,
-            new HttpConnectionFactory(httpConfiguration))) {
+        //HTTP Connector
+        HandlerCollection handlerCollection;
+        try (ServerConnector httpServerConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration))) {
             httpServerConnector.setPort(httpPort);
             httpServerConnector.setAcceptQueueSize(2);
             httpServerConnector.setIdleTimeout(300000);
 
+            // SSL Context
+            SslContextFactory sslContextFactory = new SslContextFactory();
+            sslContextFactory.setKeyStoreType(provProperties.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
+            sslContextFactory.setKeyStorePath(provProperties.getProperty(KEYSTORE_PATH_PROPERTY));
+            sslContextFactory.setKeyStorePassword(provProperties.getProperty(KEYSTORE_PASS_PROPERTY));
+            sslContextFactory.setKeyManagerPassword(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
+
+            String ts = provProperties.getProperty(TRUSTSTORE_PATH_PROPERTY);
+            if (ts != null && ts.length() > 0) {
+                intlogger.info("@@ TS -> " + ts);
+                sslContextFactory.setTrustStorePath(ts);
+                sslContextFactory.setTrustStorePassword(provProperties.getProperty(TRUSTSTORE_PASS_PROPERTY));
+            } else {
+                sslContextFactory.setTrustStorePath(DEFAULT_TRUSTSTORE);
+                sslContextFactory.setTrustStorePassword("changeit");
+            }
+
+            sslContextFactory.setWantClientAuth(true);
+            sslContextFactory.setExcludeCipherSuites(
+                    "SSL_RSA_WITH_DES_CBC_SHA",
+                    "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+                    "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+                    "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+                    "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                    "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                    "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
+            );
+            sslContextFactory.addExcludeProtocols("SSLv3");
+            sslContextFactory.setIncludeProtocols(provProperties.getProperty(
+                    "org.onap.dmaap.datarouter.provserver.https.include.protocols", "TLSv1.1|TLSv1.2").trim().split("\\|"));
+
+            intlogger.info("Not supported protocols prov server:-" + String.join(",", sslContextFactory.getExcludeProtocols()));
+            intlogger.info("Supported protocols prov server:-" + String.join(",", sslContextFactory.getIncludeProtocols()));
+            intlogger.info("Not supported ciphers prov server:-" + String.join(",", sslContextFactory.getExcludeCipherSuites()));
+            intlogger.info("Supported ciphers prov server:-" + String.join(",", sslContextFactory.getIncludeCipherSuites()));
+
             // HTTPS configuration
             HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration);
             httpsConfiguration.setRequestHeaderSize(8192);
 
             // HTTPS connector
-            SslContextFactory sslContextFactory = new SslContextFactory();
-            sslContextFactory.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
-            sslContextFactory.setKeyStorePassword(p.getProperty(KEYSTORE_PASS_PROPERTY));
-            sslContextFactory
-                    .setKeyManagerPassword(p.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
-            // SSL stuff
-            /* Skip SSLv3 Fixes */
-            sslContextFactory.addExcludeProtocols("SSLv3");
-            logger.info("Excluded protocols prov-" + Arrays.toString(sslContextFactory.getExcludeProtocols()));
-            /* End of SSLv3 Fixes */
-
             try (ServerConnector httpsServerConnector = new ServerConnector(server,
                     new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
                     new HttpConnectionFactory(httpsConfiguration))) {
+
                 httpsServerConnector.setPort(httpsPort);
                 httpsServerConnector.setIdleTimeout(30000);
                 httpsServerConnector.setAcceptQueueSize(2);
 
-                sslContextFactory.setKeyStoreType(p.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
-                sslContextFactory.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
-                sslContextFactory.setKeyStorePassword(p.getProperty(KEYSTORE_PASS_PROPERTY));
-                sslContextFactory
-                        .setKeyManagerPassword(p.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
-
-                String ts = p.getProperty(TRUSTSTORE_PATH_PROPERTY);
-                if (ts != null && ts.length() > 0) {
-                    logger.info("@@ TS -> " + ts);
-                    sslContextFactory.setTrustStorePath(ts);
-                    sslContextFactory.setTrustStorePassword(p.getProperty(TRUSTSTORE_PASS_PROPERTY));
-                } else {
-                    sslContextFactory.setTrustStorePath(DEFAULT_TRUSTSTORE);
-                    sslContextFactory.setTrustStorePassword("changeit");
+                // Servlet and Filter configuration
+                ServletContextHandler servletContextHandler = new ServletContextHandler(0);
+                servletContextHandler.setContextPath("/");
+                servletContextHandler.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
+                servletContextHandler.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
+                servletContextHandler.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
+                servletContextHandler.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
+                servletContextHandler.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
+                servletContextHandler.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
+                servletContextHandler.addServlet(new ServletHolder(new GroupServlet()), "/group/*");
+                servletContextHandler.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
+                servletContextHandler.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
+                servletContextHandler.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
+                servletContextHandler.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
+                servletContextHandler.addFilter(new FilterHolder(new ThrottleFilter()), "/publish/*", EnumSet.of(DispatcherType.REQUEST));
+
+                //CADI Filter activation check
+                if (Boolean.parseBoolean(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false"))) {
+                    //Get cadi properties
+                    Properties cadiProperties = null;
+                    try {
+                        intlogger.info("PROV0001 Prov - Loading CADI properties");
+                        cadiProperties = new Properties();
+                        Inner obj = new Main().new Inner();
+                        InputStream in = obj.getCadiProps();
+                        cadiProperties.load(in);
+                    } catch (IOException e1) {
+                        intlogger.error("PROV0001 Exception loading CADI properties", e1);
+                    }
+                    cadiProperties.setProperty("aaf_locate_url", provProperties.getProperty("org.onap.dmaap.datarouter.provserver.cadi.aaf.url", "https://aaf-onap-test.osaaf.org:8095"));
+                    intlogger.info("PROV0001  aaf_url set to - " + cadiProperties.getProperty("aaf_url"));
+
+                    PropAccess access = new PropAccess(cadiProperties);
+                    servletContextHandler.addFilter(new FilterHolder(new DRProvCadiFilter(true, access)), "/*", EnumSet.of(DispatcherType.REQUEST));
                 }
-                sslContextFactory.setWantClientAuth(true);
 
-                // Servlet and Filter configuration
-                ServletContextHandler ctxt = new ServletContextHandler(0);
-                ctxt.setContextPath("/");
-                ctxt.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
-                ctxt.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
-                ctxt.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
-                ctxt.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
-                ctxt.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
-                ctxt.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
-                ctxt.addServlet(new ServletHolder(new GroupServlet()),
-                        "/group/*"); //Provision groups - Rally US708115 -1610
-                ctxt.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
-                ctxt.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
-                ctxt.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
-                ctxt.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
-                ctxt.addFilter(new FilterHolder(new ThrottleFilter()), "/publish/*", EnumSet.of(DispatcherType.REQUEST));
-
-                ContextHandlerCollection contexts = new ContextHandlerCollection();
-                contexts.addHandler(ctxt);
-
-                // Request log configuration
-                NCSARequestLog nrl = new NCSARequestLog();
-                nrl.setFilename(
-                        p.getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
-                nrl.setFilenameDateFormat("yyyyMMdd");
-                nrl.setRetainDays(90);
-                nrl.setAppend(true);
-                nrl.setExtended(false);
-                nrl.setLogCookies(false);
-                nrl.setLogTimeZone("GMT");
-
-                RequestLogHandler reqlog = new RequestLogHandler();
-                reqlog.setRequestLog(nrl);
+                ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
+                contextHandlerCollection.addHandler(servletContextHandler);
 
                 // Server's Handler collection
-                hc = new HandlerCollection();
-                hc.setHandlers(new Handler[]{contexts, new DefaultHandler()});
-                hc.addHandler(reqlog);
-
-                // Daemon to clean up the log directory on a daily basis
-                Timer rolex = new Timer();
-                rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L);    // run once per day
-
-                // Start LogfileLoader
-                LogfileLoader.getLoader();
-
-                try (ServerConnector serverConnector = new ServerConnector(server,
-                        new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
-                        new HttpConnectionFactory(httpsConfiguration))) {
-                    serverConnector.setPort(httpsPort);
-                    serverConnector.setIdleTimeout(500000);
-                }
+                handlerCollection = new HandlerCollection();
+                handlerCollection.setHandlers(new Handler[]{contextHandlerCollection, new DefaultHandler()});
+                handlerCollection.addHandler(requestLogHandler);
 
                 server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector});
             }
         }
-        server.setHandler(hc);
-        server.setStopAtShutdown(true);
-        server.setStopTimeout(5000);
+        server.setHandler(handlerCollection);
 
-        server.setDumpAfterStart(false);
-        server.setDumpBeforeStop(false);
+        // Daemon to clean up the log directory on a daily basis
+        Timer rolex = new Timer();
+        rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L);    // run once per day
+
+        // Start LogfileLoader
+        LogfileLoader.getLoader();
 
-        server.start();
+        try {
+            server.start();
+            intlogger.info("Prov Server started-" + server.getState());
+        } catch (Exception e) {
+            intlogger.info("Jetty failed to start. Reporting will we unavailable", e);
+        }
         server.join();
-        logger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
+        intlogger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
     }
 
     private static boolean checkDatabase() {
@@ -270,7 +301,7 @@ public class Main {
                 Thread.sleep(5000L);
                 System.exit(0);
             } catch (Exception e) {
-                // ignore
+                intlogger.error("Exception in Main.shutdown() method " + e);
             }
         });
     }
index 2127f00..35ce062 100644 (file)
@@ -128,17 +128,6 @@ public class SubscribeServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (!aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
-            }
-
             // Display a list of URLs
             Collection<String> list = Subscription.getSubscriptionUrlList(feedid);
             String t = JSONUtilities.createJSONArray(list);
@@ -228,17 +217,6 @@ public class SubscribeServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
                 return;
             }
-            // Check with the Authorizer
-            AuthorizationResponse aresp = authz.decide(req);
-            if (!aresp.isAuthorized()) {
-                message = "Policy Engine disallows access.";
-                elr.setMessage(message);
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);
-                eventlogger.info(elr);
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
-                return;
-            }
-
             // check content type is SUB_CONTENT_TYPE, version 1.0
             ContentHeader ch = getContentHeader(req);
             String ver = ch.getAttribute("version");
@@ -272,7 +250,7 @@ public class SubscribeServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
                 return;
             }
-            Subscription sub = null;
+            Subscription sub;
             try {
                 sub = new Subscription(jo);
             } catch (InvalidObjectException e) {
@@ -286,13 +264,70 @@ public class SubscribeServlet extends ProxyServlet {
             }
             sub.setFeedid(feedid);
             sub.setSubscriber(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header
+            /*
+             * START - AAF changes
+             * TDP EPIC US# 307413
+             * CADI code - check on permissions based on Legacy/AAF users to allow to create/add subscription
+             */
+            String feedAafInstance = feed.getAafInstance();
+            String subAafInstance = sub.getAafInstance();
+            boolean subAafLegacyEmptyOrNull = (subAafInstance == null || subAafInstance.equals("") || subAafInstance.equalsIgnoreCase("legacy"));
 
+            // This extra check added to verify AAF feed with AAF subscriber having empty aaf instance check
+            if (feedAafInstance == null || feedAafInstance.equals("") || feedAafInstance.equalsIgnoreCase("legacy")) {
+                if (subAafLegacyEmptyOrNull) {
+                    AuthorizationResponse aresp = authz.decide(req);
+                    if (!aresp.isAuthorized()) {
+                        message = "Policy Engine disallows access";
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                } else {
+                    //If Legacy Feed and AAF instance provided in Subscriber JSON
+                    message = "AAF Subscriber can not be added to legacy Feed- " + feedid;
+                    elr.setMessage(message);
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                    eventlogger.info(elr);
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                    return;
+                }
+            } else {
+                //New AAF Requirement to add legacy subscriber to AAF Feed
+                if (subAafLegacyEmptyOrNull) {
+                    AuthorizationResponse aresp = authz.decide(req);
+                    if (!aresp.isAuthorized()) {
+                        message = "Policy Engine disallows access.";
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                } else {
+                    //New AAF Requirement to add subscriber by publisher on publisher approval only
+                    String permission = getSubscriberPermission(subAafInstance, BaseServlet.APPROVE_SUB_PERMISSION);
+                    eventlogger.info("SubscribeServlet.doPost().. Permission String - " + permission);
+                    if (!req.isUserInRole(permission)) {
+                        message = "AAF disallows access to permission - " + permission;
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_FORBIDDEN);
+                        eventlogger.info(elr);
+                        sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
+                        return;
+                    }
+                }
+            }
+            /*
+             * END - AAF changes
+             */
             // Check if this subscription already exists; not an error (yet), just warn
             Subscription sub2 = Subscription.getSubscriptionMatching(sub);
             if (sub2 != null) {
                 intlogger.warn(
-                    "PROV0011 Creating a duplicate subscription: new subid=" + sub.getSubid() + ", old subid=" + sub2
-                        .getSubid());
+                    "PROV0011 Creating a duplicate subscription: new subid=" + sub.getSubid() + ", old subid=" + sub2.getSubid());
             }
 
             // Create SUBSCRIPTIONS table entries
index ec4d33a..d7c4657 100644 (file)
@@ -58,7 +58,7 @@ import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.send
 @SuppressWarnings("serial")\r
 public class SubscriptionServlet extends ProxyServlet {\r
 \r
-    public static final String SUBCNTRL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-control";\r
+    private static final String SUBCNTRL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-control";\r
     //Adding EELF Logger Rally:US664892\r
     private static EELFLogger eelflogger = EELFManager.getInstance()\r
         .getLogger(SubscriptionServlet.class);\r
@@ -113,17 +113,37 @@ public class SubscriptionServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);\r
                 return;\r
             }\r
-            // Check with the Authorizer\r
-            AuthorizationResponse aresp = authz.decide(req);\r
-            if (!aresp.isAuthorized()) {\r
-                message = "Policy Engine disallows access.";\r
-                elr.setMessage(message);\r
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
-                eventlogger.info(elr);\r
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);\r
-                return;\r
+            /*\r
+             * START - AAF changes\r
+             * TDP EPIC US# 307413\r
+             * CADI code - check on permissions based on Legacy/AAF users to allow to delete/remove subscription\r
+             */\r
+            String aafInstance = sub.getAafInstance();\r
+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {\r
+                AuthorizationResponse aresp = authz.decide(req);\r
+                if (!aresp.isAuthorized()) {\r
+                    message = "Policy Engine disallows access.";\r
+                    elr.setMessage(message);\r
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
+                    eventlogger.info(elr);\r
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);\r
+                    return;\r
+                }\r
+            } else {\r
+                String permission = getSubscriberPermission(aafInstance, BaseServlet.DELETE_PERMISSION);\r
+                eventlogger.info("SubscriptionServlet.doDelete().. Permission String - " + permission);\r
+                if (!req.isUserInRole(permission)) {\r
+                    message = "AAF disallows access to permission - " + permission;\r
+                    elr.setMessage(message);\r
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
+                    eventlogger.info(elr);\r
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);\r
+                    return;\r
+                }\r
             }\r
-\r
+            /*\r
+             * END - AAF changes\r
+             */\r
             // Delete Subscription\r
             if (doDelete(sub)) {\r
                 activeSubs--;\r
@@ -270,16 +290,6 @@ public class SubscriptionServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);\r
                 return;\r
             }\r
-            // Check with the Authorizer\r
-            AuthorizationResponse aresp = authz.decide(req);\r
-            if (!aresp.isAuthorized()) {\r
-                message = "Policy Engine disallows access.";\r
-                elr.setMessage(message);\r
-                elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
-                eventlogger.info(elr);\r
-                sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);\r
-                return;\r
-            }\r
             // check content type is SUB_CONTENT_TYPE, version 1.0\r
             ContentHeader ch = getContentHeader(req);\r
             String ver = ch.getAttribute("version");\r
@@ -314,6 +324,38 @@ public class SubscriptionServlet extends ProxyServlet {
                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);\r
                 return;\r
             }\r
+\r
+            /*\r
+             * START - AAF changes\r
+             * TDP EPIC US# 307413\r
+             * CADI code - check on permissions based on Legacy/AAF users to allow to delete/remove subscription\r
+             */\r
+            String aafInstance = sub.getAafInstance();\r
+            if (aafInstance == null || aafInstance.equals("") || aafInstance.equalsIgnoreCase("legacy")) {\r
+                AuthorizationResponse aresp = authz.decide(req);\r
+                if (!aresp.isAuthorized()) {\r
+                    message = "Policy Engine disallows access.";\r
+                    elr.setMessage(message);\r
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
+                    eventlogger.info(elr);\r
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);\r
+                    return;\r
+                }\r
+            } else {\r
+                String permission = getSubscriberPermission(aafInstance, BaseServlet.EDIT_PERMISSION);\r
+                eventlogger.info("SubscriptionServlet.doDelete().. Permission String - " + permission);\r
+                if (!req.isUserInRole(permission)) {\r
+                    message = "AAF disallows access to permission - " + permission;\r
+                    elr.setMessage(message);\r
+                    elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
+                    eventlogger.info(elr);\r
+                    sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);\r
+                    return;\r
+                }\r
+            }\r
+            /*\r
+             * END - AAF changes\r
+             */\r
             sub.setSubid(oldsub.getSubid());\r
             sub.setFeedid(oldsub.getFeedid());\r
             sub.setSubscriber(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header\r
@@ -373,13 +415,6 @@ public class SubscriptionServlet extends ProxyServlet {
      */\r
     @Override\r
     public void doPost(HttpServletRequest req, HttpServletResponse resp) {\r
-// OLD pre-3.0 code\r
-//        String message = "POST not allowed for the subscriptionURL.";\r
-//        EventLogRecord elr = new EventLogRecord(req);\r
-//        elr.setMessage(message);\r
-//        elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);\r
-//        eventlogger.info(elr);\r
-//        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);\r
 \r
         setIpFqdnRequestIDandInvocationIDForEelf("doPost", req);\r
         eelflogger.info(EelfMsgs.ENTRY);\r
index a2076b0..502dbbd 100644 (file)
 \r
 package org.onap.dmaap.datarouter.provisioning.beans;\r
 \r
+import org.apache.log4j.Level;\r
 import org.apache.log4j.Logger;\r
 import org.json.JSONArray;\r
+import org.json.JSONException;\r
 import org.json.JSONObject;\r
 import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;\r
+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;\r
 import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;\r
 \r
 import java.io.InvalidObjectException;\r
+import java.security.GeneralSecurityException;\r
 import java.sql.*;\r
-import java.util.*;\r
 import java.util.Date;\r
+import java.util.*;\r
 \r
 /**\r
  * The representation of a Feed.  Feeds can be retrieved from the DB, or stored/updated in the DB.\r
@@ -59,6 +63,7 @@ public class Feed extends Syncable {
     private boolean suspended;\r
     private Date last_mod;\r
     private Date created_date;\r
+    private String aaf_instance;\r
 \r
     /**\r
      * Check if a feed ID is valid.\r
@@ -82,7 +87,7 @@ public class Feed extends Syncable {
             }\r
             db.release(conn);\r
         } catch (SQLException e) {\r
-            intlogger.error("SQLException " + e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0024 Feed.isFeedValid: ", e);\r
         }\r
         return count != 0;\r
     }\r
@@ -132,8 +137,8 @@ public class Feed extends Syncable {
             }\r
             db.release(conn);\r
         } catch (SQLException e) {\r
-            intlogger.info("countActiveFeeds: " + e.getMessage());\r
-            intlogger.error("SQLException " + e.getMessage());\r
+            intlogger.info("PROV0025 Feed.countActiveFeeds: " + e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0025 Feed.countActiveFeeds: ", e);\r
         }\r
         return count;\r
     }\r
@@ -153,8 +158,8 @@ public class Feed extends Syncable {
             }\r
             db.release(conn);\r
         } catch (SQLException e) {\r
-            intlogger.info("getMaxFeedID: " + e.getMessage());\r
-            intlogger.error("SQLException " + e.getMessage());\r
+            intlogger.info("PROV0026 Feed.getMaxFeedID: "+e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0026 Feed.getMaxFeedID: ", e);\r
         }\r
         return max;\r
     }\r
@@ -200,7 +205,7 @@ public class Feed extends Syncable {
             }\r
             db.release(conn);\r
         } catch (SQLException e) {\r
-            intlogger.error("SQLException " + e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0027 Feed.getAllFeeds: ", e);\r
         }\r
         return map.values();\r
     }\r
@@ -234,7 +239,7 @@ public class Feed extends Syncable {
             }\r
             db.release(conn);\r
         } catch (SQLException e) {\r
-            intlogger.error("SQLException " + e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0028 Feed.getFilteredFeedUrlList: ", e);\r
         }\r
         return list;\r
     }\r
@@ -271,7 +276,7 @@ public class Feed extends Syncable {
             }\r
             db.release(conn);\r
         } catch (SQLException e) {\r
-            intlogger.error("SQLException " + e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0029 Feed.getFeedBySQL: ", e);\r
         }\r
         return feed;\r
     }\r
@@ -294,6 +299,7 @@ public class Feed extends Syncable {
         this.suspended = false;\r
         this.last_mod = new Date();\r
         this.created_date = new Date();\r
+        this.aaf_instance = "";\r
     }\r
 \r
     public Feed(ResultSet rs) throws SQLException {\r
@@ -315,6 +321,7 @@ public class Feed extends Syncable {
         this.suspended = rs.getBoolean("SUSPENDED");\r
         this.last_mod = rs.getDate("LAST_MOD");\r
         this.created_date = rs.getTimestamp("CREATED_DATE");\r
+        this.aaf_instance = rs.getString("AAF_INSTANCE");\r
     }\r
 \r
     public Feed(JSONObject jo) throws InvalidObjectException {\r
@@ -322,41 +329,49 @@ public class Feed extends Syncable {
         try {\r
             // The JSONObject is assumed to contain a vnd.dmaap-dr.feed representation\r
             this.feedid = jo.optInt("feedid", -1);\r
-            this.groupid = jo.optInt("groupid"); //New field is added - Groups feature Rally:US708115 - 1610\r
+            this.groupid = jo.optInt("groupid");\r
             this.name = jo.getString("name");\r
+            this.aaf_instance = jo.optString("aaf_instance", "legacy");\r
+            if(!(aaf_instance.equalsIgnoreCase("legacy"))){\r
+                if (aaf_instance.length() > 255){\r
+                    throw new InvalidObjectException("aaf_instance field is too long");\r
+                }\r
+            }\r
             if (name.length() > 255)\r
                 throw new InvalidObjectException("name field is too long");\r
-            this.version = jo.getString("version");\r
-            if (version.length() > 20)\r
+            try {\r
+                this.version = jo.getString("version");\r
+            } catch (JSONException e) {\r
+                this.version = null;\r
+            }\r
+            if(version != null && version.length() > 20)\r
                 throw new InvalidObjectException("version field is too long");\r
             this.description = jo.optString("description");\r
-            this.business_description = jo.optString("business_description"); // New field is added - Groups feature Rally:US708102 - 1610\r
+            this.business_description = jo.optString("business_description");\r
             if (description.length() > 1000)\r
                 throw new InvalidObjectException("technical description field is too long");\r
-\r
-            if (business_description.length() > 1000) // New field is added - Groups feature Rally:US708102 - 1610\r
+            if (business_description.length() > 1000)\r
                 throw new InvalidObjectException("business description field is too long");\r
-\r
             this.authorization = new FeedAuthorization();\r
             JSONObject jauth = jo.getJSONObject("authorization");\r
             this.authorization.setClassification(jauth.getString("classification"));\r
             if (this.authorization.getClassification().length() > 32)\r
                 throw new InvalidObjectException("classification field is too long");\r
-            JSONArray ja = jauth.getJSONArray("endpoint_ids");\r
-            for (int i = 0; i < ja.length(); i++) {\r
-                JSONObject id = ja.getJSONObject(i);\r
+            JSONArray endPointIds = jauth.getJSONArray("endpoint_ids");\r
+            for (int i = 0; i < endPointIds.length(); i++) {\r
+                JSONObject id = endPointIds.getJSONObject(i);\r
                 FeedEndpointID fid = new FeedEndpointID(id.getString("id"), id.getString("password"));\r
-                if (fid.getId().length() > 20)\r
+                if (fid.getId().length() > 60)\r
                     throw new InvalidObjectException("id field is too long (" + fid.getId() + ")");\r
                 if (fid.getPassword().length() > 32)\r
-                    throw new InvalidObjectException("password field is too long (" + fid.getPassword() + ")");\r
+                    throw new InvalidObjectException("password field is too long ("+ fid.getPassword()+")");  //Fortify scan fixes - Privacy Violation\r
                 this.authorization.getEndpoint_ids().add(fid);\r
             }\r
             if (this.authorization.getEndpoint_ids().size() < 1)\r
                 throw new InvalidObjectException("need to specify at least one endpoint_id");\r
-            ja = jauth.getJSONArray("endpoint_addrs");\r
-            for (int i = 0; i < ja.length(); i++) {\r
-                String addr = ja.getString(i);\r
+            endPointIds = jauth.getJSONArray("endpoint_addrs");\r
+            for (int i = 0; i < endPointIds.length(); i++) {\r
+                String addr = endPointIds.getString(i);\r
                 if (!JSONUtilities.validIPAddrOrSubnet(addr))\r
                     throw new InvalidObjectException("bad IP addr or subnet mask: " + addr);\r
                 this.authorization.getEndpoint_addrs().add(addr);\r
@@ -368,8 +383,10 @@ public class Feed extends Syncable {
             JSONObject jol = jo.optJSONObject("links");\r
             this.links = (jol == null) ? (new FeedLinks()) : (new FeedLinks(jol));\r
         } catch (InvalidObjectException e) {\r
+            intlogger.log(Level.WARN, "PROV0030 Feed.Feed: ", e);\r
             throw e;\r
         } catch (Exception e) {\r
+            intlogger.error("PROV0031 Feed.Feed: invalid JSON: "+e);\r
             throw new InvalidObjectException("invalid JSON: " + e.getMessage());\r
         }\r
     }\r
@@ -389,6 +406,14 @@ public class Feed extends Syncable {
         fl.setLog(URLUtilities.generateFeedLogURL(feedid));\r
     }\r
 \r
+    public String getAafInstance() {\r
+        return aaf_instance;\r
+    }\r
+\r
+    public void setAaf_instance(String aaf_instance) {\r
+        this.aaf_instance = aaf_instance;\r
+    }\r
+\r
     //new getter setters for groups- Rally:US708115 - 1610\r
     public int getGroupid() {\r
         return groupid;\r
@@ -499,6 +524,7 @@ public class Feed extends Syncable {
         jo.put("suspend", suspended);\r
         jo.put("last_mod", last_mod.getTime());\r
         jo.put("created_date", created_date.getTime());\r
+        jo.put("aaf_instance", aaf_instance);\r
         return jo;\r
     }\r
 \r
@@ -581,7 +607,7 @@ public class Feed extends Syncable {
             }\r
 \r
             // Finally, create the FEEDS row\r
-            sql = "insert into FEEDS (FEEDID, NAME, VERSION, DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, DELETED, SUSPENDED,BUSINESS_DESCRIPTION, GROUPID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?)";\r
+            sql = "insert into FEEDS (FEEDID, NAME, VERSION, DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, DELETED, SUSPENDED,BUSINESS_DESCRIPTION, GROUPID, AAF_INSTANCE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";\r
             try(PreparedStatement ps2 = c.prepareStatement(sql)) {\r
                 ps2.setInt(1, feedid);\r
                 ps2.setString(2, getName());\r
@@ -595,8 +621,9 @@ public class Feed extends Syncable {
                 ps2.setString(10, getLinks().getLog());\r
                 ps2.setBoolean(11, isDeleted());\r
                 ps2.setBoolean(12, isSuspended());\r
-                ps2.setString(13, getBusiness_description()); // New field is added - Groups feature Rally:US708102 - 1610\r
-                ps2.setInt(14, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
+                ps2.setString(13, getBusiness_description());\r
+                ps2.setInt(14, groupid);\r
+                ps2.setString(15, getAafInstance());\r
                 ps2.executeUpdate();\r
             }\r
         } catch (SQLException e) {\r
@@ -675,8 +702,8 @@ public class Feed extends Syncable {
             ps.setString(2, getAuthorization().getClassification());\r
             ps.setInt(3, deleted ? 1 : 0);\r
             ps.setInt(4, suspended ? 1 : 0);\r
-            ps.setString(5, getBusiness_description()); // New field is added - Groups feature Rally:US708102 - 1610\r
-            ps.setInt(6, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
+            ps.setString(5, getBusiness_description());\r
+            ps.setInt(6, groupid);\r
             ps.setInt(7, feedid);\r
             ps.executeUpdate();\r
             ps.close();\r
@@ -760,6 +787,8 @@ public class Feed extends Syncable {
             return false;\r
         if (suspended != of.suspended)\r
             return false;\r
+        if (!aaf_instance.equals(of.aaf_instance))\r
+            return false;\r
         return true;\r
     }\r
 \r
@@ -770,6 +799,6 @@ public class Feed extends Syncable {
 \r
     @Override\r
     public int hashCode() {\r
-        return Objects.hash(feedid, groupid, name, version, description, business_description, authorization, publisher, links, deleted, suspended, last_mod, created_date);\r
+        return super.hashCode();\r
     }\r
-}\r
+}
\ No newline at end of file
index 0c0c546..bdc062f 100644 (file)
 \r
 package org.onap.dmaap.datarouter.provisioning.beans;\r
 \r
-import java.io.InvalidObjectException;\r
-import java.sql.Connection;\r
-import java.sql.PreparedStatement;\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
-import java.sql.Statement;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Objects;\r
-import java.util.Properties;\r
+import org.apache.log4j.Level;\r
 import org.apache.log4j.Logger;\r
 import org.json.JSONObject;\r
 import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;\r
 import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;\r
 \r
+import java.io.InvalidObjectException;\r
+import java.security.GeneralSecurityException;\r
+import java.sql.*;\r
+import java.util.Date;\r
+import java.util.*;\r
+\r
 /**\r
  * The representation of a Subscription.  Subscriptions can be retrieved from the DB, or stored/updated in the DB.\r
  *\r
@@ -62,6 +58,7 @@ public class Subscription extends Syncable {
     private int feedid;\r
     private int groupid; //New field is added - Groups feature Rally:US708115 - 1610\r
     private SubDelivery delivery;\r
+    private boolean followRedirect;\r
     private boolean metadataOnly;\r
     private String subscriber;\r
     private SubLinks links;\r
@@ -69,18 +66,20 @@ public class Subscription extends Syncable {
     private Date lastMod;\r
     private Date createdDate;\r
     private boolean privilegedSubscriber;\r
+    private String aafInstance;\r
     private boolean decompress;\r
 \r
     public static Subscription getSubscriptionMatching(Subscription sub) {\r
         SubDelivery deli = sub.getDelivery();\r
         String sql = String.format(\r
-                "select * from SUBSCRIPTIONS where FEEDID = %d and DELIVERY_URL = \"%s\" and DELIVERY_USER = \"%s\" and DELIVERY_PASSWORD = \"%s\" and DELIVERY_USE100 = %d and METADATA_ONLY = %d",\r
+                "select * from SUBSCRIPTIONS where FEEDID = %d and DELIVERY_URL = \"%s\" and DELIVERY_USER = \"%s\" and DELIVERY_PASSWORD = \"%s\" and DELIVERY_USE100 = %d and METADATA_ONLY = %d and FOLLOW_REDIRECTS = %d",\r
                 sub.getFeedid(),\r
                 deli.getUrl(),\r
                 deli.getUser(),\r
                 deli.getPassword(),\r
                 deli.isUse100() ? 1 : 0,\r
-                sub.isMetadataOnly() ? 1 : 0\r
+                sub.isMetadataOnly() ? 1 : 0,\r
+                sub.isFollowRedirect() ? 1 :0\r
         );\r
         List<Subscription> list = getSubscriptionsForSQL(sql);\r
         return !list.isEmpty() ? list.get(0) : null;\r
@@ -145,7 +144,6 @@ public class Subscription extends Syncable {
             DB db = new DB();\r
             @SuppressWarnings("resource")\r
             Connection conn = db.getConnection();\r
-\r
             try (PreparedStatement stmt = conn.prepareStatement(sql)) {\r
                 stmt.setString(1, String.valueOf(feedid));\r
                 try (ResultSet rs = stmt.executeQuery()) {\r
@@ -197,12 +195,14 @@ public class Subscription extends Syncable {
         this.groupid = -1; //New field is added - Groups feature Rally:US708115 - 1610\r
         this.delivery = new SubDelivery(url, user, password, false);\r
         this.metadataOnly = false;\r
+        this.followRedirect = false;\r
         this.subscriber = "";\r
         this.links = new SubLinks();\r
         this.suspended = false;\r
         this.lastMod = new Date();\r
         this.createdDate = new Date();\r
         this.privilegedSubscriber = false;\r
+        this.aafInstance = "";\r
         this.decompress = false;\r
     }\r
 \r
@@ -212,13 +212,14 @@ public class Subscription extends Syncable {
         this.groupid = rs.getInt("GROUPID"); //New field is added - Groups feature Rally:US708115 - 1610\r
         this.delivery = new SubDelivery(rs);\r
         this.metadataOnly = rs.getBoolean("METADATA_ONLY");\r
+        this.followRedirect = rs.getBoolean("FOLLOW_REDIRECTS");\r
         this.subscriber = rs.getString("SUBSCRIBER");\r
-        this.links = new SubLinks(rs.getString("SELF_LINK"), URLUtilities.generateFeedURL(feedid),\r
-                rs.getString("LOG_LINK"));\r
+        this.links = new SubLinks(rs.getString("SELF_LINK"), URLUtilities.generateFeedURL(feedid), rs.getString("LOG_LINK"));\r
         this.suspended = rs.getBoolean("SUSPENDED");\r
         this.lastMod = rs.getDate("LAST_MOD");\r
         this.createdDate = rs.getDate("CREATED_DATE");\r
         this.privilegedSubscriber = rs.getBoolean("PRIVILEGED_SUBSCRIBER");\r
+        this.aafInstance = rs.getString("AAF_INSTANCE");\r
         this.decompress  = rs.getBoolean("DECOMPRESS");\r
     }\r
 \r
@@ -229,7 +230,11 @@ public class Subscription extends Syncable {
             this.subid = jo.optInt(SUBID_KEY, -1);\r
             this.feedid = jo.optInt(FEEDID_KEY, -1);\r
             this.groupid = jo.optInt(GROUPID_KEY, -1); //New field is added - Groups feature Rally:US708115 - 1610\r
-\r
+            this.aafInstance = jo.optString("aaf_instance", "legacy");\r
+            if(!(aafInstance.equalsIgnoreCase("legacy"))){\r
+                if (aafInstance.length() > 255)\r
+                    throw new InvalidObjectException("aaf_instance field is too long");\r
+            }\r
             JSONObject jdeli = jo.getJSONObject("delivery");\r
             String url = jdeli.getString("url");\r
             String user = jdeli.getString("user");\r
@@ -245,15 +250,15 @@ public class Subscription extends Syncable {
             if (url.length() > 256) {\r
                 throw new InvalidObjectException("delivery url field is too long");\r
             }\r
-            if (user.length() > 20) {\r
+            if (user.length() > 60) {\r
                 throw new InvalidObjectException("delivery user field is too long");\r
             }\r
             if (password.length() > 32) {\r
                 throw new InvalidObjectException("delivery password field is too long");\r
             }\r
             this.delivery = new SubDelivery(url, user, password, use100);\r
-\r
             this.metadataOnly = jo.getBoolean("metadataOnly");\r
+            this.followRedirect = jo.optBoolean("follow_redirect", false);\r
             this.suspended = jo.optBoolean("suspend", false);\r
             this.privilegedSubscriber = jo.optBoolean("privilegedSubscriber", false);\r
             this.decompress = jo.optBoolean("decompress", false);\r
@@ -296,6 +301,13 @@ public class Subscription extends Syncable {
         SubLinks sl = getLinks();\r
         sl.setFeed(URLUtilities.generateFeedURL(feedid));\r
     }\r
+    public String getAafInstance() {\r
+        return aafInstance;\r
+    }\r
+\r
+    public void setAafInstance(String aafInstance) {\r
+        this.aafInstance = aafInstance;\r
+    }\r
 \r
     //New getter setters for Groups feature Rally:US708115 - 1610\r
     public int getGroupid() {\r
@@ -322,7 +334,14 @@ public class Subscription extends Syncable {
         this.metadataOnly = metadataOnly;\r
     }\r
 \r
-    public boolean isSuspended() {\r
+    private boolean isFollowRedirect() {\r
+        return followRedirect;\r
+    }\r
+    public void setFollowRedirect(boolean followRedirect) {\r
+        this.followRedirect = followRedirect;\r
+    }\r
+\r
+    boolean isSuspended() {\r
         return suspended;\r
     }\r
 \r
@@ -355,7 +374,7 @@ public class Subscription extends Syncable {
         return links;\r
     }\r
 \r
-    public void setLinks(SubLinks links) {\r
+    void setLinks(SubLinks links) {\r
         this.links = links;\r
     }\r
 \r
@@ -375,12 +394,14 @@ public class Subscription extends Syncable {
         jo.put(GROUPID_KEY, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
         jo.put("delivery", delivery.asJSONObject());\r
         jo.put("metadataOnly", metadataOnly);\r
+        jo.put("follow_redirect", followRedirect);\r
         jo.put("subscriber", subscriber);\r
         jo.put("links", links.asJSONObject());\r
         jo.put("suspend", suspended);\r
         jo.put(LAST_MOD_KEY, lastMod.getTime());\r
         jo.put(CREATED_DATE, createdDate.getTime());\r
         jo.put("privilegedSubscriber", privilegedSubscriber);\r
+        jo.put("aaf_instance", aafInstance);\r
         jo.put("decompress", decompress);\r
         return jo;\r
     }\r
@@ -419,7 +440,7 @@ public class Subscription extends Syncable {
             }\r
 \r
             // Create the SUBSCRIPTIONS row\r
-            String sql = "insert into SUBSCRIPTIONS (SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, DECOMPRESS) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";\r
+            String sql = "insert into SUBSCRIPTIONS (SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, FOLLOW_REDIRECTS, DECOMPRESS, AAF_INSTANCE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";\r
             ps = c.prepareStatement(sql, new String[]{SUBID_COL});\r
             ps.setInt(1, subid);\r
             ps.setInt(2, feedid);\r
@@ -432,7 +453,9 @@ public class Subscription extends Syncable {
             ps.setBoolean(9, isSuspended());\r
             ps.setInt(10, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
             ps.setBoolean(11, isPrivilegedSubscriber());\r
-            ps.setBoolean(12, isDecompress());\r
+            ps.setInt(12, isFollowRedirect() ? 1 : 0);\r
+            ps.setBoolean(13, isDecompress());\r
+            ps.setString(14, getAafInstance());\r
             ps.execute();\r
             ps.close();\r
             // Update the row to set the URLs\r
@@ -446,6 +469,7 @@ public class Subscription extends Syncable {
         } catch (SQLException e) {\r
             rv = false;\r
             intlogger.warn("PROV0005 doInsert: " + e.getMessage());\r
+            intlogger.log(Level.WARN, "PROV0005 Subscription.doInsert(1): ", e);\r
         } finally {\r
             try {\r
                 if (ps != null) {\r
@@ -463,7 +487,7 @@ public class Subscription extends Syncable {
         boolean rv = true;\r
         PreparedStatement ps = null;\r
         try {\r
-            String sql = "update SUBSCRIPTIONS set DELIVERY_URL = ?, DELIVERY_USER = ?, DELIVERY_PASSWORD = ?, DELIVERY_USE100 = ?, METADATA_ONLY = ?, SUSPENDED = ?, GROUPID = ?, PRIVILEGED_SUBSCRIBER = ?, DECOMPRESS = ? where SUBID = ?";\r
+            String sql = "update SUBSCRIPTIONS set DELIVERY_URL = ?, DELIVERY_USER = ?, DELIVERY_PASSWORD = ?, DELIVERY_USE100 = ?, METADATA_ONLY = ?, SUSPENDED = ?, GROUPID = ?, PRIVILEGED_SUBSCRIBER = ?, FOLLOW_REDIRECTS = ?, DECOMPRESS = ? where SUBID = ?";\r
             ps = c.prepareStatement(sql);\r
             ps.setString(1, delivery.getUrl());\r
             ps.setString(2, delivery.getUser());\r
@@ -473,8 +497,9 @@ public class Subscription extends Syncable {
             ps.setInt(6, suspended ? 1 : 0);\r
             ps.setInt(7, groupid); //New field is added - Groups feature Rally:US708115 - 1610\r
             ps.setInt(8, privilegedSubscriber ? 1 : 0);\r
-            ps.setInt(9, decompress ? 1 : 0);\r
-            ps.setInt(10, subid);\r
+            ps.setInt(9, isFollowRedirect() ? 1 : 0);\r
+            ps.setInt(10, isDecompress() ? 1 : 0);\r
+            ps.setInt(11, subid);\r
             ps.executeUpdate();\r
         } catch (SQLException e) {\r
             rv = false;\r
@@ -576,19 +601,27 @@ public class Subscription extends Syncable {
         if (metadataOnly != os.metadataOnly) {\r
             return false;\r
         }\r
+        if (followRedirect != os.followRedirect) {\r
+            return false;\r
+        }\r
         if (!subscriber.equals(os.subscriber)) {\r
             return false;\r
         }\r
         if (!links.equals(os.links)) {\r
             return false;\r
         }\r
-        return suspended == os.suspended;\r
+        if (suspended != os.suspended) {\r
+            return false;\r
+        }\r
+        if (!aafInstance.equals(os.aafInstance)) {\r
+            return false;\r
+        }\r
+        return true;\r
     }\r
 \r
     @Override\r
     public int hashCode() {\r
-        return Objects.hash(subid, feedid, groupid, delivery, metadataOnly, subscriber, links, suspended, lastMod,\r
-                createdDate);\r
+        return super.hashCode();\r
     }\r
 \r
     @Override\r
index 3e2436f..8ca7118 100644 (file)
@@ -185,8 +185,8 @@ public class DB {
             connection = getConnection();\r
             Set<String> actualTables = getTableSet(connection);\r
             boolean initialize = false;\r
-            for (String table : expectedTables) {\r
-                initialize |= !actualTables.contains(table.toLowerCase());\r
+            for (String tableName : expectedTables) {\r
+                initialize |= !actualTables.contains(tableName);\r
             }\r
             if (initialize) {\r
                 intlogger.info("PROV9001: First time startup; The database is being initialized.");\r
@@ -211,13 +211,13 @@ public class DB {
      * @return the set of table names\r
      */\r
     private Set<String> getTableSet(Connection connection) {\r
-        Set<String> tables = new HashSet<String>();\r
+        Set<String> tables = new HashSet<>();\r
         try {\r
             DatabaseMetaData md = connection.getMetaData();\r
             ResultSet rs = md.getTables(null, null, "%", null);\r
             if (rs != null) {\r
                 while (rs.next()) {\r
-                    tables.add(rs.getString("TABLE_NAME"));\r
+                    tables.add(rs.getString("TABLE_NAME").toUpperCase());\r
                 }\r
                 rs.close();\r
             }\r
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilter.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilter.java
new file mode 100644 (file)
index 0000000..fb8b072
--- /dev/null
@@ -0,0 +1,259 @@
+/**
+ * -
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ * <p>
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dmaap.datarouter.provisioning.utils;
+
+import org.apache.log4j.Logger;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.filter.CadiFilter;
+import org.onap.dmaap.datarouter.provisioning.BaseServlet;
+import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
+import org.onap.dmaap.datarouter.provisioning.beans.Feed;
+import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+
+public class DRProvCadiFilter extends CadiFilter {
+    private static Logger eventlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.events");
+    private static Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
+    private String aafInstance = "";
+
+    public DRProvCadiFilter(boolean init, PropAccess access) throws ServletException {
+        super(init, access);
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        HttpServletRequest httpRequest = null;
+        HttpServletResponse httpResponse = null;
+        //cadi code
+        try {
+            httpRequest = (HttpServletRequest) request;
+            httpResponse = (HttpServletResponse) response;
+        } catch (ClassCastException e) {
+            try {
+                throw new ServletException("Only serving HTTP today", e);
+            } catch (ServletException e1) {
+                intlogger.error("PROV7001 DRProvCadiFilter.doFilter: ", e1);
+            }
+        }
+        EventLogRecord elr = new EventLogRecord(httpRequest);
+        String excludeAAF = httpRequest.getHeader(BaseServlet.EXCLUDE_AAF_HEADER);//send this param value as true, if want to add legacy feed/subscriber in AAF env
+
+        String pathUrl = httpRequest.getServletPath();
+        if (!(pathUrl.contains("internal") ||
+                pathUrl.contains("sublog") ||
+                pathUrl.contains("feedlog") ||
+                pathUrl.contains("statistics") ||
+                pathUrl.contains("publish") ||
+                pathUrl.contains("group"))) {
+
+            String method = httpRequest.getMethod().toUpperCase();
+            if (!(method.equals("POST"))) { // if request method is PUT method (publish or Feed update) Needs to check for DELETE
+                if (method.equals("PUT") || method.equals("DELETE")) {
+                    if ((pathUrl.contains("subs"))) {//edit subscriber
+                        int subId = BaseServlet.getIdFromPath(httpRequest);
+                        if (subId <= 0) {
+                            String message = String.format("Invalid request URI - %s", httpRequest.getPathInfo());
+                            elr.setMessage(message);
+                            elr.setResult(HttpServletResponse.SC_NOT_FOUND);
+                            eventlogger.info(elr);
+                            httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+                            return;
+                        }
+                        if (isAAFSubscriber(subId)) {//edit AAF Subscriber
+                            String message = String.format("DRProvCadiFilter - Edit AAF Subscriber : %d : AAF Instance - %s", subId, aafInstance);
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            //request.setAttribute("aafInstance", aafInstance);// no need to set it in request since it is taken care in respective servlets
+                            super.doFilter(request, response, chain);
+
+                        } else {//Edit or publish legacy Subscriber
+                            String message = "DRProvCadiFilter - Edit/Publish Legacy Subscriber :" + subId;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            chain.doFilter(request, response);
+                        }
+
+                    } else {//edit or publish Feed
+                        int feedId = BaseServlet.getIdFromPath(httpRequest);
+                        if (feedId <= 0) {
+                            String message = "Invalid request URI - " + httpRequest.getPathInfo();
+                            elr.setMessage(message);
+                            elr.setResult(HttpServletResponse.SC_NOT_FOUND);
+                            eventlogger.info(elr);
+                            httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+                            return;
+                        }
+
+                        if (isAAFFeed(feedId)) {//edit AAF Feed
+                            String message = "DRProvCadiFilter - Edit AAF Feed:" + feedId + ":" + "AAF Instance -" + aafInstance;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            super.doFilter(request, response, chain);
+
+                        } else {//Edit or publish legacy Feed
+                            String message = "DRProvCadiFilter - Edit/Publish Legacy Feed:" + feedId;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            chain.doFilter(request, response);
+                        }
+                    }
+                } else {// in all other cases defaults to legacy behavior
+                    String message = "DRProvCadiFilter - Default Legacy Feed/Subscriber URI -:" + httpRequest.getPathInfo();
+                    elr.setMessage(message);
+                    eventlogger.info(elr);
+                    chain.doFilter(request, response);
+                }
+            } else {
+                //check to add legacy/AAF subscriber
+                if ((pathUrl.contains("subscribe"))) {//add subscriber
+                    int feedId = BaseServlet.getIdFromPath(httpRequest);
+                    if (feedId <= 0) {
+                        String message = "Invalid request URI - " + httpRequest.getPathInfo();
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_NOT_FOUND);
+                        eventlogger.info(elr);
+                        httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+                        return;
+                    }
+                    if (isAAFFeed(feedId)) {//check if AAF Feed or legacy to add new subscriber
+                        if (excludeAAF == null) {
+                            String message = "DRProvCadiFilter -Invalid request Header Parmeter " + BaseServlet.EXCLUDE_AAF_HEADER + " = " + httpRequest.getHeader(BaseServlet.EXCLUDE_AAF_HEADER);
+                            elr.setMessage(message);
+                            elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
+                            eventlogger.info(elr);
+                            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+                            return;
+                        }
+                        if (excludeAAF.equalsIgnoreCase("true")) {//Check to add legacy subscriber to AAF Feed
+                            String message = "DRProvCadiFilter - add legacy subscriber to AAF Feed, FeedID:" + feedId;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            chain.doFilter(request, response);
+                        } else {
+                            String message = "DRProvCadiFilter - Add AAF subscriber to AAF Feed, FeedID:" + feedId + ":" + "AAF Instance -" + aafInstance;
+                            elr.setMessage(message);
+                            eventlogger.info(elr);
+                            super.doFilter(request, response, chain);
+                        }
+                    } else {//Add legacy susbcriber to legacy Feed
+                        String message = "DRProvCadiFilter - add legacy subscriber to legacy Feed:" + feedId;
+                        elr.setMessage(message);
+                        eventlogger.info(elr);
+                        chain.doFilter(request, response);
+                    }
+                } else {//add AAF feed
+                    if (excludeAAF == null) {
+                        String message = "DRProvCadiFilter -Invalid request Header Parmeter " + BaseServlet.EXCLUDE_AAF_HEADER + " = " + httpRequest.getHeader(BaseServlet.EXCLUDE_AAF_HEADER);
+                        elr.setMessage(message);
+                        elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
+                        eventlogger.info(elr);
+                        httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
+                        return;
+                    }
+                    if (excludeAAF.equalsIgnoreCase("true")) {//add legacy feed
+                        String message = "DRProvCadiFilter - Create new legacy Feed : EXCLUDE_AAF = " + excludeAAF;
+                        elr.setMessage(message);
+                        eventlogger.info(elr);
+                        chain.doFilter(request, response);
+                    } else {//add AAF Feed
+                        String message = "DRProvCadiFilter - Create new AAF Feed : EXCLUDE_AAF = " + excludeAAF;
+                        elr.setMessage(message);
+                        eventlogger.info(elr);
+                        super.doFilter(request, response, chain);
+                    }
+                }
+            }
+        } else {
+            //All other requests default to (Non CADI) legacy
+            chain.doFilter(request, response);
+        }
+    }
+
+    /**
+     * Check if it is AAF feed OR existing feed.
+     *
+     * @param feedId the Feed ID
+     * @return true if it is valid
+     */
+    @SuppressWarnings("resource")
+    private boolean isAAFFeed(int feedId) {
+        try {
+            Feed feed = Feed.getFeedById(feedId);
+            if (feed != null) {
+                if (!((feed.getAafInstance().equalsIgnoreCase("legacy")) || feed.getAafInstance() == null || feed.getAafInstance().equals(""))) { //also apply null check and empty check too
+                    aafInstance = feed.getAafInstance();
+                    String message = "DRProvCadiFilter.isAAFFeed: aafInstance-:" + aafInstance + "; feedId:- " + feedId;
+                    intlogger.debug(message);
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                String message = "DRProvCadiFilter.isAAFFeed; Feed does not exist FeedID:-" + feedId;
+                intlogger.debug(message);
+            }
+
+        } catch (Exception e) {
+            intlogger.error("PROV0073 DRProvCadiFilter.isAAFFeed: ", e);
+            return false;
+        }
+        return false;
+    }
+
+    /**
+     * Check if it is AAF sub OR existing sub.
+     *
+     * @param subId the Sub ID
+     * @return true if it is valid
+     */
+    @SuppressWarnings("resource")
+    private boolean isAAFSubscriber(int subId) {
+        try {
+            Subscription subscriber = Subscription.getSubscriptionById(subId);
+            if (subscriber != null) {
+                if (!((subscriber.getAafInstance().equalsIgnoreCase("legacy")) || subscriber.getAafInstance() == null || subscriber.getAafInstance().equals(""))) { //also apply null check and empty check too
+                    aafInstance = subscriber.getAafInstance();
+                    String message = "DRProvCadiFilter.isAAFSubscriber: aafInstance-:" + aafInstance + "; subId:- " + subId;
+                    intlogger.debug(message);
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                String message = "DRProvCadiFilter.isAAFSubscriber; Subscriber does not exist subId:-" + subId;
+                intlogger.debug(message);
+            }
+        } catch (Exception e) {
+            intlogger.error("PROV0073 DRProvCadiFilter.isAAFSubscriber: ", e);
+            return false;
+        }
+        return false;
+    }
+
+}
index af9f829..6c5a13f 100644 (file)
@@ -82,7 +82,7 @@ public class LogfileLoader extends Thread {
     /**\r
      * This is a singleton -- there is only one LogfileLoader object in the server\r
      */\r
-    private static LogfileLoader p;\r
+    private static LogfileLoader logfileLoader;\r
 \r
     /**\r
      * Get the singleton LogfileLoader object, and start it if it is not running.\r
@@ -90,11 +90,11 @@ public class LogfileLoader extends Thread {
      * @return the LogfileLoader\r
      */\r
     public static synchronized LogfileLoader getLoader() {\r
-        if (p == null)\r
-            p = new LogfileLoader();\r
-        if (!p.isAlive())\r
-            p.start();\r
-        return p;\r
+        if (logfileLoader == null)\r
+            logfileLoader = new LogfileLoader();\r
+        if (!logfileLoader.isAlive())\r
+            logfileLoader.start();\r
+        return logfileLoader;\r
     }\r
 \r
     /**\r
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/PasswordProcessor.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/PasswordProcessor.java
new file mode 100644 (file)
index 0000000..4414203
--- /dev/null
@@ -0,0 +1,73 @@
+/**\r
+ * -\r
+ * ============LICENSE_START=======================================================\r
+ * Copyright (C) 2019 Nordix Foundation.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * <p>\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * <p>\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * <p>\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.dmaap.datarouter.provisioning.utils;\r
+\r
+import javax.crypto.Cipher;\r
+import javax.crypto.SecretKey;\r
+import javax.crypto.SecretKeyFactory;\r
+import javax.crypto.spec.PBEKeySpec;\r
+import javax.crypto.spec.PBEParameterSpec;\r
+import java.nio.charset.StandardCharsets;\r
+import java.security.GeneralSecurityException;\r
+import java.util.Base64;\r
+\r
+/**\r
+ * The Processing of a Password.  Password can be encrypted and decrypted.\r
+ * @author Vikram Singh\r
+ * @version $Id: PasswordProcessor.java,v 1.0 2016/12/14 10:16:52 EST\r
+ */\r
+public class PasswordProcessor {\r
+\r
+    private PasswordProcessor(){}\r
+\r
+    private static final String SECRET_KEY_FACTORY_TYPE = "PBEWithMD5AndDES";\r
+    private static final String PASSWORD_ENCRYPTION_STRING = (new DB()).getProperties().getProperty("org.onap.dmaap.datarouter.provserver.passwordencryption");\r
+    private static final char[] PASSWORD = PASSWORD_ENCRYPTION_STRING.toCharArray();\r
+    private static final byte[] SALT = {(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,};\r
+\r
+    /**\r
+     * Encrypt password.\r
+     * @param property the Password\r
+     * @return Encrypted password.\r
+     */\r
+    public static String encrypt(String property) throws GeneralSecurityException {\r
+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_TYPE);\r
+        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));\r
+        Cipher pbeCipher = Cipher.getInstance(SECRET_KEY_FACTORY_TYPE);\r
+        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 32));\r
+        return Base64.getEncoder().encodeToString(pbeCipher.doFinal(property.getBytes(StandardCharsets.UTF_8)));\r
+    }\r
+\r
+    /**\r
+     * Decrypt password.\r
+     * @param property the Password\r
+     * @return Decrypt password.\r
+     */\r
+    public static String decrypt(String property) throws GeneralSecurityException {\r
+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_TYPE);\r
+        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));\r
+        Cipher pbeCipher = Cipher.getInstance(SECRET_KEY_FACTORY_TYPE);\r
+        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 32));\r
+        return new String(pbeCipher.doFinal(Base64.getDecoder().decode(property)), StandardCharsets.UTF_8);\r
+    }\r
+\r
+}\r
diff --git a/datarouter-prov/src/main/resources/drProvCadi.properties b/datarouter-prov/src/main/resources/drProvCadi.properties
new file mode 100644 (file)
index 0000000..56f2e5c
--- /dev/null
@@ -0,0 +1,23 @@
+cadi_x509_issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US
+cadi_keyfile=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.keyfile
+cadi_keystore=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.jks
+cadi_keystore_password=AT{];bvaDiytVD&oWhMZj0N5
+cadi_key_password=AT{];bvaDiytVD&oWhMZj0N5
+cadi_alias=dmaap-dr-prov@dmaap-dr.onap.org
+cadi_truststore=/opt/app/datartr/aaf_certs/org.onap.dmaap-dr.trust.jks
+cadi_truststore_password=ljlS@Y}0]{UO(TnwvEWkgJ%]
+
+aaf_env=DEV
+aaf_locate_url=https://aaf-onap-test.osaaf.org:8095
+aaf_oauth2_introspect_url=https://AAF_LOCATE_URL/AAF_NS.introspect:2.1/introspect
+aaf_oauth2_token_url=https://AAF_LOCATE_URL/AAF_NS.token:2.1/token
+aaf_url=https://AAF_LOCATE_URL/AAF_NS.service:2.1
+cadi_protocols=TLSv1.1,TLSv1.2
+cm_url=https://AAF_LOCATE_URL/AAF_NS.cm:2.1
+fs_url=https://AAF_LOCATE_URL/AAF_NS.fs.2.1
+gui_url=https://AAF_LOCATE_URL/AAF_NS.gui.2.1
+
+cadi_latitude=53.423
+cadi_longitude=7.940
+
+cadi_loglevel=DEBUG
\ No newline at end of file
index 14c59a6..55f0aee 100755 (executable)
@@ -1,10 +1,8 @@
-use datarouter;
-
 CREATE TABLE FEEDS (
     FEEDID         INT UNSIGNED NOT NULL PRIMARY KEY,
     GROUPID        INT(10) UNSIGNED NOT NULL DEFAULT 0,
     NAME           VARCHAR(255) NOT NULL,
-    VERSION        VARCHAR(20) NOT NULL,
+    VERSION        VARCHAR(20) NULL,
     DESCRIPTION    VARCHAR(1000),
     BUSINESS_DESCRIPTION VARCHAR(1000) DEFAULT NULL,
     AUTH_CLASS     VARCHAR(32) NOT NULL,
@@ -16,13 +14,14 @@ CREATE TABLE FEEDS (
     DELETED        BOOLEAN DEFAULT FALSE,
     LAST_MOD       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED      BOOLEAN DEFAULT FALSE,
-    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    AAF_INSTANCE   VARCHAR(256)
 );
 
 CREATE TABLE FEED_ENDPOINT_IDS (
     FEEDID        INT UNSIGNED NOT NULL,
-    USERID        VARCHAR(20) NOT NULL,
-    PASSWORD      VARCHAR(32) NOT NULL
+    USERID        VARCHAR(60) NOT NULL,
+    PASSWORD      VARCHAR(100) NOT NULL
 );
 
 CREATE TABLE FEED_ENDPOINT_ADDRS (
@@ -35,8 +34,9 @@ CREATE TABLE SUBSCRIPTIONS (
     FEEDID                      INT UNSIGNED NOT NULL,
     GROUPID                     INT(10) UNSIGNED NOT NULL DEFAULT 0,
     DELIVERY_URL                VARCHAR(256),
-    DELIVERY_USER               VARCHAR(20),
-    DELIVERY_PASSWORD           VARCHAR(32),
+    FOLLOW_REDIRECTS            TINYINT(1) NOT NULL DEFAULT 0,
+    DELIVERY_USER               VARCHAR(60),
+    DELIVERY_PASSWORD           VARCHAR(100),
     DELIVERY_USE100             BOOLEAN DEFAULT FALSE,
     METADATA_ONLY               BOOLEAN DEFAULT FALSE,
     SUBSCRIBER                  VARCHAR(8) NOT NULL,
@@ -45,8 +45,9 @@ CREATE TABLE SUBSCRIPTIONS (
     LAST_MOD                    TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED                   BOOLEAN DEFAULT FALSE,
     PRIVILEGED_SUBSCRIBER       BOOLEAN DEFAULT FALSE,
+    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     DECOMPRESS                  BOOLEAN DEFAULT FALSE,
-    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    AAF_INSTANCE                VARCHAR(256)
 
 );
 
@@ -89,7 +90,7 @@ CREATE TABLE LOG_RECORDS (
 CREATE TABLE INGRESS_ROUTES (
     SEQUENCE  INT UNSIGNED NOT NULL,
     FEEDID    INT UNSIGNED NOT NULL,
-    USERID    VARCHAR(20),
+    USERID    VARCHAR(50),
     SUBNET    VARCHAR(44),
     NODESET   INT UNSIGNED NOT NULL
 );
@@ -144,6 +145,6 @@ INSERT INTO PARAMETERS VALUES
     ('PROV_MAXFEED_COUNT',  '10000'),
     ('PROV_MAXSUB_COUNT',   '100000'),
     ('PROV_REQUIRE_CERT', 'false'),
-    ('PROV_REQUIRE_SECURE', 'false'),
+    ('PROV_REQUIRE_SECURE', 'true'),
     ('_INT_VALUES', 'LOGROLL_INTERVAL|PROV_MAXFEED_COUNT|PROV_MAXSUB_COUNT|DELIVERY_INIT_RETRY_INTERVAL|DELIVERY_MAX_RETRY_INTERVAL|DELIVERY_RETRY_RATIO|DELIVERY_MAX_AGE|DELIVERY_FILE_PROCESS_INTERVAL')
-    ;
+    ;
\ No newline at end of file
index 4dcdee5..4539346 100755 (executable)
@@ -47,6 +47,22 @@ org.onap.dmaap.datarouter.provserver.localhost = 127.0.0.1
 
 # Database access
 org.onap.dmaap.datarouter.db.driver   = org.mariadb.jdbc.Driver
-org.onap.dmaap.datarouter.db.url      = jdbc:mariadb://172.100.0.2:3306/datarouter
+org.onap.dmaap.datarouter.db.url      = jdbc:mariadb://datarouter-mariadb:3306/datarouter
 org.onap.dmaap.datarouter.db.login    = datarouter
 org.onap.dmaap.datarouter.db.password = datarouter
+
+# PROV - DEFAULT ENABLED TLS PROTOCOLS
+org.onap.dmaap.datarouter.provserver.https.include.protocols = TLSv1.1|TLSv1.2
+
+# AAF config
+org.onap.dmaap.datarouter.provserver.cadi.enabled = false
+
+org.onap.dmaap.datarouter.provserver.passwordencryption   = PasswordEncryptionKey#@$%^&1234#
+org.onap.dmaap.datarouter.provserver.aaf.feed.type        = org.onap.dmaap-dr.feed
+org.onap.dmaap.datarouter.provserver.aaf.sub.type         = org.onap.dmaap-dr.sub
+org.onap.dmaap.datarouter.provserver.aaf.instance         = legacy
+org.onap.dmaap.datarouter.provserver.aaf.action.publish   = publish
+org.onap.dmaap.datarouter.provserver.aaf.action.subscribe = subscribe
+
+# AAF URL to connect to AAF server
+org.onap.dmaap.datarouter.provserver.cadi.aaf.url = https://aaf-onap-test.osaaf.org:8095
\ No newline at end of file
index a8f9c56..e2a2bc2 100755 (executable)
  ******************************************************************************/
 package org.onap.dmaap.datarouter.provisioning;
 
-import static org.hamcrest.Matchers.notNullValue;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.argThat;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.jetbrains.annotations.NotNull;
 import org.json.JSONArray;
 import org.json.JSONObject;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.authz.Authorizer;
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;
 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.Mockito.*;
+import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
+
 
 @RunWith(PowerMockRunner.class)
-@SuppressStaticInitializationFor("org.onap.dmaap.datarouter.provisioning.beans.Feed")
 public class DRFeedsServletTest extends DrServletTestBase {
 
     private static DRFeedsServlet drfeedsServlet;
+    private static EntityManagerFactory emf;
+    private static EntityManager em;
+    private DB db;
 
     @Mock
     private HttpServletRequest request;
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
+
+    @BeforeClass
+    public static void init() {
+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");
+        em = emf.createEntityManager();
+        System.setProperty(
+                "org.onap.dmaap.datarouter.provserver.properties",
+                "src/test/resources/h2Database.properties");
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        em.clear();
+        em.close();
+        emf.close();
+    }
 
     @Before
     public void setUp() throws Exception {
-        super.setUp();
         listAppender = setTestLogger(DRFeedsServlet.class);
         drfeedsServlet = new DRFeedsServlet();
+        db = new DB();
         setAuthoriserToReturnRequestIsAuthorized();
         setPokerToNotCreateTimersWhenDeleteFeedIsCalled();
         setupValidAuthorisedRequest();
@@ -137,14 +153,11 @@ public class DRFeedsServletTest extends DrServletTestBase {
     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds_With_Valid_Name_And_Version() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
-        when(request.getParameter("name")).thenReturn("stub_name");
-        when(request.getParameter("version")).thenReturn("stub_version");
-        PowerMockito.mockStatic(Feed.class);
-        Feed feed = mock(Feed.class);
-        PowerMockito.when(Feed.getFeedByNameVersion(anyString(), anyString())).thenReturn(feed);
-        when(feed.asJSONObject(true)).thenReturn(mock(JSONObject.class));
+        when(request.getParameter("name")).thenReturn("Feed1");
+        when(request.getParameter("version")).thenReturn("v0.1");
         drfeedsServlet.doGet(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_OK));
+        verify(response).setContentType(BaseServlet.FEEDFULL_CONTENT_TYPE);
         verifyEnteringExitCalled(listAppender);
     }
 
@@ -205,54 +218,70 @@ public class DRFeedsServletTest extends DrServletTestBase {
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
+    public void Given_Request_Is_HTTP_POST_And_CadiEnabled_Is_True_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
         throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
+        JSONObject JSObject = buildRequestJsonObject();
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "legacy");
+                return jo;
+            }
+        };
         drfeedsServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
-        throws Exception {
-        drfeedsServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
-    }
-
-    @Test
-    public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated()
-        throws Exception {
-        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxFeeds", 0, true);
+    public void Given_Request_Is_HTTP_POST_And_CadiEnabled_Is_False_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
+            throws Exception {
+        setAuthoriserToReturnRequestNotAuthorized();
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "false", true);
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
+        JSONObject JSObject = buildRequestJsonObject();
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
-                return new JSONObject();
+                JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "legacy");
+                return jo;
             }
         };
         drfeedsServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Feed_Is_Not_Valid_Object_Bad_Request_Response_Is_Generated()
-        throws Exception {
-        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
+    public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_True_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
         JSONObject JSObject = buildRequestJsonObject();
-
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
                 return jo;
             }
         };
-
         drfeedsServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Invalid request exclude_AAF"));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Feed_Already_Exists_Bad_Request_Response_Is_Generated()
-        throws Exception {
-        setFeedToReturnInvalidFeedIdSupplied();
+    public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_False_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
         JSONObject JSObject = buildRequestJsonObject();
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -260,59 +289,119 @@ public class DRFeedsServletTest extends DrServletTestBase {
                 jo.put("name", "not_stub_name");
                 jo.put("version", "1.0");
                 jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
                 return jo;
             }
         };
         drfeedsServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
+    public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_False_With_Permissions_Then_Created_OK_Response_Is_Generated() throws Exception {
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
         JSONObject JSObject = buildRequestJsonObject();
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|create")).thenReturn(true);
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "stub_name");
-                jo.put("version", "2.0");
+                jo.put("name", "not_stub_name");
+                jo.put("version", "1.0");
                 jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
                 return jo;
             }
 
             @Override
             protected boolean doInsert(Insertable bean) {
-                return false;
+                return true;
             }
         };
         drfeedsServlet.doPost(request, response);
-        verify(response)
-            .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
+        verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
+        verifyEnteringExitCalled(listAppender);
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
+        throws Exception {
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+    }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Change_On_Feeds_Succeeds_A_STATUS_OK_Response_Is_Generated()
+    public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated()
         throws Exception {
-        ServletOutputStream outStream = mock(ServletOutputStream.class);
-        when(response.getOutputStream()).thenReturn(outStream);
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxFeeds", 0, true);
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                return new JSONObject();
+            }
+        };
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Feed_Is_Not_Valid_Object_Bad_Request_Response_Is_Generated()
+        throws Exception {
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                return new JSONObject();
+            }
+        };
+
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Feed_Already_Exists_Bad_Request_Response_Is_Generated()
+        throws Exception {
+        when(request.getParameter("name")).thenReturn("AafFeed");
+        when(request.getParameter("version")).thenReturn("v0.1");
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|create")).thenReturn(true);
         JSONObject JSObject = buildRequestJsonObject();
+        DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.1");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
+                return jo;
+            }
+        };
+        drfeedsServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("This feed already exists in the database"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
+        JSONObject JSObject = buildRequestJsonObject();
+        when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
                 jo.put("name", "stub_name");
-                jo.put("version", "1.0");
+                jo.put("version", "2.0");
                 jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "legacy");
                 return jo;
             }
 
             @Override
             protected boolean doInsert(Insertable bean) {
-                return true;
+                return false;
             }
         };
         drfeedsServlet.doPost(request, response);
-        verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
-        verifyEnteringExitCalled(listAppender);
+        verify(response)
+            .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
     }
 
     @NotNull
@@ -335,7 +424,7 @@ public class DRFeedsServletTest extends DrServletTestBase {
 
     private void setUpValidSecurityOnHttpRequest() throws Exception {
         when(request.isSecure()).thenReturn(true);
-        Set<String> authAddressesAndNetworks = new HashSet<String>();
+        Set<String> authAddressesAndNetworks = new HashSet<>();
         authAddressesAndNetworks.add(("127.0.0.1"));
         FieldUtils
             .writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,
@@ -348,29 +437,6 @@ public class DRFeedsServletTest extends DrServletTestBase {
         when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
     }
 
-    private void setValidPathInfoInHttpHeader() {
-        when(request.getPathInfo()).thenReturn("/123");
-    }
-
-    private void setFeedToReturnInvalidFeedIdSupplied() {
-        PowerMockito.mockStatic(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(null);
-        when(Feed.getFeedByNameVersion(anyString(), anyString())).thenReturn(mock(Feed.class));
-    }
-
-    private void setFeedToReturnValidFeedForSuppliedId() {
-        PowerMockito.mockStatic(Feed.class);
-        Feed feed = mock(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(feed);
-        when(feed.isDeleted()).thenReturn(false);
-        when(feed.asJSONObject(true)).thenReturn(mock(JSONObject.class));
-        when(feed.getPublisher()).thenReturn("Stub_Value");
-        when(feed.getName()).thenReturn("stub_name");
-        when(feed.getVersion()).thenReturn("1.0");
-        when(feed.asLimitedJSONObject()).thenReturn(mock(JSONObject.class));
-        PowerMockito.when(feed.getFeedByNameVersion(anyString(), anyString())).thenReturn(null);
-    }
-
     private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
         AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
         Authorizer authorizer = mock(Authorizer.class);
@@ -395,13 +461,10 @@ public class DRFeedsServletTest extends DrServletTestBase {
     private void setupValidAuthorisedRequest() throws Exception {
         setUpValidSecurityOnHttpRequest();
         setBehalfHeader("Stub_Value");
-        setValidPathInfoInHttpHeader();
-        setFeedToReturnValidFeedForSuppliedId();
     }
 
-    private void setUpValidContentHeadersAndJSONOnHttpRequest() {
+    private void setUpValidContentHeadersAndJSONOnHttpRequest() throws IllegalAccessException {
         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.0");
         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
-
     }
 }
index 265a2ee..bad6e2c 100644 (file)
@@ -28,17 +28,11 @@ import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.Before;
 import org.onap.dmaap.datarouter.provisioning.utils.DB;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
 import java.util.Properties;
-import java.util.Scanner;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
@@ -46,7 +40,6 @@ import static org.mockito.Mockito.when;
 
 public class DrServletTestBase {
 
-
     @Before
     public void setUp() throws Exception {
         Properties props = new Properties();
@@ -61,7 +54,7 @@ public class DrServletTestBase {
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "synctask", synchronizerTask, true);
     }
 
-    public ListAppender<ILoggingEvent> setTestLogger(Class c) {
+    ListAppender<ILoggingEvent> setTestLogger(Class c) {
         Logger logger = (Logger) LoggerFactory.getLogger(c);
         ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
         listAppender.start();
@@ -69,7 +62,7 @@ public class DrServletTestBase {
         return listAppender;
     }
 
-    public void verifyEnteringExitCalled(ListAppender<ILoggingEvent> listAppender) {
+    void verifyEnteringExitCalled(ListAppender<ILoggingEvent> listAppender) {
         assertEquals("EELF0004I  Entering data router provisioning component with RequestId and InvocationId", listAppender.list.get(0).getMessage());
         assertEquals("EELF0005I  Exiting data router provisioning component with RequestId and InvocationId", listAppender.list.get(2).getMessage());
         assertEquals(3, listAppender.list.size());
index f042e11..f4eac05 100755 (executable)
@@ -71,7 +71,7 @@ public class FeedServletTest extends DrServletTestBase {
     private static EntityManager em;
     private DB db;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
 
     @BeforeClass
     public static void init() {
@@ -120,8 +120,7 @@ public class FeedServletTest extends DrServletTestBase {
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated() throws Exception {
         when(request.getPathInfo()).thenReturn(null);
         feedServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
@@ -129,8 +128,7 @@ public class FeedServletTest extends DrServletTestBase {
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
         when(request.getPathInfo()).thenReturn("/123");
         feedServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
@@ -138,13 +136,28 @@ public class FeedServletTest extends DrServletTestBase {
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
         feedServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        feedServlet.doDelete(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_With_Permissions_Then_A_NO_CONTENT_Response_Is_Generated() {
+        when(request.getPathInfo()).thenReturn("/3");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|delete")).thenReturn(true);
+        feedServlet.doDelete(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
+        verifyEnteringExitCalled(listAppender);
+    }
+
 
     @Test
     public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Fails_An_Internal_Server_Error_Is_Reported()
@@ -161,8 +174,7 @@ public class FeedServletTest extends DrServletTestBase {
 
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated()
-        throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
         feedServlet.doDelete(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
         reinsertFeedIntoDb();
@@ -209,6 +221,7 @@ public class FeedServletTest extends DrServletTestBase {
     public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
         throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/2");
         feedServlet.doGet(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
@@ -218,6 +231,7 @@ public class FeedServletTest extends DrServletTestBase {
     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
         feedServlet.doGet(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_OK));
         verifyEnteringExitCalled(listAppender);
@@ -264,9 +278,9 @@ public class FeedServletTest extends DrServletTestBase {
         throws Exception {
         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed-fail; version=2.0");
         when(request.getContentType()).thenReturn("stub_contentType");
+        when(request.getPathInfo()).thenReturn("/2");
         feedServlet.doPut(request, response);
-        verify(response)
-            .sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
     }
 
     @Test
@@ -274,12 +288,19 @@ public class FeedServletTest extends DrServletTestBase {
         throws Exception {
         ServletInputStream inStream = mock(ServletInputStream.class);
         when(request.getInputStream()).thenReturn(inStream);
+        when(request.getPathInfo()).thenReturn("/2");
+        FeedServlet feedServlet = new FeedServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                return null;
+            }
+        };
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("Badly formed JSON"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Invalid_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 return new JSONObject();
@@ -292,6 +313,7 @@ public class FeedServletTest extends DrServletTestBase {
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Feed_Change_Is_Not_Publisher_Who_Requested_Feed_Bad_Request_Response_Is_Generated() throws Exception {
         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -302,13 +324,13 @@ public class FeedServletTest extends DrServletTestBase {
                 return jo;
             }
         };
-
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("must be modified by the same publisher"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Feed_Name_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -320,52 +342,99 @@ public class FeedServletTest extends DrServletTestBase {
             }
         };
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("name of the feed may not be updated"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Feed_Version_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "stub_name");
-                jo.put("version", "2.0");
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.2");
                 jo.put("authorization", JSObject);
                 return jo;
             }
         };
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("version of the feed may not be updated"));
     }
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
+        setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "Feed1");
+                jo.put("name", "AafFeed");
                 jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
                 return jo;
             }
         };
-        setAuthoriserToReturnRequestNotAuthorized();
         feedServlet.doPut(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access"));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Fails_An_Internal_Server_Error_Response_Is_Generated() throws Exception {
+    public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        JSONObject JSObject = buildRequestJsonObject();
+        FeedServlet feedServlet = new FeedServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.1");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
+                return jo;
+            }
+        };
+        feedServlet.doPut(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_With_Permissions_Then_STATUS_OK__Response_Is_Generated() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|edit")).thenReturn(true);
+        JSONObject JSObject = buildRequestJsonObject();
+        FeedServlet feedServlet = new FeedServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "AafFeed");
+                jo.put("version", "v0.1");
+                jo.put("authorization", JSObject);
+                jo.put("aaf_instance", "*");
+                return jo;
+            }
+            @Override
+            protected boolean doUpdate(Updateable bean) {
+                return true;
+            }
+
+        };
+        feedServlet.doPut(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_OK));
+        verifyEnteringExitCalled(listAppender);
+    }
 
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Fails_An_Internal_Server_Error_Response_Is_Generated() throws Exception {
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "Feed1");
+                jo.put("name", "AafFeed");
                 jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
                 return jo;
@@ -384,15 +453,20 @@ public class FeedServletTest extends DrServletTestBase {
     public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Suceeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
         JSONObject JSObject = buildRequestJsonObject();
         FeedServlet feedServlet = new FeedServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
                 JSONObject jo = new JSONObject();
-                jo.put("name", "Feed1");
+                jo.put("name", "AafFeed");
                 jo.put("version", "v0.1");
                 jo.put("authorization", JSObject);
                 return jo;
             }
+            @Override
+            protected boolean doUpdate(Updateable bean) {
+                return true;
+            }
 
         };
         feedServlet.doPut(request, response);
@@ -427,11 +501,9 @@ public class FeedServletTest extends DrServletTestBase {
 
     private void setUpValidSecurityOnHttpRequest() throws Exception {
         when(request.isSecure()).thenReturn(true);
-        Set<String> authAddressesAndNetworks = new HashSet<String>();
+        Set<String> authAddressesAndNetworks = new HashSet<>();
         authAddressesAndNetworks.add(("127.0.0.1"));
-        FieldUtils
-            .writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,
-                true);
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,true);
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
     }
 
index 0b5c23f..b867c67 100755 (executable)
@@ -27,19 +27,24 @@ import ch.qos.logback.core.read.ListAppender;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.jetbrains.annotations.NotNull;
 import org.json.JSONObject;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.authz.Authorizer;
-import org.onap.dmaap.datarouter.provisioning.beans.Feed;
 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
 import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -54,20 +59,39 @@ import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
 
 
 @RunWith(PowerMockRunner.class)
-@SuppressStaticInitializationFor({"org.onap.dmaap.datarouter.provisioning.beans.Feed", "org.onap.dmaap.datarouter.provisioning.beans.Subscription"})
+@PrepareForTest(Subscription.class)
 public class SubscribeServletTest extends DrServletTestBase {
     private static SubscribeServlet subscribeServlet;
+    private static EntityManagerFactory emf;
+    private static EntityManager em;
+    private DB db;
 
     @Mock
     private HttpServletRequest request;
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
+
+    @BeforeClass
+    public static void init() {
+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");
+        em = emf.createEntityManager();
+        System.setProperty(
+                "org.onap.dmaap.datarouter.provserver.properties",
+                "src/test/resources/h2Database.properties");
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        em.clear();
+        em.close();
+        emf.close();
+    }
 
     @Before
     public void setUp() throws Exception {
-        super.setUp();
+        db = new DB();
         listAppender = setTestLogger(SubscribeServlet.class);
         subscribeServlet = new SubscribeServlet();
         setAuthoriserToReturnRequestIsAuthorized();
@@ -110,26 +134,18 @@ public class SubscribeServletTest extends DrServletTestBase {
 
     @Test
     public void Given_Request_Is_HTTP_GET_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        setFeedToReturnInvalidFeedIdSupplied();
+        when(request.getPathInfo()).thenReturn("/123");
         subscribeServlet.doGet(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
 
-
-    @Test
-    public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
-        setAuthoriserToReturnRequestNotAuthorized();
-        subscribeServlet.doGet(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
-    }
-
-
     @Test
     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
         ServletOutputStream outStream = mock(ServletOutputStream.class);
         when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/1");
         PowerMockito.mockStatic(Subscription.class);
-        List<String> list = new ArrayList<String>();
+        List<String> list = new ArrayList<>();
         list.add("{}");
         PowerMockito.when(Subscription.getSubscriptionUrlList(anyInt())).thenReturn(list);
         subscribeServlet.doGet(request, response);
@@ -171,7 +187,7 @@ public class SubscribeServletTest extends DrServletTestBase {
 
     @Test
     public void Given_Request_Is_HTTP_POST_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        setFeedToReturnInvalidFeedIdSupplied();
+        when(request.getPathInfo()).thenReturn("/123");
         subscribeServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -179,41 +195,107 @@ public class SubscribeServletTest extends DrServletTestBase {
     @Test
     public void Given_Request_Is_HTTP_POST_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/1");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("sync", false);
+                return jo;
+            }
+            @Override
+            protected boolean doInsert(Insertable bean) {
+                return false;
+            }
+        };
         subscribeServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
-        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.1");
-        when(request.getContentType()).thenReturn("stub_contentType");
+    public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_Legacy_Feed_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/1");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
+            }
+            @Override
+            protected boolean doInsert(Insertable bean) {
+                return false;
+            }
+        };
         subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF Subscriber can not be added to legacy Feed"));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
+    public void Given_Request_Is_HTTP_POST_And_Legacy_Subscriber_Added_To_AAF_Feed_And_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
+        setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getPathInfo()).thenReturn("/2");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
+            }
+        };
         subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access."));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated() throws Exception {
-        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxSubs", 0, true);
+    public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
+        JSONObject JSObject = buildRequestJsonObject();
         SubscribeServlet subscribeServlet = new SubscribeServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
-                return new JSONObject();
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
+                return jo;
             }
         };
         subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
     }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
+    public void Given_Request_Is_HTTP_POST_And_AAF_Subscriber_Added_To_AAF_Feed_With_Permissions_Then_OK_Response_Is_Generated() throws Exception {
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getPathInfo()).thenReturn("/2");
+        when(request.isUserInRole("org.onap.dmaap-dr.feed|*|approveSub")).thenReturn(true);
         PowerMockito.mockStatic(Subscription.class);
-        PowerMockito.when(Subscription.getSubscriptionMatching(mock(Subscription.class))).thenReturn(null);
-        PowerMockito.when(Subscription.countActiveSubscriptions()).thenReturn(0);
+        PowerMockito.when(Subscription.getSubscriptionMatching(new Subscription())).thenReturn(null);
         JSONObject JSObject = buildRequestJsonObject();
         SubscribeServlet subscribeServlet = new SubscribeServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -223,26 +305,56 @@ public class SubscribeServletTest extends DrServletTestBase {
                 jo.put("metadataOnly", true);
                 jo.put("suspend", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
                 jo.put("sync", false);
                 return jo;
             }
 
             @Override
             protected boolean doInsert(Insertable bean) {
-                return false;
+                return true;
             }
         };
         subscribeServlet.doPost(request, response);
-        verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
+        verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
+        verifyEnteringExitCalled(listAppender);
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.1");
+        when(request.getContentType()).thenReturn("stub_contentType");
+        when(request.getPathInfo()).thenReturn("/1");
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
+    }
 
     @Test
-    public void Given_Request_Is_HTTP_POST_And_Change_On_Feeds_Succeeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
-        ServletOutputStream outStream = mock(ServletOutputStream.class);
-        when(response.getOutputStream()).thenReturn(outStream);
+    public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/1");
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated() throws Exception {
+        FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxSubs", 0, true);
+        when(request.getPathInfo()).thenReturn("/1");
+        SubscribeServlet subscribeServlet = new SubscribeServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                return new JSONObject();
+            }
+        };
+        subscribeServlet.doPost(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
+        when(request.getPathInfo()).thenReturn("/2");
         PowerMockito.mockStatic(Subscription.class);
-        PowerMockito.when(Subscription.getSubscriptionMatching(mock(Subscription.class))).thenReturn(null);
+        PowerMockito.when(Subscription.getSubscriptionMatching(new Subscription())).thenReturn(null);
         JSONObject JSObject = buildRequestJsonObject();
         SubscribeServlet subscribeServlet = new SubscribeServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -252,21 +364,21 @@ public class SubscribeServletTest extends DrServletTestBase {
                 jo.put("metadataOnly", true);
                 jo.put("suspend", true);
                 jo.put("delivery", JSObject);
-                jo.put("sync", true);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
+                jo.put("sync", false);
                 return jo;
             }
 
             @Override
             protected boolean doInsert(Insertable bean) {
-                return true;
+                return false;
             }
         };
         subscribeServlet.doPost(request, response);
-        verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
-        verifyEnteringExitCalled(listAppender);
+        verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
     }
 
-
     @NotNull
     private JSONObject buildRequestJsonObject() {
         JSONObject JSObject = new JSONObject();
@@ -279,7 +391,7 @@ public class SubscribeServletTest extends DrServletTestBase {
 
     private void setUpValidSecurityOnHttpRequest() throws Exception {
         when(request.isSecure()).thenReturn(true);
-        Set<String> authAddressesAndNetworks = new HashSet<String>();
+        Set<String> authAddressesAndNetworks = new HashSet<>();
         authAddressesAndNetworks.add(("127.0.0.1"));
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks, true);
         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
@@ -290,27 +402,6 @@ public class SubscribeServletTest extends DrServletTestBase {
         when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
     }
 
-    private void setValidPathInfoInHttpHeader() {
-        when(request.getPathInfo()).thenReturn("/123");
-    }
-
-    private void setFeedToReturnInvalidFeedIdSupplied() {
-        PowerMockito.mockStatic(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(null);
-    }
-
-    private void setFeedToReturnValidFeedForSuppliedId() {
-        PowerMockito.mockStatic(Feed.class);
-        Feed feed = mock(Feed.class);
-        PowerMockito.when(Feed.getFeedById(anyInt())).thenReturn(feed);
-        when(feed.isDeleted()).thenReturn(false);
-        when(feed.asJSONObject(true)).thenReturn(mock(JSONObject.class));
-        when(feed.getPublisher()).thenReturn("Stub_Value");
-        when(feed.getName()).thenReturn("stub_name");
-        when(feed.getVersion()).thenReturn("1.0");
-        when(feed.asLimitedJSONObject()).thenReturn(mock(JSONObject.class));
-    }
-
     private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
         AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
         Authorizer authorizer = mock(Authorizer.class);
@@ -335,8 +426,6 @@ public class SubscribeServletTest extends DrServletTestBase {
     private void setupValidAuthorisedRequest() throws Exception {
         setUpValidSecurityOnHttpRequest();
         setBehalfHeader("Stub_Value");
-        setValidPathInfoInHttpHeader();
-        setFeedToReturnValidFeedForSuppliedId();
     }
 
     private void setUpValidContentHeadersAndJSONOnHttpRequest() {
index aede69c..a17e23e 100755 (executable)
@@ -27,7 +27,10 @@ import ch.qos.logback.core.read.ListAppender;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.jetbrains.annotations.NotNull;
 import org.json.JSONObject;
-import org.junit.*;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
@@ -37,6 +40,9 @@ import org.onap.dmaap.datarouter.provisioning.beans.SubDelivery;
 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
 import org.onap.dmaap.datarouter.provisioning.utils.DB;
+import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
 import javax.persistence.EntityManager;
@@ -46,7 +52,6 @@ import javax.servlet.ServletInputStream;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.FileNotFoundException;
 import java.sql.SQLException;
 import java.util.HashSet;
 import java.util.Set;
@@ -57,6 +62,7 @@ import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
 
 
 @RunWith(PowerMockRunner.class)
+@PrepareForTest(PasswordProcessor.class)
 public class SubscriptionServletTest extends DrServletTestBase {
     private static EntityManagerFactory emf;
     private static EntityManager em;
@@ -72,7 +78,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
     @Mock
     private HttpServletResponse response;
 
-    ListAppender<ILoggingEvent> listAppender;
+    private ListAppender<ILoggingEvent> listAppender;
 
     @BeforeClass
     public static void init() {
@@ -84,7 +90,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
     }
 
     @AfterClass
-    public static void tearDownClass() throws FileNotFoundException {
+    public static void tearDownClass() {
         em.clear();
         em.close();
         emf.close();
@@ -125,7 +131,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
 
     @Test
     public void Given_Request_Is_HTTP_DELETE_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doDelete(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -149,11 +155,22 @@ public class SubscriptionServletTest extends DrServletTestBase {
     }
 
     @Test
-    public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_CADI_Is_Enabled_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/2");
+        subscriptionServlet.doDelete(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_DELETE_And_AAF_CADI_Is_Enabled_With_Permissions_Then_A_NO_CONTENT_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/2");
+        when(request.isUserInRole("org.onap.dmaap-dr.sub|*|delete")).thenReturn(true);
         subscriptionServlet.doDelete(request, response);
         verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
         verifyEnteringExitCalled(listAppender);
-        insertSubscriptionIntoDb();
+        resetAafSubscriptionInDB();
     }
 
     @Test
@@ -180,7 +197,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
 
     @Test
     public void Given_Request_Is_HTTP_GET_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doGet(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -225,7 +242,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
 
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doPut(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
     }
@@ -233,10 +250,82 @@ public class SubscriptionServletTest extends DrServletTestBase {
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
         setAuthoriserToReturnRequestNotAuthorized();
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
+                jo.put("decompress", true);
+                jo.put("sync", true);
+                jo.put("changeowner", true);
+                return jo;
+            }
+        };
         subscriptionServlet.doPut(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
     }
 
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_CADI_Is_Enabled_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/3");
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", true);
+                jo.put("changeowner", true);
+                return jo;
+            }
+        };
+        subscriptionServlet.doPut(request, response);
+        verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access"));
+    }
+
+    @Test
+    public void Given_Request_Is_HTTP_PUT_And_AAF_CADI_Is_Enabled_With_Permissions_Then_OK_Response_Is_Generated() throws Exception {
+        ServletOutputStream outStream = mock(ServletOutputStream.class);
+        when(response.getOutputStream()).thenReturn(outStream);
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
+        when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        when(request.getPathInfo()).thenReturn("/3");
+        when(request.isUserInRole("org.onap.dmaap-dr.sub|*|edit")).thenReturn(true);
+        PowerMockito.mockStatic(PasswordProcessor.class);
+        JSONObject JSObject = buildRequestJsonObject();
+        SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
+            protected JSONObject getJSONfromInput(HttpServletRequest req) {
+                JSONObject jo = new JSONObject();
+                jo.put("name", "stub_name");
+                jo.put("version", "2.0");
+                jo.put("metadataOnly", true);
+                jo.put("suspend", true);
+                jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "*");
+                jo.put("follow_redirect", false);
+                jo.put("sync", true);
+                return jo;
+            }
+        };
+        subscriptionServlet.doPut(request, response);
+        verify(response).setStatus(eq(HttpServletResponse.SC_OK));
+        resetAafSubscriptionInDB();
+        verifyEnteringExitCalled(listAppender);
+    }
+
     @Test
     public void Given_Request_Is_HTTP_PUT_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated() throws Exception {
         when(request.getContentType()).thenReturn("stub_ContentType");
@@ -281,6 +370,8 @@ public class SubscriptionServletTest extends DrServletTestBase {
                 jo.put("privilegedSubscriber", true);
                 jo.put("decompress", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
                 jo.put("subscriber", "differentSubscriber");
                 jo.put("sync", true);
                 return jo;
@@ -304,7 +395,9 @@ public class SubscriptionServletTest extends DrServletTestBase {
                 jo.put("suspend", true);
                 jo.put("privilegedSubscriber", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
                 jo.put("decompress", true);
+                jo.put("follow_redirect", false);
                 jo.put("sync", true);
                 return jo;
             }
@@ -324,6 +417,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
         when(response.getOutputStream()).thenReturn(outStream);
         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.subscription; version=1.0");
+        PowerMockito.mockStatic(PasswordProcessor.class);
         JSONObject JSObject = buildRequestJsonObject();
         SubscriptionServlet subscriptionServlet = new SubscriptionServlet() {
             protected JSONObject getJSONfromInput(HttpServletRequest req) {
@@ -335,6 +429,8 @@ public class SubscriptionServletTest extends DrServletTestBase {
                 jo.put("privilegedSubscriber", true);
                 jo.put("decompress", true);
                 jo.put("delivery", JSObject);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
                 jo.put("sync", true);
                 jo.put("changeowner", true);
                 return jo;
@@ -370,7 +466,7 @@ public class SubscriptionServletTest extends DrServletTestBase {
 
     @Test
     public void Given_Request_Is_HTTP_POST_And_Subscription_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
-        when(request.getPathInfo()).thenReturn("/3");
+        when(request.getPathInfo()).thenReturn("/123");
         subscriptionServlet.doPost(request, response);
         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
     }
@@ -435,6 +531,8 @@ public class SubscriptionServletTest extends DrServletTestBase {
                 jo.put("suspend", true);
                 jo.put("delivery", JSObject);
                 jo.put("privilegedSubscriber", false);
+                jo.put("aaf_instance", "legacy");
+                jo.put("follow_redirect", false);
                 jo.put("decompress", false);
                 jo.put("failed", false);
                 return jo;
@@ -498,8 +596,8 @@ public class SubscriptionServletTest extends DrServletTestBase {
         setValidPathInfoInHttpHeader();
     }
 
-    private void insertSubscriptionIntoDb() throws SQLException {
-        Subscription subscription = new Subscription(URL, USER, PASSWORD);
+    private void changeSubscriptionBackToNormal() throws SQLException {
+        Subscription subscription = new Subscription("https://172.100.0.5", "user1", "password1");
         subscription.setSubid(1);
         subscription.setSubscriber("user1");
         subscription.setFeedid(1);
@@ -510,22 +608,23 @@ public class SubscriptionServletTest extends DrServletTestBase {
         subscription.setSuspended(false);
         subscription.setPrivilegedSubscriber(false);
         subscription.setDecompress(false);
-        subscription.doInsert(db.getConnection());
+        subscription.changeOwnerShip();
+        subscription.doUpdate(db.getConnection());
     }
 
-    private void changeSubscriptionBackToNormal() throws SQLException {
-        Subscription subscription = new Subscription("https://172.100.0.5", "user1", "password1");
-        subscription.setSubid(1);
-        subscription.setSubscriber("user1");
+    private void resetAafSubscriptionInDB() throws SQLException {
+        Subscription subscription = new Subscription("https://172.100.0.5:8080", "user2", "password2");
+        subscription.setSubid(2);
+        subscription.setSubscriber("user2");
         subscription.setFeedid(1);
         SubDelivery subDelivery = new SubDelivery(URL, USER, PASSWORD, true);
         subscription.setDelivery(subDelivery);
         subscription.setGroupid(1);
         subscription.setMetadataOnly(false);
         subscription.setSuspended(false);
-        subscription.setPrivilegedSubscriber(false);
+        subscription.setAafInstance("https://aaf-onap-test.osaaf.org:8095");
         subscription.setDecompress(false);
-        subscription.changeOwnerShip();
+        subscription.setPrivilegedSubscriber(false);
         subscription.doUpdate(db.getConnection());
     }
 }
\ No newline at end of file
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilterTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/DRProvCadiFilterTest.java
new file mode 100644 (file)
index 0000000..5e24c5a
--- /dev/null
@@ -0,0 +1,269 @@
+/**-\r
+ * ============LICENSE_START=======================================================\r
+ *  Copyright (C) 2019 Nordix Foundation.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * SPDX-License-Identifier: Apache-2.0\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.dmaap.datarouter.provisioning.utils;\r
+\r
+import org.junit.Before;\r
+import org.junit.BeforeClass;\r
+import org.junit.Test;\r
+import org.junit.runner.RunWith;\r
+import org.mockito.Mock;\r
+import org.onap.aaf.cadi.PropAccess;\r
+import org.onap.aaf.cadi.filter.CadiFilter;\r
+import org.onap.dmaap.datarouter.provisioning.BaseServlet;\r
+import org.powermock.api.mockito.PowerMockito;\r
+import org.powermock.api.support.membermodification.MemberMatcher;\r
+import org.powermock.core.classloader.annotations.PrepareForTest;\r
+import org.powermock.modules.junit4.PowerMockRunner;\r
+\r
+import javax.persistence.EntityManager;\r
+import javax.persistence.EntityManagerFactory;\r
+import javax.persistence.Persistence;\r
+import javax.servlet.FilterChain;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import static org.hamcrest.Matchers.notNullValue;\r
+import static org.mockito.Matchers.argThat;\r
+import static org.mockito.Matchers.eq;\r
+import static org.mockito.Mockito.*;\r
+import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;\r
+\r
+@RunWith(PowerMockRunner.class)\r
+@PrepareForTest({CadiFilter.class})\r
+public class DRProvCadiFilterTest {\r
+\r
+    @Mock\r
+    private PropAccess access;\r
+\r
+    @Mock\r
+    private HttpServletRequest request;\r
+\r
+    @Mock\r
+    private HttpServletResponse response;\r
+\r
+    @Mock\r
+    private FilterChain chain;\r
+\r
+    private DRProvCadiFilter cadiFilter;\r
+\r
+\r
+    private static EntityManagerFactory emf;\r
+    private static EntityManager em;\r
+\r
+\r
+    @BeforeClass\r
+    public static void init() {\r
+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");\r
+        em = emf.createEntityManager();\r
+        System.setProperty(\r
+                "org.onap.dmaap.datarouter.provserver.properties",\r
+                "src/test/resources/h2Database.properties");\r
+    }\r
+\r
+    @Before\r
+    public void setUp() throws Exception {\r
+        cadiFilter = new DRProvCadiFilter(false, access);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_Called_And_Path_Contains_subs_And_SubId_Is_Incorrectly_Set_Then_Not_Found_Response_Returned() throws Exception{\r
+        setRequestMocking("PUT", "subs");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_And_Path_Contains_subs_And_Is_AAF_Subscriber_then_call_Super_doFilter() throws Exception{\r
+        setRequestMocking("PUT", "subs");\r
+        when(request.getPathInfo()).thenReturn("/2");\r
+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(0)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_And_Path_Contains_subs_And_Is_Not_AAF_Subscriber_then_call_chain_doFilter() throws Exception{\r
+        setRequestMocking("PUT", "subs");\r
+        when(request.getPathInfo()).thenReturn("/5");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_And_FeedId_Is_Incorrectly_Set_Then_Not_Found_Response_Returned () throws Exception{\r
+        setRequestMocking("PUT", "feeds");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_And_FeedId_Is_Correctly_Set_And_Is_AAF_Feed_Then_Call_Super_doFilter() throws Exception{\r
+        setRequestMocking("PUT", "feeds");\r
+        when(request.getPathInfo()).thenReturn("/2");\r
+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(0)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_And_FeedId_Is_Correctly_Set_And_Is_Not_AAF_Feed_then_call_chain_doFilter() throws Exception{\r
+        setRequestMocking("PUT", "feeds");\r
+        when(request.getPathInfo()).thenReturn("/1");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_Get_Then_call_chain_doFilter() throws Exception{\r
+        setRequestMocking("GET", "feeds");\r
+        when(request.getPathInfo()).thenReturn("/5");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+    }\r
+\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_Then_call_chain_doFilter() throws Exception{\r
+        setRequestMocking("POST", "subscribe");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_FeedId_Is_Incorrectly_Set_Then_Not_Found_Response_Returned() throws Exception{\r
+        setRequestMocking("POST", "subscribe");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Exclude_AAF_Is_NULL_Then_Bad_Request_Response_Returned() throws Exception{\r
+        setRequestMocking("POST", "subscribe");\r
+        when(request.getPathInfo()).thenReturn("/2");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Exclude_AAF_Equals_True_Then_Call_Chain_doFilter() throws Exception{\r
+        setRequestMocking("POST", "subscribe");\r
+        when(request.getPathInfo()).thenReturn("/2");\r
+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("true");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Exclude_AAF_Equals_False_Then_Call_Super_doFilter() throws Exception{\r
+        setRequestMocking("POST", "subscribe");\r
+        when(request.getPathInfo()).thenReturn("/2");\r
+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("false");\r
+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(0)).doFilter(request, response);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Is_Not_AAF_Exclude_AAF_Equals_Then_Call_Chain_doFilter() throws Exception{\r
+        setRequestMocking("POST", "subscribe");\r
+        when(request.getPathInfo()).thenReturn("/5");\r
+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("false");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Path_Not_Includes_subscribe_And_Exclude_AAF_Is_NULL_Then_Bad_Request_Response_Returned() throws Exception{\r
+        setRequestMocking("POST", "other");\r
+        when(request.getPathInfo()).thenReturn("/5");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Path_Not_Includes_subscribe_And_Exclude_AAF_Equals_True_Then_Call_Chain_doFilter() throws Exception{\r
+        setRequestMocking("POST", "other");\r
+        when(request.getPathInfo()).thenReturn("/5");\r
+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("true");\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(1)).doFilter(request, response);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_With_POST_And_Path_Not_Includes_subscribe_And_Exclude_AAF_Equals_False_Then_Call_Super_doFilter() throws Exception{\r
+        setRequestMocking("POST", "other");\r
+        when(request.getPathInfo()).thenReturn("/5");\r
+        when(request.getHeader("X-EXCLUDE-AAF")).thenReturn("false");\r
+        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(CadiFilter.class));\r
+\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(chain, times(0)).doFilter(request, response);\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_Called_And_Path_Contains_subs_And_getSubId_Throws_NumberFormatException_then_Not_Found_response_returned() throws Exception{\r
+            setRequestMocking("PUT", "subs");\r
+            when(request.getPathInfo()).thenReturn("5/");\r
+            cadiFilter.doFilter(request, response, chain);\r
+            verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void Given_doFilter_called_And_FeedId_Throws_Set_Then_Not_Found_Response_Returned () throws Exception{\r
+        setRequestMocking("PUT", "feeds");\r
+        when(request.getPathInfo()).thenReturn("//5");\r
+        cadiFilter.doFilter(request, response, chain);\r
+        verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));\r
+    }\r
+\r
+    private void setRequestMocking(String method, String servletPath)\r
+    {\r
+        when(request.getRemoteAddr()).thenReturn(null);\r
+        when(request.getHeader(BEHALF_HEADER)).thenReturn(null);\r
+        when(request.getAttribute(BaseServlet.CERT_ATTRIBUTE)).thenReturn(null);\r
+        when(request.getMethod()).thenReturn(method);\r
+        when(request.getServletPath()).thenReturn(servletPath);\r
+    }\r
+\r
+    }\r
index 9412adf..1fb30c9 100755 (executable)
@@ -2,7 +2,7 @@ CREATE TABLE FEEDS (
     FEEDID         INT UNSIGNED NOT NULL PRIMARY KEY,
     GROUPID        INT(10) UNSIGNED NOT NULL DEFAULT 0,
     NAME           VARCHAR(255) NOT NULL,
-    VERSION        VARCHAR(20) NOT NULL,
+    VERSION        VARCHAR(20) NULL,
     DESCRIPTION    VARCHAR(1000),
     BUSINESS_DESCRIPTION VARCHAR(1000) DEFAULT NULL,
     AUTH_CLASS     VARCHAR(32) NOT NULL,
@@ -14,13 +14,14 @@ CREATE TABLE FEEDS (
     DELETED        BOOLEAN DEFAULT FALSE,
     LAST_MOD       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED      BOOLEAN DEFAULT FALSE,
-    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    CREATED_DATE   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    AAF_INSTANCE   VARCHAR(256)
 );
 
 CREATE TABLE FEED_ENDPOINT_IDS (
     FEEDID        INT UNSIGNED NOT NULL,
-    USERID        VARCHAR(20) NOT NULL,
-    PASSWORD      VARCHAR(32) NOT NULL
+    USERID        VARCHAR(60) NOT NULL,
+    PASSWORD      VARCHAR(100) NOT NULL
 );
 
 CREATE TABLE FEED_ENDPOINT_ADDRS (
@@ -33,8 +34,9 @@ CREATE TABLE SUBSCRIPTIONS (
     FEEDID                      INT UNSIGNED NOT NULL,
     GROUPID                     INT(10) UNSIGNED NOT NULL DEFAULT 0,
     DELIVERY_URL                VARCHAR(256),
-    DELIVERY_USER               VARCHAR(20),
-    DELIVERY_PASSWORD           VARCHAR(32),
+    FOLLOW_REDIRECTS            TINYINT(1) NOT NULL DEFAULT 0,
+    DELIVERY_USER               VARCHAR(60),
+    DELIVERY_PASSWORD           VARCHAR(100),
     DELIVERY_USE100             BOOLEAN DEFAULT FALSE,
     METADATA_ONLY               BOOLEAN DEFAULT FALSE,
     SUBSCRIBER                  VARCHAR(8) NOT NULL,
@@ -43,8 +45,9 @@ CREATE TABLE SUBSCRIPTIONS (
     LAST_MOD                    TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     SUSPENDED                   BOOLEAN DEFAULT FALSE,
     PRIVILEGED_SUBSCRIBER       BOOLEAN DEFAULT FALSE,
+    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     DECOMPRESS                  BOOLEAN DEFAULT FALSE,
-    CREATED_DATE                TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    AAF_INSTANCE                VARCHAR(256)
 
 );
 
@@ -87,7 +90,7 @@ CREATE TABLE LOG_RECORDS (
 CREATE TABLE INGRESS_ROUTES (
     SEQUENCE  INT UNSIGNED NOT NULL,
     FEEDID    INT UNSIGNED NOT NULL,
-    USERID    VARCHAR(20),
+    USERID    VARCHAR(50),
     SUBNET    VARCHAR(44),
     NODESET   INT UNSIGNED NOT NULL
 );
@@ -136,7 +139,7 @@ INSERT INTO PARAMETERS VALUES
     ('DELIVERY_MAX_RETRY_INTERVAL', '3600'),
     ('DELIVERY_FILE_PROCESS_INTERVAL', '600'),
     ('DELIVERY_RETRY_RATIO', '2'),
-    ('LOGROLL_INTERVAL', '300'),
+    ('LOGROLL_INTERVAL', '30'),
     ('PROV_AUTH_ADDRESSES', 'dmaap-dr-prov|dmaap-dr-node'),
     ('PROV_AUTH_SUBJECTS', ''),
     ('PROV_MAXFEED_COUNT',  '10000'),
@@ -149,11 +152,17 @@ INSERT INTO PARAMETERS VALUES
 INSERT INTO GROUPS(GROUPID, AUTHID, NAME, DESCRIPTION, CLASSIFICATION, MEMBERS)
 VALUES (1, 'Basic dXNlcjE6cGFzc3dvcmQx', 'Group1', 'First Group for testing', 'Class1', 'Member1');
 
-INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, DECOMPRESS)
-VALUES (1, 1, 'https://172.100.0.5:8080', 'user1', 'password1', true, false, 'user1', false, 1, false, false);
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, FOLLOW_REDIRECTS, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, PRIVILEGED_SUBSCRIBER, AAF_INSTANCE, DECOMPRESS)
+VALUES (1, 1, 'https://172.100.0.5:8080', 0, 'user1', 'password1', true, false, 'user1', false, 1, false, 'legacy', false);
 
-INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, SUBSCRIBER, SELF_LINK, LOG_LINK)
-VALUES (23, 1, 'http://delivery_url', 'user1', 'somepassword', 'sub123', 'selflink', 'loglink');
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, FOLLOW_REDIRECTS, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, AAF_INSTANCE)
+VALUES (2, 1, 'https://172.100.0.5:8080', 0, 'user2', 'password2', true, true, 'subsc2', false, 1, '*');
+
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, FOLLOW_REDIRECTS, DELIVERY_USER, DELIVERY_PASSWORD, DELIVERY_USE100, METADATA_ONLY, SUBSCRIBER, SUSPENDED, GROUPID, AAF_INSTANCE)
+VALUES (3, 1, 'https://172.100.0.5:8080', 0, 'user3', 'password3', true, true, 'subsc3', false, 1, '*');
+
+INSERT INTO SUBSCRIPTIONS(SUBID, FEEDID, DELIVERY_URL, DELIVERY_USER, DELIVERY_PASSWORD, SUBSCRIBER, SELF_LINK, LOG_LINK, AAF_INSTANCE)
+VALUES (23, 1, 'http://delivery_url', 'user1', 'somepassword', 'sub123', 'selflink', 'loglink', 'legacy');
 
 INSERT INTO FEED_ENDPOINT_IDS(FEEDID, USERID, PASSWORD)
 VALUES (1, 'USER', 'PASSWORD');
@@ -164,6 +173,12 @@ VALUES (1, '172.0.0.1');
 INSERT INTO FEEDS(FEEDID, GROUPID, NAME, VERSION, DESCRIPTION, BUSINESS_DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK)
 VALUES (1, 1,'Feed1','v0.1', 'First Feed for testing', 'First Feed for testing', 'auth_class', 'pub','self_link','publish_link','subscribe_link','log_link');
 
+INSERT INTO FEEDS(FEEDID, GROUPID, NAME, VERSION, DESCRIPTION, BUSINESS_DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, AAF_INSTANCE)
+VALUES (2, 1,'AafFeed','v0.1', 'AAF Feed for testing', 'AAF Feed for testing', 'auth_class', 'pub','self_link','publish_link','subscribe_link','log_link','*');
+
+INSERT INTO FEEDS(FEEDID, GROUPID, NAME, VERSION, DESCRIPTION, BUSINESS_DESCRIPTION, AUTH_CLASS, PUBLISHER, SELF_LINK, PUBLISH_LINK, SUBSCRIBE_LINK, LOG_LINK, AAF_INSTANCE)
+VALUES (3, 1,'DeleteableAafFeed','v0.1', 'AAF Feed3 for testing', 'AAF Feed3 for testing', 'auth_class', 'pub','self_link','publish_link','subscribe_link','log_link','*');
+
 insert into INGRESS_ROUTES(SEQUENCE, FEEDID , USERID, SUBNET, NODESET)
 VALUES (1,1,'user',null,2);
 
index a7ed3fa..fee9c68 100755 (executable)
@@ -28,4 +28,5 @@ org.onap.dmaap.datarouter.provserver.isaddressauthenabled  = true
 org.onap.dmaap.datarouter.provserver.https.relaxation      = false
 org.onap.dmaap.datarouter.provserver.accesslog.dir         = unit-test-logs
 org.onap.dmaap.datarouter.provserver.spooldir              = unit-test-logs/spool
-org.onap.dmaap.datarouter.provserver.localhost             = 127.0.0.1
\ No newline at end of file
+org.onap.dmaap.datarouter.provserver.localhost             = 127.0.0.1
+org.onap.dmaap.datarouter.provserver.passwordencryption    = PasswordEncryptionKey#@$%^&1234#
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index a515dc5..3de167a 100755 (executable)
--- a/pom.xml
+++ b/pom.xml
@@ -55,6 +55,7 @@
         <thoughtworks.version>1.4.10</thoughtworks.version>
         <google.guava.version>26.0-jre</google.guava.version>
         <qos.logback.version>1.2.3</qos.logback.version>
+        <aaf-cadi-aaf.version>2.1.10</aaf-cadi-aaf.version>
         <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
         <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
         <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>