Add support for Generate Certificate Signing Request(CSR)

Redfish supports generating CSR, added support for the same

Tested:
-------OP930-------
bash-4.2$ python python openbmctool.py -H $BMC_IP -U rrr -P pppp certificate
generatecsr server NJ w3.ibm.com US IBM IBM-UNIT NY EC 2048 prime256v1 cp
abc.com an.com,bm.com gn sn un in ClientAuthentication,CodeSigning

Attempting login...
Not supported
User bbbb has been logged out

-------OP940-------
bash-4.2$ python openbmctool.py -H $BMC_IP -U uuu -P ppp certificate generatecsr server NJ w3.ibm.com US IBM IBM-UNIT NY EC 2048 prime256v1 cp abc.com an.com,bm.com gn sn un in ClientAuthentication,CodeSigning
Attempting login...
Generating CSR url=/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/
GenerateCSR complete.
{
  "CSRString": "-----BEGIN CERTIFICATE REQUEST-----\nMIIByzCCAXICAQEwggEOMQ8wDQYDVR0RDAZhbi5jb20xDzANBgNVHREMBmJtLmNv\nbTELMAkGA1UEBwwCTkoxEzARBgNVBAMMCnczLmlibS5jb20xCzAJBgNVBCkMAmNw\nMQswCQYDVQQGEwJVUzEWMBQGCSqGSIb3DQEJARYHYWJjLmNvbTELMAkGA1UEKgwC\nZ24xCzAJBgNVBCsMAmluMQwwCgYEKw4DAgwCRUMxHTAbBgNVHQ8MFENsaWVudEF1\ndGhlbnRpY2F0aW9uMRQwEgYDVR0PDAtDb2RlU2lnbmluZzEMMAoGA1UECgwDSUJN\nMQswCQYDVQQIDAJOWTELMAkGA1UEBAwCc24xETAPBgkqhkiG9w0BCQIMAnVuMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9Rt+I8tkTneN+5w+Ln5YgrIlvjEVPFcI\nazDzmxgjL6jtaeDcha9cYtj/7VXA67WSp9odVGWhAgM61LMpP3DcNKAAMAoGCCqG\nSM49BAMCA0cAMEQCIDpPzyNqhoRCYHIXxbTaynQ/ac2Oa3zff2G5HBdqx+eBAiAZ\nl+O7TAYxr+UzbbgSWEARuc5Kc7c4xLwldtecwxPbRg==\n-----END CERTIFICATE REQUEST-----\n",
  "CertificateCollection": {
    "@odata.id": "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
  }
}
User root has been logged out

bash-4.2$ python openbmctool.py -H $BMC_IP -U uuuu -P pppp certificate generatecsr --help
usage: openbmctool.py certificate generatecsr [-h]
                                              {server,client,authority} city
                                              commonName country organization
                                              organizationUnit state {RSA,EC}
                                              {2048} keyCurveId contactPerson
                                              email alternativeNames givenname
                                              surname unstructuredname
                                              initials keyUsage

positional arguments:
  {server,client,authority}
                        Generate CSR
  city                  The city or locality of the organization making the
                        request
  commonName            The fully qualified domain name of the component that
                        is being secured.
  country               The country of the organization making the request
  organization          The name of the organization making the request.
  organizationUnit      The name of the unit or division of the organization
                        making the request.
  state                 The state, province, or region of the organization
                        making the request.
  {RSA,EC}              The type of key pair for use with signing algorithms.
  {2048}                The length of the key in bits, if needed based on the
                        value of the 'KeyPairAlgorithm' parameter.
  keyCurveId            The curve ID to be used with the key, if needed based
                        on the value of the 'KeyPairAlgorithm' parameter.
  contactPerson         The name of the user making the request
  email                 The email address of the contact within the
                        organization
  alternativeNames      Additional hostnames of the component that is being
                        secured
  givenname             The given name of the user making the request
  surname               The surname of the user making the request
  unstructuredname      he unstructured name of the subject
  initials              The initials of the user making the request
  keyUsage              The usage of the key contained in the certificate

optional arguments:
  -h, --help            show this help message and exit

Signed-off-by: Marri Devender Rao <devenrao@in.ibm.com>
Change-Id: I12c0a1311e233a238806f500fd97048780f0e0c1
diff --git a/thalerj/openbmctool.py b/thalerj/openbmctool.py
index 25456bb..4077ebe 100755
--- a/thalerj/openbmctool.py
+++ b/thalerj/openbmctool.py
@@ -2716,6 +2716,58 @@
         print("List certificates complete.")
     return resp.text
 
