Python API: Add Compliance Standard to Policy

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Python API: Add Compliance Standard to Policy

L1 Bithead

Hi all,

 

I'm having trouble adding a Compliance Standard to an existing Policy via the API. 

 

In essence my code looks like:

import requests

url = https://api2.redlock.io/policy/{policy_id}

header = {'Content-Type': 'application/json', 'x-redlock-auth': 'token'}

payload = {
    'name': 'policy_name',
    'policyType': 'policy_type',
    'severity': 'policy_severity',
    'complianceMetadata': [
        {
            'standardName': 'standard_name',
            'requirementId': 'requirement_ID',
            'sectionId': 'section_id'
        }
    ]
}

response = requests.request('PUT', url, json=payload, header=header)

However, everytime I send the request, I'm returned with a 500 Server Error (and, unfortunately, the API documentation is super unhelpful with this). I'm not sure if I'm sending the right information to add a compliance standard as the API documentation doesn't show what info needs to be sent. If I leave out required fields (name, policyType, and severity), I'm returned a 400 error (bad request, which makes sense). But I can't figure out why I keep getting the 500 Server Error.

 

Any ideas here would be much appreciated! Thanks!

3 accepted solutions

Accepted Solutions

L4 Transporter

At first glance, you are likely missing some required fields that is necessary when PUT-ing a policy.  What I would recommend is do a GET on the policy, use the returned payload as base, update the complianceMetadata field with what you want to include, then PUT the entire thing back into Prisma Public Cloud.

 

I agree that the error message is super unhelpful; you might get more information by checking the response header.  The error message is included in there, and it might provide some hints.

 

Hope this helps.

View solution in original post

The bare minimum needed in compliance metadata is: 

 

 

"complianceMetadata":[ 
      { 
         "standardName":"Eddie",
         "requirementId":"1.1",
         "sectionId":"1.1.1",
         "customAssigned":true,
         "complianceId":"46e6887f-ba66-43f3-aaeb-9af56c1cc546",
         "requirementName":"Eddie req"
      }
   ],

You shouldn't need to include anything else in the metadata...

View solution in original post

L4 Transporter

Got it to work.  For these policies without RQL, you need to include this field within the "rule" field:

 

      "parameters":{  
         "savedSearch":"false"
      },

 

One way to find out if you need the above is to check for the rule -> parameters -> savedSearch field after you GET the policy.  I think all default policies with RQL will have "savedSearch" = "true", so if that field/value combo isn't in the returned JSON, you know you need to add "savedSearch": "false" to the payload before returning.

View solution in original post

7 REPLIES 7

L4 Transporter

At first glance, you are likely missing some required fields that is necessary when PUT-ing a policy.  What I would recommend is do a GET on the policy, use the returned payload as base, update the complianceMetadata field with what you want to include, then PUT the entire thing back into Prisma Public Cloud.

 

I agree that the error message is super unhelpful; you might get more information by checking the response header.  The error message is included in there, and it might provide some hints.

 

Hope this helps.

Thanks, @kchen.

 

The response header is this: 

x-redlock-status →[{"i18nKey":"internal_error","severity":"error","subject":null}]

 

Your approach is something that I actually implemented as a workaround, but no bueno. The work around looks like this:

req_header = {'Content-Type':'application/json','x-redlock-auth':jwt_token}

# This is a small function to get a policy by ID
policy = get_redlock_policy_by_ID(req_header, 'policy_ID')

    new_std = {
        'standardName': 'standard_name',
        'standardDescription': '',
        'requirementId': 'req_ID',
        'requirementName': 'req_name',
        'sectionId': 'section_ID',
        'sectionDescription': '',
        'policyId': '',
        'complianceId': 'compliance_ID',
        'systemDefault': False,
        'customAssigned': True
        }

    standards = policy['complianceMetadata']

    for standard in standards:
        if not 'standard_name' in standard['standardName']:
            new_std['policyId'] = policy['policyId']
            policy['complianceMetadata'].append(new_std)

            try:
                response = requests.request('PUT', '{}/policy/{}'.format(REDLOCK_API_URL, policy['policyId']), json=policy, headers=req_header)

                if response.status_code == 200:
                    print('Successful push ---- YA BOI DID IT')
                else:
                    logging.error(' HTTPStatus: ' + str(response.status_code) + ' ' + response.reason)
                    sys.exit(1)
            except requests.exceptions.RequestException as e:
                logging.error(' Data Push -- Function: update_redlock_compliance_details: {}'.format(e))
                break

 

