Forum Discussion

Vincent_Li_9688's avatar
Vincent_Li_9688
Historic F5 Account
May 22, 2012

How to upload cert through Management :: KeyCertificate :: certificate_import_from_file

Hi ,

 

 

I adopted the Perl Certificate Info script https://devcentral.f5.com/wiki/iControl.PlCertificateInfo.ashx, and attempt to add new feature like uploading certificate to BIGIP according to https://devcentral.f5.com/wiki/iControl.Management__KeyCertificate__certificate_import_from_file.ashx, sample code below, the script is not working and there is no error reports, anyone can shed some light on what's going on?

 

 

use SOAP::Lite;

 

use MIME::Base64;

 

use Math::BigInt;

 

 

BEGIN { push (@INC, ".."); }

 

use iControlTypeCast;

 

 

----------------------------------------------------------------------------

 

Validate Arguments

 

----------------------------------------------------------------------------

 

my $sHost = $ARGV[0];

 

my $sPort = $ARGV[1];

 

my $sUID = $ARGV[2];

 

my $sPWD = $ARGV[3];

 

my $sCommand = $ARGV[4];

 

my $sProtocol = "https";

 

my $sMode = "MANAGEMENT_MODE_DEFAULT";

 

 

my $sCert_ids = "vli_cert";

 

my $sFile_names = "/home/vincent/vli_webselfsigncrt.pem"; <==where cert stored in my local linux

 

 

 

if ( ("80" eq $sPort) or ("8080" eq $sPort) )

 

{

 

$sProtocol = "http";

 

}

 

 

if ( ($sHost eq "") or ($sPort eq "") or ($sUID eq "") or ($sPWD eq "") )

 

{

 

&usage();

 

}

 

 

sub usage()

 

{

 

my ($sCmd) = @_;

 

print "Usage: CertAdmin.pl host port uid pwd command [options]\n";

 

print " -----------------------------------------------------------\n";

 

 

if ( ($sCmd eq "") or ($sCmd eq "upload") )

 

{

 

print " upload - upload certificate\n";

 

}

 

if ( ($sCmd eq "") or ($sCmd eq "info") )

 

{

 

print " info - List certificate info\n";

 

}

 

if ( ($sCmd eq "") or ($sCmd eq "version") )

 

{

 

print " version - Gets the version of this interface\n";

 

}

 

exit();

 

}

 

 

 

----------------------------------------------------------------------------

 

Transport Information

 

----------------------------------------------------------------------------

 

sub SOAP::Transport::HTTP::Client::get_basic_credentials

 

{

 

return "$sUID" => "$sPWD";

 

}

 

 

$KeyCertificate = SOAP::Lite

 

-> uri('urn:iControl:Management/KeyCertificate')

 

-> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi");

 

eval { $KeyCertificate->transport->http_request->header

 

(

 

'Authorization' =>

 

'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '')

 

); };

 

 

 

 

if ( $sCommand eq "upload" )

 

{

 

&UPLoadCert($sMode);

 

}

 

elsif ( $sCommand eq "info" )

 

{

 

&GetCertInfo($sMode);;

 

}

 

elsif ( $sCommand eq "version" )

 

{

 

&handle_version();

 

}

 

else

 

{

 

&usage();

 

}

 

 

sub UPLoadCert()

 

{

 

my $mode = (@_);

 

$soapResponse = $KeyCertificate->certificate_import_from_file(

 

SOAP::Data->name(mode => $sMode),

 

SOAP::Data->name(cert_ids => $sCert_ids),

 

SOAP::Data->name(file_names => $sFile_names),

 

SOAP::Data->name(overwrite => 1),

 

);

 

&checkResponse($soapResponse);

 

}

 

 

sub GetCertInfo()

 

{

 

my ($mode) = (@_);

 

$soapResponse = $KeyCertificate->get_certificate_list(

 

SOAP::Data->name(mode => $mode)

 

);

 

............SNIP......

 

}

 

 

so if I run "./CertAdmin.pl host port user pass info", it work fine to list existing cert info

 

but if I run "./CertAdmin host port user pass upload", no errors, but nothing happens to the cert uploading, the function certificate_import_from_file() is bit unclear on where to put the originate certificate, on local box or on bigip.

 

 

Vincent

 

 

