Skip to main content
Solved

HTTP Data collection: Path depth

  • 15 July 2024
  • 5 replies
  • 106 views

Hi!

I’m trying to follow the tutorial

to implement monitoring of SAP SCC. Two issues:

  1. HTTP basic authentication: it’s not clear from the tutorial how to get a plain simple HTTP basic auth. Took me hour to figure out (use the source, Luke!) that you just need to pass ‘basic’ like this:
    "authorization": {
    "basic": 1,
    "username": "%(constants.username)",
    "password": "%(constants.password)"
    },

    I would add it to the original post, but the comments are locked. Please add it, so people save a lot of time.

  2. Path depth. SAP will respond with a JSON of this type:

    {
    "subaccounts": c
    {
    "description": "SAP BAS",
    "displayName": "SAP BAS",
    "tunnel": {
    "state": "Connected",
    "connectedSinceTimeStamp": 1720773876375,
    "connections": 0,
    "applicationConnections": c],
    "serviceChannels": a],
    "subaccountCertificate": {
    "notAfterTimeStamp": 1749540416000,
    "notBeforeTimeStamp": 1718000816000,
    "subjectDN": "CN=B0CADA20E31311EBBF8AD3BE0A31F20A,L=35319f63-2ec5-4a96-a3e2-6b8c1c14367f,OU=edca892d-9bfb-4aae-aafd-f4c5aa10bd4e,OU=SAP Cloud Platform Clients,O=SAP SE,C=DE",
    "issuer": "CN=SAP Cloud Platform Client CA,OU=SAP Cloud Platform Clients,O=SAP SE,L=EU10,C=DE"
    },
    "user": "user@notyourbusiness.com"
    },
    "regionHost": "cf.eu10.hana.ondemand.com",
    "subaccount": "35319f63-2ec5-4a96-a3e2-6b8c1c14367f",
    "locationID": ""
    },
    {
    "description": "",
    "displayName": "CALM",
    "tunnel": {
    "state": "Connected",
    "connectedSinceTimeStamp": 1720775091197,
    "connections": 0,
    "applicationConnections": c],
    "serviceChannels": a],
    "subaccountCertificate": {
    "notAfterTimeStamp": 1733323959000,
    "notBeforeTimeStamp": 1701697959000,
    "subjectDN": "CN=B0CADA20E31311EBBF8AD3BE0A31F20A,L=882afc82-327b-4368-8588-dd6086ac0370,OU=edca892d-9bfb-4aae-aafd-f4c5aa10bd4e,OU=SAP Cloud Platform Clients,O=SAP SE,C=DE",
    "issuer": "CN=SAP Cloud Platform Client CA,OU=SAP Cloud Platform Clients,O=SAP SE,L=EU10,C=DE"
    },
    "user": "auser@notyourbusiness.com"
    },
    "regionHost": "cf.eu10.hana.ondemand.com",
    "subaccount": "882afc82-327b-4368-8588-dd6086ac0370",
    "locationID": ""
    }
    ],
    "version": 1
    }

    I tried to get the values with this code:
     

            "parse":  
    {
    "name": "Entries",
    "type": "body",
    "path": "$.subaccounts
  3. ",
    "entries": e
    {
    "id": "displayName"
    },
    {
    "id": "regionHost"
    },
    {
    "id": "tunnel.state"
    },
    {
    "id": "tunnel.subaccountCertificate.notAfterTimeStamp"
    },

    {
    "id": "subaccount"
    }
    ]
    }
  4. It will get the tunnel.state, but not tunnel.subaccountCertificate.notAfterTimeStamp. As I understood the code (use the source, Luke! Again), it allows only one step of siblings, which is also not mentioned anywhere. Is it possible to modify the code so it recurses down the path?

    Except for these: Great tool! Looking forward to use it more.

    Thanks guys! 

5 replies

Userlevel 4
Badge +12

Hi @derEdu,

I will consider adding your tip about basic authentication. 🤙🏻

About the recursion into JSON structure, it should be working since last November release. Can you show the complete output you get with --debug option?

 

Badge +3

Hi @omercier!

regarding the recursion: unfortunately, it doesn’t. I have the recent Centreon release (24.04) and also tested it with the recent centreon-plugins from Github. I’ll send you a complete output in PM, but for the public: here are the http tables (the run is from a different SCC, but the original one looks the same):

