<!-- 
RSS generated by JIRA (8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d) at Wed Feb 07 20:16:43 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>OpenDaylight JIRA</title>
    <link>https://jira.opendaylight.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>8.20.10</version>
        <build-number>820010</build-number>
        <build-date>22-06-2022</build-date>
    </build-info>


<item>
            <title>[NETCONF-1115] Handle unencrypted password in login-password for topology node</title>
                <link>https://jira.opendaylight.org/browse/NETCONF-1115</link>
                <project id="10142" key="NETCONF">netconf</project>
                    <description>&lt;p&gt;&lt;tt&gt;netconf-node-topology:login-password/password&lt;/tt&gt; is supposed to keep the encrypted password of a NETCONF device. However, in some cases a password saved in field may work even if it&apos;s not properly encrypted because &lt;tt&gt;AAAEncryptionService.decrypt&lt;/tt&gt; may return the original password when decryption fails.&lt;/p&gt;

&lt;p&gt;For example, the following request with unencrypted password&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;PUT /rests/data/network-topology:network-topology/topology=topology-netconf/node=netconf-mdsal

{
    &quot;network-topology:node&quot;: [
        {
            &quot;node-id&quot;: &quot;netconf-mdsal&quot;,
            &quot;netconf-node-topology:concurrent-rpc-limit&quot;: 0,
            &quot;netconf-node-topology:schema-cache-directory&quot;: &quot;netconf-mdsal&quot;,
            &quot;netconf-node-topology:login-password&quot;: {
                &quot;username&quot;: &quot;admin&quot;,
                &quot;password&quot;: &quot;adminadmin&quot;
            },
            &quot;netconf-node-topology:default-request-timeout-millis&quot;: 1800000,
            &quot;netconf-node-topology:port&quot;: 2830,
            &quot;netconf-node-topology:tcp-only&quot;: false,
            &quot;netconf-node-topology:host&quot;: &quot;127.0.0.1&quot;,
            &quot;netconf-node-topology:actor-response-wait-time&quot;: 600,
            &quot;netconf-node-topology:keepalive-delay&quot;: 600
        }
    ]
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;makes controller attempt to establish a NETCONF session with &lt;tt&gt;adminadmin&lt;/tt&gt; as the password after failing to decrypt the password:&lt;/p&gt;

&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;02:03:07.828 ERROR [opendaylight-cluster-data-notification-dispatcher-58] Failed to decrypt encoded data
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
	at com.sun.crypto.provider.CipherCore.prepareInputBuffer(CipherCore.java:888) ~[?:?]
	at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:730) ~[?:?]
	at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) ~[?:?]
	at javax.crypto.Cipher.doFinal(Cipher.java:2205) ~[?:?]
	at org.opendaylight.aaa.encrypt.impl.AAAEncryptionServiceImpl.decrypt(AAAEncryptionServiceImpl.java:154) ~[?:?]
	at org.opendaylight.netconf.topology.spi.DefaultNetconfClientConfigurationBuilderFactory.getHandlerFromCredentials(DefaultNetconfClientConfigurationBuilderFactory.java:96) ~[bundleFile:?]
	at org.opendaylight.netconf.topology.spi.DefaultNetconfClientConfigurationBuilderFactory.createClientConfigurationBuilder(DefaultNetconfClientConfigurationBuilderFactory.java:68) ~[bundleFile:?]
	at org.opendaylight.netconf.topology.spi.NetconfNodeHandler.&amp;lt;init&amp;gt;(NetconfNodeHandler.java:143) ~[bundleFile:?]
	at org.opendaylight.netconf.topology.spi.AbstractNetconfTopology.setupConnection(AbstractNetconfTopology.java:142) ~[bundleFile:?]
	at org.opendaylight.netconf.topology.spi.AbstractNetconfTopology.lockedEnsureNode(AbstractNetconfTopology.java:108) ~[bundleFile:?]
	at org.opendaylight.netconf.topology.spi.AbstractNetconfTopology.ensureNode(AbstractNetconfTopology.java:96) ~[bundleFile:?]
	at org.opendaylight.netconf.topology.impl.NetconfTopologyImpl.onDataTreeChanged(NetconfTopologyImpl.java:145) ~[?:?]
	at org.opendaylight.mdsal.binding.dom.adapter.BindingDOMDataTreeChangeListenerAdapter.onDataTreeChanged(BindingDOMDataTreeChangeListenerAdapter.java:44) ~[bundleFile:?]
	at org.opendaylight.controller.cluster.datastore.DataTreeChangeListenerActor.dataTreeChanged(DataTreeChangeListenerActor.java:90) ~[bundleFile:?]
	at org.opendaylight.controller.cluster.datastore.DataTreeChangeListenerActor.handleReceive(DataTreeChangeListenerActor.java:45) ~[bundleFile:?]
	at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:24) ~[bundleFile:?]
	at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:20) ~[bundleFile:?]
	at scala.PartialFunction.applyOrElse(PartialFunction.scala:214) ~[bundleFile:?]
	at scala.PartialFunction.applyOrElse$(PartialFunction.scala:213) ~[bundleFile:?]
	at akka.japi.pf.UnitCaseStatement.applyOrElse(CaseStatements.scala:20) ~[bundleFile:?]
	at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:269) ~[bundleFile:?]
	at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:270) ~[bundleFile:?]
	at akka.actor.Actor.aroundReceive(Actor.scala:537) ~[bundleFile:?]
	at akka.actor.Actor.aroundReceive$(Actor.scala:535) ~[bundleFile:?]
	at akka.actor.AbstractActor.aroundReceive(AbstractActor.scala:220) ~[bundleFile:?]
	at akka.actor.ActorCell.receiveMessage(ActorCell.scala:579) ~[bundleFile:?]
	at akka.actor.ActorCell.invoke(ActorCell.scala:547) ~[bundleFile:?]
	at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:270) ~[bundleFile:?]
	at akka.dispatch.Mailbox.run(Mailbox.scala:231) ~[bundleFile:?]
	at akka.dispatch.Mailbox.exec(Mailbox.scala:243) ~[bundleFile:?]
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[?:?]
	at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[?:?]
	at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[?:?]
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[?:?]
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[?:?]

