Board

Purpose

This system hosts an OpenERP instance available at board.cacert.org.

Administration

System Administration

Todo

find an additional admin

Application Administration

Application

Administrator(s)

OpenERP

Gero Treuner, Michael Tänzer, Treasurer

Note

use personalized accounts only

Additional People

Jan Dittberner and Mario Lipinski have sudo access on that machine too.

Basics

Physical Location

This system is located in an LXC container on physical machine Infra02.

Logical Location

IP Internet

213.154.225.252

IP Intranet

172.16.2.34

IP Internal

10.0.0.34

MAC address

00:ff:80:a9:e8:4d (eth0)

See also

See Network

DNS

Name

Type

Content

board.cacert.org.

IN A

213.154.225.252

board.cacert.org.

IN SSHFP

1 1 F5C02A860A1CC07AEEFBF802540680C7476BDE6E

board.cacert.org.

IN SSHFP

2 1 7B6EEB0CCDFB2E2CFE479E0AECE36FF995FDD1F4

board.intra.cacert.org

IN A

172.16.2.34

Operating System

  • Debian GNU/Linux 7.11

Services

Listening services

Port

Service

Origin

Purpose

22/tcp

ssh

ANY

admin console access

25/tcp

smtp

local

mail delivery to local MTA

80/tcp

http

ANY

Webserver redirecting to HTTPS

443/tcp

https

ANY

Webserver for OpenERP

5666/tcp

nrpe

monitor

remote monitoring service

5432/tcp

pgsql

local

PostgreSQL database for OpenERP

8069/tcp

xmlrpc

local

OpenERP XML-RPC service

Running services

Service

Usage

Start mechanism

openssh server

ssh daemon for remote administration

init script /etc/init.d/ssh

Apache httpd

Webserver for OpenERP

init script /etc/init.d/apache2

cron

job scheduler

init script /etc/init.d/cron

rsyslog

syslog daemon

init script /etc/init.d/syslog

PostgreSQL

PostgreSQL database server for OpenERP

init script /etc/init.d/postgresql

Postfix

SMTP server for local mail submission

init script /etc/init.d/postfix

Nagios NRPE server

remote monitoring service queried by Monitor

init script /etc/init.d/nagios-nrpe-server

OpenERP server

OpenERP WSGI application

init script /etc/init.d/openerp

Databases

RDBMS

Name

Used for

PostgreSQL

openerp

OpenERP

Connected Systems

Outbound network connections

  • HTTP (80/tcp) to nightly.openerp.com

  • DNS (53) resolving nameservers 172.16.2.2 and 172.16.2.3

  • Emailout as SMTP relay

  • Proxyout as HTTP proxy for APT

  • crl.cacert.org (rsync) for getting CRLs

Security

SSH host keys

Algorithm

Fingerprints

RSA

SHA256:j20Xl83ZK90nYXuIxOMJTcQH75rBcAWIfRnzoPs1qr4, MD5:c7:a0:3f:63:a5:cb:9a:8f:1f:eb:55:63:46:c3:8d:f1

DSA

SHA256:If2oWICT8sA7I+n0kyr+e6oTKa4oKaDFs/kSOQu3UwU, MD5:f6:b7:e5:52:24:27:1e:ea:32:c8:f1:2e:45:f7:24:d3

ECDSA

SHA256:bAsIi9uHC2lm5HSho3EtdltumBmNPUvHIcFJo0UXj7A, MD5:0f:fc:76:f8:24:99:95:f7:d2:28:59:6e:f0:1e:39:ac

ED25519

-

Todo

setup ED25519 host key (needs update to Jessie)

Non-distribution packages and modifications

OpenERP is installed from non-distribution packages from http://nightly.openerp.com/7.0/nightly/deb/. The package source is disabled in /etc/apt/sources.lists.d/openerp.list to avoid accidential updates that cause damage to the customization.

Todo

update to Odoo (OpenERP successor)

Local modifications to OpenERP

OpenERP has been modified. The init script /etc/init.d/openerp has the following line added to the do_start() function to make a request to the OpenERP daemon that causes that daemon to load its configuration and start regular cleanup tasks (like sending scheduled mails):

sleep 1; curl --silent localhost:8069 > /dev/null

Some files have been patched to either fix bugs in the upstream OpenERP code or to add customizations for CAcert’s needs.

/usr/lib/python2.7/dist-packages/openerp/addons/web/static/lib/py.js/lib/py.js

