Search code examples
scalasshsbtscalatest

Multiple SSH connections not allowed in an sbt session


In a multi-module Scala project I'm running several integration tests where I use scala-ssh (v. 0.8) to connect to a remote machine via SSH and transfer a file from there.

If I run an integration test once in an sbt session, everything works as expected - I can connect to the machine and download any file. The related bits of Scala code are:

private lazy val fileInventory: AnsibleYamlFileInventory = {
    val inventory = SSH(ansibleHost, HostResourceConfig()) { client =>
      client.fileTransfer {
        scp =>
          val tmpLocalFile = Files.createTempFile("inventory", ".yaml")
          scp.download(remoteYamlInventoryFile, tmpLocalFile.toAbsolutePath.toString)
          new AnsibleYamlFileInventory(tmpLocalFile)
      }
    }

    inventory.fold(s => throw new RuntimeException(s), identity)
}

The problem occurs if I try to run the same test (or another integration test) within the same sbt session. I get the same error message as mentioned here:

    14:32:11.751 [reader] ERROR net.schmizz.sshj.transport.TransportImpl - Dying because - {}
net.schmizz.sshj.common.SSHRuntimeException: null
        at net.schmizz.sshj.common.Buffer.readPublicKey(Buffer.java:432)
        at net.schmizz.sshj.transport.kex.AbstractDHG.next(AbstractDHG.java:75)
        at net.schmizz.sshj.transport.KeyExchanger.handle(KeyExchanger.java:367)
        at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:509)
        at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:107)
        at net.schmizz.sshj.transport.Decoder.received(Decoder.java:175)
        at net.schmizz.sshj.transport.Reader.run(Reader.java:60)
Caused by: java.security.GeneralSecurityException: java.security.spec.InvalidKeySpecException: key spec not recognised
        at net.schmizz.sshj.common.KeyType$3.readPubKeyFromBuffer(KeyType.java:156)
        at net.schmizz.sshj.common.Buffer.readPublicKey(Buffer.java:430)
        ... 6 common frames omitted
Caused by: java.security.spec.InvalidKeySpecException: key spec not recognised
        at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
        at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
        at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
        at net.schmizz.sshj.common.KeyType$3.readPubKeyFromBuffer(KeyType.java:154)
        ... 7 common frames omitted

If I kill that sbt session and relaunch another one, I can again run only a single integration test before the problem reoccurs.

I have already installed the JCE 8 files as suggested. So, I'm wondering what I need to fix to get multiple tests running successfully where one after another they can ssh into that remote machine.


Solution

  • After some debugging I found out that the problem was due to BouncyCastle, which remains registered as a JCE provider in a follow-up test and causes problems. This shows up in the stack trace as:

    INFO net.schmizz.sshj.common.SecurityUtils - BouncyCastle already registered as a JCE provider
    

    I decided to add a security provider dynamically and remove it after tests are done.

    def doTests(): Unit = {
    
      import org.bouncycastle.jce.provider.BouncyCastleProvider
      import java.security.Security
    
      Security.addProvider(new BouncyCastleProvider)
    
      "Some test" should {
        "be BLABLA" in {
          assert(...) // some test
        }
      }
    
      "Some other test" should {
        "be BLABLABLA" in {
          assert(...) // some other test
        }
      }
    
      Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME)
    }