02:03:07.855 WARN [sshd-NetconfSshClient[2914912]-nio2-thread-3] Server at /127.0.0.1:2830 presented unverified EC key: SHA256:3kA4ClemSJjEhFPu1EdCQnWku+XYuWQi33bFFRK90G8
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case the connection failed because the password is incorrect. But there are many cases where the correct unencrypted password works.&lt;/p&gt;

&lt;p&gt;This behavior encourages keeping unencrypted password in the configuration because it may not discovered or it may be simply ignored because it works. Also, this may cause confusion since some may work but some may not.&lt;/p&gt;

&lt;p&gt;So the device should not be activated when decryption fails to mitigate the issue.&lt;/p&gt;</description>
                <environment></environment>
        <key id="37164">NETCONF-1115</key>
            <summary>Handle unencrypted password in login-password for topology node</summary>
                <type id="10100" iconUrl="https://jira.opendaylight.org/secure/viewavatar?size=xsmall&amp;avatarId=10310&amp;avatarType=issuetype">Improvement</type>
                                            <priority id="3" iconUrl="https://jira.opendaylight.org/images/icons/priorities/major.svg">Medium</priority>
                        <status id="10003" iconUrl="https://jira.opendaylight.org/images/icons/status_generic.gif" description="">Confirmed</status>
                    <statusCategory id="2" key="new" colorName="blue-gray"/>
                                    <resolution id="-1">Unresolved</resolution>
                                        <assignee username="ivanhrasko">Ivan Hrasko</assignee>
                                    <reporter username="sangwookha">Sangwook Ha</reporter>
                        <labels>
                            <label>pt</label>
                    </labels>
                <created>Thu, 3 Aug 2023 01:49:37 +0000</created>
                <updated>Wed, 7 Feb 2024 14:30:37 +0000</updated>
                                                            <fixVersion>7.0.0</fixVersion>
                                    <component>netconf</component>
                        <due></due>
                            <votes>0</votes>
                                    <watches>4</watches>
                                                                                                                <comments>
                            <comment id="72507" author="JIRAUSER13216" created="Tue, 29 Aug 2023 08:55:36 +0000"  >&lt;p&gt;Cause:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;According to &lt;a href=&quot;https://github.com/opendaylight/netconf/blob/3c5e8fedc83a64aafa24bd760bff50e2c9b9fa96/plugins/netconf-client-mdsal/src/main/yang/odl-netconf-device.yang#L28&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;odl-netconf-device&lt;/a&gt; model (used in &lt;a href=&quot;https://github.com/opendaylight/netconf/blob/3c5e8fedc83a64aafa24bd760bff50e2c9b9fa96/apps/netconf-topology/src/main/yang/netconf-node-topology.yang#L8&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;netconf-node-topology-node&lt;/a&gt;) &lt;ins&gt;login-password&lt;/ins&gt; container expected to contain encrypted &lt;ins&gt;password&lt;/ins&gt; value&lt;/li&gt;
	&lt;li&gt;Encrypted value handling is served by &lt;ins&gt;aaa-encrypt-service&lt;/ins&gt; which provides both encryption for persistence and decryption for usage in ssh connection&lt;/li&gt;
	&lt;li&gt;Due to &lt;ins&gt;aaa-encrypt-service&lt;/ins&gt; is an OSGi component with own configuration having no API exposed to end user, the password encryption is performed dynamically on input processing, encrypted value is not expected to be provided by user&lt;/li&gt;
	&lt;li&gt;Dynamic password value encryption is implemented for &lt;a href=&quot;https://github.com/opendaylight/netconf/blob/3c5e8fedc83a64aafa24bd760bff50e2c9b9fa96/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfTopologyRPCProvider.java#L72&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;netconf-node-topology:create-device&lt;/a&gt; RPC processing, but not for direct data insert/update&lt;/li&gt;
	&lt;li&gt;Once node data is updated in configuration datastore the device connection is triggered with assumption password value is properly encrypted&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Non-encrypted password value as a case of incorrect configuration to be handled via &lt;a href=&quot;https://jira.opendaylight.org/browse/NETCONF-1114&quot; title=&quot;Incorrect operational state of device configuration with Invalid encrypted password&quot; class=&quot;issue-link&quot; data-issue-key=&quot;NETCONF-1114&quot;&gt;NETCONF-1114&lt;/a&gt;. The expected resolution is no connection to device performed if configuration processing fails with immediate failure status to be set for device.&lt;/p&gt;

