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.client.mdsal;
10 import com.google.common.base.Strings;
11 import java.io.IOException;
12 import java.io.StringReader;
13 import java.security.KeyPair;
14 import java.util.Optional;
15 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
16 import org.opendaylight.aaa.encrypt.PKIUtil;
17 import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
18 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
19 import org.opendaylight.netconf.shaded.sshd.client.future.AuthFuture;
20 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
24 public final class DatastoreBackedPublicKeyAuth extends AuthenticationHandler {
25 private static final Logger LOG = LoggerFactory.getLogger(DatastoreBackedPublicKeyAuth.class);
27 private final String username;
28 private final String pairId;
29 private final CredentialProvider credentialProvider;
30 private final AAAEncryptionService encryptionService;
32 // FIXME: do not use Optional here and deal with atomic set
33 private Optional<KeyPair> keyPair = Optional.empty();
35 public DatastoreBackedPublicKeyAuth(final String username, final String pairId,
36 final CredentialProvider credentialProvider,
37 final AAAEncryptionService encryptionService) {
38 this.username = username;
40 this.credentialProvider = credentialProvider;
41 this.encryptionService = encryptionService;
43 // try to immediately retrieve the pair from the adapter
48 public String getUsername() {
53 public AuthFuture authenticate(final ClientSession session) throws IOException {
54 // if we have keypair set the identity, otherwise retry the retrieval from the adapter
55 // if successful set the identity.
56 if (keyPair.isPresent() || tryToSetKeyPair()) {
57 session.addPublicKeyIdentity(keyPair.orElseThrow());
59 return session.auth();
62 private boolean tryToSetKeyPair() {
63 LOG.debug("Trying to retrieve keypair for: {}", pairId);
64 final var dsKeypair = credentialProvider.credentialForId(pairId);
65 if (dsKeypair == null) {
66 LOG.debug("Unable to retrieve keypair for: {}", pairId);
70 final String passPhrase = Strings.isNullOrEmpty(dsKeypair.getPassphrase()) ? "" : dsKeypair.getPassphrase();
72 keyPair = Optional.of(new PKIUtil().decodePrivateKey(
73 new StringReader(encryptionService.decrypt(dsKeypair.getPrivateKey()).replace("\\n", "\n")),
74 encryptionService.decrypt(passPhrase)));
75 } catch (IOException exception) {
76 LOG.warn("Unable to decode private key, id={}", pairId, exception);