analitics

Pages

Tuesday, February 11, 2020

Python 3.7.5 : Using the hug framework - part 001.

Today I will come with another tutorial series about the hug framework.
The hug framework is on the top 3 performing web frameworks for Python and comes with the cleanest way to create HTTP REST APIs on Python 3.
The official webpage can be found hug web page with a good area for learn.
Let's install this python package.
[mythcat@desk projects]$ mkdir hug_001
[mythcat@desk projects]$ cd hug_001/
[mythcat@desk hug_001]$ pip3 install hug --user
...
Successfully installed hug-2.6.1
The Hug is a framework that allows you to expose a single code in several ways:
  • a local package;
  • as an A.P.I.;
  • as a C.L.I.;
Let's create an app.py python script to see all of these options:
import hug

# local pkg 
@hug.local()
def get_products(product:hug.types.text):
        """Get product name"""
        return {"product":product.upper()}

# API
@hug.get()

# CLI
@hug.cli()
To test it I used this source code:
import hug

# local pkg 
@hug.get()
@hug.local()
def get_products(product:hug.types.text):
        """Get product name"""
        return {"product":product.upper()}
The rerver can be run with this command:
[mythcat@desk hug_001]$ hug -f app.py

/#######################################################################\
          `.----``..-------..``.----.
         :/:::::--:---------:--::::://.
        .+::::----##/-/oo+:-##----:::://
        `//::-------/oosoo-------::://.       ##    ##  ##    ##    #####
          .-:------./++o/o-.------::-`   ```  ##    ##  ##    ##  ##
             `----.-./+o+:..----.     `.:///. ########  ##    ## ##
   ```        `----.-::::::------  `.-:::://. ##    ##  ##    ## ##   ####
  ://::--.``` -:``...-----...` `:--::::::-.`  ##    ##  ##   ##   ##    ##
  :/:::::::::-:-     `````      .:::::-.`     ##    ##    ####     ######
   ``.--:::::::.                .:::.`
         ``..::.                .::         EMBRACE THE APIs OF THE FUTURE
             ::-                .:-
             -::`               ::-                   VERSION 2.6.1
             `::-              -::`
              -::-`           -::-
\########################################################################/

 Copyright (C) 2016 Timothy Edmund Crosley
 Under the MIT License


Serving on :8000...
OPen the browser with the http://localhost:8000/ or http://localhost:8000/products:
If you want to use the CLI then you need to make these changes in the source code:
import hug
# cli 
@hug.cli()
# local pkg 
@hug.get('/products')
@hug.local()
def get_products(product:hug.types.text):
        """Get product name"""
        return {"product":product.upper()}
# the main CLI
if __name__ == '__main__':
        get_products.interface.cli() 
I can see the help area from python:
[mythcat@desk hug_001]$ hug -f app.py -c help
app

Available Commands:

 - get_products: Get product name 
The hug help show the all arguments for use:
[mythcat@desk hug_001]$ hug --help
usage: hug [-h] [-v] [-f FILE] [-m MODULE] [-ho HOST] [-p PORT] [-n] [-ma]
           [-i INTERVAL] [-c COMMAND] [-s]

Hug API Development Server

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  -f FILE, --file FILE  file
  -m MODULE, --module MODULE
                        module
  -ho HOST, --host HOST
                        host
  -p PORT, --port PORT  A whole number
  -n, --no_404_documentation
                        Providing any value will set this to true
  -ma, --manual_reload  Providing any value will set this to true
  -i INTERVAL, --interval INTERVAL
                        A whole number
  -c COMMAND, --command COMMAND
                        command
  -s, --silent          Providing any value will set this to true 

Wednesday, January 22, 2020

Python 3.7.5 : Django security issues - part 003.

Let's update this subject today with another new tutorial.
In the last tutorial about Django security I wrote about python package named django-axes.
First, let's fix an old issue about a URL pattern that matches anything and expects an integer that generates errors like:
...
  File "/home/mythcat/.local/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1772, 
in get_prep_value
    ) from e