&lt;p&gt;Delegating password value encryption to user requires at least encryption service API exposed so user would have the ability to encrypt the password value by himself with assurance this value will be properly decrypted (because same service will use same parameters). However this approach requires shared component update, which complicates and delays solution delivery.&lt;/p&gt;

&lt;p&gt;The suggested approach is to add dynamic password encryption to direct data update via dedicated&#160;DataTreeChangeListener implementation:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Scope is configuration datastore&lt;/li&gt;
	&lt;li&gt;Monitor nodes having encrypted password values&lt;/li&gt;
	&lt;li&gt;if encrypted password value added/changed check if the &lt;ins&gt;aaa-encrypt-service&lt;/ins&gt; can perform the value decryption&lt;/li&gt;
	&lt;li&gt;if decryption fails assume the value is not encrypted, then encrypt and override it&lt;/li&gt;
&lt;/ul&gt;
</comment>
                            <comment id="72653" author="ivanhrasko" created="Tue, 17 Oct 2023 11:14:11 +0000"  >&lt;p&gt;We are going from different approach:&lt;/p&gt;

&lt;p&gt;Enforce base64 encoding for odl-netconf-device model for of all leafs that are claiming its their type by YANG string type pattern. Analyze RPCs which can be used to create such data, realize that we want to allow user to use plain strings in RPC payloads and adapt payloads YANG definition accordingly.&lt;/p&gt;

