Posted on 2 Comments

Create a self hosted agent on local machine for Azure Devops

Azure Devops services provide great functionality for deployment solutions. One of them is the local agent creation if you do not have a cloud/hosted available server.

In this article I will explain the procedure on how to create one.

Go to your project on your organisation and select agent pools. You can choose either the default or create a new one.

When selecting your agent pool, you should press on new agent. There you can find instructions on how to create your agent. In my case it is a Mac OS X machine

Download the files and follow the instructions. The configuration steps for Mac OS X ask for the server URL. You should input the below:

https://dev.azure.com/Your_Org_Name

Then you should select PAT authentication and generate a new token from your account panel -> personal access tokens.

Input the access permissions for the token and the expiration date. Also copy the key on a safe place. If you do not provide sufficient access on the token, you will get errors during the configuration.

When the configuration is completed agent will try a test connection.

When the above step is finished, try to run the agent.

./run.sh on macosx

If the procedure is succeful you will see your machine ready to accept jobs

Also the agent should appear online under agents tab

Posted on Leave a comment

Deploy Always Available Infrastructure on Azure

Availability is a critical matter when it refers to systems. The ideal scenario for an administrator would be 100% availability for a virtual server/appliance.

However this is not achievable when we deal with infrastructure as we need to close the systems on purpose (patching, maintenance tasks, etc) but also disasters or other nonphysical causes create a downtime.

When we deal with Azure cloud we have the following options that we can use:

  • Availability sets
  • Availability zone

An Availability Zone is a high-availability offering that protects your applications and data from datacenter failures. Availability Zones are unique physical locations within an Azure region. Each zone is made up of one or more datacenters equipped with independent power, cooling, and networking. To ensure resiliency, there’s a minimum of three separate zones in all enabled regions

Availability sets are another datacenter configuration to provide VM redundancy and availability. This configuration within a datacenter ensures that during either a planned or unplanned maintenance event, at least one virtual machine is available and meets the 99.95% Azure SLA. For more information, see the SLA for Virtual Machines.

When you create a new VM resource on Azure, you should choose between availability sets or availability zone (depending on the region on which you deployed your server)

However as stated in the first article from Microsoft:

To achieve comprehensive business continuity on Azure, build your application architecture using the combination of Availability Zones with Azure region pairs. You can synchronously replicate your applications and data using Availability Zones within an Azure region for high-availability and asynchronously replicate across Azure regions for disaster recovery protection.

So the final image is the below. Based on your needs you could choose whichever option is more appropriate for you. However as recommended from Microsoft, you should use availability zones (newer feature than availability sets)

Below are some very good resources that Microsoft provides:

https://docs.microsoft.com/en-us/azure/availability-zones/az-overview

https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability

https://docs.microsoft.com/en-us/azure/best-practices-availability-paired-regions

Posted on 1 Comment

The ultimate Guide of Security – Infrastructure Web application Hardening

This guide is written in order to help the IT Security Administrators secure their Infrastructure (VM in the cloud or something equivalent) that host web applications. It encloses knowledge that has been gained from multiple penetrations test from different vendors in projects that I have participated. It cannot protect you 100% but is a good and detailed way to start your security hardening.

Table of contents:

  • OS patching
  • Strong passwords and permissions
  • SSL Certificate
  • Install fail2ban
  • Set up firewall
  • Limit ssh access
  • PHP Hardening
  • Apache Hardening

OS patching:
Keep always your OS ( Red Hat Linux or equivalent) up to date with the latest security updates and patches. As a result before starting your installations perform an OS update. It is very important also to keep your Apache and PHP packages patched.

Strong passwords and permissions:
Create strong passwords for your users and add users with separate directories and permissions. Each user should have its own directory to manipulate files and should not have root access. For example if user X should be the application owner, then he should have permissions only to write/upload files in /var/www/application folder and no root permissions.

SSL Certificate:
Install a valid SSL Certificate and redirect all http traffic to https. You can view my blog post on how to install your apache SSL certificate from here. Redirection can be implemented by adding the appropriate rule in your .htaccess file.

Install fail2ban:
Fail2Ban scans log files like /var/log/auth.log and bans IP addresses conducting too many failed login attempts. You can find it from Github and configure it appropriately.

Set up firewall:
You should consider enabling a firewall for your infrastructure like Cloudflare that enables WAF/DDOS protection actions. You could also enable the build in Linux firewall and set up rules through iptables.

