Configuration Options in Code or INI Files?

Recently I was admonishing my colleagues for embedding configuration options into Python code. I thought it was commonly accepted that all configuration options should be in text files that are not code. Typically in Python world this seems to be something like INI files, which are parsed to get to the values. Nowadays JSON could also be an option. After polling the opinions of some other colleagues, friends and others, it seems the situation is not as clear as I thought.

I think I have personally embedded configuration options in one case in production code, and felt dirty afterwards. But maybe I have just been living in the past, thinking the thoughts of a C/C++ programmer…

Some of the first things that come to my mind when thinking why configuration options should be in regular text files:

  • Text (INI format especially) is easier to edit than (Python) code
  • It is easier to reload configuration options from a regular text file
  • Code files should be read only
  • If you make a mistake in a code file, you will get an error that only programmers will understand
  • Loading configuration options from a regular text file offers better security

The counter arguments to those could include:

  • It is actually simpler to write complex structures in Python than INI, and you can use all of Python’s power
  • It can be pretty easy to reload Python modules as well (although you have to be careful with imports). Often there is no need to reload options.
  • Of course the code file would be made writable for only a brief period of time
  • If the target audience of the program are programmers, it makes perfect sense to show errors only programmers could understand. And you could even catch some errors and give nicer messages to end users.
  • The configuration file can be edited only by the super users (or the legitimate intended users of the program, and the program can not grant them more power than they would otherwise have)

I can think of a bunch more reasons but they all seem to follow pretty much the same pattern, with same pattern of counter arguments.

So if the intended users of the application were software engineers, systems administrators or others capable of deciphering Python tracebacks, and the program couldn’t grant the user more access to the system than they would otherwise have, I guess I don’t have a strong case against config-in-code.

But in most use cases I think the security implications are actually a pretty strong reason why config should be separate from code. You can lock down code as tightly as your system allows, and you can be as strict about parsing and loading values from text config file as you like. This doesn’t eliminate all security issues from config files, but it adds a layer of protection.

Similar Posts:

    None Found

10 Comments

  1. bc:

    Get (mostly) the best of both worlds: use YAML. I’m not sure if you can lock down YAML from a security POV though.

  2. JWK:

    A compromise i like is first check for the configuration file / environment value. If it is not there so use the internal value and add a log entry for that action. At least you can trace that behavior.

  3. bc:

    OK, I checked. PyYAML has a “safe_load” function which will only create basic types, hence avoiding the security-risk of loading an untrusted file which could create a malicious object.

  4. James Thiele:

    -1 on config options in code.

    Big downside is merging changes.

    Alice writes a program and gives copies to Bob, Carol, Dan and Ellen. They all edit their copies for personal config options. Alice finds a bug and sends out a new version. Now everybody has to do a diff/patch cycle. If the config options were in a seperate file they’d just drop in Alice’s new code.

  5. mkay:

    +1 on options in code

    Most “options” aren’t really options at the office. Some, like the Java class we should use to do X don’t have any other values, but the argument is that “someday we’ll need that”. Usually they are instances of over-engineering.

    I opt for the opposite and write straight-forward code. When something needs to become an option, then I move to a configuration file. Anything outside of the code needs a *lot* more documentation, maintenance, QA, etc.

  6. Marcos Dione:

    ini files are really the wrong solution for complex things. see, config files are mostly a way to reprogram a certain tool; it’s like the switches in the first programmable computers. implementing complex decisions with switches is difficult. for those cases I prefer coding your own decisions. an example I’m toying with right now is a email server; it’s routing table is complex enough to be more simple to implement by code rather than switches.

  7. Kevin:

    It’s python, do both. Write your INI in Python – keep the config separate from the code, but also keep it in code. Just import the config file. For long running daemons you can attempt to reload the file every x minutes or some such. This allows you to update your config without touching the application code, but gives you the power of Python for storing your config info in Dicts and such.

  8. Cory:

    I think you’re missing the most important reasons to use ini files, although you kind of dance around it.

    The reason not to use code is because ini files are not code. This is important. INI files are a declarative syntax; they cannot have ifs or loops. Files that have a pure-declarative syntax have the following advantages:

    – they can be losslessly transformed into another format (including code). Code files do not have this advantage; there’s always the risk that they contain an if block, which means you need an interpreter with a loaded namespace and runtime environment to understand them.

    – they can be machine-edited. Code can’t be machine edited in the general case, see above. You will want this if your package needs to be packaged in a .deb or .rpm for example; upgrade scripts take care of making edits around your users’ changes.

    – They can be safely transferred (provided you filter out passwords). Sending code over a wire is risky to the person receiving it, who must then interpret it. Declarative ini files aren’t code, and can be safely parsed.

  9. sage:

    I definitly use yaml too instead of ini files.
    yaml is easier to read than json (while every json file should be read by a yaml parser too)
    yaml is easier to abstract complex structure than ini files.

  10. zaur:

    Last time I been considering a Python Object Notation (PyON). It bases on python syntax. It could be considered as readable reconstructable representation for python objects. It dosn’t use eval/exec for reconstruction; it bases on AST interpretation. I think it could be usefull for configuration purposes.

    http://code.google.com/p/pyon/

    P.S. PyON project is very young but you already able to do interesting things 🙂