Re: How to test?

2020-04-25 Thread Manfred Lotz
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

2020-04-25 Thread Kor son of Rynar
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?

2020-04-25 Thread Cholo Lennon

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?

2020-04-25 Thread DL Neil via Python-list

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