org.pentaho.di.job.entries.pgpencryptfiles.GPG Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kettle-engine Show documentation
Show all versions of kettle-engine Show documentation
Container pom for Pentaho Data Integration modules
The newest version!
/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 by Hitachi Vantara : http://www.pentaho.com
*
*******************************************************************************
*
* 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.
*
******************************************************************************/
package org.pentaho.di.job.entries.pgpencryptfiles;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileType;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.core.vfs.KettleVFS;
import org.pentaho.di.i18n.BaseMessages;
/**
* This defines a GnuPG wrapper class.
*
* @author Samatar
* @since 25-02-2011
*
*/
public class GPG {
private static Class> PKG = JobEntryPGPEncryptFiles.class; // for i18n purposes, needed by Translator2!!
private LogChannelInterface log;
private final String gnuPGCommand = "--batch --armor ";
/** gpg program location **/
private String gpgexe = "/usr/local/bin/gpg";
/** temporary file create when running command **/
private File tmpFile;
/**
* Reads an output stream from an external process. Implemented as a thread.
*/
class ProcessStreamReader extends Thread {
StringBuilder stream;
InputStreamReader in;
static final int BUFFER_SIZE = 1024;
/**
* Creates new ProcessStreamReader object.
*
* @param in
*/
ProcessStreamReader( InputStream in ) {
super();
this.in = new InputStreamReader( in );
this.stream = new StringBuilder();
}
public void run() {
try {
int read;
char[] c = new char[BUFFER_SIZE];
while ( ( read = in.read( c, 0, BUFFER_SIZE - 1 ) ) > 0 ) {
stream.append( c, 0, read );
if ( read < BUFFER_SIZE - 1 ) {
break;
}
}
} catch ( IOException io ) {
// Ignore read errors
}
}
String getString() {
return stream.toString();
}
}
/**
* Constructs a new GnuPG
*
* @param gpgFilename
* gpg program location
* @param logInterface
* LogChannelInterface
* @throws KettleException
*/
public GPG( String gpgFilename, LogChannelInterface logInterface ) throws KettleException {
this.log = logInterface;
this.gpgexe = gpgFilename;
// Let's check GPG filename
if ( Utils.isEmpty( getGpgExeFile() ) ) {
// No filename specified
throw new KettleException( BaseMessages.getString( PKG, "GPG.GPGFilenameMissing" ) );
}
// We have a filename, we need to check
FileObject file = null;
try {
file = KettleVFS.getFileObject( getGpgExeFile() );
if ( !file.exists() ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.GPGFilenameNotFound" ) );
}
// The file exists
if ( !file.getType().equals( FileType.FILE ) ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.GPGNotAFile", getGpgExeFile() ) );
}
// Ok we have a real file
// Get the local filename
this.gpgexe = KettleVFS.getFilename( file );
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.ErrorCheckingGPGFile", getGpgExeFile() ), e );
} finally {
try {
if ( file != null ) {
file.close();
}
} catch ( Exception e ) {
// Ignore close errors
}
}
}
/**
* Returns GPG program location
*
* @return GPG filename
*/
public String getGpgExeFile() {
return this.gpgexe;
}
/**
* Runs GnuPG external program
*
* @param commandArgs
* command line arguments
* @param inputStr
* key ID of the key in GnuPG's key database
* @param fileMode
* @return result
* @throws KettleException
*/
private String execGnuPG( String commandArgs, String inputStr, boolean fileMode ) throws KettleException {
Process p;
String command = getGpgExeFile() + " " + ( fileMode ? "" : gnuPGCommand + " " ) + commandArgs;
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "GPG.RunningCommand", command ) );
}
String retval;
try {
if ( Const.isWindows() ) {
p = Runtime.getRuntime().exec( command );
} else {
ProcessBuilder processBuilder = new ProcessBuilder( "/bin/sh", "-c", command );
p = processBuilder.start();
}
} catch ( IOException io ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.IOException" ), io );
}
ProcessStreamReader psr_stdout = new ProcessStreamReader( p.getInputStream() );
ProcessStreamReader psr_stderr = new ProcessStreamReader( p.getErrorStream() );
psr_stdout.start();
psr_stderr.start();
if ( inputStr != null ) {
BufferedWriter out = new BufferedWriter( new OutputStreamWriter( p.getOutputStream() ) );
try {
out.write( inputStr );
} catch ( IOException io ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.ExceptionWrite" ), io );
} finally {
if ( out != null ) {
try {
out.close();
} catch ( Exception e ) {
// Ignore
}
}
}
}
try {
p.waitFor();
psr_stdout.join();
psr_stderr.join();
} catch ( InterruptedException i ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.ExceptionWait" ), i );
}
try {
if ( p.exitValue() != 0 ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.Exception.ExistStatus", psr_stderr
.getString() ) );
}
} catch ( IllegalThreadStateException itse ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.ExceptionillegalThreadStateException" ), itse );
} finally {
p.destroy();
}
retval = psr_stdout.getString();
return retval;
}
/**
* Decrypt a file
*
* @param cryptedFilename
* crypted filename
* @param passPhrase
* passphrase for the personal private key to sign with
* @param decryptedFilename
* decrypted filename
* @throws KettleException
*/
public void decryptFile( FileObject cryptedFilename, String passPhrase, FileObject decryptedFilename ) throws KettleException {
decryptFile( KettleVFS.getFilename( cryptedFilename ), passPhrase, KettleVFS.getFilename( decryptedFilename ) );
}
/**
* Decrypt a file
*
* @param cryptedFilename
* crypted filename
* @param passPhrase
* passphrase for the personal private key to sign with
* @param decryptedFilename
* decrypted filename
* @throws KettleException
*/
public void decryptFile( String cryptedFilename, String passPhrase, String decryptedFilename ) throws KettleException {
try {
execGnuPG( "--batch --yes "
+ ( Utils.isEmpty( passPhrase ) ? "" : "--passphrase " + "\"" + passPhrase + "\" " ) + "--output "
+ "\"" + decryptedFilename + "\" " + "--decrypt " + "\"" + cryptedFilename + "\"", null, true );
} catch ( Exception e ) {
throw new KettleException( e );
}
}
/**
* Encrypt a file
*
* @param filename
* file to encrypt
* @param userID
* specific user id key
* @param cryptedFilename
* crypted filename
* @param asciiMode
* output ASCII file
* @throws KettleException
*/
public void encryptFile( FileObject filename, String userID, FileObject cryptedFilename, boolean asciiMode ) throws KettleException {
encryptFile( KettleVFS.getFilename( filename ), userID, KettleVFS.getFilename( cryptedFilename ), asciiMode );
}
/**
* Encrypt a file
*
* @param filename
* file to encrypt
* @param userID
* specific user id key
* @param cryptedFilename
* crypted filename
* @param asciiMode
* output ASCII file
* @throws KettleException
*/
public void encryptFile( String filename, String userID, String cryptedFilename, boolean asciiMode ) throws KettleException {
try {
execGnuPG( "--batch --yes"
+ ( asciiMode ? " -a" : "" ) + " -r " + "\"" + Const.NVL( userID, "" ) + "\" " + "--output " + "\""
+ cryptedFilename + "\" " + "--encrypt " + "\"" + filename + "\"", null, true );
} catch ( Exception e ) {
throw new KettleException( e );
}
}
/**
* Sign and encrypt a file
*
* @param file
* file to encrypt
* @param userID
* specific user id key
* @param cryptedFile
* crypted filename
* @param asciiMode
* output ASCII file
* @throws KettleException
*/
public void signAndEncryptFile( FileObject file, String userID, FileObject cryptedFile, boolean asciiMode ) throws KettleException {
signAndEncryptFile( KettleVFS.getFilename( file ), userID, KettleVFS.getFilename( cryptedFile ), asciiMode );
}
/**
* Sign and encrypt a file
*
* @param filename
* file to encrypt
* @param userID
* specific user id key
* @param cryptedFilename
* crypted filename
* @param asciiMode
* output ASCII file
* @throws KettleException
*/
public void signAndEncryptFile( String filename, String userID, String cryptedFilename, boolean asciiMode ) throws KettleException {
try {
execGnuPG(
"--batch --yes"
+ ( asciiMode ? " -a" : "" ) + ( Utils.isEmpty( userID ) ? "" : " -r " + "\"" + userID + "\"" )
+ " " + "--output " + "\"" + cryptedFilename + "\" " + "--encrypt --sign " + "\"" + filename + "\"",
null, true );
} catch ( Exception e ) {
throw new KettleException( e );
}
}
/**
* Sign a file
*
* @param filename
* file to encrypt
* @param userID
* specific user id key
* @param cryptedFilename
* crypted filename
* @param asciiMode
* output ASCII file
* @throws KettleException
*/
public void signFile( String filename, String userID, String signedFilename, boolean asciiMode ) throws KettleException {
try {
execGnuPG( "--batch --yes"
+ ( asciiMode ? " -a" : "" ) + ( Utils.isEmpty( userID ) ? "" : " -r " + "\"" + userID + "\"" ) + " "
+ "--output " + "\"" + signedFilename + "\" " + ( asciiMode ? "--clearsign " : "--sign " ) + "\""
+ filename + "\"", null, true );
} catch ( Exception e ) {
throw new KettleException( e );
}
}
/**
* Sign a file
*
* @param file
* file to encrypt
* @param userID
* specific user id key
* @param signedFile
* crypted filename
* @param asciiMode
* output ASCII file
* @throws KettleException
*/
public void signFile( FileObject file, String userID, FileObject signedFile, boolean asciiMode ) throws KettleException {
try {
signFile( KettleVFS.getFilename( file ), userID, KettleVFS.getFilename( signedFile ), asciiMode );
} catch ( Exception e ) {
throw new KettleException( e );
}
}
/**
* Verify a signature
*
* @param filename
* filename
* @throws KettleException
*/
public void verifySignature( FileObject filename ) throws KettleException {
verifySignature( KettleVFS.getFilename( filename ) );
}
/**
* Verify a signature
*
* @param filename
* filename
* @originalFilename fill this value in case of detached signature
* @throws KettleException
*/
public void verifySignature( String filename ) throws KettleException {
execGnuPG( "--batch --verify " + "\"" + filename + "\"", null, true );
}
/**
* Verify a signature for detached file
*
* @param signatureFilename
* filename
* @param originalFilenamefill
* this value in case of detached signature
* @throws KettleException
*/
public void verifyDetachedSignature( String signatureFilename, String originalFilename ) throws KettleException {
execGnuPG( "--batch --verify " + "\"" + signatureFilename + "\" " + "\"" + originalFilename + "\"", null, true );
}
/**
* Verify a signature for detached file
*
* @param signatureFile
* filename
* @param originalFile
* fill this value in case of detached signature
* @throws KettleException
*/
public void verifyDetachedSignature( FileObject signatureFile, FileObject originalFile ) throws KettleException {
verifyDetachedSignature( KettleVFS.getFilename( signatureFile ), KettleVFS.getFilename( originalFile ) );
}
/**
* Encrypt a string
*
* @param plainText
* input string to encrypt
* @param keyID
* key ID of the key in GnuPG's key database to encrypt with
* @return encrypted string
* @throws KettleException
*/
public String encrypt( String plainText, String keyID ) throws KettleException {
return execGnuPG( "-r \"" + keyID + "\" --encrypt ", plainText, false );
}
/**
* Signs and encrypts a string
*
* @param plainText
* input string to encrypt
* @param userID
* key ID of the key in GnuPG's key database to encrypt with
* @param passPhrase
* passphrase for the personal private key to sign with
* @return encrypted string
* @throws KettleException
*/
public String signAndEncrypt( String plainText, String userID, String passPhrase ) throws KettleException {
try {
createTempFile( plainText );
return execGnuPG(
"-r \"" + userID + "\" --passphrase-fd 0 -se \"" + getTempFileName() + "\"", passPhrase, false );
} finally {
deleteTempFile();
}
}
/**
* Sign
*
* @param stringToSign
* input string to sign
* @param passPhrase
* passphrase for the personal private key to sign with
* @throws KettleException
*/
public String sign( String stringToSign, String passPhrase ) throws KettleException {
String retval;
try {
createTempFile( stringToSign );
retval = execGnuPG( "--passphrase-fd 0 --sign \"" + getTempFileName() + "\"", passPhrase, false );
} finally {
deleteTempFile();
}
return retval;
}
/**
* Decrypt a string
*
* @param cryptedText
* input string to decrypt
* @param passPhrase
* passphrase for the personal private key to sign with
* @return plain text
* @throws KettleException
*/
public String decrypt( String cryptedText, String passPhrase ) throws KettleException {
try {
createTempFile( cryptedText );
return execGnuPG( "--passphrase-fd 0 --decrypt \"" + getTempFileName() + "\"", passPhrase, false );
} finally {
deleteTempFile();
}
}
/**
* Create a unique temporary file when needed by one of the main methods. The file handle is store in tmpFile object
* var.
*
* @param content
* data to write into the file
* @throws KettleException
*/
private void createTempFile( String content ) throws KettleException {
this.tmpFile = null;
FileWriter fw;
try {
this.tmpFile = File.createTempFile( "GnuPG", null );
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "GPG.TempFileCreated", getTempFileName() ) );
}
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "GPG.ErrorCreatingTempFile" ), e );
}
try {
fw = new FileWriter( this.tmpFile );
fw.write( content );
fw.flush();
fw.close();
} catch ( Exception e ) {
// delete our file:
deleteTempFile();
throw new KettleException( BaseMessages.getString( PKG, "GPG.ErrorWritingTempFile" ), e );
}
}
/**
* Delete temporary file.
*
* @throws KettleException
*/
private void deleteTempFile() {
if ( this.tmpFile != null ) {
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "GPG.DeletingTempFile", getTempFileName() ) );
}
this.tmpFile.delete();
}
}
/**
* Returns temporary filename.
*
* @return temporary filename
*/
private String getTempFileName() {
return this.tmpFile.getAbsolutePath();
}
public String toString() {
return "GPG";
}
}