Archives par mot-clé : sécurité

ODOO 8 – Configuration firewall sur Debian

Avant le déploiement d'un serveur ODOO sur un nouveau serveur Debian, il faut bien entendu protéger son serveur Debian par des règles firewall ("iptables filter").

Lors de l'installation d'un serveur Debian, aucune règle firewall n'est configurée.

La commande suivante (en étant connecté "root")
iptables -L
... affiche le résultat (pas de règles) :
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

Avant de configurer les règles firewall, il faut installer le paquet suivant qui permet de persister les règles au reboot du serveur debian :
apt-get install iptables-persistent

Ensuite, soit j'utilise Webmin pour configurer mes règles (plus simple que les commandes en ligne), soit je récupère les règles d'un autre serveur debian (les mêmes règles reviennent souvent) par la commande :
iptables-save > /tmp/iprules.txt

Je transfère ensuite le fichier iprules.txt sur mon serveur à configurer puis je lance la commande :
iptables-restore -c < /tmp/iprules.txt

Je peux éventuellement les modifier par webmin.

Enfin, il faut les sauvegarder (exemple en IP v4) :
iptables-save > /etc/iptables/rules.v4

ODOO 8 – exemple de gestion multi-sociètés

Objectif
Gestion d'un réseau de franchises qui propose des services à des particuliers.

Nous nous limiterons à un périmètre fonctionnel restreint : gestion des ventes et comptabilité.

Les franchises sont autonomes et indépendantes les unes des autres.
La socièté mère via un coordinateur, a un accès total aux franchises et en particulier, peut réaliser des opérations pour le compte d'une franchise (création client, devis, facture ...).
Ces opérations doivent être ensuite accessibles en accès total par la franchise concernée ... sans que les autres franchises y aient accès.

Description
Nous partons d'une base ODOO v8 vierge ...

- Installation des modules gestion des vents (sales) et comptabilité France (I10n_fr)
- Installation de toutes les fonctions "comptabilité"

 - Configuration de l'utilisateur "Administrator" à Multi-sociètés (menu Configuration>Utilisateurs)

- Création des sociètés SM (Socièté Mère), Franchise1 et Franchise2

- Rattacher les franchises à la société mère

- Création du plan comptable pour chaque franchise

- Création d'un utilisateur par franchise, rattaché à sa franchise et avec comme sociètés autorisées SM et Franchise1 (ou Franchise2) et droits d'accès "responsable ventes" et "comptable" :

- Création du coordinateur de la socièté mère avec comme sociètés autorisées Franchise 1 et Franchise 2 en plus de SM et droits d'accès "responsable ventes" et "responsable finances" :

- Création de l'article "Service1" rattaché à aucune socièté

Remarque: ne pas cocher l'option "gérer plusieurs sociétés" dans "paramètres généraux" (cette option est nécessaire pour des produits "stockables", elle n'est pas nécessaire pour des services)

>>> Il faut maintenant intervenir sur les règles d'enregistrement (record rules) pour modifier les droits d'accès sur certains objets.

Ces règles vont permettre à une franchise d'accèder totalement aux objets créés par le coordinateur de la socièté mère pour son compte.

Pour cela, il faut se rendre dans le menu "Configuration>Technical>Sécurité>Règles sur les enregistrements" :

- Devis/Bon de commande :
Modifier la règle "Sales Order multi-company" avec la valeur :
['|','|',('company_id','=',False),('company_id','child_of',[user.company_id.id]),('partner_id.parent_id.company_id','in',[user.company_id.id])]

 - Facture
Modifier la règle "Invoice multi-company" avec la valeur :
['|','|',('company_id','=',False),('company_id','child_of',[user.company_id.id]),('commercial_partner_id.company_id','in',[user.company_id.id])]

- Client
Modifier la règle "res.partner company" avec la valeur :
['|','|',('company_id','=',False),('company_id','child_of',[user.company_id.id]),('parent_id.company_id','in',[user.company_id.id])]