ValueError: Field 'id' expected a number but got 'favicon.ico'.
[22/Jan/2020 21:50:06] "GET /favicon.ico/ HTTP/1.1" 500 130547
Now, let's start my project:
[mythcat@desk ~]$ cd projects/
[mythcat@desk projects]$ cd django/
[mythcat@desk django]$ source env/bin/activate
Create a new folder named static in the test001 folder and add a icon file named favicon.ico.
(env) [mythcat@desk django]$ cd mysite/test001/
(env) [mythcat@desk test001]$ mkdir static 
In the settings.py file you need to have this source code:

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]
Change in the urls.py this line of source code to fix the error:
path('<int:author_id>/',views.index_next, name = 'index_next'),
Let's run the Django project server with:
(env) [mythcat@desk django]$ cd mysite/
(env) [mythcat@desk mysite]$ python3 manage.py runserver
I login into my admin area with user catalin and password adminadmin.
If you try to login with a bad password then the account is locked by django-axes python package.
Use this command to reset all lockouts and access records.
(env) [mythcat@desk mysite]$ python3 manage.py axes_reset
No attempts found.
Into admin area you can see the AXES area with Access attempts and Access logs.
Axes listens to the following signals from django.contrib.auth.signals to log access attempts.
In this case Axes lockout responses on failed user authentication attempts from login views.
The Access logs shows access log, see examples:
Jan. 22, 2020, 8:46 p.m.-127.0.0.1catalinMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36/admin/login/
Jan. 21, 2020, 6:42 p.m.Jan. 22, 2020, 8:45 p.m.127.0.0.1catalinMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36/admin/login/
You can set the axes into settings.py file , see this link.


Tuesday, January 21, 2020

Python 3.7.5 : Use Django Formsets.

Django Formsets manage the complexity of multiple copies of a form in a view.
This simplifies the task of creating a formset for a form that handles multiple instances of a model.
Let's start with my old project:
[mythcat@desk ~]$ cd projects/
[mythcat@desk projects]$ cd django/
[mythcat@desk django]$ source env/bin/activate
Into models.py I add these classes:
#create Inline Form with book and author
class Author(models.Model):
    author_book = models.CharField(max_length = 100)
    def __str__(self):
        return self.author_book

class Book(models.Model):
    book_name = models.CharField(max_length = 100)
    author_book_name = models.ForeignKey(Author,on_delete=models.CASCADE)
    def __str__(self):
        return self.book_name

(env) [mythcat@desk mysite]$ python3 manage.py makemigrations
Migrations for 'test001':
  test001/migrations/0004_author_book.py
    - Create model Author
    - Create model Book
(env) [mythcat@desk mysite]$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, axes, contenttypes, sessions, test001
Running migrations:
  Applying test001.0004_author_book... OK
Add the classes to admin.py:
from .models import Author, Book
...
admin.site.register(Author)
admin.site.register(Book)
Now you can log in into the admin area and add authors and then add books.

Add the source code to views.py:
...
# add to views.py Author and Book 
from .models import Author, Book
# Author , Book redirect 
from django.shortcuts import redirect
...
# author and book source code 
def index_next(request, author_id):
    author = Author.objects.get(pk=author_id)
    BookFormset = inlineformset_factory(Author,Book, fields=('book_name',))
    if request.method == 'POST':
        formset = BookFormset(request.POST,instance = author)
        if formset.is_valid():
            formset.save()
            return redirect('index_next',author_id = author_id)
    formset = BookFormset(instance = author)
    return render(request, 'index_next.html', {'formset': formset})
...
Let's fix the URL for the next step.
Add the source code to urls.py:
...
# add index_next to urls.py 
from test001.views import index_next
...
urlpatterns = [
    ...
    path('&lt author_id &gt',views.index_next, name = 'index_next'),
    ...
    ]
Add index_next.html file into the template folder and into this file write HTML5 with a form and one submit button.
In the form tag add this:
{{ formset.as_p }}
Run the runserver command:
(env) [mythcat@desk mysite]$ python3 manage.py runserver
Use this http://127.0.0.1:8000/1 to see the first on the database shown on the browser.
You can customize the output of inline form, see source code:
...
BookFormset = inlineformset_factory(Author,Book, fields=('book_name',), can_delete=False, extra=1)
...
See the full project on my GitHub account at django_chart project repo.

Monday, January 20, 2020

Python 3.7.5 : Django security issues - part 002.

