2 * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netconf.sal.connect.util;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import com.google.common.util.concurrent.SettableFuture;
16 import java.util.List;
17 import java.util.stream.Collectors;
18 import javax.annotation.PreDestroy;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
22 import org.opendaylight.mdsal.binding.api.DataBroker;
23 import org.opendaylight.mdsal.binding.api.RpcProviderService;
24 import org.opendaylight.mdsal.binding.api.WriteTransaction;
25 import org.opendaylight.mdsal.common.api.CommitInfo;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddKeystoreEntryInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddKeystoreEntryOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddKeystoreEntryOutputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddPrivateKeyInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddPrivateKeyOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddPrivateKeyOutputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddTrustedCertificateInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddTrustedCertificateOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.AddTrustedCertificateOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.NetconfKeystoreService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveKeystoreEntryInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveKeystoreEntryOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveKeystoreEntryOutputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemovePrivateKeyInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemovePrivateKeyOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemovePrivateKeyOutputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveTrustedCertificateInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveTrustedCertificateOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.RemoveTrustedCertificateOutputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredentialBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredentialKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificate;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateKey;
54 import org.opendaylight.yangtools.concepts.Registration;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
58 import org.osgi.service.component.annotations.Activate;
59 import org.osgi.service.component.annotations.Component;
60 import org.osgi.service.component.annotations.Deactivate;
61 import org.osgi.service.component.annotations.Reference;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
66 @Component(service = { })
67 public final class NetconfSalKeystoreService implements NetconfKeystoreService, AutoCloseable {
68 private static final Logger LOG = LoggerFactory.getLogger(NetconfSalKeystoreService.class);
69 private static final InstanceIdentifier<Keystore> KEYSTORE_IID = InstanceIdentifier.create(Keystore.class);
71 // FIXME: we are populating config datastore, but there may be risks with concurrent access. We really should be
72 // using cluster singleton service here.
73 private final DataBroker dataBroker;
74 private final AAAEncryptionService encryptionService;
75 private final Registration reg;
79 public NetconfSalKeystoreService(@Reference final DataBroker dataBroker,
80 @Reference final AAAEncryptionService encryptionService, @Reference final RpcProviderService rpcProvider) {
81 this.dataBroker = requireNonNull(dataBroker);
82 this.encryptionService = requireNonNull(encryptionService);
84 reg = rpcProvider.registerRpcImplementation(NetconfKeystoreService.class, this);
85 LOG.info("NETCONF keystore service started");
93 LOG.info("NETCONF keystore service stopped");
97 public ListenableFuture<RpcResult<RemoveKeystoreEntryOutput>> removeKeystoreEntry(
98 final RemoveKeystoreEntryInput input) {
99 LOG.debug("Removing keypairs: {}", input);
101 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
103 for (final String id : input.getKeyId()) {
104 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION,
105 KEYSTORE_IID.child(KeyCredential.class, new KeyCredentialKey(id)));
108 final SettableFuture<RpcResult<RemoveKeystoreEntryOutput>> rpcResult = SettableFuture.create();
110 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
112 public void onSuccess(final CommitInfo result) {
113 LOG.debug("remove-key-pair success. Input: {}", input);
114 rpcResult.set(RpcResultBuilder.success(new RemoveKeystoreEntryOutputBuilder().build()).build());
118 public void onFailure(final Throwable throwable) {
119 LOG.warn("remove-key-pair failed. Input: {}", input, throwable);
120 rpcResult.setException(throwable);
122 }, MoreExecutors.directExecutor());
128 public ListenableFuture<RpcResult<AddKeystoreEntryOutput>> addKeystoreEntry(final AddKeystoreEntryInput input) {
129 LOG.debug("Adding keypairs: {}", input);
131 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
132 final List<KeyCredential> keypairs = input.nonnullKeyCredential().values().stream()
133 .map(keypair -> new KeyCredentialBuilder(keypair)
134 .setPrivateKey(encryptionService.encrypt(keypair.getPrivateKey()))
135 .setPassphrase(encryptionService.encrypt(keypair.getPassphrase()))
137 .collect(Collectors.toList());
139 for (KeyCredential keypair : keypairs) {
140 writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
141 KEYSTORE_IID.child(KeyCredential.class, keypair.key()), keypair);
144 final SettableFuture<RpcResult<AddKeystoreEntryOutput>> rpcResult = SettableFuture.create();
146 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
148 public void onSuccess(final CommitInfo result) {
149 LOG.debug("add-key-pair success. Input: {}", input);
150 rpcResult.set(RpcResultBuilder.success(new AddKeystoreEntryOutputBuilder().build()).build());
154 public void onFailure(final Throwable throwable) {
155 LOG.warn("add-key-pair failed. Input: {}", input, throwable);
156 rpcResult.setException(throwable);
158 }, MoreExecutors.directExecutor());
164 public ListenableFuture<RpcResult<AddTrustedCertificateOutput>> addTrustedCertificate(
165 final AddTrustedCertificateInput input) {
166 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
168 for (TrustedCertificate certificate : input.nonnullTrustedCertificate().values()) {
169 writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
170 KEYSTORE_IID.child(TrustedCertificate.class, certificate.key()), certificate);
173 final SettableFuture<RpcResult<AddTrustedCertificateOutput>> rpcResult = SettableFuture.create();
175 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
177 public void onSuccess(final CommitInfo result) {
178 LOG.debug("add-trusted-certificate success. Input: {}", input);
179 rpcResult.set(RpcResultBuilder.success(new AddTrustedCertificateOutputBuilder().build()).build());
183 public void onFailure(final Throwable throwable) {
184 LOG.warn("add-trusted-certificate failed. Input: {}", input, throwable);
185 rpcResult.setException(throwable);
187 }, MoreExecutors.directExecutor());
193 public ListenableFuture<RpcResult<RemoveTrustedCertificateOutput>> removeTrustedCertificate(
194 final RemoveTrustedCertificateInput input) {
195 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
197 for (final String name : input.getName()) {
198 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION,
199 KEYSTORE_IID.child(TrustedCertificate.class, new TrustedCertificateKey(name)));
202 final SettableFuture<RpcResult<RemoveTrustedCertificateOutput>> rpcResult = SettableFuture.create();
204 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
206 public void onSuccess(final CommitInfo result) {
207 LOG.debug("remove-trusted-certificate success. Input: {}", input);
208 rpcResult.set(RpcResultBuilder.success(new RemoveTrustedCertificateOutputBuilder().build()).build());
212 public void onFailure(final Throwable throwable) {
213 LOG.warn("remove-trusted-certificate failed. Input: {}", input, throwable);
214 rpcResult.setException(throwable);
216 }, MoreExecutors.directExecutor());
222 public ListenableFuture<RpcResult<AddPrivateKeyOutput>> addPrivateKey(final AddPrivateKeyInput input) {
223 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
225 for (PrivateKey key: input.nonnullPrivateKey().values()) {
226 writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
227 KEYSTORE_IID.child(PrivateKey.class, key.key()), key);
230 final SettableFuture<RpcResult<AddPrivateKeyOutput>> rpcResult = SettableFuture.create();
232 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
234 public void onSuccess(final CommitInfo result) {
235 LOG.debug("add-private-key success. Input: {}", input);
236 rpcResult.set(RpcResultBuilder.success(new AddPrivateKeyOutputBuilder().build()).build());
240 public void onFailure(final Throwable throwable) {
241 LOG.warn("add-private-key failed. Input: {}", input, throwable);
242 rpcResult.setException(throwable);
244 }, MoreExecutors.directExecutor());
250 public ListenableFuture<RpcResult<RemovePrivateKeyOutput>> removePrivateKey(final RemovePrivateKeyInput input) {
251 final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
253 for (final String name : input.getName()) {
254 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION,
255 KEYSTORE_IID.child(PrivateKey.class, new PrivateKeyKey(name)));
258 final SettableFuture<RpcResult<RemovePrivateKeyOutput>> rpcResult = SettableFuture.create();
260 writeTransaction.commit().addCallback(new FutureCallback<CommitInfo>() {
262 public void onSuccess(final CommitInfo result) {
263 LOG.debug("remove-private-key success. Input: {}", input);
264 rpcResult.set(RpcResultBuilder.success(new RemovePrivateKeyOutputBuilder().build()).build());
268 public void onFailure(final Throwable throwable) {
269 LOG.warn("remove-private-key failed. Input: {}", input, throwable);
270 rpcResult.setException(throwable);
272 }, MoreExecutors.directExecutor());