101 lines
3.4 KiB
Kotlin
101 lines
3.4 KiB
Kotlin
package app.credentials
|
|
|
|
import org.apache.sshd.agent.SshAgent
|
|
import org.apache.sshd.agent.local.AgentImpl
|
|
import org.apache.sshd.agent.local.LocalAgentFactory
|
|
import org.apache.sshd.client.SshClient
|
|
import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractive
|
|
import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory
|
|
import org.apache.sshd.client.auth.keyboard.UserInteraction
|
|
import org.apache.sshd.client.auth.password.PasswordAuthenticationReporter
|
|
import org.apache.sshd.client.auth.password.UserAuthPassword
|
|
import org.apache.sshd.client.future.ConnectFuture
|
|
import org.apache.sshd.client.session.ClientSession
|
|
import org.apache.sshd.common.NamedResource
|
|
import org.apache.sshd.common.config.keys.FilePasswordProvider
|
|
import org.apache.sshd.common.keyprovider.FileKeyPairProvider
|
|
import org.apache.sshd.common.session.SessionContext
|
|
import org.eclipse.jgit.transport.RemoteSession
|
|
import org.eclipse.jgit.transport.URIish
|
|
import java.lang.Exception
|
|
import java.security.KeyPair
|
|
import java.time.Duration
|
|
import javax.inject.Inject
|
|
import javax.inject.Provider
|
|
|
|
|
|
private const val DEFAULT_SSH_PORT = 22
|
|
|
|
class GRemoteSession @Inject constructor(
|
|
private val processProvider: Provider<GProcess>,
|
|
) : RemoteSession {
|
|
private val credentialsStateManager = CredentialsStateManager
|
|
|
|
private val client = SshClient.setUpDefaultClient()
|
|
|
|
private var connectFuture: ConnectFuture? = null
|
|
|
|
override fun exec(commandName: String, timeout: Int): Process {
|
|
println(commandName)
|
|
|
|
val connectFuture = checkNotNull(connectFuture)
|
|
|
|
val session = connectFuture.clientSession
|
|
|
|
val auth = session.auth()
|
|
auth.addListener { arg0 ->
|
|
println("Authentication completed with " + if (arg0.isSuccess) "success" else "failure")
|
|
}
|
|
|
|
session.waitFor(
|
|
listOf(
|
|
ClientSession.ClientSessionEvent.WAIT_AUTH,
|
|
ClientSession.ClientSessionEvent.CLOSED,
|
|
ClientSession.ClientSessionEvent.AUTHED
|
|
), Duration.ofHours(2)
|
|
)
|
|
auth.verify()
|
|
|
|
val process = processProvider.get()
|
|
process.setup(session, commandName)
|
|
return process
|
|
}
|
|
|
|
|
|
override fun disconnect() {
|
|
client.close()
|
|
}
|
|
|
|
fun setup(uri: URIish) {
|
|
client.open()
|
|
|
|
val port = if (uri.port == -1) {
|
|
DEFAULT_SSH_PORT
|
|
} else
|
|
uri.port
|
|
|
|
val filePasswordProvider = object : FilePasswordProvider {
|
|
override fun getPassword(session: SessionContext?, resourceKey: NamedResource?, retryIndex: Int): String? {
|
|
credentialsStateManager.updateState(CredentialsState.SshCredentialsRequested)
|
|
|
|
var credentials = credentialsStateManager.currentCredentialsState
|
|
while (credentials is CredentialsState.CredentialsRequested) {
|
|
// TODO check if support for ED25519 with pwd can be added
|
|
credentials = credentialsStateManager.currentCredentialsState
|
|
}
|
|
|
|
return if(credentials !is CredentialsState.SshCredentialsAccepted)
|
|
null
|
|
else
|
|
credentials.password
|
|
}
|
|
}
|
|
|
|
client.filePasswordProvider = filePasswordProvider
|
|
|
|
val connectFuture = client.connect(uri.user, uri.host, port)
|
|
connectFuture.await()
|
|
|
|
this.connectFuture = connectFuture
|
|
}
|
|
} |