Wednesday, December 09, 2015

Django: staticfiles

Locate static file location in codebase:

>>> from django.contrib.staticfiles.finders import find

>>> find("img/logo.png", all=True)
[u'/sites/static_in_pro/our_static/img/logo.png']

>>> find("img/logo.png",)
u'/sites/static_in_pro/our_static/img/logo.png'

Monday, December 07, 2015

LetsEncrypt with HAProxy or Nginx


At this time, LetsEncrypt is in public beta, but I suspect that it will continue to evolve. 

# all commands must be done as root
sudo su

# Download the letsencrypt repo 
git clone https://github.com/letsencrypt/letsencrypt.git /top/letsencrypt/

# change to the desired keys directory.  All commands following are relative to this dir.
cd /jaz/sites/common/etc/keys/

# Generate a 4096 bit ssl private key
openssl genrsa 4096 > jazstudios.com.key

# Generate the certificate signing request.  The following allows lets you specify a SAN (Subject Alternative Name) which allows www and non-www versions of the same domain.  The output needs to be in "der" format. 

openssl req -new -sha256 \
    -key joejasinski.com.key \
    -subj "/C=US/ST=IL/L=Chicago/O=Jazstudios/OU=Information Technology/CN=www.joejasinski.com" \
    -reqexts SAN \
    -outform der \
    -config <(cat /etc/ssl/openssl.cnf \
        <(printf "[SAN]\nsubjectAltName=DNS:joejasinski.com,DNS:www.joejasinski.com")) \
    -out joejasinski.com.csr

# execute the letsencrypt command.  This will prompt you through a few actions.  The most important is that you will need to stop any server running on port 80 and run the python script that they provide in the output.  This will serve up a specific secret file at a specific location, allowing letsencrypt to authenticate the server.  (You could also host the secret file with your webserver)

/opt/letsencrypt/letsencrypt-auto --email example@gmail.com --text \
    --authenticator manual \
    --work-dir /tmp/work/ \
    --config-dir /tmp/config/ \
    --logs-dir /tmp/logs/ auth \
    --cert-path /tmp/certs/ \
    --chain-path /tmp/chains/ \
    --csr joejasinski.com.csr

# --text = use the text based 'wizard' installer instead of an ncurses one
# --authenticator manual = the admin must manually host the verification file
# --csr = path to the previously generated csr file


# The command that it will have you run looks something like this:

mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge
cd /tmp/letsencrypt/public_html
printf "%s" asdfkjasfdasfdasfdasfdasdf > .well-known/acme-challenge/asdfasdfasfd
# run only once per server:
$(command -v python2 || command -v python2.7 || command -v python2.6) -c \
"import BaseHTTPServer, SimpleHTTPServer; \
s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
s.serve_forever()"

# The output of the of the letsencrypt-auto command will be a file called 0000_chain.pem.  This file contains the host certificate and the intermediate certificate.  It will look something like this.  

-----BEGIN CERTIFICATE-----
       Host certificate contents
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
       letsencrypt intermediate certificate
-----END CERTIFICATE-----


# Unrelated, but a good idea: generate a dhparam used for perfect forward security 

openssl dhparam -out dhparam.pem 4096

For hosting with Nginx, this file can be set to the ssl_certificate parameter. The ssl_certificate_key setting would be set to the location of the key file.

For hosting with HAProxy, you want to modify the file so it looks something like this:

-----BEGIN CERTIFICATE-----
       Host certificate contents
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
       Private key contents
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
       letsencrypt intermediate certificate
-----END CERTIFICATE-----
-----BEGIN DH PARAMETERS-----
       contents of dhparam.pem
-----END DH PARAMETERS-----

Friday, November 13, 2015

Dig Commands


Look up A record example.com as seen by 8.8.8.8 nameserver
dig @8.8.8.8 exampe.com

Show the MX record for a yahoo domain
dig yahoo.com MX

Show the TTL for a given domain
dig imagescape.com TTL

Show the TXT record for an yahoo domain
dig yahoo.com TXT

Show only the answer
dig yahoo.com +nocomments +noquestion +noauthority +noadditional +nostats

All Records
dig @8.8.8.8 imagescape.com ANY +noall +answer