--- /usr/lib/python2.7/dist-packages/openerp/addons/web/static/lib/py.js/lib/py.js	2013-06-16 23:26:30.660384152 +0000
+++ /usr/lib/python2.7/dist-packages/openerp/addons/web/static/lib/py.js/lib/py.js	2013-06-16 23:30:02.035589446 +0000
@@ -764,7 +764,14 @@
 
         // Conversion
         toJSON: function () {
-            throw new Error(this.constructor.name + ' can not be converted to JSON');
+            var out = {};
+            for(var k in this) {
+                if (this.hasOwnProperty(k) && !/^__/.test(k)) {
+                    var val = this[k];
+                    out[k] = val.toJSON ? val.toJSON() : val;
+                }
+            }
+            return out;
         }
     });
     var NoneType = py.type('NoneType', null, {

/usr/lib/python2.7/dist-packages/openerp/addons/account/account.py

--- /usr/lib/python2.7/dist-packages/openerp/addons/account/account.py  2015-01-25 22:56:20.528382003 +0000
+++ /usr/lib/python2.7/dist-packages/openerp/addons/account/account.py  2015-01-25 23:32:37.088302059 +0000
@@ -234,7 +234,7 @@
         pos = 0
         while pos < len(domain):
             if domain[pos][0] == 'code' and domain[pos][1] in ('like', 'ilike') and domain[pos][2]:
-                domain[pos] = ('code', '=like', tools.ustr(domain[pos][2].replace('%', '')) + '%')
+                domain[pos] = ('code', '=ilike', tools.ustr(domain[pos][2].replace('%', '')) + '%')
             if domain[pos][0] == 'journal_id':
                 if not domain[pos][2]:
                     del domain[pos]
@@ -583,13 +583,13 @@
             pass
         if name:
             if operator not in expression.NEGATIVE_TERM_OPERATORS:
-                ids = self.search(cr, user, ['|', ('code', '=like', name+"%"), '|',  ('shortcut', '=', name), ('name', operator, name)]+args, limit=limit)
+                ids = self.search(cr, user, ['|', ('code', '=ilike', name+"%"), '|',  ('shortcut', '=', name), ('name', operator, name)]+args, limit=limit)
                 if not ids and len(name.split()) >= 2:
                     #Separating code and name of account for searching
                     operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
                     ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2)]+ args, limit=limit)
             else:
-                ids = self.search(cr, user, ['&','!', ('code', '=like', name+"%"), ('name', operator, name)]+args, limit=limit)
+                ids = self.search(cr, user, ['&','!', ('code', '=ilike', name+"%"), ('name', operator, name)]+args, limit=limit)
                 # as negation want to restric, do if already have results
                 if ids and len(name.split()) >= 2:
                     operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.

/usr/lib/python2.7/dist-packages/openerp/addons/account/edi/invoice.py

--- /usr/lib/python2.7/dist-packages/openerp/addons/account/edi/invoice.py      2014-07-19 14:44:57.389199363 +0000
+++ /usr/lib/python2.7/dist-packages/openerp/addons/account/edi/invoice.py      2014-07-19 14:45:21.745410574 +0000
@@ -271,7 +271,6 @@
                     "amount": inv.residual,
                     "currency_code": inv.currency_id.name,
                     "button_subtype": "services",
-                    "no_note": "1",
                     "bn": "OpenERP_Invoice_PayNow_" + inv.currency_id.name,
                 }
                 res[inv.id] = "https://www.paypal.com/cgi-bin/webscr?" + url_encode(params)

/usr/lib/python2.7/dist-packages/openerp/addons/account_followup/account_followup.py

This patch includes a Paypal link in payment reminders.

--- /usr/lib/python2.7/dist-packages/openerp/addons/account_followup/account_followup.py        2015-01-25 18:39:56.719266967 +0000
+++ /usr/lib/python2.7/dist-packages/openerp/addons/account_followup/account_followup.py        2015-01-25 18:41:39.620003461 +0000
@@ -21,6 +21,7 @@
 
 from openerp.osv import fields, osv
 from lxml import etree
+from urllib import urlencode
 
 from openerp.tools.translate import _
 
@@ -274,10 +275,25 @@
                         strbegin = "<TD><B>"
                         strend = "</B></TD>"
                     followup_table +="<TR>" + strbegin + str(aml['date']) + strend + strbegin + aml['name'] + strend + strbegin + (aml['ref'] or '') + strend + strbegin + str(date) + strend + strbegin + str(aml['balance']) + strend + strbegin + block + strend + "</TR>"
