pkgsrc and github archives

Tags: , ,
No Comments »

I recently switched pkgin‘s repository from SourceForge‘s CVS to GitHub. Long story short, I heard here and there that SF was considering to drop CVS support and I found GitHub service to be more responsive and elegant. Also, I was looking for an excuse to learn git :)

Anyway, GitHub interface may be sexy, they used to have some kind of “upload” section which has been dropped. That may sound like a simple story, but the fact is when it comes to packaging a GitHub-hosted application, things are not that simple when the author has not explicitly tagged a specific release. Another use case, in which I actually am, is when you have an ongoing development, like pkgin in pkgsrc WIP and do not want to tag every test-release.

The way I found to handle that case with pkgsrc is to use GitHub’s commit archives. In short, I will use that kind of URL:

https://github.com/NetBSDfr/pkgin/archive/34b823c158e62e4d347de74499a075a2259382c5.tar.gz

which is redirected like this by GitHub:

HTTP/1.1 302 Found
Server: GitHub.com
Date: Sun, 21 Apr 2013 21:05:17 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Status: 302 Found
Cache-Control: max-age=0, private
Strict-Transport-Security: max-age=2592000
X-Frame-Options: deny
Set-Cookie: logged_in=no; domain=.github.com; path=/; expires=Thu, 21-Apr-2033 21:05:17 GMT; HttpOnly
Location: https://nodeload.github.com/NetBSDfr/pkgin/tar.gz/34b823c158e62e4d347de74499a075a2259382c5
X-Runtime: 13
Content-Length: 156
Vary: Accept-Encoding

HTTP/1.1 200 OK
Server: GitHub.com
Date: Sun, 21 Apr 2013 21:05:18 GMT
Content-Type: application/x-gzip
Connection: keep-alive
Content-Length: 187510
Content-Disposition: attachment; filename=pkgin-34b823c158e62e4d347de74499a075a2259382c5.tar.gz
Vary: Accept-Encoding

and permits to point to a particular commit, no matter if it has been tagged or not.

A typical pkgsrc Makefile will look like this:

VERSION=                34b823c158e62e4d347de74499a075a2259382c5
DISTNAME=               ${VERSION}
PKGNAME=                pkgin-20130412
CATEGORIES=             pkgtools
MASTER_SITES=           https://github.com/NetBSDfr/pkgin/archive/
FETCH_USING=            curl

# [...]

WRKSRC=                 ${WRKDIR}/pkgin-${VERSION}

# [...]

Note that FETCH_USING= curl is mandatory here in order to follow redirect codes along with https.

There you go, happy GitHub packaging!

Update

Here’s another approach pointed out by Amitai Schlair (schmonz@):

GIT_COMMIT=	dd51ac5

DISTNAME=	${GIT_COMMIT}
PKGNAME=	p5-App-Prove-Plugin-ProgressBar-0.01
CATEGORIES=	devel perl5
MASTER_SITES=	-http://nodeload.github.com/Ovid/App-Prove-Plugin-ProgressBar/tar.gz/${GIT_COMMIT}

# [...]

WRKSRC=		${WRKDIR}/App-Prove-Plugin-ProgressBar-${GIT_COMMIT}

Here, Amitai doesn’t use HTTPS so specifying curl as the fetch method is not mandatory. The dash before the URL in the MASTER_SITES line means that DISTNAME will not be appended when fetching, which is very handy when it comes to GitHub archives.

pkgtools/pkgin, quick fix

Tags: ,
No Comments »

Damn I love pkgsrc. Let me tell you this story as an example…

A while ago, a couple of pkgin users told me it was a shame that /usr/pkg/etc/pkgin/repositories.conf was still pointing to a 5.0 URL when pkgin is freshly installed. Thing is, pkgin does support the $osrelease variable, but on NetBSD, the result of kern.osrelease can be 6.0_SOMETHING, which would lead to:

ftp://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/$arch/6.0_SOMETHING/All

and this does dot exists on the repository.

So in the REPOSITORIES file, which is used to generate the right repositories.conf entry, I added that line:

ftp://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/$arch/@OSREL@/All

And wrote the following trick in pkgtools/pkgin‘s Makefile:

.if ${OPSYS} == "NetBSD"
SUBST_CLASSES+=         osrel
SUBST_STAGE.osrel=      pre-configure
SUBST_MESSAGE.osrel=    Adjusting repository OS release
SUBST_FILES.osrel=      REPOSITORIES
SUBST_SED.osrel=        -e "s|@OSREL@|${OS_VERSION:C/_.*//}|"
.endif

