Category Archives: Programming

Ubuntu: get last stable kernel

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/env ruby
require 'net/http'
require 'nokogiri'
require 'fileutils'
require 'securerandom'
require 'progressbar'
require 'micro-optparse'

VERSION='2.1'

options = Parser.new do |p|
  p.banner = "This is a script for getting last kernel version from kernel.ubuntu.com/~kernel-ppa/mainline, for usage see below"
  p.version = "script version #{VERSION}"
  p.option :arch, 'architecture type "amd64" or "i386", default "amd64"', :default => 'amd64', :value_in_set => ['amd64', 'i386']
  p.option :type, 'kernel type "generic" or "lowlatency", default "generic"', :default => 'generic', :value_in_set => ['generic', 'lowlatency']
  p.option :show, 'only show last stable kernel version end exit', :default => false, :optional => true
  p.option :install, 'install downloaded kernel', :default => false, :optional => true
  p.option :clear, 'remove folder with kernel deb packages from /tmp', :default => false, :optional => true
end.process!

HOST = 'kernel.ubuntu.com'
MAINLINE = '/~kernel-ppa/mainline/'
$arch = options[:arch] || 'amd64'
$type = options[:type] || 'generic'
$versions = []
$files = []

def get_all_versions
  $versions = []
  source = Net::HTTP.get( HOST, MAINLINE )
  page = Nokogiri::HTML( source )
  page.css('a').each do |a|
    $versions << a.text if !a.text.include? '-rc'
  end
end

def get_last_version
  get_all_versions if $files.empty?
  $versions[-1]
end

def get_all_files
  $files = []
  source = Net::HTTP.get( HOST, "#{MAINLINE}#{get_last_version}" )
  page = Nokogiri::HTML( source )
  page.css('a').each do |a|
    $files << a.text if( ( a.text.include? $arch and a.text.include? $type ) or a.text.include? '_all' )
  end
end


def generate_tmp_folder
  path = "/tmp/#{SecureRandom.hex}"
  FileUtils.mkdir_p(path) unless File.exists?(path)
  return path
end

def download_file(path, file)
  counter = 0
  file_path = "#{MAINLINE}#{get_last_version}#{file}"
  Net::HTTP.start( HOST ) do |http|
    response = http.request_head( URI.escape( file_path ) )
    ProgressBar
    pbar = ProgressBar.new( "progress", response['content-length'].to_i )
    puts file
    pbar.file_transfer_mode
    File.open( "#{path}/#{file}", 'w' ) do |f|
      http.get( file_path ) do |str|
        f.write str
        counter += str.length
        pbar.set(counter)
      end
    end
    pbar.finish
  end
end