- Détail facture (account.move)
Modifier la règle "Account Entry" avec la valeur :
['|','|',('company_id','=',False),('company_id','child_of',[user.company_id.id]),('partner_id.company_id','in',[user.company_id.id])]

Bien entendu, nous nous limitons à ces quelques règles car nous n'utilisons ici que les 2 modules "ventes" et "comptabilité". 
Il faudrait effectuer le même type de modification sur d'autres règles si d'autres modules étaient installés.

Pour terminer, précisons que ces règles peuvent être modifiées directement en base de données sans risque d'écrasement par un update de module, grâce à la clause "data noupdate=1" présente à la création des règles :

extrait fichier "sale_security.xml"

 

ODOO 8 – accès mixte http/https au CMS et au Back-Office (2/2)

!! mise à jour le 04/12/2014 !!

L'objectif est d'accéder au CMS en http et au Back-office en https.
Cela permet :

  • d'éviter d'acheter un certificat ssl pour l'accès des internautes au CMS
  • d'accéder en https au Back-Office grâce à un certificat ssl auto-signé et gratuit 

Après avoir réalisé plusieurs tests, j'arrive à la conclusion qu'il est très difficile de trouver une configuration Nginx réellement opérationnelle.
Même si on y arrivait, elle serait extrêmement sensible à toute évolution ultérieure de Odoo.
Cela conforte donc la remarque de SISalp concernant cette "fausse bonne idée".
Je déconseille donc désormais cette solution !!

Environnement technique
- serveur virtualisé Debian 7.3 (wheezy) sur lequel est installé ODOO
- navigateur sur PC Linux Mint 14  à partir duquel on accède à ODOO

Description 

Se connecter sur le serveur debian avec les droits "root"
- installer nginx
apt-get install nginx

- créer les clés ssl
mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
openssl rsa -passin pass:x -in server.pass.key -out server.key
rm server.pass.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

- créer le fichier de configuration
 vi /etc/nginx/sites-available/votre_site.com

... avec le contenu suivant (désormais déconseillé) :

upstream odoosrv {
    server 127.0.0.1:8069;
}

server {
    listen      80 default;
    server_name votre_site.com www.votre_site.com;
    access_log  /var/log/nginx/odoosrv.access.log;
    error_log   /var/log/nginx/odoosrv.error.log;



    location ~ ^/(sitemap.xml) {
        root /var/www;
    }
    location /website/static/ {
        proxy_cache_valid 200 60m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://odoosrv;
    }
    location /web/static/ {
        proxy_cache_valid 200 60m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://odoosrv;
    }
    location /web/login {
        rewrite ^/.*$ https://$host$request_uri? permanent;
    }

    location /web/database/ {
        rewrite ^/.*$ https://$host$request_uri? permanent;
    }
    location / {
        proxy_pass  http://odoosrv;
    }
}

server {
    listen      443;

    server_name votre_site.com www.votre_site.com;

    ssl on;
    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    keepalive_timeout   60;

    ssl_ciphers             HIGH:!ADH:!MD5;
    ssl_protocols           SSLv3 TLSv1;
    ssl_prefer_server_ciphers on;

    proxy_buffers 16 64k;
    proxy_buffer_size 128k;

    location /web/static/ {
        proxy_cache_valid 200 60m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://odoosrv;
    }

    location ~ /. {
        proxy_pass  http://odoosrv;

        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;

        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto https;
    }

    location /page {
    return 301 http://$host$request_uri;
    }

    location / {
    return 301 http://$host$request_uri;
    }
}

- créer le lien symbolique
ln -s /etc/nginx/sites-available/votre_site.com /etc/nginx/sites-enabled/votre_site.com

- relancer nginx
/etc/init.d/nginx restart

N'étant pas spécialiste de Nginx, je suis preneur de toute proposition d'optimisation du fichier précédent. Merci d'avance.