And it still returns: 

>> ERROR:root: HTTPStatus: 500 Server Error

The bare minimum needed in compliance metadata is: 

 

 

"complianceMetadata":[ 
      { 
         "standardName":"Eddie",
         "requirementId":"1.1",
         "sectionId":"1.1.1",
         "customAssigned":true,
         "complianceId":"46e6887f-ba66-43f3-aaeb-9af56c1cc546",
         "requirementName":"Eddie req"
      }
   ],

You shouldn't need to include anything else in the metadata...

L4 Transporter

@JBox I get error 500s if the format of my JSON is incorrect.  Can you try to perform a GET then immediately PUT it back without modifying the payload?  If that still gives a 500, it's likely because you need to json.dumps the payload before sending it back.

 

Another thing, the "complianceId" field is very confusing.  That refers to the Compliance Section GUID.  It is not easy to get this ID number.  You will have to do a GET on the compliance standard, to find the requirements GUID, then you can GET the list of sections and section GUIDs.  Example, my compliance standard ID is 052009c7-7640-436c-bcde-69846acf73e8, so I have to

GET https://api.redlock.io/compliance/052009c7-7640-436c-bcde-69846acf73e8/requirement

 

Then in the response, I can find the requirements ID, which I can do:

 

GET https://api.redlock.io/compliance/f2cf9fe2-1007-48b7-b5bb-1f24e8535953/section

 

Then within that response, I can find the "id" of the section that I want to use, which is the value for the "complianceId" field in the complianceMetadata object.

 

 

 

 

Thanks, @kchen. and @ebeuerlein.

 

It ended up working for all but 2 policies with the work-around on GET-requesting the entire policy, appending the "complianceMetadata" array and PUT-requesting the whole policy back.

 

The issue now is the two that it didn't update for (Prisma Public Cloud default policies). The first one is a known bug that the internal engineering team are working on. However, the second that didn't work is returning another 500 error. It is an old policy that hasn't been converted to RQL yet. If 500 errors are usually bad JSON, is there a difference in a RQL Policy JSON vs Non-RQL Policy JSON? Pulling the data from the server and having a look at it, it doesn't seem so but I can't get this one to update via the API. Otherwise, I can't figure out why it would work on all RQL policies and not this one non-RQL policy.

 

Any further suggestions would be awesome!

L4 Transporter

Got it to work.  For these policies without RQL, you need to include this field within the "rule" field:

 

      "parameters":{  
         "savedSearch":"false"
      },

 

One way to find out if you need the above is to check for the rule -> parameters -> savedSearch field after you GET the policy.  I think all default policies with RQL will have "savedSearch" = "true", so if that field/value combo isn't in the returned JSON, you know you need to add "savedSearch": "false" to the payload before returning.

Worked perfectly, thanks @kchen!

  • 3 accepted solutions
  • 13334 Views
  • 7 replies
  • 0 Likes
Like what you see?

Show your appreciation!

Click Like if a post is helpful to you or if you just want to show your support.

Click Accept as Solution to acknowledge that the answer to your question has been provided.

The button appears next to the replies on topics you’ve started. The member who gave the solution and all future visitors to this topic will appreciate it!

These simple actions take just seconds of your time, but go a long way in showing appreciation for community members and the LIVEcommunity as a whole!

The LIVEcommunity thanks you for your participation!