The SUBST framework, part of pkgsrc, will then use (a portable) sed to replace @OSREL@ with the variable ${OS_VERSION}, which is defined in mk/bsd.prefs.mk (included in the Makefile), but will erase anything like the regexp “_.*”. This magic is done by the :C modifier, which behaves like the :S modifier but is capable of replacing regexps instead of simple strings.

Learn to know the power of pkgsrc

sysutils/conky

Tags: , , , ,
4 Comments »

Tout ça, c’est la faute à Guigui2. Et à Nils aussi.

Y’a quoi, 2/3 semaines, ces deux là me disent que ce serait tellement bieeeen si on avait conky dans pkgsrc et que patati le challeeenge et que patata tellement c’est beau tellement y’a des thèmes de ouf et j’en passe et des meilleures.

Et je regarde.

Et c’est l’engrenage.

Deux semaines plus tard donc, je viens d’importer sysutils/conky dans pkgsrc current avec le support des sensors usuels, CPU (SMP), load, mémoire, réseau, disque ainsi que batterie et température. Et ces deux derniers, c’étaient pas les plus simples.

En effet, si par exemple FreeBSD dispose de sysctl fort conviviaux du type hw.acpi.battery.time ou hw.acpi.battery.life, bin nous non. Nous on préfère se faire chier avec envsys(3) dont l’utilisation est expliquée de manière parfaite par ce commentaire trouvé dans sysutils/torsmo:

    /*
     * Using the envsys API is like pulling teeth without anesthetic.
     * so just popen envstat and parse the output instead.
     */

Ça résume assez bien la situation.
Mais comme je suis un peu sado-maso sur les bords, et que je souhaitais présenter un peu plus que le pourcentage de charge de la batterie, je me suis lancé dans l’écriture d’une petite fonction qui simplifie grandement l’accès aux ressources d’envsys. En gros ça donne ça:

#include <sys /envsys.h>
#include <prop /proplib.h>

#define _DEV_SYSMON "/dev/sysmon"

#define P_BOOL      0
#define P_UINT8     1
#define P_INT64     2
#define P_STRING    3

typedef struct Devquery {
    int         type;
    char        *dev;
    char        *key;
    char        *row;
} Devquery;

int             sysmon_fd;

int8_t envsys_get_val(Devquery, void *);

void
sysmon_open()
{
    sysmon_fd = open(_DEV_SYSMON, O_RDONLY);
}

void
sysmon_close()
{   
    if (sysmon_fd > -1)
        close(sysmon_fd);
}

int8_t
envsys_get_val(Devquery dq, void *val)
{   
    char *descr;
    const char *cval;
    prop_dictionary_t dict;
    prop_object_t device;
    prop_object_iterator_t iter;
    prop_object_t obj;
    bool rc = false;

    if (sysmon_fd < 0)
        return -1;

    if (prop_dictionary_recv_ioctl(sysmon_fd, ENVSYS_GETDICTIONARY, &dict)
        != 0)
        return -1;

    if ((device = prop_dictionary_get(dict, dq.dev)) == NULL)
        return -1;

    iter = prop_array_iterator(device);

    while((obj = prop_object_iterator_next(iter)))  {
        descr = (char *)prop_string_cstring_nocopy(prop_dictionary_get(obj,
                "description"));
        if (descr != NULL && *descr) {
            if(strcmp(descr, dq.key) == 0) {
                switch(dq.type) {
                case P_BOOL:
                    rc = prop_dictionary_get_bool(obj,
                        dq.row, (bool *)val);
                case P_UINT8:
                    rc = prop_dictionary_get_uint8(obj,
                        dq.row, (uint8_t *)val);
                    break;
                case P_INT64:
                    rc = prop_dictionary_get_int64(obj, dq.row,
                        (int64_t *)val);
                    break;
                case P_STRING:
                    rc = prop_dictionary_get_cstring_nocopy(obj,
                        dq.row, &cval);
                    val = (void *)cval;
                    break;
                }
            }
        }
    }

    prop_object_iterator_release(iter);
    prop_object_release(dict);

    if (rc == false) {
        val = NULL;
        return -1;
    }

    return 0;
}

On utilise la fonction de cette façon:

    Devquery dq_ac = { P_BOOL, "acpiacad0", "connected", "cur-value" };

    if (envsys_get_val(dq_ac, (void *)&connected) < 0)

Dans cet exemple, connected sera placé à 1 si l'élément acpiacad0 est connecté, 0 autrement.

Le package n'est pas encore parfait, mais il est désormais tout à fait utilisable. Upstream a été contacté et l'integration de mes patchs est en cours.

Mandatory screenshot:

Ça va pas être possible avec vos baskets

