aboutsummaryrefslogtreecommitdiffstats
path: root/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/ftp/SftpClient.java
blob: d1685203ea0bd88b2b89728f8c716b5ea84bd16c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*-
 * ============LICENSE_START======================================================================
 * Copyright (C) 2018-2019 Nordix Foundation, 2020 Nokia. All rights reserved.
 * ===============================================================================================
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 * ============LICENSE_END========================================================================
 */

package org.onap.dcaegen2.collectors.datafile.ftp;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.nio.file.Path;
import java.util.Optional;

import org.jetbrains.annotations.NotNull;
import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException;
import org.onap.dcaegen2.collectors.datafile.exceptions.NonRetryableDatafileTaskException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Gets file from xNF with SFTP protocol.
 *
 * @author <a href="mailto:martin.c.yan@est.tech">Martin Yan</a>
 */
public class SftpClient implements FileCollectClient {

    private static final Logger logger = LoggerFactory.getLogger(SftpClient.class);

    private static final int SFTP_DEFAULT_PORT = 22;
    private static final String STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";

    private final FileServerData fileServerData;
    protected Session session = null;
    protected ChannelSftp sftpChannel = null;
    private final SftpClientSettings settings;

    public SftpClient(FileServerData fileServerData, SftpClientSettings sftpConfig) {
        this.fileServerData = fileServerData;
        this.settings = sftpConfig;
    }

    @Override
    public void collectFile(String remoteFile, Path localFile) throws DatafileTaskException {
        logger.trace("collectFile {}", localFile);

        try {
            sftpChannel.get(remoteFile, localFile.toString());
            logger.trace("File {} Download successful from xNF", localFile.getFileName());
        } catch (SftpException e) {
            boolean retry = e.id != ChannelSftp.SSH_FX_NO_SUCH_FILE && e.id != ChannelSftp.SSH_FX_PERMISSION_DENIED
                && e.id != ChannelSftp.SSH_FX_OP_UNSUPPORTED;
            if (retry) {
                throw new DatafileTaskException("Unable to get file from xNF. Data: " + fileServerData, e);
            } else {
                throw new NonRetryableDatafileTaskException(
                    "Unable to get file from xNF. No retry attempts will be done. Data: " + fileServerData, e);
            }
        }

        logger.trace("collectFile OK");
    }

    @Override
    public void close() {
        logger.trace("closing sftp session");
        if (sftpChannel != null) {
            sftpChannel.exit();
            sftpChannel = null;
        }
        if (session != null) {
            session.disconnect();
            session = null;
        }
    }

    @Override
    public void open() throws DatafileTaskException {
        try {
            if (session == null) {
                session = setUpSession(fileServerData);
                sftpChannel = getChannel(session);
            }
        } catch (JSchException e) {
            boolean retry = !e.getMessage().contains("Auth fail");
            if (retry) {
                throw new DatafileTaskException("Could not open Sftp client. " + e);
            } else {
                throw new NonRetryableDatafileTaskException(
                    "Could not open Sftp client, no retry attempts will be done. " + e);
            }
        }
    }
    JSch createJsch() {
        return new JSch();
    }

    private int getPort(Optional<Integer> port) {
        return port.isPresent() ? port.get() : SFTP_DEFAULT_PORT;
    }

    private Session setUpSession(FileServerData fileServerData) throws JSchException {
        boolean useStrictHostChecking = this.settings.shouldUseStrictHostChecking();
        JSch jsch = createJschClient(useStrictHostChecking);
        return createJshSession(jsch, fileServerData, useStrictHostChecking);
    }

    private JSch createJschClient(boolean useStrictHostChecking) throws JSchException {
        JSch jsch = createJsch();
        if (useStrictHostChecking) {
            jsch.setKnownHosts(this.settings.getKnownHostsFilePath());
        }
        return jsch;
    }

    private Session createJshSession(JSch jsch, FileServerData fileServerData, boolean useStrictHostKeyChecking)
        throws JSchException {
        Session newSession =
            jsch.getSession(fileServerData.userId(), fileServerData.serverAddress(), getPort(fileServerData.port()));
        newSession.setConfig(STRICT_HOST_KEY_CHECKING, toYesNo(useStrictHostKeyChecking));
        newSession.setPassword(fileServerData.password());
        newSession.connect();
        return newSession;
    }

    @NotNull
    private String toYesNo(boolean useStrictHostKeyChecking) {
        return useStrictHostKeyChecking ? "yes" : "no";
    }

    private ChannelSftp getChannel(Session session) throws JSchException {
        Channel channel = session.openChannel("sftp");
        channel.connect();
        return (ChannelSftp) channel;
    }

}