*** Pour sécuriser un  site en production, il faudrait protéger beaucoup plus les accès au back-office :

  • en interdisant (via firewall) tout port autre que 80 et 443
  • en demandant une authentification supplémentaire sur le serveur web pour le port 443
  • en interdisant l'accès à la location /web/database/manager qui permet d'administrer les bases
  • etc ...

*** exemple de sitemap.xml à ajouter sous /var/www
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>http://www.agipme.fr/website/info</loc>
    </url>
    <url>
        <loc>http://www.agipme.fr/</loc>
    </url><url>
        <loc>http://www.agipme.fr/page/aboutus</loc>
        <lastmod>2014-11-20</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/actualites</loc>
        <lastmod>2014-11-20</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/a-propos</loc>
        <lastmod>2015-01-02</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/blog</loc>
        <lastmod>2015-01-08</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/contactus</loc>
        <lastmod>2014-12-05</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/faq</loc>
        <lastmod>2015-01-03</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/mention-legale</loc>
        <lastmod>2015-01-08</lastmod>
    </url><url>
        <loc>http://www.agipme.fr/page/odoo</loc>
        <lastmod>2015-01-09</lastmod>
    </url>
</urlset>

Authentification SSO OpenERP / Google

L'objectif est de permettre une authentification unique OpenERP/Google.
Plus précisément, il suffira de s'authentifier à Google pour accèder ensuite à OpenERP sans s'authentifier une seconde fois.
Ceci est possible pour Google comme pour d'autres sites (facebook, twitter ...) à partir du moment où ces sites permettent le protocole Oauth2.

Prérequis :
- il faut bien entendu posséder un compte google pour réaliser cette procédure

Cela se fait en 2 étapes :
- création d'un identifiant Oauth2 chez Google
- configurer OpenERP pour autoriser le SSO avec Google

Etape 1 :
- appeler l'url :   https://cloud.google.com/console
- s'authentifier à google
- créer un projet Google (ex: OpenERP oauth2)

- sélectionner ce projet puis aller dans "registered apps"

- cliquer sur "register app" pour créer une application

- puis après avoir cliqué sur "register", nous remplissons les champs "web origin" et "redirect uri"

- enfin nous mémorisons l'information "client ID"

Etape 2:
- se connecter à OpenERP en "admin"
- aller dans le menu "configuration"
- valider l'authentification externe

- sélectionner "Google" dans les fournisseurs "Oauth"

- copier l'info "client ID" récupérée précédemment et cliquer sur "autorisé"

- créer un utilisateur OpenERP correspondant au compte google en précisant comme info "connexion" l'adresse gmail

- dans le navigateur, se connecter à Google avec son compte "gmail"

- appeler notre url OpenERP (ex: localhost:8069) et cliquer sur "Log in with Google"

