Ruby on Rails¶
Please begin with the PostgreSQL installation
Quick start for a production system
apt-get install ruby rubygems build-essential ruby-dev rake gem install bundler
apt-get install git git clone https://github.com/guardianproject/OSTel.git useradd -s /bin/bash -m webapp rsync -av --exclude '.git/*' OSTel /home/webapp/ chown -R webapp:webapp /home/webapp/OSTel/ su - webapp cd OSTel bundle install --path vendor/bundle --without development exit su - postgres createuser -d -E -P -e ruby_on_rails_username (after hitting enter, pick a random long password, you never have to type this by hand, it goes in your config/database.yml ) exit
You will be asked two questions, 'Shall the new role be a superuser?' and 'Shall the new role be allowed to create more new roles?' .. the answer to both is no
As the user you picked above , edit OSTel/config/database.yml with your connection information, this will vary on your configuration
The relevant part of your config file will typically yours will end up looking something like this:
production: adapter: postgresql encoding: unicode database: production username: username_you_chose password: password_you_chose pool: 5 timeout: 5000
su - webapp echo "PATH=$PATH:$HOME/OSTel/vendor/bundle/ruby/1.9.1/bin" >> ~/.profile echo "export RAILS_ENV=production" >> ~/.profile source .profile cd OSTel export RAILS_ENV=production rake db:create rake db:migrate bundle exec rails server --env production
You should now have an application server running on your IP address at port 3000. For a high performance web server on a production system, refer to the Unicorn and nginx pages.
Security¶
Ruby on Rails does not make it simple to edit the default logging configuration. To disable IP address logging differs by Rails version. I took the hacker way out after days of debugging. Issue #1164
Here are links to stories about later versions of Rails. As of Rails 4.0, logging is a proper configuration option and does not require patching source code.
http://cbpowell.wordpress.com/2012/04/05/beautiful-logging-for-ruby-on-rails-3-2/
http://cbpowell.wordpress.com/2011/02/03/beautiful-logging-for-your-ruby-on-rails-application/
SIP domain and outgoing email¶
The front end application depends on email to send user registration notifications. This is configured in /home/webapp/OSTel/config/initializers/smtp_settings.rb
The quick start for email is to use gmail , though this does not scale and will break your application when you reach the gmail SMTP quota . Sendgrid and Mailgun are two commercial providers as of the time of this writing that I've used and recommend.
You also must set the desired domain name for email notifications in /home/webapp/OSTel/config/environments/production.rb
. Replace example.com with your domain
config.domain = "example.com" config.action_mailer.default_url_options = { :host => config.domain }
The next step is to install Kamailio
Data model and customization info¶
If you would like to generate users manually or forego the entire front end application for user provisioning, you must know both the Rails data model and the schema that Kamailio requires for a valid registered user.
Manual user creation¶
# su - webapp $ cd OSTel $ bundle exec rails console production > u = User.create(:email => "foo@bar.com", :sip_username => "foo", :password => "changeme") > u.save
Data model and schema¶
The User model is a Rails ActiveRecord model
The schema looks like this after the Rails database is set up. There are validations which do not exist in the database but are enforced by the ActiveRecord model, they are described below.
CREATE TABLE users ( id integer NOT NULL, email character varying(255) DEFAULT ''::character varying NOT NULL, encrypted_password character varying(128) DEFAULT ''::characte r varying NOT NULL, confirmation_token character varying(255), confirmed_at timestamp without time zone, confirmation_sent_at timestamp without time zone, reset_password_token character varying(255), reset_password_sent_at timestamp without time zone, remember_created_at timestamp without time zone, sign_in_count integer DEFAULT 0, current_sign_in_at timestamp without time zone, last_sign_in_at timestamp without time zone, current_sign_in_ip character varying(255), last_sign_in_ip character varying(255), failed_attempts integer DEFAULT 0, unlock_token character varying(255), locked_at timestamp without time zone, created_at timestamp without time zone, updated_at timestamp without time zone, authentication_token character varying(255), freeswitch_id integer, freeswitch_password character varying(255), ha1 character varying(255), ha1b character varying(255), domain character varying(255), sip_username character varying(255) ); CREATE SEQUENCE users_id_seq START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1; ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass); ALTER TABLE ONLY users ADD CONSTRAINT users_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX index_users_on_sip_username ON users USING btree (sip_username);
Authentication¶
The user authentication framework is called Devise. It manages user passwords and validates required records. The validated records are :email and :password. Email must be unique for the web application, as it is used as the user identifier. The password is encrypted pre-save via a hook in Devise.
Kamailio requires both the :ha1 and :ha1b fields to be encoded using Digest Authentication
This is implemented via the User ActiveRecord model with a pre-save and pre-update hook. Inspect the User model for the encoding method, named generate_sip_hash. It requires a plaintext password, which means it cannot pull data directly from the model since :password is a meta-field that is encrypted and saved into :encrypted_password. The table should not be populated manually unless you want to bypass the Rails application and create Kamailio users with a custom application.
For example, to provision a new Kamailio user you need username, domain and password. In the application, :domain is retrieved from the configuration and available through the global variable Devise::Application.config.domain
. username is set with :sip_username and :password is set through the pre-encrypted value provided by Devise. The following commented definition of generate_sip_hash demonstrates how to properly encode the :ha1 and :ha1b fields.
def generate_sip_hash # validate the presence of a password if (self.password) # get the domain from the global configuration domain = Devise::Application.config.domain # encode string as "username:domain:password" self.ha1 = Digest::MD5.hexdigest("#{self.sip_username}:#{domain}:#{self.password}") # encode string as "username@domain1:domain2:password" self.ha1b = Digest::MD5.hexdigest("#{self.sip_username}@#{domain}:#{domain}:#{self.password}") # set domain for SIP realm. self.domain = domain end end
The :ha1b field format is used if your application would like to use an email-like identifier for the username. For example, if I would like to provision users with an email address (foo@bar.com) as the username, you can manually set domain1 to "bar.com" and domain2 to that of your SIP server. If both :ha1 and :ha1b are set, users can log in with either identifier. See the AUTH_DB module documentation for details.
Next up! Kamailio