I recently start to use Red Hat Enterprise Linux for development in a virtual machine environment. Because I can destroy the virtual machine safely and quickly on my host, I need a quick way to manage my entitlements to comply with the seat limit associated with my subscription. Red Hat provides a list of web API interfaces that cover most account management operations. Combining WL’s build-in web service query functions, I can easily turn a notebook to dynamic account management platform. The main WL functions used are
◼
  • HTTPRequest / URLRead / URLExecute: build complete API, just like CURL
  • ◼
  • ByteArrayToString / ImportString: parse serialized data in JSON format
  • Step by Step

    Follow the knowledge base article, I need to generate a offline token through my portal. This token is served as a private secrete key that I should keep to myself only.
    The offline code should look like this
    offline="eyJhbGci...ZGe0";
    The next step is to use the offline token to generate a temporary signature (or called access code) used for subsequent operation. This step is essential that the following data sensitive operation won’t be tempered over internet transition. The life time of such signature is 900 seconds = 15 minutes.
    ​
    The documented CURL command in terminal looks like
    $ offline_token='eyJhbGciOiJSUzI1NiIsInR5cCIgOiA'
    ​
    $ curl https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token -d grant_type=refresh_token -d client_id=rhsm-api -d refresh_token=$offline_token
    The -d option in the script is translated to a list of rule in the Body section in my HTTPRequest. The Post method can be omitted in the HTTPRequest below
    In[]:=
    reuqest=HTTPRequest["https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token",<|"Body"{"grant_type""refresh_token","client_id""rhsm-api","refresh_token"->offline}|>]
    Use URLRead to retrieve the response
    In[]:=
    response=URLRead[reuqest]
    The response says OK. I can also check the status code manually to verify the success
    In[]:=
    result=List@@response;
    In[]:=
    result〚2〛["StatusCode"]===200
    Out[]=
    True
    The signature is returned in a serialized form
    In[]:=
    result〚1〛//Head
    Out[]=
    ByteArray
    The rest of the response also contains some verbose header messages. I can print them in the notebook for debug purpose
    In[]:=
    Grid[​​result[[2]]["Headers"],​​Background{None,{{LightBlue,None}}},​​AlignmentLeft]
    Out[]=
    Cache-Control
    no-store
    X-XSS-Protection
    1; mode=block
    Pragma
    no-cache
    X-Frame-Options
    SAMEORIGIN
    Strict-Transport-Security
    max-age=31536000; includeSubDomains
    X-Content-Type-Options
    nosniff
    X-Site
    phx2
    Content-Type
    application/json
    Vary
    Accept-Encoding
    Content-Encoding
    gzip
    Date
    Tue, 15 Dec 2020 02:35:12 GMT
    Content-Length
    1730
    Connection
    keep-alive
    I use ByteArrayToString to deserialize the result to obtain the human readable form
    deserialized=ByteArrayToString[result〚1〛]
    {"access_token":"eyJhbGci...Y0fRwqPsbE","expires_in":900,"refresh_expires_in":0,"refresh_token":"eyJhb...iFI4RmVA","token_type":"bearer","not-before-policy":0,"session_state":"9f949da5-0290-...-...-1234","scope":"offline_access"}
    Notice the output put above is string, I have convert it to expression using the RawJSON attribute in the following function. The result is of Association type.
    In[]:=
    access=ImportString[deserialized,"RawJSON"]
    access_tokeneyJhbGci...Y0fRwqPsbEE,expires_in900,refresh_expires_in0,refresh_tokeneyJhb...iFI4RmVA,token_typebearer,not-before-policy0,session_state9f949da5-0290-...-...-1234,scopeoffline_access
    Use the “access_token” key to find the signature
    In[]:=
    access["access_token"]
    eyJhbGci...Y0fRwqPsbEE

    Example: Find Subscription

    The documented CURL command to retrieve my subscriptions are
    # curl -H "Authorization: Bearer $token" https://api.access.redhat.com/management/v1/subscriptions
    The command requires headers corresponding request in WL is
    In[]:=
    request2=HTTPRequest["https://api.access.redhat.com/management/v1/subscriptions",<|"Headers"{"Authorization""Bearer "<>access["access_token"]}|>]
    In[]:=
    subscription=URLExecute[request2];
    Convert the body part of the response to Dataset for organized display
    Dataset[Association@@@("body"/.subscription)]
    In case the signature is expired or invalid, URLExcute returns the following message
    URLExecute[request2Expired]
    Authentication required

    Example: Delete User Subscription

    I need to delete a subscription associated with a virtual machine I just destroyed with RHEL previously installed. UUID is needed to operate account management on any specific user
    In[]:=
    request3=HTTPRequest["https://api.access.redhat.com/management/v1/systems",<|"Headers"{"Authorization""Bearer "<>access["access_token"]}|>]
    Print the subscription information
    Append the second UUID to a URL and add DELETE method in the head
    Perform deletion on the server side. On successful deletion, URLExecute returns empty string and URLRead should return 204 for status code.
    Verify the user with the given UUID is deleted by calling the system management web API with the signature
    Now the second entry is deleted

    Summary

    ◼
  • HTTPRequest / URLRead / URLExecute: build complete API, just like CURL
  • ◼
  • ByteArrayToString / ImportString: parse serialized data in JSON format
  • ◼
  • View the full list of API template from https://access.redhat.com/management/api/rhsm
  • ◼
  • Steps above can be transferred to Red Hat Satellite service management as well