&lt;p&gt;If needed to modify odl-netconf-device or netconf-node-topology create new revisions in that case.&lt;/p&gt;</comment>
                            <comment id="72700" author="JIRAUSER13318" created="Thu, 19 Oct 2023 17:16:55 +0000"  >&lt;p&gt;Enforcing base64 encoding will prevent many invalid password values but it&apos;s still possible to pass the pattern checking without being actually base64 encoded.&lt;br/&gt;
Since &lt;a href=&quot;https://github.com/opendaylight/aaa/blob/master/aaa-encrypt-service/impl/src/main/java/org/opendaylight/aaa/encrypt/impl/AAAEncryptionServiceImpl.java#L145&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;AAAEncryptionServiceImpl.decrypt()&lt;/a&gt; returns original value when decryption fails and there is no checking of decryption failure in netconf, many plaintext passwords can be put into the field and successfully used as long as the pattern matches the base64 encode format - e.g. any password composed of alphanumeric characters whose length is multiples of 4.&lt;/p&gt;

&lt;p&gt;It seems problematic that the decrypt function does not have clear API contract that can signal decryption failure, not even documentation, when it&apos;s a public API used by other downstream projects - and also inconsistent in that it catches decryption errors but not that of base64 decoding.&lt;/p&gt;</comment>
                            <comment id="72701" author="petersuna" created="Tue, 24 Oct 2023 09:09:55 +0000"  >&lt;p&gt;I will investigate the potential consequences of AAAEncryptionServiceImpl throwing an exception in case of encryption or decryption failure. IMHO, the primary concept is to delegate the validation of password values to the data store, relieving upper layers of this responsibility.&lt;/p&gt;</comment>
                            <comment id="73009" author="ivanhrasko" created="Fri, 5 Jan 2024 10:09:06 +0000"  >&lt;p&gt;The issue is blocked by &lt;a href=&quot;https://jira.opendaylight.org/browse/NETCONF-1216&quot; title=&quot;Input length must be multiple of 16 when decrypting with padded cipher&quot; class=&quot;issue-link&quot; data-issue-key=&quot;NETCONF-1216&quot;&gt;&lt;del&gt;NETCONF-1216&lt;/del&gt;&lt;/a&gt; and &lt;a href=&quot;https://jira.opendaylight.org/browse/NETCONF-1217&quot; title=&quot;Given final block not properly padded. Such issues can arise if a bad key is used during decryption&quot; class=&quot;issue-link&quot; data-issue-key=&quot;NETCONF-1217&quot;&gt;&lt;del&gt;NETCONF-1217&lt;/del&gt;&lt;/a&gt;. The change type to binary does not solve those as the only way to reliably use encryption service is via RPC. Needs more investigation.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10000">
                    <name>Blocks</name>
                                                                <inwardlinks description="is blocked by">
                                        <issuelink>
            <issuekey id="37805">NETCONF-1216</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="37806">NETCONF-1217</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                            <issuelinktype id="10300">
                    <name>Issue split</name>
                                            <outwardlinks description="split to">
                                        <issuelink>
            <issuekey id="37503">NETCONF-1186</issuekey>
        </issuelink>
                            </outwardlinks>
                                                        </issuelinktype>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="37701">AAA-266</issuekey>
        </issuelink>
                            </outwardlinks>
                                                        </issuelinktype>
                    </issuelinks>
                <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                            <customfield id="customfield_11400" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|i0462n:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                </customfields>
    </item>
</channel>
</rss>