How to Hide Your ActiveAdmin Path
I will assume you've already installed devise in your Rails app. Also lets assume you are already using your /admin route. And lets assume you've secured your admin route possibly with code like this:
app/controllers/admin_controller.rb
class AdminController < ApplicationController
before_filter :require_permission
private
def require_permission
if not current_user.try(:admin?)
redirect_to root_path
end
end
end
or in your routes file
config/routes.rb
authenticated :user, lambda {|u| u.admin } do
get 'admin', to: 'admin#index'
end
but maybe you just want to link to ActiveAdmin from a user's hompage if they're an admin. You could simply just enter in your view:
<% if current_user.admin? %>
<%= link_to "ActiveAdmin", "/your_active_admin_url" %>
<% end %>
but then anyone could enter yourwebsite.com/your_active_admin_url
if they know the directory (presuming the other security measures aren't in effect). So let's up the paranoia and make the directory randomly change with each Rails restart
First let's edit our ActiveAdmin initializer file.
config/initializers/active_admin.rb
require 'securerandom'
ActiveAdmin.setup do |config|
config.default_namespace = SecureRandom.base64( 24
).gsub( /[+\/=]/, ""
).prepend( "aa"
).downcase
end
and lets make it as a subdirectory under admin. So in our routes file:
config/routes.rb
scope :admin do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
end
Now since the namespace is random it will look something like this /admin/aanoh3viemwxppom9sxgfpdhv99c01gsf/dashboard
and it will change every time Rails is restarted.
You might be thinking... well that's cool and all, but how am I going to know how to get to the ActiveAdmin page on a server where I don't see the routes? I can't guess it...
Now this is where you will need a url path helper to update your links every time the path changes. So let's create a helper method. Paste this in your file:
app/helpers/application_helper.rb
module ApplicationHelper
def active_admin
ObjectSpace.each_object(
ActiveAdmin::Resource::Routes
).first.namespace.name
end
end
and now every time you want to use Rail's built-in path helpers you will prepend them with an eval of this. For example:
eval("#{active_admin}_dashboard_path")
So now you can change the link on your admin users page to this:
<% if current_user.admin? %>
<%= link_to "ActiveAdmin", eval("#{active_admin}_dashboard_path") %>
<% end %>
And you've done it! Random folder path for ActiveAdmin achieved! So for the paranoid feel free to incorporate ALL of the above methods for admin security. And make sure they work before you lock yourself out ;-)
Of course the weakest link in security is people. Everyone you give admin privileges to are an added security risk. Because people are most often susceptible to social engineering. So make sure all admin's are educated on this to help maintain your system's integrity.
God Bless! Code, Comment, Share!
-Daniel P. Clark
Written by Daniel P. Clark
Related protips
3 Responses
The only problem here is that you lose the ability to bookmark the URL since it does in fact change every time rails is restarted. How does this work on a load balancer? If deployed to multiple servers would each instance not have its own URL?
Yes it is purposefully done so you can't bookmark it. Security in obscurity. And yes if it's on multiple servers each would have it's own url... but they would each work on their own servers. ActiveAdmin controls themselves don't have a problem with the relative url. You will often handle items/resources from outside of ActiveAdmin scope. Otherwise you can simply include the dynamic directory link helper.
If several ActiveAdmin's are running on different servers and accessing the same database resource, this obscure subdirectory has no affect on how the data is handled or processed. It will be the same as if there were no obscure subdirectory.
I'm not sure about a load balancer. It's just a link, although dynamic, so I don't believe it would be an issue.
If for some reason you wanted to access ActiveAdmin's on different servers as they may have instances where they would keep controls specific to that server, then you could design an api call to the random directory string. But then again you would want to secure and obscure the api call. ;-) Or just ensure the admin user is logged in for the remote request to get the directory string. It all depends on how far you want to go with it.
after all this process, what if I personally want to access next time?