A propos de ce Blog

Ce blog a pour vocation d’exposer mon portfolio, mes compétences, mes expériences et toutes les astuces et informations qui me semblent intéréssantes de garder et de partager à tout le monde.

N’hesitez pas à me contacter et a me laisser vos remarques par email ou en laissant un commentaire via Disqus en dessous de chaque article.

Bonne lecture !



Commands tips & tricks

Infos Reseau

1
2
IP=$(ip -4 -o a | sed -e '/^2:/!d;s/^.*inet //;s/\/.*$//g')
HOSTNAME=$(hostname -s)

Modification des hosts et dns

1
[[ $(grep -E "$IP(.*)$(hostname -s)(.*)" /etc/hosts) ]] || echo -e "$IP    $(hostname -s)" >> /etc/hosts

Verification execution en root

1
[[ $(whoami) != root ]] && { echo "ERREUR : Veuillez exécuter ce script en tant que root avec la commande sudo !"; exit 1; }

Proxy

APT:

1
echo -e "Acquire::http::Proxy \"${PROXY_URL}/\";" > /etc/apt/apt.conf.d/proxy.conf

System:

1
2
3
4
5
PROXY_URL="http://USER:PASS@HOST:PORT"
echo -e "export http_proxy='${PROXY_URL}'\n
export https_proxy='${PROXY_URL}'\n
export no_proxy=EXCLUDED_DOMAIN.fr,localhost,127.0.0.1,${HOSTNAME}" > /etc/profile.d/proxy.sh
source /etc/profile.d/proxy.sh

Maven:

1
2
mkdir -p ~/.m2
echo ${http_proxy} | tr "/:@" " " | awk '{print "<settings>\n<proxies>\n<proxy>\n<id>proxy</id>\n<active>true</active>\n<protocol>"$1"</protocol>\n<host>"$4"</host>\n<port>"$5"</port>\n<username>"$2"</username>\n<password>"$3"</password>\n</proxy>\n</proxies>\n</settings>"}' > ~/.m2/settings.xml

Curl:

1
echo "proxy = ${http_proxy}" > ~/.curlrc

Decompresser à la volée

1
curl -s $PACKAGE_REGISTRY/stedolan/jq/1.6/jq-1.6.tar.gz | tar xz -C /usr/bin/ && chmod +x /usr/bin/jq

Add Iptables

1
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT && iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT && iptables-save 2> /dev/null > /etc/sysconfig/iptables

Optimisation memoire Java (java heap size)

1
-Xmx2048m -Xms512m -XX:MaxPermSize=2048m -XX:+UseConcMarkSweepGC -XX:ReservedCodeCacheSize=128m -XX:+HeapDumpOnOutOfMemoryError

Changement de cible binaire

1
2
3
4
5
update-alternatives --set php /usr/bin/php5.6

Alias alternative from vars:
echo "[[ \${php} ]] && alias php='update-alternatives --set php /usr/bin/php\${php} > /dev/null; php' \
\n[[ \${node} ]] && alias node='nvm use \${node} >/dev/null; node'" >> ~/.bashrc

Manipulation de variables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Variable avec nom dynamique (shell): 
varname="toto"
varcontent="content"
$varname=$varcontent

name=${varname}
data=${!varname}

Variable avec nom dynamique (Groovy):
def OC_CONFIG_PATH="OC_CONFIG_AA"
evaluate("env.${OC_CONFIG_PATH} = \"--config='/tmp/$OC_CONFIG_PATH/config'\" ")
env.OC_CONFIG_PATH="$OC_CONFIG_PATH"
OC_CONFIG_PATH=\${!OC_CONFIG_PATH}
env.KUBECONFIG="/tmp/AA/oc_config_${JOB_BASE_NAME}"

Sed tricks

1
2
3
4
5
change maven version
sed -i -r -e 's#<source>(.*)</source>#<source>1.8</source>#g' -e 's#<target>(.*)</target>#<target>1.8</target>#g' pom.xml

# Export 'exist*' groovy vars outside this shell
echo "\$(env | grep -E '_exist|_version' |sed 's/^/env./')" | tee ${WORKSPACE}/vars.groovy

Find tricks

1
2
find ${builder.buildDir}/ -name "*.sh" -exec chmod +x {} \\;
find ${builder.buildDir}/ -name "*.sh" -exec chmod 755 {} \\;

Import propre sql

1
mysql -u root -e "source /db.sql;"

GIT- Appliquer des changements d'une branche autonome à une autre

Git

Pour appliquer les changement d’une branche à une autre :

Comparer la liste des fichiers de master par rapport à une autre branche (demo) avec exclusion de fichier

