The NetApp Manageability SDK, or NMSDK, provides resources that you can use to develop applications which monitor and manage NetApp storage systems running ONTAP.  As a long time NetApp Systems Engineer, with an interest in automation, I’ve been using the NMSDK for over a decade.

Despite having some significant experience scripting with the NMSDK, and helping customers do the same, I never was pushed to use anything other than regular old username and password based authentication over HTTPS.  When I was recently asked by a customer to help them avoid storing passwords in their scripts that manage ONTAP systems, I assumed I would quickly find some details on the topic.  What I quickly realized was that our documentation and sample code for this particular aspect of NMSDK integration was difficult to find!

After a bit more digging into various sources, and testing on a lab system, I had it working without too much trouble. Like most things, this is really easy to do once you have seen it happen.  So, let’s get to it!

The first step is to generate a self-signed certificate, using OpenSSL.  In my example, I generate this certificate from a Linux system.  I will point out a few important details about this command:

  • Notice the “-days 1095” argument. 1095 days is 3 years, so you would need to renew this certificate after 3 years.
  • The {COUNTRY}, {STATE}, {CITY}, and {ORG} are all relatively unimportant sections of the -subj
  • The CN={USER} section of the -subj argument is very important! You will need to have a user of the same name configured on your ONTAP cluster (or on a SVM), and the role of this ONTAP user will define what kind of API calls you are allowed to make when authenticated with this certificate.
linux1$ openssl req -x509 -nodes -days 1095 -newkey rsa:2048 -keyout yourKeyFile.key -out yourPemFile.pem \

Now that we have seen the syntax and a bit of explanation to go with it, here is an example of actually running this command.  Note that in this example, my ONTAP user will have to be cert_user.

linux1$ openssl req -x509 -nodes -days 1095 -newkey rsa:2048 -keyout test.key -out test.pem \
-subj "/C=US/ST=NC/L=RTP/O=NetApp/CN=cert_user"
Generating a 2048 bit RSA private key
writing new private key to 'test.key'

OK, we have our certificate and key file created, let’s get ONTAP configured.  The commands below show the syntax for making this happen. Again, take special note of the {USER} argument in the security login create command.

cluster1:: security certificate install -type client-ca -vserver {VSERVER}
 --- Cut and paste the cert including BEGIN and END statements from yourPemFile.pem ---
cluster1:: security ssl modify -vserver {VSERVER} -client-enabled true
cluster1:: security login create -user-or-group-name {USER} -application ontapi -authmethod cert \
-role {ROLE} -vserver {VSERVER}

Again, now that we have seen the syntax, let’s take a look at an actual example of making this happen.  As you would expect, I’m using the cert_user account, and in my example I’m giving full admin privileges to this user.  You can create a different role for your user if so required.  You can also configure your role, user, and certificate for a SVM other than the main cluster management SVM, if that meets your needs.

cluster1:: security certificate install -type client-ca -vserver cluster1

Please enter Certificate: Press enter when done

You should keep a copy of the CA-signed digital certificate for future reference.
cluster1:: security ssl modify -vserver cluster1 -client-enabled true
cluster1:: security login create -user-or-group-name cert_user -application ontapi -authmethod cert \
-role admin -vserver cluster1

That’s it!  OK, we are done with configuration, how about some sample code that uses the NMSDK to leverage our new certificate based authentication.  First, a very simple snippet of Python code that leverages this authentication model.

#!/usr/bin/env python

import sys
from NaServer import *

cluster = "cluster1"
transport = "HTTPS"
port = 443
cert = "test.pem"
key = "test.key"

s = NaServer(cluster, 1, 30)
s.set_client_cert_and_key(cert, key)

api = NaElement("system-get-version")
output = s.invoke_elem(api)
if (output.results_status() == "failed"):
    r = output.results_reason()
    print("Failed: " + str(r))

ontap_version = output.child_get_string("version")
print ("V: " + ontap_version)

How about another very simple example, this time with Perl.

#!/usr/bin/perl -w

use lib 'NMSDK';
use NaServer;

$cluster = "cluster1";
$transport = "HTTPS";
$port = 443;
$style = "CERTIFICATE";
$cert = "test.pem";
$key = "test.key";

$server = new NaServer($cluster, 1, 30);
$server->set_client_cert_and_key($cert, $key);

$output = $server->invoke('system-get-version');
if ($output->results_status() eq "failed") {
    die "Error: ", $output->results_reason();

$version = $output->child_get_string('version');
print "V: $version\n";

That’s it!  One last note here – if you configured your certificate and user in ONTAP as part of a data SVM, instead of as part of the main cluster management SVM, you would connect to a management LIF on that particular SVM via the cluster variable that is used when creating the NaServer object in the above scripts.  Hit me up in the comments if you have any questions or have problems getting this to work.

Pin It on Pinterest