Reverse Lookup
dig -x 198.178.132.10

Nice output that looks like the domain record
dig @ns.imagescape.com imagescape.com any +multiline +noall +answer

Find the authoritative nameserver for a domain:
dig -t ns imagescape.com +short

Find the SOA of the domain:
dig joejasinski.com soa +noall +answer

Download a zone file (zone transfer):
dig axfr domain.com


Common Options:
  +short  = show only the results
  +[no]comments = show/hide the comments
  +[no]question = show/hide the question section
  +[no]authority = show/hide the authority section
  +[no]stats = show/hide the stats section
  +[no]answer = show/hide the answer section
  +[no]all = show/hide everything


https://neverendingsecurity.wordpress.com/2015/04/13/dig-commands-cheatsheet/
https://www.madboa.com/geek/dig/

Nice article:
http://anouar.adlani.com/2011/12/useful-dig-command-to-troubleshot-your-domains.html



Monday, November 02, 2015

Python Email Send


Simple email test from python

import smtplib
from email.mime.text import MIMEText
f = "no-reply@example.com"
t = "joe@example.com"
s = smtplib.SMTP('localhost')
msg = MIMEText("this is a test")
msg["Subject"] = "This is a test - ignore"
msg["To"] = t
msg["From"] = f
s.sendmail(f, [t], msg.as_string())

Sunday, August 23, 2015

Docker Gitlab

1) Create the following file
vim run_gitlab.sh

CONTAINER_NAME="gitlab_server"
GITLAB_DATA_DIR="`pwd`/gitlab/"
GITLAB_SSH_PORT="2222"
GITLAB_HTTP_PORT="8080"
GITLAB_HTTPS_PORT="8443"

docker rm ${CONTAINER_NAME}
sudo docker run --detach \
    --publish ${GITLAB_HTTPS_PORT}:443 \
    --publish ${GITLAB_HTTP_PORT}:8000 \
    --publish ${GITLAB_SSH_PORT}:22 \
    --name ${CONTAINER_NAME} \
    --restart always \
    --volume ${GITLAB_DATA_DIR}config:/etc/gitlab \
    --volume ${GITLAB_DATA_DIR}logs:/var/log/gitlab \
    --volume ${GITLAB_DATA_DIR}gitlab/data:/var/opt/gitlab \
    gitlab/gitlab-ce:latest

2) Run to create the initial directories
   sudo ./run_gitlab.sh 

3) Configure: modify the following settings

    sudo vim gitlab/config/gitlab.rb 

         external_url 'http://localhost:8000'
         gitlab_rails['gitlab_ssh_host'] = 'localhost'
         gitlab_rails['gitlab_shell_ssh_port'] = 2222

4) Restart docker

    sudo docker restart gitlab_server

5) Visit http://localhost:8080 and login with

    root 5iveL!fe


Source:
https://gitlab.com/gitlab-org/gitlab-ce/tree/master/docker

Autostart:
https://docs.docker.com/articles/host_integration/

Friday, July 24, 2015

Docker Redis

1) Create a script as such:
CONTAINER_NAME="redis_server"
REDIS_DATA_DIR="`pwd`/data-dir/redis/"
HOST_PORT_1="6379"

if [ ! -d "${REDIS_DATA_DIR}" ]
then
    mkdir -p "${REDIS_DATA_DIR}"
fi

docker rm ${CONTAINER_NAME}
docker run --name ${CONTAINER_NAME} --rm \
   -p ${HOST_PORT_1}:6379 \
   -v ${REDIS_DATA_DIR}:/data \
    redis

Postgres Query: Given an index find associated table

select
    t.relname as table_name,
    i.relname as index_name,
    array_to_string(array_agg(a.attname), ', ') as column_names
from
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
where
    t.oid = ix.indrelid
    and i.oid = ix.indexrelid
    and a.attrelid = t.oid
    and a.attnum = ANY(ix.indkey)
    and t.relkind = 'r'
    and i.relname = 'Index_to_search_for'
group by
    t.relname,
    i.relname
order by
    t.relname,
    i.relname;
 
 
Source:
http://stackoverflow.com/questions/2204058/list-columns-with-indexes-in-postgresql

Docker MongoDB

1) Create a directory for local data:

