1
0
mirror of https://github.com/vmware/vsphere-automation-sdk-python.git synced 2024-11-26 19:29:58 -05:00
vsphere-automation-sdk-python/vsphere/6.0/_modules/vmware/vapi/security/sso.html
2018-08-07 16:42:25 -07:00

524 lines
49 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vmware.vapi.security.sso &mdash; vCloud Suite SDK for Python 6.0.0 documentation</title>
<link rel="stylesheet" href="../../../../_static/vapitheme.css" type="text/css" />
<link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../../../',
VERSION: '6.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../../../_static/jquery.js"></script>
<script type="text/javascript" src="../../../../_static/underscore.js"></script>
<script type="text/javascript" src="../../../../_static/doctools.js"></script>
<link rel="top" title="vCloud Suite SDK for Python 6.0.0 documentation" href="../../../../index.html" />
<link rel="up" title="Module code" href="../../../index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../../../index.html">vCloud Suite SDK for Python 6.0.0 documentation</a> &raquo;</li>
<li><a href="../../../index.html" accesskey="U">Module code</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1>Source code for vmware.vapi.security.sso</h1><div class="highlight"><pre>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">SSO Security Helper</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="n">__author__</span> <span class="o">=</span> <span class="s">&#39;VMware, Inc.&#39;</span>
<span class="n">__copyright__</span> <span class="o">=</span> <span class="s">&#39;Copyright 2011-2014 VMware, Inc. All rights reserved. -- VMware Confidential&#39;</span>
<span class="kn">from</span> <span class="nn">base64</span> <span class="kn">import</span> <span class="n">b64encode</span><span class="p">,</span> <span class="n">b64decode</span>
<span class="kn">import</span> <span class="nn">datetime</span>
<span class="kn">import</span> <span class="nn">decimal</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">from</span> <span class="nn">lxml</span> <span class="kn">import</span> <span class="n">etree</span>
<span class="kn">from</span> <span class="nn">OpenSSL</span> <span class="kn">import</span> <span class="n">crypto</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">simplejson</span> <span class="kn">as</span> <span class="nn">json</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">from</span> <span class="nn">vmware.vapi.bindings.datetime_helper</span> <span class="kn">import</span> <span class="n">DateTimeConverter</span>
<span class="kn">from</span> <span class="nn">vmware.vapi.core</span> <span class="kn">import</span> <span class="n">SecurityContext</span>
<span class="kn">from</span> <span class="nn">vmware.vapi.data.serializers.jsonrpc</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">DecimalEncoder</span><span class="p">,</span> <span class="n">canonicalize_double</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">vmware.vapi.lib.constants</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">PARAMS</span><span class="p">,</span> <span class="n">SCHEME_ID</span><span class="p">,</span> <span class="n">EXECUTION_CONTEXT</span><span class="p">,</span> <span class="n">SECURITY_CONTEXT</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">vmware.vapi.protocol.common.lib</span> <span class="kn">import</span> <span class="n">RequestProcessor</span>
<span class="kn">from</span> <span class="nn">vmware.vapi.settings</span> <span class="kn">import</span> <span class="n">config</span>
<span class="n">key_regex</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">r&#39;-----BEGIN [A-Z ]*PRIVATE KEY-----\n&#39;</span><span class="p">)</span>
<span class="n">SAML_SCHEME_ID</span> <span class="o">=</span> <span class="s">&#39;com.vmware.vapi.std.security.saml_hok_token&#39;</span>
<span class="n">SAML_BEARER_SCHEME_ID</span> <span class="o">=</span> <span class="s">&#39;com.vmware.vapi.std.security.saml_bearer_token&#39;</span>
<span class="n">PRIVATE_KEY</span> <span class="o">=</span> <span class="s">&#39;privateKey&#39;</span>
<span class="n">SAML_TOKEN</span> <span class="o">=</span> <span class="s">&#39;samlToken&#39;</span>
<span class="n">SIGNATURE_ALGORITHM</span> <span class="o">=</span> <span class="s">&#39;signatureAlgorithm&#39;</span>
<span class="n">DEFAULT_ALGORITHM_TYPE</span> <span class="o">=</span> <span class="s">&#39;RS256&#39;</span>
<span class="n">TIMESTAMP</span> <span class="o">=</span> <span class="s">&#39;timestamp&#39;</span>
<span class="n">EXPIRES</span> <span class="o">=</span> <span class="s">&#39;expires&#39;</span>
<span class="n">CREATED</span> <span class="o">=</span> <span class="s">&#39;created&#39;</span>
<span class="n">REQUEST_VALIDITY</span> <span class="o">=</span> <span class="mi">20</span>
<span class="n">SIGNATURE</span> <span class="o">=</span> <span class="s">&#39;signature&#39;</span>
<span class="n">DIGEST</span> <span class="o">=</span> <span class="s">&#39;value&#39;</span>
<span class="n">AUTHENTICATED</span> <span class="o">=</span> <span class="s">&#39;requestAuthenticated&#39;</span>
<span class="n">STS_URL_PROP</span> <span class="o">=</span> <span class="s">&#39;stsurl&#39;</span>
<span class="n">CERTIFICATE_PROP</span> <span class="o">=</span> <span class="s">&#39;certificate&#39;</span>
<span class="n">PRIVATE_KEY_PROP</span> <span class="o">=</span> <span class="s">&#39;privatekey&#39;</span>
<span class="n">SECTION</span> <span class="o">=</span> <span class="n">__name__</span>
<span class="c"># Algorithm Header Parameter Values for JWS based on the following link</span>
<span class="c"># https://datatracker.ietf.org/doc/draft-ietf-jose-json-web-algorithms/?include_text=1</span>
<span class="n">algorithm_map</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">&#39;RS256&#39;</span><span class="p">:</span> <span class="s">&#39;sha256&#39;</span><span class="p">,</span>
<span class="s">&#39;RS384&#39;</span><span class="p">:</span> <span class="s">&#39;sha384&#39;</span><span class="p">,</span>
<span class="s">&#39;RS512&#39;</span><span class="p">:</span> <span class="s">&#39;sha512&#39;</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<div class="viewcode-block" id="setup_saml_token_processors"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.setup_saml_token_processors">[docs]</a><span class="k">def</span> <span class="nf">setup_saml_token_processors</span><span class="p">():</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If SAML token based authentication scheme is used, this operation</span>
<span class="sd"> should be invoked by the client to setup the request processors</span>
<span class="sd"> that does the request signing using the token.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">config</span><span class="o">.</span><span class="n">cfg</span><span class="o">.</span><span class="n">has_section</span><span class="p">(</span>
<span class="s">&#39;vmware.vapi.protocol.client.msg.json_connector&#39;</span><span class="p">):</span>
<span class="n">config</span><span class="o">.</span><span class="n">cfg</span><span class="o">.</span><span class="n">add_section</span><span class="p">(</span><span class="s">&#39;vmware.vapi.protocol.client.msg.json_connector&#39;</span><span class="p">)</span>
<span class="n">config</span><span class="o">.</span><span class="n">cfg</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s">&#39;vmware.vapi.protocol.client.msg.json_connector&#39;</span><span class="p">,</span>
<span class="s">&#39;processors&#39;</span><span class="p">,</span>
<span class="s">&#39;vmware.vapi.security.sso.JSONSSOSigner&#39;</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="create_saml_bearer_security_context"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.create_saml_bearer_security_context">[docs]</a><span class="k">def</span> <span class="nf">create_saml_bearer_security_context</span><span class="p">(</span><span class="n">token</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Create a security context for SAML bearer token based</span>
<span class="sd"> authentication scheme</span>
<span class="sd"> :type token: :class:`str`</span>
<span class="sd"> :param token: SAML Token</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">SecurityContext</span><span class="p">({</span><span class="n">SCHEME_ID</span><span class="p">:</span> <span class="n">SAML_BEARER_SCHEME_ID</span><span class="p">,</span>
<span class="n">SAML_TOKEN</span><span class="p">:</span> <span class="n">token</span><span class="p">})</span>
</div>
<div class="viewcode-block" id="create_saml_security_context"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.create_saml_security_context">[docs]</a><span class="k">def</span> <span class="nf">create_saml_security_context</span><span class="p">(</span><span class="n">token</span><span class="p">,</span> <span class="n">private_key</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Create a security context for SAML token based</span>
<span class="sd"> authentication scheme</span>
<span class="sd"> :type token: :class:`str`</span>
<span class="sd"> :param token: SAML Token</span>
<span class="sd"> :type private_key: :class:`str`</span>
<span class="sd"> :param private_key: Absolute file path of the private key of the user</span>
<span class="sd"> :rtype: :class:`vmware.vapi.core.SecurityContext`</span>
<span class="sd"> :return: Newly created security context</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">private_key_data</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">private_key</span><span class="p">,</span> <span class="s">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
<span class="n">private_key_data</span> <span class="o">=</span> <span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="k">return</span> <span class="n">SecurityContext</span><span class="p">({</span><span class="n">SCHEME_ID</span><span class="p">:</span> <span class="n">SAML_SCHEME_ID</span><span class="p">,</span>
<span class="n">PRIVATE_KEY</span><span class="p">:</span> <span class="n">private_key_data</span><span class="p">,</span>
<span class="n">SAML_TOKEN</span><span class="p">:</span> <span class="n">token</span><span class="p">,</span>
<span class="n">SIGNATURE_ALGORITHM</span><span class="p">:</span> <span class="n">DEFAULT_ALGORITHM_TYPE</span><span class="p">})</span>
</div>
<div class="viewcode-block" id="JSONCanonicalEncoder"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONCanonicalEncoder">[docs]</a><span class="k">class</span> <span class="nc">JSONCanonicalEncoder</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">JSONEncoder</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Custom JSON Encoder class to canonicalize dictionary</span>
<span class="sd"> and list objects</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="JSONCanonicalEncoder.encode"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONCanonicalEncoder.encode">[docs]</a> <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">o</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Encode a given python object</span>
<span class="sd"> :type o: :class:`object`</span>
<span class="sd"> :param o: Python object</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: JSON string in canonicalized form</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
<span class="c"># Remove non-significant whitespace characters</span>
<span class="c"># Keys are sorted lexicographically using UCS code</span>
<span class="c"># point values</span>
<span class="n">sorted_keys</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">o</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
<span class="n">sorted_items</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">key</span><span class="p">),</span>
<span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">o</span><span class="p">[</span><span class="n">key</span><span class="p">]))</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">sorted_keys</span><span class="p">]</span>
<span class="n">string</span> <span class="o">=</span> <span class="s">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sorted_items</span><span class="p">)</span>
<span class="k">return</span> <span class="s">&#39;{</span><span class="si">%s</span><span class="s">}&#39;</span> <span class="o">%</span> <span class="n">string</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
<span class="c"># Arrays must preserve the initial ordering</span>
<span class="c"># Remove non-significant whitespace characters</span>
<span class="n">string</span> <span class="o">=</span> <span class="s">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="bp">self</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">o</span><span class="p">])</span>
<span class="k">return</span> <span class="s">&#39;[</span><span class="si">%s</span><span class="s">]&#39;</span> <span class="o">%</span> <span class="n">string</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">decimal</span><span class="o">.</span><span class="n">Decimal</span><span class="p">):</span>
<span class="k">return</span> <span class="n">canonicalize_double</span><span class="p">(</span><span class="n">o</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">JSONEncoder</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">o</span><span class="p">)</span>
</div></div>
<div class="viewcode-block" id="JSONCanonicalizer"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONCanonicalizer">[docs]</a><span class="k">class</span> <span class="nc">JSONCanonicalizer</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This class is responsible for transforming JSON messages into their</span>
<span class="sd"> canonical representation.</span>
<span class="sd"> The canonical form is defined by the following rules:</span>
<span class="sd"> 1. Non-significant(1) whitespace characters MUST NOT be used</span>
<span class="sd"> 2. Non-significant(1) line endings MUST NOT be used</span>
<span class="sd"> 3. Entries (set of name/value pairs) in JSON objects MUST be sorted</span>
<span class="sd"> lexicographically(2) by their names based on UCS codepoint values</span>
<span class="sd"> 4. Arrays MUST preserve their initial ordering</span>
<span class="sd"> Link to the IEFT proposal:</span>
<span class="sd"> https://datatracker.ietf.org/doc/draft-staykov-hu-json-canonical-form/</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="nd">@staticmethod</span>
<div class="viewcode-block" id="JSONCanonicalizer.canonicalize"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONCanonicalizer.canonicalize">[docs]</a> <span class="k">def</span> <span class="nf">canonicalize</span><span class="p">(</span><span class="n">input_message</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Canonicalize the input message</span>
<span class="sd"> :type input_message: :class:`str`</span>
<span class="sd"> :param input_message: Input message</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: Canonicalized message</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">py_obj</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">input_message</span><span class="p">,</span> <span class="n">parse_float</span><span class="o">=</span><span class="n">decimal</span><span class="o">.</span><span class="n">Decimal</span><span class="p">)</span>
<span class="k">return</span> <span class="n">JSONCanonicalEncoder</span><span class="p">()</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">py_obj</span><span class="p">)</span>
</div>
<span class="nd">@staticmethod</span>
<div class="viewcode-block" id="JSONCanonicalizer.canonicalize_py_obj"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONCanonicalizer.canonicalize_py_obj">[docs]</a> <span class="k">def</span> <span class="nf">canonicalize_py_obj</span><span class="p">(</span><span class="n">py_obj</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Canonicalize the input python object</span>
<span class="sd"> :type input_message: :class:`object`</span>
<span class="sd"> :param input_message: Input python object</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: Canonicalized message</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">JSONCanonicalEncoder</span><span class="p">()</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">py_obj</span><span class="p">)</span>
</div></div>
<div class="viewcode-block" id="JSONSSOSigner"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONSSOSigner">[docs]</a><span class="k">class</span> <span class="nc">JSONSSOSigner</span><span class="p">(</span><span class="n">RequestProcessor</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This class is used for signing JSON request messages</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="JSONSSOSigner.process"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONSSOSigner.process">[docs]</a> <span class="k">def</span> <span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">input_message</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Sign the input JSON request message.</span>
<span class="sd"> The message is signed using user&#39;s private key. The digest and saml</span>
<span class="sd"> token is then added to the security context block of the execution</span>
<span class="sd"> context. A timestamp is also added to guard against replay attacks</span>
<span class="sd"> Sample input security context:</span>
<span class="sd"> {</span>
<span class="sd"> &#39;schemeId&#39;: &#39;SAML_TOKEN&#39;,</span>
<span class="sd"> &#39;privateKey&#39;: &lt;PRIVATE_KEY&gt;,</span>
<span class="sd"> &#39;samlToken&#39;: &lt;SAML_TOKEN&gt;,</span>
<span class="sd"> &#39;signatureAlgorithm&#39;: &lt;ALGORITHM&gt;,</span>
<span class="sd"> }</span>
<span class="sd"> Security context block before signing:</span>
<span class="sd"> {</span>
<span class="sd"> &#39;schemeId&#39;: &#39;SAML_TOKEN&#39;,</span>
<span class="sd"> &#39;signatureAlgorithm&#39;: &lt;ALGORITHM&gt;,</span>
<span class="sd"> &#39;timestamp&#39;: {</span>
<span class="sd"> &#39;created&#39;: &#39;2012-10-26T12:24:18.941Z&#39;,</span>
<span class="sd"> &#39;expires&#39;: &#39;2012-10-26T12:44:18.941Z&#39;,</span>
<span class="sd"> }</span>
<span class="sd"> }</span>
<span class="sd"> Security context block after signing:</span>
<span class="sd"> {</span>
<span class="sd"> &#39;schemeId&#39;: &#39;SAML_TOKEN&#39;,</span>
<span class="sd"> &#39;signatureAlgorithm&#39;: &lt;ALGORITHM&gt;,</span>
<span class="sd"> &#39;signature&#39;: {</span>
<span class="sd"> &#39;samlToken&#39;: &lt;SAML_TOKEN&gt;,</span>
<span class="sd"> &#39;value&#39;: &lt;DIGEST&gt;</span>
<span class="sd"> }</span>
<span class="sd"> &#39;timestamp&#39;: {</span>
<span class="sd"> &#39;created&#39;: &#39;2012-10-26T12:24:18.941Z&#39;,</span>
<span class="sd"> &#39;expires&#39;: &#39;2012-10-26T12:44:18.941Z&#39;,</span>
<span class="sd"> }</span>
<span class="sd"> }</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">input_message</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">return</span>
<span class="c"># process only if the schemeId in the request matches the schemeId of</span>
<span class="c"># this signer</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">SAML_SCHEME_ID</span> <span class="ow">in</span> <span class="n">input_message</span><span class="p">:</span>
<span class="k">return</span> <span class="n">input_message</span>
<span class="n">py_obj</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">input_message</span><span class="p">,</span> <span class="n">parse_float</span><span class="o">=</span><span class="n">decimal</span><span class="o">.</span><span class="n">Decimal</span><span class="p">)</span>
<span class="n">json_params</span> <span class="o">=</span> <span class="n">py_obj</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">PARAMS</span><span class="p">)</span> <span class="c"># pylint: disable=E1103</span>
<span class="n">ctx</span> <span class="o">=</span> <span class="n">json_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">EXECUTION_CONTEXT</span><span class="p">)</span>
<span class="n">sec_ctx</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SECURITY_CONTEXT</span><span class="p">)</span>
<span class="n">private_key</span> <span class="o">=</span> <span class="n">sec_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">PRIVATE_KEY</span><span class="p">)</span>
<span class="n">saml_token</span> <span class="o">=</span> <span class="n">sec_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SAML_TOKEN</span><span class="p">)</span>
<span class="n">jws_algorithm</span> <span class="o">=</span> <span class="n">sec_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SIGNATURE_ALGORITHM</span><span class="p">)</span>
<span class="n">algorithm</span> <span class="o">=</span> <span class="n">algorithm_map</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">jws_algorithm</span><span class="p">)</span>
<span class="n">new_sec_ctx</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">new_sec_ctx</span><span class="p">[</span><span class="n">SCHEME_ID</span><span class="p">]</span> <span class="o">=</span> <span class="n">sec_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SCHEME_ID</span><span class="p">)</span>
<span class="n">new_sec_ctx</span><span class="p">[</span><span class="n">TIMESTAMP</span><span class="p">]</span> <span class="o">=</span> <span class="n">_generate_request_timestamp</span><span class="p">()</span>
<span class="n">new_sec_ctx</span><span class="p">[</span><span class="n">SIGNATURE_ALGORITHM</span><span class="p">]</span> <span class="o">=</span> <span class="n">jws_algorithm</span>
<span class="c"># Replace the old security context with the new one</span>
<span class="k">del</span> <span class="n">ctx</span><span class="p">[</span><span class="n">SECURITY_CONTEXT</span><span class="p">]</span>
<span class="n">ctx</span><span class="p">[</span><span class="n">SECURITY_CONTEXT</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_sec_ctx</span>
<span class="n">pkey</span> <span class="o">=</span> <span class="n">crypto</span><span class="o">.</span><span class="n">load_privatekey</span><span class="p">(</span>
<span class="n">crypto</span><span class="o">.</span><span class="n">FILETYPE_PEM</span><span class="p">,</span> <span class="n">_prep_private_key</span><span class="p">(</span><span class="n">private_key</span><span class="p">))</span>
<span class="n">canonical_message</span> <span class="o">=</span> <span class="n">JSONCanonicalizer</span><span class="o">.</span><span class="n">canonicalize_py_obj</span><span class="p">(</span><span class="n">py_obj</span><span class="p">)</span>
<span class="n">digest</span> <span class="o">=</span> <span class="n">b64encode</span><span class="p">(</span><span class="n">crypto</span><span class="o">.</span><span class="n">sign</span><span class="p">(</span><span class="n">pkey</span><span class="p">,</span> <span class="n">canonical_message</span><span class="p">,</span> <span class="n">algorithm</span><span class="p">))</span>
<span class="n">new_sec_ctx</span><span class="p">[</span><span class="n">SIGNATURE</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">SAML_TOKEN</span><span class="p">:</span> <span class="n">saml_token</span><span class="p">,</span>
<span class="n">DIGEST</span><span class="p">:</span> <span class="n">digest</span><span class="p">}</span>
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">py_obj</span><span class="p">,</span>
<span class="n">check_circular</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
<span class="n">separators</span><span class="o">=</span><span class="p">(</span><span class="s">&#39;,&#39;</span><span class="p">,</span> <span class="s">&#39;:&#39;</span><span class="p">),</span>
<span class="n">cls</span><span class="o">=</span><span class="n">DecimalEncoder</span><span class="p">)</span>
</div></div>
<div class="viewcode-block" id="JSONSSOVerifier"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONSSOVerifier">[docs]</a><span class="k">class</span> <span class="nc">JSONSSOVerifier</span><span class="p">(</span><span class="n">RequestProcessor</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This class is used to verify the authenticity of the request</span>
<span class="sd"> message by verifying the digest present in the security context</span>
<span class="sd"> block.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="JSONSSOVerifier.process"><a class="viewcode-back" href="../../../../vmware.vapi.security.html#vmware.vapi.security.sso.JSONSSOVerifier.process">[docs]</a> <span class="k">def</span> <span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">input_message</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Verify the input JSON message.</span>
<span class="sd"> For verification, we need 4 things:</span>
<span class="sd"> 1. algorithm: extracted from security context</span>
<span class="sd"> 2. certificate: public key of the principal embedded in the</span>
<span class="sd"> SAML token is used</span>
<span class="sd"> 3. digest: value field from signature block</span>
<span class="sd"> 4. canonical msg: signature block is removed from the request</span>
<span class="sd"> and the remaining part is canonicalized</span>
<span class="sd"> Sample input security context:</span>
<span class="sd"> {</span>
<span class="sd"> &#39;schemeId&#39;: &#39;SAML_TOKEN&#39;,</span>
<span class="sd"> &#39;signatureAlgorithm&#39;: &lt;ALGORITHM&gt;,</span>
<span class="sd"> &#39;signature&#39;: {</span>
<span class="sd"> &#39;samlToken&#39;: &lt;SAML_TOKEN&gt;,</span>
<span class="sd"> &#39;value&#39;: &lt;DIGEST&gt;</span>
<span class="sd"> }</span>
<span class="sd"> &#39;timestamp&#39;: {</span>
<span class="sd"> &#39;created&#39;: &#39;2012-10-26T12:24:18.941Z&#39;,</span>
<span class="sd"> &#39;expires&#39;: &#39;2012-10-26T12:44:18.941Z&#39;,</span>
<span class="sd"> }</span>
<span class="sd"> }</span>
<span class="sd"> :type input_message: :class:`str`</span>
<span class="sd"> :param input_message: Input JSON request message</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: JSON request message after signature verification</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">input_message</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">SAML_SCHEME_ID</span> <span class="ow">in</span> <span class="n">input_message</span><span class="p">:</span>
<span class="k">return</span> <span class="n">input_message</span>
<span class="n">py_obj</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">input_message</span><span class="p">,</span> <span class="n">parse_float</span><span class="o">=</span><span class="n">decimal</span><span class="o">.</span><span class="n">Decimal</span><span class="p">)</span>
<span class="n">json_params</span> <span class="o">=</span> <span class="n">py_obj</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">PARAMS</span><span class="p">)</span> <span class="c"># pylint: disable=E1103</span>
<span class="n">execution_ctx</span> <span class="o">=</span> <span class="n">json_params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">EXECUTION_CONTEXT</span><span class="p">)</span>
<span class="n">sec_ctx</span> <span class="o">=</span> <span class="n">execution_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SECURITY_CONTEXT</span><span class="p">)</span>
<span class="n">signature</span> <span class="o">=</span> <span class="n">sec_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SIGNATURE</span><span class="p">)</span>
<span class="k">del</span> <span class="n">sec_ctx</span><span class="p">[</span><span class="n">SIGNATURE</span><span class="p">]</span>
<span class="n">digest</span> <span class="o">=</span> <span class="n">b64decode</span><span class="p">(</span><span class="n">signature</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">DIGEST</span><span class="p">))</span>
<span class="n">jws_algorithm</span> <span class="o">=</span> <span class="n">sec_ctx</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SIGNATURE_ALGORITHM</span><span class="p">)</span>
<span class="n">algorithm</span> <span class="o">=</span> <span class="n">algorithm_map</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">jws_algorithm</span><span class="p">)</span>
<span class="n">saml_token</span> <span class="o">=</span> <span class="n">signature</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">SAML_TOKEN</span><span class="p">)</span>
<span class="n">certificate</span> <span class="o">=</span> <span class="n">_extract_certificate</span><span class="p">(</span><span class="n">saml_token</span><span class="p">)</span>
<span class="n">pubkey</span> <span class="o">=</span> <span class="n">crypto</span><span class="o">.</span><span class="n">load_certificate</span><span class="p">(</span>
<span class="n">crypto</span><span class="o">.</span><span class="n">FILETYPE_PEM</span><span class="p">,</span> <span class="n">_prep_certificate</span><span class="p">(</span><span class="n">certificate</span><span class="p">))</span>
<span class="n">canonical_message</span> <span class="o">=</span> <span class="n">JSONCanonicalizer</span><span class="o">.</span><span class="n">canonicalize_py_obj</span><span class="p">(</span><span class="n">py_obj</span><span class="p">)</span>
<span class="n">crypto</span><span class="o">.</span><span class="n">verify</span><span class="p">(</span><span class="n">pubkey</span><span class="p">,</span> <span class="n">digest</span><span class="p">,</span> <span class="n">canonical_message</span><span class="p">,</span> <span class="n">algorithm</span><span class="p">)</span>
<span class="n">sec_ctx</span><span class="p">[</span><span class="n">SAML_TOKEN</span><span class="p">]</span> <span class="o">=</span> <span class="n">saml_token</span>
<span class="n">sec_ctx</span><span class="p">[</span><span class="n">AUTHENTICATED</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>
<span class="n">sec_ctx</span><span class="p">[</span><span class="n">SIGNATURE_ALGORITHM</span><span class="p">]</span> <span class="o">=</span> <span class="n">jws_algorithm</span>
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">py_obj</span><span class="p">,</span>
<span class="n">check_circular</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
<span class="n">separators</span><span class="o">=</span><span class="p">(</span><span class="s">&#39;,&#39;</span><span class="p">,</span> <span class="s">&#39;:&#39;</span><span class="p">),</span>
<span class="n">cls</span><span class="o">=</span><span class="n">DecimalEncoder</span><span class="p">)</span>
</div></div>
<span class="k">def</span> <span class="nf">_extract_element</span><span class="p">(</span><span class="n">xml</span><span class="p">,</span> <span class="n">element_name</span><span class="p">,</span> <span class="n">namespace</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> An internal method provided to extract an element from the given XML.</span>
<span class="sd"> :type xml: :class:`str`</span>
<span class="sd"> :param xml: The XML string from which the element will be extracted.</span>
<span class="sd"> :type element_name: :class:`str`</span>
<span class="sd"> :param element_name: The element that needs to be extracted from the XML.</span>
<span class="sd"> :type namespace: :class:`dict`</span>
<span class="sd"> :param namespace: A dict containing the namespace of the element to be</span>
<span class="sd"> extracted.</span>
<span class="sd"> :rtype: etree element.</span>
<span class="sd"> :return: The extracted element.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">assert</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">namespace</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">xml</span><span class="o">.</span><span class="n">xpath</span><span class="p">(</span><span class="s">&quot;//</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">namespace</span><span class="o">.</span><span class="n">keys</span><span class="p">())[</span><span class="mi">0</span><span class="p">],</span> <span class="n">element_name</span><span class="p">),</span>
<span class="n">namespaces</span><span class="o">=</span><span class="n">namespace</span><span class="p">)</span>
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
<span class="k">return</span> <span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> does not seem to be present in the XML.&quot;</span> <span class="o">%</span>
<span class="n">element_name</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_prep_private_key</span><span class="p">(</span><span class="n">private_key</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Append proper prefix and suffix text to a private key. There is no</span>
<span class="sd"> standard way for storing certificates. OpenSSL expects the demarcation</span>
<span class="sd"> text. This method makes sure that the text the markers are present.</span>
<span class="sd"> :type text: :class:`str`</span>
<span class="sd"> :param text: The private key of the service user.</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: Normalized private key.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">key_regex</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">private_key</span><span class="p">):</span>
<span class="k">return</span> <span class="s">&quot;&quot;&quot;-----BEGIN RSA PRIVATE KEY-----</span>
<span class="si">%s</span><span class="s"></span>
<span class="s">-----END RSA PRIVATE KEY-----&quot;&quot;&quot;</span> <span class="o">%</span> <span class="n">private_key</span>
<span class="k">return</span> <span class="n">private_key</span>
<span class="k">def</span> <span class="nf">_prep_certificate</span><span class="p">(</span><span class="n">certificate</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Append proper prefix and suffix text to a certificate. There is no</span>
<span class="sd"> standard way for storing certificates. OpenSSL expects the demarcation</span>
<span class="sd"> text. This method makes sure that the text the markers are present.</span>
<span class="sd"> :type text: :class:`str`</span>
<span class="sd"> :param text: The certificate of the service user.</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: Normalized certificate</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">certificate</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;-----BEGIN CERTIFICATE-----&#39;</span><span class="p">):</span>
<span class="k">return</span> <span class="s">&quot;&quot;&quot;-----BEGIN CERTIFICATE-----</span>
<span class="si">%s</span><span class="s"></span>
<span class="s">-----END CERTIFICATE-----&quot;&quot;&quot;</span> <span class="o">%</span> <span class="n">certificate</span>
<span class="k">return</span> <span class="n">certificate</span>
<span class="k">def</span> <span class="nf">_extract_certificate</span><span class="p">(</span><span class="n">hok_token</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Extract Certificate of the principal from Holder of Key SAML token</span>
<span class="sd"> :type hok_token: :class:`str`</span>
<span class="sd"> :param hok_token: Holder of key SAML token</span>
<span class="sd"> :rtype: :class:`str`</span>
<span class="sd"> :return: Certificate of the principal</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">xml</span> <span class="o">=</span> <span class="n">etree</span><span class="o">.</span><span class="n">fromstring</span><span class="p">(</span><span class="n">hok_token</span><span class="p">)</span>
<span class="n">subject</span> <span class="o">=</span> <span class="n">_extract_element</span><span class="p">(</span>
<span class="n">xml</span><span class="p">,</span>
<span class="s">&#39;SubjectConfirmationData&#39;</span><span class="p">,</span>
<span class="p">{</span><span class="s">&#39;saml2&#39;</span><span class="p">:</span> <span class="s">&#39;urn:oasis:names:tc:SAML:2.0:assertion&#39;</span><span class="p">})</span>
<span class="n">xml_certificate</span> <span class="o">=</span> <span class="n">subject</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="n">xml_certificate</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\\</span><span class="s">n&#39;</span><span class="p">,</span> <span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_generate_request_timestamp</span><span class="p">():</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Generate a timestamp for the request. This will be embedded in the security</span>
<span class="sd"> context of the request to protect it against replay attacks</span>
<span class="sd"> :rtype: :class:`dict`</span>
<span class="sd"> :return: Timestamp block that can be inserted in security context</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">created_dt</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">utcnow</span><span class="p">()</span>
<span class="n">offset</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">minutes</span><span class="o">=</span><span class="n">REQUEST_VALIDITY</span><span class="p">)</span>
<span class="n">created</span> <span class="o">=</span> <span class="n">DateTimeConverter</span><span class="o">.</span><span class="n">convert_from_datetime</span><span class="p">(</span><span class="n">created_dt</span><span class="p">)</span>
<span class="n">expires</span> <span class="o">=</span> <span class="n">DateTimeConverter</span><span class="o">.</span><span class="n">convert_from_datetime</span><span class="p">(</span><span class="n">created_dt</span> <span class="o">+</span> <span class="n">offset</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span><span class="n">EXPIRES</span><span class="p">:</span> <span class="n">expires</span><span class="p">,</span> <span class="n">CREATED</span><span class="p">:</span> <span class="n">created</span><span class="p">}</span>
</pre></div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../../../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="../../../../index.html">vCloud Suite SDK for Python 6.0.0 documentation</a> &raquo;</li>
<li><a href="../../../index.html" >Module code</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2014, VMware, Inc..
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>