if __FILE__ == $0

  if options[:show]
    puts "Last stable version: #{get_last_version.sub('/', '')}"
    exit 0
  end

  get_all_files
  path = generate_tmp_folder

  $files.each do |file|
    download_file(path, file)
  end

  if options[:install]
    puts "\nInstalling kernel\n"
    output = %x[ sudo dpkg -i #{path}/linux-*.deb ]
    puts output
    puts "\nDon't forget reboot your PC/server\n"
  end

  if options[:clear]
    puts "\nremoving #{path}\n"
    %x[ rm -rf #{path} ]
  end

  if !options[:clear] and !options[:install]
    puts "\nrun \ bash -c 'sudo dpkg -i #{path}/linux-*.deb\' if you'd like to install downloaded kernel!\n"
  end
end

Script version 2.1, new version could be found in github: https://github.com/alter/get_last_ubuntu_kernel.git

Specific bash and tool features for working with quotes

Magic dollar

Try to make
user$ x='\n' && echo $x
\n
the same if you use double-quotes, how to output new line ?

user$ x=$'\n' && echo $x

and you get new line! — magic $''

Hex in commands

Try to replace «asd to 'dsa in file
user$ sed -i 's/\»asd/\'dsa/g' file
> ^C
but shell will try to open quotes and it get 3 qoutes, of course it ask you to close one of quotes:
use hex!
user$ sed -i 's/\x22asd/\x27dsa/g' file

Zabbix: Domain's expiration date monitoring

Put in zabbix's externalscripts/ folder following script «paid-domain.rb»:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env ruby
require 'whois'
require 'date'

domain = ARGV[0]

whs = Whois::Client.new(timeout: 30)
r = whs.lookup(domain)
expire = r.expires_on.strftime("%Y-%m-%d")
today = Time.now.strftime("%Y-%m-%d")
expire_date = DateTime.parse(expire)
today_date = DateTime.parse(today)
difference_in_days = (expire_date - today_date).to_i
puts difference_in_days

Install necessary gem:
gem install whois

Add script's description to zabbix_agent.d folder, I named config «paid-domain.conf»:
UserParameter=domain.daysleft[*],/etc/zabbix/externalscripts/paid-domain.rb «$1»

Then you have to add new item in Templates/Hosts with item's name domain.daysleft[example.com]
script will return amount of days from now to expiration date, just add triggers which will notify you.

Zabbix: pushbullet notifications

Put in zabbix's alertscripts folder following script:

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
#!/bin/bash

WDIR='/tmp/zabbix/pushbullet'
LOG="/var/log/pushbullet.log"
mkdir -p $WDIR &>/dev/null

(
to="$1"
subject="$2"
body="$3"

if [[ -z "$to" ]]; then exit 0; fi

OID=$(echo "$body" | grep '^Original event ID: ' | awk '{print $4}')


if [[ -z $(echo "$subject" | grep '^PROBLEM') ]]; then
    # delete
    if [[ -f "$WDIR/$to-$OID" ]]; then
        ID=$(cat "$WDIR/$to-$OID")
        R=$(curl -u "$to": "https://api.pushbullet.com/v2/pushes/$ID" -X DELETE)
        echo -ne "$D Delete\nTo: $to\nSubject: $subject\nBody: $body\nOID: $OID\nResult: " >> $LOG
        echo "$R" >> $LOG
    fi
else
    # send
    D=$(date -R)
    echo -ne "$D Sending\nTo: $to\nSubject: $subject\nBody: $body\nOID: $OID\nResult: " >> $LOG
    R=$(curl -u "$to": https://api.pushbullet.com/v2/pushes -d type=note -d title="$subject" -d body="$body")
    echo "$R" >> $LOG
    ID=$(echo "$R" | grep -Po '"iden":"[^"]+"' | tr -d '"' | awk -F ':' '{print $2}')
    echo "$ID" > "$WDIR/$to-$OID"
fi

) &>/dev/null

Add it to administration->Media types
Then in Profile->Media of your user choose pushbullet and put Access token from https://www.pushbullet.com/account in «Send to» field.

That script will push new notification on trigger if the last one was activated and it removes notification from pushbullet if zabbix sent «OK».

PS: Zabbix's notification template (Configure->Actions->Triggers) should contains following string «Original event ID: {EVENT.ID}»

Ruby: array to hash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env ruby
require 'awesome_print'

url = %x[curl -s -I ya.ru |egrep -v HTTP]
options = []
url.split("\r\n").each do |el|
options << el.split(": ")
end

options = options.to_h

puts "Whole Hash-array: "
ap options

puts "Option by key 'Server' "
ap options["Server"]

output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Whole Hash-array:
{
"Server" => "nginx",
"Date" => "Mon, 19 May 2014 17:47:10 GMT",
"Content-Type" => "text/html; charset=UTF-8",
"Content-Length" => "8159",
"Connection" => "close",
"Cache-Control" => "no-cache,no-store,max-age=0,must-revalidate",
"Expires" => "Mon, 19 May 2014 17:47:10 GMT",
"Last-Modified" => "Mon, 19 May 2014 17:47:10 GMT",
"P3P" => "policyref=\"/w3c/p3p.xml\", CP=\"NON DSP ADM DEV PSD IVDo OUR IND STP PHY PRE NAV UNI\"",
"Set-Cookie" => "yandexuid=8305933271400521630; Expires=Thu, 16-May-2024 17:47:10 GMT; Domain=.ya.ru; Path=/",
"X-Frame-Options" => "DENY",
"X-XRDS-Location" => "http://openid.yandex.ru/server_xrds/"
}
Option by key 'Server'
"nginx"

Rails: validates values from db

Example: we have POST form, which has

1
<select>

options, the values for these options we get from db, something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="new_form">
<%= form_tag(controller: "jobs", action: "create", method: "post") do %>
  <h2>Choose Territory</h2>
  <%= collection_select(:job, :territory_id, Territory.all, :id, :name) %>

  <h2>Choose Server</h2>
  <%= collection_select(:job, :server_id, Server.all, :id, :name) %>

  <h2>Choose Job type</h2>
  <%= collection_select(:job, :jobtype_id, Jobtype.all, :id, :name) %>

  <h2>Enter Version</h2>
  <%= text_field(:job, :version, size: 12) %>
  <p>
    <%=  submit_tag("Add Job") %>
  </p>
<% end %>
</div>

And we would like to be sure that values which gets by destination url are fine, then we have to create validates for these data, let's go:
add new file to «conserns», I named it get_all_ids.rb:

1
2
3
4
5
module GetAllIds extend ActiveSupport::Concern
  def self.ids
    all.collect { |record| record.id }
  endg
end

then include that «concern» to model

1
2
3
class Territory < ActiveRecord::Base
  include GetAllIds
end

I have added it to models Territory, Jobtype and Server

And the last step is adding validates to destination model:

1
2
3
4
5
  validates :territory_id, :jobtype_id, :server_id, :version, presence: true
  validates :version, format: { with: /[0-9]\.[0-9]\.[0-9]{2}\.[0-9]{1,3}(\.[0-9]{1,3})?/, message: "Version number have to contains from numbers and '.' only !"}
  validates :territory_id, inclusion: Territory.ids
  validates :jobtype_id, inclusion: Jobtype.ids
  validates :server_id, inclusion: Server.ids

The last 3 validates are checks for our data.

PHP: DBConfig Class

This is a short note, my own bicycle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class DBConfig{
    private $hostname;
    private $port;
    private $username;
    private $password;
    private $dbname;
   
    public function &__get($property) {
        if(property_exists($this, $property)){
            return $this->$property;
        }
    }

    public function __set($property, $value) {
        if(property_exists($this, $property)){
            $this->$property = $value;
        }
    }
}
?>

How to use:

1
2
3
4
5
6
    $dbconf = new DBConfig();
    $dbconf->hostname = "127.0.0.1";
    $dbconf->port = 6432;
    $dbconf->username = "user_ro";
    $dbconf->password = "user_ro_pass";
    $dbconf->dbname = "test_db";

Then you could use it where do you want:
pgsql:

1
$dbconn = pg_connect("host = $dbconf->hostname port = $dbconf->port, dbname = $dbconf->dbname, user = $dbconf->username, password = $dbconf->password options='--client_encoding=UTF8'");

IT Security Brothers (http://itsb.pro)

Hi guys, I would like to present you our new project IT Security Brothers http://itsb.pro
We provide pentest, consultations and IT outsourcing services.
Feel free to hire us for IT jobs.