Enforce base64 encoding for netconf-keystore
[netconf.git] / keystore / keystore-legacy / src / main / java / org / opendaylight / netconf / keystore / legacy / impl / ConfigListener.java
1 /*
2  * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.keystore.legacy.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.Stopwatch;
13 import java.util.List;
14 import org.eclipse.jdt.annotation.NonNullByDefault;
15 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
16 import org.opendaylight.mdsal.binding.api.DataTreeModification;
17 import org.opendaylight.netconf.keystore.legacy.impl.DefaultNetconfKeystoreService.ConfigStateBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev231109.Keystore;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev231109._private.keys.PrivateKey;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev231109.keystore.entry.KeyCredential;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev231109.trusted.certificates.TrustedCertificate;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 @NonNullByDefault
26 record ConfigListener(DefaultNetconfKeystoreService keystore) implements DataTreeChangeListener<Keystore> {
27     private static final Logger LOG = LoggerFactory.getLogger(ConfigListener.class);
28
29     ConfigListener {
30         requireNonNull(keystore);
31     }
32
33     @Override
34     public void onInitialData() {
35         keystore.runUpdate(builder -> {
36             builder.privateKeys().clear();
37             builder.trustedCertificates().clear();
38         });
39     }
40
41     @Override
42     public void onDataTreeChanged(final List<DataTreeModification<Keystore>> changes) {
43         LOG.debug("Starting update with {} changes", changes.size());
44         final var sw = Stopwatch.createStarted();
45         keystore.runUpdate(builder -> onDataTreeChanged(builder, changes));
46         LOG.debug("Update finished in {}", sw);
47     }
48
49     private static void onDataTreeChanged(final ConfigStateBuilder builder,
50             final List<DataTreeModification<Keystore>> changes) {
51         for (var change : changes) {
52             LOG.debug("Processing change {}", change);
53             final var rootNode = change.getRootNode();
54
55             for (var mod : rootNode.getModifiedChildren(PrivateKey.class)) {
56                 switch (mod.modificationType()) {
57                     case SUBTREE_MODIFIED, WRITE -> {
58                         final var privateKey = mod.dataAfter();
59                         builder.privateKeys().put(privateKey.requireName(), privateKey);
60                     }
61                     case DELETE -> builder.privateKeys().remove(mod.dataBefore().requireName());
62                     default -> {
63                         // no-op
64                     }
65                 }
66             }
67             for (var mod : rootNode.getModifiedChildren(TrustedCertificate.class)) {
68                 switch (mod.modificationType()) {
69                     case SUBTREE_MODIFIED, WRITE -> {
70                         final var trustedCertificate = mod.dataAfter();
71                         builder.trustedCertificates().put(trustedCertificate.requireName(), trustedCertificate);
72                     }
73                     case DELETE -> builder.trustedCertificates().remove(mod.dataBefore().requireName());
74                     default -> {
75                         // no-op
76                     }
77                 }
78             }
79             for (var mod : rootNode.getModifiedChildren(KeyCredential.class)) {
80                 switch (mod.modificationType()) {
81                     case SUBTREE_MODIFIED, WRITE -> {
82                         final var keyCredential = mod.dataAfter();
83                         builder.credentials().put(keyCredential.requireKeyId(), keyCredential);
84                     }
85                     case DELETE -> builder.credentials().remove(mod.dataBefore().requireKeyId());
86                     default -> {
87                         // no-op
88                     }
89                 }
90             }
91         }
92     }
93 }