+def certificateGenerateCSR(host, args, session):
+    """
+        Called by certificate management function. Generate CSR for server/
+        client certificates
+        Example:
+        certificate generatecsr server NJ w3.ibm.com US IBM IBM-UNIT NY EC 2048 prime256v1 cp abc.com an.com,bm.com gn sn un in ClientAuthentication,CodeSigning
+        certificate generatecsr client NJ w3.ibm.com US IBM IBM-UNIT NY EC 2048 prime256v1 cp abc.com an.com,bm.com gn sn un in ClientAuthentication,CodeSigning
+        @param host: string, the hostname or IP address of the bmc
+        @param args: contains additional arguments used by the certificate replace sub command
+        @param session: the active session to use
+    """
+    if not redfishSupportPresent(host, session):
+        return "Not supported";
+
+    httpHeader = {'Content-Type': 'application/octet-stream'}
+    httpHeader.update(xAuthHeader)
+    url = "";
+    if(args.type.lower() == 'server'):
+        url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
+    elif(args.type.lower() == 'client'):
+        url = "/redfish/v1/AccountService/LDAP/Certificates/"
+    elif(args.type.lower() == 'authority'):
+        url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
+    print("Generating CSR url=" + url)
+    generateCSRUrl = "https://" + host + \
+        "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
+    try:
+        usage_list = args.keyUsage.split(",")
+        alt_name_list = args.alternativeNames.split(",")
+        data ={"CertificateCollection":{"@odata.id":url},
+            "CommonName":args.commonName, "City":args.city,
+            "Country":args.country, "Organization":args.organization,
+            "OrganizationalUnit":args.organizationUnit, "State":args.state,
+            "KeyPairAlgorithm":args.keyPairAlgorithm,
+            "KeyBitLength":int(args.keyBitLength), "KeyCurveId":args.keyCurveId,
+            "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
+            "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
+            "KeyUsage":usage_list, "Surname":args.surname,
+            "UnstructuredName":args.unstructuredname}
+        resp = session.post(generateCSRUrl, headers=httpHeader,
+            json=data, verify=False)
+    except(requests.exceptions.Timeout):
+        return(connectionErrHandler(args.json, "Timeout", None))
+    except(requests.exceptions.ConnectionError) as err:
+        return connectionErrHandler(args.json, "ConnectionError", err)
+    if resp.status_code != 200:
+        print(resp.text)
+        return "Failed to generate CSR"
+    else:
+        print("GenerateCSR complete.")
+    return resp.text
+
 def enableLDAP(host, args, session):
     """
          Called by the ldap function. Configures LDAP.
@@ -4060,6 +4112,45 @@
         help="Certificate list")
     certList.set_defaults(func=certificateList)
 
+    certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
+    certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
+        help="Generate CSR")
+    certGenerateCSR.add_argument('city',
+        help="The city or locality of the organization making the request")
+    certGenerateCSR.add_argument('commonName',
+        help="The fully qualified domain name of the component that is being secured.")
+    certGenerateCSR.add_argument('country',
+        help="The country of the organization making the request")
+    certGenerateCSR.add_argument('organization',
+        help="The name of the organization making the request.")
+    certGenerateCSR.add_argument('organizationUnit',
+        help="The name of the unit or division of the organization making the request.")
+    certGenerateCSR.add_argument('state',
+        help="The state, province, or region of the organization making the request.")
+    certGenerateCSR.add_argument('keyPairAlgorithm',  choices=['RSA', 'EC'],
+        help="The type of key pair for use with signing algorithms.")
+    certGenerateCSR.add_argument('keyBitLength', choices=['2048'],
+        help="The length of the key in bits, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
+    certGenerateCSR.add_argument('keyCurveId',
+        help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
+    certGenerateCSR.add_argument('contactPerson',
+        help="The name of the user making the request")
+    certGenerateCSR.add_argument('email',
+        help="The email address of the contact within the organization")
+    certGenerateCSR.add_argument('alternativeNames',
+        help="Additional hostnames of the component that is being secured")
+    certGenerateCSR.add_argument('givenname',
+        help="The given name of the user making the request")
+    certGenerateCSR.add_argument('surname',
+        help="The surname of the user making the request")
+    certGenerateCSR.add_argument('unstructuredname',
+        help="he unstructured name of the subject")
+    certGenerateCSR.add_argument('initials',
+        help="The initials of the user making the request")
+    certGenerateCSR.add_argument('keyUsage', help="The usage of the key contained in the certificate")
+
+    certGenerateCSR.set_defaults(func=certificateGenerateCSR)
+
     # local users
     parser_users = subparsers.add_parser("local_users", help="Work with local users")
     parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")