hi all,
couple of week before, I had a wonderful discussion with micheal about
providing SOAP APIs to the OpenCA system. Basically the idea is,
1) to programatically automate & manage some of OpenCA process from other
applications.
2) interoperable API to any environment.
we are running an management software (java based) in our university. We need
to provide pki (as pluggable module) to that application. We have been using
OpenCA for the last one year....and we are quiet comfortable with that.
Unfortunately their is no open API available for OpenCA to run as a
transparent server in the background. we found ejbca project from
sourceforge.net has such a feature both as standalone PKI system or API to
connect to other legacy systems. But We didn't try any other opensource pki
software (because of wonderful support from OpenCA team, especially micheal
;) ). we started thinking about writing API's for OpenCA just when other
folks started discussing about OpenCA Server in the devel list.
I quickly did some experiment with perl SOAP modules and tried something....
all i did was simply cut & paste some code from the OpenCA 'cmds' directory
and installation of SOAP::Lite from CPAN. It's working and also i am able to
call those methods from java envirnment (after all soap is meant for that). I
shared my experience with micheal, he encourged me to discuss in the devel
list.
I have added a prototype test program here.... Remeber i not a perl or SOAP
expert, I started learning perl after working with OpenCA ;). Just want to
give back something to the OpenCA community. i will keep doing some work on
the same line.... If you guys have any idea or suggestions for OpenCA API's (
I am really need help in overall structure for the API's ) please write
back...
Thanks,
venki.
use strict;
package OpenCA::SOAP;
## Load necessary OpenCA modules
##
use OpenCA::OpenSSL;
use OpenCA::REQ;
use OpenCA::DBI;
use OpenCA::Tools;
## define global variables
##
## constructor method
sub loadConf
{
my $invocant = shift;
my $class = ref($invocant)||$invocant;
my $HOME = "/epki/jc";
my $self = {
# TempDir => "/epki/jc/OpenCA/var/tmp",
TempDir => "/tmp",
ModuleID => 0,
ModuleShift => 8,
OpenSSLPath => "/usr/local/ssl/bin/openssl",
CACert => "$HOME/OpenCA/var/crypto/cacerts/cacert.pem"
};
bless $self,$class;
return $self;
}
sub generateRequest
{
my $self = shift;
my ($email,$cn,$ou,$passwd) = @_;
## following method of accepting input parameters
## should be rewritten
my $role = "User";
my $ra = "Trustcenter itself";
my $bits = "1024";
my $org = "JamCracker";
my $country = "US";
my @elements = ("emailAddress","CN","OU","O","C");
## form DN string
my $dn = "";
$dn .= $elements [0]."=".$email.",";
$dn .= $elements [1]."=".$cn.",";
$dn .= $elements [2]."=".$ou.",";
$dn .= $elements [3]."=".$org.",";
$dn .= $elements [4]."=".$country;
## create temp file
my $keyFile = "$self->{TempDir}/key_$$.pem";
## create OpenSSL object
my $cryptoShell = new OpenCA::OpenSSL( SHELL => $self->{OpenSSLPath});
if (not defined $cryptoShell)
{
die "Can't create OpenSSL object";
}
## create key pairs
if (not $cryptoShell->genKey(
BITS => $bits,
OUTFILE => $keyFile,
PASSWD => $passwd) )
{
die "Can't create key pairs";
}
## change to pkcs8
my $key = $cryptoShell->dataConvert (
DATATYPE => "KEY",
INFORM => "PEM",
OUTFORM => "PKCS8",
INPASSWD => $passwd,
OUTPASSWD => $passwd,
INFILE => $keyFile );
if (not $key)
{
die "Can't Convert to pkcs8 format";
}
## generate PKCS10 request
my $req = new OpenCA::REQ (
SHELL => $cryptoShell,
KEYFILE => $keyFile,
SUBJECT => $dn,
PASSWD => $passwd,
FORMAT => "PEM" );
if (not $req)
{
die "Can't create REQ object";
}
unlink($keyFile);
## compose request
my $tmp = "-----BEGIN HEADER-----\n";
$tmp .= "TYPE = PKCS#10\n";
my $db = new OpenCA::DBI(
SHELL => $cryptoShell,
DB_Type => "mysql",
DB_Name => "jcpki",
DB_Host => "localhost",
DB_Port => "3306",
DB_User => "jcpki",
DB_Passwd => "jcpki");
if (not $db)
{
die "Can't initialize OpenCA::DBI class";
}
my $req_elements = $db->elements(DATATYPE=>"REQUEST");
if ((not defined $req_elements) or ($req_elements < 0))
{
die "Database failed while counting the requests";
}
else
{
$req_elements++;
}
my $new_serial = ($req_elements << $self->{ModuleShift})|$self->{ModuleID};
$tmp .= "SERIAL = ".$new_serial."\n";
my $tools = new OpenCA::Tools();
if (not $tools)
{
die "Cannot initialize OpenCA::Tools class!";
}
$tmp .= "NOTBEFORE = ".$tools->getDate()."\n";
my $pin_digest = $cryptoShell->getDigest(
DATA => $passwd,
ALGORITHM => "sha1");
if (not $pin_digest)
{
die "OpenSSL failed during the calculation of hash";
}
$tmp .= "PIN = $pin_digest\n";
$tmp .= "RA = $ra\n";
$tmp .= "ROLE = $role\n";
$tmp .= "-----END HEADER-----\n";
$tmp .= $req->getPEM();
$tmp .= $key;
my $new_req;
if (not $new_req = new OpenCA::REQ(SHELL=>$cryptoShell,
DATA =>$tmp))
{
die "Internal Request Error";
}
if (not $db->storeItem( DATATYPE=>"PENDING_REQUEST",
OBJECT =>$new_req,
INFORM =>"PEM",
MODE =>"INSERT"))
{
die "Error while storing REQ in database\n";
}
return "Success\n";
}
sub getCACertificate
{
my $self = shift;
my $certificate = "";
if (not open (FD, $self->{CACert}))
{
die "Can't Access CA Certificate File";
}
while (<FD>)
{
$certificate .= $_;
}
return $certificate;
}
1;
#!/usr/bin/perl -w
use SOAP::Lite;
my $soap = SOAP::Lite
->uri('http://192.168.2.66:7777/OpenCA/SOAP')
->proxy('http://192.168.2.66:7777')
;
my $obj = $soap->call(loadConf)->result;
my $result = $soap->generateRequest($obj,"[EMAIL PROTECTED]","test1","security","myPasswd");
unless (defined $result->fault)
{
print $result->result;
}else{
print $result->faultcode;
print $result->faultstring;
}
#!/usr/bin/perl -w
use SOAP::Transport::HTTP;
# don't want to die on 'Broken pipe' or Ctrl-C
$SIG{PIPE} = 'IGNORE';
$daemon = SOAP::Transport::HTTP::Daemon
-> new (LocalPort => 7777)
-> dispatch_to('/home/venki/perlws/soapprg/modules/','OpenCA::SOAP')
;
print "Contact to SOAP server at ", $daemon->url, "\n";
$daemon->handle;