======> variables
http.tables.subaccountReqEntries.[2].displayName = SAP Analytics Cloud
http.tables.subaccountReqEntries.[2].tunnel.state = Connected
http.tables.subaccountReqEntries.[2].subaccount = 8a176e16-55a0-4683-9435-daf61a197589
http.tables.subaccountReqEntries.[2].tunnel.subaccountCertificate.notAfterTimeStamp =
http.tables.subaccountReqEntries.[2].regionHost = cf.eu10.hana.ondemand.com
http.tables.subaccountReqEntries.[3].subaccount = i6frso7ll9
http.tables.subaccountReqEntries.[3].tunnel.subaccountCertificate.notAfterTimeStamp =
http.tables.subaccountReqEntries.[3].regionHost = hana.ondemand.com
http.tables.subaccountReqEntries.[3].displayName = STE ADS
http.tables.subaccountReqEntries.[3].tunnel.state = Connected
http.tables.subaccountReqEntries.[1].tunnel.subaccountCertificate.notAfterTimeStamp =
http.tables.subaccountReqEntries.[1].subaccount = 79797d7f-f74c-4791-99ad-74a7af8edb3c
http.tables.subaccountReqEntries.[1].regionHost = cf.eu10.hana.ondemand.com
http.tables.subaccountReqEntries.[1].displayName = Cloud Identity Management
http.tables.subaccountReqEntries.[1].tunnel.state = Connected
http.tables.subaccountReqEntries.[0].tunnel.state = Connected
http.tables.subaccountReqEntries.[0].displayName = Datasphere
http.tables.subaccountReqEntries.[0].regionHost = cf.eu10.hana.ondemand.com
http.tables.subaccountReqEntries.[0].tunnel.subaccountCertificate.notAfterTimeStamp =
http.tables.subaccountReqEntries.[0].subaccount = 35ee546b-dc1c-45e3-b1f3-4ba855cb6953

as you see, ‘notAfterTimStamp” variables are empty. I think the relevant code is here in collection.pm, sub parse_structure:

            if ($ref eq 'HASH') {

                if (!defined($value->{ $_->{id} })) {
                    # Check and assume in case of hash reference first part is the hash ref and second the hash key
                    if($_->{id} =~ /^(.+?)\.(.*)$/){
                        if (!defined($value->{$1}->{$2})) {
                            $entry->{ $_->{id} } = '';
                            next;
                        }else{
                            $entry->{ $_->{id} } = $value->{$1}->{$2};
                        }
                    }else {
                        $entry->{ $_->{id} } = '';
                        next;
                    }

The first group of your regex is non-greedy so it will grab only the portion before the first ‘.’, resulting in “tunnel’ in my case.  Thus, $value{$1}->{$2} is not defined.

 

Badge +3

 @omercier 

Update: I was right with my assumption and I suggest the following patch:

1) added a recursive sub

sub traverse_hash {
my ($self, $search, $data) = @_;
if ($search !~ /\./) {
#last run or found nothing
if (defined ($data->{$search})){
return $data->{$search};
}else{
return "";
}
}
my $key="";
my @parts=[];
my $ref="";
@parts=split(/\./, $search);
$key=shift(@parts);
$ref=ref($data->{$key});
if ($ref eq "HASH") {
#need to go deeper
return $self->traverse_hash(join(".", @parts), $data->{$key});
}else{
#whoa, strange things happen here
return "";
}

}

2 ) changed the code mentioned in my previous post

            if ($ref eq 'HASH') {
if (!defined($value->{ $_->{id} })) {
if($_->{id} =~ /\./){
$entry->{ $_->{id} }=$self->traverse_hash($_->{id}, $value);
}else {
$entry->{ $_->{id} } = '';
next;
}

 It works so far, but I’m a perl aprentice, not a perl magician like yourself. Don’t judge me too much and please take it into review. 

Badge +3

Update: After a few more tests, I filed a bug on Github. Can be found here: https://github.com/centreon/centreon-plugins/issues/5118

Userlevel 4
Badge +12

Thanks @derEdu!

We’ll examine it carefully, although due to the summer break it will probably wait a little…

  

 It works so far, but I’m a perl aprentice, not a perl magician like yourself. Don’t judge me too much and please take it into review. 

Believe me I’m just an old beginner 😆

No harsh judgement!

Reply