APM

Rotate your license keys with Python and the NerdGraph API

Part 5 of 5: Automating common DevOps tasks in New Relic

Published 4 min read

For security reasons, it's important that you regularly rotate your license keys. License key rotation is even required in some industries, such as those using the Payment Card Industry Data Security Standard (PCI DSS). This post shows you how to create, read, update, and delete license keys using New Relic Query Language (NRQL) and Python. 

Creating a license key

Here's how you can create a license key using the NerdGraph API. The following code defines and calls a Python method called nerdgraph_createkey. Note that each XXX in {accountId: XXX, userId: XXX, name: "XXX", notes: "XXX" } needs to be replaced. accountId and userId are integers while name and notes are strings.

If the response is successful, you can optionally serialize the object as a JSON-formatted stream or print it as a Python dictionary.

import requests
import json
from license import user_key

def nerdgraph_createkey(key):
  # GraphQL query to NerdGraph
  query = """
  mutation {
    apiAccessCreateKeys(keys: {user: {accountId: XXX, userId: XXX, name: "XXX", notes: "XXX" } }) {
      createdKeys {
        id
        key
        name
        notes
        type
      }
      errors {
        message
        type
        ... on ApiAccessIngestKeyError {
          accountId
          errorType
          ingestType
        }
      }
    }
  }"""
  
  # NerdGraph endpoint
  endpoint = "https://api.newrelic.com/graphql"
  headers = {'API-Key': f'{key}'}
  response = requests.post(endpoint, headers=headers, json={"query": query})

  if response.status_code == 200:
    # convert a JSON into an equivalent python dictionary
    json_dictionary = json.loads(response.content)
    print(json_dictionary['data']['apiAccessCreateKeys']['createdKeys'])

    # optional - serialize object as a JSON formatted stream
    # json_response = json.dumps(response.json()["data"]["dashboardCreateSnapshotUrl"], indent=2)
    # print(json_response)

  else:
      # raise an error with a HTTP response code
      raise Exception(f'Nerdgraph query failed with a {response.status_code}.')

nerdgraph_createkey(user_key)

Reading a license key

This query will return the license keys for an account (including the name associated with the key and any notes). Note that the code follows the same structure as the previous example. The query is different and the response is also parsed differently.

import requests
import json
from license import user_key

def nerdgraph_readkey(key):
  # GraphQL query to NerdGraph
  query = """
  {
    actor {
      apiAccess {
        keySearch(query: {types: USER, scope: {ingestTypes: LICENSE}}) {
          keys {
            name
            key
            type
            notes
            id
          }
        }
      }
    }
  }"""
  
  # NerdGraph endpoint
  endpoint = "https://api.newrelic.com/graphql"
  headers = {'API-Key': f'{key}'}
  response = requests.post(endpoint, headers=headers, json={"query": query})

  if response.status_code == 200:
    # convert a JSON into an equivalent python dictionary
    json_dictionary = json.loads(response.content)
    print(json_dictionary['data']['actor']['apiAccess']['keySearch'])

    # optional - serialize object as a JSON formatted stream
    # json_response = json.dumps(response.json()['data']['actor']['apiAccess']['keySearch'], indent=2)
    # print(json_response)

  else:
      # raise an error with a HTTP response code
      raise Exception(f'Nerdgraph query failed with a {response.status_code}.')

nerdgraph_readkey(user_key)

Updating a license key

Next, let's take a look at how you can update a license key.  Once again, you need to replace each XXX in {keyId: "XXX", name: "XXX", notes: "XXX" }.

import requests
import json
from license import user_key

def nerdgraph_updatekey(key):
  # GraphQL query to NerdGraph
  query = """
  mutation {
    apiAccessUpdateKeys(keys: {user: {keyId: "XXX", name: "XXX", notes: "XXX" } }) {
      updatedKeys {
        id
        key
        type
        name
        notes
      }
      errors {
        message
      }
    }
  }"""
  
  # NerdGraph endpoint
  endpoint = "https://api.newrelic.com/graphql"
  headers = {'API-Key': f'{key}'}
  response = requests.post(endpoint, headers=headers, json={"query": query})

  if response.status_code == 200:
    # convert a JSON into an equivalent python dictionary
    json_dictionary = json.loads(response.content)
    print(json_dictionary)

    # optional - serialize object as a JSON formatted stream
    # json_response = json.dumps(response.json()["data"]["dashboardCreateSnapshotUrl"], indent=2)
    # print(json_response)

  else:
      # raise an error with a HTTP response code
      raise Exception(f'Nerdgraph query failed with a {response.status_code}.')

nerdgraph_updatekey(user_key)

Deleting license keys

Finally, you can delete license keys with the following code.

import requests
import json
from license import user_key

def nerdgraph_deletekey(key):
  # GraphQL query to NerdGraph
  query = """
  mutation {
    apiAccessDeleteKeys(keys: {userKeyIds: "XXX"}) {
      deletedKeys {
        id
      }
      errors {
        message
      }
    }
  }"""
  
  # NerdGraph endpoint
  endpoint = "https://api.newrelic.com/graphql"
  headers = {'API-Key': f'{key}'}
  response = requests.post(endpoint, headers=headers, json={"query": query})

  if response.status_code == 200:
    # convert a JSON into an equivalent python dictionary
    json_dictionary = json.loads(response.content)
    print(json_dictionary)

    # optional - serialize object as a JSON formatted stream
    # json_response = json.dumps(response.json()["data"]["dashboardCreateSnapshotUrl"], indent=2)
    # print(json_response)

  else:
      # raise an error with a HTTP response code
      raise Exception(f'Nerdgraph query failed with a {response.status_code}.')

nerdgraph_deletekey(user_key)