Configure postfix to use mandrill for sending email

Postfix-logo

In this configuration relay all email sending mandrill. So that we do not need to configure all applications one by one to use mandrill. It will affect all applications in the server.

1. Create /etc/postfix/sasl_passwd

[smtp.mandrillapp.com]:587 USERNAME:API_KEY

2. Edit /etc/postfix/main.cf, add the following code

smtp_sasl_security_options = noanonymous

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
relayhost = [smtp.mandrillapp.com]:587

3. run in shell:

postmap hash:/etc/postfix/sasl_passwd

4. restart postfix

service postfix restart

Now try to send an email, then monitor the log in mandrill dashboard.

Securing JSON-API wordpress plugin

wordpress-logo

JSON-API is very useful wordpress plugin. I often use it to retrieve wordpress data to mobile app. It can handle custom fields, custom post types, taxonomy, etc. It also has custom controllers that we can use to extent the functionality.

Unfortunately this plugin has no access control. So once you install this plugin, everyone can access the data as well. I made a little update to limit the access. Basically I added a secret key or a password, but I will use term api key. Only someone with correct api key can access the data.

So how to do this.

Edit json-api.php file, line 26, add the following code.

  /* ########### QUICK MOD: ADDING API KEY ########### */
  $json_api_key = "b34b40ca8771c48c204e55f927376885";
  /* ########### QUICK MOD: ADDING API KEY ########### */
  if ($_GET['json']) {
    if ($_GET['wpapikey'] != $json_api_key) {
      print "[error:99] Permission denied!";
      exit;
    }
  }
  /* ########### QUICK MOD: ADDING API KEY ########### */

Change b34b40ca8771c48c204e55f927376885 to anything as you like as the api key. For the complete diff, see this commit in github:
https://github.com/dodyrw/wp-json-api-key/commit/d29459421ceec73e9b639d4e2ffbeb04931df576

Now every JSON-API request will require api key. Otherwise it will return permission denied error message. For example:

http://www.dodyweb.com/?json=get_recent_posts&dev=1&wpapikey=b34b40ca8771c48c204e55f927376885

SSL Pinning with AFNetworking 2

Screen Shot 2013-12-23 at 8.14.56 AM

If we use web services in our app, we need to secure the connection from data sniffing. Normally we can use SSL connection every time we call web services. It will prevent someone from sniffing the data traffic.

However it is not enough. We also need to prevent from “Man in the middle attack“. Someone else can disguise as the web service provider. Instead of connecting to genuine web service server, the app will connect to someone else server. And we know that it will lead to a serious problem!

So how do we prevent from “Man in the middle attack”.

First, the web service provider must have SSL certificate. They will supply us with .crt file. Or if you own the web service, buy a SSL certificate for your domain. Then we need to tell our app that it should always connect to server with valid SSL certificate.

Before we begin to code, we need to convert .crt file to .cer file and add this file in xcode project. Open terminal and run the following command.

openssl x509 -in www.mydomain.com.crt -out www.mydomain.com.cer -outform der

If you use NSURLConnection, you need to check certificate in - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge. You need to add NSURLConnectionDelegate protocol.

Using AFNetworking 2.0, it will be easier. We need to create AFSecurityPolicy and set AFHTTPRequestOperationManager to use it.

Since I use it multiple times, I create a method for this purpose.

- (AFSecurityPolicy*) dodyrwSecurityPolicy
{
    /**** SSL Pinning ****/
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"www.dodyrw.com" ofType:@"cer"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
    [securityPolicy setAllowInvalidCertificates:NO];
    [securityPolicy setPinnedCertificates:@[certData]];
    [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate];
    /**** SSL Pinning ****/

    return securityPolicy;
}

Then set it in manager.

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    /**** SSL Pinning ****/
    [manager setSecurityPolicy:[self dodyrwSecurityPolicy]];
    /**** SSL Pinning ****/
    
    [manager GET:WEBSITE_URL parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary* responseObject) {
        //..... beautiful code here
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //..... beautiful code here
    }];

Installing phpredis (pecl) on ubuntu

Screen Shot 2013-06-18 at 12.33.11 PM

In order to install phpredis, we will need to have make and pecl installed.

apt-get install php-pear
apt-get install make
pecl install redis

Then we need to put extension=redis.so in php.ini file. In my case it php ini file is located at /etc/php5/fpm/php.ini.

vim /etc/php5/fpm/php.ini

To activate it, we need to restart apache or php5-fpm.

service php5-fpm restart

Update php5 cli on mac / osx using Liip package

Run the following command in shell to get the current php version

php -v

If you are using Lion like me, and never update php, then you may get 5.3.10.
Unfortunately today I spent a few hours trying to make fuelphp 1.4 oil work normal like when I was using 1.3.

At the moment, the lastest php version is 5.3.19.

In order to update PHP5 CLI on OSX using LIIP package, use the following command.

curl -s http://php-osx.liip.ch/install.sh | bash -s 5.3

# rename the old php
sudo mv /usr/bin/php /usr/bin/php_old

# copy the new package to /usr/bin
sudo cp /usr/local/php5-20121126-082829/bin/php /usr/bin/php

# test version
php -v

# get phpinfo, useful to locate php.ini file
php -i

# test fuel php oil
oil console

Now fuelphp oil should work normally, using 5.3.19 fixed the problem (at least for me) :D.

EDIT:
Rather than rename old php file, it is better to set PATH to new php location
Edit ~/.bashrc using nano or vim.
Add /usr/local/php5/bin, so you might have something like this:

PATH=/usr/local/php5/bin;$PATH:$HOME/.rvm/bin