AWS Lambda Integration with Freshservice API for Bulk Assets update

We are working on Freshservice API URL integration with our AWS Lambda function to automate of AWS VMs Tags update into Freshservice Inventory for our AWS VMs Assets at Freshservice Inventory.

We have configured AWS Lambda function and provided required Freshservice API Key and Freshservice API URL in our Lambda configuration. And then we have tried executing AWS Lambda function but getting failed due to unable to reach Freshservice Instance. In today’s call with Nivedha, as suggested by the solution document, we have tried updating AWS Lambda code by changing Instance ID as to Display ID but that also gets failed and having same issue again.

So, by said that we are requesting to get this resolved for us with right team, we are stuck at this stage due to Freshservice API URL integration is not working with our AWS Lambda function.
Please consider this as priority and let us know your response to connect on this.

Hi @Naresh,

Please share the code you are using to make an API call to Freshservice and the exact error message you received.

Have you tried using cURL or Postman to check if the API works fine?

Hello Ravi,

We have used the below AWS Lambda code and getting error as “Failed to fetch assets from Freshworks: 404

@Naresh Can you share the code again? I can’t see the code in your post.

Also, Have you tried using cURL or Postman to check if the API works fine?

Hi Raviraj,

Yes, we have checked CURL and POSTMAN with complete end point of API URL with one single Asset ID was working fine, which we did check along with Nivedha from Freshservice Support.

Here our requirement is to update all the AWS VMs Tags information automatically from AWS to Freshservice using AWS Lambda function by integrating Freshservice API URL, which is not working…

We are getting an error “Failed to fetch assets from Freshworks: 404”

===================Here is the AWS Lambda Code we used in our Sandbox Environment=========================

import boto3

import requests

from datetime import datetime

AWS Config Aggregator details

aggregator_name = ‘aws-controltower-GuardrailsComplianceAggregator’

region_name = ‘us-west-2’ # Specify your region

Freshworks API details

freshworks_domain = ‘cepheidservicedesk-sandbox-jan-23.freshservice.com/api/v2/assets/{asset_id}

freshworks_api_key = ‘2b3xxxxxxxxxxxxxx’

AWS account ID for Freshworks

aws_account_id = ‘994000000000’

Initialize AWS Config client

config_client = boto3.client(‘config’, region_name=region_name)

Function to convert datetime objects to strings

def convert_datetime(obj):

if isinstance(obj, datetime):

return obj.isoformat()

raise TypeError(“Type not serializable”)

Function to get instance details and tags from AWS Config Aggregator

def get_instance_details(aggregator_name):

try:

Check if the aggregator exists

config_client.describe_configuration_aggregators(

ConfigurationAggregatorNames=[aggregator_name]

)

Get the list of aggregated resources

paginator = config_client.get_paginator(‘list_aggregate_discovered_resources’)

page_iterator = paginator.paginate(

ConfigurationAggregatorName=aggregator_name,

ResourceType=‘AWS::EC2::Instance’

)

instance_details =

for page in page_iterator:

for resource in page[‘ResourceIdentifiers’]:

resource_details = config_client.get_aggregate_resource_config(

ConfigurationAggregatorName=aggregator_name,

ResourceIdentifier={

‘SourceAccountId’: resource[‘SourceAccountId’],

‘SourceRegion’: resource[‘SourceRegion’],

‘ResourceId’: resource[‘ResourceId’],

‘ResourceType’: resource[‘ResourceType’]

}

)

instance_details.append(resource_details[‘ConfigurationItem’])

return instance_details

except config_client.exceptions.NoSuchConfigurationAggregatorException:

print(f"The configuration aggregator ‘{aggregator_name}’ does not exist.")

return

Function to get asset IDs from Freshworks

def get_freshworks_assets():

url = f"https://{freshworks_domain}/api/v2/assets"

