Cisco APIC Security Configuration Guide, Release 6.2(x)

PDF

Cisco APIC Security Configuration Guide, Release 6.2(x)

Generate an X.509 certificate and a private key

Want to summarize with AI?

Log in

Configure X.509 certificate and private key generation using OpenSSL commands for secure authentication.


Generate an X.509 certificate and private key to enable secure authentication. The certificate will be added to the user's profile on the APIC for signature verification, while the private key is used by the client to generate signatures.

X.509 certificates contain public keys used for signature verification, while private keys must be kept secure and are never stored on the APIC. This process creates both components needed for certificate-based authentication.

Procedure

  1. Enter an OpenSSL command to generate an X.509 certificate and private key.

    Example:

    $ openssl req -new -newkey rsa:1024 -days 36500 -nodes -x509 -keyout userabc.key -out userabc.crt -subj '/CN=User ABC/O=Cisco Systems/C=US'
    Note
    • Once the X.509 certificate is generated, it will be added to the users profile on the APIC, and it is used to verify signatures. The private key is used by the client to generate the signatures.

    • The certificate contains a public key but not the private key. The public key is the primary information used by the APIC to verify the calculated signature. The private key is never stored on the APIC. You must keep it secret.

  2. Display the fields in the certificate using OpenSSL.

    Example:

    $ openssl x509 -text -in userabc.crt
            Certificate:
                Data:
                    Version: 3 (0x2)
                    Serial Number:
                        c4:27:6c:4d:69:7c:d2:b6
                    Signature Algorithm: sha1WithRSAEncryption
                    Issuer: CN=User ABC, O=Cisco Systems, C=US
                    Validity
                        Not Before: Jan 12 16:36:14 2015 GMT
                        Not After : Dec 19 16:36:14 2114 GMT
                    Subject: CN=User ABC, O=Cisco Systems, C=US
                    Subject Public Key Info:
                        Public Key Algorithm: rsaEncryption
                        RSA Public Key: (1024 bit)
                            Modulus (1024 bit):
                                00:92:35:12:cd:2b:78:ef:9d:ca:0e:11:77:77:3a:
                                99:d3:25:42:94:b5:3e:8a:32:55:ce:e9:21:2a:ff:
                                e0:e4:22:58:6d:40:98:b1:0d:42:21:db:cd:44:26:
                                50:77:e5:fa:b6:10:57:d1:ec:95:e9:86:d7:3c:99:
                                ce:c4:7f:61:1d:3c:9e:ae:d8:88:be:80:a0:4a:90:
                                d2:22:e9:1b:25:27:cd:7d:f3:a5:8f:cf:16:a8:e1:
                                3a:3f:68:0b:9c:7c:cb:70:b9:c7:3f:e8:db:85:d8:
                                98:f6:e3:70:4e:47:e2:59:03:49:01:83:8e:50:4a:
                                5f:bc:35:d2:b1:07:be:ec:e1
                            Exponent: 65537 (0x10001)
                    X509v3 extensions:
                        X509v3 Subject Key Identifier:
                            0B:E4:11:C7:23:46:10:4F:D1:10:4C:C1:58:C2:1E:18:E8:6D:85:34
                        X509v3 Authority Key Identifier:
                            keyid:0B:E4:11:C7:23:46:10:4F:D1:10:4C:C1:58:C2:1E:18:E8:6D:85:34
                            DirName:/CN=User ABC/O=Cisco Systems/C=US
                            serial:C4:27:6C:4D:69:7C:D2:B6
            
                        X509v3 Basic Constraints:
                            CA:TRUE
                Signature Algorithm: sha1WithRSAEncryption
                    8f:c4:9f:84:06:30:59:0c:d2:8a:09:96:a2:69:3d:cf:ef:79:
                    91:ea:cd:ae:80:16:df:16:31:3b:69:89:f7:5a:24:1f:fd:9f:
                    d1:d9:b2:02:41:01:b9:e9:8d:da:a8:4c:1e:e5:9b:3e:1d:65:
                    84:ff:e8:ad:55:3e:90:a0:a2:fb:3e:3e:ef:c2:11:3d:1b:e6:
                    f4:5e:d2:92:e8:24:61:43:59:ec:ea:d2:bb:c9:9a:7a:04:91:
                    8e:91:bb:9d:33:d4:28:b5:13:ce:dc:fe:c3:e5:33:97:5d:37:
                    cc:5f:ad:af:5a:aa:f4:a3:a8:50:66:7d:f4:fb:78:72:9d:56:
                    91:2c
            [snip]
    

