ONTAP Rest API Discussions
ONTAP Rest API Discussions
Hi,
I am trying to understand if we can use cert as authentication process instead of password for REST APIs access
I checked the API document and all I can see is password based authentication only (below content is from API documentation)
#####################################
HTTP authentication Process for REST API:-
At an HTTP level, basic authentication is used for the API transactions. An HTTP header with the user name and password in a base64 string is added to each request
curl -X GET -u username:password -k 'https://<ip_address>/api/cluster? fields=version'
#####################################
Any idea if we can use purely use certs for authentication, basically I am trying to implement password less authentication. Kindly let me know, Thanks.
Thanks,
-Srini
Solved! See The Solution
Not having an intermediate CA is not a problem; it's not required.
For your last post, that would be expected. The server cert is what is sent for the client to validate the server identity. This is the same function as the certificate that you would get from going to https://google.com, for example. You local machine checks the root CA provided in that certificate and makes sure it trusts it. Passing -k to curl makes curl skip this trust check.
Right now we're trying to deal with the certificate validation going in the other way. That is, the client is sending the server a certificate and the server must declare if it trusts the root that signed it as well as the contents of it, which is where the failure is happening (the 401).
I'm not too sure what the remaining issue might be. I may have to tap out here and suggest that you open a ticket with support who may have more experience in getting this to work. If you do find the solution though, I wouldn't mind hearing what it was.
Yes, you can use certificate/key authentication with the rest API. Here's a basic workflow for it:
================================================================================
= As the administrative account, create a new root_ca certificate which will be
= used to sign all certificate requests for the user accounts you'd like to be
= able to authenticate
================================================================================
cycrh6rtp20:~/$ curl -iku admin -X POST -d '{"type": "root_ca", "common_name": "MyCompany", "expiry_time": "3652days"}' https://<cluster_mgmt>/api/security/certificates
Enter host password for user 'admin':
HTTP/1.1 201 Created
Date: Fri, 02 Oct 2020 10:07:54 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Location: /api/security/certificates/23c38b55-0497-11eb-b855-005056bb97cc
Content-Length: 3
Content-Type: application/hal+json
{
}cycrh6rtp20:~/$
================================================================================
= Create a certificate signing request for the user that you want. The common_name
= in the request must match the username in ONTAP
================================================================================
cycrh6rtp20:~/$ openssl genrsa -out cert_user.key 2048
Generating RSA private key, 2048 bit long modulus
..................+++
................................................................................................+++
e is 65537 (0x10001)
cycrh6rtp20:~/$ openssl req -sha256 -new -nodes -key cert_user.key -subj /C=US/ST=PA/L=Pittsburgh/O=MyCompany/OU=BestPart/CN=ricky_bobby -out cert_user.csr
cycrh6rtp20:~/$
================================================================================
= Have ONTAP sign the certificate request with the root CA we created earlier
= and save the response to a file
================================================================================
cycrh6rtp20:~/$ curl -iku admin -X POST -d '{"signing_request": "-----BEGIN CERTIFICATE REQUEST-----
MIICsTCCAZkCAQAwbDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlBBMRMwEQYDVQQH
DApQaXR0c2J1cmdoMRIwEAYDVQQKDAlNeUNvbXBhbnkxETAPBgNVBAsMCEJlc3RQ
YXJ0MRQwEgYDVQQDDAtyaWNreV9ib2JieTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAL49TSzQTP3CaBKz461n1UGdiculboS+e76sBbjNVl58mO0qsREi
V8WNSNblZbJGbkz4rotUO4YQIizs0w7iMyQaEgZbysBYG4OXYW6duZg/kCkbpchz
vI/q+Uqbg5WAbS2DyPx0GhfUpxnld2NVoH1yBFG8auJZ7Z2UVkpeFouyfOy6JQAz
oF8fnHCENN7Wh7HlYF0I+mf9KW2HN5790TbgLx6Yaz4uiQ+eK/vWgGFJjTi5Am/x
FbNLnafTL5o6mk9WhqJamYLhxm2FY04Z0RvHtPC5i/30qj8MrfvmI144RvIuBPUz
vyvRv9JzRxfo6C6PCj2XDdWMWVtAJikOXa8CAwEAAaAAMA0GCSqGSIb3DQEBCwUA
A4IBAQB2oMYRhiemhZq5RdtekDKDh6C7QiRclmJUZQuOB9Dac9pwJO/oSC0+668I
TTCdLY+L7YQ96V2X34Pau0HzIiPlxyJm6ZzNf9pXBIeJWwzdG5/LXTQqg/LlT1Rl
utBwemSuBSQdij1EEEpuY+vHkftDTQMkgkOWB5EWlTzzVQzswIFbES/IOyxBY7s9
WD3d/GAD/UHBX5uKYvvm3WKJrf5UifPUJBqm+BjK1qcseCyNFpurRxwUKyjerI0W
oRdRtdjYM7wYZyvT9YlKBUcvNMmkIw0LIFwVhk2hBXM2+BJtGfdeHyFfOujjdRkh
ncnwe1Sy2w8Mi/I6aAh6sM6QtWv5
-----END CERTIFICATE REQUEST-----"}' https://<cluster_mgmt>/api/security/certificates/23c38b55-0497-11eb-b855-005056bb97cc/sign
Enter host password for user 'admin':
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Date: Fri, 02 Oct 2020 10:15:58 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Content-Length: 1274
Content-Type: application/hal+json
{
"public_certificate": "-----BEGIN CERTIFICATE-----\nMIIDXDCCAkSgAwIBAgIIFjolasqTdLgwDQYJKoZIhvcNAQELBQAwITESMBAGA1UE\nAxMJTXlDb21wYW55MQswCQYDVQQGEwJVUzAeFw0yMDEwMDIxMDE1NThaFw0yMTEw\nMDIxMDE1NThaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJQQTETMBEGA1UEBwwK\nUGl0dHNidXJnaDESMBAGA1UECgwJTXlDb21wYW55MREwDwYDVQQLDAhCZXN0UGFy\ndDEUMBIGA1UEAwwLcmlja3lfYm9iYnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\nggEKAoIBAQC+PU0s0Ez9wmgSs+OtZ9VBnYnLpW6Evnu+rAW4zVZefJjtKrERIlfF\njUjW5WWyRm5M+K6LVDuGECIs7NMO4jMkGhIGW8rAWBuDl2FunbmYP5ApG6XIc7yP\n6vlKm4OVgG0tg8j8dBoX1KcZ5XdjVaB9cgRRvGriWe2dlFZKXhaLsnzsuiUAM6Bf\nH5xwhDTe1oex5WBdCPpn/Slthzee/dE24C8emGs+LokPniv71oBhSY04uQJv8RWz\nS52n0y+aOppPVoaiWpmC4cZthWNOGdEbx7TwuYv99Ko/DK375iNeOEbyLgT1M78r\n0b/Sc0cX6Ogujwo9lw3VjFlbQCYpDl2vAgMBAAGjTTBLMAkGA1UdEwQCMAAwHQYD\nVR0OBBYEFBiErwnY2ZaAEuzX/ggjHJ9JMN+bMB8GA1UdIwQYMBaAFAldpMFmjRvm\nPlhx0COQtmtMB/K2MA0GCSqGSIb3DQEBCwUAA4IBAQDBJ3iYfOf5zHj1duych9Z8\nN2S4CJJqUrzYGuP7h+0nQK1wM3QnzUZGuv2h60kZ5lNItS0RbpWxViZNPuFfMvsC\n0hP6M1eLIXl39N1U6c/T4KOUZBOwW50kRLp5jJycMTNLrbE+g+43JbP94Y5f/JN4\n/HdwXnodCFslPSHj+x/5IFLTL6aCBD0b+6DW5DYHd6jORxN0xYlEzI5SxKdRlbAp\nBpJYEUZg1DK84Ojb9fuLOUeFvFA4oSpoH/nbqtGlGmODrzzZTZs8IU9/C4kXC/qC\n37fjbviTn/aQbMxIpW3jfAWsVcMohvfL+lUnZ8hmtZDXLuxvFu3C/MHLIuUuTX2x\n-----END CERTIFICATE-----\n"
}cycrh6rtp20:~/$ echo -e "-----BEGIN CERTIFICATE-----\nMIIDXDCCAkSgAwIBAgIIFjolasqTdLgwDQYJKoZIhvcNAQELBQAwITESMBAGA1UE\nAxMJTXlDb21wYW55MQswCQYDVQQGEwJVUzAeFw0yMDEwMDIxMDE1NThaFw0yMTEw\nMDIxMDE1NThaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJQQTETMBEGA1UEBwwK\nUGl0dHNidXJnaDESMBAGAUECgwJTXlDb21wYW55MREwDwYDVQQLDAhCZXN0UGFy\ndDEUMBIGA1UEAwwLcmlja3lfYm9iYnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\nggEKAoIBAQC+PU0s0Ez9wmgSs+OtZ9VBnYnLpW6Evnu+rAW4zVZefJjtKrERIlfF\njUjW5WWyRm5M+K6LVDuGECIs7NMO4jMkGhIGW8rAWBuDl2FunbmYP5ApG6XIc7yP\n6vlKm4OVgG0tg8j8dBoX1KcZ5XdjVaB9cgRRvGriWe2dlFZKXhaLsnzsuiUAM6Bf\nH5xwhDTe1oex5WBdCPpn/Slthzee/dE24C8emGs+LokPniv71oBhSY04uQJv8RWz\nS52n0y+aOppPVoaiWpmC4cZthWNOGdEbx7TwuYv99Ko/DK375iNeOEbyLgT1M78r\n0b/Sc0cX6Ogujwo9lw3VjFlbQCYpDl2vAgMBAAGjTTBLMAkGA1UdEwQCMAAwHQYD\nVR0OBBYEFBiErwnY2ZaAEuzX/ggjHJ9JMN+bMB8GA1UdIwQYMBaAFAldpMFmjRvm\nPlhx0COQtmtMB/K2MA0GCSqGSIb3DQEBCwUAA4IBAQDBJ3iYfOf5zHj1duych9Z8\nN2S4CJJqUrzYGuP7h+0nQK1wM3QnzUZGuv2h60kZ5lNItS0RbpWxViZNPuFfMvsC\n0hP6M1eLIXl39N1U6c/T4KOUZBOwW50kRLp5jJycMTNLrbE+g+43JbP94Y5f/JN4\n/HdwXnodCFslPSHj+x/5IFLTL6aCBD0b+6DW5DYHd6jORxN0xYlEzI5SxKdRlbAp\nBpJYEUZg1DK84Ojb9fuLOUeFvFA4oSpoH/nbqtGlGmODrzzZTZs8IU9/C4kXC/qC\n37fjbviTn/aQbMxIpW3jfAWsVcMohvfL+lUnZ8hmtZDXLuxvFu3C/MHLIuUuTX2x\n-----END CERTIFICATE-----\n" > cert_user.crt
cycrh6rtp20:~/$
================================================================================
= Create a user account in ONTAP with a username matching our certificate's
= common name
================================================================================
cycrh6rtp20:~/$ curl -iku admin -X POST -d '{"name": "ricky_bobby", "applications": [{"application": "http", "authentication_methods": ["cert"]}]}' https://<cluster_mgmt>/api/security/accounts
Enter host password for user 'admin':
HTTP/1.1 201 Created
Date: Fri, 02 Oct 2020 10:19:34 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Location: /api/security/accounts/2327973e-ff18-11ea-9dc7-005056bb97cc/ricky_bobby
Content-Length: 3
Content-Type: application/hal+json
{
}cycrh6rtp20:~/$
================================================================================
= Now we can authenticate to the API as our user by passing our certificate and key
================================================================================
cycrh6rtp20:~/$ curl -ik --cert cert_user.crt --key cert_user.key https://<cluster_mgmt>/api/cluster?fields=version
HTTP/1.1 200 OK
Date: Fri, 02 Oct 2020 10:20:37 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Content-Length: 221
Content-Type: application/hal+json
{
"version": {
"full": "NetApp Release Cloudwalker__9.9.0: Mon Sep 28 12:10:37 UTC 2020",
"generation": 9,
"major": 9,
"minor": 0
},
"_links": {
"self": {
"href": "/api/cluster"
}
}
}cycrh6rtp20:~/$
================================================================================
= If you want to limit the scope of the user and what they can do, you can change
= the user's role from admin to something custom that has only the permissions
= you want
================================================================================
cycrh6rtp20:~/$ curl -iku admin -X POST -d '{"name": "volume_reader", "privileges": [{"access": "readonly", "path": "/api/storage/volumes"}]}' https://<cluster_mgmt>/api/security/roles
Enter host password for user 'admin':
HTTP/1.1 201 Created
Date: Fri, 02 Oct 2020 10:25:52 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Location: /api/security/roles/2327973e-ff18-11ea-9dc7-005056bb97cc/volume_reader
Content-Length: 3
Content-Type: application/hal+json
{
}cycrh6rtp20:~/$
cycrh6rtp20:~/$ curl -iku admin -X PATCH -d '{"role": {"name": "volume_reader"}}' https://<cluster_mgmt>/api/security/accounts/2327973e-ff18-11ea-9dc7-005056bb97cc/ricky_bobby
Enter host password for user 'admin':
HTTP/1.1 200 OK
Date: Fri, 02 Oct 2020 10:26:50 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Content-Length: 3
Content-Type: application/hal+json
{
}cycrh6rtp20:~/$
================================================================================
= Now our previous cluster API call will fail, but we can still get a list of
= volumes from the API
================================================================================
cycrh6rtp20:~/$ curl -ik --cert cert_user.crt --key cert_user.key https://<cluster_mgmt>/api/cluster?fields=version
HTTP/1.1 403 Forbidden
Date: Fri, 02 Oct 2020 10:27:30 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Content-Length: 86
Content-Type: application/hal+json
{
"error": {
"message": "not authorized for that command",
"code": "6"
}
}cycrh6rtp20:~/$ curl -ik --cert cert_user.crt --key cert_user.key https://<cluster_mgmt>/api/storage/volumes?return_records=false
HTTP/1.1 200 OK
Date: Fri, 02 Oct 2020 10:27:58 GMT
Server: libzapid-httpd
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
Content-Length: 119
Content-Type: application/hal+json
{
"num_records": 5,
"_links": {
"self": {
"href": "/api/storage/volumes?return_records=false"
}
}
}cycrh6rtp20:~/$
Thank you very much Robert for swift response with detailed info.
I tried executing the posted procedure , unfortunately its giving error, I see authorization error, please see below.
HTTP/1.1 401 Unauthorized
Date: Fri, 02 Oct 2020 14:10:58 GMT
Server: Apache
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
WWW-Authenticate: Basic realm="ONTAP"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
</body></html>
Not sure what's the issue, I have also tried executing all cert commands directly on storage but no luck, same error with this process as well
Here is what I have followed manually
1)Created root CA
2)Generated SSL certificate
3)Signed the generated SSL certificate by root CA cert
4)Installed CA signed certificate with type "server"
5)while accessing API, provided CA signed Cert and Private key details
Any idea what could be the issue here, thanks - Srini
I don't think you need/want to install the certificate that you had signed back on the cluster. That is only needed on the client side. The important parts of that are that it is signed by a CA that is installed on the cluster and that the common name in that certificate matches the username of the account that you want to authenticate as.
You didn't mention any details about the user you are trying to authenticate as. But make sure that account has the http application and cert authentication method enabled. That is also required and not mentioned in your steps below.
Hi Robert,
Thank you for clarifying on certs stuff.
Yeah, the account I used is matching with the common name used for the cert, please see details below
Second
User/Group Authentication Acct Authentication
Name Application Method Role Name Locked Method
-------------- ----------- ------------- ---------------- ------ --------------
apiread http cert admin - none
This is the command I used to create this account
curl -iku admin -X POST -d '{"name": "apiread", "applications": [{"application": "http", "authentication_methods": ["cert"]}]}' https://<cdotname>/api/security/accounts
And please see below command which I executed for cert
openssl req -sha256 -new -nodes -key cert_user.key -subj /C=IE/ST=""/L=Dublin/O=<mycompany>/OU=BestPart/CN=apiread -out cert_user.csr
Kindly advise.
Thanks,
-Srini
Was the root CA that you created in step one installed on the cluster (type root_ca)? If not, I think that would cause the issue as well since the cluster wouldn't have a CA available by which to verify the certificate that curl is providing.
Hi Robert,
Thank you for checking and responding on this.
Yeah, I verified it and see that root CA exists fine, please see below
###Replaced actual values with dummy value for security reasons###
Vserver Serial Number Certificate Name Type
---------- --------------- -------------------------------------- ------------
<adminSVMname>
<Serialno>
<CertName>
root-ca
Certificate Authority: <CA>
Expiration Date: Wed Oct 02 13:55:51 2030
I am wondering with this process, we were able to create root-ca and signed cert however intermediate cert is not there here.
Any idea if that is causing the issue because what is understand is, always cert verification starts with low level signed- cert>intermediate cert>root cert
Also tried by providing root CA cert to the command using switch "--cacert" (this has root ca cert value) as shown below however no luck( its giving same unauthorized error)
curl -ik --cacert cert_user_ca.crt --cert cert_user.crt --key cert_user.key https://<adminsvmname>/api/cluster?fields=version
***Error Details***
HTTP/1.1 401 Unauthorized
Date: Sat, 03 Oct 2020 07:13:34 GMT
Server: Apache
X-Content-Type-Options: nosniff
Cache-Control: no-cache,no-store,must-revalidate
WWW-Authenticate: Basic realm="ONTAP"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
</body></html>
*******************************************
Hi Robert,
I think I found the problem, I ran the command in verbose mode and see that it is checking "server" cert instead of "root-ca" cert, I have two certs with same common name (server and root-ca), Kindly review this and advise.Thanks
Please see below verbose o/p
* About to connect() to <adminsvmname> port 443 (#0)
* Trying xxx.xx.xxx.xx...
* Connected to <adminsvmname> (xxx.xx.xxx.xx) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: --------------------------------------> This is Server cert, looks like it is validating against this instead of root-CA-cert
* subject: C=US,CN=<adminsvmname>
* start date: Oct 03 08:04:42 2020 GMT
* expire date: Oct 03 08:04:42 2021 GMT
* common name: <adminsvmname>
* issuer: C=US,CN=<adminsvmname>
> GET /api/cluster?fields=version HTTP/1.1
> User-Agent: curl/7.29.0
> Host: <adminsvmname>
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
HTTP/1.1 401 Unauthorized
< Date: Sat, 03 Oct 2020 08:07:11 GMT
Date: Sat, 03 Oct 2020 08:07:11 GMT
< Server: Apache
Server: Apache
< X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
< Cache-Control: no-cache,no-store,must-revalidate
Cache-Control: no-cache,no-store,must-revalidate
< WWW-Authenticate: Basic realm="ONTAP"
WWW-Authenticate: Basic realm="ONTAP"
< Content-Length: 381
Content-Length: 381
< Content-Type: text/html; charset=iso-8859-1
Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
</body></html>
* Connection #0 to host <adminsvmname> left intact
Not having an intermediate CA is not a problem; it's not required.
For your last post, that would be expected. The server cert is what is sent for the client to validate the server identity. This is the same function as the certificate that you would get from going to https://google.com, for example. You local machine checks the root CA provided in that certificate and makes sure it trusts it. Passing -k to curl makes curl skip this trust check.
Right now we're trying to deal with the certificate validation going in the other way. That is, the client is sending the server a certificate and the server must declare if it trusts the root that signed it as well as the contents of it, which is where the failure is happening (the 401).
I'm not too sure what the remaining issue might be. I may have to tap out here and suggest that you open a ticket with support who may have more experience in getting this to work. If you do find the solution though, I wouldn't mind hearing what it was.