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;