Adjust to yangtools-2.0.0/odlparent-3.0.0 changes
[netconf.git] / netconf / sal-netconf-connector / src / main / java / org / opendaylight / netconf / sal / connect / netconf / auth / DatastoreBackedPublicKeyAuth.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. 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
9 package org.opendaylight.netconf.sal.connect.netconf.auth;
10
11 import com.google.common.base.Strings;
12 import java.io.IOException;
13 import java.io.StringReader;
14 import java.security.KeyPair;
15 import java.util.Optional;
16 import org.apache.sshd.client.future.AuthFuture;
17 import org.apache.sshd.client.session.ClientSession;
18 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
19 import org.opendaylight.aaa.encrypt.PKIUtil;
20 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
21 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfKeystoreAdapter;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.keystore.entry.KeyCredential;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 public class DatastoreBackedPublicKeyAuth extends AuthenticationHandler {
27
28     private static final Logger LOG = LoggerFactory.getLogger(DatastoreBackedPublicKeyAuth.class);
29
30     private final String username;
31     private final String pairId;
32     private final NetconfKeystoreAdapter keystoreAdapter;
33     private final AAAEncryptionService encryptionService;
34
35     private Optional<KeyPair> keyPair = Optional.empty();
36
37     public DatastoreBackedPublicKeyAuth(final String username, final String pairId,
38                                         final NetconfKeystoreAdapter keystoreAdapter,
39                                         final AAAEncryptionService encryptionService) {
40         this.username = username;
41         this.pairId = pairId;
42         this.keystoreAdapter = keystoreAdapter;
43         this.encryptionService = encryptionService;
44
45         // try to immediately retrieve the pair from the adapter
46         tryToSetKeyPair();
47     }
48
49     @Override
50     public String getUsername() {
51         return username;
52     }
53
54     @Override
55     public AuthFuture authenticate(final ClientSession session) throws IOException {
56         // if we have keypair set the identity, otherwise retry the retrieval from the adapter
57         // if successful set the identity.
58         if (keyPair.isPresent() || tryToSetKeyPair()) {
59             session.addPublicKeyIdentity(keyPair.get());
60         }
61         return session.auth();
62     }
63
64     private boolean tryToSetKeyPair() {
65         LOG.debug("Trying to retrieve keypair for: {}", pairId);
66         final Optional<KeyCredential> keypairOptional = keystoreAdapter.getKeypairFromId(pairId);
67
68         if (keypairOptional.isPresent()) {
69             final KeyCredential dsKeypair = keypairOptional.get();
70             final String passPhrase = Strings.isNullOrEmpty(dsKeypair.getPassphrase()) ? "" : dsKeypair.getPassphrase();
71
72             try {
73                 this.keyPair = Optional.of(
74                         new PKIUtil().decodePrivateKey(
75                                 new StringReader(encryptionService.decrypt(dsKeypair.getPrivateKey())),
76                                 encryptionService.decrypt(passPhrase)));
77             } catch (IOException exception) {
78                 LOG.warn("Unable to decode private key, id={}", pairId, exception);
79                 return false;
80             }
81             return true;
82         }
83         LOG.debug("Unable to retrieve keypair for: {}", pairId);
84         return false;
85     }
86 }