Przeglądaj źródła

Merge remote-tracking branch 'origin/FD3-284'

Luciano Andrade 7 lat temu
rodzic
commit
3dfe0b95b0

+ 3 - 1
Resources/config/services.yml

@@ -12,4 +12,6 @@ services:
     auth.oauth_proxy.listener:
         class: AuthBundle\Security\Firewall\OAuthProxyListener
         arguments: [ '@security.token_storage', '@security.authentication.manager', '@auth.access_token.service' ]
-        public: false
+        public: false
+        calls:
+            - [ setLogger, ['@logger'] ]

+ 130 - 52
Security/Firewall/OAuthProxyListener.php

@@ -5,12 +5,17 @@ namespace AuthBundle\Security\Firewall;
 use AuthBundle\Services\AccessTokenService;
 use Base\OAuthClientBundle\Security\Core\User\CustomOAuthUser;
 use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
+use Monolog\Logger;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
 use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
 use Symfony\Component\Security\Core\Exception\AuthenticationException;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
 use Symfony\Component\Security\Http\Firewall\ListenerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
 
 class OAuthProxyListener implements ListenerInterface
 {
@@ -29,7 +34,10 @@ class OAuthProxyListener implements ListenerInterface
      * @var AccessTokenService
      */
     protected $accessTokenService;
-
+    /**
+     * @var Logger
+     */
+    private $logger;
 
     /**
      * @param TokenStorageInterface $tokenStorage
@@ -43,60 +51,104 @@ class OAuthProxyListener implements ListenerInterface
         $this->accessTokenService = $accessTokenService;
     }
 
+    /**
+     * @param Logger $logger
+     */
+    public function setLogger(Logger $logger)
+    {
+        $this->logger = $logger;
+    }
+
+
     /**
      * Se crea el User y Token mediante alguno de los métodos
      *
      * 1. Http Basic
      * 2. Authorization
      * 3. Client Ip
+     * 4. Firewalls
      *
      * @param GetResponseEvent $event
-     *
      * @return type
+     *
      */
     public function handle(GetResponseEvent $event)
     {
         $request = $event->getRequest();
-        $auth_info = array();
-        if ($request->headers->has("php-auth-user") && $request->headers->has("php-auth-pw")) {
-            $username = $request->headers->get("php-auth-user");
-            $password = $request->headers->get("php-auth-pw");
-            $token = $this->accessTokenService->getToken($username, $password);
-            unset($token['user_info']);
-            $accessToken = $token;
-            $auth_info = $this->accessTokenService->getUserInfo($username, $password);
+        $messageLog = "";
+        // verifico si la ip esta bloqueada. Se utiliza la variable API_CIDR_DENY para almacenar las ip o rangos de ip
+        if (\AuthBundle\Utils\IpUtils::checkIpDeny($request->getClientIp())) {
+            $messageLog = "Deny IP: " . $request->getClientIp();
+            $error = true;
+        } else if (($this->tokenStorage != null &&
+            $this->tokenStorage->getToken() != null &&
+            $this->tokenStorage->getToken() instanceof OAuthToken)) {
+            // como los firewalls comparten info a traves del context no tengo que hacer nada, ya esta logueado.
+            $messageLog = "Firewalls (IP: " . $request->getClientIp() . ")";
+            $error = false;
+        } else if ($request->headers->has("php-auth-user") && $request->headers->has("php-auth-pw")) {
+            $messageLog = "PHP-AUTH (IP: " . $request->getClientIp() . ")";
+            // el header contiene php-auth-user && php-auth-pw
+            $error = !$this->PHPAuth($request);
         } elseif ($request->headers->has("authorization")) {
-            $authorization = $request->headers->get("authorization");
-            $pieces = explode(' ', $authorization);
-            $accessToken = array(
-                'access_token' => $pieces[1],
-            );
-            $auth_info = $this->accessTokenService->requestUserInfo($authorization);
-            if (isset($auth_info['username'])) {
-                $username = $auth_info['username'];
-            } else {
-                return $this->deny($event);
-            }
+            $messageLog = "AUTHORIZATION (IP: " . $request->getClientIp() . ")";
+            // el header contiene authorization
+            $error = !$this->PHPAuthorization($request);
         } elseif ($request->getClientIp()) {
-            $username = $clientIp = $request->getClientIp();
-            if (\AuthBundle\Utils\IpUtils::checkIp($clientIp) === false) {
-                return $this->deny($event);
-            }
-            // @TODO: Generar access token para el caso de IP valida
-            $accessToken = array(
-                'access_token' => '',
-            );
-            $auth_info['roles'] = array('ROLE_USER');
-            // @TODO: Traer la tenencia Base de la app Base
-            $tenancy = array(
-                'id' => 1,
-                'name' => 'Tenencia Base',
-            );
-            $auth_info['tenancies'] = $auth_info['tenancyCurrent'] = $tenancy;
+            $messageLog = "AUTHORIZATION (IP: " . $request->getClientIp() . ")";
+            $error = !$this->clientIp($request);
+        } else {
+            $messageLog = "NO REFERENCE. DENY ALL.";
+            $error = true;
+        }
+        if ($error) {
+            $this->logger->info("ERROR - " . $messageLog);
+            $this->deny($event);
         } else {
-            return $this->deny($event);
+            $this->logger->info("OK - " . $messageLog);
         }
+    }
+
+    /**
+     * @param GetResponseEvent $event
+     */
+    private function deny(GetResponseEvent $event)
+    {
+        $this->tokenStorage->setToken(null);
+
+        $response = new Response();
+        $response->setStatusCode(Response::HTTP_FORBIDDEN);
+        $event->setResponse($response);
+
+        echo 'The OAuth authentication failed.' . PHP_EOL;
 
+        return;
+    }
+
+    /**
+     * @param Request $request
+     * @return bool Retorna TRUE si pudo crear y setear el CustomOAuthUser
+     */
+    private function PHPAuth(Request $request)
+    {
+        $username = $request->headers->get("php-auth-user");
+        $password = $request->headers->get("php-auth-pw");
+        $token = $this->accessTokenService->getToken($username, $password);
+        unset($token['user_info']);
+        $accessToken = $token;
+        $auth_info = $this->accessTokenService->getUserInfo($username, $password);
+        return $this->createCustomOAuthUser($username, $accessToken, $auth_info);
+    }
+
+    /**
+     * Crea el custom user.
+     * @param string $username
+     * @param array $accessToken
+     * @param array $auth_info
+     * @return bool Retorna TRUE si pudo crear el CustomOAuthUser
+     */
+    private function createCustomOAuthUser(string $username, array $accessToken, array $auth_info)
+    {
         try {
             $user = new CustomOAuthUser($username);
             if (count($auth_info)) {
@@ -111,28 +163,54 @@ class OAuthProxyListener implements ListenerInterface
             $authToken = $this->authenticationManager->authenticate($token);
             $this->tokenStorage->setToken($authToken);
 
-            return;
+            return true;
         } catch (\Exception $failed) {
-            var_dump($failed->getMessage());
+            //var_dump($failed->getMessage());
+            return false;
         }
-
-        $this->deny($event);
     }
 
     /**
-     * @param GetResponseEvent $event
+     * @param Request $request
+     * @return bool Retorna TRUE si pudo crear y setear el CustomOAuthUser
      */
-    private function deny(GetResponseEvent $event)
+    private function PHPAuthorization($request)
     {
-        $this->tokenStorage->setToken(null);
-
-        $response = new Response();
-        $response->setStatusCode(Response::HTTP_FORBIDDEN);
-        $event->setResponse($response);
-
-        echo 'The OAuth authentication failed.' . PHP_EOL;
-
-        return;
+       $authorization = $request->headers->get("authorization");
+        $pieces = explode(' ', $authorization);
+        $accessToken = array(
+            'access_token' => $pieces[1],
+        );
+        $auth_info = $this->accessTokenService->requestUserInfo($authorization);
+        if (isset($auth_info['username'])) {
+            $username = $auth_info['username'];
+            return $this->createCustomOAuthUser($username, $accessToken, $auth_info);
+        } else {
+            return false;
+        }
     }
 
+    /**
+     * @param Request $request
+     * @return bool Retorna TRUE si pudo crear y setear el CustomOAuthUser
+     */
+    private function clientIp($request)
+    {
+        $username = $clientIp = $request->getClientIp();
+        if (\AuthBundle\Utils\IpUtils::checkIp($clientIp) === false) {
+            return false;
+        }
+        // @TODO: Generar access token para el caso de IP valida
+        $accessToken = array(
+            'access_token' => '',
+        );
+        $auth_info['roles'] = array('ROLE_USER');
+        // @TODO: Traer la tenencia Base de la app Base
+        $tenancy = array(
+            'id' => 1,
+            'name' => 'Tenencia Base',
+        );
+        $auth_info['tenancies'] = $auth_info['tenancyCurrent'] = $tenancy;
+        return $this->createCustomOAuthUser($username, $accessToken, $auth_info);
+    }
 }

+ 42 - 8
Utils/IpUtils.php

@@ -10,7 +10,7 @@ class IpUtils
     /**
      * @param string $clientIp
      * @param array $ips
-     * 
+     *
      * @return boolean
      */
     public static function checkIp($clientIp, $ips = array())
@@ -19,10 +19,9 @@ class IpUtils
             return false;
         }
         // Se filtran las ips pasadas como parametros
-        $ips = array_filter($ips, function($ip) {
+        $ips = array_filter($ips, function ($ip) {
             return IpUtils::isIp($ip);
         });
-
         // existe la variable de entorno API_CIDR ?
         // ej. API_CIDR = 127.0.0.1, 127.0.0.1-127.0.0.10, 127.0.0.1/24
         if (getenv("API_CIDR") !== false) {
@@ -30,7 +29,7 @@ class IpUtils
             $pieces = array_map('trim', explode(',', $API_CIDR));
             foreach ($pieces as $ip) {
                 if (strpos($ip, '-') !== false) {
-                    $this->getIpRange($ip, $ips);
+                    IpUtils::getIpRange($ip, $ips);
                 } elseif (IpUtils::isIp($ip)) {
                     $ips[] = $ip;
                 }
@@ -49,10 +48,10 @@ class IpUtils
     /**
      * @param string $ipRange
      * @param array $ips
-     * 
+     *
      * @return array
      */
-    public function getIpRange($ipRange, $ips = array())
+    public static function getIpRange($ipRange, $ips = array())
     {
         $pieces = array_map('trim', explode('-', $ipRange));
         if (isset($pieces[0]) && isset($pieces[1]) && IpUtils::isIp($pieces[0]) && IpUtils::isIp($pieces[1])) {
@@ -71,7 +70,7 @@ class IpUtils
 
     /**
      * @param string $ip
-     * 
+     *
      * @return boolean
      */
     public static function isIp($ip)
@@ -80,8 +79,43 @@ class IpUtils
             $pieces = explode('/', $ip);
             $ip = $pieces[0];
         }
-
         return filter_var($ip, FILTER_VALIDATE_IP);
     }
 
+    /**
+     *
+     * @param string $clientIp
+     * @param array $ips
+     *
+     * @return boolean Retorna TRUE si la ip esta dentro de las ip bloqueadas.
+     */
+    public static function checkIpDeny($clientIp, $ips = array())
+    {
+        if (IpUtils::isIp($clientIp) === false) {
+            return false;
+        }
+        // Se filtran las ips pasadas como parametros
+        $ips = array_filter($ips, function ($ip) {
+            return IpUtils::isIp($ip);
+        });
+        // existe la variable de entorno API_CIDR_DENY ?
+        // ej. API_CIDR_DENY = 127.0.0.1, 127.0.0.1-127.0.0.10, 127.0.0.1/24
+        if (getenv("API_CIDR_DENY") !== false) {
+            $API_CIDR = getenv("API_CIDR_DENY");
+            $pieces = array_map('trim', explode(',', $API_CIDR));
+            foreach ($pieces as $ip) {
+                if (strpos($ip, '-') !== false) {
+                    IpUtils::getIpRange($ip, $ips);
+                } elseif (IpUtils::isIp($ip)) {
+                    $ips[] = $ip;
+                }
+            }
+        }
+        foreach ($ips as $ip) {
+            if (trim($clientIp) == trim($ip) || SfIpUtils::checkIp($clientIp, $ip)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }