Re: How to test?
On Sat, 25 Apr 2020 18:41:37 +1200
DL Neil wrote:
> On 25/04/20 5:16 PM, Manfred Lotz wrote:
> > On Fri, 24 Apr 2020 19:12:39 -0300
> > Cholo Lennon wrote:
> >
> >> On 24/4/20 15:40, Manfred Lotz wrote:
> >>> I have a command like application which checks a directory tree
> >>> for certain things. If there are errors then messages will be
> >>> written to stdout.
> >>>
> >>> How to test this in the best way?
> >>>
> >>> One idea was for the error situations to write messages to files
> >>> and then later when running the tests to compare the error
> >>> messages output to the previously saved output.
> >>>
> >>> Is there anything better?
> >>>
> >>>
> >>
> >> Maybe I am wrong because I don't understand your scenario: If your
> >> application is like a command, it has to return an error code to
> >> the system, a distinct number for each error condition. The error
> >> code is easier to test than the stdout/stderr.
> >>
> >
> > Yes, a different error code for each condition is good to test.
> > However, I need to test as well the correct file name and other
> > values belonging to a certain error condition.
>
> It is frustrating to be shown only part of the information, and later
> be told our efforts aren't good-enough.
I found the tips I got here quite good. Actually, each time when I had
a questions here I got competent answers.
> How about respecting our
> (donated) time, and posting some sample code that shows exactly
> what/where the problem lies?
>
Sorry, perhaps I was too lazy to explain. Hope the following
explanation isn't too bad.
What I do here specifically is to check directory trees' file objects
for user and group ownerships as well as permissions according to a
given policy. There is a general policy and there could be exceptions
which specify a specific policy for a certain file.
The policy file is a JSON file and could have different categories.
Each category defines a policy for a certain directory tree. Comand
line args could overwrite directory names, as well as user and group.
Or if for example a directory is not specified in the JSON file I am
required to specify it via command line. Otherwise no check can take
place.
Here an example of a simple json file:
default":
{
"match_perms": "644",
"match_permsd": "755",
"match_permsx": "755",
"owner": "manfred",
"group": "manfred"
}
}
another simple example:
{
"default":
{
"have_all_permsx" : "555",
"have_all_perms" : "444",
"have_all_permsd" : "555",
"owner": "manfred",
"group": "manfred"
}
}
class Category contains a policy.
Here a simplified version of Category
class Category:
def __init__(self, cat, jsoncat, dirdict, ownerdict, groupdict):
self.cat = cat
self.jsoncat = jsoncat
self.keep_fs = jsoncat.get('keep_fs')
self.dir = jsoncat.get('dir')
if dirdict.get(cat):
self.dir = os.path.realpath(dirdict[cat])
self.policy = Policy(jsoncat, ownerdict, groupdict)
def check(self, fpath):
self.policy.check(fpath)
It is important to note that ownerdict and groupdict are overwrites
from the command line, and could be empty if nothing was
specified.
In my main routine I do this
...
for cat in cats:
...
for d in scantree(cat.dir):
# if `keep_fs` was specified then we must
# make sure the file is on the same device
if cat.keep_fs and devid != get_devid(d.path):
continue
cat.check(d)
...
class Policy contains required user and group owners and a
list of permission objects for files, for executable files and for
directories.
Those permissions are described like this
class BasePerms:
def __init__(self, perms: str):
"""Create an object holding a permission which is octal"""
self.perms = int(perms, 8)
class MatchPerms(BasePerms):
def check(self, fpath: str, mode: int):
mode = mode & 0o
if mode != self.perms:
print("%s perms differ, should have %s has %s" % (fpath,
oct(self.perms), oct(mode)))
class HaveAllPerms(BasePerms):
def check(self, fpath: str, mode: int):
mode = mode & 0o
if (mode & self.perms) != self.perms:
print("%s: perms differ, should have all of %s has %s" % (fpath,
oct(self.perms), oct(mode)))
After getting some ideas here I want to change my code to return an
error object in check() instead of doing a print(). Or return None
if all is ok.
Then the error object could have a print-like method and a compare
method so that later on when doing a test I could compare two error
objects. Perhaps I can combine it with callback. I have to play with
these things.
--
Manfred
--
https://mail.python.org/mailman/listinfo/python-list
Re: Secure Coding in Python
Dear Souvik, On Fri, Apr 10, 2020 at 9:53 PM Souvik Dutta wrote: > Is this what you are looking for? > https://medium.com/@felsen88/python-secure-coding-guidelines-73c7ce1db86c > Thank you very much for the link. Yes, it is along those lines, although the reference above has more links to good coding style practices (also important, of course) than actual secure coding advice, IMHO. For example, any idiom or library you would recommend for input validation? [potentially malicious input from the cmdline arguments, Unix environment, network socket, etc] Thanks again, -- Kor > On Sat, 11 Apr, 2020, 3:54 am Kor son of Rynar, > wrote: > >> Dear list, >> >> As many of you know, SEI/CERT maintains a set of secure coding standards >> for many languages like C/C++, Java and Perl: >> >> SEI CERT Coding Standards >> >> >> https://wiki.sei.cmu.edu/confluence/display/seccode/SEI+CERT+Coding+Standards >> >> I'm looking for something similar, but with specific advice applicable to >> Python. Books and online references are welcome. >> >> On the same topic: coming from Perl, I'm used to "Taint mode": >> -- >> https://perldoc.perl.org/perlsec.html >> >> While in this mode, Perl takes special precautions called taint checks to >> prevent both obvious and subtle traps. Some of these checks are reasonably >> simple, such as verifying that path directories aren't writable by others; >> careful programmers have always used checks like these. Other checks, >> however, are best supported by the language itself, and it is these checks >> especially that contribute to making a set-id Perl program more secure >> than >> the corresponding C program. >> >> You may not use data derived from outside your program to affect something >> else outside your program--at least, not by accident. All command line >> arguments, environment variables, locale information (see perllocale), >> results of certain system calls (readdir(), readlink(), the variable of >> shmread(), the messages returned by msgrcv(), the password, gcos and shell >> fields returned by the getpwxxx() calls), and all file input are marked as >> "tainted". Tainted data may not be used directly or indirectly in any >> command that invokes a sub-shell, nor in any command that modifies files, >> directories, or processes, ... >> -- >> >> Is there anything like this in Python? What would be your >> recommendations? Thanks! >> >> Regards, >> -- >> Kor. >> -- >> https://mail.python.org/mailman/listinfo/python-list >> > -- https://mail.python.org/mailman/listinfo/python-list
Re: How to test?
On 4/25/20 2:16 AM, Manfred Lotz wrote: On Fri, 24 Apr 2020 19:12:39 -0300 Cholo Lennon wrote: On 24/4/20 15:40, Manfred Lotz wrote: I have a command like application which checks a directory tree for certain things. If there are errors then messages will be written to stdout. How to test this in the best way? One idea was for the error situations to write messages to files and then later when running the tests to compare the error messages output to the previously saved output. Is there anything better? Maybe I am wrong because I don't understand your scenario: If your application is like a command, it has to return an error code to the system, a distinct number for each error condition. The error code is easier to test than the stdout/stderr. Yes, a different error code for each condition is good to test. However, I need to test as well the correct file name and other values belonging to a certain error condition. So, I though that you were testing your application from an "external point of view", running it and validating its behavior. This is not the case... if you need such degree of control over its functionality, IMHO, you just need a unit test framework to validate every part of it. If you still need to execute the application to test it, the best way, as other suggested, it is to log the working conditions. You can design very well the log information in order to simplify the parsing of it. -- Cholo Lennon Bs.As. ARG -- https://mail.python.org/mailman/listinfo/python-list
Re: How to test?
On 25/04/20 7:53 PM, Manfred Lotz wrote: On Sat, 25 Apr 2020 18:41:37 +1200 DL Neil wrote: On 25/04/20 5:16 PM, Manfred Lotz wrote: On Fri, 24 Apr 2020 19:12:39 -0300 Cholo Lennon wrote: On 24/4/20 15:40, Manfred Lotz wrote: I have a command like application which checks a directory tree for certain things. If there are errors then messages will be written to stdout. > What I do here specifically is to check directory trees' file objects > for user and group ownerships as well as permissions according to a > given policy. There is a general policy and there could be exceptions > which specify a specific policy for a certain file. If I have understood correctly, the objective is to check a dir-tree to ensure that specific directory/file-permissions are in-effect/have not been changed. The specifications come from a .JSON file and may be over-ridden by command-line arguments. Correct? There must be a whole 'genre' of programs which inspect a directory-tree and doing 'something' to the files-contained. I had a few, and needing another, decided to write a generic 'scanner' which would then call a tailored-function to perform the particular 'something' - come to think of it, am not sure if that was ever quite finished. Sigh! > One idea was for the error situations to write messages to files > and then later when running the tests to compare the error > messages output to the previously saved output. > > Is there anything better? The next specification appears to be that you want a list of files and their stats, perhaps reporting only any exceptions which weren't there 'last time'. In which case, an exception could be raised, or it might be simpler to call a reporting-function when a file should be 'reported'. I'm still a little confused about the difference between printing/logging/reporting some sort of exception, and the need to compare with 'history'. The problem with the "previously saved output" is the process of linking 'today's data' with that from the last run. I would use a database (but then, that's my background/bias) to store each file's stat. Alternately, if you only need to store exceptions, and that number is likely to be small, perhaps output only the exceptions from 'this run' to a .JSON/.yaml file - which would become input (and a dict for easy look-ups) next time? Maybe I am wrong because I don't understand your scenario: If your application is like a command, it has to return an error code to the system, a distinct number for each error condition. The error code is easier to test than the stdout/stderr. Either way, you might decrease the amount of data to be stored by reducing the file's stat to a code. How to test this in the best way? The best way to prepare for unit-testing is to have 'units' of code (apologies!). An effective guide is to break the code into functions and methods, so that each performs exactly one piece/unit of work - and only the one. A better guide is that if you cannot name the procedure using one description and want to add an "and" an "or" or some other conjunction, perhaps there should be more than one procedure! For example: >for cat in cats: > ... > for d in scantree(cat.dir): > # if `keep_fs` was specified then we must > # make sure the file is on the same device > if cat.keep_fs and devid != get_devid(d.path): > continue > > cat.check(d) If this were a function, how would you name it? First of all we are processing every category, then we are scanning a dir-tree, and finally we are doing something to each directory found. If we split these into separate routines, eg (sub-setting the above): > for d in scantree(cat.dir): do_something_with_directory( d ) and you devise a (much) more meaningful name than mine, it will actually help readers (others - but also you!) to understand the steps within the logic. Now if we have a function which checks a single fileNM for 'whatever', the code will start something like: def stat_file( fileNM ): '''Gather stat information for nominated file.''' etc So, we can now write a test-function because we don't need any "categories", we don't need all the dir-tree, and we don't need to have performed a scan - all we need is a (valid and previously inspected) file-path. Thus (using Pytest): def test_stat_file( ... ): '''Test file stat.''' assert stat_file( "...file-path" ) == ...its known-stat def test_stat_dir( ... ): '''Test file stat.''' assert stat_file( "...dir-path" ) == ...its known-stat There is no need to test for a non-existent file, if you are the only user! In case you hadn't thought about it, make the test path, part of your test directory - not part of 'the real