Tags: , , ,
No Comments »

Dans ma boîte, l’équipe sécurité a publié voila quelques mois de cela un module pour nginx: un firewall applicatif du nom de naxsi.

Ce module, sous licence GPLv2, je viens de le publier dans pkgsrc current sous la forme d’une option de www/nginx. Je me propose de vous montrer ici comment sécuriser simplement votre serveur web / proxy inverse nginx grâce à naxsi.

Premièrement, si comme moi (et comme il se doit) vous utilisez une branche stable de pkgsrc, mettez simplement à jour www/nginx comme ceci:

$ cd /usr/pkgsrc/www/nginx
# cvs up -rHEAD -dP

Puis spécifiez à pkgsrc que vous souhaitez activer l’option naxsi pour le paquet nginx:

$ grep nginx /etc/mk.conf
PKG_OPTIONS.nginx+=     naxsi

Ceci fait, reconstruisez le paquet comme d’habitude:

$ cd /usr/pkgsrc/www/nginx
$ sudo make update clean

Dans la configuration de nginx, incluez les règles par défaut de naxsi de cette façon:

http {
    include       /usr/pkg/etc/nginx/mime.types;
    include       /usr/pkg/etc/nginx/naxsi_core.rules; # < --- ici
    default_type  application/octet-stream;

Comme vous pourrez le constater, le fichier /usr/pkg/etc/nginx/naxsi_core.rules contient un set de règles déjà très efficaces contre bon nombre d'attaques connues.
Reste alors à activer le filtrage sur une location et choisir quels types d'attaques vous souhaitez bloquer; par exemple:

        location / {
            SecRulesEnabled;
            CheckRule "$SQL >= 8" BLOCK;
            CheckRule "$RFI >= 8" BLOCK;
            CheckRule "$TRAVERSAL >= 4" BLOCK;
            CheckRule "$EVADE >= 4" BLOCK;
            CheckRule "$XSS >= 8" BLOCK;

Un redémarrage de nginx plus loin, on essayera par exemple d’accéder à une adresse louche:

$ wget -O- http://coruscant/?../../etc/passwd
--2012-04-22 10:21:01--  http://coruscant/?../../etc/passwd
Resolving coruscant... 192.168.1.2
Connecting to coruscant|192.168.1.2|:80... connected.
HTTP request sent, awaiting response... No data received.

Et de constater dans /var/log/nginx/error.log:

2012/04/22 10:21:01 [error] 25353#0: *15 NAXSI_FMT: ip=192.168.1.1&server=192.168.1.2&uri=/&total_processed=1&total_blocked=1&zone0=ARGS&id0=1200&var_name0=, client: 192.168.1.1, server: localhost, request: "GET /?../../etc/passwd HTTP/1.0", host: "192.168.1.2"

Moi j’trouve ça assez classe tout de même.

Toutes les infos relatives à la configuration de naxsi sont disponibles sur le Wiki de ce dernier.

pkgin 0.5.2.3

Tags: , ,
No Comments »

!@#!@# de bug.

Des mois que je cherchais au mauvais endroit, en effet, uniquement chez certains utilisateurs (évidemment), un pkgin up / fug proposait d’installer l’univers. Problème dans le moteur de dépendances me dis-je; que de temps perdu à décortiquer ce qui fonctionnait parfaitement, pour finalement tomber sur ceci:

static const struct Summary {
	const int	type;
	const char	*tbl_name;
	const char	*deps;
	const char	*conflicts;
	const char	*requires;
	const char	*provides;
	const char	*end;
} sumsw[] = {
	{
		LOCAL_SUMMARY,
		"LOCAL_PKG",
		"LOCAL_DEPS",
		"LOCAL_CONFLICTS",
		"LOCAL_REQUIRES",
		"LOCAL_PROVIDES",
		NULL
	},
	{
		REMOTE_SUMMARY,
		"REMOTE_PKG",
		"REMOTE_DEPS",
		"REMOTE_CONFLICTS",
		"REMOTE_REQUIRES",
		"REMOTE_PROVIDES",
		NULL
	},
};

[...]

	for (ptbl = __UNCONST(sum.tbl_name), i = 0;
		 i < nelms;
		 ptbl += ((strlen(ptbl) + 1) * sizeof(char)), i++) {

Il ne faut PAaaaaaaas coder avec de l'alcool dans le sang, il ne faut pas, parce qu'après, on se retrouve avec des bouts de trucs ni faits ni à faire qui supposent que les membres d'une structure seront forcément alignés, et des effets de bords qui n'ont rien à voir.

Bref, stacktic m'a proposé cette méthode, bien plus élégante:

static const struct Summary {
	const int	type;
	const char	*tbl_name;
	const char	*deps;
	const char	*conflicts;
	const char	*requires;
	const char	*provides;
	const char	*end;
} sumsw[] = {
	[LOCAL_SUMMARY] = {
		LOCAL_SUMMARY,
		"LOCAL_PKG",
		"LOCAL_DEPS",
		"LOCAL_CONFLICTS",
		"LOCAL_REQUIRES",
		"LOCAL_PROVIDES",
		NULL
	},
	[REMOTE_SUMMARY] = {
		REMOTE_SUMMARY,
		"REMOTE_PKG",
		"REMOTE_DEPS",
		"REMOTE_CONFLICTS",
		"REMOTE_REQUIRES",
		"REMOTE_PROVIDES",
		NULL
	},
};

[...]

	/* (REMOTE[LOCAL)_PKG is first -> skip */
	for (arr = &(sum.tbl_name) + 1; *arr != NULL; ++arr) {

Aaah, bah oui, tout de suite c’est moins dégueulasse hein.

0.5.2.3 est dans current, et le pullup request vient de partir.

meh.

Aiguille, fil, trou

Tags: , ,
No Comments »

Pour une partie de mon parc de machines, je fais mon propre bulk build. Ce dernier ne construit pas l’ensemble des packages, mais un petit subset (environ 600 packages) avec mes propres préférences. Parmi elles, il en est une qui fout un merdier sans nom dans le build, converters/libiconv. Comme je l’expliquais ici il y a quelques temps, j’ai besoin de construire converters/php-iconv avec la version pkgsrc de la libiconv. Cet impératif a un impact non négligeable dans la configuration de mon /etc/mk.conf, aussi je vous livre ce dernier, final et fonctionnel:

.ifdef BSD_PKG_MK

# no base X11
MKX11=no
X11_TYPE=modular
# clean dependencies when the "clean" target is called
CLEANDEPENDS=yes
# everybody likes vim
ACCEPTABLE_LICENSES+=vim-license

USE_BUILTIN.iconv=      no
# A built-in gettext is always going to use a built-in iconv.
USE_BUILTIN.gettext=    no

PKG_RCD_SCRIPTS=        yes

PKG_OPTIONS.irssi=      perl inet6
PKG_OPTIONS.mplayer=    oss

DSPAM_STORAGE_DRIVER=   mysql
PKG_OPTIONS.dspam+=     graphs
MYSQL_VERSION_DEFAULT=  50
PHP_VERSION_DEFAULT=    52
PKG_OPTIONS.php=        -cgi fastcgi

PKG_OPTIONS.rtorrent=           xmlrpc

UPDATE_TARGET=package-install
DEPENDS_TARGET=         bulk-install
BATCH=                  yes

ACCEPTABLE_LICENSES+= socks5-license
ACCEPTABLE_LICENSES+= sendmail-license
ACCEPTABLE_LICENSES+= openmotif-license
ACCEPTABLE_LICENSES+= idea-license

PKG_OPTIONS.dovecot=    ssl ldap dovecot-sieve dovecot-managesieve
PKG_OPTIONS.nagios-nrpe = ssl tcpwrappers

PKGCHK_CONF?=   /usr/pkgsrc/pkgchk.conf
BULK_PREREQ+=   converters/libiconv
#
# Parse pkgchk.conf and supply list of packages for the bulk build framework.
#
.if defined(SPECIFIC_PKGS)
PKGLIST!=               awk '{print $$1}' ${PKGCHK_CONF}
.  for _pkg_ in ${PKGLIST}
HOST_SPECIFIC_PKGS+=    ${_pkg_}
.  endfor
.endif

.endif # BSD_PKG_MK

À noter, donc, les particularités suivantes:

  • Xorg modular pour les dépendances relatives à X11
  • libiconv en provenance de pkgsrc, il est impératif de faire de même pour gettext
  • irssi est compilé avec le support perl et IPv6
  • storage MySQL pour dspam
  • MySQL 5.0
  • PHP 5.2
  • Options ssl ldap dovecot-sieve et dovecot-managesieve pour dovecot
  • Options ssl et tcpwrappers pour nagios-nrpe
  • On ajoute libiconv comme pré-requis pour la construction bulk

J’utilise, pour générer tout ce petit monde, l’excellent script du sieur orgrim, disponible ici, avec sa note explicative.

WP Theme & Icons based on GlossyBlue by N.Design Studio
Banner from www.trynthlas.com
Entries RSS Comments RSS Log in
Performance Optimization WordPress Plugins by W3 EDGE