Resource server ban error

Fix to allow to config several ips per resource server (IPV4/V6)

Change-Id: I73cc684009774e7dcc187ad5de425c9a1547ea76
This commit is contained in:
Sebastian Marcet 2016-02-23 16:02:07 -03:00
parent cd480b2911
commit b7eb03974e
25 changed files with 392 additions and 129 deletions

View File

@ -35,6 +35,7 @@ class ApiResourceServerController extends AbstractRESTController implements ICRU
$data['apis'] = $apis->toArray();
$client = $resource_server->getClient();
if (!is_null($client)) {
$data['client_id'] = $client->getClientId();
$data['client_secret'] = $client->getClientSecret();
@ -79,10 +80,10 @@ class ApiResourceServerController extends AbstractRESTController implements ICRU
$values = Input::all();
$rules = array(
'host' => 'required|host|max:255',
'ip' => 'required|ip|max:16',
'host' => 'required|host|max:255',
'ips' => 'required',
'friendly_name' => 'required|text|max:512',
'active' => 'required|boolean',
'active' => 'required|boolean',
);
// Creates a Validator instance and validates the data.
$validation = Validator::make($values, $rules);
@ -95,7 +96,7 @@ class ApiResourceServerController extends AbstractRESTController implements ICRU
$new_resource_server_model = $this->resource_server_service->add(
$values['host'],
$values['ip'],
$values['ips'],
$values['friendly_name'],
$values['active']);
@ -144,9 +145,9 @@ class ApiResourceServerController extends AbstractRESTController implements ICRU
$values = Input::all();
$rules = array(
'id' => 'required|integer',
'host' => 'sometimes|required|host|max:255',
'ip' => 'sometimes|required|ip|max:16',
'id' => 'required|integer',
'host' => 'sometimes|required|host|max:255',
'ips' => 'required',
'friendly_name' => 'sometimes|required|text|max:512',
);
// Creates a Validator instance and validates the data.

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
class UpdateResourceServer extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::table('oauth2_resource_server', function ($table) {
$table->text('ips');
});
DB::statement("UPDATE oauth2_resource_server SET ips = ip;");
Schema::table('oauth2_resource_server', function ($table) {
$table->dropColumn('ip');
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateWhiteListedIps extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('white_listed_ips', function($table)
{
$table->bigIncrements('id')->unsigned();
$table->text('ip');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -3,16 +3,16 @@
/**
* Class DatabaseSeeder
*/
class DatabaseSeeder extends Seeder {
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Eloquent::unguard();
/**
* Run the database seeds.
* @return void
*/
public function run()
{
Eloquent::unguard();
$this->call('OpenIdExtensionsSeeder');
$this->call('ServerConfigurationSeeder');
@ -28,6 +28,5 @@ class DatabaseSeeder extends Seeder {
$this->call('ApiSeeder');
$this->call('ApiScopeSeeder');
$this->call('ApiEndpointSeeder');
}
}
}

View File

@ -360,9 +360,17 @@ SQL;
ResourceServer::create(
array(
'friendly_name' => 'test resource server',
'host' => $components['host'],
'ip' => '127.0.0.1'
'friendly_name' => 'test resource server',
'host' => $components['host'],
'ips' => '127.0.0.1,10.0.0.0,2001:4800:7821:101:be76:4eff:fe06:858b,174.143.201.173'
)
);
ResourceServer::create(
array(
'friendly_name' => 'test resource server 2',
'host' => $components['host'],
'ips' => '10.0.0.0,2001:4800:7821:101:be76:4eff:fe06:858b,174.143.201.173'
)
);
@ -644,7 +652,8 @@ SQL;
private function seedTestUsersAndClients(){
$resource_server = ResourceServer::first();
$resource_server = ResourceServer::where('friendly_name', '=', 'test resource server')->first();
$resource_server2 = ResourceServer::where('friendly_name', '=', 'test resource server 2')->first();
// create users and clients ...
User::create(
@ -838,6 +847,24 @@ SQL;
)
);
Client::create(
array(
'app_name' => 'resource_server_client2',
'app_description' => 'resource_server_client2',
'app_logo' => null,
'client_id' => 'resource.server.2.openstack.client',
'client_secret' => '123456789123456789123456789123456789123456789',
'client_type' => IClient::ClientType_Confidential,
'application_type' => IClient::ApplicationType_Service,
'token_endpoint_auth_method' => OAuth2Protocol::TokenEndpoint_AuthMethod_ClientSecretBasic,
'resource_server_id' => $resource_server2->id,
'rotate_refresh_token' => false,
'use_refresh_token' => false,
'client_secret_expires_at' => $now->add(new \DateInterval('P6M')),
)
);
$client_confidential = Client::where('app_name','=','oauth2_test_app')->first();
$client_confidential2 = Client::where('app_name','=','oauth2_test_app2')->first();
$client_confidential3 = Client::where('app_name','=','oauth2_test_app3')->first();

View File

@ -136,6 +136,7 @@ class ValidateBearerTokenGrantType extends AbstractGrantType
)
);
}
if (!$this->current_client->isResourceServerClient())
{
// if current client is not a resource server, then we could only access to our own tokens
@ -174,14 +175,14 @@ class ValidateBearerTokenGrantType extends AbstractGrantType
);
}
//check resource server ip address
if ($current_ip !== $resource_server->ip)
if (!$resource_server->isOwn($current_ip))
{
throw new BearerTokenDisclosureAttemptException
(
sprintf
(
'resource server ip (%s) differs from current request ip %s',
$resource_server->ip,
$resource_server->getIPAddresses(),
$current_ip
)
);

View File

@ -18,15 +18,13 @@ interface IResourceServer {
* @return bool
*/
public function isActive();
public function setActive($active);
/**
* get resource server ip address
* @return string
* @param bool $active
* @return void
*/
public function getIp();
public function setActive($active);
public function setIp($ip);
/**
* get resource server friendly name
@ -40,4 +38,14 @@ interface IResourceServer {
*/
public function getClient();
/**
* @param string $ip
* @return bool
*/
public function isOwn($ip);
/**
* @return string
*/
public function getIPAddresses();
}

View File

@ -54,16 +54,14 @@ interface IResourceServerService {
public function delete($id);
/**
* Creates a new resource server instance, and a brand new
* confidential registered client associated with it
/** Creates a new resource server instance
* @param $host
* @param $ip
* @param $ips
* @param $friendly_name
* @param bool $active
* @return IResourceServer
*/
public function add($host,$ip,$friendly_name, $active);
public function add($host, $ips, $friendly_name, $active);
/**

View File

@ -15,5 +15,5 @@ final class UtilsServiceCatalog {
const ServerConfigurationService = 'utils\\services\\IServerConfigurationService';
const CacheService = 'utils\\services\\ICacheService';
const BannedIpService = 'utils\\services\\IBannedIPService';
const TransactionService = 'utils\\db\\ITransactionService';
const TransactionService = 'utils\\db\\ITransactionService';
}

View File

@ -1,6 +1,9 @@
<?php
use utils\model\BaseModelEloquent;
/**
* Class BannedIP
*/
class BannedIP extends BaseModelEloquent
{
protected $table = 'banned_ips';

View File

@ -0,0 +1,23 @@
<?php
/**
* Copyright 2015 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use utils\model\BaseModelEloquent;
/**
* Class WhiteListedIP
*/
class WhiteListedIP extends BaseModelEloquent
{
protected $table = 'white_listed_ips';
}

View File

@ -3,10 +3,13 @@
use oauth2\models\IResourceServer;
use utils\model\BaseModelEloquent;
/**
* Class ResourceServer
*/
class ResourceServer extends BaseModelEloquent implements IResourceServer
{
protected $fillable = array('host', 'ip', 'active', 'friendly_name');
protected $fillable = array('host', 'ips', 'active', 'friendly_name');
protected $table = 'oauth2_resource_server';
@ -49,15 +52,6 @@ class ResourceServer extends BaseModelEloquent implements IResourceServer
return $this->active;
}
/**
* get resource server ip address
* @return string
*/
public function getIp()
{
return $this->ip;
}
/**
* get resource server friendly name
* @return mixed
@ -85,13 +79,26 @@ class ResourceServer extends BaseModelEloquent implements IResourceServer
$this->active = $active;
}
public function setIp($ip)
{
$this->ip = $ip;
}
public function setFriendlyName($friendly_name)
{
$this->friendly_name = $friendly_name;
}
/**
* @param string $ip
* @return bool
*/
public function isOwn($ip)
{
$ips = explode(',', $this->ips);
return in_array($ip, $ips);
}
/**
* @return string
*/
public function getIPAddresses()
{
return $this->ips;
}
}

View File

@ -65,7 +65,7 @@ final class ResourceServerService implements IResourceServerService
if (is_null($resource_server)) {
throw new InvalidResourceServer(sprintf('resource server id %s does not exists!', $id));
}
$allowed_update_params = array('host', 'ip', 'active', 'friendly_name');
$allowed_update_params = array('host', 'ips', 'active', 'friendly_name');
foreach ($allowed_update_params as $param) {
if (array_key_exists($param, $params)) {
@ -158,12 +158,12 @@ final class ResourceServerService implements IResourceServerService
/** Creates a new resource server instance
* @param $host
* @param $ip
* @param $ips
* @param $friendly_name
* @param bool $active
* @return IResourceServer
*/
public function add($host, $ip, $friendly_name, $active)
public function add($host, $ips, $friendly_name, $active)
{
$client_service = $this->client_service;
@ -175,7 +175,7 @@ final class ResourceServerService implements IResourceServerService
return $this->tx_service->transaction(function () use (
$host,
$ip,
$ips,
$friendly_name,
$active,
$client_service
@ -186,10 +186,10 @@ final class ResourceServerService implements IResourceServerService
$host));
}
if (ResourceServer::where('ip', '=', $ip)->count() > 0)
if (ResourceServer::where('ips','like', '%'.$ips.'%')->count() > 0)
{
throw new InvalidResourceServer(sprintf('there is already another resource server with that ip (%s).',
$ip));
$ips));
}
if (ResourceServer::where('friendly_name', '=', $friendly_name)->count() > 0) {
@ -201,9 +201,9 @@ final class ResourceServerService implements IResourceServerService
(
array
(
'host' => $host,
'ip' => $ip,
'active' => $active,
'host' => $host,
'ips' => $ips,
'active' => $active,
'friendly_name' => $friendly_name
)
);
@ -258,6 +258,6 @@ final class ResourceServerService implements IResourceServerService
*/
public function getByIPAddress($ip)
{
return ResourceServer::where('ip', '=', $ip)->first();
return ResourceServer::where('ips','like', '%'.$ip.'%')->first();
}
}

View File

@ -887,10 +887,8 @@ final class TokenService implements ITokenService
if (!is_array($current_audience)) {
$current_audience = array($current_audience);
}
return \ResourceServer
::where('active', '=', true)
->where('ip', '=', $current_ip)
return \ResourceServer::where('ips','like', '%'.$current_ip.'%')
->where('active', '=', true)
->whereIn('host', $current_audience)->count() > 0;
}

View File

@ -111,6 +111,9 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
$res = true;
$remote_address = IPHelper::getUserIp();
try {
if($this->isIPAddressWhitelisted($remote_address)) return true;
//check if banned ip is on cache ...
if ($this->cache_service->incCounterIfExists($remote_address)) {
$this->counter_measure->trigger();
@ -155,7 +158,6 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
Log::error($ex);
$res = false;
}
return $res;
}
@ -196,7 +198,7 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
);
$initial_delay_on_tar_pit = intval($this->server_configuration_service->getConfigValue($params[1]));
if ($exception_count >= $max_attempts && !$this->isIPAddressWhitelisted($remote_ip))
if (!$this->isIPAddressWhitelisted($remote_ip) && $exception_count >= $max_attempts)
{
Log::warning
(
@ -227,8 +229,9 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
*/
private function isIPAddressWhitelisted($ip)
{
$rs = $this->resource_server_service->getByIPAddress($ip);
return !is_null($rs);
$resource_server = $this->resource_server_service->getByIPAddress($ip);
$white_listed_ip = \WhiteListedIP::where('ip','=', $ip)->first();
return !is_null($resource_server) || !is_null($white_listed_ip);
}
}

View File

@ -44,6 +44,7 @@ Log::useDailyFiles(storage_path() . '/logs/' . $logFile,$days = 0, $level = 'deb
//set email log
$to = Config::get('log.to_email');
$from = Config::get('log.from_email');
if(!empty($to) && !empty($from)){
$subject = 'openstackid error';
$mono_log = Log::getMonolog();

View File

@ -345,11 +345,65 @@ class OAuth2ProtocolTest extends OpenStackIDBaseTest
//old token and new token should be equal
$this->assertTrue(!empty($validate_access_token));
$this->assertTrue($validate_access_token === $access_token);
return $access_token;
} catch (Exception $ex) {
throw $ex;
}
}
public function testResourceServerInstrospection()
{
$access_token = $this->testValidateToken();
$client_id = 'resource.server.1.openstack.client';
$client_secret = '123456789123456789123456789123456789123456789';
//do token validation ....
$params = array(
'token' => $access_token,
);
$response = $this->action("POST", "OAuth2ProviderController@introspection",
$params,
array(),
array(),
// Symfony interally prefixes headers with "HTTP", so
array("HTTP_Authorization" => " Basic " . base64_encode($client_id . ':' . $client_secret)));
$this->assertResponseStatus(200);
$this->assertEquals('application/json;charset=UTF-8', $response->headers->get('Content-Type'));
$content = $response->getContent();
$response = json_decode($content);
$validate_access_token = $response->access_token;
//old token and new token should be equal
$this->assertTrue(!empty($validate_access_token));
$this->assertTrue($validate_access_token === $access_token);
}
public function testResourceServerInstrospectionNotValidIP()
{
$access_token = $this->testValidateToken();
$client_id = 'resource.server.2.openstack.client';
$client_secret = '123456789123456789123456789123456789123456789';
//do token validation ....
$params = array(
'token' => $access_token,
);
$response = $this->action("POST", "OAuth2ProviderController@introspection",
$params,
array(),
array(),
// Symfony interally prefixes headers with "HTTP", so
array("HTTP_Authorization" => " Basic " . base64_encode($client_id . ':' . $client_secret)));
$this->assertResponseStatus(400);
$this->assertEquals('application/json;charset=UTF-8', $response->headers->get('Content-Type'));
$content = $response->getContent();
$response = json_decode($content);
}
/** test validate token grant
* @throws Exception
*/

View File

@ -21,6 +21,8 @@ abstract class OpenStackIDBaseTest extends TestCase {
{
if (Schema::hasTable('banned_ips'))
DB::table('banned_ips')->delete();
if (Schema::hasTable('white_listed_ips'))
DB::table('white_listed_ips')->delete();
if (Schema::hasTable('user_exceptions_trail'))
DB::table('user_exceptions_trail')->delete();
if (Schema::hasTable('server_configuration'))

View File

@ -4,8 +4,8 @@
* Class ResourceServerApiTest
* Test ResourceServer REST API
*/
class ResourceServerApiTest extends TestCase {
class ResourceServerApiTest extends TestCase
{
private $current_realm;
@ -20,9 +20,10 @@ class ResourceServerApiTest extends TestCase {
$this->current_host = $parts['host'];
}
public function testGetById(){
public function testGetById()
{
$resource_server = ResourceServer::where('host','=', $this->current_host)->first();
$resource_server = ResourceServer::where('host', '=', $this->current_host)->first();
$response = $this->action("GET", "ApiResourceServerController@get",
$parameters = array('id' => $resource_server->id),
@ -30,32 +31,34 @@ class ResourceServerApiTest extends TestCase {
array(),
array());
$content = $response->getContent();
$content = $response->getContent();
$response_resource_server = json_decode($content);
$this->assertResponseStatus(200);
$this->assertTrue($response_resource_server->id === $resource_server->id);
}
public function testGetByPage(){
public function testGetByPage()
{
$response = $this->action("GET", "ApiResourceServerController@getByPage",
$parameters = array('page_nbr' => 1,'page_size'=>10),
$parameters = array('page_nbr' => 1, 'page_size' => 10),
array(),
array(),
array());
$content = $response->getContent();
$content = $response->getContent();
$list = json_decode($content);
$this->assertTrue(isset($list->total_items) && intval($list->total_items)>0);
$this->assertTrue(isset($list->total_items) && intval($list->total_items) > 0);
$this->assertResponseStatus(200);
}
public function testCreate(){
public function testCreate()
{
$data = array(
'host' => 'www.resource.server.2.test.com',
'ip' => '127.0.0.1',
'ips' => '10.0.0.1',
'friendly_name' => 'Resource Server 2',
'active' => true,
);
@ -73,11 +76,12 @@ class ResourceServerApiTest extends TestCase {
$this->assertResponseStatus(201);
}
public function testRegenerateClientSecret(){
public function testRegenerateClientSecret()
{
$data = array(
'host' => 'www.resource.server.3.test.com',
'ip' => '127.0.0.1',
'ips' => '10.0.0.2',
'friendly_name' => 'Resource Server 3',
'active' => true,
);
@ -95,7 +99,7 @@ class ResourceServerApiTest extends TestCase {
$new_id = $json_response->resource_server_id;
$response = $this->action("GET", "ApiResourceServerController@get",$parameters = array('id' => $new_id),
$response = $this->action("GET", "ApiResourceServerController@get", $parameters = array('id' => $new_id),
array(),
array(),
array());
@ -108,7 +112,7 @@ class ResourceServerApiTest extends TestCase {
$client_secret = $json_response->client_secret;
$response = $this->action("PUT", "ApiResourceServerController@regenerateClientSecret",
$parameters = array('id'=>$new_id),
$parameters = array('id' => $new_id),
array(),
array(),
array());
@ -121,24 +125,25 @@ class ResourceServerApiTest extends TestCase {
$new_secret = $json_response->new_secret;
$this->assertTrue(!empty($new_secret));
$this->assertTrue($new_secret!==$client_secret);
$this->assertTrue($new_secret !== $client_secret);
$this->assertResponseStatus(200);
}
public function testDelete(){
public function testDelete()
{
$data = array(
'host' => 'www.resource.server.4.test.com',
'ip' => '127.0.0.1',
'ips' => '10.0.0.4',
'friendly_name' => 'Resource Server 4',
'active' => true,
);
$response = $this->action("POST", "ApiResourceServerController@create",
$parameters = $data,
$parameters = $data,
array(),
array(),
array());
@ -149,7 +154,7 @@ class ResourceServerApiTest extends TestCase {
$new_id = $json_response->resource_server_id;
$response = $this->action("DELETE", "ApiResourceServerController@delete",$parameters = array('id' => $new_id),
$response = $this->action("DELETE", "ApiResourceServerController@delete", $parameters = array('id' => $new_id),
array(),
array(),
array());
@ -157,7 +162,7 @@ class ResourceServerApiTest extends TestCase {
$this->assertResponseStatus(204);
$response = $this->action("GET", "ApiResourceServerController@get",$parameters = array('id' => $new_id),
$response = $this->action("GET", "ApiResourceServerController@get", $parameters = array('id' => $new_id),
array(),
array(),
array());
@ -168,16 +173,17 @@ class ResourceServerApiTest extends TestCase {
$this->assertResponseStatus(404);
$this->assertTrue($json_response->error==='resource server not found');
$this->assertTrue($json_response->error === 'resource server not found');
}
public function testDeleteExistingOne(){
public function testDeleteExistingOne()
{
$resource_server = ResourceServer::where('host','=', $this->current_host)->first();
$resource_server = ResourceServer::where('host', '=', $this->current_host)->first();
$new_id = $resource_server->id;
$response = $this->action("DELETE", "ApiResourceServerController@delete",$parameters = array('id' => $new_id),
$response = $this->action("DELETE", "ApiResourceServerController@delete", $parameters = array('id' => $new_id),
array(),
array(),
array());
@ -186,7 +192,7 @@ class ResourceServerApiTest extends TestCase {
$this->assertResponseStatus(204);
$response = $this->action("GET", "ApiResourceServerController@get",$parameters = array('id' => $new_id),
$response = $this->action("GET", "ApiResourceServerController@get", $parameters = array('id' => $new_id),
array(),
array(),
array());
@ -195,16 +201,17 @@ class ResourceServerApiTest extends TestCase {
}
public function testUpdate(){
public function testUpdate()
{
$data = array(
'host' => 'www.resource.server.5.test.com',
'ip' => '127.0.0.1',
'ips' => '10.0.0.8',
'friendly_name' => 'Resource Server 5',
'active' => true,
);
$response = $this->action("POST", "ApiResourceServerController@create",$parameters = $data,
$response = $this->action("POST", "ApiResourceServerController@create", $parameters = $data,
array(),
array(),
array());
@ -216,13 +223,13 @@ class ResourceServerApiTest extends TestCase {
$new_id = $json_response->resource_server_id;
$data_update = array(
'id' => $new_id,
'host' => 'www.resource.server.5.test.com',
'ip' => '127.0.0.2',
'id' => $new_id,
'host' => 'www.resource.server.5.test.com',
'ips' => '127.0.0.2',
'friendly_name' => 'Resource Server 6',
);
$response = $this->action("PUT", "ApiResourceServerController@update",$parameters = $data_update, array(),
$response = $this->action("PUT", "ApiResourceServerController@update", $parameters = $data_update, array(),
array(),
array());
@ -232,7 +239,8 @@ class ResourceServerApiTest extends TestCase {
$this->assertResponseStatus(200);
$response = $this->action("GET", "ApiResourceServerController@get",$parameters = array('id' => $new_id), array(),
$response = $this->action("GET", "ApiResourceServerController@get", $parameters = array('id' => $new_id),
array(),
array(),
array());
@ -240,32 +248,33 @@ class ResourceServerApiTest extends TestCase {
$updated_values = json_decode($content);
$this->assertTrue($updated_values->ip === '127.0.0.2');
$this->assertTrue($updated_values->ips === '127.0.0.2');
$this->assertTrue($updated_values->friendly_name === 'Resource Server 6');
$this->assertResponseStatus(200);
}
public function testUpdateStatus(){
public function testUpdateStatus()
{
$data = array(
'host' => 'www.resource.server.7.test.com',
'ip' => '127.0.0.1',
'ips' => '127.0.0.8',
'friendly_name' => 'Resource Server 7',
'active' => true,
);
$response = $this->action("POST", "ApiResourceServerController@create", $data);
$this->assertResponseStatus(201);
$this->assertResponseStatus(201);
$content = $response->getContent();
$json_response = json_decode($content);
$new_id = $json_response->resource_server_id;
$response = $this->action("DELETE", "ApiResourceServerController@deactivate",array('id'=> $new_id));
$this->assertResponseStatus(200);
$response = $this->action("DELETE", "ApiResourceServerController@deactivate", array('id' => $new_id));
$this->assertResponseStatus(200);
$content = $response->getContent();
$json_response = json_decode($content);
$this->assertTrue($json_response==='ok');
$response = $this->action("GET", "ApiResourceServerController@get",$parameters = array('id' => $new_id));
$this->assertResponseStatus(200);
$this->assertTrue($json_response === 'ok');
$response = $this->action("GET", "ApiResourceServerController@get", $parameters = array('id' => $new_id));
$this->assertResponseStatus(200);
$content = $response->getContent();
$updated_values = json_decode($content);
$this->assertTrue($updated_values->active === false);

View File

@ -4,6 +4,10 @@
<title>Welcome to openstackId - Server Admin - Edit Resource Server</title>
@stop
@section('css')
{{ HTML::style('bower_assets/bootstrap-tagsinput/dist/bootstrap-tagsinput.css') }}
@append
@section('content')
@include('menu',array('is_oauth2_admin' => $is_oauth2_admin, 'is_openstackid_admin' => $is_openstackid_admin))
<a href="{{ URL::action("AdminController@listResourceServers") }}">Go Back</a>
@ -21,10 +25,13 @@
<input type="text" class="form-control" name="friendly_name" id="friendly_name" value="{{ $resource_server->friendly_name }}">
</div>
<div class="form-group">
<label class="control-label" for="ip">IP Address&nbsp;<span class="glyphicon glyphicon-info-sign accordion-toggle" aria-hidden="true" title=""></span></label>
<input type="text" class="form-control" name="ip" id="ip" value="{{ $resource_server->ip }}">
</div>
<div class="form-group">
<label for="ip">IP Addresses&nbsp;<span class="glyphicon glyphicon-info-sign accordion-toggle" aria-hidden="true"
title=""></span></label>
<input type="text" name="ips" id="ips" value="{{$resource_server->ips}}"
style="width: 100%"></input>
</div>
<div class="checkbox">
<label>
@ -147,5 +154,6 @@
success : '{{ Lang::get("messages.global_successfully_save_entity", array("entity" => "Resource Server")) }}'
};
</script>
{{ HTML::script('bower_assets/bootstrap-tagsinput/dist/bootstrap-tagsinput.js')}}
{{ HTML::script('assets/js/oauth2/profile/admin/edit-resource-server.js') }}
@append

View File

@ -7,10 +7,10 @@
<label class="control-label" for="friendly_name">Friendly Name&nbsp;<span class="glyphicon glyphicon-info-sign accordion-toggle" aria-hidden="true" title=""></span></label>
<input type="text" class="form-control" name="friendly_name" id="friendly_name">
</div>
<div class="form-group">
<label class="control-label" for="ip">IP Address&nbsp;<span class="glyphicon glyphicon-info-sign accordion-toggle" aria-hidden="true" title=""></span></label>
<input type="text" class="form-control" name="ip" id="ip">
<label for="ips">IP Addresses&nbsp;<span class="glyphicon glyphicon-info-sign accordion-toggle" aria-hidden="true"
title=""></span></label>
<input type="text" name="ips" id="ips" style="width: 100%"></input>
</div>
<div class="checkbox">
<label>

View File

@ -4,6 +4,10 @@
<title>Welcome to openstackId - Server Admin - Resource Server</title>
@stop
@section('css')
{{ HTML::style('bower_assets/bootstrap-tagsinput/dist/bootstrap-tagsinput.css') }}
@append
@section('content')
@include('menu',array('is_oauth2_admin' => $is_oauth2_admin, 'is_openstackid_admin' => $is_openstackid_admin))
<div class="row">
@ -28,7 +32,7 @@
<tr>
<th>Friendly Name</th>
<th>Host</th>
<th>IP Address</th>
<th>IP Addresses</th>
<th>Active</th>
<th>&nbsp;</th>
</tr>
@ -36,10 +40,10 @@
<tbody id="body-resource-servers">
@foreach ($resource_servers as $resource_server)
<tr id="{{ $resource_server->id }}">
<td>{{$resource_server->friendly_name}}</td>
<td>{{$resource_server->host}}</td>
<td>{{$resource_server->ip}}</td>
<td>
<td width="25%">{{$resource_server->friendly_name}}</td>
<td width="25%">{{$resource_server->host}}</td>
<td width="10%">{{$resource_server->ips}}</td>
<td width="5%">
<input type="checkbox" class="resource-server-active-checkbox" id="resource-server-active_{{$resource_server->id}}"
data-resource-server-id="{{$resource_server->id}}"
@if ( $resource_server->active)
@ -47,7 +51,7 @@
@endif
value="{{$resource_server->id}}"/>
</td>
<td>
<td width="25%">
&nbsp;
{{ HTML::link(URL::action("AdminController@editResourceServer",array("id"=>$resource_server->id)),'Edit',array('class'=>'btn btn-default active edit-resource-server','title'=>'Edits a Registered Resource Server')) }}
{{ HTML::link(URL::action("ApiResourceServerController@delete",array("id"=>$resource_server->id)),'Delete',array('class'=>'btn btn-default btn-delete active delete-resource-server','title'=>'Deletes a Registered Resource Server')) }}
@ -73,5 +77,6 @@
add : '{{URL::action("ApiResourceServerController@create",null)}}'
};
</script>
{{ HTML::script('bower_assets/bootstrap-tagsinput/dist/bootstrap-tagsinput.js')}}
{{ HTML::script('assets/js/oauth2/profile/admin/resource-servers.js') }}
@append

View File

@ -1,8 +1,23 @@
var regex_ipv4 = /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i;
var regex_ipv6 = /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i;
jQuery.validator.addMethod("ipV4", function(value, element) {
return this.optional(element) || /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i.test(value);
return this.optional(element) || regex_ipv4.test(value);
}, "Please enter a valid IPV4 address");
jQuery.validator.addMethod("ipv4V6Set", function(value, element) {
var ips = value.split(',');
for(var ip of ips)
{
var valid = regex_ipv4.test(ip);
if(!valid)
valid = regex_ipv6.test(ip);
if(!valid) return false;
}
return true
}, "Please enter a valid IP (V4/V6) address");
jQuery.validator.addMethod("ssl_uri", function(value, element) {
var regex = /^https:\/\/([\w@][\w.:@]+)\/?[\w\.?=%&=\-@/$,]*$/ig;

View File

@ -87,7 +87,7 @@ jQuery(document).ready(function($){
rules: {
"host" : {required: true, nowhitespace:true,rangelength: [1, 512]},
"friendly_name": {required: true, free_text:true,rangelength: [1, 255]},
"ip": {required: true, ipV4:true}
"ips": {required: true, ipv4V6Set: true }
}
});
@ -99,6 +99,23 @@ jQuery(document).ready(function($){
});
$('#ips').tagsinput({
trimValue: true,
onTagExists: function(item, $tag) {
$tag.hide().fadeIn();
},
allowDuplicates: false
});
$('#ips').on('beforeItemAdd', function(event) {
var ip = event.item;
var valid = regex_ipv4.test(ip);
if(!valid)
valid = regex_ipv6.test(ip);
if(!valid)
event.cancel = true;
});
api_dialog.on('hidden.bs.modal', function () {
api_form.cleanForm();
api_validator.resetForm();

View File

@ -9,13 +9,13 @@ function loadResourceServers(){
success: function (data,textStatus,jqXHR) {
//load data...
var uris = data.page;
var template = $('<tbody><tr><td class="fname"></td><td class="hname"></td><td class="ip"></td><td class="resource-server-active"><input type="checkbox" class="resource-server-active-checkbox"></td><td>&nbsp;<a class="btn btn-default active edit-resource-server" title="Edits a Registered Resource Server">Edit</a>&nbsp;<a class="btn btn-default btn-delete active delete-resource-server" title="Deletes a Registered Resource Server">Delete</a></td></tr></tbody>');
var template = $('<tbody><tr><td width="25%" class="fname"></td><td width="25%" class="hname"></td><td width="10%"class="ips"></td><td width="5%" class="resource-server-active"><input type="checkbox" class="resource-server-active-checkbox"></td><td width="25%">&nbsp;<a class="btn btn-default active edit-resource-server" title="Edits a Registered Resource Server">Edit</a>&nbsp;<a class="btn btn-default btn-delete active delete-resource-server" title="Deletes a Registered Resource Server">Delete</a></td></tr></tbody>');
var directives = {
'tr':{
'resource_server<-context':{
'td.fname':'resource_server.friendly_name',
'td.hname':'resource_server.host',
'td.ip':'resource_server.ip',
'td.ips':'resource_server.ips',
'.resource-server-active-checkbox@value':'resource_server.id',
'.resource-server-active-checkbox@checked':function(arg){
return arg.item.active?'true':'';
@ -60,7 +60,7 @@ $(document).ready(function() {
rules: {
"host" : {required: true, nowhitespace:true,rangelength: [1, 512]},
"friendly_name": {required: true, free_text:true,rangelength: [1, 255]},
"ip": {required: true, ipV4:true}
"ips": { required: true},
}
});
@ -69,6 +69,23 @@ $(document).ready(function() {
backdrop:"static"
});
$('#ips').tagsinput({
trimValue: true,
onTagExists: function(item, $tag) {
$tag.hide().fadeIn();
},
allowDuplicates: false
});
$('#ips').on('beforeItemAdd', function(event) {
var ip = event.item;
var valid = regex_ipv4.test(ip);
if(!valid)
valid = regex_ipv6.test(ip);
if(!valid)
event.cancel = true;
});
dialog_resource_server.on('hidden', function () {
resource_server_form.cleanForm();
resource_server_validator.resetForm();