The project can be found at this Github project.
Let's start with my default project and activate the env:
[mythcat@desk ~]$ cd projects/
[mythcat@desk projects]$ cd django/
[mythcat@desk django]$ source env/bin/activate
Let's install this python module:
(env) [mythcat@desk django]$ pip3 install django-axes --user
Make these changes into settings.py:
(env) [mythcat@desk django]$ cd mysite/
(env) [mythcat@desk mysite]$ ls
db.sqlite3  manage.py  mysite  test001
(env) [mythcat@desk mysite]$ cd mysite/
(env) [mythcat@desk mysite]$ vim settings.py 
Into your settings.py add axes:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'test001',
    'rest_framework',
    'axes'
] 
Add this source code in settings.py:
AUTHENTICATION_BACKENDS = [
    # AxesBackend should be the first backend in the AUTHENTICATION_BACKENDS list.
    'axes.backends.AxesBackend',

    # Django ModelBackend is the default authentication backend.
    'django.contrib.auth.backends.ModelBackend',
] 
Add axes.middleware.AxesMiddleware into MIDDLEWARE area:
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'axes.middleware.AxesMiddleware',
] 
Check the configuration with this command:
(env) [mythcat@desk mysite]$ cd ..
(env) [mythcat@desk mysite]$ python manage.py check
System check identified no issues (0 silenced).
Use this command to sync the database:
(env) [mythcat@desk mysite]$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, axes, contenttypes, sessions, test001
Running migrations:
  Applying axes.0001_initial... OK
  Applying axes.0002_auto_20151217_2044... OK
  Applying axes.0003_auto_20160322_0929... OK
  Applying axes.0004_auto_20181024_1538... OK
  Applying axes.0005_remove_accessattempt_trusted... OK
  Applying axes.0006_remove_accesslog_trusted... OK
Once Axes is is installed and configured, you can login and logout of your application via the django.contrib.auth views.
This python package can be integrated with some popular 3rd party packages such as Django Allauth, Django REST Framework, and other tools.
I will come with additional information about this python package in the future.

Saturday, January 18, 2020

Python 3.7.5 : Django security issues - part 001.

Django like any website development and framework implementation requires security settings and configurations.
Today I will present some aspects of this topic and then I will come back with other information.
1. First, check your security vulnerabilities by the following command:
[mythcat@desk django]$ source env/bin/activate
(env) [mythcat@desk django]$ cd mysite
(env) [mythcat@desk mysite]$ python3 manage.py check --deploy
...
  File "/home/mythcat/projects/django/mysite/mysite/settings.py", line 14
    <<<<<<< HEAD
     
This shows us the bad changes in source code, is added by GitHub features.
Let's run it again:
(env) [mythcat@desk mysite]$ python3 manage.py check --deploy
System check identified some issues:

WARNINGS:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. 
If your entire site is served only over SSL, you may want to consider setting a value and 
enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling
 HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site 
should be available over both SSL and non-SSL connections, you may want to either set this 
setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes 
it more difficult for network traffic sniffers to hijack user sessions.
?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have
 not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network
 traffic sniffers to steal the CSRF token.
?: (security.W018) You should not have DEBUG set to True in deployment.
?: (security.W020) ALLOWED_HOSTS must not be empty in deployment.
?: (security.W022) You have not set the SECURE_REFERRER_POLICY setting. Without this, your site 
will not send a Referrer-Policy header. You should consider enabling this header to protect user privacy.

System check identified 7 issues (0 silenced).
This output show us the security warnning problems.
2. Use the Observatory by Mozilla site to scan the security status of your Django website.
3. Django has built-in security against most forms of CSRF threats, but The CSRF protection cannot protect against man-in-the-middle attacks.
Use HTTPS with HTTP Strict Transport Security by add these lines in your settings.py file.
CSRF_COOKIE_SECURE = True #to avoid transmitting the CSRF cookie over HTTP accidentally.
SESSION_COOKIE_SECURE = True #to avoid transmitting the session cookie over HTTP accidentally.
4. A Cross-site Scripting (XSS) allows an attacker to inject a script into the content of a website or application.
In your settings.py use this:
django.middleware.security.SecurityMiddleware
...
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
5. You can create fake admin login page using django-admin-honeypot to attempt unauthorized access.
6. Use SSL Redirect on your settings.py file.
SECURE_SSL_REDIRECT = True
7. Add Content Security Policy (CSP) to your Django website with the installed django-csp, add following lines to your settings.py file:
# Content Security Policy
CSP_DEFAULT_SRC = ("'none'", )
CSP_STYLE_SRC = ("'self'", )
CSP_SCRIPT_SRC = ("'self'", )
CSP_IMG_SRC = ("'self'", )
CSP_FONT_SRC = ("'self'", )
# Google Tag Manager or Google Analytics should be allowed in your CSP policy. 
CSP_DEFAULT_SRC = ("'none'", )
CSP_STYLE_SRC = ("'self'", "fonts.googleapis.com", "'sha256-/3kWSXHts8LrwfemLzY9W0tOv5I4eLIhrf0pT8cU0WI='")
CSP_SCRIPT_SRC = ("'self'", "ajax.googleapis.com", "www.googletagmanager.com", "www.google-analytics.com")
CSP_IMG_SRC = ("'self'", "data:", "www.googletagmanager.com", "www.google-analytics.com")
CSP_FONT_SRC = ("'self'", "fonts.gstatic.com")
CSP_CONNECT_SRC = ("'self'", )
CSP_OBJECT_SRC = ("'none'", )
CSP_BASE_URI = ("'none'", )
CSP_FRAME_ANCESTORS = ("'none'", )
CSP_FORM_ACTION = ("'self'", )
CSP_INCLUDE_NONCE_IN = ('script-src',)
The HTTP Strict Transport Security can be set into your settings.py file:
SECURE_HSTS_SECONDS = 86400  # 1 day
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
8. Use records login attempts to your Django powered site and prevents attackers from brute forcing using the django-axes.
This tutorial solves most of the security issues of any website built with Django and not just related to this framework.