mkdir `pwd`/data-dir

2) Create a script as such:

CONTAINER_NAME="mongodb_server"
MONGO_DATA_DIR="`pwd`/data-dir"
HOST_PORT_1="27017"

if [ ! -d "${MONGO_DATA_DIR}" ]
then
    mkdir -p "${MONGO_DATA_DIR}"
fi

docker rm ${CONTAINER_NAME}
docker run --name ${CONTAINER_NAME} --rm \
   -p ${HOST_PORT_1}:27017 \
   -v ${MONGO_DATA_DIR}:/data/db \
   mongo

Wednesday, June 24, 2015

Django Manipulating the Session without a request



Django: Lookup a session without a request

    from django.conf import settings
    from importlib import import_module
    engine = import_module(settings.SESSION_ENGINE)
    session_store = engine.SessionStore("new_or_existing_sessionID")
    uid = session_store.get('_auth_user_id')

    try:
        del session_store['session_key']
    except IndexError:
        pass

    session_store.save()

Tuesday, May 12, 2015

GlusterFS Configuration

Assume node1 is: 192.168.33.10
Assume node2 is: 192.168.33.11

Sources:
https://www.digitalocean.com/community/tutorials/how-to-create-a-redundant-storage-pool-using-glusterfs-on-ubuntu-servers
http://www.jamescoyle.net/how-to/457-glusterfs-firewall-rules


On BOTH nodes

# set hosts file entry (or configure DNS)
vim /etc/hosts
192.168.33.10 gluster1
192.168.33.11 gluster2

# On Ubuntu: install requirements 
sudo add-apt-repository ppa:semiosis/ubuntu-glusterfs-3.5
sudo apt-get update
sudo apt-get install glusterfs-server
sudo apt-get install glusterfs-client

# On Centos: install requirements
wget -P /etc/yum.repos.d http://download.gluster.org/pub/gluster/glusterfs/LATEST/RHEL/glusterfs-epel.repo
yum install glusterfs-server
yum install glusterfs-client

# make storage location for gluster data
sudo mkdir /gluster-storage

# make a mountpoint
sudo mkdir /mnt/media/

ON GLUSTER 1

# connect node 1 and node 2
sudo gluster peer probe gluster2
sudo gluster peer status

# create a Gluster replica volume
sudo gluster volume create volume1 replica 2 transport tcp \
      gluster1:/gluster-storage \
      gluster2:/gluster-storage force

# list volumes
sudo gluster volume list

# start the gluster volume
sudo gluster volume start volume1

# mount the volume
sudo mount -t glusterfs gluster1:/volume1 /mnt/media/

# only allow given ips
sudo gluster volume set volume1 auth.allow gluster1,gluster2

sudo gluster volume info
sudo gluster volume profile volume1 start
sudo gluster volume profile volume1 info
sudo gluster volume status

# stop the volume
sudo gluster volume stop volume1

FSTAB Entries

** ON Gluster 1
gluster1:/volume1 /mnt/media/ glusterfs defaults,_netdev,backupvolfile-server=gluster2 0 0

** ON Gluster 2
gluster2:/volume1 /mnt/media/ glusterfs defaults,_netdev,backupvolfile-server=gluster1 0 0

systemd quickstart


Source:
https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
https://wiki.ubuntu.com/SystemdForUpstartUsers
http://wiki.nginx.org/FedoraSystemdServiceFile

Start/stop/reload a service:
service foo start   # or
systemctl start foo

service foo stop   # or 
systemctl stop foo

service foo restart   # or 
systemctl restart foo

Reload a service using reload signal:
service foo reload

See if service is running:
service foo status   # or 
systemctl status foo

See tree listing of all services:
systemctl status

See job log: 
sudo journalctl -u foo -f

Enable a service (to start on boot):
systemctl enable foo

Disable a service:
systemctl disable foo

Service Definition Directory:
/lib/systemd/system/

Example Nginx Service: /lib/systemd/system/nginx.service 
[Unit]
Description=The nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target


Links:
https://scottlinux.com/2014/12/08/how-to-create-a-systemd-service-in-linux-centos-7/

Saturday, May 09, 2015

Simple ClamAV Usage


