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

Pro Tip: Tag you SSL certs (Certs discovered from extensions)

Maheedhar_T
Mentor

Heya,
Most of us are using SSL cert extension but the catch here is that we cannot use Auto-tagging rules directly for certs to put on some tags to the crets. However, the certs are most of the time discovered from hosts so why not inherit the tags from the hosts itself?

Here is how you can do it with a simple workflow.
Step-1:
Get the certs that do not have the required Tags.
We can use simple DQL for this

 

fetch `dt.entity.python:certificate_monitor_certificate`, from: now()-7d 
| fieldsAdd host_att, host_port, tags
| fieldsAdd tagStr = toString(tags)
| filterOut (matchesPhrase(tagStr,"Application") and matchesPhrase(tagStr,"Environment") and matchesPhrase(tagStr,"SnowAppId"))

 

 

Step-2:
Get the host on which these certs run and get the Tags from them.

 

fetch dt.entity.host
| filter id == "{{ _.item ['host_att'] }}"
| fieldsAdd tags

 


This is a step that uses the result from the previous step as a loop so go to options in the workflow step, select Loop task and in the list we mention the result of previous step like this.

 

{{ result("get_cert_details")["records"] }}

 

Maheedhar_T_0-1739341158445.png


Step-3:
We use js here and the results from previous steps to place the extracted tags to each cert.

 

import { execution } from '@dynatrace-sdk/automation-utils';
import { monitoredEntitiesCustomTagsClient } from "@dynatrace-sdk/client-classic-environment-v2";

// Function to extract tags based on id
function getTagsById(data, id) {
    for (const item of data) {
        for (const record of item.records) {
            if (record.id === id) {
                return record.tags; // Return tags if id matches
            }
        }
    }
    return null; // Return null if id is not found
}

// Function to extract specific key-value pairs from an array of tags
function extractValues(array) {
    const keysToExtract = ["Application", "SnowAppID"]; // Only include "Application" and "SnowAppID"
    const result = [];

    array.forEach(item => {
        keysToExtract.forEach(key => {
            if (item.startsWith(key + ":")) {
                const value = item.split(":")[1]; // Extract value after the key
                result.push({ key: key, value: value }); // Push key-value pair to result
            }
        });
    });

    return result;
}

export default async function ({ execution_id }) {
    try {
        const ex = await execution(execution_id); // Get the current execution details using the provided execution ID
        const cert_res = await ex.result("get_cert_details"); // Get certificate details from the execution results
        const certs = cert_res.records;
        const host_tags_res = await ex.result("get_host_tags"); // Get host tags from the execution results

        const required_substrings = ["Application", "SnowAppID"]; // Define required substrings to check in tags

        for (const item of certs) {
            const tagsPresent = required_substrings.every(substring =>
                item.tags.some(tag => tag.includes(substring))
            ); // Check if all required substrings are present in the tags

            if (!tagsPresent) {
                const host_id = item.host_att; // Get host ID from certificate
                const certTags = getTagsById(host_tags_res, host_id); // Get tags for the host
                const postTags = extractValues(certTags); // Extract required key-value pairs from tags
                console.log(postTags);

                const entitySelector = `type("dt.entity.python:certificate_monitor_certificate"),entityName("${item['entity.name']}")`; // Create an entity selector for the certificate
                console.log(entitySelector);

                const data = await monitoredEntitiesCustomTagsClient.postTags({
                    entitySelector: entitySelector,
                    body: { tags: postTags },
                }); // Post the extracted tags to the monitored entity
                console.log(data);
            }
        }

        return { triggeredBy: ex.trigger }; // Return the trigger information from the execution details
    } catch (error) {
        console.error("An error occurred:", error); // Log any errors that occur during the process
        throw error;
    }
}

 


voila once you run this all the crets discovered from hosts now are tagged with the required Tags.

(Make changes to this according to the Tags that you need to inherit from the host)


Adding the json of the workflow here,

 

metadata:
  version: "1"
  dependencies:
    apps:
      - id: dynatrace.automations
        version: ^1.985.4
  inputs: []