1
git diff master..demo --stat ':(exclude)fichier1' ':(exclude)README.md'

Comparer le contenu des fichiers de master par rapport à demo

1
git diff master..demo

Appliquer les changement de master sur metro pour le fichier fichier_2.txt

1
2
git checkout demo
git checkout --patch master fichier_2.txt

-> Options:
y: accepter les changements
n: refuser les changements
a: accepter tous les changements
e: editer manuellement le fichier (si la ligne à garder commence par - il faut juste le remplacer par un espace et supprimer la ligne correspondante qui commence par un +)

Cherrypick entre plusieurs repos

  • Preparation

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    git clone https://repoA.git repoA
    git clone https://repoB.git repoB
    git clone https://repoC.git repoC

    cd repoB/
    git remote add repoA ../repoA
    git remote add repoC ../repoC

    cd ..

    cd repoC/
    git remote add repoA ../repoA
    git remote add repoB ../repoB
  • Utilisation

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Recupération de un ou plusieurs commits de repoA vers repoB

    cd repoB/
    git fetch repoA

    -> pour un seul commit:
    git cherry-pick <commit_id>

    -> pour un groupe de commits:
    git cherry-pick <first_commit>..<last_commit>

    git push

Application à grande échelle

1
for br in $(git branch --list | tr -d '*' | grep -v <SOURCE BRANCH>); do git checkout $br; git checkout --patch <SOURCE BRANCH> <FICHIER> ; done

Configuration réseau sous Ubuntu 18.04

Sur Ubuntu 18, la gestion du réseau est maintenant géré par Netplan au lieu de NetworkManager
La gestion DNS peut être gérée par systemd ou intégrée à Netplan

Gestion des DNS avec systemd

Editer le fichier resolved:

1
2
3
4
5
6
7
8
9
10
11
vi /etc/systemd/resolved.conf

[Resolve]
DNS=8.8.8.8 8.8.4.4
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#Cache=yes
#DNSStubListener=yes

puis redemarer le service:

1
systemctl restart systemd-resolved.service

Gestion reseau avec netplan

Editer le fichier de configuration de netplan

1
vi /etc/netplan/50-cloud-init.yaml

Exemple de configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
network:
version: 2
ethernets:
ens192:
dhcp4: false
addresses: [163.172.123.123/24, 212.83.123.123/32]
gateway4: 163.172.123.1
ens33:
dhcp4: true
dhcp4-overrides:
route-metric: 50
nameservers:
addresses: [8.8.8.8]
wifis:
wlp2s0b1:
dhcp4: no
dhcp6: no
addresses: [192.168.0.21/24]
gateway4: 192.168.0.1
nameservers:
addresses: [192.168.0.1, 8.8.8.8]
access-points:
"network_ssid_name":
password: "**********"

puis appliquer les modifications:

1
sudo netplan apply


Menu en Shell

Create Usage function

1
2
3
4
5
6
7
8
9
10
USAGE(){
echo "-e <env>, --env=<value> Précise l'environnement cible (--env=dev, --env=rec, --env=prod, etc)"
echo "-u, --uninstall Désinstalle le Chatbot"
echo "-d, --delete-volumes Supprime les données persistantes du Chatbot (peut être cumulé avec l'option --uninstall)"
echo "-p, --pull Télécharge seulement les images nécessaires au Chatbot"
echo "-h, --help Affiche cette page d'aide"
echo
echo "Si aucune option n'est précisée, le script lance un déploiement du Chatbot en mode interactif"
echo
}

Using Menu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
OPTS=$(getopt --options "e:,h,u,d,p" --long "env:,help,uninstall,delete-volumes,pull" --name "$0" -- "$@")
[[ $? != 0 ]] && { echo "Echec à la lecture des options !" >&2 ; exit 1; }
eval set -- "$OPTS"

while true ; do
case "$1" in
-e | --env ) ENV="$2"; shift 2 ;;
-p | --pull ) DOWNLOAD_IMAGES; EXIT_STATUS=true; shift ;;
-u | --uninstall ) CLEAN_ENV; EXIT_STATUS=true; shift ;;
-d | --delete-volumes ) CLEAN_PERSISTENT_DATA; shift ;;
-h | --help ) USAGE; exit 1;;
-- ) shift; break ;;
* ) USAGE; exit 1;;
esac
done
[[ $EXIT_STATUS ]] && exit 0;

Importation certificat SSL (ubuntu/centos)

Importation certificat SSL (ubuntu/centos)