Saturday, January 11, 2020

Python 3.7.5 : About asterisk operators in Python.

The asterisk known as the star operator is used in Python with more than one meaning attached to it.
Today I will show you some simple examples of how can be used.
Let's start with these issues.
You can merge two or more dictionaries by unpacking them in a new one:
>>> a = {'u': 1}
>>> b = {'v': 2}
>>> ab = {**a, **b, 'c':'d'}
>>> ab
{'u': 1, 'v': 2, 'c': 'd'}
Create multiple assignments:
>>> *x, y = 1, 2, 3, 4
>>> x
[1, 2, 3]
You can split into lists and generate sets:
>>> *a, = "Python"
>>> a
['P', 'y', 't', 'h', 'o', 'n']
>>> print(a)
['P', 'y', 't', 'h', 'o', 'n']
>>> *a,
('P', 'y', 't', 'h', 'o', 'n')
>>> zeros = (0,) * 8
>>> print(zeros)
(0, 0, 0, 0, 0, 0, 0, 0)
For numeric data types is used as multiplication operator:
>>> 2 * 3
6
You can use in mathematical function as an exponent:
>>> 3**2
9
You can create a sequences of strings using it like a repetition operator:
>>> t = 'Bye!'
>>> t * 4 
'Bye!Bye!Bye!Bye!'
>>> p = [0,1]
>>> p * 4 
[0, 1, 0, 1, 0, 1, 0, 1]
>>> r = (0,1)
>>> r * 4
(0, 1, 0, 1, 0, 1, 0, 1)
You can used into definition with arguments: *args and **kwargs:
def set_zero(*args):
    result = 0
The *args will give you all function parameters as a tuple.
The **kwargs will give you all keyword arguments except for those corresponding to a formal parameter as a dictionary.
See the PEP 3102 about Keyword-Only Arguments.

Thursday, January 9, 2020

Python 3.7.5 : The this python package.

The this python package is simple to use:
[mythcat@desk ~]$ python3 
Python 3.7.5 (default, Dec 15 2019, 17:54:26) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Monday, January 6, 2020

Python 3.7.5 : Post class and migration process.

Today I will solve some issues with the Django framework like:
  • create a new class for posts;
  • explain how the migration process works.
  • use the database with Django shell;
Let's activate the environment:
[mythcat@desk django]$ source env/bin/activate
I used my old project django-chart, see my old tutorials.
Let's add some source code to the models.py to create a class for the post into my website:
...
# Post data 
from django.utils import timezone
from django.contrib.auth.models import User
...
#create a post
class Post(models.Model):
  title = models.CharField(max_length = 100)
  content = models.TextField()
  date_posted = models.DateTimeField(default = timezone.now)
  #if the user is deleted their posts is deleted 
  author = models.ForeignKey(User, on_delete = models.CASCADE)
Let's use the migration process to update the database:
(env) [mythcat@desk django]$ cd mysite/
(env) [mythcat@desk mysite]$ python3 manage.py makemigrations
Migrations for 'test001':
  test001/migrations/0003_post.py
  - Create model Post