You have successfully generated an X.509 certificate and private key pair. The certificate file contains the public key and certificate information, while the private key file contains the secret key for generating signatures.


Create a local user and add a user certificate using the GUI

This task creates a local user account with authentication credentials and associates an X.509 certificate for certificate-based authentication through the GUI.

Local users provide direct authentication to the system without requiring external authentication servers. Adding user certificates enables certificate-based authentication as an alternative to password-based login.

Procedure

  1. On the menu bar, choose ADMIN > AAA.

  2. In the Navigation pane, click Users and Local Users in the Work pane.

  3. In the Work pane, verify that you in the Local Users tab.

    The ADMIN user is present by default

  4. In the Work pane, click on task icon drop-down list and select Create Local User.

  5. In the Security dialog box, choose the desired security domain for the user, and click Next.

  6. In the Roles dialog box, click the radio buttons to choose the roles for your user, and click Next.

    You can provide read-only or read/write privileges.

  7. In the User Identity dialog box, perform the following actions:

    1. In the Login ID field, add an ID.
    2. In the Password field, enter the password.
    3. In the Confirm Password field, confirm the password.
    4. (Optional) For Certificate based authentication, in the User Certificate Attribute field, enter the user identity from the authentication certificate.
    5. Click Finish.
  8. In the Navigation pane, click the name of the user that you created. In the Work pane, expand the + sign next to your user in the Security Domains area.

    The access privileges for your user are displayed.
  9. In the Work pane, in the User Certificates area, click the user certificates + sign, and in the Create X509 Certificate dialog box, perform the following actions:

    1. In the Name field, enter a certificate name.
    2. In the Data field, enter the user certificate details.
    3. Click Submit.
    The X509 certificate is created for the local user.

A local user account is created with the specified credentials and security domain access. The X.509 certificate is associated with the user for certificate-based authentication.


Create a local user and add a user certificate using the REST API

This task creates a local user account with personal details and associates a user certificate for secure authentication purposes.

Use this procedure when you need to establish a local user account with certificate-based authentication and assign multiple user roles for access privileges.

Procedure

Create a local user and add a user certificate.

Example:

method: POST
        url: http://apic/api/node/mo/uni/userext/user-userabc.json
        payload:
        {
            "aaaUser": {
                "attributes": {
                    "name": "userabc",
                    "firstName": "Adam",
                    "lastName": "BC",
                    "phone": "408-525-4766",
                    "email": "userabc@cisco.com",
                },
                "children": [{
                    "aaaUserCert": {
                        "attributes": {
                            "name": "userabc.crt",
                            "data": "-----BEGIN CERTIFICATE-----\nMIICjjCCAfegAwIBAgIJAMQnbE <snipped content> ==\n-----END CERTIFICATE-----",
                        },
                        "children": []
                    },
                    "aaaUserDomain": {
                        "attributes": {
                            "name": "all",
                        },
                        "children": [{
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "aaa",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "access-admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "fabric-admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "nw-svc-admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "ops",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "read-all",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "tenant-admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "tenant-ext-admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }, {
                            "aaaUserRole": {
                                "attributes": {
                                    "name": "vmm-admin",
                                    "privType": "writePriv",
                                },
                                "children": []
                            }
                        }]
                    }
                }]
            }
        }

A local user account is created with the specified personal details, certificate, and multiple user roles with write privileges assigned across various administrative domains.


Create a local user using python SDK