-                total = rml_parse.formatLang(total, dp='Account', currency_obj=currency)
                 followup_table += '''<tr> </tr>
                                 </table>
-                                <center>''' + _("Amount due") + ''' : %s </center>''' % (total)
+                                <center>''' + _("Amount due") + ''' : %s </center>''' % (rml_parse.formatLang(total, dp='Account', currency_obj=currency))
+                # Add PayPal link if available to allow direct payment
+                if company.paypal_account:
+                    params = {
+                        "cmd": "_xclick",
+                        "business": company.paypal_account,
+                        "item_name": "%s Amount Due in %s" % (company.name, currency.name or ''),
+                        "invoice": currency_dict['line'][0]['name'],
+                        "amount": total,
+                        "currency_code": currency.name,
+                        "button_subtype": "services",
+                        "bn": "OpenERP_Invoice_PayNow_" + currency.name,
+                    }
+                    followup_table += '''
+                        <center><a href="%s">
+                            <img class="oe_edi_paypal_button" src="https://www.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif" alt="Pay directly with PayPal"/>
+                        </a></center>''' % ("https://www.paypal.com/cgi-bin/webscr?" + urlencode(params))
         return followup_table
 
     def write(self, cr, uid, ids, vals, context=None):

/usr/lib/python2.7/dist-packages/openerp/addons/account_followup/report/account_followup_print.py

This patch causes OpenERP to include non-overdue but open payments in reminders.

--- /usr/lib/python2.7/dist-packages/openerp/addons/account_followup/report/account_followup_print.py   2015-04-20 01:07:31.357995387 +0000
+++ /usr/lib/python2.7/dist-packages/openerp/addons/account_followup/report/account_followup_print.py   2015-04-20 01:09:21.314693739 +0000
@@ -58,7 +58,6 @@
                             ('reconcile_id', '=', False),
                             ('state', '!=', 'draft'),
                             ('company_id', '=', company_id),
-                            ('date_maturity', '<=', fields.date.context_today(self,self.cr,self.uid)),
                         ])
 
         # lines_per_currency = {currency: [line data, ...], ...}

/usr/lib/python2.7/dist-packages/openerp/addons/web/static/src/js/view_form.js

Fix form display.

Todo

check whether the form display issue has been fixed upstream

--- /usr/lib/python2.7/dist-packages/openerp/addons/web/static/src/js/view_form.js      2013-01-29 15:03:35.053098527 +0000
+++ /usr/lib/python2.7/dist-packages/openerp/addons/web/static/src/js/view_form.js      2013-01-29 15:08:27.372588389 +0000
@@ -3176,7 +3176,11 @@
         if (! no_recurse) {
             var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context());
             dataset.name_get([self.get("value")]).done(function(data) {
-                self.display_value["" + self.get("value")] = data[0][1];
+                var value = "";
+                if (data.length > 0 && data[0].length > 1) {
+                    value = data[0][1];
+                }
+                self.display_value["" + self.get("value")] = value;
                 self.render_value(true);
             });
         }

Risk assessments on critical packages

Using a customized OpenERP version that is not updated causes a small risk to miss upstream security updates. The risk is mitigated by restricting the access to the system to a very small group of users that are authenticated using personalized client certificates.

Critical Configuration items

Keys and X.509 certificates

  • Certificate for CN board.cacert.org, see details in the certificate list

    • certificate in file /etc/ssl/certs/board.crt

    • private key in file /etc/ssl/private/board.key

  • /etc/ssl/certs/cacert.org.pem CAcert.org Class 1 and Class 3 CA certificates (allowed CA certificates for client certificates)

Apache httpd configuration

  • /etc/apache2/conf.d/openerp-httpd.conf

    Defines the WSGI setup for OpenERP

  • /etc/apache2/sites-available/default

    Defines the HTTP to HTTPS redirection

  • /etc/apache2/sites-available/default-ssl

    Defines the HTTPS and client authentication configuration

  • /var/local/ssl/http_fake_auth.passwd

    Defines the authorized users based on the DN in their client certificate

CRL update job

/etc/cron.hourly/update-crls

OpenERP configuration

/etc/openerp/openerp-server.conf

This file configures the database that is used by OpenERP and the interface that the XML-RPC service binds to.

Tasks

Todo

add a section documenting how to add/remove openerp users

Changes

Planned

Todo

switch to Puppet management

Todo

replace nrpe with icinga2 agent

Todo

disable unneeded Apache modules

Todo

setup IPv6

Todo

update to Debian 8/9/10

System Future

  • No plans

Additional documentation

References

OpenERP 7.0 documentation

https://doc.odoo.com/