Before to run the migrate command I will show what happened with this migration output from SQL view.
This is great to solve issues and see the exact SQL code generated.
I have in the output of command makemigrations the application name test001 and the migration number 0003.
I will use all of this information output to show how you can see the SQL code:
(env) [mythcat@desk mysite]$ python3 manage.py sqlmigrate test001 0003
BEGIN;
--
-- Create model Post
--
CREATE TABLE "test001_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
"title" varchar(100) NOT NULL, "content" text NOT NULL, "date_posted" datetime NOT NULL, 
"author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "test001_post_author_id_fed29ee6" ON "test001_post" ("author_id");
COMMIT;
This print SQL code that it's going to run when I will use the next command:
(env) [mythcat@desk mysite]$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, test001
Running migrations:
  Applying test001.0003_post... OK
The migration process solves issues linked to changes in the database.
Let's use the Django shell to see the User changes into the database:
(env) [mythcat@desk mysite]$ python3 manage.py shell
Python 3.7.5 (default, Dec 15 2019, 17:54:26) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from test001.models import Post
>>> from django.contrib.auth.models import User
>>> User.objects.all()
...
>>> User.objects.first()
...
>>> User.objects.filter(username='catalin')
...
>>> User.objects.filter(username='catalin').first()
...
>>> user = User.objects.filter(username='catalin').first()
>>> user
...
>>> user.id
1
>>> user.pk
1
>>> Post.objects.all()
...
Let's add a post to the database and show it:
>>> post_1=Post(title='First title', content='The first content!',author=user)
>>> post_1.save()
>>> Post.objects.all()
...
I can see the posts and information about the user with the Django shell.
>>> post = Post.objects.first()
>>> post.content
'The first content!'
>>> post.date_posted
...
>>> post.author
...
>>> post.author.email
...
>>> user.post_set.all()
...
You need to add to views.py the new model changes:
...
from .models import Post
...
def posts(request):
  context = {
  'posts':Post.objects.all()
  }
  return render(request, 'test001/posts.html', context)
...
Into the templates folder, I created the file named posts.html to load the data to HTML5.
{% extends 'base.html' %}
{% block content %}
  {% for post in posts %}
  <article>
  <div>{{ post.title }}</div>
  <div>{{ post.content }}</div>
  <div>{{ post.author }}</div>
  <div>{{ post.date_posted|date:"F d, Y" }}</div>
  </article>
  {% endfor %}
{% endblock content %}
To see these changes into the website I add the route to this HTML5 file posts.html into urls.py file:
app_name = 'test001'
urlpatterns = [
...
    path('posts/',posts, name = 'posts'),
...
]
Now I can run the server and see the output from the database into posts URL.
(env) [mythcat@desk mysite]$ python3 manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 06, 2020 - 17:52:29
Django version 3.0.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
...
This is the output of my running server...

Python 3.7.5 : Set json with settings in Django project.

[mythcat@desk django]$ source env/bin/activate
(env) [mythcat@desk django]$ cd mysite/
(env) [mythcat@desk mysite]$ ls
db.sqlite3  manage.py  mysite  test001
(env) [mythcat@desk mysite]$ pwd
/home/mythcat/projects/django/mysite
Create a file named config.json in the folder django:
(env) [mythcat@desk mysite]$ vim /home/mythcat/projects/django/config.json
Open your settings.py file from your Django project and copy your secret key from this file to config.json, see:
{ 
  "SECRET_KEY":"your_secret_key_from_settings.py"
}
Change your settings.py file with these changes:
...
import json 
...
with open('/home/mythcat/projects/django/config.json') as config_file:
    config = json.load(config_file)
...
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config['SECRET_KEY']
This allows us to get the SECRET_KEY from the config.json file.
We can add many variables into file config.json, like EMAIL_USER and EMAIL_PASS.
You need to have a validate JSON file and the settings.py will change from this:
EMAIL_HOST_USER = os.environ.get('EMAIL_USER')
...
to this source code for EMAIL_USER variable:
EMAIL_HOST_USER = config.get('EMAIL_USER')
...

Sunday, January 5, 2020

Python 3.7.5 : Testing cryptography python package - part 001.