1
2
3
4
5
6
7
8
9
10
11
12
13
if [ "$(. /etc/os-release && echo "$ID")" = "ubuntu" ]; then
CERT_DIR="/usr/local/share/ca-certificates"
cp $APACHE_PATH/ssl/certs/cacert.pem $CERT_DIR/ca.crt
---- OR ----
openssl s_client -connect HOST:PORT -showcerts </dev/null 2>/dev/null | sed -e '/-----BEGIN/,/-----END/!d' | sudo tee -a $CERT_DIR/HOST.crt
update-ca-certificates --fresh
else
CERT_DIR="/etc/pki/ca-trust/source/anchors"
cp $APACHE_PATH/ssl/certs/cacert.pem $CERT_DIR/ca.crt
---- OR ----
openssl s_client -connect HOST:PORT -showcerts </dev/null 2>/dev/null | sed -e '/-----BEGIN/,/-----END/!d' | sudo tee -a $CERT_DIR/HOST.crt
update-ca-trust
fi

Redimensionnement d'un disque vmware suite à une augmentation de disque alloué

Redimensionnement d’un disque d’une machnie virtuelle sous vmware

Après avoir augmenté l’espace alloué d’un disque il se peut que la vm ne voit pas son disque agrandit.

Il faut donc taper les commandes suivantes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
gdisk /dev/sda
Command (? for help): w
Warning! Secondary header is placed too early on the disk! Do you want to
correct this problem? (Y/N): y
Do you want to proceed? (Y/N): y
reboot now
fdisk /dev/sda
Command (m for help): p
Command (m for help): d
Partition number (1,2, default 2): 2
Command (m for help): n
Partition number (2-128, default 2): 2
First sector (4096-209715166, default 4096): 4096
Last sector, +sectors or +size{K,M,G,T,P} (4096-209715166, default 209715166): 209715166
Do you want to remove the signature? [Y]es/[N]o: y
Command (m for help): w
reboot now
resize2fs /dev/sda2

Docker tips & tricks

Install latest docker & docker-compose

1
2
curl -sSL https://get.docker.com/ | sh
curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Configure proxy for docker

1
2
3
4
mkdir -p /etc/systemd/system/docker.service.d
PROXY_URL='http:/USER:PASS@PROXY:PORT'
echo -e "[Service] \nEnvironment=\"HTTPS_PROXY=${PROXY_URL}\"\nEnvironment=\"NO_PROXY=localhost,127.0.0.1,${HOSTNAME}\"" > /etc/systemd/system/docker.service.d/http-proxy.conf
systemctl daemon-reload && systemctl restart docker

Change data directory & activate logrotate

1
2
3
mkdir -p /etc/docker/ /data
echo -e "{\"data-root\": \"/data/docker\",\"log-driver\": \"json-file\", \"log-opts\": { \"max-size\": \"100m\",\"max-file\": \"5\" }}}" | tee /etc/docker/daemon.json
systemctl daemon-reload && systemctl enable docker && systemctl restart docker

Clean by filter orphan images or regex container

1
2
docker rmi $(docker images -q -f 'dangling=true') 2> /dev/null || true
docker rm -f $(docker ps -aq -f 'name=NAME*') 2> /dev/null || true

Import many images from directory, apply tag by date and latest, and push to registry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Livraisons="2018-10-10 2019-01-21 2019-03-21 2019-03-26 2019-04-10 2019-04-11"

for livraison in $Livraisons;do
for image in $(ls $IMAGES_PATH/$livraison/*.tar); do
name=$(docker load -q -i $image | awk '{print $3}');
newtag=$(basename $name | sed -e "s/:.*$/:$(basename $(dirname $image))/g")
latesttag=$(basename $name | sed -e 's/:.*$/:latest/g')
docker tag $name $DOCKER_REGISTRY/$newtag;
docker tag $name $DOCKER_REGISTRY/$latesttag
docker push $DOCKER_REGISTRY/$newtag
docker push $DOCKER_REGISTRY/$latesttag
docker rmi $name >/dev/null;
echo -e "\n==> image $DOCKER_REGISTRY/$newtag imported\n";
done
done

Dockerfile exemple multi-tool container

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
### Input variables ##
ARG http_proxy
ARG https_proxy
ARG no_proxy

## put arg as env for futur use
ENV http_proxy=$http_proxy
ENV https_proxy=$https_proxy
ENV no_proxy=$no_proxy

# System Env
ENV TERM=xterm
ENV LC_ALL=C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive

# Package Env
ENV INSTALL="apt-utils software-properties-common vim dos2unix sqlite3 mysql-server mysql-client libpcre3-dev apache2 php-pear php-pecl-http maven"
ENV INSTALL_PHP="5.5 5.6 7.0 7.2"
ENV INSTALL_PHP_MODULES="xml mysql http mcrypt sqlite3 mbstring curl cli gd dev intl xsl memcache memcached zip apc"
ENV INSTALL_JAVA="openjdk-8-jdk openjdk-8-jre"
ENV INSTALL_NODEJS="8 9 10 11 12"

# Download others packages
RUN apt-get update -y && apt-get install -y software-properties-common apt-transport-https lsb-release

# Download the signing key for php repo
RUN wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg

# Add repo for php packages
RUN echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list && apt-get update -y

# Add nvm for nodejs managing
RUN wget -O install.sh https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh; bash install.sh

# Installing packages
# System packages
RUN /bin/bash -c 'for packages in ${INSTALL[@]};do apt-get install -y ${packages} ;done'

# Php & php modules packages
RUN /bin/bash -c 'for php_version in ${INSTALL_PHP[@]};do apt-get install -y php${php_version} ; for php_modules in ${INSTALL_PHP_MODULES[@]};do apt-get install -y php${php_version}-${php_modules} ;done ;done'

# Java packages
RUN /bin/bash -c 'for java_version in ${INSTALL_JAVA[@]};do apt-get install -y ${java_version} ;done'

# Nodejs packages
RUN /bin/bash -c 'source ~/.profile 2>/dev/null; for node_version in ${INSTALL_NODEJS[@]};do nvm install ${node_version} ;done'

Pipeline Devops pour Let's Encrypt

Montage d’une pipeline DevOps pour Let’s Encrypt

Afin de faciliter mes futurs projecs et de pouvoir les sécuriser, j’ai décider d’utiliser Let’s Encrypt de façon automatique.

Il était déja possible d’utiliser Let’s Encrypt pour certifier un nom de domain ou sous domaine, aujourd’hui il est possible de certifier via un wilcard, ce qui nous permet de couvrir le totalité des nom de domaines / sous-domaines et futurs sous-domaines sous la forme *.mon-domaine.fr

Integration de Let’s Encrypt dans une pipeline

Avec ce concept de wildcard, il est maintenant possible de gérer un seul certificat pour l’ensemble des domaines, ce qui automatise déjà la création d’un certificat par projet.

Pour automatiser cette génération, j’ai intégré Let’s Encrypt dans une pipeline Gitlab-ci, ce qui permet de nous passer d’un serveur pour le faire.

=> Lien vers le job de la pipeline de génération

Cette Pipeline est appellée automatiquement tous les 1er du mois avec Gitscheldule (semblable à cron).

Déploiement et livraison des certificats

Avec cette Pipeline Gitlab-Ci, une partie n’est pas couverte, c’est celle du chargement du certificat sur le serveur de l’application.

Deux cas sont étudiées:

  • Site hebergé avec Git-Pages, comme ce porte folio, les certificats doivent donc être poussés vers Gitlab directement
  • Site hebergé sur un serveur classique, il faudra donc pouvoir récupérer les fichiers directement et les faire portés par apache/nginix etc..

Cas Gitlab-Pages

Gitlab Fournit une Api avec laquelle il est possible de pousser directement les certificats sur un domaine associé.

J’ai donc développé un script qui parcours la totalités de mes projets Gitlab, cherche si ils contiennent des Gitlab-Pages et si ils sont attachés à un nom de domaine.

Dans ce cas le certificat est récupéré de la pile de cache de la pipeline Let’Encrypt et est poussé directement par api sur le domaine du Gitlab-page.

=> Lien vers le script

Cas récuperation des livrables

Afin de pouvoir récupérer les certificats pour pouvoir les exploiter sur un autre serveur, j’ai utilisé les artifacts dans la pipeline Gitab-Ci.

La fonction artifacts permet d’archiver un contenu présent dans un job Gitlab-ci et de le proposer en téléchargement une fois la pipeline terminée.

Cette fonction peut être utile dans de nombreux cas, par exemple récuperer les sources/livrables d’une complation, récuperer des logs etc..

Il est donc possible de récuperer les certificats génénerés via l’interface Gitlab ou par API, c’est cette dernière qui nous intéresse.

Effectivement il suffit d’ajouter la commande suivante dans une tache cron mensuelle sur le serveur en question, et les certificats seront automatiquement actualisés

1
curl --output certificats.zip -L --header "PRIVATE-TOKEN: $TOKEN" https://gitlab.com/api/v4/projects/8641028/jobs/artifacts/master/download?job=certbot-renew

=> Lien vers le job de la pipeline de déploiement