def test_is_scheme_https(self): """ When called with a URL, ``is_scheme_https()`` should return ``True`` if the scheme is HTTPS, and ``False`` otherwise. """ self.assertTrue(is_scheme_https('https://www.example.com/')) self.assertFalse(is_scheme_https('http://www.example.com/'))
def validate_pgturl(self, pgturl, pgtid, pgtiou): """ Verify the provided proxy callback URL. This verification process requires three steps: 1. The URL scheme must be HTTPS 2. The SSL certificate must be valid and its name must match that of the service 3. The callback URL must respond with a 200 or 3xx response code It is not required for validation that 3xx redirects be followed. """ # Ensure the scheme is HTTPS before proceeding if not is_scheme_https(pgturl): raise InternalError("Proxy callback %s is not HTTPS" % pgturl) # Connect to proxy callback URL, checking the SSL certificate pgturl = add_query_params(pgturl, {'pgtId': pgtid, 'pgtIou': pgtiou}) try: verify = os.environ.get('REQUESTS_CA_BUNDLE', True) r = requests.get(pgturl, verify=verify) except (requests.exceptions.ConnectionError, requests.exceptions.SSLError) as e: raise InternalError("Proxy callback %s returned %s" % (pgturl, e)) # Check the returned HTTP status code try: r.raise_for_status() except requests.exceptions.HTTPError as e: raise InternalError("Proxy callback %s returned %s" % (pgturl, e))
def validate_callback(self, service, pgturl, pgtid, pgtiou): """Verify the provided proxy callback URL.""" if not get_config(service, 'PROXY_ALLOW'): raise UnauthorizedServiceProxy("%s is not authorized to use proxy authentication" % service) if not is_scheme_https(pgturl): raise InvalidProxyCallback("Proxy callback %s is not HTTPS" % pgturl) if not is_valid_proxy_callback(service, pgturl): raise InvalidProxyCallback("%s is not an authorized proxy callback URL" % pgturl) # Check the proxy callback URL and SSL certificate pgturl_params = add_query_params(pgturl, {'pgtId': pgtid, 'pgtIou': pgtiou}) verify = os.environ.get('REQUESTS_CA_BUNDLE', True) try: r = requests.get(pgturl_params, verify=verify, timeout=3.0) except requests.exceptions.SSLError: msg = "SSL cert validation failed for proxy callback %s" % pgturl raise InvalidProxyCallback(msg) except requests.exceptions.ConnectionError: msg = "Error connecting to proxy callback %s" % pgturl raise InvalidProxyCallback(msg) except requests.exceptions.Timeout: msg = "Timeout connecting to proxy callback %s" % pgturl raise InvalidProxyCallback(msg) # Check the returned HTTP status code try: r.raise_for_status() except requests.exceptions.HTTPError as e: msg = "Proxy callback %s returned %s" % (pgturl, e) raise InvalidProxyCallback(msg)
def validate_callback(self, service, pgturl, pgtid, pgtiou): """Verify the provided proxy callback URL.""" if not proxy_allowed(service): raise UnauthorizedServiceProxy("%s is not authorized to use proxy authentication" % service) if not is_scheme_https(pgturl): raise InvalidProxyCallback("Proxy callback %s is not HTTPS" % pgturl) if not proxy_callback_allowed(service, pgturl): raise InvalidProxyCallback("%s is not an authorized proxy callback URL" % pgturl) # Verify that the SSL certificate is valid verify = os.environ.get('REQUESTS_CA_BUNDLE', True) try: requests.get(pgturl, verify=verify, timeout=5) except requests.exceptions.SSLError: raise InvalidProxyCallback("SSL certificate validation failed for proxy callback %s" % pgturl) except requests.exceptions.RequestException as e: raise InvalidProxyCallback(e) # Callback certificate appears valid, so send the ticket strings pgturl = add_query_params(pgturl, {'pgtId': pgtid, 'pgtIou': pgtiou}) try: response = requests.get(pgturl, verify=verify, timeout=5) except requests.exceptions.RequestException as e: raise InvalidProxyCallback(e) try: response.raise_for_status() except requests.exceptions.HTTPError as e: raise InvalidProxyCallback("Proxy callback %s returned %s" % (pgturl, e))
def validate_ticket(self, ticket, service, renew=False, require_https=False): """ Given a ticket string and service identifier, validate the corresponding ``Ticket``. If validation succeeds, return the ``Ticket``. If validation fails, raise an appropriate error. If ``renew`` is ``True``, ``ServiceTicket`` validation will only succeed if the ticket was issued from the presentation of the user's primary credentials. If ``require_https`` is ``True``, ``ServiceTicket`` validation will only succeed if the service URL scheme is HTTPS. """ if not ticket: raise InvalidRequest("No ticket string provided") if not self.model.TICKET_RE.match(ticket): raise InvalidTicket("Ticket string %s is invalid" % ticket) try: t = self.get(ticket=ticket) except self.model.DoesNotExist: raise InvalidTicket("Ticket %s does not exist" % ticket) if t.is_consumed(): raise InvalidTicket("%s %s has already been used" % (t.name, ticket)) if t.is_expired(): raise InvalidTicket("%s %s has expired" % (t.name, ticket)) if not service: raise InvalidRequest("No service identifier provided") if require_https and not is_scheme_https(service): raise InvalidService("Service %s is not HTTPS" % service) if not is_valid_service(service): raise InvalidService("Service %s is not a valid %s URL" % (service, t.name)) try: if not match_service(t.service, service): raise InvalidService("%s %s for service %s is invalid for " "service %s" % (t.name, ticket, t.service, service)) except AttributeError: pass try: if renew and not t.is_primary(): raise InvalidTicket("%s %s was not issued via primary " "credentials" % (t.name, ticket)) except AttributeError: pass logger.debug("Validated %s %s" % (t.name, ticket)) return t
def validate_ticket(self, ticket, service, renew=False, require_https=False): """ Given a ticket string and service identifier, validate the corresponding ``Ticket``. If validation succeeds, return the ``Ticket``. If validation fails, raise an appropriate error. If ``renew`` is ``True``, ``ServiceTicket`` validation will only succeed if the ticket was issued from the presentation of the user's primary credentials. If ``require_https`` is ``True``, ``ServiceTicket`` validation will only succeed if the service URL scheme is HTTPS. """ if not ticket: raise InvalidRequest("No ticket string provided") if not self.model.TICKET_RE.match(ticket): raise InvalidTicket("Ticket string %s is invalid" % ticket) try: t = self.get(ticket=ticket) except self.model.DoesNotExist: raise InvalidTicket("Ticket %s does not exist" % ticket) if t.is_consumed(): raise InvalidTicket("%s %s has already been used" % (t.name, ticket)) if t.is_expired(): raise InvalidTicket("%s %s has expired" % (t.name, ticket)) if not service: raise InvalidRequest("No service identifier provided") if require_https and not is_scheme_https(service): raise InvalidService("Service %s is not HTTPS" % service) if not is_valid_service_url(service): raise InvalidService("Service %s is not a valid %s URL" % (service, t.name)) try: if not same_origin(t.service, service): raise InvalidService("%s %s for service %s is invalid for " "service %s" % (t.name, ticket, t.service, service)) except AttributeError: pass try: if renew and not t.is_primary(): raise InvalidTicket("%s %s was not issued via primary " "credentials" % (t.name, ticket)) except AttributeError: pass logger.debug("Validated %s %s" % (t.name, ticket)) return t
def validate_callback(self, service, pgturl, pgtid, pgtiou): """Verify the provided proxy callback URL.""" if not can_proxy_authentication(service): raise UnauthorizedServiceProxy( "%s is not authorized to use proxy authentication" % service) if not is_scheme_https(pgturl): raise InvalidProxyCallback("Proxy callback %s is not HTTPS" % pgturl) if not is_valid_proxy_callback(service, pgturl): raise InvalidProxyCallback( "%s is not an authorized proxy callback URL" % pgturl) # Check the proxy callback URL and SSL certificate pgturl_params = add_query_params(pgturl, { 'pgtId': pgtid, 'pgtIou': pgtiou }) verify = os.environ.get('REQUESTS_CA_BUNDLE', True) try: r = requests.get(pgturl_params, verify=verify, timeout=3.0) except requests.exceptions.SSLError: msg = "SSL cert validation failed for proxy callback %s" % pgturl raise InvalidProxyCallback(msg) except requests.exceptions.ConnectionError: msg = "Error connecting to proxy callback %s" % pgturl raise InvalidProxyCallback(msg) except requests.exceptions.Timeout: msg = "Timeout connecting to proxy callback %s" % pgturl raise InvalidProxyCallback(msg) # Check the returned HTTP status code try: r.raise_for_status() except requests.exceptions.HTTPError as e: msg = "Proxy callback %s returned %s" % (pgturl, e) raise InvalidProxyCallback(msg)
def validate_callback(self, url, pgtid, pgtiou): """ Verify the provided proxy callback URL. This verification process requires three steps: 1. The URL scheme must be HTTPS 2. The SSL certificate must be valid and its name must match that of the service 3. The callback URL must respond with a 200 or 3xx response code It is not required for validation that 3xx redirects be followed. """ # Ensure the scheme is HTTPS before proceeding if not is_scheme_https(url): raise InvalidProxyCallback("Proxy callback %s is not HTTPS" % url) # Connect to proxy callback URL, checking the SSL certificate url_params = add_query_params(url, {'pgtId': pgtid, 'pgtIou': pgtiou}) verify = os.environ.get('REQUESTS_CA_BUNDLE', True) try: r = requests.get(url_params, verify=verify, timeout=3.0) except requests.exceptions.SSLError: msg = "SSL cert validation failed for proxy callback %s" % url raise InvalidProxyCallback(msg) except requests.exceptions.ConnectionError: msg = "Error connecting to proxy callback %s" % url raise InvalidProxyCallback(msg) except requests.exceptions.Timeout: msg = "Timeout connecting to proxy callback %s" % url raise InvalidProxyCallback(msg) # Check the returned HTTP status code try: r.raise_for_status() except requests.exceptions.HTTPError as e: msg = "Proxy callback %s returned %s" % (url, e) raise InvalidProxyCallback(msg)