There are many python packets that present themselves as useful encryption and decryption solutions. I recommend before you test them, use them and spend time with them to focus on the correct study of cryptology because many disadvantages and problems can arise in the correct and safe writing of the source code.
Today I will show you a simple example with cryptography python package.
Let's install this with pip3 tool:
[mythcat@desk projects]$ pip3 install cryptography --user
You can read more about this python package on the documentation website.
Let's try a simple method of encryption and decryption.
I will show you how to solve this issue with the class cryptography.hazmat.primitives.ciphers.aead.AESGCM:
The AES-GCM construction is composed of the AES block cipher utilizing Galois Counter Mode (GCM).
The GCM (Galois Counter Mode) is a mode of operation for block ciphers.
An AEAD (authenticated encryption with additional data) mode is a type
of block cipher mode that simultaneously encrypts the message as well as authenticating it.

The Value of AESGCM key must be 128, 192, or 256 bits, see the size of the key:
[mythcat@desk projects]$ python3
Python 3.7.5 (default, Dec 15 2019, 17:54:26) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> from cryptography.hazmat.primitives.ciphers.aead import AESGCM
>>> aad = None
>>> key = 'catafestcatafestcatafestcatafest'
>>> aesgcm = AESGCM(key.encode('utf-8'))
>>> nonce = '12345678'
>>> data_binary = b'Hello world!'
>>> 
>>> cipher_text = aesgcm.encrypt(nonce.encode('utf-8'), data_binary, aad)
>>> print(cipher_text)
b'0\xab\xd2!mXe\xc3/\xdb\x15\xcaoT\x0f\x1d\xbb&\xc4\x92\xdf\\ZTMD\xa2\x9f'
>>> data_text = aesgcm.decrypt(nonce.encode('utf-8'), cipher_text, aad)
>>> print(data_text)
b'Hello world!'

Saturday, January 4, 2020

Python 3.7.5 : Testing the PyMongo package - part 001.

MongoDB and PyMongo are not my priorities for the new year 2020 but because they are quite evolved I thought to start presenting it within my free time.
The PyMongo python package is a Python distribution containing tools for working with MongoDB.
The full documentation can be found on this webpage.
You can see my tutorial about how to install the MongoDB into Fedora 31 on this webpage.
I used that webpage install to test this python package, see the result:
[mythcat@desk mongo_test]$ mongo
...
MongoDB server version: 4.2.2-rc1
> use admin 
switched to db admin
> show dbs
> db.auth('admin', 'admin')
1
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
Let's install it with pip3 tool:
[mythcat@desk projects]$ pip3 install pymongo --user
Collecting pymongo
...
Successfully installed pymongo-3.10.0
Let's start with a simple example:
[mythcat@desk projects]$ mkdir mongo_test
[mythcat@desk projects]$ cd mongo_test/
[mythcat@desk mongo_test]$ vim mongo001.py
If you have already created the admin user, to run the next spython script you need to change the role like this:
> use admin;
switched to db admin
> db.grantRolesToUser('admin', [{ role: 'root', db: 'admin' }])
The script show you how to use a simple connection to the MongoDB:
import pymongo
from pymongo import MongoClient, errors

MONGO_URI = 'mongodb://admin:admin767779@127.0.0.1:27017/admin'
client = pymongo.MongoClient(MONGO_URI)
print("Server info : ")
print(client.server_info())
print("Databases : " + str(client.list_database_names()))
print("Connect to : admin database!")
db = client['admin']
db2 = client.config
print(db)
print(db2)
print("Collection admin : ")
collection = db['admin']
collection2 = db.config
print(collection)
print(collection2)
print("try call find_one method")
try:
    one_doc= collection2.find_one()
    print ("find_one():", one_doc)
except errors.ServerSelectionTimeoutError as err:
    print ("find_one() ERROR:", err)

