Przeglądaj źródła

Agregado de variable con ip denegadas

Agregado del chequeo por firewalls compartidos (context,stateless)
gabriel 7 lat temu
rodzic
commit
d31c6ee7a8
2 zmienionych plików z 156 dodań i 69 usunięć
  1. 114 61
      Security/Firewall/OAuthProxyListener.php
  2. 42 8
      Utils/IpUtils.php

+ 114 - 61
Security/Firewall/OAuthProxyListener.php

@@ -9,22 +9,26 @@ 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
 {
 
     /**
-     * @var TokenStorageInterface 
+     * @var TokenStorageInterface
      */
     protected $tokenStorage;
 
     /**
-     * @var AuthenticationManagerInterface 
+     * @var AuthenticationManagerInterface
      */
     protected $authenticationManager;
-    
+
     /**
      * @var AccessTokenService
      */
@@ -45,58 +49,81 @@ class OAuthProxyListener implements ListenerInterface
 
     /**
      * 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);
+        // 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())) {
+            $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.
+            $error = false;
+        } else if ($request->headers->has("php-auth-user") && $request->headers->has("php-auth-pw")) {
+            // 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);
-            }
+            // 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;
+            $error = !$this->clientIp($request);
         } else {
-            return $this->deny($event);
+            $error = true;
         }
-                
+        if ($error) {
+            $this->deny($event);
+        }
+    }
+
+    /**
+     * @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)) {
@@ -107,32 +134,58 @@ class OAuthProxyListener implements ListenerInterface
 
             $token = new OAuthToken($accessToken, $user->getRoles());
             $token->setUser($user);
-            
+
             $authToken = $this->authenticationManager->authenticate($token);
             $this->tokenStorage->setToken($authToken);
-            
-            return;
+
+            return true;
         } catch (\Exception $failed) {
             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;
+    }
 }