Source: Nice Resource
http://askubuntu.com/questions/250290/how-do-i-scan-for-viruses-with-clamav

Install:
sudo apt-get install clamav

Refresh virus definition database:
sudo freshclam

Scan all files on computer showing each
clamscan -r /

Only display infected files and ring bell
clamscan -r --bell -i /

Scan all files and move them to infected dir
clamscan -r --move=/home/USER/VIRUS /home/USER

Scan all files and remove bad ones
clamscan -r --remove /home/USER

Friday, April 03, 2015

Python Tokenlib

Make an expiring token using a known secret.

Source:
https://github.com/mozilla-services/tokenlib

Make a token, hashed with a secret, and storing an IP, that expires in 12 seconds
>>> t = tokenlib.make_token({"ip":"1.1.1.1."}, secret="1234567890", timeout=12)

Parse a token before expiration time is up
>>> tokenlib.parse_token(t, secret="1234567890")
{u'ip': u'1.1.1.1.', u'expires': 1428098130.01954, u'salt': u'fbd08e'}

Parse a token after expiration time is up
>>> tokenlib.parse_token(t, secret="1234567890")
Traceback (most recent call last):
  File "", line 1, in
  File "tokenlib/__init__.py", line 186, in parse_token
    return TokenManager(**kwds).parse_token(token, now=now)
  File "/tokenlib/__init__.py", line 143, in parse_token
    raise errors.ExpiredTokenError()
tokenlib.errors.ExpiredTokenError: token has expired

Friday, March 27, 2015

Simple Python Http Server

Serves up files in the current directory.

Python 3
python3 -m http.server
or
python3 -m http.server 8080

Python 2
python -m SimpleHTTPServer
or 
python -m SimpleHTTPServer 8080


Sunday, March 01, 2015

Nodejs Hue Quicksheet

Summary of the following article:
https://github.com/peter-murray/node-hue-api


// load the module
var hue = require('node-hue-api');

// define some display functions
var displayResult = function(result) {
    console.log("Created user: " + JSON.stringify(result));
};

// define some display functions
var displayError = function(err) {
    console.error(err);
};

// search for bridges
timeout = 6000  // 6 seconds
hue.upnpSearch(timeout).then(displayBridges).done();

// register a new user
hostname = '192.168.1.112';
newUserName = null;
userDescription = "some description";
hue.registerUser(hostname, newUserName, userDescription)
   .then(displayResult).fail(displayError).done();

// define connection information
var hostname = "192.168.1.112",
    username="*************************",
    api;

// create the api object
api = new hue.HueApi(hostname, username);

// get basic information about the gateway api
api.description().then(displayResult).fail(displayError).done();

// get the full state of the gateway
api.fullState().then(displayResult).fail(displayError).done();

// see the users that are registered
api.registeredUsers().then(displayResult).fail(displayError).done();

// show the lights and their states
api.lights().then(displayResult).fail(displayError).done();

// define a state and set it to light #1
state = hue.lightState.create().on().white(500, 100);
api.setLightState(1, state).then(displayResult).fail(displayError).done();

// turn light #1 on
api.setLightState(1, state.on()).then(displayResult).fail(displayError).done();

// turn light #1 off
api.setLightState(1, state.off()).then(displayResult).fail(displayError).done();

// get the status of light #1
api.lightStatus(1).then(displayResult).fail(displayError).done();

// see the light groups 
api.groups().then(displayResult).fail(displayError).done();

// see the available scenes  
api.scenes().then(displayResult).fail(displayError).done();

// create a new scene assign light #1-7 to it.  Will include a scene 'id' in the result
lightIds = [1,2,3,4,5,6,7]
sceneName = "Demo Scene"
api.createScene(lightIds, sceneName).then(displayResults).done();

// update an existing scene
lightIds = [1,2,3,4,5,6,]
sceneName = "Updated Demo Scene"
sceneId = "id-generated-by-gateway"
api.updateScene(sceneId, lightIds, sceneName).then(displayResults).done();

// set states for light #1 in a scene
state = lightState.create().on().hue(2000)
sceneId = "id-generated-by-gateway"
lightId = 1
api.setSceneLightState(sceneId, lightId, state).then(displayResults).done();

// recall scene
api.recallScene(sceneId).then(displayResults).done();