class AuthMongo

Public Class Methods

new(config = nil) click to toggle source
# File lib/mongo-proxy/auth.rb, line 14
def initialize(config = nil)
  @config = config
  @log = @config[:logger]
  @request_id = 20
  @last_error = {}
end

Public Instance Methods

wire_auth(conn, msg) click to toggle source
# File lib/mongo-proxy/auth.rb, line 21
def wire_auth(conn, msg)
  return nil unless msg

  authed, response = auth(conn, msg)

  if !authed
    @last_error[conn] = true
  else
    @last_error[conn] = false
  end

  if response
    return WireMongo::build_reply(response, get_request_id, msg[:header][:requestID])
  else
    return authed
  end
end

Private Instance Methods

auth(conn, msg) click to toggle source
# File lib/mongo-proxy/auth.rb, line 86
def auth(conn, msg)
  op = msg[:header][:opCode]

  if op == WireMongo::OP_KILL_CURSORS
    return true, nil
  end

  db = msg[:database]
  coll = msg[:collection]
  query = (msg[:query] or {})

  case op
  when WireMongo::OP_QUERY, WireMongo::OP_GET_MORE
    return reply_unauth(db, coll) unless db and coll
    return reply_unauth(db, coll) if query['$where'] != nil

    # handle authentication process
    if coll == '$cmd'

      if query['count']
        # fields key can be nil but must exist
        unless query.size == 3 and query['query'] and query.has_key? 'fields'
          return reply_unauth(db, coll)
        end
        return true, nil

      elsif query['getlasterror'] == 1
        if @last_error[conn]
          return reply_unauth(db, coll)
          @last_error[conn] = false
        else
          return true, nil
        end

      # allow ismaster query, listDatabases query
      elsif db == 'admin'
        if @@admin_cmd_whitelist.include?(query)
          return true, nil
        elsif query['getLog'] == 'startupWarnings'
          if @config[:motd]
            return reply_motd
          else
            return true
          end
        end

      end # if db == 'admin'
      return reply_unauth(db, coll)
    end # if coll == '$cmd'

    return true, nil if coll == 'system.namespaces' # list collections
    return reply_unauth(db, coll) if coll[0] == '$' #other command

    return true, nil

  when WireMongo::OP_UPDATE, WireMongo::OP_INSERT, WireMongo::OP_DELETE
    #return reply_unauth(db, coll)
    return false, nil

  else
    return reply_unauth(db, coll)

  end
end
get_request_id() click to toggle source
# File lib/mongo-proxy/auth.rb, line 79
def get_request_id
  x = @request_id
  @request_id += 1
  return x
end
reply_error(err) click to toggle source
# File lib/mongo-proxy/auth.rb, line 66
def reply_error(err)
  return false, {
    'errmsg' => err,
    'ok' => 0.0
  }
end
reply_motd() click to toggle source
# File lib/mongo-proxy/auth.rb, line 41
def reply_motd
  motd = @config[:motd]
  motd = motd.split("\n")
  return true, {
    'totalLinesWritten' => motd.size,
    'log' => motd,
    'ok' => 1.0
  }
end
reply_ok() click to toggle source
# File lib/mongo-proxy/auth.rb, line 73
def reply_ok
  return true, {
    'ok' => 1.0
  }
end
reply_unauth(db, coll) click to toggle source
# File lib/mongo-proxy/auth.rb, line 51
def reply_unauth(db, coll)
  @log.info "replying unauthed for collection #{db}.#{coll}"
  return false, {
    'ok' => 0,
    'n' => 0,
      'code' => 2,
      'errmsg' => 'Writes and Javascript execution are disallowed in this interface.',
    'writeErrors' => {
      'index' => 0,
      'code' => 2,
      'errmsg' => 'Writes and Javascript execution are disallowed in this interface.'
    }
  }
end