print("Client close!")
client.close()
The output is this:
[mythcat@desk mongo_test]$ python3 mongo001.py 
Server info : 
{'version': '4.2.2-rc1', 'gitVersion': 'a0bbbff6ada159e19298d37946ac8dc4b497eadf', 'modules': [],
 'allocator': 'tcmalloc', 'javascriptEngine': 'mozjs', 'sysInfo': 'deprecated', 'versionArray': [4, 2, 2, -49],
 'openssl': {'running': 'OpenSSL 1.1.1d FIPS  10 Sep 2019', 'compiled': 'OpenSSL 1.1.1 FIPS  11 Sep 2018'},
 'buildEnvironment': {'distmod': 'rhel80', 'distarch': 'x86_64', 'cc': '/opt/mongodbtoolchain/v3/bin/gcc:
 gcc (GCC) 8.2.0', 'ccflags': '-fno-omit-frame-pointer -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare
 -Wno-unknown-pragmas -Winvalid-pch -Werror -O2 -Wno-unused-local-typedefs -Wno-unused-function
 -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable
 -Wno-missing-braces -fstack-protector-strong -fno-builtin-memcmp', 'cxx': '/opt/mongodbtoolchain/v3/bin/g++:
 g++ (GCC) 8.2.0', 'cxxflags': '-Woverloaded-virtual -Wno-maybe-uninitialized -fsized-deallocation -std=c++17',
 'linkflags': '-pthread -Wl,-z,now -rdynamic -Wl,--fatal-warnings -fstack-protector-strong -fuse-ld=gold -Wl,
--build-id -Wl,--hash-style=gnu -Wl,-z,noexecstack -Wl,--warn-execstack -Wl,-z,relro', 'target_arch':
 'x86_64', 'target_os': 'linux'}, 'bits': 64, 'debug': False, 'maxBsonObjectSize': 16777216, 'storageEngines':
 ['biggie', 'devnull', 'ephemeralForTest', 'wiredTiger'], 'ok': 1.0}
Databases : ['admin', 'config', 'local']
Connect to : admin database!
Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), 'admin')
Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), 'config')
Collection admin : 
Collection(Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True),
 'admin'), 'admin')
Collection(Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True),
 'admin'), 'config')
try call find_one method
find_one(): None
Client close!


Thursday, January 2, 2020

Python 3.7.5 : Testing the Falcon framework - part 001.

I start the new year with this python framework named Falcon.
The Falcon is a low-level, high-performance Python framework for building HTTP APIs, app backends, and higher-level frameworks.
The main reason was the speed of this python framework, see this article about falcon benchmark.
You can see is more faster like Flask and Django.
The instalation is easy with pip tool, you can read also the documenation webpage:
[mythcat@desk projects]$ mkdir falcon_test
[mythcat@desk projects]$ cd falcon_test/
[mythcat@desk falcon_test]$ pip3 install falcon --user
Collecting falcon
...
Successfully installed falcon-2.0.0
Falcon also fully supports CPython 2.7 and 3.5+.
If you want to install the latest beta or release candidate use:
[mythcat@desk falcon_test]$ pip3 install --pre falcon --user
The Falcon framework is easy to use.
First, I created a folder named test001 for my falcon application script named app.py:
[mythcat@desk falcon_test]$ mkdir test001
[mythcat@desk falcon_test]$ cd test001/
[mythcat@desk test001]$ vim app.py
In this python script I used python packages json and falcon with a class named req_class:
import json
import falcon

class req_class:
    def on_get(self,req,resp):
        print("on_get class")
my_falcon_api = falcon.API()
my_falcon_api.add_route('/test',req_class())
The url route is set to test.
To test the falcon framework we need the Gunicorn python package.
The Gunicorn is working on my Fedora Linux distro and I'm not sure if working Gunicorn on Windows.
You can try on Windows O.S. the waitress python package.
[mythcat@desk falcon_test]$ pip3 install gunicorn --user
Collecting gunicorn
...
Successfully installed gunicorn-20.0.4
To test this simple Falcon application use this command line where the app python script and my falcon variable A.P.I. named my_falcon_api is used.
[mythcat@desk test001]$ gunicorn app:my_falcon_api
[2020-01-02 18:57:48 +0200] [4401] [INFO] Starting gunicorn 20.0.4
[2020-01-02 18:57:48 +0200] [4401] [INFO] Listening at: http://127.0.0.1:8000 (4401)
[2020-01-02 18:57:48 +0200] [4401] [INFO] Using worker: sync
[2020-01-02 18:57:48 +0200] [4404] [INFO] Booting worker with pid: 4404
on_get class
on_get class
Open in the browser this URL with the route I set: http://127.0.0.1:8000/test.
You will don't see anything in the browser but will see the python output of the print function for my request.

Tuesday, December 31, 2019

News : The Python 2.7 no longer support from Python team.

The 1st of January 2020 will mark the sunset of Python 2.7.
It’s clear that Python 3 is more popular these days.
You can learn more about the popularity of both on Google Trends.
Python 3.0 was released in December 2008.
The main goal was to fix problems existing in Python 2.
Since the 1st January 2020, Python 2 will no longer receive any support whatsoever from the core Python team.
Migrating to Python 3 is recommended, including some of the top libraries, such as machine learning.