Changeset 7471


Ignore:
Timestamp:
Apr 9, 2018, 3:23:53 PM (5 years ago)
Author:
Nicklas Nordborg
Message:

References #2112: Add support for SSH private keys to file server items

Added 3 new database columns for storing the private key data, password and format. No special update is needed besides incrementing the schema version.

Location:
trunk/src/core/net/sf/basedb
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/net/sf/basedb/core/FileServer.java

    r7381 r7471  
    334334  public static final int FINGERPRINT_LENGTH = FileServerData.FINGERPRINT_LENGTH;
    335335
     336  /**
     337    The maximum length of the SSH private key format path that can be stored in the database.
     338    @see #setSshPrivateKeyFormat(String)
     339    @since 3.13
     340  */
     341  public static final int MAX_FORMAT_LENGTH = FileServerData.MAX_FORMAT_LENGTH;
    336342 
    337343  /**
     
    535541  }
    536542 
     543  /**
     544    The maximum length of the SSH private key that can be stored in the database.
     545    @see #setSshPrivateKey(byte[])
     546    @since 3.13
     547  */
     548  public static final int MAX_PRIVATE_KEY_LENGTH = FileServerData.MAX_PRIVATE_KEY_LENGTH;
     549 
     550  /**
     551    Check if a SSH private key has been set on this file server.
     552    @since 3.13
     553  */
     554  public boolean hasSshPrivateKey()
     555  {
     556    byte[] key = getData().getSshPrivateKey();
     557    return key != null && key.length > 0;
     558  }
     559 
     560  /**
     561    Get the private key that BASE should use to authenticate with the server
     562    when connecting with SSH. This can be used as an alternate to password
     563    authentication. Note that BASE has no built-in support for SSH connections.
     564    See http://baseplugins.thep.lu.se/wiki/net.sf.basedb.xfiles for an extension
     565    which includes support for SSH.
     566    <p>
     567   
     568    NOTE! WRITE permission is required to read this property since
     569    it may contain sensitive data.
     570   
     571    @return A byte array with the private key or null if no private key has been set
     572    @since 3.13
     573  */
     574  public byte[] getSshPrivateKey()
     575  {
     576    if (!hasPermission(Permission.WRITE))
     577    {
     578      throw new PermissionDeniedException("WRITE permission is required to read the raw private key");
     579    }
     580    byte[] key = getData().getSshPrivateKey();
     581    if (key == null || key.length == 0) return null;
     582    return Arrays.copyOf(key, key.length);
     583  }
     584 
     585  /**
     586    Set the private that BASE should use to authenticate with the server
     587    when connecting with SSH.
     588   
     589    @param privateKey The private key data or null if no private key is required
     590    @since 3.13
     591  */
     592  public void setSshPrivateKey(byte[] privateKey)
     593  {
     594    checkPermission(Permission.WRITE);
     595    if (privateKey != null && privateKey.length > MAX_PRIVATE_KEY_LENGTH)
     596    {
     597      throw new InvalidDataException("The 'sshPrivateKey' mustn't be longer than "+MAX_PRIVATE_KEY_LENGTH+
     598          " bytes. The supplied value is "+privateKey.length+ " bytes.");
     599    }
     600    byte[] key = null;
     601    if (privateKey != null && privateKey.length > 0)
     602    {
     603      key = Arrays.copyOf(privateKey, privateKey.length);
     604    }
     605    getData().setSshPrivateKey(key);
     606  }
     607
     608  /**
     609    Get the password that is needed to unlock the SSH private key.
     610    NOTE! WRITE permission is required to read this property.
     611    @return The password (which may be null)
     612    @since 3.13
     613  */
     614  public String getSshPrivateKeyPassword()
     615  {
     616    if (!hasPermission(Permission.WRITE))
     617    {
     618      throw new PermissionDeniedException("WRITE permission is required to read the password");
     619    }
     620    return getData().getSshPrivateKeyPassword();
     621  }
     622 
     623  /**
     624    Set the password that is needed to unlock the SSH private key.
     625   
     626    @param password The new password (can be null)
     627    @throws PermissionDeniedException If the logged in user doesn't have
     628      write permission
     629    @throws InvalidDataException If the password is longer than {@link #MAX_PASSWORD_LENGTH}
     630    @since 3.13
     631  */
     632  public void setSshPrivateKeyPassword(String password)
     633    throws PermissionDeniedException, InvalidDataException
     634  {
     635    checkPermission(Permission.WRITE);
     636    getData().setSshPrivateKeyPassword(StringUtil.setNullableString(password,
     637        "sshPrivateKeyPassword", MAX_PASSWORD_LENGTH));
     638  }
     639 
     640  /**
     641    Get the format of the SSH private key.
     642    @return The format (which may be null to use auto-detection)
     643    @since 3.13
     644  */
     645  public String getSshPrivateKeyFormat()
     646  {
     647    return getData().getSshPrivateKeyFormat();
     648  }
     649 
     650  /**
     651    Set the format of the SSH private key. Supported values are:
     652   
     653    * PuTTY
     654    * OpenSSH
     655    * OpenSSHv1
     656    * PKCS5
     657    * PKCS8
     658   
     659    @param format The private key format or null to use auto-detection
     660    @throws PermissionDeniedException If the logged in user doesn't have
     661      write permission
     662    @throws InvalidDataException If the password is longer than {@link #MAX_FORMAT_LENGTH}
     663    @since 3.13
     664  */
     665  public void setSshPrivateKeyFormat(String password)
     666    throws PermissionDeniedException, InvalidDataException
     667  {
     668    checkPermission(Permission.WRITE);
     669    getData().setSshPrivateKeyFormat(StringUtil.setNullableString(password,
     670        "sshPrivateKeyFormat", MAX_FORMAT_LENGTH));
     671  }
     672
    537673  /**
    538674    @since 3.3
  • trunk/src/core/net/sf/basedb/core/Install.java

    r7413 r7471  
    119119    method.
    120120  */
    121   public static final int NEW_SCHEMA_VERSION = Integer.valueOf(140).intValue();
     121  public static final int NEW_SCHEMA_VERSION = Integer.valueOf(141).intValue();
    122122 
    123123  public static synchronized int createTables(SchemaGenerator.Mode mode, ProgressReporter progress,
  • trunk/src/core/net/sf/basedb/core/Update.java

    r7461 r7471  
    391391    </td>
    392392  </tr>
     393  <tr>
     394    <td>141</td>
     395    <td>
     396      Added {@link FileServerData#getSshPrivateKey()}, {@link FileServerData#getSshPrivateKeyPassword()}
     397      and {@link FileServerData#getSshPrivateKeyFormat()}. No special database update is needed.
     398      Only increase the schema version.
     399    </td>
     400  </tr>
    393401 
    394402  </table>
     
    632640        schemaVersion = setSchemaVersionInTransaction(session, 140);
    633641        progress_current += 2 * progress_step;
     642      }
     643     
     644      if (schemaVersion < 141)
     645      {
     646        if (progress != null) progress.display((int)(progress_current), "--Updating schema version: " + schemaVersion + " -> 141...");
     647        schemaVersion = setSchemaVersionInTransaction(session, 141);
     648        progress_current += progress_step;
    634649      }
    635650
  • trunk/src/core/net/sf/basedb/core/data/FileServerData.java

    r7332 r7471  
    158158  }
    159159 
     160  public static final int MAX_PRIVATE_KEY_LENGTH = 65535;
     161  private byte[] sshPrivateKey;
     162  /**
     163    Get the SSH private key that we need to send to the server
     164    to make the server accept our connection.
     165    @since 3.13
     166    @hibernate.property column="`ssh_private_key`" type="binary" length="65535" not-null="false"
     167  */
     168  @PropertyPathProtected
     169  public byte[] getSshPrivateKey()
     170  {
     171    return sshPrivateKey;
     172  }
     173  public void setSshPrivateKey(byte[] sshPrivateKey)
     174  {
     175    this.sshPrivateKey = sshPrivateKey;
     176  }
     177 
     178  private String sshPrivateKeyPassword;
     179  /**
     180    Get the password that is used to unlock the SSH private key.
     181    @since 3.13
     182    @hibernate.property column="`ssh_private_key_password`" type="string" length="255" not-null="false"
     183  */
     184  @PropertyPathProtected
     185  public String getSshPrivateKeyPassword()
     186  {
     187    return sshPrivateKeyPassword;
     188  }
     189  public void setSshPrivateKeyPassword(String sshPrivateKeyPassword)
     190  {
     191    this.sshPrivateKeyPassword = sshPrivateKeyPassword;
     192  }
     193
     194  public static final int MAX_FORMAT_LENGTH = 255;
     195  private String sshPrivateKeyFormat;
     196  /**
     197    Get the private key format.
     198    @since 3.13
     199    @hibernate.property column="`ssh_private_key_format`" type="string" length="255" not-null="false"
     200  */
     201  public String getSshPrivateKeyFormat()
     202  {
     203    return sshPrivateKeyFormat;
     204  }
     205  public void setSshPrivateKeyFormat(String sshPrivateKeyFormat)
     206  {
     207    this.sshPrivateKeyFormat = sshPrivateKeyFormat;
     208  }
     209 
    160210  public static final int MAX_CERTIFICATE_LENGTH = 65535;
    161211  private byte[] serverCertificate;
  • trunk/src/core/net/sf/basedb/util/uri/ConnectionParameters.java

    r6497 r7471  
    2424import java.net.URI;
    2525import java.net.URISyntaxException;
     26
     27import org.bouncycastle.util.Arrays;
    2628
    2729import net.sf.basedb.core.FileServer;
     
    5456    parameters.setUsername(fileServer.getUsername());
    5557    parameters.setPassword(fileServer.getPassword());
    56     parameters.setServerCertificate(fileServer.getServerCertificate());
    57     parameters.setClientCertificate(fileServer.getClientCertificate());
     58    parameters.setServerCertificate(Arrays.clone(fileServer.getServerCertificate()));
     59    parameters.setClientCertificate(Arrays.clone(fileServer.getClientCertificate()));
    5860    parameters.setClientCertificatePassword(fileServer.getClientCertificatePassword());
    5961    parameters.setRootPath(fileServer.getRootPath());
    6062    parameters.setSshFingerprint(fileServer.getSshFingerprint());
     63    parameters.setSshPrivateKey(Arrays.clone(fileServer.getSshPrivateKey()));
     64    parameters.setSshPrivateKeyPassword(fileServer.getSshPrivateKeyPassword());
     65    parameters.setSshPrivateKeyFormat(fileServer.getSshPrivateKeyFormat());
    6166    return parameters;
    6267  }
     
    6873  private String rootPath;
    6974  private String sshFingerprint;
     75  private byte[] sshPrivateKey;
     76  private String sshPrivateKeyPassword;
     77  private String sshPrivateKeyFormat;
    7078  private byte[] serverCertificate;
    7179  private byte[] clientCertificate;
     
    208216  }
    209217
    210  
     218  /**
     219    Get the private key that should be used to authenticate with the server
     220    when connecting using SSH.
     221    @since 3.13
     222  */
     223  public byte[] getSshPrivateKey()
     224  {
     225    return sshPrivateKey;
     226  }
     227  public void setSshPrivateKey(byte[] sshPrivateKey)
     228  {
     229    this.sshPrivateKey = sshPrivateKey;
     230  }
     231 
     232  /**
     233    Get the password that is needed to unlock the SSH private key.
     234    @return The password (which may be null)
     235    @since 3.13
     236  */
     237  public String getSshPrivateKeyPassword()
     238  {
     239    return sshPrivateKeyPassword;
     240  }
     241  public void setSshPrivateKeyPassword(String password)
     242  {
     243    this.sshPrivateKeyPassword = password;
     244  }
     245 
     246  /**
     247    Get the format of the SSH private key (if known).
     248    @return The private key format (or null to try auto-detection)
     249    @since 3.13
     250  */
     251  public String getSshPrivateKeyFormat()
     252  {
     253    return sshPrivateKeyFormat;
     254  }
     255  public void setSshPrivateKeyFormat(String format)
     256  {
     257    this.sshPrivateKeyFormat = format;
     258  }
     259
    211260  /**
    212261    If the connection parameters include a specific host:port or root path
Note: See TracChangeset for help on using the changeset viewer.