workflow:
  title: certTagger
  tasks:
    post_tags:
      name: post_tags
      description: Build a custom task running js Code
      action: dynatrace.automations:run-javascript
      input:
        script: >
          // Optional import of SDK modules

          import { execution } from '@dynatrace-sdk/automation-utils';

          import { monitoredEntitiesCustomTagsClient } from
          "@dynatrace-sdk/client-classic-environment-v2";


          // Function to extract tags based on id

          function getTagsById(data, id) {
              for (const item of data) {
                  for (const record of item.records) {
                      if (record.id === id) {
                          return record.tags; // Return tags if id matches
                      }
                  }
              }
              return null; // Return null if id is not found
          }


          // Function to extract specific key-value pairs from an array of tags

          function extractValues(array) {
              const keysToExtract = ["Application", "SnowAppID", "Environment"];
              const result = [];

              array.forEach(item => {
                  keysToExtract.forEach(key => {
                      if (item.startsWith(key + ":")) {
                          const value = item.split(":")[1]; // Extract value after the key
                          result.push({ key: key, value: value }); // Push key-value pair to result
                      }
                  });
              });

              return result;
          }


          export default async function ({ execution_id }) {
              try {
                  // Get the current execution details using the provided execution ID
                  const ex = await execution(execution_id);

                  // Get certificate details and host tags from the execution results
                  const cert_res = await ex.result("get_cert_details");
                  const certs = cert_res.records;
                  const host_tags_res = await ex.result("get_host_tags");

                  // Define required substrings to check in tags
                  const required_substrings = ["Application", "CFU", "SnowAppID", "Environment"];

                  // Iterate over each certificate
                  for (const item of certs) {
                      // Check if all required substrings are present in the tags
                      const tagsPresent = required_substrings.every(substring =>
                          item.tags.some(tag => tag.includes(substring))
                      );

                      // If not all required tags are present, fetch and add them
                      if (!tagsPresent) {
                          const host_id = item.host_att; // Get host ID from certificate
                          const certTags = getTagsById(host_tags_res, host_id); // Get tags for the host
                          const postTags = extractValues(certTags); // Extract required key-value pairs from tags
                          console.log(postTags);

                          // Create an entity selector for the certificate
                          const entitySelector = `type("dt.entity.python:certificate_monitor_certificate"),entityName("${item['entity.name']}")`;
                          console.log(entitySelector);

                          // Post the extracted tags to the monitored entity
                          const data = await monitoredEntitiesCustomTagsClient.postTags({
                              entitySelector: entitySelector,
                              body: { tags: postTags },
                          });
                          console.log(data);
                      }
                  }

                  // Return the trigger information from the execution details
                  return { triggeredBy: ex.trigger };
              } catch (error) {
                  // Log any errors that occur during the process
                  console.error("An error occurred:", error);
                  throw error;
              }
          }
      position:
        x: 0
        y: 3
      predecessors:
        - get_host_tags
      conditions:
        states:
          get_host_tags: OK
    get_host_tags:
      name: get_host_tags
      description: Executes DQL query
      action: dynatrace.automations:execute-dql-query
      input:
        query: |-
          fetch dt.entity.host
          | filter id == "{{ _.item ['host_att'] }}"
          | fieldsAdd tags
      position:
        x: 0
        y: 2
      predecessors:
        - get_cert_details
      conditions:
        states:
          get_cert_details: OK
      concurrency: 1
      withItems: item in {{ result("get_cert_details")["records"] }}
    get_cert_details:
      name: get_cert_details
      description: Executes DQL query
      action: dynatrace.automations:execute-dql-query
      input:
        query: >-
          fetch `dt.entity.python:certificate_monitor_certificate`, from:
          now()-7d 

          | fieldsAdd host_att, host_port, tags

          | fieldsAdd tagStr = toString(tags)

          | filterOut (matchesPhrase(tagStr,"Application") and
          matchesPhrase(tagStr,"CFU") and matchesPhrase(tagStr,"Environment")
          and matchesPhrase(tagStr,"SnowAppId"))
      position:
        x: 0
        y: 1
      predecessors: []
  description: ""
  trigger: {}
  schemaVersion: 3

 


Thanks,
Maheedhar.

Maheedhar
0 REPLIES 0

Featured Posts