Limit ssh access:
Limit IP addresses that could access your infrastructure server. You could do that by disabling all from /etc/hosts.deny and allow only the IP addresses that you will use in /etc/hosts.allow . As a result you should

/etc/hosts.deny:
sshd : ALL

/etc/hosts.allow:
sshd : YOUR_IPS/24

PHP Hardening:
open_basedir, if set, limits all file operations to the defined directory and below. When a script tries to access the filesystem for example using fsockopen() the location of the file is checked. If the file is outside the defined directory PHP will refuse access.
Set openbasedir to your site directory. For example if your web application is a drupal installed in the directory /var/www/drupal then your openbasedir should be set to include your app directory and every other directory that you want (see below example).

open_basedir = "/home/X/:/var/www/drupal/:/tmp/"

Also you should consider disabling some php functions for security reasons like the below.

disable_functions = phpinfo,exec,shell_exec,passthru,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,proc_close,symlink,apache_getenv,apache_get_modules,apache_get_version,apache_lookup_uri,apache_note,apache_request_headers,apache_reset_timeout,apache_response_headers,apache_setenv,closelog,curl_exec,curl_multi_exec,debugger_off,debugger_on,define_syslog_var,define_syslog_variables,diskfreespace,disk_free_space,dl,escapeshellarg,escapeshellcmd,exec,ftok,ftp_connect,ftp_exec,ftp_get,ftp_login,ftp_nb_fput,ftp_put,ftp_raw,ftp_rawlist,getmypid,getmyuid,highlight_file,ignore_user_abord,ini_alter,ini_get_all,ini_restore,leak,limit,link,listen,mysql_list_dbs,openlog,parse_ini_file,passthru,pclose,pcntl_exec,pg_host,php_uname,popen,posix_access,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_mknod,posix_setegid,posix_seteuid,posix_setgid,posix_setp,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,readfile,readlink,safe_dir,satty,scandir,set_time,set_time_limit,shell_exec,show_source,socket_accept,socket_bind,socket_clear_error,socket_close,socket_connect,source,symlink,syslog,system,tmpfile,virtual

Disable allow_url_include and allow_url_fopen

allow_url_fopen=Off
allow_url_include=Off

The previous described actions should be applied on /etc/php.ini file.

Some of them may disable your web application behavior so you should check if you need them.

Apache Hardening:


Disable content or MIME sniffing:

Header set X-Content-Type-Options: "nosniff"

Defense from Clickjacking attack:

Header set X-Frame-Options: "sameorigin"

Set Strict-Transport-Security header settings configured for a timespan of 2 years:

Header set Strict-Transport-Security "max-age=63072000; includeSubDomains;"

Add X-XSS-Protection header to prevent some level of XSS:

Header set X-XSS-Protection "1; mode=block"

Add Referrer-Policy header to your webserver:

Header always set Referrer-Policy "same-origin"

Deny TRACE/TRACK requests:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]

Hide Apache Information:

ServerSignature Off
ServerTokens Prod

Of course there are a lot more things that could be applied for your infrastructure hardening per case. The system Administrator should always be up to date with the security standards and discoveries in order to eliminate risks from malicious unauthorized access.

Posted on Leave a comment

Extend available properties of User.Identity – Asp.Net [web api]

Asp.net web api by default contains some pre configured fields that can handle the registration of a user in a web app. Some of them are Email, Password, Confirm Password and others. You can extend those properties and include your own for your purposes with the following procedure.

First of all you need to execute some commands in the package manager. You can find nuget package manager in Tools -> Nuget Package Manager -> PM Console 

The first thing to do is to enable Migrations

Enable-Migrations

The you can go to Models\AccountBindingModels.cs and add your property to the class RegisterBindingModel. Also add the same property in the Models\IdentityModels.cs inside ApplicationUser class. For example lets assume you want to add a username in the registration proccess. For this purpose you can use the following line

 public string AppUserName { get; set; }

Also include in the file.

using System;

The you must execute:

Add-Migration "AppUserName"
Update-Database

Those commands will run all the migration files and update the database schema to add a AppUserName column in your database.

Then update the registration action in Controllers\AccountController.cs to store AppUserName as well.

var user = new ApplicationUser() { UserName = model.Email, Email = model.Email, AppUserName = model.AppUserName };

It was that easy. you can finally find AppUserName in your database.