Create a local user account in the APIC system with certificate-based authentication and appropriate role assignments for system access.

Use the Python SDK to programmatically create local users in the APIC system. This method provides automated user provisioning with certificate authentication and role-based access control.

Before you begin

Follow these steps to create a local user using Python SDK:

Procedure

Create a local user.

Example:

#!/usr/bin/env python
from cobra.model.pol import Uni as PolUni
from cobra.model.aaa import UserEp as AaaUserEp
from cobra.model.aaa import User as AaaUser
from cobra.model.aaa import UserCert as AaaUserCert
from cobra.model.aaa import UserDomain as AaaUserDomain
from cobra.model.aaa import UserRole as AaaUserRole
from cobra.mit.access import MoDirectory
from cobra.mit.session import LoginSession
from cobra.internal.codec.jsoncodec import toJSONStr

APIC = 'http://10.10.10.1'
username = 'admin'
password = 'p@$$w0rd'

session = LoginSession(APIC, username, password)
modir = MoDirectory(session)
modir.login()

def readFile(fileName=None, mode="r"):
   if fileName is None:
      return ""
   fileData = ""
   with open(fileName, mode) as aFile:
      fileData = aFile.read()
   return fileData

# Use a dictionary to define the domain and a list of tuples to define
# our aaaUserRoles (roleName, privType)
# This can further be abstracted by doing a query to get the valid
# roles, that is what the GUI does

userRoles = {'all': [
               ('aaa', 'writePriv'),
               ('access-admin', 'writePriv'),
               ('admin', 'writePriv'),
               ('fabric-admin', 'writePriv'),
               ('nw-svc-admin', 'writePriv'),
               ('ops', 'writePriv'),
               ('read-all', 'writePriv'),
               ('tenant-admin', 'writePriv'),
               ('tenant-ext-admin', 'writePriv'),
               ('vmm-admin', 'writePriv'),
           ],
}

uni = PolUni('') # '' is the Dn string for topRoot
aaaUserEp = AaaUserEp(uni)
aaaUser = AaaUser(aaaUserEp, 'userabc', firstName='Adam',
                  email='userabc@cisco.com')

aaaUser.lastName = 'BC'
aaaUser.phone = '555-111-2222'
aaaUserCert = AaaUserCert(aaaUser, 'userabc.crt')
aaaUserCert.data = readFile("/tmp/userabc.crt")
# Now add each aaaUserRole to the aaaUserDomains which are added to the
# aaaUserCert
for domain,roles in userRoles.items():
   aaaUserDomain = AaaUserDomain(aaaUser, domain)
   for roleName, privType in roles:
       aaaUserRole = AaaUserRole(aaaUserDomain, roleName,
                                 privType=privType)
print toJSONStr(aaaUser, prettyPrint=True)

cr = ConfigRequest()
cr.addMo(aaaUser)
modir.commit(cr)
# End of Script to create a user

A local user account is created in the APIC system with the specified certificate authentication and role assignments across all domains.


Using a private key to calculate a signature

This task allows you to authenticate with APIC using signature-based authentication, which provides a secure method for API access without transmitting passwords.

Signature-based authentication requires calculating a digital signature using your private key for each API request. This signature is sent to the APIC as a cookie in the request header for verification.

Before you begin

You must have the following information available:

  • HTTP method - GET, POST, DELETE

  • REST API URI being requested, including any query options

  • For POST requests, the actual payload being sent to the APIC

  • The private key used to generate the X.509 certificate for the user

  • The distinguished name for the user X.509 certificate on the APIC

Follow these steps to use a private key to calculate a signature:

