Regular expression support for CORS and OAuth ACLs
Make it possible for allowed_origins and valid_oauth_clients to include regular expressions, for cases where part or all of the domain/URL cannot be predicted or easily enumerated. Change-Id: I9cfc729547560438e0fa1e47cc90cd5579168c73
This commit is contained in:
parent
4c1c7c0cfc
commit
3e4e956ff8
@ -277,7 +277,8 @@ whitespace at the start of the line.
|
|||||||
.. warning:: If you are running the API in a VM, and plan to access it
|
.. warning:: If you are running the API in a VM, and plan to access it
|
||||||
remotely, ie. by its IP address or hostname, you also need to add
|
remotely, ie. by its IP address or hostname, you also need to add
|
||||||
that IP address or hostname to the ``valid_oauth_clients`` line in
|
that IP address or hostname to the ``valid_oauth_clients`` line in
|
||||||
the ``oauth`` section. Uncomment this line too.
|
the ``oauth`` section. Uncomment this line too. It can be a regular
|
||||||
|
expression as well if started with a ``^`` character.
|
||||||
|
|
||||||
|
|
||||||
5. Install tox
|
5. Install tox
|
||||||
@ -446,7 +447,8 @@ running on the same machine.
|
|||||||
|
|
||||||
If your browser is on a different machine, the hostname or IP address of the
|
If your browser is on a different machine, the hostname or IP address of the
|
||||||
machine running the API will need to be in the ``valid_oauth_clients`` key of
|
machine running the API will need to be in the ``valid_oauth_clients`` key of
|
||||||
``./etc/storyboard.conf`` for the API in order to log in.
|
``./etc/storyboard.conf`` for the API in order to log in. It can be a regular
|
||||||
|
expression as well if started with a ``^`` character.
|
||||||
|
|
||||||
By default, the API server uses port 8080, and so the API can be accessed
|
By default, the API server uses port 8080, and so the API can be accessed
|
||||||
at http://localhost:8080/. That will produce a 404 as the API doesn't
|
at http://localhost:8080/. That will produce a 404 as the API doesn't
|
||||||
|
@ -61,7 +61,7 @@ enable_notifications = True
|
|||||||
# refresh_token_ttl = 604800
|
# refresh_token_ttl = 604800
|
||||||
|
|
||||||
# A list of valid client id's that may connect to StoryBoard.
|
# A list of valid client id's that may connect to StoryBoard.
|
||||||
# valid_oauth_clients = storyboard.openstack.org, localhost
|
# valid_oauth_clients = ^.*\.openstack\.org, localhost
|
||||||
|
|
||||||
[scheduler]
|
[scheduler]
|
||||||
# Storyboard's scheduled task management configuration
|
# Storyboard's scheduled task management configuration
|
||||||
@ -73,7 +73,7 @@ enable_notifications = True
|
|||||||
# W3C CORS configuration. For more information, see http://www.w3.org/TR/cors/
|
# W3C CORS configuration. For more information, see http://www.w3.org/TR/cors/
|
||||||
|
|
||||||
# List of permitted CORS domains.
|
# List of permitted CORS domains.
|
||||||
allowed_origins = https://storyboard.openstack.org, http://localhost:9000
|
allowed_origins = ^https://.*\.openstack\.org, http://localhost:9000
|
||||||
|
|
||||||
# CORS browser options cache max age (in seconds)
|
# CORS browser options cache max age (in seconds)
|
||||||
# max_age=3600
|
# max_age=3600
|
||||||
|
@ -61,7 +61,7 @@ lock_path = $state_path/lock
|
|||||||
# refresh_token_ttl = 604800
|
# refresh_token_ttl = 604800
|
||||||
|
|
||||||
# A list of valid client id's that may connect to StoryBoard.
|
# A list of valid client id's that may connect to StoryBoard.
|
||||||
# valid_oauth_clients = storyboard.openstack.org, localhost
|
# valid_oauth_clients = ^.*\.openstack\.org, localhost
|
||||||
|
|
||||||
[scheduler]
|
[scheduler]
|
||||||
# Storyboard's scheduled task management configuration
|
# Storyboard's scheduled task management configuration
|
||||||
@ -73,7 +73,7 @@ lock_path = $state_path/lock
|
|||||||
# W3C CORS configuration. For more information, see http://www.w3.org/TR/cors/
|
# W3C CORS configuration. For more information, see http://www.w3.org/TR/cors/
|
||||||
|
|
||||||
# List of permitted CORS domains.
|
# List of permitted CORS domains.
|
||||||
# allowed_origins = https://storyboard.openstack.org, http://localhost:9000
|
# allowed_origins = ^https://.*\.openstack\.org, http://localhost:9000
|
||||||
|
|
||||||
# CORS browser options cache max age (in seconds)
|
# CORS browser options cache max age (in seconds)
|
||||||
# max_age=3600
|
# max_age=3600
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
import requests
|
import requests
|
||||||
@ -62,7 +64,14 @@ class OpenIdClient(object):
|
|||||||
if not client_id:
|
if not client_id:
|
||||||
raise InvalidClient(redirect_uri=redirect_uri,
|
raise InvalidClient(redirect_uri=redirect_uri,
|
||||||
message=e_msg.NO_CLIENT_ID)
|
message=e_msg.NO_CLIENT_ID)
|
||||||
if client_id not in CONF.oauth.valid_oauth_clients:
|
oauth_client_is_invalid = True
|
||||||
|
for valid_oauth_client in CONF.oauth.valid_oauth_clients:
|
||||||
|
if ((valid_oauth_client == client_id) or
|
||||||
|
(valid_oauth_client.startswith('^') and
|
||||||
|
re.match(valid_oauth_client, client_id))):
|
||||||
|
oauth_client_is_invalid = False
|
||||||
|
break
|
||||||
|
if oauth_client_is_invalid:
|
||||||
raise UnauthorizedClient(redirect_uri=redirect_uri,
|
raise UnauthorizedClient(redirect_uri=redirect_uri,
|
||||||
message=e_msg.INVALID_CLIENT_ID)
|
message=e_msg.INVALID_CLIENT_ID)
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
# implied. See the License for the specific language governing permissions and
|
# implied. See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
# Default allowed headers
|
# Default allowed headers
|
||||||
|
|
||||||
ALLOWED_HEADERS = [
|
ALLOWED_HEADERS = [
|
||||||
@ -97,18 +99,21 @@ class CORSMiddleware(object):
|
|||||||
return start_response(status, headers, exc_info)
|
return start_response(status, headers, exc_info)
|
||||||
|
|
||||||
# Does this request match one of our origin domains?
|
# Does this request match one of our origin domains?
|
||||||
if origin in self.allowed_origins:
|
for allowed_origin in self.allowed_origins:
|
||||||
|
if ((allowed_origin == origin) or
|
||||||
|
(allowed_origin.startswith('^') and
|
||||||
|
re.match(allowed_origin, origin))):
|
||||||
|
|
||||||
# Is this an OPTIONS request?
|
# Is this an OPTIONS request?
|
||||||
if method == 'OPTIONS':
|
if method == 'OPTIONS':
|
||||||
options_headers = [('Content-Length', '0')]
|
options_headers = [('Content-Length', '0')]
|
||||||
replacement_start_response('204 No Content', options_headers)
|
replacement_start_response('204 No Content',
|
||||||
return ''
|
options_headers)
|
||||||
else:
|
return ''
|
||||||
# Handle the request.
|
else:
|
||||||
return self.app(env, replacement_start_response)
|
# Handle the request.
|
||||||
else:
|
return self.app(env, replacement_start_response)
|
||||||
# This is not a request for a permitted CORS domain. Return
|
# This is not a request for a permitted CORS domain. Return
|
||||||
# the response without the appropriate headers and let the browser
|
# the response without the appropriate headers and let the browser
|
||||||
# figure out the details.
|
# figure out the details.
|
||||||
return self.app(env, start_response)
|
return self.app(env, start_response)
|
||||||
|
Loading…
Reference in New Issue
Block a user