8 Replies

  • Hi Vincent,

     

     

    I think the iControl call expects the cert to be stored on the host that the iControl script is running on. If you don't get any useful info from the script when it fails, you could add debug to the script to see where it's failing.

     

     

    Aaron
  • Travis_Collavo_'s avatar
    Travis_Collavo_
    Historic F5 Account
    Hello,

     

     

    Any progress on this one? I can execute the certificate_import_from_file function successfully, but the certificate never shows up in the GUI under File Management. Where does the certificate need to be located when you call the certificate_import_from_file function?

     

     

    Thanks,

     

    Travis
  • Travis_Collavo_'s avatar
    Travis_Collavo_
    Historic F5 Account
    PS - I've tried referencing the local file on my laptop as well as an uploaded copy in /var/tmp and /config/ssl/ssl.crt with no difference in the end result.

     

     

    My code is as follows:

     

     

    $KeyCertificate = &GetInterface("Management/KeyCertificate");

     

     

    sub importCert()

     

    {

     

    my ($cert_id, $fileName) = (@_);

     

     

    print "\nabout to attempt to import cert_id $cert_id, fileName $fileName\n";

     

    $soap_response = $KeyCertificate->certificate_import_from_file

     

    (

     

    SOAP::Data->name(mode => "MANAGEMENT_MODE_DEFAULT"),

     

    SOAP::Data->name(cert_ids => $cert_id),

     

    SOAP::Data->name(file_names => $fileName),

     

    SOAP::Data->name(overwrite => 1)

     

    );

     

     

    if ( $soap_response->fault )

     

    {

     

    print $soap_response->faultcode, " ", $soap_response->faultstring, "\n";

     

    $success = 0;

     

    }

     

    else

     

    {

     

    $success = 1;

     

    }

     

     

    return $success

     

     

    }

     

  • 1) The method expects you to pass an array for the cert_ids and file_names fields

     

     

    you all are sending a single string

     

    my $sCert_ids = "vli_cert";

     

    SOAP::Data->name(cert_ids => $sCert_ids),

     

     

    Ex. it should be something like:

     

     

    my $cert_id = "vli_cert"

     

    my $cert_ids = [ $cert_id ]

     

    SOAP::Data->name(cert_ids => $cert_ids),

     

     

    or for simplicity just put a [ ] around the arguments.

     

     

    SOAP::Data->name(cert_ids => [ $sCert_ids ]),

     

     

    $cert_id

     

     

    2) More importantly, this particular method looks for a file on the bigip itself.

     

     

    If it can find the file locally, it does upload the file into the LTM Certificate Section but seems to ignore the cert_id fields.

     

     

    Ex. if I submit:

     

     

    filename = /var/tmp/pki-2048/bigip/website.pem

     

    cert_id = test-iControl-upload

     

     

    it creates a file called "website.crt"

     

     

    If you want to upload a file to the bigip before "importing" to the LTM Certificate section, you could use something like:

     

     

    https://devcentral.f5.com/wiki/iControl.System__ConfigSync__upload_file.ashx

     

     

     

     

    If you want to upload a file directly from your desktop, I would just use the "certificate_import_from_pem" method which you can garble up the file as one big string:

     

     

    ex.

     

     

    something like:

     

     

    {

     

    local $/=undef;

     

    open FILE, "$sLocalFile" or die "Couldn't open file: $!";

     

    $file_data = ;

     

    close FILE;

     

    }

     

     

    ....

     

     

    {

     

     

    $soapResponse = $KeyCertificate->certificate_import_from_pem(

     

    SOAP::Data->name(mode => $sMode ),

     

    SOAP::Data->name(cert_ids => [ $cert_id ] ),

     

    SOAP::Data->name(pem_data => [ $file_data ] ),

     

    SOAP::Data->name(overwrite => 1 ),

     

    );

     

    &checkResponse($soapResponse);

     

     

    }

     

     

    which does honor the cert_id field coincidently and writes file whatever you provide there.

     

     

     

     

     

     

  • This is what I do.

     

     

    - Read the pem key and pem cert values into strings "cert_pem_data" and "cert_key_data"

     

     

    - Automatically generate an identifier from the certificate subject CN.

     

     

    In Python, it looks something like:

     

     

            derive identifier from cert_pem_data
            log.info("Determining certificate subject CN...")
            x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem_data)
            for component in x509.get_subject().get_components():
                if component[0].lower() == "cn":
                    subject_cn = component[1]
            log.info("CN is \"%s\"." % subject_cn)
            log.debug("Scrubbing subject CN to create certificate/key identifier...")
            identifier = replace_all(subject_cn, {'*': 'wildcard'}).strip()
            log.debug("identifier = %s" % identifier)
     
     - Upload the pem key / cert 
         management_mode_type = b.Management.KeyCertificate.typefactory.create("Management.KeyCertificate.ManagementModeType")
        b.Management.KeyCertificate.certificate_import_from_pem(mode=management_mode_type.MANAGEMENT_MODE_DEFAULT, cert_ids=[identifier], pem_data=[pem_data], overwrite=True)
        time.sleep(3)
        b.Management.KeyCertificate.key_import_from_pem(mode=management_mode_type.MANAGEMENT_MODE_DEFAULT, key_ids=[identifier], pem_data=[pem_data], overwrite=True)
    
    

     

     

    - Notice the "sleep" statement. F5 has some growing pains with their new device sync groups. You will need to insert a sleep between these upload operations or else replication between F5's break.

     

     

    I also have other code which generates the client SSL profile and creates the necessary bundle which includes an intermediate certificate.

     

     

    Hope this helps.
  • Hi,

     

    I am starting to work with iControl to provision/manage ssl certs. Can you please provide your code which generates the client SSL profile/bundle (intermediate cert).

     

    Thank you.

     

    - Spuds23