Procedure

  1. Concatenate the HTTP method, REST API URI, and payload together in this order and save them to a file.

    This concatenated data must be saved to a file for OpenSSL to calculate the signature. In this example, we use a filename of payload.txt. Remember that the private key is in a file called userabc.key.

    Example:

    GET example:
    GET http://10.10.10.1/api/class/fvTenant.json?rsp-subtree=children
    POST example:
    POST http://10.10.10.1/api/mo/tn-test.json{"fvTenant": {"attributes": {"status": "deleted", "name": "test"}}}
  2. Verify that the payload.txt file contains the correct information.

    For example, using the GET example shown in the previous step:

    GET http://10.10.10.1/api/class/fvTenant.json?rsp-subtree=children

    Your payload.txt file should contain only the following information:

    GET/api/class/fvTenant.json?rsp-subtree=children
  3. Verify that you didn't inadvertently create a new line when you created the payload file.

    Example:

    # cat –e payload.txt

    Determine if there is a $ symbol at the end of the output, similar to the following:

    GET/api/class/fvTenant.json?rsp=subtree=children$

    If so, then that means that a new line was created when you created the payload file. To prevent creating a new line when generating the payload file, use a command similar to the following:

    echo -n "GET/api/class/fvTenant.json?rsp-subtree=children" >payload.txt
  4. Calculate a signature using the private key and the payload file using OpenSSL.

    Example:

    openssl dgst -sha256 -sign userabc.key payload.txt > payload_sig.bin
    The resulting file has the signature printed on multiple lines.
  5. Convert the signature to base64 format:

    Example:

    openssl base64 -A -in payload_sig.bin -out payload_sig.base64
  6. Strip the signature of the new lines using Bash.

    Example:

    $ tr -d '\n' < payload_sig.base64
    P+OTqK0CeAZjl7+Gute2R1Ww8OGgtzE0wsLlx8fIXXl4V79Zl7
    Ou8IdJH9CB4W6CEvdICXqkv3KaQszCIC0+Bn07o3qF//BsIplZmYChD6gCX3f7q
    IcjGX+R6HAqGeK7k97cNhXlWEoobFPe/oajtPjOu3tdOjhf/9ujG6Jv6Ro=
    Note

    This is the signature that will be sent to the APIC for this specific request. Other requests will require to have their own signatures calculated.

  7. Place the signature inside a string to enable the APIC to verify the signature against the payload.

    This complete signature is sent to the APIC as a cookie in the header of the request.

    Example:

    APIC-Request-Signature=P+OTqK0CeAZjl7+Gute2R1Ww8OGgtzE0wsLlx8f
    IXXl4V79Zl7Ou8IdJH9CB4W6CEvdICXqkv3KaQszCIC0+Bn07o3qF//BsIplZmYChD6gCX3f
    7qIcjGX+R6HAqGeK7k97cNhXlWEoobFPe/oajtPjOu3tdOjhf/9ujG6Jv6Ro=; 
    APIC-Certificate-Algorithm=v1.0; APIC-Certificate-Fingerprint=fingerprint; 
    APIC-Certificate-DN=uni/userext/user-userabc/usercert-userabc.crt
    Note

    The DN used here must match the DN of the user certified object containing the x509 certificate in the next step.

  8. Use the CertSession class in the Python SDK to communicate with an APIC using signatures.

    This script is an example of how to use the CertSession class in the ACI Python SDK to make requests to an APIC using signatures.

    Example:

    #!/usr/bin/env python
    # It is assumed the user has the X.509 certificate already added to
    # their local user configuration on the APIC
    from cobra.mit.session import CertSession
    from cobra.mit.access import MoDirectory
    
    def readFile(fileName=None, mode="r"):
        if fileName is None:
            return ""
        fileData = ""
        with open(fileName, mode) as aFile:
            fileData = aFile.read()
        return fileData
    
    pkey = readFile("/tmp/userabc.key")
    csession = CertSession("https://ApicIPOrHostname/",
                           "uni/userext/user-userabc/usercert-userabc", pkey)
    
    modir = MoDirectory(csession)
    resp = modir.lookupByDn('uni/fabric')
    pring resp.dn
    # End of script
    Note

    The DN used in the earlier step must match the DN of the user certified object containing the x509 certificate in this step.

You have successfully created a signature for APIC authentication and can now use the CertSession class to make authenticated API requests to the APIC.