2

i'm currently working on a project for dns-enumeration, which sends requests to various APIs. Some of these APIs require an API-Key, which i provide in a config.ini file. In my current setup I use configparser to read-in the different values into an object, so i can access the object when needed. Now, as I try to implement something like a class structure, i would like to read-in the config file once in the init of a parent class, so i can inherit every tool that needs an API-Key from that class.

Right now the setup looks something like this:

class Source:
    def __init__(self):
        config = configparser.ConfigParser()
        config.read('./config.ini')
        self.config = config

class BinaryEdge(Source):
    def __init__(self):
        super().__init__()

    def query(self, domain, dnsprobe):
        api_key = self.config['BINARYEDGE']['API-KEY']
        url = 'https://api.binaryedge.io/v2/query/domains/subdomain/' + domain
        fqdns = []
        ...

In my understanding, if i initiate a new BinaryEdge-Instance, for example like this:

if __name__ == "__main__":
    BinaryEdge = BinaryEdge()
    print(BinaryEdge.query("heise.de", False))

It technically should read in the config file into an object and pass it to the newly created object, so i can access it via self.config, something like this:

 def query(self, domain, dnsprobe):
        api_key = self.config['BINARYEDGE']['API-KEY']
        url = 'https://api.binaryedge.io/v2/query/domains/subdomain/' + domain
        fqdns = []
        ...

But when im debugging this setup, the config object stays default (and threrefore empty), which obviously leads straight into a key error:

File "/usr/lib64/python3.9/configparser.py", line 960, in __getitem__
    raise KeyError(key)
KeyError: 'BINARYEDGE'

As im not as good in python programming as i would like to be, i'm struggling solving this error on my own and would be thankful for any advancing input.

  • Try `print(self.config.sections())` in `Source` and `BinaryEdge` constructors. So we can see if it really changes. Are you sure you're not just misspelling the `['BINARYEDGE']['API-KEY']` keys? – Jakub Szlaur Jan 22 '21 at 10:31
  • Thats what the print gets me, im pretty sure, that i did not misspell the key ;-): Print on Source_init: Print on BinaryEdge_init: Print on BinaryEdge_query: – Kokaninchen Jan 22 '21 at 10:35
  • Try the `print(self.config.sections())`. I think you are misspelling the `['BINARYEDGE']['API-KEY']` keys. – Jakub Szlaur Jan 22 '21 at 10:36
  • 1
    the self. config.sections leads to [] on every output :/ I have an already running version without the class-environment, with the same keys (c+p) and it works (that was the first thing i checked ;-) ) – Kokaninchen Jan 22 '21 at 10:38
  • Then it seems that the module didn't even read the file. Or that it does not have any sections (which is sure not the case because you want to read something from it). 1) Are you sure you have the right path to the file? 2) Look into the file if something is there or it's empty. – Jakub Szlaur Jan 22 '21 at 10:42

2 Answers2

3

I figured it out myself after getting input from @Jakub Szlaur:

My file-path pointed to the wrong folders, therefore the config.ini file was never reached.

After changing:

config.read('./config.ini')

to

config.read('$HOME/$PROJECT_PATH/config.ini')

it worked as expected.

I also changed the "Source"-Class according to the comments for "better code-style":

class Source:
    def __init__(self):
        self.config = self.readconfig('../config.ini')
        
    def readconfig(self, filename):
        config = configparser.ConfigParser()
        config.read(filename)
        return config

Thanks for the help! ;-)

0

The code looks like it should work (I can't find any errors). Try checking your config file to see whether there really is such a key.

But about the code itself, there are a couple of things that I would recommend changing.

First, although reading the config is part of the initialisation of Source, it would be better if you made it a function, then called that function:


class Source:
    def __init__(self):
        self.config = self.readconfig("./config.ini")

    def readconfig(self, filename):
        config = configparser.ConfigParser()
        config.read(filename)
        return config

Never do this: BinaryEdge = BinaryEdge(). If you wanted to make another instance of BinaryEdge, it would call the BinaryEdge variable instead. Name it something different.