- cliquer sur "J'accepte" (cette fenêtre ne s'affiche que la 1ère fois)

- puis la connexion à OpenERP se réalise automatiquement !!

Sécurité – Gestion des droits d'accès – Accès aux données (2/2)

OpenERP permet aussi de restreindre les données accessibles aux utilisateurs.
Ce "filtrage" peut se faire par enregistrement et/ou par champ.

Filtrage des enregistrements
Les "règles d'enregistrement" (i.e. "record rules") permettent de filtrer les enregistrements lors de l'accès à un objet.

Il existe 2 types de filtrage (d'ailleurs complémentaires).

1- Filtrage  "conditionnel" :
Seuls les documents qui satisfont à la contrainte exprimée dans "domain_force", sont accédés :

extrait fichier "sale_security.xml"

2- Filtrage "groupe" :
Seuls les utilisateurs appartenant aux groupes indiqués dans "groups" peuvent accéder à l'objet :

extrait fichier "sale_security.xml"

Filtrage des champs
Ce filtrage peut se faire à 2 niveaux : dans la vue ou dans l'objet (nouveauté v7).

1- Filtrage "vue" :
Ce filtrage est plus "lâche" puisqu'il est à faire dans toutes les vues s'interfaçant à l'objet.

extrait fichier "sale_view.xml"

2- filtrage "objet" :
Ce filtrage de plus bas niveau est plus sécuritaire. Il se fait lors de la création de la classe liée à l'objet.

extrait fichier "hr.py"

Sécurité – Gestion des droits d'accès – Accès applicatifs (1/2)

La gestion des droits d'accès applicatifs aux modules OpenERP repose sur :

  • les groupes
  • les ACL (Access Control List)

Un "groupe" (objet "res.groups") caractérise une typologie d'utilisation d'un ou plusieurs modules (ex: utilisateur simple de vente, responsable  des ventes).

Un utilisateur est affecté à un ou plusieurs groupes lors de sa création ou de sa modification.

Une ACL définit les droits d'accès d'un groupe sur (en général) un objet OpenERP.

Groupe
Un groupe est déclaré dans un fichier xml "<nom module>_security.xml" présent sous le répertoire "security" du module.

1- Un groupe peut-être "transverse" (commun à plusieurs applications) ou "catégorisé" :

  • exemple de groupe "transverse"
extrait fichier "/base/res/res_security.xml"
extrait copie écran "gestion des droits utilisateurs"
  • exemple de groupes "catégorisés"
extrait fichier "yd_security.xml"

extrait copie écran "gestion des droits utilisateurs"

2- Il est possible de restreindre les accès au niveau des menus :

extrait fichier "sale_view.xml"

3- Il est possible de restreindre les accès au niveau des actions de type "Window Actions" :

extrait fichier "sale_view.xml"

4- Il est possible de restreindre les accès au niveau des vues :

extrait fichier "sale_view.xml"

5- Un groupe peut hériter des droits d'un autre groupe grâce à la clause "implied_ids" :

extrait fichier "lunch_security.xml"

 6- Il est possible d'affecter un groupe à un utilisateur (ex: "administrateur") dans la livraison du module :

extrait fichier "lunch_security.xml"

Nb: telle qu'elle est implémentée dans OpenERP, la notion de "groupe" ressemble selon moi, à celle de rôle applicatif plutôt que celle de groupe d'utilisateurs.

ACL
Une ACL définit les droits d'accès au format "CRUD" (lecture, création, modification, suppression) d'un groupe sur un objet OpenERP.
Si l'information "groupe" n'est pas renseignée dans l'ACL, c'est que l'objet est accessible à tous (sauf droits restrictifs sur menus et actions).

Nous verrons ultérieurement qu'une ACL peut adresser aussi une vue PostgreSQL (cas des rapports).

Les ACL d'un module sont déclarées dans un fichier nommé "ir.model.access.csv" présent dans le répertoire "security" du module.

Voici un exemple d'ACL (exemple de l'appli YD vue précédemment)

Anonymisation des données OpenERP

Un module OpenERP permet d'anonymiser les données confidentielles (clients, factures, commandes, écritures comptables, utilisateurs ...) , ce qui est très utile dans les cas suivants :

  • constitution de jeux de tests
  • alimentation de différents environnements (développement, intégration, recette ...)
  • en cas d'anomalie difficile à reproduire, pouvoir fournir les données anonymisées au support (intégrateur ou éditeur)
  • migration de version OpenERP réalisée en externe 

Nous partons du jeu de données suivant (ex: clients)

     Nous commençons par installer le module "Data Anonymization"

    Ce qui conduit à ajouter les fonctions suivantes dans le menu "Configuration"

    Pour pallier un petit bug de la version testée de OpenERP, il nous faut ajouter un champ à masquer. Pour cela nous allons d'ans l'écran suivant et cliquons sur "Créer"

    Nous remplissons les champs puis cliquons sur "Enregistrer"

    Nous choisissons ensuite  "Masquer la base"

    Attention, un fichier nommé "field_anonymization_xxx.pickle" nécessaire au retour arrière est créé dans le répertoire d'installation de OpenERP (/opt/openerp pour nous).
    Et voici le résultat !!

    Pour revenir en arrière, il faut choisir "démasquage" en sélectionnant le fichier "field_anonymization_xxx.pickle"