headers = {

‘Authorization’: f’Bearer {freshworks_api_key}',

‘Content-Type’: ‘application/json’

}

response = requests.get(url, headers=headers)

if response.status_code == 200:

return response.json()[‘assets’]

else:

print(f"Failed to fetch assets from Freshworks: {response.status_code}")

return

Function to update tags in Freshworks

def update_freshworks_tags(asset_id, tags):

url = f"https://{freshworks_domain}/api/v2/assets/{asset_id}"

headers = {

‘Authorization’: f’Bearer {freshworks_api_key}',

‘Content-Type’: ‘application/json’

}

payload = {

‘asset’: {

‘custom_fields’: tags

}

}

response = requests.put(url, headers=headers, json=payload)

if response.status_code == 200:

print(f"Successfully updated tags for asset ID {asset_id}")

else:

print(f"Failed to update tags for asset ID {asset_id}: {response.status_code}")

Define the required tag keys

required_tag_keys = [

“AccountName”, “Environment”, “Application”, “BusinessApplicationName”,

“SystemCriticality”, “PatchGroup”, “SystemName”, “RegionName”,

“ITOwner”, “ITDepartment”, “SystemOwner”, “SystemOwnerDepartment”,

“SystemFunction”, “SystemCreator”, “SystemRequester”, “CostCenter”,

“SystemType”, “Backup”

]

def lambda_handler(event, context):

Get instance details

instances = get_instance_details(aggregator_name)

Get Freshworks assets

freshworks_assets = get_freshworks_assets()

Create a mapping of instance IDs to asset IDs

asset_mapping = {asset[‘unique_identifier’]: asset[‘id’] for asset in freshworks_assets}

Process instance details and update tags in Freshworks

if instances:

for instance in instances:

instance_id = instance[“resourceId”]

account_id = instance[“accountId”]

tags = instance.get(“tags”, {})

Ensure all required tag values are present in the correct order

tag_values = {tag: tags.get(tag, “N/A”) for tag in required_tag_keys}

Update tags in Freshworks if the instance ID matches an asset ID and account ID matches

if instance_id in asset_mapping and account_id == aws_account_id:

update_freshworks_tags(asset_mapping[instance_id], tag_values)

return {

‘statusCode’: 200,

‘body’: ‘Instance tags have been updated in Freshworks.’

}

===================Here is the AWS Lambda Code we used in our Sandbox Environment=========================

Thanks and Regards

Naresh Kambam

@Naresh The 404 error code means that the entire request URL is not exactly right or the specific Resource is not available.

Can you recheck if the URL is accurate? Can you check by hard-coding the endpoint completely once to see if it works before using any template code?

Issue suspected:
You’re making API request to this URL - https://{freshworks_domain}/api/v2/assets
But, the freshworks_domain variable value is set as http://cepheidservicedesk-sandbox-jan-23.freshservice.com/api/v2/assets/{asset_id}. So, there seems to be duplicate path set resulting in a wrong endpoint. Can you verify this and remove the duplicate path?

If a single asset worked via cURL and Postman, please check the same from AWS Lambda to see if the same can be replicated and works to ensure the network and authentication work fine.
If it works, then you can extend the implementation of your logic to update all the assets.

Hi Raviraj,

The same URL when we checked for specific Asset ID from AWS Lambda it was working fine it seems but not work multiple assets.

Thanks and Regards

Naresh Kambam

Hi @Naresh,

Please simplify the code to use the URL in plain text first and test. If it works, then you can modify it to use variables.

Looks like the URL has duplicate path when using variable dynamically. Please check this and revert back with plain text URL if it fails again.

+ Eswar, as he is the one working on this code and testing.

Hi Raviraj,

Eswar is on leave this week. He will be back to work from next week Monday onwards.

We had multiple code changes and testing as well but those were not working as expected, that is the reason we have posted details in Dev Community as per suggestion by the Freshservice Support Team.

Thanks and Regards

Naresh Kambam