diff --git a/pr/558/.buildinfo b/pr/558/.buildinfo new file mode 100644 index 00000000..ce8d7095 --- /dev/null +++ b/pr/558/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 28e360c58107c7f3efabd87cc17bbc9d +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/pr/558/_static/_sphinx_javascript_frameworks_compat.js b/pr/558/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000..8549469d --- /dev/null +++ b/pr/558/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,134 @@ +/* + * _sphinx_javascript_frameworks_compat.js + * ~~~~~~~~~~ + * + * Compatability shim for jQuery and underscores.js. + * + * WILL BE REMOVED IN Sphinx 6.0 + * xref RemovedInSphinx60Warning + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/pr/558/_static/antsibull-minimal.css b/pr/558/_static/antsibull-minimal.css new file mode 100644 index 00000000..85c1ce33 --- /dev/null +++ b/pr/558/_static/antsibull-minimal.css @@ -0,0 +1,3 @@ +@charset "UTF-8"; +/* Copyright (c) Ansible and contributors */ +/* GNU General Public License v3.0+ (see https://www.gnu.org/licenses/gpl-3.0.txt) */.ansible-links{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.ansible-links>a{padding:4px 12px;margin:2px 4px;cursor:pointer;border-radius:3px;background-color:#5bbdbf;color:#fff}.ansible-links>a:active,.ansible-links>a:focus,.ansible-links>a:hover{background-color:#91d9db}.ansible-links>a:focus{outline:3px solid #204748}table.documentation-table{border-bottom:1px solid #000;border-right:1px solid #000}table.documentation-table th{background-color:#6ab0de}table.documentation-table td,table.documentation-table th{padding:4px;border-left:1px solid #000;border-top:1px solid #000}table.documentation-table td.elbow-placeholder{border-top:0;width:30px;min-width:30px}table.documentation-table td{vertical-align:top}table.documentation-table td:first-child{white-space:nowrap}table.documentation-table tr .ansibleOptionLink{display:inline-block;visibility:hidden}table.documentation-table tr .ansibleOptionLink:after{content:"🔗"}table.documentation-table tr:hover .ansibleOptionLink:after{visibility:visible}table.documentation-table tr:nth-child(odd){background-color:#fff}table.documentation-table tr:nth-child(2n){background-color:#e7f2fa}table.ansible-option-table{display:table;border-color:#000!important;height:1px}table.ansible-option-table tr{height:100%}table.ansible-option-table td,table.ansible-option-table th{border-color:#000!important;border-bottom:none!important;vertical-align:top!important}table.ansible-option-table th>p{font-size:medium!important}table.ansible-option-table thead tr{background-color:#6ab0de}table.ansible-option-table tbody .row-odd td{background-color:#fff!important}table.ansible-option-table tbody .row-even td{background-color:#e7f2fa!important}table.ansible-option-table ul>li>p{margin:0!important}table.ansible-option-table ul>li>div[class^=highlight]{margin-bottom:4px!important}table.ansible-option-table p.ansible-option-title{display:inline}table.ansible-option-table .ansible-option-type-line{font-size:small;margin-bottom:0}table.ansible-option-table .ansible-option-elements,table.ansible-option-table .ansible-option-type{color:purple}table.ansible-option-table .ansible-option-required{color:red}table.ansible-option-table .ansible-option-versionadded{font-style:italic;font-size:small;color:#006400}table.ansible-option-table .ansible-option-aliases{color:#006400;white-space:normal}table.ansible-option-table .ansible-option-line{margin-top:8px}table.ansible-option-table .ansible-option-choices{font-weight:700}table.ansible-option-table .ansible-option-choices-default-mark,table.ansible-option-table .ansible-option-default{color:#00f}table.ansible-option-table .ansible-option-default-bold{color:#00f;font-weight:700}table.ansible-option-table .ansible-option-returned-bold{font-weight:700}table.ansible-option-table .ansible-option-sample{color:#00f;word-wrap:break-word;word-break:break-all}table.ansible-option-table .ansible-option-sample-bold{color:#000;font-weight:700}table.ansible-option-table .ansible-option-configuration{font-weight:700}table.ansible-option-table .ansibleOptionLink{display:inline-block;visibility:hidden}table.ansible-option-table .ansibleOptionLink:after{content:"🔗"}table.ansible-option-table p{margin:0 0 8px}table.ansible-option-table tr:hover .ansibleOptionLink:after{visibility:visible}table.ansible-option-table td{padding:0!important;white-space:normal}table.ansible-option-table td>div.ansible-option-cell{padding:8px 16px;border-top:1px solid #000}table.ansible-option-table td:first-child{height:inherit;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}table.ansible-option-table td:first-child>div.ansible-option-cell{height:inherit;-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;white-space:nowrap;max-width:100%}table.ansible-option-table .ansible-option-indent{margin-left:2em;border-right:1px solid #000}table.ansible-option-table .ansible-attribute-support-label{display:none}table.ansible-option-table .ansible-attribute-support-label,table.ansible-option-table .ansible-attribute-support-property{font-weight:700}table.ansible-option-table .ansible-attribute-support-none{font-weight:700;color:red}table.ansible-option-table .ansible-attribute-support-partial{font-weight:700;color:#a5a500}table.ansible-option-table .ansible-attribute-support-full{font-weight:700;color:green}table.ansible-option-table .ansible-attribute-details{font-style:italic}@media (max-width:1200px){table.ansible-option-table{display:block;height:unset;border:none!important}table.ansible-option-table thead{display:none}table.ansible-option-table tbody,table.ansible-option-table td,table.ansible-option-table tr{display:block;border:none!important}table.ansible-option-table tbody .row-even td,table.ansible-option-table tbody .row-odd td{background-color:unset!important}table.ansible-option-table td>div.ansible-option-cell{border-top:none}table.ansible-option-table td:first-child>div.ansible-option-cell{background-color:#e7f2fa!important}table.ansible-option-table td:not(:first-child){display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}table.ansible-option-table td:not(:first-child)>div.ansible-option-cell{margin-left:1em}table.ansible-option-table .ansible-option-indent,table.ansible-option-table .ansible-option-indent-desc{margin-left:1em;border:none;border-right:3px solid #e7f2fa}table.ansible-option-table .ansible-attribute-support-label{display:unset}}.ansible-version-added{font-style:italic} \ No newline at end of file diff --git a/pr/558/_static/basic.css b/pr/558/_static/basic.css new file mode 100644 index 00000000..eeb0519a --- /dev/null +++ b/pr/558/_static/basic.css @@ -0,0 +1,899 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} +dl.field-list > dt:after { + content: ":"; +} + + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/pr/558/_static/css/ansible.css b/pr/558/_static/css/ansible.css new file mode 100644 index 00000000..bf839ba4 --- /dev/null +++ b/pr/558/_static/css/ansible.css @@ -0,0 +1,490 @@ +@import 'theme.css'; +/*! minified with http://css-minify.online-domain-tools.com/ - all comments + * must have ! to preserve during minifying with that tool */ +/*! Fix for read the docs theme: + * https://rackerlabs.github.io/docs-rackspace/tools/rtd-tables.html + */ +/*! override table width restrictions */ +@media screen and (min-width: 767px) { + /*! If we ever publish to read the docs, we need to use !important for + * these two styles as read the docs itself loads their theme in a way that + * we can't otherwise override it. + */ + .wy-table-responsive table td { + white-space: normal; + } + .wy-table-responsive { + overflow: visible; + } +} +/*! + * We use the class documentation-table for attribute tables where the first + * column is the name of an attribute and the second column is the description. + */ +/*! These tables look like this: + * + * Attribute Name Description + * -------------- ----------- + * **NAME** This is a multi-line description + * str/required that can span multiple lines + * added in x.y + * With multiple paragraphs + * -------------- ----------- + * + * **NAME** is given the class .value-name + * str is given the class .value-type + * / is given the class .value-separator + * required is given the class .value-required + * added in x.y is given the class .value-added-in + */ +/*! The extra .rst-content is so this will override rtd theme */ +.rst-content table.documentation-table td { + vertical-align: top; +} +table.documentation-table td:first-child { + white-space: nowrap; + vertical-align: top; +} +table.documentation-table td:first-child p:first-child { + font-weight: 700; + display: inline; +} +/*! This is now redundant with above position-based styling */ +/*! +table.documentation-table .value-name { + font-weight: bold; + display: inline; +} +*/ +table.documentation-table .value-type { + font-size: x-small; + color: purple; + display: inline; +} +table.documentation-table .value-separator { + font-size: x-small; + display: inline; +} +table.documentation-table .value-required { + font-size: x-small; + color: red; + display: inline; +} +.value-added-in { + font-size: x-small; + font-style: italic; + color: green; + display: inline; +} +/*! Ansible-specific CSS pulled out of rtd theme for 2.9 */ +.DocSiteProduct-header { + flex: 1; + -webkit-flex: 1; + padding: 10px 20px 20px; + display: flex; + display: -webkit-flex; + flex-direction: column; + -webkit-flex-direction: column; + align-items: center; + -webkit-align-items: center; + justify-content: flex-start; + -webkit-justify-content: flex-start; + margin-left: 20px; + margin-right: 20px; + text-decoration: none; + font-weight: 400; + font-family: "Open Sans", sans-serif; +} +.DocSiteProduct-header:active, +.DocSiteProduct-header:focus, +.DocSiteProduct-header:visited { + color: #fff; +} +.DocSiteProduct-header--core { + font-size: 25px; + background-color: #5bbdbf; + border: 2px solid #5bbdbf; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + color: #fff; + padding-left: 2px; + margin-left: 2px; +} +.DocSiteProduct-headerAlign { + width: 100%; +} +.DocSiteProduct-logo { + width: 60px; + height: 60px; + margin-bottom: -9px; +} +.DocSiteProduct-logoText { + margin-top: 6px; + font-size: 25px; + text-align: left; +} +.DocSiteProduct-CheckVersionPara { + margin-left: 2px; + padding-bottom: 4px; + margin-right: 2px; + margin-bottom: 10px; +} +/*! Ansible color scheme */ +.wy-nav-top, +.wy-side-nav-search { + background-color: #5bbdbf; +} +.wy-menu-vertical header, +.wy-menu-vertical p.caption { + color: #5bbdbf; +} +.wy-menu-vertical a { + padding: 0; +} +.wy-menu-vertical a.reference.internal { + padding: 0.4045em 1.618em; +} +/*! Override sphinx rtd theme max-with of 800px */ +.wy-nav-content { + max-width: 100%; +} +/*! + * Override sphinx_rtd_theme - keeps left-nav from overwriting + * Documentation title + **/ +.wy-nav-side { + top: 45px; +} +/*! + * Ansible - changed absolute to relative to remove extraneous side scroll bar + **/ +.wy-grid-for-nav { + position: relative; +} +/*! Ansible narrow the search box */ +.wy-side-nav-search input[type="text"] { + width: 90%; + padding-left: 24px; +} +/*! Ansible - remove so highlight indenting is correct */ +.rst-content .highlighted { + padding: 0; +} +.DocSiteBanner { + display: flex; + display: -webkit-flex; + justify-content: center; + -webkit-justify-content: center; + flex-wrap: wrap; + -webkit-flex-wrap: wrap; + margin-bottom: 25px; +} +.DocSiteBanner-imgWrapper { + max-width: 100%; +} +td, +th { + min-width: 100px; +} +table { + overflow-x: auto; + max-width: 100%; +} +.documentation-table td, +.documentation-table th { + padding: 4px; + border-left: 1px solid #000; + border-top: 1px solid #000; +} +.documentation-table { + border-right: 1px solid #000; + border-bottom: 1px solid #000; +} +@media print { + * { + background: 0 0 !important; + color: #000 !important; + text-shadow: none !important; + filter: none !important; + -ms-filter: none !important; + } + #nav, + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + /*! Don't show links for images, or javascript/internal links */ + pre, + blockquote { + border: 0 solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + /*! h5bp.com/t */ + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + h2, + h3, + p { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + #google_image_div, + .DocSiteBanner { + display: none !important; + } +} +#sideBanner, +.DocSite-globalNav { + display: none; +} +.DocSite-sideNav { + display: block; + margin-bottom: 40px; +} +.DocSite-nav { + display: none; +} +.ansibleNav { + background: #000; + padding: 0 20px; + width: auto; + border-bottom: 1px solid #444; + font-size: 14px; + z-index: 1; +} +.ansibleNav ul { + list-style: none; + padding-left: 0; + margin-top: 0; +} +.ansibleNav ul li { + padding: 7px 0; + border-bottom: 1px solid #444; +} +.ansibleNav ul li:last-child { + border: none; +} +.ansibleNav ul li a { + color: #fff; + text-decoration: none; + text-transform: uppercase; + padding: 6px 0; +} +.ansibleNav ul li a:hover { + color: #5bbdbf; + background: 0 0; +} +h4 { + font-size: 105%; +} +h5 { + font-size: 90%; +} +h6 { + font-size: 80%; +} +@media screen and (min-width: 768px) { + .DocSite-globalNav { + display: block; + position: fixed; + } + #sideBanner { + display: block; + } + .DocSite-sideNav { + display: none; + } + .DocSite-nav { + flex: initial; + -webkit-flex: initial; + display: flex; + display: -webkit-flex; + flex-direction: row; + -webkit-flex-direction: row; + justify-content: flex-start; + -webkit-justify-content: flex-start; + padding: 15px; + background-color: #000; + text-decoration: none; + font-family: "Open Sans", sans-serif; + } + .DocSiteNav-logo { + width: 28px; + height: 28px; + margin-right: 8px; + margin-top: -6px; + position: fixed; + z-index: 1; + } + .DocSiteNav-title { + color: #fff; + font-size: 20px; + position: fixed; + margin-left: 40px; + margin-top: -4px; + z-index: 1; + } + .ansibleNav { + height: 45px; + width: 100%; + font-size: 13px; + padding: 0 60px 0 0; + } + .ansibleNav ul { + float: right; + display: flex; + flex-wrap: nowrap; + margin-top: 13px; + } + .ansibleNav ul li { + padding: 0; + border-bottom: none; + } + .ansibleNav ul li a { + color: #fff; + text-decoration: none; + text-transform: uppercase; + padding: 8px 13px; + } + h4 { + font-size: 105%; + } + h5 { + font-size: 90%; + } + h6 { + font-size: 80%; + } +} +@media screen and (min-width: 768px) { + #sideBanner, + .DocSite-globalNav { + display: block; + } + .DocSite-sideNav { + display: none; + } + .DocSite-nav { + flex: initial; + -webkit-flex: initial; + display: flex; + display: -webkit-flex; + flex-direction: row; + -webkit-flex-direction: row; + justify-content: flex-start; + -webkit-justify-content: flex-start; + padding: 15px; + background-color: #000; + text-decoration: none; + font-family: "Open Sans", sans-serif; + } + .DocSiteNav-logo { + width: 28px; + height: 28px; + margin-right: 8px; + margin-top: -6px; + position: fixed; + } + .DocSiteNav-title { + color: #fff; + font-size: 20px; + position: fixed; + margin-left: 40px; + margin-top: -4px; + } + .ansibleNav { + height: 45px; + font-size: 13px; + padding: 0 60px 0 0; + } + .ansibleNav ul { + float: right; + display: flex; + flex-wrap: nowrap; + margin-top: 13px; + } + .ansibleNav ul li { + padding: 0; + border-bottom: none; + } + .ansibleNav ul li a { + color: #fff; + text-decoration: none; + text-transform: uppercase; + padding: 8px 13px; + } + h4 { + font-size: 105%; + } + h5 { + font-size: 90%; + } + h6 { + font-size: 80%; + } +} +/* ansibleOptionLink is adapted from h1 .headerlink in sphinx_rtd_theme */ +/* This definition lives in the antsibull Sphinx extension; we update it here to use the icon from FontAwesome */ +/* https://github.com/ansible-community/antsibull/blob/main/sphinx_antsibull_ext/css/antsibull-minimal.scss */ +tr .ansibleOptionLink::after { + content: "" !important; + font-family: FontAwesome; +} +tr .ansibleOptionLink { + font: normal normal normal 14px/1 FontAwesome; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +@media screen and (min-width: 767px) { + /* Move anchors a bit up so that they aren't hidden by the header bar */ + section [id] { + padding-top: 45px; + margin-top: -45px; + } + /* + * Without this, + * for example most links in the page's TOC aren't usable anymore + * */ + section a[id] { + padding-top: 0; + margin-top: 0; + } +} + +/* Assure reading examples does not require horizontal scrolling */ +.rst-content div[class^="highlight"] pre { + white-space: pre-wrap; +} + +.rst-content dl dt { margin-bottom: 0; } + +/*! Make sure that environment variable links are blue */ +.rst-content code.xref.std-envvar { color: #2980b9; } diff --git a/pr/558/_static/css/badge_only.css b/pr/558/_static/css/badge_only.css new file mode 100644 index 00000000..c718cee4 --- /dev/null +++ b/pr/558/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/pr/558/_static/css/fonts/Roboto-Slab-Bold.woff b/pr/558/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 00000000..6cb60000 Binary files /dev/null and b/pr/558/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/pr/558/_static/css/fonts/Roboto-Slab-Bold.woff2 b/pr/558/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 00000000..7059e231 Binary files /dev/null and b/pr/558/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/pr/558/_static/css/fonts/Roboto-Slab-Regular.woff b/pr/558/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 00000000..f815f63f Binary files /dev/null and b/pr/558/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/pr/558/_static/css/fonts/Roboto-Slab-Regular.woff2 b/pr/558/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 00000000..f2c76e5b Binary files /dev/null and b/pr/558/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/pr/558/_static/css/fonts/fontawesome-webfont.eot b/pr/558/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..e9f60ca9 Binary files /dev/null and b/pr/558/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/pr/558/_static/css/fonts/fontawesome-webfont.svg b/pr/558/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..855c845e --- /dev/null +++ b/pr/558/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pr/558/_static/css/fonts/fontawesome-webfont.ttf b/pr/558/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..35acda2f Binary files /dev/null and b/pr/558/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/pr/558/_static/css/fonts/fontawesome-webfont.woff b/pr/558/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..400014a4 Binary files /dev/null and b/pr/558/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/pr/558/_static/css/fonts/fontawesome-webfont.woff2 b/pr/558/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 00000000..4d13fc60 Binary files /dev/null and b/pr/558/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/pr/558/_static/css/fonts/lato-bold-italic.woff b/pr/558/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 00000000..88ad05b9 Binary files /dev/null and b/pr/558/_static/css/fonts/lato-bold-italic.woff differ diff --git a/pr/558/_static/css/fonts/lato-bold-italic.woff2 b/pr/558/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 00000000..c4e3d804 Binary files /dev/null and b/pr/558/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/pr/558/_static/css/fonts/lato-bold.woff b/pr/558/_static/css/fonts/lato-bold.woff new file mode 100644 index 00000000..c6dff51f Binary files /dev/null and b/pr/558/_static/css/fonts/lato-bold.woff differ diff --git a/pr/558/_static/css/fonts/lato-bold.woff2 b/pr/558/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 00000000..bb195043 Binary files /dev/null and b/pr/558/_static/css/fonts/lato-bold.woff2 differ diff --git a/pr/558/_static/css/fonts/lato-normal-italic.woff b/pr/558/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 00000000..76114bc0 Binary files /dev/null and b/pr/558/_static/css/fonts/lato-normal-italic.woff differ diff --git a/pr/558/_static/css/fonts/lato-normal-italic.woff2 b/pr/558/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 00000000..3404f37e Binary files /dev/null and b/pr/558/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/pr/558/_static/css/fonts/lato-normal.woff b/pr/558/_static/css/fonts/lato-normal.woff new file mode 100644 index 00000000..ae1307ff Binary files /dev/null and b/pr/558/_static/css/fonts/lato-normal.woff differ diff --git a/pr/558/_static/css/fonts/lato-normal.woff2 b/pr/558/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 00000000..3bf98433 Binary files /dev/null and b/pr/558/_static/css/fonts/lato-normal.woff2 differ diff --git a/pr/558/_static/css/rtd-ethical-ads.css b/pr/558/_static/css/rtd-ethical-ads.css new file mode 100644 index 00000000..a146003e --- /dev/null +++ b/pr/558/_static/css/rtd-ethical-ads.css @@ -0,0 +1,4 @@ +.ethical-sidebar, +.ethical-footer { + border-radius: 0 !important; +} diff --git a/pr/558/_static/css/theme.css b/pr/558/_static/css/theme.css new file mode 100644 index 00000000..09a1af86 --- /dev/null +++ b/pr/558/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dt:after,html.writer-html5 .rst-content dl.field-list>dt:after,html.writer-html5 .rst-content dl.footnote>dt:after{content:":"}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets,html.writer-html5 .rst-content dl.footnote>dt>span.brackets{margin-right:.5rem}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{font-style:italic}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p,html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content dl.citation,.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content dl.citation code,.rst-content dl.citation tt,.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/pr/558/_static/doctools.js b/pr/558/_static/doctools.js new file mode 100644 index 00000000..527b876c --- /dev/null +++ b/pr/558/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/pr/558/_static/documentation_options.js b/pr/558/_static/documentation_options.js new file mode 100644 index 00000000..bcae2ea9 --- /dev/null +++ b/pr/558/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: false, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/pr/558/_static/file.png b/pr/558/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/pr/558/_static/file.png differ diff --git a/pr/558/_static/images/Ansible-Mark-RGB_Black.png b/pr/558/_static/images/Ansible-Mark-RGB_Black.png new file mode 100644 index 00000000..0b4e7219 Binary files /dev/null and b/pr/558/_static/images/Ansible-Mark-RGB_Black.png differ diff --git a/pr/558/_static/images/Ansible-Mark-RGB_Black.svg b/pr/558/_static/images/Ansible-Mark-RGB_Black.svg new file mode 100644 index 00000000..c600b6ee --- /dev/null +++ b/pr/558/_static/images/Ansible-Mark-RGB_Black.svg @@ -0,0 +1,14 @@ + + + diff --git a/pr/558/_static/images/Ansible-Mark-RGB_White.png b/pr/558/_static/images/Ansible-Mark-RGB_White.png new file mode 100644 index 00000000..5754701a Binary files /dev/null and b/pr/558/_static/images/Ansible-Mark-RGB_White.png differ diff --git a/pr/558/_static/images/Ansible-Mark-RGB_White.svg b/pr/558/_static/images/Ansible-Mark-RGB_White.svg new file mode 100644 index 00000000..2275aece --- /dev/null +++ b/pr/558/_static/images/Ansible-Mark-RGB_White.svg @@ -0,0 +1 @@ + diff --git a/pr/558/_static/jquery-3.6.0.js b/pr/558/_static/jquery-3.6.0.js new file mode 100644 index 00000000..fc6c299b --- /dev/null +++ b/pr/558/_static/jquery-3.6.0.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_account_facts

+
+

Note

+

This plugin was part of the community.crypto collection (version 2.10.0).

+
+

This module has been removed +in version 2.0.0 of community.crypto. +The ‘community.crypto.acme_account_facts’ module has been renamed to ‘community.crypto.acme_account_info’.

+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/acme_account_info_module.html b/pr/558/acme_account_info_module.html new file mode 100644 index 00000000..d33dea41 --- /dev/null +++ b/pr/558/acme_account_info_module.html @@ -0,0 +1,682 @@ + + + + + + + community.crypto.acme_account_info module – Retrieves information on ACME accounts — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_account_info module – Retrieves information on ACME accounts

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.acme_account_info.

+
+ +
+

Synopsis

+
    +
  • Allows to retrieve information on accounts a CA supporting the ACME protocol, such as Let’s Encrypt.

  • +
  • This module only works with the ACME v2 protocol.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+ +
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

account_key_content

+

string

+

Content of the ACME account RSA or Elliptic Curve key.

+

Mutually exclusive with account_key_src.

+

Required if account_key_src is not used.

+

Warning: the content will be written into a temporary file, which will be deleted by Ansible when the module completes. Since this is an important private key — it can be used to change the account key, or to revoke your certificates without knowing their private keys —, this might not be acceptable.

+

In case cryptography is used, the content is not written into a temporary file. It can still happen that it is written to disk by Ansible in the process of moving the module with its argument to the node where it is executed.

+
+

account_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the account key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+
+

account_key_src

+

aliases: account_key

+

path

+

Path to a file containing the ACME account RSA or Elliptic Curve key.

+

Private keys can be created with the community.crypto.openssl_privatekey or community.crypto.openssl_privatekey_pipe modules. If the requisite (cryptography) is not available, keys can also be created directly with the openssl command line tool: RSA keys can be created with openssl genrsa .... Elliptic curve keys can be created with openssl ecparam -genkey .... Any other tool creating private keys in PEM format can be used as well.

+

Mutually exclusive with account_key_content.

+

Required if account_key_content is not used.

+
+

account_uri

+

string

+

If specified, assumes that the account URI is as given. If the account key does not match this account, or an account with this URI does not exist, the module fails.

+
+

acme_directory

+

string / required

+

The ACME directory to use. This is the entry point URL to access the ACME CA server API.

+

For safety reasons the default is set to the Let’s Encrypt staging server (for the ACME v1 protocol). This will create technically correct, but untrusted certificates.

+

For Let’s Encrypt, all staging endpoints can be found here: https://letsencrypt.org/docs/staging-environment/. For Buypass, all endpoints can be found here: https://community.buypass.com/t/63d4ay/buypass-go-ssl-endpoints

+

For Let’s Encrypt, the production directory URL for ACME v2 is https://acme-v02.api.letsencrypt.org/directory.

+

For Buypass, the production directory URL for ACME v2 and v1 is https://api.buypass.com/acme/directory.

+

For ZeroSSL, the production directory URL for ACME v2 is https://acme.zerossl.com/v2/DV90.

+

For Sectigo, the production directory URL for ACME v2 is https://acme-qa.secure.trust-provider.com/v2/DV.

+

The notes for this module contain a list of ACME services this module has been tested against.

+
+

acme_version

+

integer / required

+

The ACME version of the endpoint.

+

Must be 1 for the classic Let’s Encrypt and Buypass ACME endpoints, or 2 for standardized ACME v2 endpoints.

+

The value 1 is deprecated since community.crypto 2.0.0 and will be removed from community.crypto 3.0.0.

+

Choices:

+
    +
  • 1

  • +
  • 2

  • +
+
+

request_timeout

+

integer

+

added in community.crypto 2.3.0

+

The time Ansible should wait for a response from the ACME API.

+

This timeout is applied to all HTTP(S) requests (HEAD, GET, POST).

+

Default: 10

+
+

retrieve_orders

+

string

+

Whether to retrieve the list of order URLs or order objects, if provided by the ACME server.

+

A value of ignore will not fetch the list of orders.

+

If the value is not ignore and the ACME server supports orders, the order_uris return value is always populated. The orders return value is only returned if this option is set to object_list.

+

Currently, Let’s Encrypt does not return orders, so the orders result will always be empty.

+

Choices:

+
    +
  • "ignore" ← (default)

  • +
  • "url_list"

  • +
  • "object_list"

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to openssl.

+

If set to openssl, will try to use the openssl binary.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "openssl"

  • +
+
+

validate_certs

+

boolean

+

Whether calls to the ACME directory will validate TLS certificates.

+

Warning: Should only ever be set to false for testing purposes, for example when testing against a local Pebble server.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

action_group

+

Action groups: community.crypto.acme, acme

+

Use group/acme or group/community.crypto.acme in module_defaults to set defaults for this module.

+
+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • The community.crypto.acme_account module allows to modify, create and delete ACME accounts.

  • +
  • This module was called acme_account_facts before Ansible 2.8. The usage did not change.

  • +
  • If a new enough version of the cryptography library is available (see Requirements for details), it will be used instead of the openssl binary. This can be explicitly disabled or enabled with the select_crypto_backend option. Note that using the openssl binary will be slower and less secure, as private key contents always have to be stored on disk (see account_key_content).

  • +
  • Although the defaults are chosen so that the module can be used with the Let’s Encrypt CA, the module can in principle be used with any CA providing an ACME endpoint, such as Buypass Go SSL.

  • +
  • So far, the ACME modules have only been tested by the developers against Let’s Encrypt (staging and production), Buypass (staging and production), ZeroSSL (production), and Pebble testing server. We have got community feedback that they also work with Sectigo ACME Service for InCommon. If you experience problems with another ACME server, please create an issue to help us supporting it. Feedback that an ACME server not mentioned does work is also appreciated.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.acme_account

Allows to create, modify or delete an ACME account.

+
+
+
+
+
+

Examples

+
- name: Check whether an account with the given account key exists
+  community.crypto.acme_account_info:
+    account_key_src: /etc/pki/cert/private/account.key
+  register: account_data
+- name: Verify that account exists
+  assert:
+    that:
+      - account_data.exists
+- name: Print account URI
+  ansible.builtin.debug:
+    var: account_data.account_uri
+- name: Print account contacts
+  ansible.builtin.debug:
+    var: account_data.account.contact
+
+- name: Check whether the account exists and is accessible with the given account key
+  acme_account_info:
+    account_key_content: "{{ acme_account_key }}"
+    account_uri: "{{ acme_account_uri }}"
+  register: account_data
+- name: Verify that account exists
+  assert:
+    that:
+      - account_data.exists
+- name: Print account contacts
+  ansible.builtin.debug:
+    var: account_data.account.contact
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

account

+

dictionary

+

The account information, as retrieved from the ACME server.

+

Returned: if account exists

+
+

contact

+

list / elements=string

+

the challenge resource that must be created for validation

+

Returned: always

+

Sample: ["mailto:me@example.com", "tel:00123456789"]

+
+

orders

+

string

+

A URL where a list of orders can be retrieved for this account.

+

Use the retrieve_orders option to query this URL and retrieve the complete list of orders.

+

Returned: always

+

Sample: "https://example.ca/account/1/orders"

+
+

public_account_key

+

string

+

the public account key as a JSON Web Key.

+

Returned: always

+

Sample: "{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4\",\"y\":\"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM\"}"

+
+

status

+

string

+

the account’s status

+

Returned: always

+

Can only return:

+
    +
  • "valid"

  • +
  • "deactivated"

  • +
  • "revoked"

  • +
+

Sample: "valid"

+
+

account_uri

+

string

+

ACME account URI, or None if account does not exist.

+

Returned: always

+
+

exists

+

boolean

+

Whether the account exists.

+

Returned: always

+
+

order_uris

+

list / elements=string

+

added in community.crypto 1.5.0

+

The list of orders.

+

If retrieve_orders is url_list, this will be a list of URLs.

+

If retrieve_orders is object_list, this will be a list of objects.

+

Returned: if account exists, retrieve_orders is not ignore, and server supports order listing

+
+

orders

+

list / elements=dictionary

+

The list of orders.

+

Returned: if account exists, retrieve_orders is object_list, and server supports order listing

+
+

authorizations

+

list / elements=string

+

A list of URLs for authorizations for this order.

+

Returned: success

+
+

certificate

+

string

+

The URL for retrieving the certificate.

+

Returned: when certificate was issued

+
+

error

+

dictionary

+

In case an error occurred during processing, this contains information about the error.

+

The field is structured as a problem document (RFC7807).

+

Returned: when an error occurred

+
+

expires

+

string

+

When the order expires.

+

Timestamp should be formatted as described in RFC3339.

+

Only required to be included in result when status is pending or valid.

+

Returned: when server gives expiry date

+
+

finalize

+

string

+

A URL used for finalizing an ACME order.

+

Returned: success

+
+

identifiers

+

list / elements=dictionary

+

List of identifiers this order is for.

+

Returned: success

+
+

type

+

string

+

Type of identifier. dns or ip.

+

Returned: success

+
+

value

+

string

+

Name of identifier. Hostname or IP address.

+

Returned: success

+
+

wildcard

+

boolean

+

Whether value is actually a wildcard. The wildcard prefix *. is not included in value if this is true.

+

Returned: required to be included if the identifier is wildcarded

+
+

notAfter

+

string

+

The requested value of the notAfter field in the certificate.

+

Date should be formatted as described in RFC3339.

+

Server is not required to return this.

+

Returned: when server returns this

+
+

notBefore

+

string

+

The requested value of the notBefore field in the certificate.

+

Date should be formatted as described in RFC3339.

+

Server is not required to return this.

+

Returned: when server returns this

+
+

status

+

string

+

The order’s status.

+

Returned: success

+

Can only return:

+
    +
  • "pending"

  • +
  • "ready"

  • +
  • "processing"

  • +
  • "valid"

  • +
  • "invalid"

  • +
+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/acme_account_module.html b/pr/558/acme_account_module.html new file mode 100644 index 00000000..54d8f607 --- /dev/null +++ b/pr/558/acme_account_module.html @@ -0,0 +1,601 @@ + + + + + + + community.crypto.acme_account module – Create, modify or delete ACME accounts — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_account module – Create, modify or delete ACME accounts

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.acme_account.

+
+ +
+

Synopsis

+
    +
  • Allows to create, modify or delete accounts with a CA supporting the ACME protocol, such as Let’s Encrypt.

  • +
  • This module only works with the ACME v2 protocol.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+ +
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

account_key_content

+

string

+

Content of the ACME account RSA or Elliptic Curve key.

+

Mutually exclusive with account_key_src.

+

Required if account_key_src is not used.

+

Warning: the content will be written into a temporary file, which will be deleted by Ansible when the module completes. Since this is an important private key — it can be used to change the account key, or to revoke your certificates without knowing their private keys —, this might not be acceptable.

+

In case cryptography is used, the content is not written into a temporary file. It can still happen that it is written to disk by Ansible in the process of moving the module with its argument to the node where it is executed.

+
+

account_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the account key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+
+

account_key_src

+

aliases: account_key

+

path

+

Path to a file containing the ACME account RSA or Elliptic Curve key.

+

Private keys can be created with the community.crypto.openssl_privatekey or community.crypto.openssl_privatekey_pipe modules. If the requisite (cryptography) is not available, keys can also be created directly with the openssl command line tool: RSA keys can be created with openssl genrsa .... Elliptic curve keys can be created with openssl ecparam -genkey .... Any other tool creating private keys in PEM format can be used as well.

+

Mutually exclusive with account_key_content.

+

Required if account_key_content is not used.

+
+

account_uri

+

string

+

If specified, assumes that the account URI is as given. If the account key does not match this account, or an account with this URI does not exist, the module fails.

+
+

acme_directory

+

string / required

+

The ACME directory to use. This is the entry point URL to access the ACME CA server API.

+

For safety reasons the default is set to the Let’s Encrypt staging server (for the ACME v1 protocol). This will create technically correct, but untrusted certificates.

+

For Let’s Encrypt, all staging endpoints can be found here: https://letsencrypt.org/docs/staging-environment/. For Buypass, all endpoints can be found here: https://community.buypass.com/t/63d4ay/buypass-go-ssl-endpoints

+

For Let’s Encrypt, the production directory URL for ACME v2 is https://acme-v02.api.letsencrypt.org/directory.

+

For Buypass, the production directory URL for ACME v2 and v1 is https://api.buypass.com/acme/directory.

+

For ZeroSSL, the production directory URL for ACME v2 is https://acme.zerossl.com/v2/DV90.

+

For Sectigo, the production directory URL for ACME v2 is https://acme-qa.secure.trust-provider.com/v2/DV.

+

The notes for this module contain a list of ACME services this module has been tested against.

+
+

acme_version

+

integer / required

+

The ACME version of the endpoint.

+

Must be 1 for the classic Let’s Encrypt and Buypass ACME endpoints, or 2 for standardized ACME v2 endpoints.

+

The value 1 is deprecated since community.crypto 2.0.0 and will be removed from community.crypto 3.0.0.

+

Choices:

+
    +
  • 1

  • +
  • 2

  • +
+
+

allow_creation

+

boolean

+

Whether account creation is allowed (when state is present).

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

contact

+

list / elements=string

+

A list of contact URLs.

+

Email addresses must be prefixed with mailto:.

+

See https://tools.ietf.org/html/rfc8555#section-7.3 for what is allowed.

+

Must be specified when state is present. Will be ignored if state is absent or changed_key.

+

Default: []

+
+

external_account_binding

+

dictionary

+

added in community.crypto 1.1.0

+

Allows to provide external account binding data during account creation.

+

This is used by CAs like Sectigo to bind a new ACME account to an existing CA-specific account, to be able to properly identify a customer.

+

Only used when creating a new account. Can not be specified for ACME v1.

+
+

alg

+

string / required

+

The MAC algorithm provided by the CA.

+

If not specified by the CA, this is probably HS256.

+

Choices:

+
    +
  • "HS256"

  • +
  • "HS384"

  • +
  • "HS512"

  • +
+
+

key

+

string / required

+

Base64 URL encoded value of the MAC key provided by the CA.

+

Padding (= symbols at the end) can be omitted.

+
+

kid

+

string / required

+

The key identifier provided by the CA.

+
+

new_account_key_content

+

string

+

Content of the ACME account RSA or Elliptic Curve key to change to.

+

Same restrictions apply as to account_key_content.

+

Mutually exclusive with new_account_key_src.

+

Required if new_account_key_src is not used and state is changed_key.

+
+

new_account_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the new account key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+

new_account_key_src

+

path

+

Path to a file containing the ACME account RSA or Elliptic Curve key to change to.

+

Same restrictions apply as to account_key_src.

+

Mutually exclusive with new_account_key_content.

+

Required if new_account_key_content is not used and state is changed_key.

+
+

request_timeout

+

integer

+

added in community.crypto 2.3.0

+

The time Ansible should wait for a response from the ACME API.

+

This timeout is applied to all HTTP(S) requests (HEAD, GET, POST).

+

Default: 10

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to openssl.

+

If set to openssl, will try to use the openssl binary.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "openssl"

  • +
+
+

state

+

string / required

+

The state of the account, to be identified by its account key.

+

If the state is absent, the account will either not exist or be deactivated.

+

If the state is changed_key, the account must exist. The account key will be changed; no other information will be touched.

+

Choices:

+
    +
  • "present"

  • +
  • "absent"

  • +
  • "changed_key"

  • +
+
+

terms_agreed

+

boolean

+

Boolean indicating whether you agree to the terms of service document.

+

ACME servers can require this to be true.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

validate_certs

+

boolean

+

Whether calls to the ACME directory will validate TLS certificates.

+

Warning: Should only ever be set to false for testing purposes, for example when testing against a local Pebble server.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

action_group

+

Action groups: community.crypto.acme, acme

+

Use group/acme or group/community.crypto.acme in module_defaults to set defaults for this module.

+
+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • The community.crypto.acme_certificate module also allows to do basic account management. When using both modules, it is recommended to disable account management for community.crypto.acme_certificate. For that, use the modify_account option of community.crypto.acme_certificate.

  • +
  • If a new enough version of the cryptography library is available (see Requirements for details), it will be used instead of the openssl binary. This can be explicitly disabled or enabled with the select_crypto_backend option. Note that using the openssl binary will be slower and less secure, as private key contents always have to be stored on disk (see account_key_content).

  • +
  • Although the defaults are chosen so that the module can be used with the Let’s Encrypt CA, the module can in principle be used with any CA providing an ACME endpoint, such as Buypass Go SSL.

  • +
  • So far, the ACME modules have only been tested by the developers against Let’s Encrypt (staging and production), Buypass (staging and production), ZeroSSL (production), and Pebble testing server. We have got community feedback that they also work with Sectigo ACME Service for InCommon. If you experience problems with another ACME server, please create an issue to help us supporting it. Feedback that an ACME server not mentioned does work is also appreciated.

  • +
+
+
+
+

See Also

+
+

See also

+
+
Automatic Certificate Management Environment (ACME)

The specification of the ACME protocol (RFC 8555).

+
+
community.crypto.acme_account_info

Retrieves facts about an ACME account.

+
+
community.crypto.openssl_privatekey

Can be used to create a private account key.

+
+
community.crypto.openssl_privatekey_pipe

Can be used to create a private account key without writing it to disk.

+
+
community.crypto.acme_inspect

Allows to debug problems.

+
+
+
+
+
+

Examples

+
- name: Make sure account exists and has given contacts. We agree to TOS.
+  community.crypto.acme_account:
+    account_key_src: /etc/pki/cert/private/account.key
+    state: present
+    terms_agreed: true
+    contact:
+    - mailto:me@example.com
+    - mailto:myself@example.org
+
+- name: Make sure account has given email address. Do not create account if it does not exist
+  community.crypto.acme_account:
+    account_key_src: /etc/pki/cert/private/account.key
+    state: present
+    allow_creation: false
+    contact:
+    - mailto:me@example.com
+
+- name: Change account's key to the one stored in the variable new_account_key
+  community.crypto.acme_account:
+    account_key_src: /etc/pki/cert/private/account.key
+    new_account_key_content: '{{ new_account_key }}'
+    state: changed_key
+
+- name: Delete account (we have to use the new key)
+  community.crypto.acme_account:
+    account_key_content: '{{ new_account_key }}'
+    state: absent
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + +

Key

Description

+

account_uri

+

string

+

ACME account URI, or None if account does not exist.

+

Returned: always

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/acme_certificate_module.html b/pr/558/acme_certificate_module.html new file mode 100644 index 00000000..069ab911 --- /dev/null +++ b/pr/558/acme_certificate_module.html @@ -0,0 +1,973 @@ + + + + + + + community.crypto.acme_certificate module – Create SSL/TLS certificates with the ACME protocol — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_certificate module – Create SSL/TLS certificates with the ACME protocol

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.acme_certificate.

+
+ +
+

Synopsis

+
    +
  • Create and renew SSL/TLS certificates with a CA supporting the ACME protocol, such as Let’s Encrypt or Buypass. The current implementation supports the http-01, dns-01 and tls-alpn-01 challenges.

  • +
  • To use this module, it has to be executed twice. Either as two different tasks in the same run or during two runs. Note that the output of the first run needs to be recorded and passed to the second run as the module argument data.

  • +
  • Between these two tasks you have to fulfill the required steps for the chosen challenge by whatever means necessary. For http-01 that means creating the necessary challenge file on the destination webserver. For dns-01 the necessary dns record has to be created. For tls-alpn-01 the necessary certificate has to be created and served. It is not the responsibility of this module to perform these steps.

  • +
  • For details on how to fulfill these challenges, you might have to read through the main ACME specification and the TLS-ALPN-01 specification. Also, consider the examples provided for this module.

  • +
  • The module includes experimental support for IP identifiers according to the RFC 8738.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+ +
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

account_email

+

string

+

The email address associated with this account.

+

It will be used for certificate expiration warnings.

+

Note that when modify_account is not set to false and you also used the community.crypto.acme_account module to specify more than one contact for your account, this module will update your account and restrict it to the (at most one) contact email address specified here.

+
+

account_key_content

+

string

+

Content of the ACME account RSA or Elliptic Curve key.

+

Mutually exclusive with account_key_src.

+

Required if account_key_src is not used.

+

Warning: the content will be written into a temporary file, which will be deleted by Ansible when the module completes. Since this is an important private key — it can be used to change the account key, or to revoke your certificates without knowing their private keys —, this might not be acceptable.

+

In case cryptography is used, the content is not written into a temporary file. It can still happen that it is written to disk by Ansible in the process of moving the module with its argument to the node where it is executed.

+
+

account_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the account key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+
+

account_key_src

+

aliases: account_key

+

path

+

Path to a file containing the ACME account RSA or Elliptic Curve key.

+

Private keys can be created with the community.crypto.openssl_privatekey or community.crypto.openssl_privatekey_pipe modules. If the requisite (cryptography) is not available, keys can also be created directly with the openssl command line tool: RSA keys can be created with openssl genrsa .... Elliptic curve keys can be created with openssl ecparam -genkey .... Any other tool creating private keys in PEM format can be used as well.

+

Mutually exclusive with account_key_content.

+

Required if account_key_content is not used.

+
+

account_uri

+

string

+

If specified, assumes that the account URI is as given. If the account key does not match this account, or an account with this URI does not exist, the module fails.

+
+

acme_directory

+

string / required

+

The ACME directory to use. This is the entry point URL to access the ACME CA server API.

+

For safety reasons the default is set to the Let’s Encrypt staging server (for the ACME v1 protocol). This will create technically correct, but untrusted certificates.

+

For Let’s Encrypt, all staging endpoints can be found here: https://letsencrypt.org/docs/staging-environment/. For Buypass, all endpoints can be found here: https://community.buypass.com/t/63d4ay/buypass-go-ssl-endpoints

+

For Let’s Encrypt, the production directory URL for ACME v2 is https://acme-v02.api.letsencrypt.org/directory.

+

For Buypass, the production directory URL for ACME v2 and v1 is https://api.buypass.com/acme/directory.

+

For ZeroSSL, the production directory URL for ACME v2 is https://acme.zerossl.com/v2/DV90.

+

For Sectigo, the production directory URL for ACME v2 is https://acme-qa.secure.trust-provider.com/v2/DV.

+

The notes for this module contain a list of ACME services this module has been tested against.

+
+

acme_version

+

integer / required

+

The ACME version of the endpoint.

+

Must be 1 for the classic Let’s Encrypt and Buypass ACME endpoints, or 2 for standardized ACME v2 endpoints.

+

The value 1 is deprecated since community.crypto 2.0.0 and will be removed from community.crypto 3.0.0.

+

Choices:

+
    +
  • 1

  • +
  • 2

  • +
+
+

agreement

+

string

+

URI to a terms of service document you agree to when using the ACME v1 service at acme_directory.

+

Default is latest gathered from acme_directory URL.

+

This option will only be used when acme_version is 1.

+
+
+

chain_dest

+

aliases: chain

+

path

+

If specified, the intermediate certificate will be written to this file.

+
+

challenge

+

string

+

The challenge to be performed.

+

Choices:

+
    +
  • "http-01" ← (default)

  • +
  • "dns-01"

  • +
  • "tls-alpn-01"

  • +
+
+
+

csr

+

aliases: src

+

path

+

File containing the CSR for the new certificate.

+

Can be created with community.crypto.openssl_csr or openssl req ....

+

The CSR may contain multiple Subject Alternate Names, but each one will lead to an individual challenge that must be fulfilled for the CSR to be signed.

+

Note: the private key used to create the CSR must not be the account key. This is a bad idea from a security point of view, and the CA should not accept the CSR. The ACME server should return an error in this case.

+

Precisely one of csr or csr_content must be specified.

+
+

csr_content

+

string

+

added in community.crypto 1.2.0

+

Content of the CSR for the new certificate.

+

Can be created with community.crypto.openssl_csr_pipe or openssl req ....

+

The CSR may contain multiple Subject Alternate Names, but each one will lead to an individual challenge that must be fulfilled for the CSR to be signed.

+

Note: the private key used to create the CSR must not be the account key. This is a bad idea from a security point of view, and the CA should not accept the CSR. The ACME server should return an error in this case.

+

Precisely one of csr or csr_content must be specified.

+
+

data

+

dictionary

+

The data to validate ongoing challenges. This must be specified for the second run of the module only.

+

The value that must be used here will be provided by a previous use of this module. See the examples for more details.

+

Note that for ACME v2, only the order_uri entry of data will be used. For ACME v1, data must be non-empty to indicate the second stage is active; all needed data will be taken from the CSR.

+

Note: the data option was marked as no_log up to Ansible 2.5. From Ansible 2.6 on, it is no longer marked this way as it causes error messages to be come unusable, and data does not contain any information which can be used without having access to the account key or which are not public anyway.

+
+

deactivate_authzs

+

boolean

+

Deactivate authentication objects (authz) after issuing a certificate, or when issuing the certificate failed.

+

Authentication objects are bound to an account key and remain valid for a certain amount of time, and can be used to issue certificates without having to re-authenticate the domain. This can be a security concern.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

dest

+

aliases: cert

+

path

+

The destination file for the certificate.

+

Required if fullchain_dest is not specified.

+
+

force

+

boolean

+

Enforces the execution of the challenge and validation, even if an existing certificate is still valid for more than remaining_days.

+

This is especially helpful when having an updated CSR, for example with additional domains for which a new certificate is desired.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

fullchain_dest

+

aliases: fullchain

+

path

+

The destination file for the full chain (that is, a certificate followed by chain of intermediate certificates).

+

Required if dest is not specified.

+
+

modify_account

+

boolean

+

Boolean indicating whether the module should create the account if necessary, and update its contact data.

+

Set to false if you want to use the community.crypto.acme_account module to manage your account instead, and to avoid accidental creation of a new account using an old key if you changed the account key with community.crypto.acme_account.

+

If set to false, terms_agreed and account_email are ignored.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

remaining_days

+

integer

+

The number of days the certificate must have left being valid. If cert_days < remaining_days, then it will be renewed. If the certificate is not renewed, module return values will not include challenge_data.

+

To make sure that the certificate is renewed in any case, you can use the force option.

+

Default: 10

+
+

request_timeout

+

integer

+

added in community.crypto 2.3.0

+

The time Ansible should wait for a response from the ACME API.

+

This timeout is applied to all HTTP(S) requests (HEAD, GET, POST).

+

Default: 10

+
+

retrieve_all_alternates

+

boolean

+

When set to true, will retrieve all alternate trust chains offered by the ACME CA. These will not be written to disk, but will be returned together with the main chain as all_chains. See the documentation for the all_chains return value for details.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_chain

+

list / elements=dictionary

+

added in community.crypto 1.0.0

+

Allows to specify criteria by which an (alternate) trust chain can be selected.

+

The list of criteria will be processed one by one until a chain is found matching a criterium. If such a chain is found, it will be used by the module instead of the default chain.

+

If a criterium matches multiple chains, the first one matching will be returned. The order is determined by the ordering of the Link headers returned by the ACME server and might not be deterministic.

+

Every criterium can consist of multiple different conditions, like issuer and subject. For the criterium to match a chain, all conditions must apply to the same certificate in the chain.

+

This option can only be used with the cryptography backend.

+
+

authority_key_identifier

+

string

+

Checks for the AuthorityKeyIdentifier extension. This is an identifier based on the private key of the issuer of the intermediate certificate.

+

The identifier must be of the form C4:A7:B1:A4:7B:2C:71:FA:DB:E1:4B:90:75:FF:C4:15:60:85:89:10.

+
+

issuer

+

dictionary

+

Allows to specify parts of the issuer of a certificate in the chain must have to be selected.

+

If issuer is empty, any certificate will match.

+

An example value would be {"commonName": "My Preferred CA Root"}.

+
+

subject

+

dictionary

+

Allows to specify parts of the subject of a certificate in the chain must have to be selected.

+

If subject is empty, any certificate will match.

+

An example value would be {"CN": "My Preferred CA Intermediate"}

+
+

subject_key_identifier

+

string

+

Checks for the SubjectKeyIdentifier extension. This is an identifier based on the private key of the intermediate certificate.

+

The identifier must be of the form A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1.

+
+

test_certificates

+

string

+

Determines which certificates in the chain will be tested.

+

all tests all certificates in the chain (excluding the leaf, which is identical in all chains).

+

first only tests the first certificate in the chain, that is the one which signed the leaf.

+

last only tests the last certificate in the chain, that is the one furthest away from the leaf. Its issuer is the root certificate of this chain.

+

Choices:

+
    +
  • "first"

  • +
  • "last"

  • +
  • "all" ← (default)

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to openssl.

+

If set to openssl, will try to use the openssl binary.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "openssl"

  • +
+
+

terms_agreed

+

boolean

+

Boolean indicating whether you agree to the terms of service document.

+

ACME servers can require this to be true.

+

This option will only be used when acme_version is not 1.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

validate_certs

+

boolean

+

Whether calls to the ACME directory will validate TLS certificates.

+

Warning: Should only ever be set to false for testing purposes, for example when testing against a local Pebble server.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

action_group

+

Action groups: community.crypto.acme, acme

+

Use group/acme or group/community.crypto.acme in module_defaults to set defaults for this module.

+
+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Notes

+
+

Note

+
    +
  • At least one of dest and fullchain_dest must be specified.

  • +
  • This module includes basic account management functionality. If you want to have more control over your ACME account, use the community.crypto.acme_account module and disable account management for this module using the modify_account option.

  • +
  • This module was called letsencrypt before Ansible 2.6. The usage did not change.

  • +
  • If a new enough version of the cryptography library is available (see Requirements for details), it will be used instead of the openssl binary. This can be explicitly disabled or enabled with the select_crypto_backend option. Note that using the openssl binary will be slower and less secure, as private key contents always have to be stored on disk (see account_key_content).

  • +
  • Although the defaults are chosen so that the module can be used with the Let’s Encrypt CA, the module can in principle be used with any CA providing an ACME endpoint, such as Buypass Go SSL.

  • +
  • So far, the ACME modules have only been tested by the developers against Let’s Encrypt (staging and production), Buypass (staging and production), ZeroSSL (production), and Pebble testing server. We have got community feedback that they also work with Sectigo ACME Service for InCommon. If you experience problems with another ACME server, please create an issue to help us supporting it. Feedback that an ACME server not mentioned does work is also appreciated.

  • +
+
+
+
+

See Also

+
+

See also

+
+
The Let’s Encrypt documentation

Documentation for the Let’s Encrypt Certification Authority. Provides useful information for example on rate limits.

+
+
Buypass Go SSL

Documentation for the Buypass Certification Authority. Provides useful information for example on rate limits.

+
+
Automatic Certificate Management Environment (ACME)

The specification of the ACME protocol (RFC 8555).

+
+
ACME TLS ALPN Challenge Extension

The specification of the tls-alpn-01 challenge (RFC 8737).

+
+
community.crypto.acme_challenge_cert_helper

Helps preparing tls-alpn-01 challenges.

+
+
community.crypto.openssl_privatekey

Can be used to create private keys (both for certificates and accounts).

+
+
community.crypto.openssl_privatekey_pipe

Can be used to create private keys without writing it to disk (both for certificates and accounts).

+
+
community.crypto.openssl_csr

Can be used to create a Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Can be used to create a Certificate Signing Request (CSR) without writing it to disk.

+
+
community.crypto.certificate_complete_chain

Allows to find the root certificate for the returned fullchain.

+
+
community.crypto.acme_certificate_revoke

Allows to revoke certificates.

+
+
community.crypto.acme_account

Allows to create, modify or delete an ACME account.

+
+
community.crypto.acme_inspect

Allows to debug problems.

+
+
+
+
+
+

Examples

+
### Example with HTTP challenge ###
+
+- name: Create a challenge for sample.com using a account key from a variable.
+  community.crypto.acme_certificate:
+    account_key_content: "{{ account_private_key }}"
+    csr: /etc/pki/cert/csr/sample.com.csr
+    dest: /etc/httpd/ssl/sample.com.crt
+  register: sample_com_challenge
+
+# Alternative first step:
+- name: Create a challenge for sample.com using a account key from hashi vault.
+  community.crypto.acme_certificate:
+    account_key_content: "{{ lookup('hashi_vault', 'secret=secret/account_private_key:value') }}"
+    csr: /etc/pki/cert/csr/sample.com.csr
+    fullchain_dest: /etc/httpd/ssl/sample.com-fullchain.crt
+  register: sample_com_challenge
+
+# Alternative first step:
+- name: Create a challenge for sample.com using a account key file.
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    csr_content: "{{ lookup('file', '/etc/pki/cert/csr/sample.com.csr') }}"
+    dest: /etc/httpd/ssl/sample.com.crt
+    fullchain_dest: /etc/httpd/ssl/sample.com-fullchain.crt
+  register: sample_com_challenge
+
+# perform the necessary steps to fulfill the challenge
+# for example:
+#
+# - copy:
+#     dest: /var/www/html/{{ sample_com_challenge['challenge_data']['sample.com']['http-01']['resource'] }}
+#     content: "{{ sample_com_challenge['challenge_data']['sample.com']['http-01']['resource_value'] }}"
+#   when: sample_com_challenge is changed and 'sample.com' in sample_com_challenge['challenge_data']
+#
+# Alternative way:
+#
+# - copy:
+#     dest: /var/www/{{ item.key }}/{{ item.value['http-01']['resource'] }}
+#     content: "{{ item.value['http-01']['resource_value'] }}"
+#   loop: "{{ sample_com_challenge.challenge_data | dict2items }}"
+#   when: sample_com_challenge is changed
+
+- name: Let the challenge be validated and retrieve the cert and intermediate certificate
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    csr: /etc/pki/cert/csr/sample.com.csr
+    dest: /etc/httpd/ssl/sample.com.crt
+    fullchain_dest: /etc/httpd/ssl/sample.com-fullchain.crt
+    chain_dest: /etc/httpd/ssl/sample.com-intermediate.crt
+    data: "{{ sample_com_challenge }}"
+
+### Example with DNS challenge against production ACME server ###
+
+- name: Create a challenge for sample.com using a account key file.
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    account_email: myself@sample.com
+    src: /etc/pki/cert/csr/sample.com.csr
+    cert: /etc/httpd/ssl/sample.com.crt
+    challenge: dns-01
+    acme_directory: https://acme-v01.api.letsencrypt.org/directory
+    # Renew if the certificate is at least 30 days old
+    remaining_days: 60
+  register: sample_com_challenge
+
+# perform the necessary steps to fulfill the challenge
+# for example:
+#
+# - community.aws.route53:
+#     zone: sample.com
+#     record: "{{ sample_com_challenge.challenge_data['sample.com']['dns-01'].record }}"
+#     type: TXT
+#     ttl: 60
+#     state: present
+#     wait: true
+#     # Note: route53 requires TXT entries to be enclosed in quotes
+#     value: "{{ sample_com_challenge.challenge_data['sample.com']['dns-01'].resource_value | regex_replace('^(.*)$', '\"\\1\"') }}"
+#   when: sample_com_challenge is changed and 'sample.com' in sample_com_challenge.challenge_data
+#
+# Alternative way:
+#
+# - community.aws.route53:
+#     zone: sample.com
+#     record: "{{ item.key }}"
+#     type: TXT
+#     ttl: 60
+#     state: present
+#     wait: true
+#     # Note: item.value is a list of TXT entries, and route53
+#     # requires every entry to be enclosed in quotes
+#     value: "{{ item.value | map('regex_replace', '^(.*)$', '\"\\1\"' ) | list }}"
+#   loop: "{{ sample_com_challenge.challenge_data_dns | dict2items }}"
+#   when: sample_com_challenge is changed
+
+- name: Let the challenge be validated and retrieve the cert and intermediate certificate
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    account_email: myself@sample.com
+    src: /etc/pki/cert/csr/sample.com.csr
+    cert: /etc/httpd/ssl/sample.com.crt
+    fullchain: /etc/httpd/ssl/sample.com-fullchain.crt
+    chain: /etc/httpd/ssl/sample.com-intermediate.crt
+    challenge: dns-01
+    acme_directory: https://acme-v01.api.letsencrypt.org/directory
+    remaining_days: 60
+    data: "{{ sample_com_challenge }}"
+  when: sample_com_challenge is changed
+
+# Alternative second step:
+- name: Let the challenge be validated and retrieve the cert and intermediate certificate
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    account_email: myself@sample.com
+    src: /etc/pki/cert/csr/sample.com.csr
+    cert: /etc/httpd/ssl/sample.com.crt
+    fullchain: /etc/httpd/ssl/sample.com-fullchain.crt
+    chain: /etc/httpd/ssl/sample.com-intermediate.crt
+    challenge: tls-alpn-01
+    remaining_days: 60
+    data: "{{ sample_com_challenge }}"
+    # We use Let's Encrypt's ACME v2 endpoint
+    acme_directory: https://acme-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    # The following makes sure that if a chain with /CN=DST Root CA X3 in its issuer is provided
+    # as an alternative, it will be selected. These are the roots cross-signed by IdenTrust.
+    # As long as Let's Encrypt provides alternate chains with the cross-signed root(s) when
+    # switching to their own ISRG Root X1 root, this will use the chain ending with a cross-signed
+    # root. This chain is more compatible with older TLS clients.
+    select_chain:
+      - test_certificates: last
+        issuer:
+          CN: DST Root CA X3
+          O: Digital Signature Trust Co.
+  when: sample_com_challenge is changed
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

account_uri

+

string

+

ACME account URI.

+

Returned: changed

+
+

all_chains

+

list / elements=dictionary

+

When retrieve_all_alternates is set to true, the module will query the ACME server for alternate chains. This return value will contain a list of all chains returned, the first entry being the main chain returned by the server.

+

See Section 7.4.2 of RFC8555 for details.

+

Returned: when certificate was retrieved and retrieve_all_alternates is set to true

+
+

cert

+

string

+

The leaf certificate itself, in PEM format.

+

Returned: always

+
+

chain

+

string

+

The certificate chain, excluding the root, as concatenated PEM certificates.

+

Returned: always

+
+

full_chain

+

string

+

The certificate chain, excluding the root, but including the leaf certificate, as concatenated PEM certificates.

+

Returned: always

+
+

authorizations

+

dictionary

+

ACME authorization data.

+

Maps an identifier to ACME authorization objects. See https://tools.ietf.org/html/rfc8555#section-7.1.4.

+

Returned: changed

+

Sample: {"example.com": {"challenges": [{"status": "valid", "token": "A5b1C3d2E9f8G7h6", "type": "http-01", "url": "https://example.org/acme/challenge/12345", "validated": "2022-08-01T01:01:02.34Z"}], "expires": "2022-08-04T01:02:03.45Z", "identifier": {"type": "dns", "value": "example.com"}, "status": "valid", "wildcard": false}}

+
+

cert_days

+

integer

+

The number of days the certificate remains valid.

+

Returned: success

+
+

challenge_data

+

list / elements=dictionary

+

Per identifier / challenge type challenge data.

+

Since Ansible 2.8.5, only challenges which are not yet valid are returned.

+

Returned: changed

+
+

record

+

string

+

The full DNS record’s name for the challenge.

+

Returned: changed and challenge is dns-01

+

Sample: "_acme-challenge.example.com"

+
+

resource

+

string

+

The challenge resource that must be created for validation.

+

Returned: changed

+

Sample: ".well-known/acme-challenge/evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"

+
+

resource_original

+

string

+

The original challenge resource including type identifier for tls-alpn-01 challenges.

+

Returned: changed and challenge is tls-alpn-01

+

Sample: "DNS:example.com"

+
+

resource_value

+

string

+

The value the resource has to produce for the validation.

+

For http-01 and dns-01 challenges, the value can be used as-is.

+

For tls-alpn-01 challenges, note that this return value contains a Base64 encoded version of the correct binary blob which has to be put into the acmeValidation x509 extension; see https://www.rfc-editor.org/rfc/rfc8737.html#section-3 for details. To do this, you might need the b64decode Jinja filter to extract the binary blob from this return value.

+

Returned: changed

+

Sample: "IlirfxKKXA...17Dt3juxGJ-PCt92wr-oA"

+
+

challenge_data_dns

+

dictionary

+

List of TXT values per DNS record, in case challenge is dns-01.

+

Since Ansible 2.8.5, only challenges which are not yet valid are returned.

+

Returned: changed

+
+

finalization_uri

+

string

+

ACME finalization URI.

+

Returned: changed

+
+

order_uri

+

string

+

ACME order URI.

+

Returned: changed

+
+
+

Authors

+
    +
  • Michael Gruener (@mgruener)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/acme_certificate_revoke_module.html b/pr/558/acme_certificate_revoke_module.html new file mode 100644 index 00000000..e2b4101c --- /dev/null +++ b/pr/558/acme_certificate_revoke_module.html @@ -0,0 +1,478 @@ + + + + + + + community.crypto.acme_certificate_revoke module – Revoke certificates with the ACME protocol — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_certificate_revoke module – Revoke certificates with the ACME protocol

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.acme_certificate_revoke.

+
+ +
+

Synopsis

+ +
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+ +
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

account_key_content

+

string

+

Content of the ACME account RSA or Elliptic Curve key.

+

Note that exactly one of account_key_src, account_key_content, private_key_src or private_key_content must be specified.

+

Warning: the content will be written into a temporary file, which will be deleted by Ansible when the module completes. Since this is an important private key — it can be used to change the account key, or to revoke your certificates without knowing their private keys —, this might not be acceptable.

+

In case cryptography is used, the content is not written into a temporary file. It can still happen that it is written to disk by Ansible in the process of moving the module with its argument to the node where it is executed.

+
+

account_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the account key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+
+

account_key_src

+

aliases: account_key

+

path

+

Path to a file containing the ACME account RSA or Elliptic Curve key.

+

RSA keys can be created with openssl rsa .... Elliptic curve keys can be created with openssl ecparam -genkey .... Any other tool creating private keys in PEM format can be used as well.

+

Mutually exclusive with account_key_content.

+

Required if account_key_content is not used.

+
+

account_uri

+

string

+

If specified, assumes that the account URI is as given. If the account key does not match this account, or an account with this URI does not exist, the module fails.

+
+

acme_directory

+

string / required

+

The ACME directory to use. This is the entry point URL to access the ACME CA server API.

+

For safety reasons the default is set to the Let’s Encrypt staging server (for the ACME v1 protocol). This will create technically correct, but untrusted certificates.

+

For Let’s Encrypt, all staging endpoints can be found here: https://letsencrypt.org/docs/staging-environment/. For Buypass, all endpoints can be found here: https://community.buypass.com/t/63d4ay/buypass-go-ssl-endpoints

+

For Let’s Encrypt, the production directory URL for ACME v2 is https://acme-v02.api.letsencrypt.org/directory.

+

For Buypass, the production directory URL for ACME v2 and v1 is https://api.buypass.com/acme/directory.

+

For ZeroSSL, the production directory URL for ACME v2 is https://acme.zerossl.com/v2/DV90.

+

For Sectigo, the production directory URL for ACME v2 is https://acme-qa.secure.trust-provider.com/v2/DV.

+

The notes for this module contain a list of ACME services this module has been tested against.

+
+

acme_version

+

integer / required

+

The ACME version of the endpoint.

+

Must be 1 for the classic Let’s Encrypt and Buypass ACME endpoints, or 2 for standardized ACME v2 endpoints.

+

The value 1 is deprecated since community.crypto 2.0.0 and will be removed from community.crypto 3.0.0.

+

Choices:

+
    +
  • 1

  • +
  • 2

  • +
+
+

certificate

+

path / required

+

Path to the certificate to revoke.

+
+

private_key_content

+

string

+

Content of the certificate’s private key.

+

Note that exactly one of account_key_src, account_key_content, private_key_src or private_key_content must be specified.

+

Warning: the content will be written into a temporary file, which will be deleted by Ansible when the module completes. Since this is an important private key — it can be used to change the account key, or to revoke your certificates without knowing their private keys —, this might not be acceptable.

+

In case cryptography is used, the content is not written into a temporary file. It can still happen that it is written to disk by Ansible in the process of moving the module with its argument to the node where it is executed.

+
+

private_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the certificate’s private key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+

private_key_src

+

path

+

Path to the certificate’s private key.

+

Note that exactly one of account_key_src, account_key_content, private_key_src or private_key_content must be specified.

+
+

request_timeout

+

integer

+

added in community.crypto 2.3.0

+

The time Ansible should wait for a response from the ACME API.

+

This timeout is applied to all HTTP(S) requests (HEAD, GET, POST).

+

Default: 10

+
+

revoke_reason

+

integer

+

One of the revocation reasonCodes defined in Section 5.3.1 of RFC5280.

+

Possible values are 0 (unspecified), 1 (keyCompromise), 2 (cACompromise), 3 (affiliationChanged), 4 (superseded), 5 (cessationOfOperation), 6 (certificateHold), 8 (removeFromCRL), 9 (privilegeWithdrawn), 10 (aACompromise).

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to openssl.

+

If set to openssl, will try to use the openssl binary.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "openssl"

  • +
+
+

validate_certs

+

boolean

+

Whether calls to the ACME directory will validate TLS certificates.

+

Warning: Should only ever be set to false for testing purposes, for example when testing against a local Pebble server.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

action_group

+

Action groups: community.crypto.acme, acme

+

Use group/acme or group/community.crypto.acme in module_defaults to set defaults for this module.

+
+

check_mode

+

Support: none

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • Exactly one of account_key_src, account_key_content, private_key_src or private_key_content must be specified.

  • +
  • Trying to revoke an already revoked certificate should result in an unchanged status, even if the revocation reason was different than the one specified here. Also, depending on the server, it can happen that some other error is returned if the certificate has already been revoked.

  • +
  • If a new enough version of the cryptography library is available (see Requirements for details), it will be used instead of the openssl binary. This can be explicitly disabled or enabled with the select_crypto_backend option. Note that using the openssl binary will be slower and less secure, as private key contents always have to be stored on disk (see account_key_content).

  • +
  • Although the defaults are chosen so that the module can be used with the Let’s Encrypt CA, the module can in principle be used with any CA providing an ACME endpoint, such as Buypass Go SSL.

  • +
  • So far, the ACME modules have only been tested by the developers against Let’s Encrypt (staging and production), Buypass (staging and production), ZeroSSL (production), and Pebble testing server. We have got community feedback that they also work with Sectigo ACME Service for InCommon. If you experience problems with another ACME server, please create an issue to help us supporting it. Feedback that an ACME server not mentioned does work is also appreciated.

  • +
+
+
+
+

See Also

+
+

See also

+
+
The Let’s Encrypt documentation

Documentation for the Let’s Encrypt Certification Authority. Provides useful information for example on rate limits.

+
+
Automatic Certificate Management Environment (ACME)

The specification of the ACME protocol (RFC 8555).

+
+
community.crypto.acme_inspect

Allows to debug problems.

+
+
+
+
+
+

Examples

+
- name: Revoke certificate with account key
+  community.crypto.acme_certificate_revoke:
+    account_key_src: /etc/pki/cert/private/account.key
+    certificate: /etc/httpd/ssl/sample.com.crt
+
+- name: Revoke certificate with certificate's private key
+  community.crypto.acme_certificate_revoke:
+    private_key_src: /etc/httpd/ssl/sample.com.key
+    certificate: /etc/httpd/ssl/sample.com.crt
+
+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/acme_challenge_cert_helper_module.html b/pr/558/acme_challenge_cert_helper_module.html new file mode 100644 index 00000000..351653f2 --- /dev/null +++ b/pr/558/acme_challenge_cert_helper_module.html @@ -0,0 +1,436 @@ + + + + + + + community.crypto.acme_challenge_cert_helper module – Prepare certificates required for ACME challenges such as tls-alpn-01 — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_challenge_cert_helper module – Prepare certificates required for ACME challenges such as tls-alpn-01

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.acme_challenge_cert_helper.

+
+ +
+

Synopsis

+
    +
  • Prepares certificates for ACME challenges such as tls-alpn-01.

  • +
  • The raw data is provided by the community.crypto.acme_certificate module, and needs to be converted to a certificate to be used for challenge validation. This module provides a simple way to generate the required certificates.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.3

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

challenge

+

string / required

+

The challenge type.

+

Choices:

+
    +
  • "tls-alpn-01"

  • +
+
+

challenge_data

+

dictionary / required

+

The challenge_data entry provided by community.crypto.acme_certificate for the challenge.

+
+

private_key_content

+

string

+

Content of the private key to use for this challenge certificate.

+

Mutually exclusive with private_key_src.

+
+

private_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the private key.

+
+

private_key_src

+

path

+

Path to a file containing the private key file to use for this challenge certificate.

+

Mutually exclusive with private_key_content.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: none

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

See Also

+
+

See also

+
+
Automatic Certificate Management Environment (ACME)

The specification of the ACME protocol (RFC 8555).

+
+
ACME TLS ALPN Challenge Extension

The specification of the tls-alpn-01 challenge (RFC 8737).

+
+
+
+
+
+

Examples

+
- name: Create challenges for a given CRT for sample.com
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    challenge: tls-alpn-01
+    csr: /etc/pki/cert/csr/sample.com.csr
+    dest: /etc/httpd/ssl/sample.com.crt
+  register: sample_com_challenge
+
+- name: Create certificates for challenges
+  community.crypto.acme_challenge_cert_helper:
+    challenge: tls-alpn-01
+    challenge_data: "{{ item.value['tls-alpn-01'] }}"
+    private_key_src: /etc/pki/cert/key/sample.com.key
+  loop: "{{ sample_com_challenge.challenge_data | dictsort }}"
+  register: sample_com_challenge_certs
+
+- name: Install challenge certificates
+  # We need to set up HTTPS such that for the domain,
+  # regular_certificate is delivered for regular connections,
+  # except if ALPN selects the "acme-tls/1"; then, the
+  # challenge_certificate must be delivered.
+  # This can for example be achieved with very new versions
+  # of NGINX; search for ssl_preread and
+  # ssl_preread_alpn_protocols for information on how to
+  # route by ALPN protocol.
+  ...:
+    domain: "{{ item.domain }}"
+    challenge_certificate: "{{ item.challenge_certificate }}"
+    regular_certificate: "{{ item.regular_certificate }}"
+    private_key: /etc/pki/cert/key/sample.com.key
+  loop: "{{ sample_com_challenge_certs.results }}"
+
+- name: Create certificate for a given CSR for sample.com
+  community.crypto.acme_certificate:
+    account_key_src: /etc/pki/cert/private/account.key
+    challenge: tls-alpn-01
+    csr: /etc/pki/cert/csr/sample.com.csr
+    dest: /etc/httpd/ssl/sample.com.crt
+    data: "{{ sample_com_challenge }}"
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

challenge_certificate

+

string

+

The challenge certificate in PEM format.

+

Returned: always

+
+

domain

+

string

+

The domain the challenge is for. The certificate should be provided if this is specified in the request’s the Host header.

+

Returned: always

+
+

identifier

+

string

+

The identifier for the actual resource. Will be a domain name if the type is dns, or an IP address if the type is ip.

+

Returned: always

+
+

identifier_type

+

string

+

The identifier type for the actual resource identifier. Will be dns or ip.

+

Returned: always

+
+

regular_certificate

+

string

+

A self-signed certificate for the challenge domain.

+

If no existing certificate exists, can be used to set-up https in the first place if that is needed for providing the challenge.

+

Returned: always

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/acme_inspect_module.html b/pr/558/acme_inspect_module.html new file mode 100644 index 00000000..fee52581 --- /dev/null +++ b/pr/558/acme_inspect_module.html @@ -0,0 +1,620 @@ + + + + + + + community.crypto.acme_inspect module – Send direct requests to an ACME server — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.acme_inspect module – Send direct requests to an ACME server

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.acme_inspect.

+
+ +
+

Synopsis

+
    +
  • Allows to send direct requests to an ACME server with the ACME protocol, which is supported by CAs such as Let’s Encrypt.

  • +
  • This module can be used to debug failed certificate request attempts, for example when community.crypto.acme_certificate fails or encounters a problem which you wish to investigate.

  • +
  • The module can also be used to directly access features of an ACME servers which are not yet supported by the Ansible ACME modules.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+ +
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

account_key_content

+

string

+

Content of the ACME account RSA or Elliptic Curve key.

+

Mutually exclusive with account_key_src.

+

Required if account_key_src is not used.

+

Warning: the content will be written into a temporary file, which will be deleted by Ansible when the module completes. Since this is an important private key — it can be used to change the account key, or to revoke your certificates without knowing their private keys —, this might not be acceptable.

+

In case cryptography is used, the content is not written into a temporary file. It can still happen that it is written to disk by Ansible in the process of moving the module with its argument to the node where it is executed.

+
+

account_key_passphrase

+

string

+

added in community.crypto 1.6.0

+

Phassphrase to use to decode the account key.

+

Note: this is not supported by the openssl backend, only by the cryptography backend.

+
+
+

account_key_src

+

aliases: account_key

+

path

+

Path to a file containing the ACME account RSA or Elliptic Curve key.

+

Private keys can be created with the community.crypto.openssl_privatekey or community.crypto.openssl_privatekey_pipe modules. If the requisite (cryptography) is not available, keys can also be created directly with the openssl command line tool: RSA keys can be created with openssl genrsa .... Elliptic curve keys can be created with openssl ecparam -genkey .... Any other tool creating private keys in PEM format can be used as well.

+

Mutually exclusive with account_key_content.

+

Required if account_key_content is not used.

+
+

account_uri

+

string

+

If specified, assumes that the account URI is as given. If the account key does not match this account, or an account with this URI does not exist, the module fails.

+
+

acme_directory

+

string / required

+

The ACME directory to use. This is the entry point URL to access the ACME CA server API.

+

For safety reasons the default is set to the Let’s Encrypt staging server (for the ACME v1 protocol). This will create technically correct, but untrusted certificates.

+

For Let’s Encrypt, all staging endpoints can be found here: https://letsencrypt.org/docs/staging-environment/. For Buypass, all endpoints can be found here: https://community.buypass.com/t/63d4ay/buypass-go-ssl-endpoints

+

For Let’s Encrypt, the production directory URL for ACME v2 is https://acme-v02.api.letsencrypt.org/directory.

+

For Buypass, the production directory URL for ACME v2 and v1 is https://api.buypass.com/acme/directory.

+

For ZeroSSL, the production directory URL for ACME v2 is https://acme.zerossl.com/v2/DV90.

+

For Sectigo, the production directory URL for ACME v2 is https://acme-qa.secure.trust-provider.com/v2/DV.

+

The notes for this module contain a list of ACME services this module has been tested against.

+
+

acme_version

+

integer / required

+

The ACME version of the endpoint.

+

Must be 1 for the classic Let’s Encrypt and Buypass ACME endpoints, or 2 for standardized ACME v2 endpoints.

+

The value 1 is deprecated since community.crypto 2.0.0 and will be removed from community.crypto 3.0.0.

+

Choices:

+
    +
  • 1

  • +
  • 2

  • +
+
+

content

+

string

+

An encoded JSON object which will be sent as the content if method is post.

+

Required when method is post, and not allowed otherwise.

+
+

fail_on_acme_error

+

boolean

+

If method is post or get, make the module fail in case an ACME error is returned.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

method

+

string

+

The method to use to access the given URL on the ACME server.

+

The value post executes an authenticated POST request. The content must be specified in the content option.

+

The value get executes an authenticated POST-as-GET request for ACME v2, and a regular GET request for ACME v1.

+

The value directory-only only retrieves the directory, without doing a request.

+

Choices:

+
    +
  • "get" ← (default)

  • +
  • "post"

  • +
  • "directory-only"

  • +
+
+

request_timeout

+

integer

+

added in community.crypto 2.3.0

+

The time Ansible should wait for a response from the ACME API.

+

This timeout is applied to all HTTP(S) requests (HEAD, GET, POST).

+

Default: 10

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to openssl.

+

If set to openssl, will try to use the openssl binary.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "openssl"

  • +
+
+

url

+

string

+

The URL to send the request to.

+

Must be specified if method is not directory-only.

+
+

validate_certs

+

boolean

+

Whether calls to the ACME directory will validate TLS certificates.

+

Warning: Should only ever be set to false for testing purposes, for example when testing against a local Pebble server.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

action_group

+

Action groups: community.crypto.acme, acme

+

Use group/acme or group/community.crypto.acme in module_defaults to set defaults for this module.

+
+

check_mode

+

Support: none

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • The account_uri option must be specified for properly authenticated ACME v2 requests (except a new-account request).

  • +
  • Using the ansible tool, community.crypto.acme_inspect can be used to directly execute ACME requests without the need of writing a playbook. For example, the following command retrieves the ACME account with ID 1 from Let’s Encrypt (assuming /path/to/key is the correct private account key): ansible localhost -m acme_inspect -a "account_key_src=/path/to/key acme_directory=https://acme-v02.api.letsencrypt.org/directory acme_version=2 account_uri=https://acme-v02.api.letsencrypt.org/acme/acct/1 method=get url=https://acme-v02.api.letsencrypt.org/acme/acct/1"

  • +
  • If a new enough version of the cryptography library is available (see Requirements for details), it will be used instead of the openssl binary. This can be explicitly disabled or enabled with the select_crypto_backend option. Note that using the openssl binary will be slower and less secure, as private key contents always have to be stored on disk (see account_key_content).

  • +
  • Although the defaults are chosen so that the module can be used with the Let’s Encrypt CA, the module can in principle be used with any CA providing an ACME endpoint, such as Buypass Go SSL.

  • +
  • So far, the ACME modules have only been tested by the developers against Let’s Encrypt (staging and production), Buypass (staging and production), ZeroSSL (production), and Pebble testing server. We have got community feedback that they also work with Sectigo ACME Service for InCommon. If you experience problems with another ACME server, please create an issue to help us supporting it. Feedback that an ACME server not mentioned does work is also appreciated.

  • +
+
+
+
+

See Also

+
+

See also

+
+
Automatic Certificate Management Environment (ACME)

The specification of the ACME protocol (RFC 8555).

+
+
ACME TLS ALPN Challenge Extension

The specification of the tls-alpn-01 challenge (RFC 8737).

+
+
+
+
+
+

Examples

+
- name: Get directory
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    method: directory-only
+  register: directory
+
+- name: Create an account
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    url: "{{ directory.newAccount}}"
+    method: post
+    content: '{"termsOfServiceAgreed":true}'
+  register: account_creation
+  # account_creation.headers.location contains the account URI
+  # if creation was successful
+
+- name: Get account information
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    url: "{{ account_creation.headers.location }}"
+    method: get
+
+- name: Update account contacts
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    url: "{{ account_creation.headers.location }}"
+    method: post
+    content: '{{ account_info | to_json }}'
+  vars:
+    account_info:
+      # For valid values, see
+      # https://tools.ietf.org/html/rfc8555#section-7.3
+      contact:
+      - mailto:me@example.com
+
+- name: Create certificate order
+  community.crypto.acme_certificate:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    csr: /etc/pki/cert/csr/sample.com.csr
+    fullchain_dest: /etc/httpd/ssl/sample.com-fullchain.crt
+    challenge: http-01
+  register: certificate_request
+
+# Assume something went wrong. certificate_request.order_uri contains
+# the order URI.
+
+- name: Get order information
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    url: "{{ certificate_request.order_uri }}"
+    method: get
+  register: order
+
+- name: Get first authz for order
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    url: "{{ order.output_json.authorizations[0] }}"
+    method: get
+  register: authz
+
+- name: Get HTTP-01 challenge for authz
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    url: "{{ authz.output_json.challenges | selectattr('type', 'equalto', 'http-01') }}"
+    method: get
+  register: http01challenge
+
+- name: Activate HTTP-01 challenge manually
+  community.crypto.acme_inspect:
+    acme_directory: https://acme-staging-v02.api.letsencrypt.org/directory
+    acme_version: 2
+    account_key_src: /etc/pki/cert/private/account.key
+    account_uri: "{{ account_creation.headers.location }}"
+    url: "{{ http01challenge.url }}"
+    method: post
+    content: '{}'
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + +

Key

Description

+

directory

+

dictionary

+

The ACME directory’s content

+

Returned: always

+

Sample: {"a85k3x9f91A4": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change", "meta": {"caaIdentities": ["letsencrypt.org"], "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf", "website": "https://letsencrypt.org"}, "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct", "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce", "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order", "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"}

+
+

headers

+

dictionary

+

The request’s HTTP headers (with lowercase keys)

+

Returned: always

+

Sample: {"boulder-requester": "12345", "cache-control": "max-age=0, no-cache, no-store", "connection": "close", "content-length": "904", "content-type": "application/json", "cookies": {}, "cookies_string": "", "date": "Wed, 07 Nov 2018 12:34:56 GMT", "expires": "Wed, 07 Nov 2018 12:44:56 GMT", "link": "<https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf>;rel=\"terms-of-service\"", "msg": "OK (904 bytes)", "pragma": "no-cache", "replay-nonce": "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGH", "server": "nginx", "status": 200, "strict-transport-security": "max-age=604800", "url": "https://acme-v02.api.letsencrypt.org/acme/acct/46161", "x-frame-options": "DENY"}

+
+

output_json

+

dictionary

+

The output parsed as JSON

+

Returned: if output can be parsed as JSON

+

Sample: [{"id": 12345}, {"key": [{"kty": "RSA"}, "..."]}]

+
+

output_text

+

string

+

The raw text output

+

Returned: always

+

Sample: "{\n  \"id\": 12345,\n  \"key\": {\n    \"kty\": \"RSA\",\n ..."

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/certificate_complete_chain_module.html b/pr/558/certificate_complete_chain_module.html new file mode 100644 index 00000000..3637a6e1 --- /dev/null +++ b/pr/558/certificate_complete_chain_module.html @@ -0,0 +1,387 @@ + + + + + + + community.crypto.certificate_complete_chain module – Complete certificate chain given a set of untrusted and root certificates — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.certificate_complete_chain module – Complete certificate chain given a set of untrusted and root certificates

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.certificate_complete_chain.

+
+ +
+

Synopsis

+
    +
  • This module completes a given chain of certificates in PEM format by finding intermediate certificates from a given set of certificates, until it finds a root certificate in another given set of certificates.

  • +
  • This can for example be used to find the root certificate for a certificate chain returned by community.crypto.acme_certificate.

  • +
  • Note that this module does not check for validity of the chains. It only checks that issuer and subject match, and that the signature is correct. It ignores validity dates and key usage completely. If you need to verify that a generated chain is valid, please use openssl verify ....

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.5

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + +

Parameter

Comments

+

input_chain

+

string / required

+

A concatenated set of certificates in PEM format forming a chain.

+

The module will try to complete this chain.

+
+

intermediate_certificates

+

list / elements=path

+

A list of filenames or directories.

+

A filename is assumed to point to a file containing one or more certificates in PEM format. All certificates in this file will be added to the set of root certificates.

+

If a directory name is given, all files in the directory and its subdirectories will be scanned and tried to be parsed as concatenated certificates in PEM format.

+

Symbolic links will be followed.

+

Default: []

+
+

root_certificates

+

list / elements=path / required

+

A list of filenames or directories.

+

A filename is assumed to point to a file containing one or more certificates in PEM format. All certificates in this file will be added to the set of root certificates.

+

If a directory name is given, all files in the directory and its subdirectories will be scanned and tried to be parsed as concatenated certificates in PEM format.

+

Symbolic links will be followed.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Examples

+
# Given a leaf certificate for www.ansible.com and one or more intermediate
+# certificates, finds the associated root certificate.
+- name: Find root certificate
+  community.crypto.certificate_complete_chain:
+    input_chain: "{{ lookup('file', '/etc/ssl/csr/www.ansible.com-fullchain.pem') }}"
+    root_certificates:
+    - /etc/ca-certificates/
+  register: www_ansible_com
+- name: Write root certificate to disk
+  copy:
+    dest: /etc/ssl/csr/www.ansible.com-root.pem
+    content: "{{ www_ansible_com.root }}"
+
+# Given a leaf certificate for www.ansible.com, and a list of intermediate
+# certificates, finds the associated root certificate.
+- name: Find root certificate
+  community.crypto.certificate_complete_chain:
+    input_chain: "{{ lookup('file', '/etc/ssl/csr/www.ansible.com.pem') }}"
+    intermediate_certificates:
+    - /etc/ssl/csr/www.ansible.com-chain.pem
+    root_certificates:
+    - /etc/ca-certificates/
+  register: www_ansible_com
+- name: Write complete chain to disk
+  copy:
+    dest: /etc/ssl/csr/www.ansible.com-completechain.pem
+    content: "{{ ''.join(www_ansible_com.complete_chain) }}"
+- name: Write root chain (intermediates and root) to disk
+  copy:
+    dest: /etc/ssl/csr/www.ansible.com-rootchain.pem
+    content: "{{ ''.join(www_ansible_com.chain) }}"
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + +

Key

Description

+

chain

+

list / elements=string

+

The chain added to the given input chain. Includes the root certificate.

+

Returned as a list of PEM certificates.

+

Returned: success

+
+

complete_chain

+

list / elements=string

+

The completed chain, including leaf, all intermediates, and root.

+

Returned as a list of PEM certificates.

+

Returned: success

+
+

root

+

string

+

The root certificate in PEM format.

+

Returned: success

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/crypto_info_module.html b/pr/558/crypto_info_module.html new file mode 100644 index 00000000..3b1adfc2 --- /dev/null +++ b/pr/558/crypto_info_module.html @@ -0,0 +1,487 @@ + + + + + + + community.crypto.crypto_info module – Retrieve cryptographic capabilities — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.crypto_info module – Retrieve cryptographic capabilities

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto.

+

To use it in a playbook, specify: community.crypto.crypto_info.

+
+

New in community.crypto 2.1.0

+ +
+

Synopsis

+
    +
  • Retrieve information on cryptographic capabilities.

  • +
  • The current version retrieves information on the Python cryptography library available to Ansible modules, and on the OpenSSL binary openssl found in the path.

  • +
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Examples

+
- name: Retrieve information
+  community.crypto.crypto_info:
+    account_key_src: /etc/pki/cert/private/account.key
+  register: crypto_information
+
+- name: Show retrieved information
+  ansible.builtin.debug:
+    var: crypto_information
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

openssl

+

dictionary

+

Information on the installed OpenSSL binary.

+

Returned: when openssl_present=true

+
+

path

+

string

+

Path of the OpenSSL binary.

+

Returned: success

+

Sample: "/usr/bin/openssl"

+
+

version

+

string

+

The OpenSSL version.

+

Returned: success

+

Sample: "1.1.1m"

+
+

version_output

+

string

+

The complete output of openssl version.

+

Returned: success

+

Sample: "OpenSSL 1.1.1m  14 Dec 2021\\n"

+
+

openssl_present

+

boolean

+

Whether the OpenSSL binary openssl is installed and can be found in the PATH.

+

Returned: always

+

Sample: true

+
+

python_cryptography_capabilities

+

dictionary

+

Information on the installed Python cryptography library.

+

Returned: when python_cryptography_installed=true

+
+

curves

+

list / elements=string

+

List of all supported elliptic curves.

+

Theoretically this should be non-empty for version 0.5 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_dsa

+

boolean

+

Whether DSA keys are supported.

+

Theoretically this should be the case for version 0.5 and higher.

+

Returned: success

+
+

has_dsa_sign

+

boolean

+

Whether signing with DSA keys is supported.

+

Theoretically this should be the case for version 1.5 and higher.

+

Returned: success

+
+

has_ec

+

boolean

+

Whether elliptic curves are supported.

+

Theoretically this should be the case for version 0.5 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_ec_sign

+

boolean

+

Whether signing with elliptic curves is supported.

+

Theoretically this should be the case for version 1.5 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_ed25519

+

boolean

+

Whether Ed25519 keys are supported.

+

Theoretically this should be the case for version 2.6 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_ed25519_sign

+

boolean

+

Whether signing with Ed25519 keys is supported.

+

Theoretically this should be the case for version 2.6 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_ed448

+

boolean

+

Whether Ed448 keys are supported.

+

Theoretically this should be the case for version 2.6 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_ed448_sign

+

boolean

+

Whether signing with Ed448 keys is supported.

+

Theoretically this should be the case for version 2.6 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_rsa

+

boolean

+

Whether RSA keys are supported.

+

Theoretically this should be the case for version 0.5 and higher.

+

Returned: success

+
+

has_rsa_sign

+

boolean

+

Whether signing with RSA keys is supported.

+

Theoretically this should be the case for version 1.4 and higher.

+

Returned: success

+
+

has_x25519

+

boolean

+

Whether X25519 keys are supported.

+

Theoretically this should be the case for version 2.0 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_x25519_serialization

+

boolean

+

Whether serialization of X25519 keys is supported.

+

Theoretically this should be the case for version 2.5 and higher, depending on the libssl version used.

+

Returned: success

+
+

has_x448

+

boolean

+

Whether X448 keys are supported.

+

Theoretically this should be the case for version 2.5 and higher, depending on the libssl version used.

+

Returned: success

+
+

version

+

string

+

The library version.

+

Returned: success

+
+

python_cryptography_import_error

+

string

+

Import error when trying to import the Python cryptography library.

+

Returned: when python_cryptography_installed=false

+
+

python_cryptography_installed

+

boolean

+

Whether the Python cryptography library is installed.

+

Returned: always

+

Sample: true

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/docsite/guide_ownca.html b/pr/558/docsite/guide_ownca.html new file mode 100644 index 00000000..de2e4ebc --- /dev/null +++ b/pr/558/docsite/guide_ownca.html @@ -0,0 +1,316 @@ + + + + + + + How to create a small CA — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

How to create a small CA

+

The community.crypto collection offers multiple modules that create private keys, certificate signing requests, and certificates. This guide shows how to create your own small CA and how to use it to sign certificates.

+

In all examples, we assume that the CA’s private key is password protected, where the password is provided in the secret_ca_passphrase variable.

+
+

Set up the CA

+

Any certificate can be used as a CA certificate. You can create a self-signed certificate (see How to create self-signed certificates), use another CA certificate to sign a new certificate (using the instructions below for signing a certificate), ask (and pay) a commercial CA to sign your CA certificate, etc.

+

The following instructions show how to set up a simple self-signed CA certificate.

+
- name: Create private key with password protection
+  community.crypto.openssl_privatekey:
+    path: /path/to/ca-certificate.key
+    passphrase: "{{ secret_ca_passphrase }}"
+
+- name: Create certificate signing request (CSR) for CA certificate
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: /path/to/ca-certificate.key
+    privatekey_passphrase: "{{ secret_ca_passphrase }}"
+    common_name: Ansible CA
+    use_common_name_for_san: false  # since we do not specify SANs, don't use CN as a SAN
+    basic_constraints:
+      - 'CA:TRUE'
+    basic_constraints_critical: true
+    key_usage:
+      - keyCertSign
+    key_usage_critical: true
+  register: ca_csr
+
+- name: Create self-signed CA certificate from CSR
+  community.crypto.x509_certificate:
+    path: /path/to/ca-certificate.pem
+    csr_content: "{{ ca_csr.csr }}"
+    privatekey_path: /path/to/ca-certificate.key
+    privatekey_passphrase: "{{ secret_ca_passphrase }}"
+    provider: selfsigned
+
+
+
+
+

Use the CA to sign a certificate

+

To sign a certificate, you must pass a CSR to the community.crypto.x509_certificate module or community.crypto.x509_certificate_pipe module.

+

In the following example, we assume that the certificate to sign (including its private key) are on server_1, while our CA certificate is on server_2. We do not want any key material to leave each respective server.

+
- name: Create private key for new certificate on server_1
+  community.crypto.openssl_privatekey:
+    path: /path/to/certificate.key
+  delegate_to: server_1
+  run_once: true
+
+- name: Create certificate signing request (CSR) for new certificate
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: /path/to/certificate.key
+    subject_alt_name:
+      - "DNS:ansible.com"
+      - "DNS:www.ansible.com"
+      - "DNS:docs.ansible.com"
+  delegate_to: server_1
+  run_once: true
+  register: csr
+
+- name: Sign certificate with our CA
+  community.crypto.x509_certificate_pipe:
+    csr_content: "{{ csr.csr }}"
+    provider: ownca
+    ownca_path: /path/to/ca-certificate.pem
+    ownca_privatekey_path: /path/to/ca-certificate.key
+    ownca_privatekey_passphrase: "{{ secret_ca_passphrase }}"
+    ownca_not_after: +365d  # valid for one year
+    ownca_not_before: "-1d"  # valid since yesterday
+  delegate_to: server_2
+  run_once: true
+  register: certificate
+
+- name: Write certificate file on server_1
+  copy:
+    dest: /path/to/certificate.pem
+    content: "{{ certificate.certificate }}"
+  delegate_to: server_1
+  run_once: true
+
+
+

Please note that the above procedure is not idempotent. The following extended example reads the existing certificate from server_1 (if exists) and provides it to the community.crypto.x509_certificate_pipe module, and only writes the result back if it was changed:

+
- name: Create private key for new certificate on server_1
+  community.crypto.openssl_privatekey:
+    path: /path/to/certificate.key
+  delegate_to: server_1
+  run_once: true
+
+- name: Create certificate signing request (CSR) for new certificate
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: /path/to/certificate.key
+    subject_alt_name:
+      - "DNS:ansible.com"
+      - "DNS:www.ansible.com"
+      - "DNS:docs.ansible.com"
+  delegate_to: server_1
+  run_once: true
+  register: csr
+
+- name: Check whether certificate exists
+  stat:
+    path: /path/to/certificate.pem
+  delegate_to: server_1
+  run_once: true
+  register: certificate_exists
+
+- name: Read existing certificate if exists
+  slurp:
+    src: /path/to/certificate.pem
+  when: certificate_exists.stat.exists
+  delegate_to: server_1
+  run_once: true
+  register: certificate
+
+- name: Sign certificate with our CA
+  community.crypto.x509_certificate_pipe:
+    content: "{{ (certificate.content | b64decode) if certificate_exists.stat.exists else omit }}"
+    csr_content: "{{ csr.csr }}"
+    provider: ownca
+    ownca_path: /path/to/ca-certificate.pem
+    ownca_privatekey_path: /path/to/ca-certificate.key
+    ownca_privatekey_passphrase: "{{ secret_ca_passphrase }}"
+    ownca_not_after: +365d  # valid for one year
+    ownca_not_before: "-1d"  # valid since yesterday
+  delegate_to: server_2
+  run_once: true
+  register: certificate
+
+- name: Write certificate file on server_1
+  copy:
+    dest: /path/to/certificate.pem
+    content: "{{ certificate.certificate }}"
+  delegate_to: server_1
+  run_once: true
+  when: certificate is changed
+
+
+
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/docsite/guide_selfsigned.html b/pr/558/docsite/guide_selfsigned.html new file mode 100644 index 00000000..be95d2f2 --- /dev/null +++ b/pr/558/docsite/guide_selfsigned.html @@ -0,0 +1,223 @@ + + + + + + + How to create self-signed certificates — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

How to create self-signed certificates

+

The community.crypto collection offers multiple modules that create private keys, certificate signing requests, and certificates. This guide shows how to create self-signed certificates.

+

For creating any kind of certificate, you always have to start with a private key. You can use the community.crypto.openssl_privatekey module to create a private key. If you only specify path, the default parameters will be used. This will result in a 4096 bit RSA private key:

+
- name: Create private key (RSA, 4096 bits)
+  community.crypto.openssl_privatekey:
+    path: /path/to/certificate.key
+
+
+

You can specify type to select another key type, size to select a different key size (only available for RSA and DSA keys), or passphrase if you want to store the key password-protected:

+
- name: Create private key (X25519) with password protection
+  community.crypto.openssl_privatekey:
+    path: /path/to/certificate.key
+    type: X25519
+    passphrase: changeme
+
+
+

To create a very simple self-signed certificate with no specific information, you can proceed directly with the community.crypto.x509_certificate module:

+
- name: Create simple self-signed certificate
+  community.crypto.x509_certificate:
+    path: /path/to/certificate.pem
+    privatekey_path: /path/to/certificate.key
+    provider: selfsigned
+
+
+

(If you used passphrase for the private key, you have to provide privatekey_passphrase.)

+

You can use selfsigned_not_after to define when the certificate expires (default: in roughly 10 years), and selfsigned_not_before to define from when the certificate is valid (default: now).

+

To define further properties of the certificate, like the subject, Subject Alternative Names (SANs), key usages, name constraints, etc., you need to first create a Certificate Signing Request (CSR) and provide it to the community.crypto.x509_certificate module. If you do not need the CSR file, you can use the community.crypto.openssl_csr_pipe module as in the example below. (To store it to disk, use the community.crypto.openssl_csr module instead.)

+
- name: Create certificate signing request (CSR) for self-signed certificate
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: /path/to/certificate.key
+    common_name: ansible.com
+    organization_name: Ansible, Inc.
+    subject_alt_name:
+      - "DNS:ansible.com"
+      - "DNS:www.ansible.com"
+      - "DNS:docs.ansible.com"
+  register: csr
+
+- name: Create self-signed certificate from CSR
+  community.crypto.x509_certificate:
+    path: /path/to/certificate.pem
+    csr_content: "{{ csr.csr }}"
+    privatekey_path: /path/to/certificate.key
+    provider: selfsigned
+
+
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/ecs_certificate_module.html b/pr/558/ecs_certificate_module.html new file mode 100644 index 00000000..3d9c827b --- /dev/null +++ b/pr/558/ecs_certificate_module.html @@ -0,0 +1,1084 @@ + + + + + + + community.crypto.ecs_certificate module – Request SSL/TLS certificates with the Entrust Certificate Services (ECS) API — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.ecs_certificate module – Request SSL/TLS certificates with the Entrust Certificate Services (ECS) API

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.ecs_certificate.

+
+ +
+

Synopsis

+
    +
  • Create, reissue, and renew certificates with the Entrust Certificate Services (ECS) API.

  • +
  • Requires credentials for the Entrust Certificate Services (ECS) API.

  • +
  • In order to request a certificate, the domain and organization used in the certificate signing request must be already validated in the ECS system. It is not the responsibility of this module to perform those steps.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • PyYAML >= 3.11

  • +
  • cryptography >= 1.6

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

additional_emails

+

list / elements=string

+

A list of additional email addresses to receive the delivery notice and expiry notification for the certificate.

+
+

backup

+

boolean

+

Whether a backup should be made for the certificate in path.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

cert_expiry

+

string

+

The date the certificate should be set to expire, in RFC3339 compliant date or date-time format. For example, 2020-02-23, 2020-02-23T15:00:00.05Z.

+

cert_expiry is only supported for requests of request_type=new or request_type=renew. If request_type=reissue, cert_expiry will be used for the first certificate issuance, but subsequent issuances will have the same expiry as the initial certificate.

+

A reissued certificate will always have the same expiry as the original certificate.

+

Note that only the date (day, month, year) is supported for specifying the expiry date. If you choose to specify an expiry time with the expiry date, the time will be adjusted to Eastern Standard Time (EST). This could have the unintended effect of moving your expiry date to the previous day.

+

Applies only to accounts with a pooling inventory model.

+

Only one of cert_expiry or cert_lifetime may be specified.

+
+

cert_lifetime

+

string

+

The lifetime of the certificate.

+

Applies to all certificates for accounts with a non-pooling inventory model.

+

cert_lifetime is only supported for requests of request_type=new or request_type=renew. If request_type=reissue, cert_lifetime will be used for the first certificate issuance, but subsequent issuances will have the same expiry as the initial certificate.

+

Applies to certificates of cert_type=CDS_INDIVIDUAL, CDS_GROUP, CDS_ENT_LITE, CDS_ENT_PRO, SMIME_ENT for accounts with a pooling inventory model.

+

P1Y is a certificate with a 1 year lifetime.

+

P2Y is a certificate with a 2 year lifetime.

+

P3Y is a certificate with a 3 year lifetime.

+

Only one of cert_expiry or cert_lifetime may be specified.

+

Choices:

+
    +
  • "P1Y"

  • +
  • "P2Y"

  • +
  • "P3Y"

  • +
+
+

cert_type

+

string

+

Specify the type of certificate requested.

+

If a certificate is being reissued or renewed, this parameter is ignored, and the cert_type of the initial certificate is used.

+

Choices:

+
    +
  • "STANDARD_SSL"

  • +
  • "ADVANTAGE_SSL"

  • +
  • "UC_SSL"

  • +
  • "EV_SSL"

  • +
  • "WILDCARD_SSL"

  • +
  • "PRIVATE_SSL"

  • +
  • "PD_SSL"

  • +
  • "CODE_SIGNING"

  • +
  • "EV_CODE_SIGNING"

  • +
  • "CDS_INDIVIDUAL"

  • +
  • "CDS_GROUP"

  • +
  • "CDS_ENT_LITE"

  • +
  • "CDS_ENT_PRO"

  • +
  • "SMIME_ENT"

  • +
+
+

client_id

+

integer

+

The client ID to submit the Certificate Signing Request under.

+

If no client ID is specified, the certificate will be submitted under the primary client with ID of 1.

+

When using a client other than the primary client, the org parameter cannot be specified.

+

The issued certificate will have an organization value in the subject distinguished name represented by the client.

+

Default: 1

+
+

csr

+

string

+

Base-64 encoded Certificate Signing Request (CSR). csr is accepted with or without PEM formatting around the Base-64 string.

+

If no csr is provided when request_type=reissue or request_type=renew, the certificate will be generated with the same public key as the certificate being renewed or reissued.

+

If subject_alt_name is specified, it will override the subject alternate names in the CSR.

+

If eku is specified, it will override the extended key usage in the CSR.

+

If ou is specified, it will override the organizational units “ou=” present in the subject distinguished name of the CSR, if any.

+

The organization “O=” field from the CSR will not be used. It will be replaced in the issued certificate by org if present, and if not present, the organization tied to client_id.

+
+

ct_log

+

boolean

+

In compliance with browser requirements, this certificate may be posted to the Certificate Transparency (CT) logs. This is a best practice technique that helps domain owners monitor certificates issued to their domains. Note that not all certificates are eligible for CT logging.

+

If ct_log is not specified, the certificate uses the account default.

+

If ct_log is specified and the account settings allow it, ct_log overrides the account default.

+

If ct_log is set to false, but the account settings are set to “always log”, the certificate generation will fail.

+

Choices:

+
    +
  • false

  • +
  • true

  • +
+
+

custom_fields

+

dictionary

+

Mapping of custom fields to associate with the certificate request and certificate.

+

Only supported if custom fields are enabled for your account.

+

Each custom field specified must be a custom field you have defined for your account.

+
+

date1

+

string

+

Custom date field.

+
+

date2

+

string

+

Custom date field.

+
+

date3

+

string

+

Custom date field.

+
+

date4

+

string

+

Custom date field.

+
+

date5

+

string

+

Custom date field.

+
+

dropdown1

+

string

+

Custom dropdown field.

+
+

dropdown2

+

string

+

Custom dropdown field.

+
+

dropdown3

+

string

+

Custom dropdown field.

+
+

dropdown4

+

string

+

Custom dropdown field.

+
+

dropdown5

+

string

+

Custom dropdown field.

+
+

email1

+

string

+

Custom email field.

+
+

email2

+

string

+

Custom email field.

+
+

email3

+

string

+

Custom email field.

+
+

email4

+

string

+

Custom email field.

+
+

email5

+

string

+

Custom email field.

+
+

number1

+

float

+

Custom number field.

+
+

number2

+

float

+

Custom number field.

+
+

number3

+

float

+

Custom number field.

+
+

number4

+

float

+

Custom number field.

+
+

number5

+

float

+

Custom number field.

+
+

text1

+

string

+

Custom text field (maximum 500 characters)

+
+

text10

+

string

+

Custom text field (maximum 500 characters)

+
+

text11

+

string

+

Custom text field (maximum 500 characters)

+
+

text12

+

string

+

Custom text field (maximum 500 characters)

+
+

text13

+

string

+

Custom text field (maximum 500 characters)

+
+

text14

+

string

+

Custom text field (maximum 500 characters)

+
+

text15

+

string

+

Custom text field (maximum 500 characters)

+
+

text2

+

string

+

Custom text field (maximum 500 characters)

+
+

text3

+

string

+

Custom text field (maximum 500 characters)

+
+

text4

+

string

+

Custom text field (maximum 500 characters)

+
+

text5

+

string

+

Custom text field (maximum 500 characters)

+
+

text6

+

string

+

Custom text field (maximum 500 characters)

+
+

text7

+

string

+

Custom text field (maximum 500 characters)

+
+

text8

+

string

+

Custom text field (maximum 500 characters)

+
+

text9

+

string

+

Custom text field (maximum 500 characters)

+
+

eku

+

string

+

If specified, overrides the key usage in the csr.

+

Choices:

+
    +
  • "SERVER_AUTH"

  • +
  • "CLIENT_AUTH"

  • +
  • "SERVER_AND_CLIENT_AUTH"

  • +
+
+

end_user_key_storage_agreement

+

boolean

+

The end user of the Code Signing certificate must generate and store the private key for this request on cryptographically secure hardware to be compliant with the Entrust CSP and Subscription agreement. If requesting a certificate of type CODE_SIGNING or EV_CODE_SIGNING, you must set end_user_key_storage_agreement to true if and only if you acknowledge that you will inform the user of this requirement.

+

Applicable only to cert_type of values CODE_SIGNING and EV_CODE_SIGNING.

+

Choices:

+
    +
  • false

  • +
  • true

  • +
+
+

entrust_api_client_cert_key_path

+

path / required

+

The path to the key for the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+
+

entrust_api_client_cert_path

+

path / required

+

The path to the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+
+

entrust_api_key

+

string / required

+

The key (password) for authentication to the Entrust Certificate Services (ECS) API.

+
+

entrust_api_specification_path

+

path

+

The path to the specification file defining the Entrust Certificate Services (ECS) API configuration.

+

You can use this to keep a local copy of the specification to avoid downloading it every time the module is used.

+

Default: "https://cloud.entrust.net/EntrustCloud/documentation/cms-api-2.1.0.yaml"

+
+

entrust_api_user

+

string / required

+

The username for authentication to the Entrust Certificate Services (ECS) API.

+
+

force

+

boolean

+

If force is used, a certificate is requested regardless of whether path points to an existing valid certificate.

+

If request_type=renew, a forced renew will fail if the certificate being renewed has been issued within the past 30 days, regardless of the value of remaining_days or the return value of cert_days - the ECS API does not support the “renew” operation for certificates that are not at least 30 days old.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

full_chain_path

+

path

+

The destination path for the full certificate chain of the certificate, intermediates, and roots.

+
+

org

+

string

+

Organization “O=” to include in the certificate.

+

If org is not specified, the organization from the client represented by client_id is used.

+

Unless the cert_type is PD_SSL, this field may not be specified if the value of client_id is not “1” (the primary client). non-primary clients, certificates may only be issued with the organization of that client.

+
+

ou

+

list / elements=string

+

Organizational unit “OU=” to include in the certificate.

+

ou behavior is dependent on whether organizational units are enabled for your account. If organizational unit support is disabled for your account, organizational units from the csr and the ou parameter are ignored.

+

If both csr and ou are specified, the value in ou will override the OU fields present in the subject distinguished name in the csr

+

If neither csr nor ou are specified for a renew or reissue operation, the OU fields in the initial certificate are reused.

+

An invalid OU from csr is ignored, but any invalid organizational units in ou will result in an error indicating “Unapproved OU”. The ou parameter can be used to force failure if an unapproved organizational unit is provided.

+

A maximum of one OU may be specified for current products. Multiple OUs are reserved for future products.

+
+

path

+

path / required

+

The destination path for the generated certificate as a PEM encoded cert.

+

If the certificate at this location is not an Entrust issued certificate, a new certificate will always be requested even if the current certificate is technically valid.

+

If there is already an Entrust certificate at this location, whether it is replaced is depends on the remaining_days calculation.

+

If an existing certificate is being replaced (see remaining_days, force, and tracking_id), whether a new certificate is requested or the existing certificate is renewed or reissued is based on request_type.

+
+

remaining_days

+

integer

+

The number of days the certificate must have left being valid. If cert_days < remaining_days then a new certificate will be obtained using request_type.

+

If request_type=renew, a renewal will fail if the certificate being renewed has been issued within the past 30 days, so do not set a remaining_days value that is within 30 days of the full lifetime of the certificate being acted upon.

+

For exmaple, if you are requesting Certificates with a 90 day lifetime, do not set remaining_days to a value 60 or higher).

+

The force option may be used to ensure that a new certificate is always obtained.

+

Default: 30

+
+

request_type

+

string

+

The operation performed if tracking_id references a valid certificate to reissue, or there is already a certificate present in path but either force is specified or cert_days < remaining_days.

+

Specifying request_type=validate_only means the request will be validated against the ECS API, but no certificate will be issued.

+

Specifying request_type=new means a certificate request will always be submitted and a new certificate issued.

+

Specifying request_type=renew means that an existing certificate (specified by tracking_id if present, otherwise path) will be renewed. If there is no certificate to renew, a new certificate is requested.

+

Specifying request_type=reissue means that an existing certificate (specified by tracking_id if present, otherwise path) will be reissued. If there is no certificate to reissue, a new certificate is requested.

+

If a certificate was issued within the past 30 days, the renew operation is not a valid operation and will fail.

+

Note that reissue is an operation that will result in the revocation of the certificate that is reissued, be cautious with its use.

+

check_mode is only supported if request_type=new

+

For example, setting request_type=renew and remaining_days=30 and pointing to the same certificate on multiple playbook runs means that on the first run new certificate will be requested. It will then be left along on future runs until it is within 30 days of expiry, then the ECS “renew” operation will be performed.

+

Choices:

+
    +
  • "new" ← (default)

  • +
  • "renew"

  • +
  • "reissue"

  • +
  • "validate_only"

  • +
+
+

requester_email

+

string / required

+

The requester email to associate with certificate tracking information and receive delivery and expiry notices for the certificate.

+
+

requester_name

+

string / required

+

The requester name to associate with certificate tracking information.

+
+

requester_phone

+

string / required

+

The requester phone number to associate with certificate tracking information.

+
+

subject_alt_name

+

list / elements=string

+

The subject alternative name identifiers, as an array of values (applies to cert_type with a value of STANDARD_SSL, ADVANTAGE_SSL, UC_SSL, EV_SSL, WILDCARD_SSL, PRIVATE_SSL, and PD_SSL).

+

If you are requesting a new SSL certificate, and you pass a subject_alt_name parameter, any SAN names in the CSR are ignored. If no subjectAltName parameter is passed, the SAN names in the CSR are used.

+

See request_type to understand more about SANs during reissues and renewals.

+

In the case of certificates of type STANDARD_SSL certificates, if the CN of the certificate is <domain>.<tld> only the www.<domain>.<tld> value is accepted. If the CN of the certificate is www.<domain>.<tld> only the <domain>.<tld> value is accepted.

+
+

tracking_id

+

integer

+

The tracking ID of the certificate to reissue or renew.

+

tracking_id is invalid if request_type=new or request_type=validate_only.

+

If there is a certificate present in path and it is an ECS certificate, tracking_id will be ignored.

+

If there is no certificate present in path or there is but it is from another provider, the certificate represented by tracking_id will be renewed or reissued and saved to path.

+

If there is no certificate present in path and the force and remaining_days parameters do not indicate a new certificate is needed, the certificate referenced by tracking_id certificate will be saved to path.

+

This can be used when a known certificate is not currently present on a server, but you want to renew or reissue it to be managed by an ansible playbook. For example, if you specify request_type=renew, tracking_id of an issued certificate, and path to a file that does not exist, the first run of a task will download the certificate specified by tracking_id (assuming it is still valid). Future runs of the task will (if applicable - see force and remaining_days) renew the certificate now present in path.

+
+

tracking_info

+

string

+

Free form tracking information to attach to the record for the certificate.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: partial

+

Check mode is only supported if request_type=new.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Notes

+
+

Note

+
    +
  • path must be specified as the output location of the certificate.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_privatekey

Can be used to create private keys (both for certificates and accounts).

+
+
community.crypto.openssl_csr

Can be used to create a Certificate Signing Request (CSR).

+
+
+
+
+
+

Examples

+
- name: Request a new certificate from Entrust with bare minimum parameters.
+        Will request a new certificate if current one is valid but within 30
+        days of expiry. If replacing an existing file in path, will back it up.
+  community.crypto.ecs_certificate:
+    backup: true
+    path: /etc/ssl/crt/ansible.com.crt
+    full_chain_path: /etc/ssl/crt/ansible.com.chain.crt
+    csr: /etc/ssl/csr/ansible.com.csr
+    cert_type: EV_SSL
+    requester_name: Jo Doe
+    requester_email: jdoe@ansible.com
+    requester_phone: 555-555-5555
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: If there is no certificate present in path, request a new certificate
+        of type EV_SSL. Otherwise, if there is an Entrust managed certificate
+        in path and it is within 63 days of expiration, request a renew of that
+        certificate.
+  community.crypto.ecs_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr: /etc/ssl/csr/ansible.com.csr
+    cert_type: EV_SSL
+    cert_expiry: '2020-08-20'
+    request_type: renew
+    remaining_days: 63
+    requester_name: Jo Doe
+    requester_email: jdoe@ansible.com
+    requester_phone: 555-555-5555
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: If there is no certificate present in path, download certificate
+        specified by tracking_id if it is still valid. Otherwise, if the
+        certificate is within 79 days of expiration, request a renew of that
+        certificate and save it in path. This can be used to "migrate" a
+        certificate to be Ansible managed.
+  community.crypto.ecs_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr: /etc/ssl/csr/ansible.com.csr
+    tracking_id: 2378915
+    request_type: renew
+    remaining_days: 79
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: Force a reissue of the certificate specified by tracking_id.
+  community.crypto.ecs_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    force: true
+    tracking_id: 2378915
+    request_type: reissue
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: Request a new certificate with an alternative client. Note that the
+        issued certificate will have it's Subject Distinguished Name use the
+        organization details associated with that client, rather than what is
+        in the CSR.
+  community.crypto.ecs_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr: /etc/ssl/csr/ansible.com.csr
+    client_id: 2
+    requester_name: Jo Doe
+    requester_email: jdoe@ansible.com
+    requester_phone: 555-555-5555
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: Request a new certificate with a number of CSR parameters overridden
+        and tracking information
+  community.crypto.ecs_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    full_chain_path: /etc/ssl/crt/ansible.com.chain.crt
+    csr: /etc/ssl/csr/ansible.com.csr
+    subject_alt_name:
+      - ansible.testcertificates.com
+      - www.testcertificates.com
+    eku: SERVER_AND_CLIENT_AUTH
+    ct_log: true
+    org: Test Organization Inc.
+    ou:
+      - Administration
+    tracking_info: "Submitted via Ansible"
+    additional_emails:
+      - itsupport@testcertificates.com
+      - jsmith@ansible.com
+    custom_fields:
+      text1: Admin
+      text2: Invoice 25
+      number1: 342
+      date1: '2018-01-01'
+      email1: sales@ansible.testcertificates.com
+      dropdown1: red
+    cert_expiry: '2020-08-15'
+    requester_name: Jo Doe
+    requester_email: jdoe@ansible.com
+    requester_phone: 555-555-5555
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created for the certificate.

+

Returned: changed and if backup is true

+

Sample: "/path/to/www.ansible.com.crt.2019-03-09@11:22~"

+
+

backup_full_chain_file

+

string

+

Name of the backup file created for the certificate chain.

+

Returned: changed and if backup is true and full_chain_path is set.

+

Sample: "/path/to/ca.chain.crt.2019-03-09@11:22~"

+
+

cert_days

+

integer

+

The number of days the certificate remains valid.

+

Returned: success

+

Sample: 253

+
+

cert_details

+

dictionary

+

The full response JSON from the Get Certificate call of the ECS API.

+

While the response contents are guaranteed to be forwards compatible with new ECS API releases, Entrust recommends that you do not make any playbooks take actions based on the content of this field. However it may be useful for debugging, logging, or auditing purposes.

+

Returned: success

+
+

cert_status

+

string

+

The certificate status in ECS.

+

Current possible values (which may be expanded in the future) are: ACTIVE, APPROVED, DEACTIVATED, DECLINED, EXPIRED, NA, PENDING, PENDING_QUORUM, READY, REISSUED, REISSUING, RENEWED, RENEWING, REVOKED, SUSPENDED

+

Returned: success

+

Sample: "ACTIVE"

+
+

filename

+

string

+

The destination path for the generated certificate.

+

Returned: changed or success

+

Sample: "/etc/ssl/crt/www.ansible.com.crt"

+
+

serial_number

+

integer

+

The serial number of the issued certificate.

+

Returned: success

+

Sample: 1235262234164342

+
+

tracking_id

+

integer

+

The tracking ID to reference and track the certificate in ECS.

+

Returned: success

+

Sample: 380079

+
+
+

Authors

+
    +
  • Chris Trufan (@ctrufan)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/ecs_domain_module.html b/pr/558/ecs_domain_module.html new file mode 100644 index 00000000..5eb99c4b --- /dev/null +++ b/pr/558/ecs_domain_module.html @@ -0,0 +1,571 @@ + + + + + + + community.crypto.ecs_domain module – Request validation of a domain with the Entrust Certificate Services (ECS) API — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.ecs_domain module – Request validation of a domain with the Entrust Certificate Services (ECS) API

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.ecs_domain.

+
+

New in community.crypto 1.0.0

+ +
+

Synopsis

+
    +
  • Request validation or re-validation of a domain with the Entrust Certificate Services (ECS) API.

  • +
  • Requires credentials for the Entrust Certificate Services (ECS) API.

  • +
  • If the domain is already in the validation process, no new validation will be requested, but the validation data (if applicable) will be returned.

  • +
  • If the domain is already in the validation process but the verification_method specified is different than the current verification_method, the verification_method will be updated and validation data (if applicable) will be returned.

  • +
  • If the domain is an active, validated domain, the return value of changed will be false, unless domain_status=EXPIRED, in which case a re-validation will be performed.

  • +
  • If verification_method=dns, details about the required DNS entry will be specified in the return parameters dns_contents, dns_location, and dns_resource_type.

  • +
  • If verification_method=web_server, details about the required file details will be specified in the return parameters file_contents and file_location.

  • +
  • If verification_method=email, the email address(es) that the validation email(s) were sent to will be in the return parameter emails. This is purely informational. For domains requested using this module, this will always be a list of size 1.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • PyYAML >= 3.11

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

client_id

+

integer

+

The client ID to request the domain be associated with.

+

If no client ID is specified, the domain will be added under the primary client with ID of 1.

+

Default: 1

+
+

domain_name

+

string / required

+

The domain name to be verified or reverified.

+
+

entrust_api_client_cert_key_path

+

path / required

+

The path to the key for the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+
+

entrust_api_client_cert_path

+

path / required

+

The path to the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+
+

entrust_api_key

+

string / required

+

The key (password) for authentication to the Entrust Certificate Services (ECS) API.

+
+

entrust_api_specification_path

+

path

+

The path to the specification file defining the Entrust Certificate Services (ECS) API configuration.

+

You can use this to keep a local copy of the specification to avoid downloading it every time the module is used.

+

Default: "https://cloud.entrust.net/EntrustCloud/documentation/cms-api-2.1.0.yaml"

+
+

entrust_api_user

+

string / required

+

The username for authentication to the Entrust Certificate Services (ECS) API.

+
+

verification_email

+

string

+

Email address to be used to verify domain ownership.

+

Email address must be either an email address present in the WHOIS data for domain_name, or one of the following constructed emails: admin@domain_name, administrator@domain_name, webmaster@domain_name, hostmaster@domain_name, postmaster@domain_name.

+

Note that if domain_name includes subdomains, the top level domain should be used. For example, if requesting validation of example1.ansible.com, or test.example2.ansible.com, and you want to use the “admin” preconstructed name, the email address should be admin@ansible.com.

+

If using the email values from the WHOIS data for the domain or its top level namespace, they must be exact matches.

+

If verification_method=email but verification_email is not provided, the first email address found in WHOIS data for the domain will be used.

+

To verify domain ownership, domain owner must follow the instructions in the email they receive.

+

Only allowed if verification_method=email

+
+

verification_method

+

string / required

+

The verification method to be used to prove control of the domain.

+

If verification_method=email and the value verification_email is specified, that value is used for the email validation. If verification_email is not provided, the first value present in WHOIS data will be used. An email will be sent to the address in verification_email with instructions on how to verify control of the domain.

+

If verification_method=dns, the value dns_contents must be stored in location dns_location, with a DNS record type of verification_dns_record_type. To prove domain ownership, update your DNS records so the text string returned by dns_contents is available at dns_location.

+

If verification_method=web_server, the contents of return value file_contents must be made available on a web server accessible at location file_location.

+

If verification_method=manual, the domain will be validated with a manual process. This is not recommended.

+

Choices:

+
    +
  • "dns"

  • +
  • "email"

  • +
  • "manual"

  • +
  • "web_server"

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: none

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • There is a small delay (typically about 5 seconds, but can be as long as 60 seconds) before obtaining the random values when requesting a validation while verification_method=dns or verification_method=web_server. Be aware of that if doing many domain validation requests.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate

Can be used to request certificates from ECS, with provider=entrust.

+
+
community.crypto.ecs_certificate

Can be used to request a Certificate from ECS using a verified domain.

+
+
+
+
+
+

Examples

+
- name: Request domain validation using email validation for client ID of 2.
+  community.crypto.ecs_domain:
+    domain_name: ansible.com
+    client_id: 2
+    verification_method: email
+    verification_email: admin@ansible.com
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: Request domain validation using DNS. If domain is already valid,
+        request revalidation if expires within 90 days
+  community.crypto.ecs_domain:
+    domain_name: ansible.com
+    verification_method: dns
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: Request domain validation using web server validation, and revalidate
+        if fewer than 60 days remaining of EV eligibility.
+  community.crypto.ecs_domain:
+    domain_name: ansible.com
+    verification_method: web_server
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+- name: Request domain validation using manual validation.
+  community.crypto.ecs_domain:
+    domain_name: ansible.com
+    verification_method: manual
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-client.key
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

client_id

+

integer

+

Client ID that the domain belongs to. If the input value client_id is specified, this will always be the same as client_id

+

Returned: changed or success

+

Sample: 1

+
+

dns_contents

+

string

+

The value that ECS will be expecting to find in the DNS record located at dns_location.

+

Returned: changed and if verification_method is dns

+

Sample: "AB23CD41432522FF2526920393982FAB"

+
+

dns_location

+

string

+

The location that ECS will be expecting to be able to find the DNS entry for domain verification, containing the contents of dns_contents.

+

Returned: changed and if verification_method is dns

+

Sample: "_pki-validation.ansible.com"

+
+

dns_resource_type

+

string

+

The type of resource record that ECS will be expecting for the DNS record located at dns_location.

+

Returned: changed and if verification_method is dns

+

Sample: "TXT"

+
+

domain_status

+

string

+

Status of the current domain. Will be one of APPROVED, DECLINED, CANCELLED, INITIAL_VERIFICATION, DECLINED, CANCELLED, RE_VERIFICATION, EXPIRED, EXPIRING

+

Returned: changed or success

+

Sample: "APPROVED"

+
+

emails

+

list / elements=string

+

The list of emails used to request validation of this domain.

+

Domains requested using this module will only have a list of size 1.

+

Returned: verification_method is email

+

Sample: ["admin@ansible.com", "administrator@ansible.com"]

+
+

ev_days_remaining

+

integer

+

The number of days the domain remains eligible for submission of “EV” certificates. Will never be greater than the value of ov_days_remaining

+

Returned: success and ev_eligible is true and domain_status is APPROVED, RE_VERIFICATION or EXPIRING.

+

Sample: 94

+
+

ev_eligible

+

boolean

+

Whether the domain is eligible for submission of “EV” certificates. Will never be true if ov_eligible is false

+

Returned: success and domain_status is APPROVED, RE_VERIFICATION or EXPIRING, or EXPIRED.

+

Sample: true

+
+

file_contents

+

string

+

The contents of the file that ECS will be expecting to find at file_location.

+

Returned: verification_method is web_server

+

Sample: "AB23CD41432522FF2526920393982FAB"

+
+

file_location

+

string

+

The location that ECS will be expecting to be able to find the file for domain verification, containing the contents of file_contents.

+

Returned: verification_method is web_server

+

Sample: "http://ansible.com/.well-known/pki-validation/abcd.txt"

+
+

ov_days_remaining

+

integer

+

The number of days the domain remains eligible for submission of “OV” certificates. Will never be less than the value of ev_days_remaining

+

Returned: success and ov_eligible is true and domain_status is APPROVED, RE_VERIFICATION or EXPIRING.

+

Sample: 129

+
+

ov_eligible

+

boolean

+

Whether the domain is eligible for submission of “OV” certificates. Will never be false if ov_eligible is true

+

Returned: success and domain_status is APPROVED, RE_VERIFICATION, EXPIRING, or EXPIRED.

+

Sample: true

+
+

verification_method

+

string

+

Verification method used to request the domain validation. If changed will be the same as verification_method input parameter.

+

Returned: changed or success

+

Sample: "dns"

+
+
+

Authors

+
    +
  • Chris Trufan (@ctrufan)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/environment_variables.html b/pr/558/environment_variables.html new file mode 100644 index 00000000..ec0a324b --- /dev/null +++ b/pr/558/environment_variables.html @@ -0,0 +1,176 @@ + + + + + + + Index of all Collection Environment Variables — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

Index of all Collection Environment Variables

+

The following index documents all environment variables declared by plugins in collections. +Environment variables used by the ansible-core configuation are documented in Ansible Configuration Settings.

+

No environment variables have been defined.

+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/get_certificate_module.html b/pr/558/get_certificate_module.html new file mode 100644 index 00000000..b474e3da --- /dev/null +++ b/pr/558/get_certificate_module.html @@ -0,0 +1,519 @@ + + + + + + + community.crypto.get_certificate module – Get a certificate from a host:port — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.get_certificate module – Get a certificate from a host:port

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.get_certificate.

+
+ +
+

Synopsis

+
    +
  • Makes a secure connection and returns information about the presented certificate

  • +
  • The module uses the cryptography Python library.

  • +
  • Support SNI (Server Name Indication) only with python >= 2.7.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • python >= 2.7 when using proxy_host

  • +
  • cryptography >= 1.6

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

ca_cert

+

path

+

A PEM file containing one or more root certificates; if present, the cert will be validated against these root certs.

+

Note that this only validates the certificate is signed by the chain; not that the cert is valid for the host presenting it.

+
+

host

+

string / required

+

The host to get the cert for (IP is fine)

+
+

port

+

integer / required

+

The port to connect to

+
+

proxy_host

+

string

+

Proxy host used when get a certificate.

+
+

proxy_port

+

integer

+

Proxy port used when get a certificate.

+

Default: 8080

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

server_name

+

string

+

added in community.crypto 1.4.0

+

Server name used for SNI (Server Name Indication) when hostname is an IP or is different from server name.

+
+

starttls

+

string

+

added in community.crypto 1.9.0

+

Requests a secure connection for protocols which require clients to initiate encryption.

+

Only available for mysql currently.

+

Choices:

+
    +
  • "mysql"

  • +
+
+

timeout

+

integer

+

The timeout in seconds

+

Default: 10

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: none

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • When using ca_cert on OS X it has been reported that in some conditions the validate will always succeed.

  • +
+
+
+
+

Examples

+
- name: Get the cert from an RDP port
+  community.crypto.get_certificate:
+    host: "1.2.3.4"
+    port: 3389
+  delegate_to: localhost
+  run_once: true
+  register: cert
+
+- name: Get a cert from an https port
+  community.crypto.get_certificate:
+    host: "www.google.com"
+    port: 443
+  delegate_to: localhost
+  run_once: true
+  register: cert
+
+- name: How many days until cert expires
+  debug:
+    msg: "cert expires in: {{ expire_days }} days."
+  vars:
+    expire_days: "{{ (( cert.not_after | to_datetime('%Y%m%d%H%M%SZ')) - (ansible_date_time.iso8601 | to_datetime('%Y-%m-%dT%H:%M:%SZ')) ).days }}"
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

cert

+

string

+

The certificate retrieved from the port

+

Returned: success

+
+

expired

+

boolean

+

Boolean indicating if the cert is expired

+

Returned: success

+
+

extensions

+

list / elements=dictionary

+

Extensions applied to the cert

+

Returned: success

+
+

asn1_data

+

string

+

The Base64 encoded ASN.1 content of the extension.

+

Note that depending on the cryptography version used, it is not possible to extract the ASN.1 content of the extension, but only to provide the re-encoded content of the extension in case it was parsed by cryptography. This should usually result in exactly the same value, except if the original extension value was malformed.

+

Returned: success

+
+

critical

+

boolean

+

Whether the extension is critical.

+

Returned: success

+
+

name

+

string

+

The extension’s name.

+

Returned: success

+
+

issuer

+

dictionary

+

Information about the issuer of the cert

+

Returned: success

+
+

not_after

+

string

+

Expiration date of the cert

+

Returned: success

+
+

not_before

+

string

+

Issue date of the cert

+

Returned: success

+
+

serial_number

+

string

+

The serial number of the cert

+

Returned: success

+
+

signature_algorithm

+

string

+

The algorithm used to sign the cert

+

Returned: success

+
+

subject

+

dictionary

+

Information about the subject of the cert (OU, CN, etc)

+

Returned: success

+
+

version

+

string

+

The version number of the certificate

+

Returned: success

+
+
+

Authors

+
    +
  • John Westcott IV (@john-westcott-iv)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/index.html b/pr/558/index.html new file mode 100644 index 00000000..b9d3b4a8 --- /dev/null +++ b/pr/558/index.html @@ -0,0 +1,274 @@ + + + + + + + Community.Crypto — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

Community.Crypto

+

Collection version 2.10.0

+ +
+

Description

+

Author:

+
    +
  • Ansible (github.com/ansible)

  • +
+

Supported ansible-core versions:

+
    +
  • 2.9.10 or newer

  • +
+
+
+

Communication

+ +
+
+
+
+

Scenario Guides

+ +
+
+

Plugin Index

+

These are the plugins in the community.crypto collection:

+
+

Modules

+ +
+
+
+
+

Filter Plugins

+ +
+
+
+
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/luks_device_module.html b/pr/558/luks_device_module.html new file mode 100644 index 00000000..211f5d77 --- /dev/null +++ b/pr/558/luks_device_module.html @@ -0,0 +1,703 @@ + + + + + + + community.crypto.luks_device module – Manage encrypted (LUKS) devices — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.luks_device module – Manage encrypted (LUKS) devices

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.luks_device.

+
+ +
+

Synopsis

+
    +
  • Module manages LUKS on given device. Supports creating, destroying, opening and closing of LUKS container and adding or removing new keys and passphrases.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptsetup

  • +
  • wipefs (when state is absent)

  • +
  • lsblk

  • +
  • blkid (when label or uuid options are used)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

cipher

+

string

+

added in community.crypto 1.1.0

+

This option allows the user to define the cipher specification string for the LUKS container.

+

Will only be used on container creation.

+

For pre-2.6.10 kernels, use aes-plain as they do not understand the new cipher spec strings. To use ESSIV, use aes-cbc-essiv:sha256.

+
+

device

+

string

+

Device to work with (for example /dev/sda1). Needed in most cases. Can be omitted only when state=closed together with name is provided.

+
+

force_remove_last_key

+

boolean

+

If set to true, allows removing the last key from a container.

+

BEWARE that when the last key has been removed from a container, the container can no longer be opened!

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

hash

+

string

+

added in community.crypto 1.1.0

+

This option allows the user to specify the hash function used in LUKS key setup scheme and volume key digest.

+

Will only be used on container creation.

+
+

keyfile

+

path

+

Used to unlock the container. Either a keyfile or a passphrase is needed for most of the operations. Parameter value is the path to the keyfile with the passphrase.

+

BEWARE that working with keyfiles in plaintext is dangerous. Make sure that they are protected.

+
+

keysize

+

integer

+

added in community.crypto 1.0.0

+

Sets the key size only if LUKS container does not exist.

+
+

label

+

string

+

added in community.crypto 1.0.0

+

This option allow the user to create a LUKS2 format container with label support, respectively to identify the container by label on later usages.

+

Will only be used on container creation, or when device is not specified.

+

This cannot be specified if type is set to luks1.

+
+

name

+

string

+

Sets container name when state=opened. Can be used instead of device when closing the existing container (that is, when state=closed).

+
+

new_keyfile

+

path

+

Adds additional key to given container on device. Needs keyfile or passphrase option for authorization. LUKS container supports up to 8 keyslots. Parameter value is the path to the keyfile with the passphrase.

+

NOTE that adding additional keys is idempotent only since community.crypto 1.4.0. For older versions, a new keyslot will be used even if another keyslot already exists for this keyfile.

+

BEWARE that working with keyfiles in plaintext is dangerous. Make sure that they are protected.

+
+

new_passphrase

+

string

+

added in community.crypto 1.0.0

+

Adds additional passphrase to given container on device. Needs keyfile or passphrase option for authorization. LUKS container supports up to 8 keyslots. Parameter value is a string with the new passphrase.

+

NOTE that adding additional passphrase is idempotent only since community.crypto 1.4.0. For older versions, a new keyslot will be used even if another keyslot already exists for this passphrase.

+
+

passphrase

+

string

+

added in community.crypto 1.0.0

+

Used to unlock the container. Either a passphrase or a keyfile is needed for most of the operations. Parameter value is a string with the passphrase.

+
+

pbkdf

+

dictionary

+

added in community.crypto 1.4.0

+

This option allows the user to configure the Password-Based Key Derivation Function (PBKDF) used.

+

Will only be used on container creation, and when adding keys to an existing container.

+
+

algorithm

+

string

+

The algorithm to use.

+

Only available for the LUKS 2 format.

+

Choices:

+
    +
  • "argon2i"

  • +
  • "argon2id"

  • +
  • "pbkdf2"

  • +
+
+

iteration_count

+

integer

+

Specify the iteration count used for the PBKDF.

+

Mutually exclusive with iteration_time.

+
+

iteration_time

+

float

+

Specify the iteration time used for the PBKDF.

+

Note that this is in seconds, not in milliseconds as on the command line.

+

Mutually exclusive with iteration_count.

+
+

memory

+

integer

+

The memory cost limit in kilobytes for the PBKDF.

+

This is not used for PBKDF2, but only for the Argon PBKDFs.

+
+

parallel

+

integer

+

The parallel cost for the PBKDF. This is the number of threads that run in parallel.

+

This is not used for PBKDF2, but only for the Argon PBKDFs.

+
+

perf_no_read_workqueue

+

boolean

+

added in community.crypto 2.3.0

+

Allows the user to bypass dm-crypt internal workqueue and process read requests synchronously.

+

Will only be used when opening containers.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

perf_no_write_workqueue

+

boolean

+

added in community.crypto 2.3.0

+

Allows the user to bypass dm-crypt internal workqueue and process write requests synchronously.

+

Will only be used when opening containers.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

perf_same_cpu_crypt

+

boolean

+

added in community.crypto 2.3.0

+

Allows the user to perform encryption using the same CPU that IO was submitted on.

+

The default is to use an unbound workqueue so that encryption work is automatically balanced between available CPUs.

+

Will only be used when opening containers.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

perf_submit_from_crypt_cpus

+

boolean

+

added in community.crypto 2.3.0

+

Allows the user to disable offloading writes to a separate thread after encryption.

+

There are some situations where offloading block write IO operations from the encryption threads to a single thread degrades performance significantly.

+

The default is to offload block write IO operations to the same thread.

+

Will only be used when opening containers.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

persistent

+

boolean

+

added in community.crypto 2.3.0

+

Allows the user to store options into container’s metadata persistently and automatically use them next time. Only perf_same_cpu_crypt, perf_submit_from_crypt_cpus, perf_no_read_workqueue, and perf_no_write_workqueue can be stored persistently.

+

Will only work with LUKS2 containers.

+

Will only be used when opening containers.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

remove_keyfile

+

path

+

Removes given key from the container on device. Does not remove the keyfile from filesystem. Parameter value is the path to the keyfile with the passphrase.

+

NOTE that removing keys is idempotent only since community.crypto 1.4.0. For older versions, trying to remove a key which no longer exists results in an error.

+

NOTE that to remove the last key from a LUKS container, the force_remove_last_key option must be set to true.

+

BEWARE that working with keyfiles in plaintext is dangerous. Make sure that they are protected.

+
+

remove_passphrase

+

string

+

added in community.crypto 1.0.0

+

Removes given passphrase from the container on device. Parameter value is a string with the passphrase to remove.

+

NOTE that removing passphrases is idempotent only since community.crypto 1.4.0. For older versions, trying to remove a passphrase which no longer exists results in an error.

+

NOTE that to remove the last keyslot from a LUKS container, the force_remove_last_key option must be set to true.

+
+

sector_size

+

integer

+

added in community.crypto 1.5.0

+

This option allows the user to specify the sector size (in bytes) used for LUKS2 containers.

+

Will only be used on container creation.

+
+

state

+

string

+

Desired state of the LUKS container. Based on its value creates, destroys, opens or closes the LUKS container on a given device.

+

present will create LUKS container unless already present. Requires device and either keyfile or passphrase options to be provided.

+

absent will remove existing LUKS container if it exists. Requires device or name to be specified.

+

opened will unlock the LUKS container. If it does not exist it will be created first. Requires device and either keyfile or passphrase to be specified. Use the name option to set the name of the opened container. Otherwise the name will be generated automatically and returned as a part of the result.

+

closed will lock the LUKS container. However if the container does not exist it will be created. Requires device and either keyfile or passphrase options to be provided. If container does already exist device or name will suffice.

+

Choices:

+
    +
  • "present" ← (default)

  • +
  • "absent"

  • +
  • "opened"

  • +
  • "closed"

  • +
+
+

type

+

string

+

added in community.crypto 1.0.0

+

This option allow the user explicit define the format of LUKS container that wants to work with. Options are luks1 or luks2

+

Choices:

+
    +
  • "luks1"

  • +
  • "luks2"

  • +
+
+

uuid

+

string

+

added in community.crypto 1.0.0

+

With this option user can identify the LUKS container by UUID.

+

Will only be used when device and label are not specified.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Examples

+
- name: Create LUKS container (remains unchanged if it already exists)
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "present"
+    keyfile: "/vault/keyfile"
+
+- name: Create LUKS container with a passphrase
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "present"
+    passphrase: "foo"
+
+- name: Create LUKS container with specific encryption
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "present"
+    cipher: "aes"
+    hash: "sha256"
+
+- name: (Create and) open the LUKS container; name it "mycrypt"
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "opened"
+    name: "mycrypt"
+    keyfile: "/vault/keyfile"
+
+- name: Close the existing LUKS container "mycrypt"
+  community.crypto.luks_device:
+    state: "closed"
+    name: "mycrypt"
+
+- name: Make sure LUKS container exists and is closed
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "closed"
+    keyfile: "/vault/keyfile"
+
+- name: Create container if it does not exist and add new key to it
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "present"
+    keyfile: "/vault/keyfile"
+    new_keyfile: "/vault/keyfile2"
+
+- name: Add new key to the LUKS container (container has to exist)
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    keyfile: "/vault/keyfile"
+    new_keyfile: "/vault/keyfile2"
+
+- name: Add new passphrase to the LUKS container
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    keyfile: "/vault/keyfile"
+    new_passphrase: "foo"
+
+- name: Remove existing keyfile from the LUKS container
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    remove_keyfile: "/vault/keyfile2"
+
+- name: Remove existing passphrase from the LUKS container
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    remove_passphrase: "foo"
+
+- name: Completely remove the LUKS container and its contents
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "absent"
+
+- name: Create a container with label
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "present"
+    keyfile: "/vault/keyfile"
+    label: personalLabelName
+
+- name: Open the LUKS container based on label without device; name it "mycrypt"
+  community.crypto.luks_device:
+    label: "personalLabelName"
+    state: "opened"
+    name: "mycrypt"
+    keyfile: "/vault/keyfile"
+
+- name: Close container based on UUID
+  community.crypto.luks_device:
+    uuid: 03ecd578-fad4-4e6c-9348-842e3e8fa340
+    state: "closed"
+    name: "mycrypt"
+
+- name: Create a container using luks2 format
+  community.crypto.luks_device:
+    device: "/dev/loop0"
+    state: "present"
+    keyfile: "/vault/keyfile"
+    type: luks2
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + +

Key

Description

+

name

+

string

+

When state=opened returns (generated or given) name of LUKS container. Returns None if no name is supplied.

+

Returned: success

+

Sample: "luks-c1da9a58-2fde-4256-9d9f-6ab008b4dd1b"

+
+
+

Authors

+
    +
  • Jan Pokorny (@japokorn)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/objects.inv b/pr/558/objects.inv new file mode 100644 index 00000000..08dfd79d Binary files /dev/null and b/pr/558/objects.inv differ diff --git a/pr/558/openssh_cert_module.html b/pr/558/openssh_cert_module.html new file mode 100644 index 00000000..22a8eaf4 --- /dev/null +++ b/pr/558/openssh_cert_module.html @@ -0,0 +1,688 @@ + + + + + + + community.crypto.openssh_cert module – Generate OpenSSH host or user certificates. — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssh_cert module – Generate OpenSSH host or user certificates.

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssh_cert.

+
+ +
+

Synopsis

+
    +
  • Generate and regenerate OpenSSH host or user certificates.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • ssh-keygen

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

force

+

boolean

+

Should the certificate be regenerated even if it already exists and is valid.

+

Equivalent to regenerate=always.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

identifier

+

string

+

Specify the key identity when signing a public key. The identifier that is logged by the server when the certificate is used for authentication.

+
+

ignore_timestamps

+

boolean

+

added in community.crypto 2.2.0

+

Whether the valid_from and valid_to timestamps should be ignored for idempotency checks.

+

However, the values will still be applied to a new certificate if it meets any other necessary conditions for generation/regeneration.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

options

+

list / elements=string

+

Specify certificate options when signing a key. The option that are valid for user certificates are:

+

clear: Clear all enabled permissions. This is useful for clearing the default set of permissions so permissions may be added individually.

+

force-command=command: Forces the execution of command instead of any shell or command specified by the user when the certificate is used for authentication.

+

no-agent-forwarding: Disable ssh-agent forwarding (permitted by default).

+

no-port-forwarding: Disable port forwarding (permitted by default).

+

no-pty: Disable PTY allocation (permitted by default).

+

no-user-rc: Disable execution of ~/.ssh/rc by sshd (permitted by default).

+

no-x11-forwarding: Disable X11 forwarding (permitted by default)

+

permit-agent-forwarding: Allows ssh-agent forwarding.

+

permit-port-forwarding: Allows port forwarding.

+

permit-pty: Allows PTY allocation.

+

permit-user-rc: Allows execution of ~/.ssh/rc by sshd.

+

permit-x11-forwarding: Allows X11 forwarding.

+

source-address=address_list: Restrict the source addresses from which the certificate is considered valid. The address_list is a comma-separated list of one or more address/netmask pairs in CIDR format.

+

At present, no options are valid for host keys.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

path

+

path / required

+

Path of the file containing the certificate.

+
+

pkcs11_provider

+

string

+

added in community.crypto 1.1.0

+

To use a signing key that resides on a PKCS#11 token, set this to the name (or full path) of the shared library to use with the token. Usually libpkcs11.so.

+

If this is set, signing_key needs to point to a file containing the public key of the CA.

+
+

principals

+

list / elements=string

+

Certificates may be limited to be valid for a set of principal (user/host) names. By default, generated certificates are valid for all users or hosts.

+
+

public_key

+

path

+

The path to the public key that will be signed with the signing key in order to generate the certificate.

+

Required if state is present.

+
+

regenerate

+

string

+

added in community.crypto 1.8.0

+

When never the task will fail if a certificate already exists at path and is unreadable otherwise a new certificate will only be generated if there is no existing certificate.

+

When fail the task will fail if a certificate already exists at path and does not match the module’s options.

+

When partial_idempotence an existing certificate will be regenerated based on serial, signature_algorithm, type, valid_from, valid_to, valid_at, and principals. valid_from and valid_to can be excluded by ignore_timestamps=true.

+

When full_idempotence identifier, options, public_key, and signing_key are also considered when compared against an existing certificate.

+

always is equivalent to force=true.

+

Choices:

+
    +
  • "never"

  • +
  • "fail"

  • +
  • "partial_idempotence" ← (default)

  • +
  • "full_idempotence"

  • +
  • "always"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serial_number

+

integer

+

Specify the certificate serial number. The serial number is logged by the server when the certificate is used for authentication. The certificate serial number may be used in a KeyRevocationList. The serial number may be omitted for checks, but must be specified again for a new certificate. Note: The default value set by ssh-keygen is 0.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

signature_algorithm

+

string

+

added in community.crypto 1.10.0

+

As of OpenSSH 8.2 the SHA-1 signature algorithm for RSA keys has been disabled and ssh will refuse host certificates signed with the SHA-1 algorithm. OpenSSH 8.1 made rsa-sha2-512 the default algorithm when acting as a CA and signing certificates with a RSA key. However, for OpenSSH versions less than 8.1 the SHA-2 signature algorithms, rsa-sha2-256 or rsa-sha2-512, must be specified using this option if compatibility with newer ssh clients is required. Conversely if hosts using OpenSSH version 8.2 or greater must remain compatible with ssh clients using OpenSSH less than 7.2, then ssh-rsa can be used when generating host certificates (a corresponding change to the sshd_config to add ssh-rsa to the CASignatureAlgorithms keyword is also required).

+

Using any value for this option with a non-RSA signing_key will cause this module to fail.

+

Note: OpenSSH versions prior to 7.2 do not support SHA-2 signature algorithms for RSA keys and OpenSSH versions prior to 7.3 do not support SHA-2 signature algorithms for certificates.

+

See https://www.openssh.com/txt/release-8.2 for more information.

+

Choices:

+
    +
  • "ssh-rsa"

  • +
  • "rsa-sha2-256"

  • +
  • "rsa-sha2-512"

  • +
+
+

signing_key

+

path

+

The path to the private openssh key that is used for signing the public key in order to generate the certificate.

+

If the private key is on a PKCS#11 token (pkcs11_provider), set this to the path to the public key instead.

+

Required if state is present.

+
+

state

+

string

+

Whether the host or user certificate should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "present" ← (default)

  • +
  • "absent"

  • +
+
+

type

+

string

+

Whether the module should generate a host or a user certificate.

+

Required if state is present.

+

Choices:

+
    +
  • "host"

  • +
  • "user"

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

use_agent

+

boolean

+

added in community.crypto 1.3.0

+

Should the ssh-keygen use a CA key residing in a ssh-agent.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

valid_at

+

string

+

Check if the certificate is valid at a certain point in time. If it is not the certificate will be regenerated. Time will always be interpreted as UTC. Mainly to be used with relative timespec for valid_from and / or valid_to. Note that if using relative time this module is NOT idempotent.

+
+

valid_from

+

string

+

The point in time the certificate is valid from. Time can be specified either as relative time or as absolute timestamp. Time will always be interpreted as UTC. Valid formats are: [+-]timespec | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS | YYYY-MM-DD HH:MM:SS | always where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h). Note that if using relative time this module is NOT idempotent.

+

The value always is only supported for OpenSSH 7.7 and greater, however, the value 1970-01-01T00:00:01 can be used with earlier versions as an equivalent expression.

+

To ignore this value during comparison with an existing certificate set ignore_timestamps=true.

+

Required if state is present.

+
+

valid_to

+

string

+

The point in time the certificate is valid to. Time can be specified either as relative time or as absolute timestamp. Time will always be interpreted as UTC. Valid formats are: [+-]timespec | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS | YYYY-MM-DD HH:MM:SS | forever where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h). Note that if using relative time this module is NOT idempotent.

+

To ignore this value during comparison with an existing certificate set ignore_timestamps=true.

+

Required if state is present.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Examples

+
- name: Generate an OpenSSH user certificate that is valid forever and for all users
+  community.crypto.openssh_cert:
+    type: user
+    signing_key: /path/to/private_key
+    public_key: /path/to/public_key.pub
+    path: /path/to/certificate
+    valid_from: always
+    valid_to: forever
+
+# Generate an OpenSSH host certificate that is valid for 32 weeks from now and will be regenerated
+# if it is valid for less than 2 weeks from the time the module is being run
+- name: Generate an OpenSSH host certificate with valid_from, valid_to and valid_at parameters
+  community.crypto.openssh_cert:
+    type: host
+    signing_key: /path/to/private_key
+    public_key: /path/to/public_key.pub
+    path: /path/to/certificate
+    valid_from: +0s
+    valid_to: +32w
+    valid_at: +2w
+    ignore_timestamps: true
+
+- name: Generate an OpenSSH host certificate that is valid forever and only for example.com and examplehost
+  community.crypto.openssh_cert:
+    type: host
+    signing_key: /path/to/private_key
+    public_key: /path/to/public_key.pub
+    path: /path/to/certificate
+    valid_from: always
+    valid_to: forever
+    principals:
+        - example.com
+        - examplehost
+
+- name: Generate an OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019
+  community.crypto.openssh_cert:
+    type: host
+    signing_key: /path/to/private_key
+    public_key: /path/to/public_key.pub
+    path: /path/to/certificate
+    valid_from: "2001-01-21"
+    valid_to: "2019-01-21"
+
+- name: Generate an OpenSSH user Certificate with clear and force-command option
+  community.crypto.openssh_cert:
+    type: user
+    signing_key: /path/to/private_key
+    public_key: /path/to/public_key.pub
+    path: /path/to/certificate
+    valid_from: always
+    valid_to: forever
+    options:
+        - "clear"
+        - "force-command=/tmp/bla/foo"
+
+- name: Generate an OpenSSH user certificate using a PKCS#11 token
+  community.crypto.openssh_cert:
+    type: user
+    signing_key: /path/to/ca_public_key.pub
+    pkcs11_provider: libpkcs11.so
+    public_key: /path/to/public_key.pub
+    path: /path/to/certificate
+    valid_from: always
+    valid_to: forever
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + +

Key

Description

+

filename

+

string

+

path to the certificate

+

Returned: changed or success

+

Sample: "/tmp/certificate-cert.pub"

+
+

info

+

list / elements=string

+

Information about the certificate. Output of ssh-keygen -L -f.

+

Returned: change or success

+
+

type

+

string

+

type of the certificate (host or user)

+

Returned: changed or success

+

Sample: "host"

+
+
+

Authors

+
    +
  • David Kainz (@lolcube)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssh_keypair_module.html b/pr/558/openssh_keypair_module.html new file mode 100644 index 00000000..da41bad3 --- /dev/null +++ b/pr/558/openssh_keypair_module.html @@ -0,0 +1,613 @@ + + + + + + + community.crypto.openssh_keypair module – Generate OpenSSH private and public keys — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssh_keypair module – Generate OpenSSH private and public keys

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssh_keypair.

+
+ +
+

Synopsis

+
    +
  • This module allows one to (re)generate OpenSSH private and public keys. It uses ssh-keygen to generate keys. One can generate rsa, dsa, rsa1, ed25519 or ecdsa private keys.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • ssh-keygen (if backend=openssh)

  • +
  • cryptography >= 2.6 (if backend=cryptography and OpenSSH < 7.8 is installed)

  • +
  • cryptography >= 3.0 (if backend=cryptography and OpenSSH >= 7.8 is installed)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backend

+

string

+

added in community.crypto 1.7.0

+

Selects between the cryptography library or the OpenSSH binary opensshbin.

+

auto will default to opensshbin unless the OpenSSH binary is not installed or when using passphrase.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "opensshbin"

  • +
+
+

comment

+

string

+

Provides a new comment to the public key.

+
+

force

+

boolean

+

Should the key be regenerated even if it already exists

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

passphrase

+

string

+

added in community.crypto 1.7.0

+

Passphrase used to decrypt an existing private key or encrypt a newly generated private key.

+

Passphrases are not supported for type=rsa1.

+

Can only be used when backend=cryptography, or when backend=auto and a required cryptography version is installed.

+
+

path

+

path / required

+

Name of the files containing the public and private key. The file containing the public key will have the extension .pub.

+
+

private_key_format

+

string

+

added in community.crypto 1.7.0

+

Used when backend=cryptography to select a format for the private key at the provided path.

+

When set to auto this module will match the key format of the installed OpenSSH version.

+

For OpenSSH < 7.8 private keys will be in PKCS1 format except ed25519 keys which will be in OpenSSH format.

+

For OpenSSH >= 7.8 all private key types will be in the OpenSSH format.

+

Using this option when regenerate=partial_idempotence or regenerate=full_idempotence will cause a new keypair to be generated if the private key’s format does not match the value of private_key_format. This module will not however convert existing private keys between formats.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "pkcs1"

  • +
  • "pkcs8"

  • +
  • "ssh"

  • +
+
+

regenerate

+

string

+

added in community.crypto 1.0.0

+

Allows to configure in which situations the module is allowed to regenerate private keys. The module will always generate a new key if the destination file does not exist.

+

By default, the key will be regenerated when it does not match the module’s options, except when the key cannot be read or the passphrase does not match. Please note that this changed for Ansible 2.10. For Ansible 2.9, the behavior was as if full_idempotence is specified.

+

If set to never, the module will fail if the key cannot be read or the passphrase is not matching, and will never regenerate an existing key.

+

If set to fail, the module will fail if the key does not correspond to the module’s options.

+

If set to partial_idempotence, the key will be regenerated if it does not conform to the module’s options. The key is not regenerated if it cannot be read (broken file), the key is protected by an unknown passphrase, or when they key is not protected by a passphrase, but a passphrase is specified.

+

If set to full_idempotence, the key will be regenerated if it does not conform to the module’s options. This is also the case if the key cannot be read (broken file), the key is protected by an unknown passphrase, or when they key is not protected by a passphrase, but a passphrase is specified. Make sure you have a backup when using this option!

+

If set to always, the module will always regenerate the key. This is equivalent to setting force to true.

+

Note that adjusting the comment and the permissions can be changed without regeneration. Therefore, even for never, the task can result in changed.

+

Choices:

+
    +
  • "never"

  • +
  • "fail"

  • +
  • "partial_idempotence" ← (default)

  • +
  • "full_idempotence"

  • +
  • "always"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

size

+

integer

+

Specifies the number of bits in the private key to create. For RSA keys, the minimum size is 1024 bits and the default is 4096 bits. Generally, 2048 bits is considered sufficient. DSA keys must be exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys, size determines the key length by selecting from one of three elliptic curve sizes: 256, 384 or 521 bits. Attempting to use bit lengths other than these three values for ECDSA keys will cause this module to fail. Ed25519 keys have a fixed length and the size will be ignored.

+
+

state

+

string

+

Whether the private and public keys should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "present" ← (default)

  • +
  • "absent"

  • +
+
+

type

+

string

+

The algorithm used to generate the SSH private key. rsa1 is for protocol version 1. rsa1 is deprecated and may not be supported by every version of ssh-keygen.

+

Choices:

+
    +
  • "rsa" ← (default)

  • +
  • "dsa"

  • +
  • "rsa1"

  • +
  • "ecdsa"

  • +
  • "ed25519"

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Notes

+
+

Note

+
    +
  • In case the ssh key is broken or password protected, the module will fail. Set the force option to true if you want to regenerate the keypair.

  • +
  • In the case a custom mode, group, owner, or other file attribute is provided it will be applied to both key files.

  • +
+
+
+
+

Examples

+
- name: Generate an OpenSSH keypair with the default values (4096 bits, rsa)
+  community.crypto.openssh_keypair:
+    path: /tmp/id_ssh_rsa
+
+- name: Generate an OpenSSH keypair with the default values (4096 bits, rsa) and encrypted private key
+  community.crypto.openssh_keypair:
+    path: /tmp/id_ssh_rsa
+    passphrase: super_secret_password
+
+- name: Generate an OpenSSH rsa keypair with a different size (2048 bits)
+  community.crypto.openssh_keypair:
+    path: /tmp/id_ssh_rsa
+    size: 2048
+
+- name: Force regenerate an OpenSSH keypair if it already exists
+  community.crypto.openssh_keypair:
+    path: /tmp/id_ssh_rsa
+    force: True
+
+- name: Generate an OpenSSH keypair with a different algorithm (dsa)
+  community.crypto.openssh_keypair:
+    path: /tmp/id_ssh_dsa
+    type: dsa
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

comment

+

string

+

The comment of the generated key.

+

Returned: changed or success

+

Sample: "test@comment"

+
+

filename

+

string

+

Path to the generated SSH private key file.

+

Returned: changed or success

+

Sample: "/tmp/id_ssh_rsa"

+
+

fingerprint

+

string

+

The fingerprint of the key.

+

Returned: changed or success

+

Sample: "SHA256:r4YCZxihVjedH2OlfjVGI6Y5xAYtdCwk8VxKyzVyYfM"

+
+

public_key

+

string

+

The public key of the generated SSH private key.

+

Returned: changed or success

+

Sample: "ssh-rsa AAAAB3Nza(...omitted...)veL4E3Xcw=="

+
+

size

+

integer

+

Size (in bits) of the SSH private key.

+

Returned: changed or success

+

Sample: 4096

+
+

type

+

string

+

Algorithm used to generate the SSH private key.

+

Returned: changed or success

+

Sample: "rsa"

+
+
+

Authors

+
    +
  • David Kainz (@lolcube)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_certificate_info_module.html b/pr/558/openssl_certificate_info_module.html new file mode 100644 index 00000000..8d90eeac --- /dev/null +++ b/pr/558/openssl_certificate_info_module.html @@ -0,0 +1,180 @@ + + + + + + + community.crypto.openssl_certificate_info — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_certificate_info

+
+

Note

+

This plugin was part of the community.crypto collection (version 2.10.0).

+
+

This module has been removed +in version 2.0.0 of community.crypto. +The ‘community.crypto.openssl_certificate_info’ module has been renamed to ‘community.crypto.x509_certificate_info’

+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_certificate_module.html b/pr/558/openssl_certificate_module.html new file mode 100644 index 00000000..dcc53e0e --- /dev/null +++ b/pr/558/openssl_certificate_module.html @@ -0,0 +1,180 @@ + + + + + + + community.crypto.openssl_certificate — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_certificate

+
+

Note

+

This plugin was part of the community.crypto collection (version 2.10.0).

+
+

This module has been removed +in version 2.0.0 of community.crypto. +The ‘community.crypto.openssl_certificate’ module has been renamed to ‘community.crypto.x509_certificate’

+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_csr_info_module.html b/pr/558/openssl_csr_info_module.html new file mode 100644 index 00000000..e6d3c53a --- /dev/null +++ b/pr/558/openssl_csr_info_module.html @@ -0,0 +1,718 @@ + + + + + + + community.crypto.openssl_csr_info module – Provide information of OpenSSL Certificate Signing Requests (CSR) — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_csr_info module – Provide information of OpenSSL Certificate Signing Requests (CSR)

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_csr_info.

+
+ +
+

Synopsis

+
    +
  • This module allows one to query information on OpenSSL Certificate Signing Requests (CSR).

  • +
  • In case the CSR signature cannot be validated, the module will fail. In this case, all return variables are still returned.

  • +
  • It uses the cryptography python library to interact with OpenSSL.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • If name_encoding is set to another value than ignore, the idna Python library needs to be installed.

  • +
  • cryptography >= 1.3

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

content

+

string

+

added in community.crypto 1.0.0

+

Content of the CSR file.

+

Either path or content must be specified, but not both.

+
+

name_encoding

+

string

+

How to encode names (DNS names, URIs, email addresses) in return values.

+

ignore will use the encoding returned by the backend.

+

idna will convert all labels of domain names to IDNA encoding. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 encoding fails.

+

unicode will convert all labels of domain names to Unicode. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 decoding fails.

+

Note that idna and unicode require the idna Python library to be installed.

+

Choices:

+
    +
  • "ignore" ← (default)

  • +
  • "idna"

  • +
  • "unicode"

  • +
+
+

path

+

path

+

Remote absolute path where the CSR file is loaded from.

+

Either path or content must be specified, but not both.

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL Certificate Signing Request
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    common_name: www.ansible.com
+
+- name: Get information on the CSR
+  community.crypto.openssl_csr_info:
+    path: /etc/ssl/csr/www.ansible.com.csr
+  register: result
+
+- name: Dump information
+  debug:
+    var: result
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

authority_cert_issuer

+

list / elements=string

+

The CSR’s authority cert issuer as a list of general names.

+

Is none if the AuthorityKeyIdentifier extension is not present.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]

+
+

authority_cert_serial_number

+

integer

+

The CSR’s authority cert serial number.

+

Is none if the AuthorityKeyIdentifier extension is not present.

+

Returned: success

+

Sample: 12345

+
+

authority_key_identifier

+

string

+

The CSR’s authority key identifier.

+

The identifier is returned in hexadecimal, with : used to separate bytes.

+

Is none if the AuthorityKeyIdentifier extension is not present.

+

Returned: success

+

Sample: "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33"

+
+

basic_constraints

+

list / elements=string

+

Entries in the basic_constraints extension, or none if extension is not present.

+

Returned: success

+

Sample: ["CA:TRUE", "pathlen:1"]

+
+

basic_constraints_critical

+

boolean

+

Whether the basic_constraints extension is critical.

+

Returned: success

+
+

extended_key_usage

+

list / elements=string

+

Entries in the extended_key_usage extension, or none if extension is not present.

+

Returned: success

+

Sample: ["Biometric Info", "DVCS", "Time Stamping"]

+
+

extended_key_usage_critical

+

boolean

+

Whether the extended_key_usage extension is critical.

+

Returned: success

+
+

extensions_by_oid

+

dictionary

+

Returns a dictionary for every extension OID

+

Returned: success

+

Sample: {"1.3.6.1.5.5.7.1.24": {"critical": false, "value": "MAMCAQU="}}

+
+

critical

+

boolean

+

Whether the extension is critical.

+

Returned: success

+
+

value

+

string

+

The Base64 encoded value (in DER format) of the extension.

+

Note that depending on the cryptography version used, it is not possible to extract the ASN.1 content of the extension, but only to provide the re-encoded content of the extension in case it was parsed by cryptography. This should usually result in exactly the same value, except if the original extension value was malformed.

+

Returned: success

+

Sample: "MAMCAQU="

+
+

key_usage

+

string

+

Entries in the key_usage extension, or none if extension is not present.

+

Returned: success

+

Sample: "['Key Agreement', 'Data Encipherment']"

+
+

key_usage_critical

+

boolean

+

Whether the key_usage extension is critical.

+

Returned: success

+
+

name_constraints_critical

+

boolean

+

added in community.crypto 1.1.0

+

Whether the name_constraints extension is critical.

+

Is none if extension is not present.

+

Returned: success

+
+

name_constraints_excluded

+

list / elements=string

+

added in community.crypto 1.1.0

+

List of excluded subtrees the CA cannot sign certificates for.

+

Is none if extension is not present.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["email:.com"]

+
+

name_constraints_permitted

+

list / elements=string

+

added in community.crypto 1.1.0

+

List of permitted subtrees to sign certificates for.

+

Returned: success

+

Sample: ["email:.somedomain.com"]

+
+

ocsp_must_staple

+

boolean

+

true if the OCSP Must Staple extension is present, none otherwise.

+

Returned: success

+
+

ocsp_must_staple_critical

+

boolean

+

Whether the ocsp_must_staple extension is critical.

+

Returned: success

+
+

public_key

+

string

+

CSR’s public key in PEM format

+

Returned: success

+

Sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."

+
+

public_key_data

+

dictionary

+

added in community.crypto 1.7.0

+

Public key data. Depends on the public key’s type.

+

Returned: success

+
+

curve

+

string

+

The curve’s name for ECC.

+

Returned: When public_key_type=ECC

+
+

exponent

+

integer

+

The RSA key’s public exponent.

+

Returned: When public_key_type=RSA

+
+

exponent_size

+

integer

+

The maximum number of bits of a private key. This is basically the bit size of the subgroup used.

+

Returned: When public_key_type=ECC

+
+

g

+

integer

+

The g value for DSA.

+

This is the element spanning the subgroup of the multiplicative group of the prime field used.

+

Returned: When public_key_type=DSA

+
+

modulus

+

integer

+

The RSA key’s modulus.

+

Returned: When public_key_type=RSA

+
+

p

+

integer

+

The p value for DSA.

+

This is the prime modulus upon which arithmetic takes place.

+

Returned: When public_key_type=DSA

+
+

q

+

integer

+

The q value for DSA.

+

This is a prime that divides p - 1, and at the same time the order of the subgroup of the multiplicative group of the prime field used.

+

Returned: When public_key_type=DSA

+
+

size

+

integer

+

Bit size of modulus (RSA) or prime number (DSA).

+

Returned: When public_key_type=RSA or public_key_type=DSA

+
+

x

+

integer

+

The x coordinate for the public point on the elliptic curve.

+

Returned: When public_key_type=ECC

+
+

y

+

integer

+

For public_key_type=ECC, this is the y coordinate for the public point on the elliptic curve.

+

For public_key_type=DSA, this is the publicly known group element whose discrete logarithm w.r.t. g is the private key.

+

Returned: When public_key_type=DSA or public_key_type=ECC

+
+

public_key_fingerprints

+

dictionary

+

Fingerprints of CSR’s public key.

+

For every hash algorithm available, the fingerprint is computed.

+

Returned: success

+

Sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63', 'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."

+
+

public_key_type

+

string

+

added in community.crypto 1.7.0

+

The CSR’s public key’s type.

+

One of RSA, DSA, ECC, Ed25519, X25519, Ed448, or X448.

+

Will start with unknown if the key type cannot be determined.

+

Returned: success

+

Sample: "RSA"

+
+

signature_valid

+

boolean

+

Whether the CSR’s signature is valid.

+

In case the check returns false, the module will fail.

+

Returned: success

+
+

subject

+

dictionary

+

The CSR’s subject as a dictionary.

+

Note that for repeated values, only the last one will be returned.

+

Returned: success

+

Sample: {"commonName": "www.example.com", "emailAddress": "test@example.com"}

+
+

subject_alt_name

+

list / elements=string

+

Entries in the subject_alt_name extension, or none if extension is not present.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]

+
+

subject_alt_name_critical

+

boolean

+

Whether the subject_alt_name extension is critical.

+

Returned: success

+
+

subject_key_identifier

+

string

+

The CSR’s subject key identifier.

+

The identifier is returned in hexadecimal, with : used to separate bytes.

+

Is none if the SubjectKeyIdentifier extension is not present.

+

Returned: success

+

Sample: "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33"

+
+

subject_ordered

+

list / elements=list

+

The CSR’s subject as an ordered list of tuples.

+

Returned: success

+

Sample: [["commonName", "www.example.com"], [{"emailAddress": "test@example.com"}]]

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
  • Yanis Guenane (@Spredzy)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_csr_module.html b/pr/558/openssl_csr_module.html new file mode 100644 index 00000000..a8edb7c6 --- /dev/null +++ b/pr/558/openssl_csr_module.html @@ -0,0 +1,1130 @@ + + + + + + + community.crypto.openssl_csr module – Generate OpenSSL Certificate Signing Request (CSR) — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_csr module – Generate OpenSSL Certificate Signing Request (CSR)

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_csr.

+
+ +
+

Synopsis

+
    +
  • Please note that the module regenerates an existing CSR if it does not match the module’s options, or if it seems to be corrupt. If you are concerned that this could overwrite your existing CSR, consider using the backup option.

  • +
  • This module allows one to (re)generate OpenSSL certificate signing requests.

  • +
  • This module supports the subjectAltName, keyUsage, extendedKeyUsage, basicConstraints and OCSP Must Staple extensions.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.3

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

authority_cert_issuer

+

list / elements=string

+

Names that will be present in the authority cert issuer field of the certificate signing request.

+

Values must be prefixed by their options. (i.e., email, URI, DNS, RID, IP, dirName, otherName and the ones specific to your CA)

+

Example: DNS:ca.example.org

+

If specified, authority_cert_serial_number must also be specified.

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this is only supported if the cryptography backend is used!

+

The AuthorityKeyIdentifier extension will only be added if at least one of authority_key_identifier, authority_cert_issuer and authority_cert_serial_number is specified.

+
+

authority_cert_serial_number

+

integer

+

The authority cert serial number.

+

If specified, authority_cert_issuer must also be specified.

+

Note that this is only supported if the cryptography backend is used!

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

The AuthorityKeyIdentifier extension will only be added if at least one of authority_key_identifier, authority_cert_issuer and authority_cert_serial_number is specified.

+
+

authority_key_identifier

+

string

+

The authority key identifier as a hex string, where two bytes are separated by colons.

+

Example: 00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this is only supported if the cryptography backend is used!

+

The AuthorityKeyIdentifier extension will only be added if at least one of authority_key_identifier, authority_cert_issuer and authority_cert_serial_number is specified.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original CSR back if you overwrote it with a new one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

basic_constraints

+

aliases: basicConstraints

+

list / elements=string

+

Indicates basic constraints, such as if the certificate is a CA.

+
+
+

basic_constraints_critical

+

aliases: basicConstraints_critical

+

boolean

+

Should the basicConstraints extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

common_name

+

aliases: CN, commonName

+

string

+

The commonName field of the certificate signing request subject.

+
+
+
+

country_name

+

aliases: C, countryName

+

string

+

The countryName field of the certificate signing request subject.

+
+

create_subject_key_identifier

+

boolean

+

Create the Subject Key Identifier from the public key.

+

Please note that commercial CAs can ignore the value, respectively use a value of their own choice instead. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

crl_distribution_points

+

list / elements=dictionary

+

added in community.crypto 1.4.0

+

Allows to specify one or multiple CRL distribution points.

+

Only supported by the cryptography backend.

+
+

crl_issuer

+

list / elements=string

+

Information about the issuer of the CRL.

+
+

full_name

+

list / elements=string

+

Describes how the CRL can be retrieved.

+

Mutually exclusive with relative_name.

+

Example: URI:https://ca.example.com/revocations.crl.

+
+

reasons

+

list / elements=string

+

List of reasons that this distribution point can be used for when performing revocation checks.

+

Choices:

+
    +
  • "key_compromise"

  • +
  • "ca_compromise"

  • +
  • "affiliation_changed"

  • +
  • "superseded"

  • +
  • "cessation_of_operation"

  • +
  • "certificate_hold"

  • +
  • "privilege_withdrawn"

  • +
  • "aa_compromise"

  • +
+
+

relative_name

+

list / elements=string

+

Describes how the CRL can be retrieved relative to the CRL issuer.

+

Mutually exclusive with full_name.

+

Example: /CN=example.com.

+

Can only be used when cryptography >= 1.6 is installed.

+
+

digest

+

string

+

The digest used when signing the certificate signing request with the private key.

+

Default: "sha256"

+
+
+
+

email_address

+

aliases: E, emailAddress

+

string

+

The emailAddress field of the certificate signing request subject.

+
+
+
+

extended_key_usage

+

aliases: extKeyUsage, extendedKeyUsage

+

list / elements=string

+

Additional restrictions (for example client authentication, server authentication) on the allowed purposes for which the public key may be used.

+
+
+
+

extended_key_usage_critical

+

aliases: extKeyUsage_critical, extendedKeyUsage_critical

+

boolean

+

Should the extkeyUsage extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

force

+

boolean

+

Should the certificate signing request be forced regenerated by this ansible module.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+
+

key_usage

+

aliases: keyUsage

+

list / elements=string

+

This defines the purpose (for example encipherment, signature, certificate signing) of the key contained in the certificate.

+
+
+

key_usage_critical

+

aliases: keyUsage_critical

+

boolean

+

Should the keyUsage extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

locality_name

+

aliases: L, localityName

+

string

+

The localityName field of the certificate signing request subject.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

name_constraints_critical

+

boolean

+

added in community.crypto 1.1.0

+

Should the Name Constraints extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

name_constraints_excluded

+

list / elements=string

+

added in community.crypto 1.1.0

+

For CA certificates, this specifies a list of identifiers which describe subtrees of names that this CA is not allowed to issue certificates for.

+

Values must be prefixed by their options. (i.e., email, URI, DNS, RID, IP, dirName, otherName and the ones specific to your CA).

+
+

name_constraints_permitted

+

list / elements=string

+

added in community.crypto 1.1.0

+

For CA certificates, this specifies a list of identifiers which describe subtrees of names that this CA is allowed to issue certificates for.

+

Values must be prefixed by their options. (i.e., email, URI, DNS, RID, IP, dirName, otherName and the ones specific to your CA).

+
+
+

ocsp_must_staple

+

aliases: ocspMustStaple

+

boolean

+

Indicates that the certificate should contain the OCSP Must Staple extension (https://tools.ietf.org/html/rfc7633).

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

ocsp_must_staple_critical

+

aliases: ocspMustStaple_critical

+

boolean

+

Should the OCSP Must Staple extension be considered as critical.

+

Note that according to the RFC, this extension should not be marked as critical, as old clients not knowing about OCSP Must Staple are required to reject such certificates (see https://tools.ietf.org/html/rfc7633#section-4).

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

organization_name

+

aliases: O, organizationName

+

string

+

The organizationName field of the certificate signing request subject.

+
+
+
+

organizational_unit_name

+

aliases: OU, organizationalUnitName

+

string

+

The organizationalUnitName field of the certificate signing request subject.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

path

+

path / required

+

The name of the file into which the generated OpenSSL certificate signing request will be written.

+
+

privatekey_content

+

string

+

added in community.crypto 1.0.0

+

The content of the private key to use when signing the certificate signing request.

+

Either privatekey_path or privatekey_content must be specified if state is present, but not both.

+
+

privatekey_passphrase

+

string

+

The passphrase for the private key.

+

This is required if the private key is password protected.

+
+

privatekey_path

+

path

+

The path to the private key to use when signing the certificate signing request.

+

Either privatekey_path or privatekey_content must be specified if state is present, but not both.

+
+

return_content

+

boolean

+

added in community.crypto 1.0.0

+

If set to true, will return the (current or generated) CSR’s content as csr.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

state

+

string

+

Whether the certificate signing request should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+
+
+

state_or_province_name

+

aliases: ST, stateOrProvinceName

+

string

+

The stateOrProvinceName field of the certificate signing request subject.

+
+

subject

+

dictionary

+

Key/value pairs that will be present in the subject name field of the certificate signing request.

+

If you need to specify more than one value with the same key, use a list as value.

+

If the order of the components is important, use subject_ordered.

+

Mutually exclusive with subject_ordered.

+
+
+

subject_alt_name

+

aliases: subjectAltName

+

list / elements=string

+

Subject Alternative Name (SAN) extension to attach to the certificate signing request.

+

Values must be prefixed by their options. (These are email, URI, DNS, RID, IP, dirName, otherName, and the ones specific to your CA).

+

Note that if no SAN is specified, but a common name, the common name will be added as a SAN except if useCommonNameForSAN is set to false.

+

More at https://tools.ietf.org/html/rfc5280#section-4.2.1.6.

+
+
+

subject_alt_name_critical

+

aliases: subjectAltName_critical

+

boolean

+

Should the subjectAltName extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

subject_key_identifier

+

string

+

The subject key identifier as a hex string, where two bytes are separated by colons.

+

Example: 00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this option can only be used if create_subject_key_identifier is false.

+

Note that this is only supported if the cryptography backend is used!

+
+

subject_ordered

+

list / elements=dictionary

+

added in community.crypto 2.0.0

+

A list of dictionaries, where every dictionary must contain one key/value pair. This key/value pair will be present in the subject name field of the certificate signing request.

+

If you want to specify more than one value with the same key in a row, you can use a list as value.

+

Mutually exclusive with subject, and any other subject field option, such as country_name, state_or_province_name, locality_name, organization_name, organizational_unit_name, common_name, or email_address.

+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

use_common_name_for_san

+

aliases: useCommonNameForSAN

+

boolean

+

If set to true, the module will fill the common name in for subject_alt_name with DNS: prefix if no SAN is specified.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

version

+

integer

+

The version of the certificate signing request.

+

The only allowed value according to RFC 2986 is 1.

+

This option no longer accepts unsupported values since community.crypto 2.0.0.

+

Choices:

+
    +
  • 1 ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Notes

+
+

Note

+
    +
  • If the certificate signing request already exists it will be checked whether subjectAltName, keyUsage, extendedKeyUsage and basicConstraints only contain the requested values, whether OCSP Must Staple is as requested, and if the request was signed by the given private key.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
community.crypto.openssl_csr_info

Provide information of OpenSSL Certificate Signing Requests (CSR).

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL Certificate Signing Request
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    common_name: www.ansible.com
+
+- name: Generate an OpenSSL Certificate Signing Request with an inline key
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_content: "{{ private_key_content }}"
+    common_name: www.ansible.com
+
+- name: Generate an OpenSSL Certificate Signing Request with a passphrase protected private key
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    privatekey_passphrase: ansible
+    common_name: www.ansible.com
+
+- name: Generate an OpenSSL Certificate Signing Request with Subject information
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    country_name: FR
+    organization_name: Ansible
+    email_address: jdoe@ansible.com
+    common_name: www.ansible.com
+
+- name: Generate an OpenSSL Certificate Signing Request with subjectAltName extension
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    subject_alt_name: 'DNS:www.ansible.com,DNS:m.ansible.com'
+
+- name: Generate an OpenSSL CSR with subjectAltName extension with dynamic list
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    subject_alt_name: "{{ item.value | map('regex_replace', '^', 'DNS:') | list }}"
+  with_dict:
+    dns_server:
+    - www.ansible.com
+    - m.ansible.com
+
+- name: Force regenerate an OpenSSL Certificate Signing Request
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    force: true
+    common_name: www.ansible.com
+
+- name: Generate an OpenSSL Certificate Signing Request with special key usages
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    common_name: www.ansible.com
+    key_usage:
+      - digitalSignature
+      - keyAgreement
+    extended_key_usage:
+      - clientAuth
+
+- name: Generate an OpenSSL Certificate Signing Request with OCSP Must Staple
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    common_name: www.ansible.com
+    ocsp_must_staple: true
+
+- name: Generate an OpenSSL Certificate Signing Request for WinRM Certificate authentication
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/winrm.auth.csr
+    privatekey_path: /etc/ssl/private/winrm.auth.pem
+    common_name: username
+    extended_key_usage:
+    - clientAuth
+    subject_alt_name: otherName:1.3.6.1.4.1.311.20.2.3;UTF8:username@localhost
+
+- name: Generate an OpenSSL Certificate Signing Request with a CRL distribution point
+  community.crypto.openssl_csr:
+    path: /etc/ssl/csr/www.ansible.com.csr
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    common_name: www.ansible.com
+    crl_distribution_points:
+      - full_name:
+          - "URI:https://ca.example.com/revocations.crl"
+        crl_issuer:
+          - "URI:https://ca.example.com/"
+        reasons:
+          - key_compromise
+          - ca_compromise
+          - cessation_of_operation
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/www.ansible.com.csr.2019-03-09@11:22~"

+
+

basicConstraints

+

list / elements=string

+

Indicates if the certificate belongs to a CA

+

Returned: changed or success

+

Sample: ["CA:TRUE", "pathLenConstraint:0"]

+
+

csr

+

string

+

added in community.crypto 1.0.0

+

The (current or generated) CSR’s content.

+

Returned: if state is present and return_content is true

+
+

extendedKeyUsage

+

list / elements=string

+

Additional restriction on the public key purposes

+

Returned: changed or success

+

Sample: ["clientAuth"]

+
+

filename

+

string

+

Path to the generated Certificate Signing Request

+

Returned: changed or success

+

Sample: "/etc/ssl/csr/www.ansible.com.csr"

+
+

keyUsage

+

list / elements=string

+

Purpose for which the public key may be used

+

Returned: changed or success

+

Sample: ["digitalSignature", "keyAgreement"]

+
+

name_constraints_excluded

+

list / elements=string

+

added in community.crypto 1.1.0

+

List of excluded subtrees the CA cannot sign certificates for.

+

Returned: changed or success

+

Sample: ["email:.com"]

+
+

name_constraints_permitted

+

list / elements=string

+

added in community.crypto 1.1.0

+

List of permitted subtrees to sign certificates for.

+

Returned: changed or success

+

Sample: ["email:.somedomain.com"]

+
+

ocsp_must_staple

+

boolean

+

Indicates whether the certificate has the OCSP Must Staple feature enabled

+

Returned: changed or success

+

Sample: false

+
+

privatekey

+

string

+

Path to the TLS/SSL private key the CSR was generated for

+

Will be none if the private key has been provided in privatekey_content.

+

Returned: changed or success

+

Sample: "/etc/ssl/private/ansible.com.pem"

+
+

subject

+

list / elements=list

+

A list of the subject tuples attached to the CSR

+

Returned: changed or success

+

Sample: [["CN", "www.ansible.com"], ["O", "Ansible"]]

+
+

subjectAltName

+

list / elements=string

+

The alternative names this CSR is valid for

+

Returned: changed or success

+

Sample: ["DNS:www.ansible.com", "DNS:m.ansible.com"]

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_csr_pipe_module.html b/pr/558/openssl_csr_pipe_module.html new file mode 100644 index 00000000..d9bc7796 --- /dev/null +++ b/pr/558/openssl_csr_pipe_module.html @@ -0,0 +1,886 @@ + + + + + + + community.crypto.openssl_csr_pipe module – Generate OpenSSL Certificate Signing Request (CSR) — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_csr_pipe module – Generate OpenSSL Certificate Signing Request (CSR)

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_csr_pipe.

+
+

New in community.crypto 1.3.0

+ +
+

Synopsis

+
    +
  • Please note that the module regenerates an existing CSR if it does not match the module’s options, or if it seems to be corrupt.

  • +
  • This module allows one to (re)generate OpenSSL certificate signing requests.

  • +
  • This module supports the subjectAltName, keyUsage, extendedKeyUsage, basicConstraints and OCSP Must Staple extensions.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.3

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

authority_cert_issuer

+

list / elements=string

+

Names that will be present in the authority cert issuer field of the certificate signing request.

+

Values must be prefixed by their options. (i.e., email, URI, DNS, RID, IP, dirName, otherName and the ones specific to your CA)

+

Example: DNS:ca.example.org

+

If specified, authority_cert_serial_number must also be specified.

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this is only supported if the cryptography backend is used!

+

The AuthorityKeyIdentifier extension will only be added if at least one of authority_key_identifier, authority_cert_issuer and authority_cert_serial_number is specified.

+
+

authority_cert_serial_number

+

integer

+

The authority cert serial number.

+

If specified, authority_cert_issuer must also be specified.

+

Note that this is only supported if the cryptography backend is used!

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

The AuthorityKeyIdentifier extension will only be added if at least one of authority_key_identifier, authority_cert_issuer and authority_cert_serial_number is specified.

+
+

authority_key_identifier

+

string

+

The authority key identifier as a hex string, where two bytes are separated by colons.

+

Example: 00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this is only supported if the cryptography backend is used!

+

The AuthorityKeyIdentifier extension will only be added if at least one of authority_key_identifier, authority_cert_issuer and authority_cert_serial_number is specified.

+
+
+

basic_constraints

+

aliases: basicConstraints

+

list / elements=string

+

Indicates basic constraints, such as if the certificate is a CA.

+
+
+

basic_constraints_critical

+

aliases: basicConstraints_critical

+

boolean

+

Should the basicConstraints extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

common_name

+

aliases: CN, commonName

+

string

+

The commonName field of the certificate signing request subject.

+
+

content

+

string

+

The existing CSR.

+
+
+
+

country_name

+

aliases: C, countryName

+

string

+

The countryName field of the certificate signing request subject.

+
+

create_subject_key_identifier

+

boolean

+

Create the Subject Key Identifier from the public key.

+

Please note that commercial CAs can ignore the value, respectively use a value of their own choice instead. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

crl_distribution_points

+

list / elements=dictionary

+

added in community.crypto 1.4.0

+

Allows to specify one or multiple CRL distribution points.

+

Only supported by the cryptography backend.

+
+

crl_issuer

+

list / elements=string

+

Information about the issuer of the CRL.

+
+

full_name

+

list / elements=string

+

Describes how the CRL can be retrieved.

+

Mutually exclusive with relative_name.

+

Example: URI:https://ca.example.com/revocations.crl.

+
+

reasons

+

list / elements=string

+

List of reasons that this distribution point can be used for when performing revocation checks.

+

Choices:

+
    +
  • "key_compromise"

  • +
  • "ca_compromise"

  • +
  • "affiliation_changed"

  • +
  • "superseded"

  • +
  • "cessation_of_operation"

  • +
  • "certificate_hold"

  • +
  • "privilege_withdrawn"

  • +
  • "aa_compromise"

  • +
+
+

relative_name

+

list / elements=string

+

Describes how the CRL can be retrieved relative to the CRL issuer.

+

Mutually exclusive with full_name.

+

Example: /CN=example.com.

+

Can only be used when cryptography >= 1.6 is installed.

+
+

digest

+

string

+

The digest used when signing the certificate signing request with the private key.

+

Default: "sha256"

+
+
+
+

email_address

+

aliases: E, emailAddress

+

string

+

The emailAddress field of the certificate signing request subject.

+
+
+
+

extended_key_usage

+

aliases: extKeyUsage, extendedKeyUsage

+

list / elements=string

+

Additional restrictions (for example client authentication, server authentication) on the allowed purposes for which the public key may be used.

+
+
+
+

extended_key_usage_critical

+

aliases: extKeyUsage_critical, extendedKeyUsage_critical

+

boolean

+

Should the extkeyUsage extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

key_usage

+

aliases: keyUsage

+

list / elements=string

+

This defines the purpose (for example encipherment, signature, certificate signing) of the key contained in the certificate.

+
+
+

key_usage_critical

+

aliases: keyUsage_critical

+

boolean

+

Should the keyUsage extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

locality_name

+

aliases: L, localityName

+

string

+

The localityName field of the certificate signing request subject.

+
+

name_constraints_critical

+

boolean

+

Should the Name Constraints extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

name_constraints_excluded

+

list / elements=string

+

For CA certificates, this specifies a list of identifiers which describe subtrees of names that this CA is not allowed to issue certificates for.

+

Values must be prefixed by their options. (i.e., email, URI, DNS, RID, IP, dirName, otherName and the ones specific to your CA).

+
+

name_constraints_permitted

+

list / elements=string

+

For CA certificates, this specifies a list of identifiers which describe subtrees of names that this CA is allowed to issue certificates for.

+

Values must be prefixed by their options. (i.e., email, URI, DNS, RID, IP, dirName, otherName and the ones specific to your CA).

+
+
+

ocsp_must_staple

+

aliases: ocspMustStaple

+

boolean

+

Indicates that the certificate should contain the OCSP Must Staple extension (https://tools.ietf.org/html/rfc7633).

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

ocsp_must_staple_critical

+

aliases: ocspMustStaple_critical

+

boolean

+

Should the OCSP Must Staple extension be considered as critical.

+

Note that according to the RFC, this extension should not be marked as critical, as old clients not knowing about OCSP Must Staple are required to reject such certificates (see https://tools.ietf.org/html/rfc7633#section-4).

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

organization_name

+

aliases: O, organizationName

+

string

+

The organizationName field of the certificate signing request subject.

+
+
+
+

organizational_unit_name

+

aliases: OU, organizationalUnitName

+

string

+

The organizationalUnitName field of the certificate signing request subject.

+
+

privatekey_content

+

string

+

The content of the private key to use when signing the certificate signing request.

+

Either privatekey_path or privatekey_content must be specified if state is present, but not both.

+
+

privatekey_passphrase

+

string

+

The passphrase for the private key.

+

This is required if the private key is password protected.

+
+

privatekey_path

+

path

+

The path to the private key to use when signing the certificate signing request.

+

Either privatekey_path or privatekey_content must be specified if state is present, but not both.

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+
+
+

state_or_province_name

+

aliases: ST, stateOrProvinceName

+

string

+

The stateOrProvinceName field of the certificate signing request subject.

+
+

subject

+

dictionary

+

Key/value pairs that will be present in the subject name field of the certificate signing request.

+

If you need to specify more than one value with the same key, use a list as value.

+

If the order of the components is important, use subject_ordered.

+

Mutually exclusive with subject_ordered.

+
+
+

subject_alt_name

+

aliases: subjectAltName

+

list / elements=string

+

Subject Alternative Name (SAN) extension to attach to the certificate signing request.

+

Values must be prefixed by their options. (These are email, URI, DNS, RID, IP, dirName, otherName, and the ones specific to your CA).

+

Note that if no SAN is specified, but a common name, the common name will be added as a SAN except if useCommonNameForSAN is set to false.

+

More at https://tools.ietf.org/html/rfc5280#section-4.2.1.6.

+
+
+

subject_alt_name_critical

+

aliases: subjectAltName_critical

+

boolean

+

Should the subjectAltName extension be considered as critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

subject_key_identifier

+

string

+

The subject key identifier as a hex string, where two bytes are separated by colons.

+

Example: 00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33

+

Please note that commercial CAs ignore this value, respectively use a value of their own choice. Specifying this option is mostly useful for self-signed certificates or for own CAs.

+

Note that this option can only be used if create_subject_key_identifier is false.

+

Note that this is only supported if the cryptography backend is used!

+
+

subject_ordered

+

list / elements=dictionary

+

added in community.crypto 2.0.0

+

A list of dictionaries, where every dictionary must contain one key/value pair. This key/value pair will be present in the subject name field of the certificate signing request.

+

If you want to specify more than one value with the same key in a row, you can use a list as value.

+

Mutually exclusive with subject, and any other subject field option, such as country_name, state_or_province_name, locality_name, organization_name, organizational_unit_name, common_name, or email_address.

+
+
+

use_common_name_for_san

+

aliases: useCommonNameForSAN

+

boolean

+

If set to true, the module will fill the common name in for subject_alt_name with DNS: prefix if no SAN is specified.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

version

+

integer

+

The version of the certificate signing request.

+

The only allowed value according to RFC 2986 is 1.

+

This option no longer accepts unsupported values since community.crypto 2.0.0.

+

Choices:

+
    +
  • 1 ← (default)

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • If the certificate signing request already exists it will be checked whether subjectAltName, keyUsage, extendedKeyUsage and basicConstraints only contain the requested values, whether OCSP Must Staple is as requested, and if the request was signed by the given private key.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
community.crypto.openssl_csr_info

Provide information of OpenSSL Certificate Signing Requests (CSR).

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL Certificate Signing Request
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    common_name: www.ansible.com
+  register: result
+- debug:
+    var: result.csr
+
+- name: Generate an OpenSSL Certificate Signing Request with an inline CSR
+  community.crypto.openssl_csr:
+    content: "{{ lookup('file', '/etc/ssl/csr/www.ansible.com.csr') }}"
+    privatekey_content: "{{ private_key_content }}"
+    common_name: www.ansible.com
+  register: result
+- name: Store CSR
+  ansible.builtin.copy:
+    dest: /etc/ssl/csr/www.ansible.com.csr
+    content: "{{ result.csr }}"
+  when: result is changed
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

basicConstraints

+

list / elements=string

+

Indicates if the certificate belongs to a CA

+

Returned: changed or success

+

Sample: ["CA:TRUE", "pathLenConstraint:0"]

+
+

csr

+

string

+

The (current or generated) CSR’s content.

+

Returned: changed or success

+
+

extendedKeyUsage

+

list / elements=string

+

Additional restriction on the public key purposes

+

Returned: changed or success

+

Sample: ["clientAuth"]

+
+

keyUsage

+

list / elements=string

+

Purpose for which the public key may be used

+

Returned: changed or success

+

Sample: ["digitalSignature", "keyAgreement"]

+
+

name_constraints_excluded

+

list / elements=string

+

List of excluded subtrees the CA cannot sign certificates for.

+

Returned: changed or success

+

Sample: ["email:.com"]

+
+

name_constraints_permitted

+

list / elements=string

+

List of permitted subtrees to sign certificates for.

+

Returned: changed or success

+

Sample: ["email:.somedomain.com"]

+
+

ocsp_must_staple

+

boolean

+

Indicates whether the certificate has the OCSP Must Staple feature enabled

+

Returned: changed or success

+

Sample: false

+
+

privatekey

+

string

+

Path to the TLS/SSL private key the CSR was generated for

+

Will be none if the private key has been provided in privatekey_content.

+

Returned: changed or success

+

Sample: "/etc/ssl/private/ansible.com.pem"

+
+

subject

+

list / elements=list

+

A list of the subject tuples attached to the CSR

+

Returned: changed or success

+

Sample: [["CN", "www.ansible.com"], ["O", "Ansible"]]

+
+

subjectAltName

+

list / elements=string

+

The alternative names this CSR is valid for

+

Returned: changed or success

+

Sample: ["DNS:www.ansible.com", "DNS:m.ansible.com"]

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_dhparam_module.html b/pr/558/openssl_dhparam_module.html new file mode 100644 index 00000000..74a64722 --- /dev/null +++ b/pr/558/openssl_dhparam_module.html @@ -0,0 +1,549 @@ + + + + + + + community.crypto.openssl_dhparam module – Generate OpenSSL Diffie-Hellman Parameters — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_dhparam module – Generate OpenSSL Diffie-Hellman Parameters

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_dhparam.

+
+ +
+

Synopsis

+
    +
  • This module allows one to (re)generate OpenSSL DH-params.

  • +
  • This module uses file common arguments to specify generated file permissions.

  • +
  • Please note that the module regenerates existing DH params if they do not match the module’s options. If you are concerned that this could overwrite your existing DH params, consider using the backup option.

  • +
  • The module can use the cryptography Python library, or the openssl executable. By default, it tries to detect which one is available. This can be overridden with the select_crypto_backend option.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • Either cryptography >= 2.0

  • +
  • Or OpenSSL binary openssl

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original DH params back if you overwrote them with new ones by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

force

+

boolean

+

Should the parameters be regenerated even it it already exists.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

path

+

path / required

+

Name of the file in which the generated parameters will be saved.

+
+

return_content

+

boolean

+

added in community.crypto 1.0.0

+

If set to true, will return the (current or generated) DH parameter’s content as dhparams.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

added in community.crypto 1.0.0

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to openssl.

+

If set to openssl, will try to use the OpenSSL openssl executable.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "openssl"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

size

+

integer

+

Size (in bits) of the generated DH-params.

+

Default: 4096

+
+

state

+

string

+

Whether the parameters should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Generate Diffie-Hellman parameters with the default size (4096 bits)
+  community.crypto.openssl_dhparam:
+    path: /etc/ssl/dhparams.pem
+
+- name: Generate DH Parameters with a different size (2048 bits)
+  community.crypto.openssl_dhparam:
+    path: /etc/ssl/dhparams.pem
+    size: 2048
+
+- name: Force regenerate an DH parameters if they already exist
+  community.crypto.openssl_dhparam:
+    path: /etc/ssl/dhparams.pem
+    force: true
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/dhparams.pem.2019-03-09@11:22~"

+
+

dhparams

+

string

+

added in community.crypto 1.0.0

+

The (current or generated) DH params’ content.

+

Returned: if state is present and return_content is true

+
+

filename

+

string

+

Path to the generated Diffie-Hellman parameters.

+

Returned: changed or success

+

Sample: "/etc/ssl/dhparams.pem"

+
+

size

+

integer

+

Size (in bits) of the Diffie-Hellman parameters.

+

Returned: changed or success

+

Sample: 4096

+
+
+

Authors

+
    +
  • Thom Wiggers (@thomwiggers)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_pkcs12_module.html b/pr/558/openssl_pkcs12_module.html new file mode 100644 index 00000000..8c6616fe --- /dev/null +++ b/pr/558/openssl_pkcs12_module.html @@ -0,0 +1,717 @@ + + + + + + + community.crypto.openssl_pkcs12 module – Generate OpenSSL PKCS#12 archive — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_pkcs12 module – Generate OpenSSL PKCS#12 archive

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_pkcs12.

+
+ +
+

Synopsis

+
    +
  • This module allows one to (re-)generate PKCS#12.

  • +
  • The module can use the cryptography Python library, or the pyOpenSSL Python library. By default, it tries to detect which one is available, assuming none of the iter_size and maciter_size options are used. This can be overridden with the select_crypto_backend option.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • PyOpenSSL >= 0.15 or cryptography >= 3.0

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

action

+

string

+

export or parse a PKCS#12.

+

Choices:

+
    +
  • "export" ← (default)

  • +
  • "parse"

  • +
+
+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original output file back if you overwrote it with a new one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

certificate_path

+

path

+

The path to read certificates and private keys from.

+

Must be in PEM format.

+
+

encryption_level

+

string

+

added in community.crypto 2.8.0

+

Determines the encryption level used.

+

auto uses the default of the selected backend. For cryptography, this is what the cryptography library’s specific version considers the best available encryption.

+

compatibility2022 uses compatibility settings for older software in 2022. This is only supported by the cryptography backend if cryptography >= 38.0.0 is available.

+

Note that this option is not used for idempotency.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "compatibility2022"

  • +
+
+

force

+

boolean

+

Should the file be regenerated even if it already exists.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+

friendly_name

+

aliases: name

+

string

+

Specifies the friendly name for the certificate and private key.

+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

iter_size

+

integer

+

Number of times to repeat the encryption step.

+

This is not considered during idempotency checks.

+

This is only used by the pyopenssl backend, or when encryption_level=compatibility2022.

+

When using it, the default is 2048 for pyopenssl and 50000 for cryptography.

+
+

maciter_size

+

integer

+

Number of times to repeat the MAC step.

+

This is not considered during idempotency checks.

+

This is only used by the pyopenssl backend. When using it, the default is 1.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+
+

other_certificates

+

aliases: ca_certificates

+

list / elements=path

+

List of other certificates to include. Pre Ansible 2.8 this parameter was called ca_certificates.

+

Assumes there is one PEM-encoded certificate per file. If a file contains multiple PEM certificates, set other_certificates_parse_all to true.

+
+

other_certificates_parse_all

+

boolean

+

added in community.crypto 1.4.0

+

If set to true, assumes that the files mentioned in other_certificates can contain more than one certificate per file (or even none per file).

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

passphrase

+

string

+

The PKCS#12 password.

+

Note: PKCS12 encryption is not secure and should not be used as a security mechanism. If you need to store or send a PKCS12 file safely, you should additionally encrypt it with something else.

+
+

path

+

path / required

+

Filename to write the PKCS#12 file to.

+
+

privatekey_content

+

string

+

added in community.crypto 2.3.0

+

Content of the private key file.

+

Mutually exclusive with privatekey_path.

+
+

privatekey_passphrase

+

string

+

Passphrase source to decrypt any input private keys with.

+
+

privatekey_path

+

path

+

File to read private key from.

+

Mutually exclusive with privatekey_content.

+
+

return_content

+

boolean

+

added in community.crypto 1.0.0

+

If set to true, will return the (current or generated) PKCS#12’s content as pkcs12.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

added in community.crypto 1.7.0

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available, and falls back to pyopenssl. If iter_size is used together with encryption_level != compatibility2022, or if maciter_size is used, auto will always result in pyopenssl to be chosen for backwards compatibility.

+

If set to pyopenssl, will try to use the pyOpenSSL library.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
  • "pyopenssl"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

src

+

path

+

PKCS#12 file path to parse.

+
+

state

+

string

+

Whether the file should exist or not. All parameters except path are ignored when state is absent.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Generate PKCS#12 file
+  community.crypto.openssl_pkcs12:
+    action: export
+    path: /opt/certs/ansible.p12
+    friendly_name: raclette
+    privatekey_path: /opt/certs/keys/key.pem
+    certificate_path: /opt/certs/cert.pem
+    other_certificates: /opt/certs/ca.pem
+    # Note that if /opt/certs/ca.pem contains multiple certificates,
+    # only the first one will be used. See the other_certificates_parse_all
+    # option for changing this behavior.
+    state: present
+
+- name: Generate PKCS#12 file
+  community.crypto.openssl_pkcs12:
+    action: export
+    path: /opt/certs/ansible.p12
+    friendly_name: raclette
+    privatekey_content: '{{ private_key_contents }}'
+    certificate_path: /opt/certs/cert.pem
+    other_certificates_parse_all: true
+    other_certificates:
+      - /opt/certs/ca_bundle.pem
+        # Since we set other_certificates_parse_all to true, all
+        # certificates in the CA bundle are included and not just
+        # the first one.
+      - /opt/certs/intermediate.pem
+        # In case this file has multiple certificates in it,
+        # all will be included as well.
+    state: present
+
+- name: Change PKCS#12 file permission
+  community.crypto.openssl_pkcs12:
+    action: export
+    path: /opt/certs/ansible.p12
+    friendly_name: raclette
+    privatekey_path: /opt/certs/keys/key.pem
+    certificate_path: /opt/certs/cert.pem
+    other_certificates: /opt/certs/ca.pem
+    state: present
+    mode: '0600'
+
+- name: Regen PKCS#12 file
+  community.crypto.openssl_pkcs12:
+    action: export
+    src: /opt/certs/ansible.p12
+    path: /opt/certs/ansible.p12
+    friendly_name: raclette
+    privatekey_path: /opt/certs/keys/key.pem
+    certificate_path: /opt/certs/cert.pem
+    other_certificates: /opt/certs/ca.pem
+    state: present
+    mode: '0600'
+    force: true
+
+- name: Dump/Parse PKCS#12 file
+  community.crypto.openssl_pkcs12:
+    action: parse
+    src: /opt/certs/ansible.p12
+    path: /opt/certs/ansible.pem
+    state: present
+
+- name: Remove PKCS#12 file
+  community.crypto.openssl_pkcs12:
+    path: /opt/certs/ansible.p12
+    state: absent
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/ansible.com.pem.2019-03-09@11:22~"

+
+

filename

+

string

+

Path to the generate PKCS#12 file.

+

Returned: changed or success

+

Sample: "/opt/certs/ansible.p12"

+
+

pkcs12

+

string

+

added in community.crypto 1.0.0

+

The (current or generated) PKCS#12’s content Base64 encoded.

+

Returned: if state is present and return_content is true

+
+

privatekey

+

string

+

Path to the TLS/SSL private key the public key was generated from.

+

Returned: changed or success

+

Sample: "/etc/ssl/private/ansible.com.pem"

+
+
+

Authors

+
    +
  • Guillaume Delpierre (@gdelpierre)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_privatekey_convert_module.html b/pr/558/openssl_privatekey_convert_module.html new file mode 100644 index 00000000..fa15e9ea --- /dev/null +++ b/pr/558/openssl_privatekey_convert_module.html @@ -0,0 +1,491 @@ + + + + + + + community.crypto.openssl_privatekey_convert module – Convert OpenSSL private keys — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_privatekey_convert module – Convert OpenSSL private keys

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_privatekey_convert.

+
+

New in community.crypto 2.1.0

+ +
+

Synopsis

+
    +
  • This module allows one to convert OpenSSL private keys.

  • +
  • The default mode for the private key file will be 0600 if mode is not explicitly set.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.2.3 (older versions might work as well)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original private key back if you overwrote it with a new one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

dest_passphrase

+

string

+

The passphrase for the private key to store.

+
+

dest_path

+

path / required

+

Name of the file in which the generated TLS/SSL private key will be written. It will have 0600 mode if mode is not explicitly set.

+
+

format

+

string / required

+

Determines which format the destination private key should be written in.

+

Please note that not every key can be exported in any format, and that not every format supports encryption.

+

Choices:

+
    +
  • "pkcs1"

  • +
  • "pkcs8"

  • +
  • "raw"

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

src_content

+

string

+

The content of the file containing the OpenSSL private key to convert.

+

Exactly one of src_path or src_content must be specified.

+
+

src_passphrase

+

string

+

The passphrase for the private key to load.

+
+

src_path

+

path

+

Name of the file containing the OpenSSL private key to convert.

+

Exactly one of src_path or src_content must be specified.

+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Convert private key to PKCS8 format with passphrase
+  community.crypto.openssl_privatekey_convert:
+    src_path: /etc/ssl/private/ansible.com.pem
+    dest_path: /etc/ssl/private/ansible.com.key
+    dest_passphrase: '{{ private_key_passphrase }}'
+    format: pkcs8
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/privatekey.pem.2019-03-09@11:22~"

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_privatekey_info_module.html b/pr/558/openssl_privatekey_info_module.html new file mode 100644 index 00000000..e9bd94ba --- /dev/null +++ b/pr/558/openssl_privatekey_info_module.html @@ -0,0 +1,549 @@ + + + + + + + community.crypto.openssl_privatekey_info module – Provide information for OpenSSL private keys — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_privatekey_info module – Provide information for OpenSSL private keys

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_privatekey_info.

+
+ +
+

Synopsis

+
    +
  • This module allows one to query information on OpenSSL private keys.

  • +
  • In case the key consistency checks fail, the module will fail as this indicates a faked private key. In this case, all return variables are still returned. Note that key consistency checks are not available all key types; if none is available, none is returned for key_is_consistent.

  • +
  • It uses the cryptography python library to interact with OpenSSL.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.2.3

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

check_consistency

+

boolean

+

added in community.crypto 2.0.0

+

Whether to check consistency of the private key.

+

In community.crypto < 2.0.0, consistency was always checked.

+

Since community.crypto 2.0.0, the consistency check has been disabled by default to avoid private key material to be transported around and computed with, and only do so when requested explicitly. This can potentially prevent side-channel attacks.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

content

+

string

+

added in community.crypto 1.0.0

+

Content of the private key file.

+

Either path or content must be specified, but not both.

+
+

passphrase

+

string

+

The passphrase for the private key.

+
+

path

+

path

+

Remote absolute path where the private key file is loaded from.

+
+

return_private_key_data

+

boolean

+

Whether to return private key data.

+

Only set this to true when you want private information about this key to leave the remote machine.

+

WARNING: you have to make sure that private key data is not accidentally logged!

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+
+- name: Get information on generated key
+  community.crypto.openssl_privatekey_info:
+    path: /etc/ssl/private/ansible.com.pem
+  register: result
+
+- name: Dump information
+  ansible.builtin.debug:
+    var: result
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

can_load_key

+

boolean

+

Whether the module was able to load the private key from disk.

+

Returned: always

+
+

can_parse_key

+

boolean

+

Whether the module was able to parse the private key.

+

Returned: always

+
+

key_is_consistent

+

boolean

+

Whether the key is consistent. Can also return none next to true and false, to indicate that consistency could not be checked.

+

In case the check returns false, the module will fail.

+

Returned: when check_consistency=true

+
+

private_data

+

dictionary

+

Private key data. Depends on key type.

+

Returned: success and when return_private_key_data is set to true

+
+

public_data

+

dictionary

+

Public key data. Depends on key type.

+

Returned: success

+
+

curve

+

string

+

The curve’s name for ECC.

+

Returned: When type=ECC

+
+

exponent

+

integer

+

The RSA key’s public exponent.

+

Returned: When type=RSA

+
+

exponent_size

+

integer

+

The maximum number of bits of a private key. This is basically the bit size of the subgroup used.

+

Returned: When type=ECC

+
+

g

+

integer

+

The g value for DSA.

+

This is the element spanning the subgroup of the multiplicative group of the prime field used.

+

Returned: When type=DSA

+
+

modulus

+

integer

+

The RSA key’s modulus.

+

Returned: When type=RSA

+
+

p

+

integer

+

The p value for DSA.

+

This is the prime modulus upon which arithmetic takes place.

+

Returned: When type=DSA

+
+

q

+

integer

+

The q value for DSA.

+

This is a prime that divides p - 1, and at the same time the order of the subgroup of the multiplicative group of the prime field used.

+

Returned: When type=DSA

+
+

size

+

integer

+

Bit size of modulus (RSA) or prime number (DSA).

+

Returned: When type=RSA or type=DSA

+
+

x

+

integer

+

The x coordinate for the public point on the elliptic curve.

+

Returned: When type=ECC

+
+

y

+

integer

+

For type=ECC, this is the y coordinate for the public point on the elliptic curve.

+

For type=DSA, this is the publicly known group element whose discrete logarithm w.r.t. g is the private key.

+

Returned: When type=DSA or type=ECC

+
+

public_key

+

string

+

Private key’s public key in PEM format.

+

Returned: success

+

Sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."

+
+

public_key_fingerprints

+

dictionary

+

Fingerprints of private key’s public key.

+

For every hash algorithm available, the fingerprint is computed.

+

Returned: success

+

Sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63', 'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."

+
+

type

+

string

+

The key’s type.

+

One of RSA, DSA, ECC, Ed25519, X25519, Ed448, or X448.

+

Will start with unknown if the key type cannot be determined.

+

Returned: success

+

Sample: "RSA"

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
  • Yanis Guenane (@Spredzy)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_privatekey_module.html b/pr/558/openssl_privatekey_module.html new file mode 100644 index 00000000..46c9d903 --- /dev/null +++ b/pr/558/openssl_privatekey_module.html @@ -0,0 +1,717 @@ + + + + + + + community.crypto.openssl_privatekey module – Generate OpenSSL private keys — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_privatekey module – Generate OpenSSL private keys

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_privatekey.

+
+ +
+

Synopsis

+
    +
  • Keys are generated in PEM format.

  • +
  • One can generate RSA, DSA, ECC or EdDSA private keys.

  • +
  • Please note that the module regenerates private keys if they do not match the module’s options. In particular, if you provide another passphrase (or specify none), change the keysize, etc., the private key will be regenerated. If you are concerned that this could overwrite your private key, consider using the backup option.

  • +
  • The default mode for the private key file will be 0600 if mode is not explicitly set.

  • +
  • This module allows one to (re)generate OpenSSL private keys.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.2.3 (older versions might work as well)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original private key back if you overwrote it with a new one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

cipher

+

string

+

The cipher to encrypt the private key. Must be auto.

+
+

curve

+

string

+

Note that not all curves are supported by all versions of cryptography.

+

For maximal interoperability, secp384r1 or secp256r1 should be used.

+

We use the curve names as defined in the IANA registry for TLS.

+

Please note that all curves except secp224r1, secp256k1, secp256r1, secp384r1 and secp521r1 are discouraged for new private keys.

+

Choices:

+
    +
  • "secp224r1"

  • +
  • "secp256k1"

  • +
  • "secp256r1"

  • +
  • "secp384r1"

  • +
  • "secp521r1"

  • +
  • "secp192r1"

  • +
  • "brainpoolP256r1"

  • +
  • "brainpoolP384r1"

  • +
  • "brainpoolP512r1"

  • +
  • "sect163k1"

  • +
  • "sect163r2"

  • +
  • "sect233k1"

  • +
  • "sect233r1"

  • +
  • "sect283k1"

  • +
  • "sect283r1"

  • +
  • "sect409k1"

  • +
  • "sect409r1"

  • +
  • "sect571k1"

  • +
  • "sect571r1"

  • +
+
+

force

+

boolean

+

Should the key be regenerated even if it already exists.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

format

+

string

+

added in community.crypto 1.0.0

+

Determines which format the private key is written in. By default, PKCS1 (traditional OpenSSL format) is used for all keys which support it. Please note that not every key can be exported in any format.

+

The value auto selects a format based on the key format. The value auto_ignore does the same, but for existing private key files, it will not force a regenerate when its format is not the automatically selected one for generation.

+

Note that if the format for an existing private key mismatches, the key is regenerated by default. To change this behavior, use the format_mismatch option.

+

Choices:

+
    +
  • "pkcs1"

  • +
  • "pkcs8"

  • +
  • "raw"

  • +
  • "auto"

  • +
  • "auto_ignore" ← (default)

  • +
+
+

format_mismatch

+

string

+

added in community.crypto 1.0.0

+

Determines behavior of the module if the format of a private key does not match the expected format, but all other parameters are as expected.

+

If set to regenerate (default), generates a new private key.

+

If set to convert, the key will be converted to the new format instead.

+

Only supported by the cryptography backend.

+

Choices:

+
    +
  • "regenerate" ← (default)

  • +
  • "convert"

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

passphrase

+

string

+

The passphrase for the private key.

+
+

path

+

path / required

+

Name of the file in which the generated TLS/SSL private key will be written. It will have 0600 mode if mode is not explicitly set.

+
+

regenerate

+

string

+

added in community.crypto 1.0.0

+

Allows to configure in which situations the module is allowed to regenerate private keys. The module will always generate a new key if the destination file does not exist.

+

By default, the key will be regenerated when it does not match the module’s options, except when the key cannot be read or the passphrase does not match. Please note that this changed for Ansible 2.10. For Ansible 2.9, the behavior was as if full_idempotence is specified.

+

If set to never, the module will fail if the key cannot be read or the passphrase is not matching, and will never regenerate an existing key.

+

If set to fail, the module will fail if the key does not correspond to the module’s options.

+

If set to partial_idempotence, the key will be regenerated if it does not conform to the module’s options. The key is not regenerated if it cannot be read (broken file), the key is protected by an unknown passphrase, or when they key is not protected by a passphrase, but a passphrase is specified.

+

If set to full_idempotence, the key will be regenerated if it does not conform to the module’s options. This is also the case if the key cannot be read (broken file), the key is protected by an unknown passphrase, or when they key is not protected by a passphrase, but a passphrase is specified. Make sure you have a backup when using this option!

+

If set to always, the module will always regenerate the key. This is equivalent to setting force to true.

+

Note that if format_mismatch is set to convert and everything matches except the format, the key will always be converted, except if regenerate is set to always.

+

Choices:

+
    +
  • "never"

  • +
  • "fail"

  • +
  • "partial_idempotence"

  • +
  • "full_idempotence" ← (default)

  • +
  • "always"

  • +
+
+

return_content

+

boolean

+

added in community.crypto 1.0.0

+

If set to true, will return the (current or generated) private key’s content as privatekey.

+

Note that especially if the private key is not encrypted, you have to make sure that the returned value is treated appropriately and not accidentally written to logs etc.! Use with care!

+

Use Ansible’s no_log task option to avoid the output being shown. See also https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-keep-secret-data-in-my-playbook.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

size

+

integer

+

Size (in bits) of the TLS/SSL key to generate.

+

Default: 4096

+
+

state

+

string

+

Whether the private key should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+

type

+

string

+

The algorithm used to generate the TLS/SSL private key.

+

Note that ECC, X25519, X448, Ed25519 and Ed448 require the cryptography backend. X25519 needs cryptography 2.5 or newer, while X448, Ed25519 and Ed448 require cryptography 2.6 or newer. For ECC, the minimal cryptography version required depends on the curve option.

+

Choices:

+
    +
  • "DSA"

  • +
  • "ECC"

  • +
  • "Ed25519"

  • +
  • "Ed448"

  • +
  • "RSA" ← (default)

  • +
  • "X25519"

  • +
  • "X448"

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
community.crypto.openssl_privatekey_info

Provide information for OpenSSL private keys.

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+
+- name: Generate an OpenSSL private key with the default values (4096 bits, RSA) and a passphrase
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+    passphrase: ansible
+    cipher: auto
+
+- name: Generate an OpenSSL private key with a different size (2048 bits)
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+    size: 2048
+
+- name: Force regenerate an OpenSSL private key if it already exists
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+    force: true
+
+- name: Generate an OpenSSL private key with a different algorithm (DSA)
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+    type: DSA
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/privatekey.pem.2019-03-09@11:22~"

+
+

curve

+

string

+

Elliptic curve used to generate the TLS/SSL private key.

+

Returned: changed or success, and type is ECC

+

Sample: "secp256r1"

+
+

filename

+

string

+

Path to the generated TLS/SSL private key file.

+

Returned: changed or success

+

Sample: "/etc/ssl/private/ansible.com.pem"

+
+

fingerprint

+

dictionary

+

The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available.

+

Returned: changed or success

+

Sample: {"md5": "84:75:71:72:8d:04:b5:6c:4d:37:6d:66:83:f5:4c:29", "sha1": "51:cc:7c:68:5d:eb:41:43:88:7e:1a:ae:c7:f8:24:72:ee:71:f6:10", "sha224": "b1:19:a6:6c:14:ac:33:1d:ed:18:50:d3:06:5c:b2:32:91:f1:f1:52:8c:cb:d5:75:e9:f5:9b:46", "sha256": "41:ab:c7:cb:d5:5f:30:60:46:99:ac:d4:00:70:cf:a1:76:4f:24:5d:10:24:57:5d:51:6e:09:97:df:2f:de:c7", "sha384": "85:39:50:4e:de:d9:19:33:40:70:ae:10:ab:59:24:19:51:c3:a2:e4:0b:1c:b1:6e:dd:b3:0c:d9:9e:6a:46:af:da:18:f8:ef:ae:2e:c0:9a:75:2c:9b:b3:0f:3a:5f:3d", "sha512": "fd:ed:5e:39:48:5f:9f:fe:7f:25:06:3f:79:08:cd:ee:a5:e7:b3:3d:13:82:87:1f:84:e1:f5:c7:28:77:53:94:86:56:38:69:f0:d9:35:22:01:1e:a6:60:...:0f:9b"}

+
+

privatekey

+

string

+

added in community.crypto 1.0.0

+

The (current or generated) private key’s content.

+

Will be Base64-encoded if the key is in raw format.

+

Returned: if state is present and return_content is true

+
+

size

+

integer

+

Size (in bits) of the TLS/SSL private key.

+

Returned: changed or success

+

Sample: 4096

+
+

type

+

string

+

Algorithm used to generate the TLS/SSL private key.

+

Returned: changed or success

+

Sample: "RSA"

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_privatekey_pipe_module.html b/pr/558/openssl_privatekey_pipe_module.html new file mode 100644 index 00000000..a3eac128 --- /dev/null +++ b/pr/558/openssl_privatekey_pipe_module.html @@ -0,0 +1,600 @@ + + + + + + + community.crypto.openssl_privatekey_pipe module – Generate OpenSSL private keys without disk access — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_privatekey_pipe module – Generate OpenSSL private keys without disk access

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_privatekey_pipe.

+
+

New in community.crypto 1.3.0

+ +
+

Synopsis

+
    +
  • Keys are generated in PEM format.

  • +
  • Make sure to not write the result of this module into logs or to the console, as it contains private key data! Use the no_log task option to be sure.

  • +
  • Note that this module is implemented as an action plugin and will always be executed on the controller.

  • +
  • One can generate RSA, DSA, ECC or EdDSA private keys.

  • +
  • Please note that the module regenerates private keys if they do not match the module’s options. In particular, if you provide another passphrase (or specify none), change the keysize, etc., the private key will be regenerated. If you are concerned that this could overwrite your private key, consider using the backup option.

  • +
  • This allows to read and write keys to vaults without having to write intermediate versions to disk.

  • +
  • This module allows one to (re)generate OpenSSL private keys without disk access.

  • +
+
+

Note

+

This module has a corresponding action plugin.

+
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.2.3 (older versions might work as well)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

cipher

+

string

+

The cipher to encrypt the private key. Must be auto.

+
+

content

+

string

+

The current private key data.

+

Needed for idempotency. If not provided, the module will always return a change, and all idempotence-related options are ignored.

+
+

content_base64

+

boolean

+

Set to true if the content is base64 encoded.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

curve

+

string

+

Note that not all curves are supported by all versions of cryptography.

+

For maximal interoperability, secp384r1 or secp256r1 should be used.

+

We use the curve names as defined in the IANA registry for TLS.

+

Please note that all curves except secp224r1, secp256k1, secp256r1, secp384r1 and secp521r1 are discouraged for new private keys.

+

Choices:

+
    +
  • "secp224r1"

  • +
  • "secp256k1"

  • +
  • "secp256r1"

  • +
  • "secp384r1"

  • +
  • "secp521r1"

  • +
  • "secp192r1"

  • +
  • "brainpoolP256r1"

  • +
  • "brainpoolP384r1"

  • +
  • "brainpoolP512r1"

  • +
  • "sect163k1"

  • +
  • "sect163r2"

  • +
  • "sect233k1"

  • +
  • "sect233r1"

  • +
  • "sect283k1"

  • +
  • "sect283r1"

  • +
  • "sect409k1"

  • +
  • "sect409r1"

  • +
  • "sect571k1"

  • +
  • "sect571r1"

  • +
+
+

format

+

string

+

Determines which format the private key is written in. By default, PKCS1 (traditional OpenSSL format) is used for all keys which support it. Please note that not every key can be exported in any format.

+

The value auto selects a format based on the key format. The value auto_ignore does the same, but for existing private key files, it will not force a regenerate when its format is not the automatically selected one for generation.

+

Note that if the format for an existing private key mismatches, the key is regenerated by default. To change this behavior, use the format_mismatch option.

+

Choices:

+
    +
  • "pkcs1"

  • +
  • "pkcs8"

  • +
  • "raw"

  • +
  • "auto"

  • +
  • "auto_ignore" ← (default)

  • +
+
+

format_mismatch

+

string

+

Determines behavior of the module if the format of a private key does not match the expected format, but all other parameters are as expected.

+

If set to regenerate (default), generates a new private key.

+

If set to convert, the key will be converted to the new format instead.

+

Only supported by the cryptography backend.

+

Choices:

+
    +
  • "regenerate" ← (default)

  • +
  • "convert"

  • +
+
+

passphrase

+

string

+

The passphrase for the private key.

+
+

regenerate

+

string

+

Allows to configure in which situations the module is allowed to regenerate private keys. The module will always generate a new key if the destination file does not exist.

+

By default, the key will be regenerated when it does not match the module’s options, except when the key cannot be read or the passphrase does not match. Please note that this changed for Ansible 2.10. For Ansible 2.9, the behavior was as if full_idempotence is specified.

+

If set to never, the module will fail if the key cannot be read or the passphrase is not matching, and will never regenerate an existing key.

+

If set to fail, the module will fail if the key does not correspond to the module’s options.

+

If set to partial_idempotence, the key will be regenerated if it does not conform to the module’s options. The key is not regenerated if it cannot be read (broken file), the key is protected by an unknown passphrase, or when they key is not protected by a passphrase, but a passphrase is specified.

+

If set to full_idempotence, the key will be regenerated if it does not conform to the module’s options. This is also the case if the key cannot be read (broken file), the key is protected by an unknown passphrase, or when they key is not protected by a passphrase, but a passphrase is specified. Make sure you have a backup when using this option!

+

If set to always, the module will always regenerate the key. This is equivalent to setting force to true.

+

Note that if format_mismatch is set to convert and everything matches except the format, the key will always be converted, except if regenerate is set to always.

+

Choices:

+
    +
  • "never"

  • +
  • "fail"

  • +
  • "partial_idempotence"

  • +
  • "full_idempotence" ← (default)

  • +
  • "always"

  • +
+
+

return_current_key

+

boolean

+

Set to true to return the current private key when the module did not generate a new one.

+

Note that in case of check mode, when this option is not set to true, the module always returns the current key (if it was provided) and Ansible will replace it by VALUE_SPECIFIED_IN_NO_LOG_PARAMETER.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

size

+

integer

+

Size (in bits) of the TLS/SSL key to generate.

+

Default: 4096

+
+

type

+

string

+

The algorithm used to generate the TLS/SSL private key.

+

Note that ECC, X25519, X448, Ed25519 and Ed448 require the cryptography backend. X25519 needs cryptography 2.5 or newer, while X448, Ed25519 and Ed448 require cryptography 2.6 or newer. For ECC, the minimal cryptography version required depends on the curve option.

+

Choices:

+
    +
  • "DSA"

  • +
  • "ECC"

  • +
  • "Ed25519"

  • +
  • "Ed448"

  • +
  • "RSA" ← (default)

  • +
  • "X25519"

  • +
  • "X448"

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

action

+

Support: full

+

Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller.

+
+

async

+

Support: none

+

This action runs completely on the controller.

+

Supports being used with the async keyword.

+
+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_info

Provide information for OpenSSL private keys.

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
+  community.crypto.openssl_privatekey_pipe:
+    path: /etc/ssl/private/ansible.com.pem
+  register: output
+  no_log: true  # make sure that private key data is not accidentally revealed in logs!
+- name: Show generated key
+  debug:
+    msg: "{{ output.privatekey }}"
+  # DO NOT OUTPUT KEY MATERIAL TO CONSOLE OR LOGS IN PRODUCTION!
+
+- block:
+    - name: Update sops-encrypted key with the community.sops collection
+      community.crypto.openssl_privatekey_pipe:
+        content: "{{ lookup('community.sops.sops', 'private_key.pem.sops') }}"
+        size: 2048
+      register: output
+      no_log: true  # make sure that private key data is not accidentally revealed in logs!
+
+    - name: Update encrypted key when openssl_privatekey_pipe reported a change
+      community.sops.sops_encrypt:
+        path: private_key.pem.sops
+        content_text: "{{ output.privatekey }}"
+      when: output is changed
+  always:
+    - name: Make sure that output (which contains the private key) is overwritten
+      set_fact:
+        output: ''
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

curve

+

string

+

Elliptic curve used to generate the TLS/SSL private key.

+

Returned: changed or success, and type is ECC

+

Sample: "secp256r1"

+
+

fingerprint

+

dictionary

+

The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available.

+

Returned: changed or success

+

Sample: {"md5": "84:75:71:72:8d:04:b5:6c:4d:37:6d:66:83:f5:4c:29", "sha1": "51:cc:7c:68:5d:eb:41:43:88:7e:1a:ae:c7:f8:24:72:ee:71:f6:10", "sha224": "b1:19:a6:6c:14:ac:33:1d:ed:18:50:d3:06:5c:b2:32:91:f1:f1:52:8c:cb:d5:75:e9:f5:9b:46", "sha256": "41:ab:c7:cb:d5:5f:30:60:46:99:ac:d4:00:70:cf:a1:76:4f:24:5d:10:24:57:5d:51:6e:09:97:df:2f:de:c7", "sha384": "85:39:50:4e:de:d9:19:33:40:70:ae:10:ab:59:24:19:51:c3:a2:e4:0b:1c:b1:6e:dd:b3:0c:d9:9e:6a:46:af:da:18:f8:ef:ae:2e:c0:9a:75:2c:9b:b3:0f:3a:5f:3d", "sha512": "fd:ed:5e:39:48:5f:9f:fe:7f:25:06:3f:79:08:cd:ee:a5:e7:b3:3d:13:82:87:1f:84:e1:f5:c7:28:77:53:94:86:56:38:69:f0:d9:35:22:01:1e:a6:60:...:0f:9b"}

+
+

privatekey

+

string

+

The generated private key’s content.

+

Please note that if the result is not changed, the current private key will only be returned if the return_current_key option is set to true.

+

Will be Base64-encoded if the key is in raw format.

+

Returned: changed, or return_current_key is true

+
+

size

+

integer

+

Size (in bits) of the TLS/SSL private key.

+

Returned: changed or success

+

Sample: 4096

+
+

type

+

string

+

Algorithm used to generate the TLS/SSL private key.

+

Returned: changed or success

+

Sample: "RSA"

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_publickey_info_module.html b/pr/558/openssl_publickey_info_module.html new file mode 100644 index 00000000..4e5aac6f --- /dev/null +++ b/pr/558/openssl_publickey_info_module.html @@ -0,0 +1,474 @@ + + + + + + + community.crypto.openssl_publickey_info module – Provide information for OpenSSL public keys — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_publickey_info module – Provide information for OpenSSL public keys

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_publickey_info.

+
+

New in community.crypto 1.7.0

+ +
+

Synopsis

+
    +
  • This module allows one to query information on OpenSSL public keys.

  • +
  • It uses the cryptography python library to interact with OpenSSL.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.2.3

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + +

Parameter

Comments

+

content

+

string

+

Content of the public key file.

+

Either path or content must be specified, but not both.

+
+

path

+

path

+

Remote absolute path where the public key file is loaded from.

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
community.crypto.openssl_privatekey_info

Provide information for OpenSSL private keys.

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
+  community.crypto.openssl_privatekey:
+    path: /etc/ssl/private/ansible.com.pem
+
+- name: Create public key from private key
+  community.crypto.openssl_publickey:
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    path: /etc/ssl/ansible.com.pub
+
+- name: Get information on public key
+  community.crypto.openssl_publickey_info:
+    path: /etc/ssl/ansible.com.pub
+  register: result
+
+- name: Dump information
+  ansible.builtin.debug:
+    var: result
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

fingerprints

+

dictionary

+

Fingerprints of public key.

+

For every hash algorithm available, the fingerprint is computed.

+

Returned: success

+

Sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63', 'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."

+
+

public_data

+

dictionary

+

Public key data. Depends on key type.

+

Returned: success

+
+

curve

+

string

+

The curve’s name for ECC.

+

Returned: When type=ECC

+
+

exponent

+

integer

+

The RSA key’s public exponent.

+

Returned: When type=RSA

+
+

exponent_size

+

integer

+

The maximum number of bits of a private key. This is basically the bit size of the subgroup used.

+

Returned: When type=ECC

+
+

g

+

integer

+

The g value for DSA.

+

This is the element spanning the subgroup of the multiplicative group of the prime field used.

+

Returned: When type=DSA

+
+

modulus

+

integer

+

The RSA key’s modulus.

+

Returned: When type=RSA

+
+

p

+

integer

+

The p value for DSA.

+

This is the prime modulus upon which arithmetic takes place.

+

Returned: When type=DSA

+
+

q

+

integer

+

The q value for DSA.

+

This is a prime that divides p - 1, and at the same time the order of the subgroup of the multiplicative group of the prime field used.

+

Returned: When type=DSA

+
+

size

+

integer

+

Bit size of modulus (RSA) or prime number (DSA).

+

Returned: When type=RSA or type=DSA

+
+

x

+

integer

+

The x coordinate for the public point on the elliptic curve.

+

Returned: When type=ECC

+
+

y

+

integer

+

For type=ECC, this is the y coordinate for the public point on the elliptic curve.

+

For type=DSA, this is the publicly known group element whose discrete logarithm w.r.t. g is the private key.

+

Returned: When type=DSA or type=ECC

+
+

type

+

string

+

The key’s type.

+

One of RSA, DSA, ECC, Ed25519, X25519, Ed448, or X448.

+

Will start with unknown if the key type cannot be determined.

+

Returned: success

+

Sample: "RSA"

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_publickey_module.html b/pr/558/openssl_publickey_module.html new file mode 100644 index 00000000..215ddde4 --- /dev/null +++ b/pr/558/openssl_publickey_module.html @@ -0,0 +1,618 @@ + + + + + + + community.crypto.openssl_publickey module – Generate an OpenSSL public key from its private key. — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_publickey module – Generate an OpenSSL public key from its private key.

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_publickey.

+
+ +
+

Synopsis

+
    +
  • This module allows one to (re)generate public keys from their private keys.

  • +
  • Public keys are generated in PEM or OpenSSH format. Private keys must be OpenSSL PEM keys. OpenSSH private keys are not supported, use the community.crypto.openssh_keypair module to manage these.

  • +
  • The module uses the cryptography Python library.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.2.3 (older versions might work as well)

  • +
  • Needs cryptography >= 1.4 if format is OpenSSH

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original public key back if you overwrote it with a different one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

force

+

boolean

+

Should the key be regenerated even it it already exists.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

format

+

string

+

The format of the public key.

+

Choices:

+
    +
  • "OpenSSH"

  • +
  • "PEM" ← (default)

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

path

+

path / required

+

Name of the file in which the generated TLS/SSL public key will be written.

+
+

privatekey_content

+

string

+

added in community.crypto 1.0.0

+

The content of the TLS/SSL private key from which to generate the public key.

+

Either privatekey_path or privatekey_content must be specified, but not both. If state is present, one of them is required.

+
+

privatekey_passphrase

+

string

+

The passphrase for the private key.

+
+

privatekey_path

+

path

+

Path to the TLS/SSL private key from which to generate the public key.

+

Either privatekey_path or privatekey_content must be specified, but not both. If state is present, one of them is required.

+
+

return_content

+

boolean

+

added in community.crypto 1.0.0

+

If set to true, will return the (current or generated) public key’s content as publickey.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

state

+

string

+

Whether the public key should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
+
+
+
+

Examples

+
- name: Generate an OpenSSL public key in PEM format
+  community.crypto.openssl_publickey:
+    path: /etc/ssl/public/ansible.com.pem
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+
+- name: Generate an OpenSSL public key in PEM format from an inline key
+  community.crypto.openssl_publickey:
+    path: /etc/ssl/public/ansible.com.pem
+    privatekey_content: "{{ private_key_content }}"
+
+- name: Generate an OpenSSL public key in OpenSSH v2 format
+  community.crypto.openssl_publickey:
+    path: /etc/ssl/public/ansible.com.pem
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    format: OpenSSH
+
+- name: Generate an OpenSSL public key with a passphrase protected private key
+  community.crypto.openssl_publickey:
+    path: /etc/ssl/public/ansible.com.pem
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    privatekey_passphrase: ansible
+
+- name: Force regenerate an OpenSSL public key if it already exists
+  community.crypto.openssl_publickey:
+    path: /etc/ssl/public/ansible.com.pem
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    force: true
+
+- name: Remove an OpenSSL public key
+  community.crypto.openssl_publickey:
+    path: /etc/ssl/public/ansible.com.pem
+    state: absent
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/publickey.pem.2019-03-09@11:22~"

+
+

filename

+

string

+

Path to the generated TLS/SSL public key file.

+

Returned: changed or success

+

Sample: "/etc/ssl/public/ansible.com.pem"

+
+

fingerprint

+

dictionary

+

The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available.

+

Returned: changed or success

+

Sample: {"md5": "84:75:71:72:8d:04:b5:6c:4d:37:6d:66:83:f5:4c:29", "sha1": "51:cc:7c:68:5d:eb:41:43:88:7e:1a:ae:c7:f8:24:72:ee:71:f6:10", "sha224": "b1:19:a6:6c:14:ac:33:1d:ed:18:50:d3:06:5c:b2:32:91:f1:f1:52:8c:cb:d5:75:e9:f5:9b:46", "sha256": "41:ab:c7:cb:d5:5f:30:60:46:99:ac:d4:00:70:cf:a1:76:4f:24:5d:10:24:57:5d:51:6e:09:97:df:2f:de:c7", "sha384": "85:39:50:4e:de:d9:19:33:40:70:ae:10:ab:59:24:19:51:c3:a2:e4:0b:1c:b1:6e:dd:b3:0c:d9:9e:6a:46:af:da:18:f8:ef:ae:2e:c0:9a:75:2c:9b:b3:0f:3a:5f:3d", "sha512": "fd:ed:5e:39:48:5f:9f:fe:7f:25:06:3f:79:08:cd:ee:a5:e7:b3:3d:13:82:87:1f:84:e1:f5:c7:28:77:53:94:86:56:38:69:f0:d9:35:22:01:1e:a6:60:...:0f:9b"}

+
+

format

+

string

+

The format of the public key (PEM, OpenSSH, …).

+

Returned: changed or success

+

Sample: "PEM"

+
+

privatekey

+

string

+

Path to the TLS/SSL private key the public key was generated from.

+

Will be none if the private key has been provided in privatekey_content.

+

Returned: changed or success

+

Sample: "/etc/ssl/private/ansible.com.pem"

+
+

publickey

+

string

+

added in community.crypto 1.0.0

+

The (current or generated) public key’s content.

+

Returned: if state is present and return_content is true

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_signature_info_module.html b/pr/558/openssl_signature_info_module.html new file mode 100644 index 00000000..4f78c14e --- /dev/null +++ b/pr/558/openssl_signature_info_module.html @@ -0,0 +1,400 @@ + + + + + + + community.crypto.openssl_signature_info module – Verify signatures with openssl — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_signature_info module – Verify signatures with openssl

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_signature_info.

+
+

New in community.crypto 1.1.0

+ +
+

Synopsis

+
    +
  • This module allows one to verify a signature for a file by a certificate.

  • +
  • The module uses the cryptography Python library.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.4 (some key types require newer versions)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

certificate_content

+

string

+

The content of the certificate used to verify the signature.

+

Either certificate_path or certificate_content must be specified, but not both.

+
+

certificate_path

+

path

+

The path to the certificate used to verify the signature.

+

Either certificate_path or certificate_content must be specified, but not both.

+
+

path

+

path / required

+

The signed file to verify.

+

This file will only be read and not modified.

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

signature

+

string / required

+

Base64 encoded signature.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • When using the cryptography backend, the following key types require at least the following cryptography version: +RSA keys: cryptography >= 1.4 +DSA and ECDSA keys: cryptography >= 1.5 +ed448 and ed25519 keys: cryptography >= 2.6

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_signature

Sign data with openssl.

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
+
+
+
+

Examples

+
- name: Sign example file
+  community.crypto.openssl_signature:
+    privatekey_path: private.key
+    path: /tmp/example_file
+  register: sig
+
+- name: Verify signature of example file
+  community.crypto.openssl_signature_info:
+    certificate_path: cert.pem
+    path: /tmp/example_file
+    signature: "{{ sig.signature }}"
+  register: verify
+
+- name: Make sure the signature is valid
+  assert:
+    that:
+      - verify.valid
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + +

Key

Description

+

valid

+

boolean

+

true means the signature was valid for the given file, false means it was not.

+

Returned: success

+
+
+

Authors

+
    +
  • Patrick Pichler (@aveexy)

  • +
  • Markus Teufelberger (@MarkusTeufelberger)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/openssl_signature_module.html b/pr/558/openssl_signature_module.html new file mode 100644 index 00000000..05f21651 --- /dev/null +++ b/pr/558/openssl_signature_module.html @@ -0,0 +1,400 @@ + + + + + + + community.crypto.openssl_signature module – Sign data with openssl — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.openssl_signature module – Sign data with openssl

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.openssl_signature.

+
+

New in community.crypto 1.1.0

+ +
+

Synopsis

+
    +
  • This module allows one to sign data using a private key.

  • +
  • The module uses the cryptography Python library.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.4 (some key types require newer versions)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

path

+

path / required

+

The file to sign.

+

This file will only be read and not modified.

+
+

privatekey_content

+

string

+

The content of the private key to use when signing the certificate signing request.

+

Either privatekey_path or privatekey_content must be specified, but not both.

+
+

privatekey_passphrase

+

string

+

The passphrase for the private key.

+

This is required if the private key is password protected.

+
+

privatekey_path

+

path

+

The path to the private key to use when signing.

+

Either privatekey_path or privatekey_content must be specified, but not both.

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: none

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • When using the cryptography backend, the following key types require at least the following cryptography version: +RSA keys: cryptography >= 1.4 +DSA and ECDSA keys: cryptography >= 1.5 +ed448 and ed25519 keys: cryptography >= 2.6

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.openssl_signature_info

Verify signatures with openssl.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
+
+
+
+

Examples

+
- name: Sign example file
+  community.crypto.openssl_signature:
+    privatekey_path: private.key
+    path: /tmp/example_file
+  register: sig
+
+- name: Verify signature of example file
+  community.crypto.openssl_signature_info:
+    certificate_path: cert.pem
+    path: /tmp/example_file
+    signature: "{{ sig.signature }}"
+  register: verify
+
+- name: Make sure the signature is valid
+  assert:
+    that:
+      - verify.valid
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + +

Key

Description

+

signature

+

string

+

Base64 encoded signature.

+

Returned: success

+
+
+

Authors

+
    +
  • Patrick Pichler (@aveexy)

  • +
  • Markus Teufelberger (@MarkusTeufelberger)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/search.html b/pr/558/search.html new file mode 100644 index 00000000..8379e5a2 --- /dev/null +++ b/pr/558/search.html @@ -0,0 +1,190 @@ + + + + + + Search — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+ + +
+ + + + +
+ +
+ +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/pr/558/searchindex.js b/pr/558/searchindex.js new file mode 100644 index 00000000..8794e29e --- /dev/null +++ b/pr/558/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["acme_account_facts_module", "acme_account_info_module", "acme_account_module", "acme_certificate_module", "acme_certificate_revoke_module", "acme_challenge_cert_helper_module", "acme_inspect_module", "certificate_complete_chain_module", "crypto_info_module", "docsite/guide_ownca", "docsite/guide_selfsigned", "ecs_certificate_module", "ecs_domain_module", "environment_variables", "get_certificate_module", "index", "luks_device_module", "openssh_cert_module", "openssh_keypair_module", "openssl_certificate_info_module", "openssl_certificate_module", "openssl_csr_info_module", "openssl_csr_module", "openssl_csr_pipe_module", "openssl_dhparam_module", "openssl_pkcs12_module", "openssl_privatekey_convert_module", "openssl_privatekey_info_module", "openssl_privatekey_module", "openssl_privatekey_pipe_module", "openssl_publickey_info_module", "openssl_publickey_module", "openssl_signature_info_module", "openssl_signature_module", "split_pem_filter", "x509_certificate_info_module", "x509_certificate_module", "x509_certificate_pipe_module", "x509_crl_info_filter", "x509_crl_info_module", "x509_crl_module"], "filenames": ["acme_account_facts_module.rst", "acme_account_info_module.rst", "acme_account_module.rst", "acme_certificate_module.rst", "acme_certificate_revoke_module.rst", "acme_challenge_cert_helper_module.rst", "acme_inspect_module.rst", "certificate_complete_chain_module.rst", "crypto_info_module.rst", "docsite/guide_ownca.rst", "docsite/guide_selfsigned.rst", "ecs_certificate_module.rst", "ecs_domain_module.rst", "environment_variables.rst", "get_certificate_module.rst", "index.rst", "luks_device_module.rst", "openssh_cert_module.rst", "openssh_keypair_module.rst", "openssl_certificate_info_module.rst", "openssl_certificate_module.rst", "openssl_csr_info_module.rst", "openssl_csr_module.rst", "openssl_csr_pipe_module.rst", "openssl_dhparam_module.rst", "openssl_pkcs12_module.rst", "openssl_privatekey_convert_module.rst", "openssl_privatekey_info_module.rst", "openssl_privatekey_module.rst", "openssl_privatekey_pipe_module.rst", "openssl_publickey_info_module.rst", "openssl_publickey_module.rst", "openssl_signature_info_module.rst", "openssl_signature_module.rst", "split_pem_filter.rst", "x509_certificate_info_module.rst", "x509_certificate_module.rst", "x509_certificate_pipe_module.rst", "x509_crl_info_filter.rst", "x509_crl_info_module.rst", "x509_crl_module.rst"], "titles": ["community.crypto.acme_account_facts", "community.crypto.acme_account_info module \u2013 Retrieves information on ACME accounts", "community.crypto.acme_account module \u2013 Create, modify or delete ACME accounts", "community.crypto.acme_certificate module \u2013 Create SSL/TLS certificates with the ACME protocol", "community.crypto.acme_certificate_revoke module \u2013 Revoke certificates with the ACME protocol", "community.crypto.acme_challenge_cert_helper module \u2013 Prepare certificates required for ACME challenges such as tls-alpn-01", "community.crypto.acme_inspect module \u2013 Send direct requests to an ACME server", "community.crypto.certificate_complete_chain module \u2013 Complete certificate chain given a set of untrusted and root certificates", "community.crypto.crypto_info module \u2013 Retrieve cryptographic capabilities", "How to create a small CA", "How to create self-signed certificates", "community.crypto.ecs_certificate module \u2013 Request SSL/TLS certificates with the Entrust Certificate Services (ECS) API", "community.crypto.ecs_domain module \u2013 Request validation of a domain with the Entrust Certificate Services (ECS) API", "Index of all Collection Environment Variables", "community.crypto.get_certificate module \u2013 Get a certificate from a host:port", "Community.Crypto", "community.crypto.luks_device module \u2013 Manage encrypted (LUKS) devices", "community.crypto.openssh_cert module \u2013 Generate OpenSSH host or user certificates.", "community.crypto.openssh_keypair module \u2013 Generate OpenSSH private and public keys", "community.crypto.openssl_certificate_info", "community.crypto.openssl_certificate", "community.crypto.openssl_csr_info module \u2013 Provide information of OpenSSL Certificate Signing Requests (CSR)", "community.crypto.openssl_csr module \u2013 Generate OpenSSL Certificate Signing Request (CSR)", "community.crypto.openssl_csr_pipe module \u2013 Generate OpenSSL Certificate Signing Request (CSR)", "community.crypto.openssl_dhparam module \u2013 Generate OpenSSL Diffie-Hellman Parameters", "community.crypto.openssl_pkcs12 module \u2013 Generate OpenSSL PKCS#12 archive", "community.crypto.openssl_privatekey_convert module \u2013 Convert OpenSSL private keys", "community.crypto.openssl_privatekey_info module \u2013 Provide information for OpenSSL private keys", "community.crypto.openssl_privatekey module \u2013 Generate OpenSSL private keys", "community.crypto.openssl_privatekey_pipe module \u2013 Generate OpenSSL private keys without disk access", "community.crypto.openssl_publickey_info module \u2013 Provide information for OpenSSL public keys", "community.crypto.openssl_publickey module \u2013 Generate an OpenSSL public key from its private key.", "community.crypto.openssl_signature_info module \u2013 Verify signatures with openssl", "community.crypto.openssl_signature module \u2013 Sign data with openssl", "community.crypto.split_pem filter \u2013 Split PEM file contents into multiple objects", "community.crypto.x509_certificate_info module \u2013 Provide information of OpenSSL X.509 certificates", "community.crypto.x509_certificate module \u2013 Generate and/or check OpenSSL certificates", "community.crypto.x509_certificate_pipe module \u2013 Generate and/or check OpenSSL certificates", "community.crypto.x509_crl_info filter \u2013 Retrieve information from X.509 CRLs in PEM format", "community.crypto.x509_crl_info module \u2013 Retrieve information on Certificate Revocation Lists (CRLs)", "community.crypto.x509_crl module \u2013 Generate Certificate Revocation Lists (CRLs)"], "terms": {"thi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "plugin": [0, 13, 19, 20, 29, 34, 38], "wa": [0, 1, 3, 4, 6, 9, 11, 14, 16, 18, 19, 20, 21, 22, 23, 25, 27, 28, 29, 31, 32, 35, 36, 38, 39, 40], "part": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "collect": [0, 9, 10, 15, 19, 20], "version": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "2": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "10": [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "0": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "modul": [0, 9, 10, 19, 20, 38], "ha": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "been": [0, 1, 2, 3, 4, 6, 11, 13, 14, 16, 17, 19, 20, 22, 23, 27, 31, 37], "remov": [0, 1, 2, 3, 4, 6, 16, 19, 20, 25, 31, 36], "The": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "renam": [0, 19, 20, 35, 36], "acme_account_info": [0, 2, 15], "i": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "To": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "instal": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "us": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "ansibl": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "galaxi": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "you": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "need": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "further": [1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "abl": [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "detail": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "playbook": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "specifi": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "allow": [1, 2, 3, 4, 6, 11, 12, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "ca": [1, 2, 3, 4, 6, 7, 11, 15, 17, 21, 22, 23, 25, 34, 35, 36, 37, 38, 39, 40], "support": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "protocol": [1, 2, 5, 6, 14, 15, 18, 36], "let": [1, 2, 3, 4, 6, 36], "": [1, 2, 3, 4, 5, 6, 9, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37, 38, 39, 40], "encrypt": [1, 2, 3, 4, 6, 14, 15, 18, 25, 26, 28, 29, 36], "onli": [1, 2, 3, 4, 6, 7, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 39, 40], "work": [1, 2, 3, 4, 6, 16, 26, 28, 29, 31], "v2": [1, 2, 3, 4, 6, 31], "below": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "ar": [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "host": [1, 2, 3, 4, 5, 6, 7, 11, 12, 15, 16, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "execut": [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "either": [1, 2, 3, 4, 6, 11, 12, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 35, 36, 37, 39, 40], "openssl": [1, 2, 3, 4, 6, 7, 8, 15], "cryptographi": [1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "1": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "5": [1, 2, 3, 4, 6, 7, 8, 12, 16, 21, 28, 29, 32, 33, 35, 36, 37], "ipaddress": [1, 2, 3, 4, 6], "comment": [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "account_key_cont": [1, 2, 3, 4, 6], "string": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "content": [1, 2, 3, 4, 5, 6, 7, 9, 11, 12, 14, 15, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "rsa": [1, 2, 3, 4, 6, 8, 10, 17, 18, 21, 27, 28, 29, 30, 32, 33, 35], "ellipt": [1, 2, 3, 4, 6, 8, 18, 21, 27, 28, 29, 30, 35], "curv": [1, 2, 3, 4, 6, 8, 18, 21, 27, 28, 29, 30, 35], "kei": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40], "mutual": [1, 2, 3, 4, 5, 6, 16, 22, 23, 25, 36, 37, 40], "exclus": [1, 2, 3, 4, 5, 6, 16, 22, 23, 25, 36, 37, 40], "account_key_src": [1, 2, 3, 4, 5, 6, 8], "warn": [1, 2, 3, 4, 6, 27, 35, 36], "written": [1, 2, 3, 4, 6, 17, 18, 22, 24, 25, 26, 28, 29, 31, 36, 40], "temporari": [1, 2, 3, 4, 6], "file": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "which": [1, 2, 3, 4, 6, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "delet": [1, 3, 4, 6, 15], "when": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "complet": [1, 2, 3, 4, 6, 8, 15, 16, 29], "sinc": [1, 2, 3, 4, 6, 9, 16, 22, 23, 25, 27], "an": [1, 2, 3, 4, 5, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 35, 36, 37, 38, 39, 40], "import": [1, 2, 3, 4, 6, 8, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36, 40], "privat": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 15, 17, 21, 22, 23, 24, 25, 30, 32, 33, 35, 36, 37, 38, 39, 40], "can": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "chang": [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "revok": [1, 2, 3, 6, 11, 15, 38, 39, 40], "your": [1, 2, 3, 4, 6, 9, 11, 12, 22, 23, 24, 28, 29, 36, 37], "certif": [1, 2, 6, 15, 24, 25, 28, 29, 31, 32, 33, 34, 38], "without": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 35, 36, 37, 39, 40], "know": [1, 2, 3, 4, 6, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36], "might": [1, 2, 3, 4, 6, 26, 28, 29, 31, 40], "accept": [1, 2, 3, 4, 6, 11, 22, 23], "In": [1, 2, 3, 4, 6, 9, 11, 18, 21, 25, 27, 28, 29, 37], "case": [1, 2, 3, 4, 6, 8, 11, 12, 14, 16, 17, 18, 21, 22, 24, 25, 26, 27, 28, 29, 31, 35, 36, 40], "It": [1, 2, 3, 4, 6, 7, 11, 18, 21, 26, 27, 28, 30, 35, 36, 37], "still": [1, 2, 3, 4, 6, 11, 17, 21, 27, 35, 36], "happen": [1, 2, 3, 4, 6], "disk": [1, 2, 3, 4, 6, 7, 10, 15, 22, 23, 26, 27, 28, 31, 36, 37], "process": [1, 2, 3, 4, 6, 12, 16, 40], "move": [1, 2, 3, 4, 6, 11, 35, 36, 37], "its": [1, 2, 3, 4, 6, 7, 9, 11, 12, 15, 16, 17, 18, 22, 23, 24, 25, 26, 28, 29, 30, 36, 37], "argument": [1, 2, 3, 4, 6, 24], "node": [1, 2, 3, 4, 6, 38], "where": [1, 2, 3, 4, 6, 9, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 35, 36, 37, 39, 40], "account_key_passphras": [1, 2, 3, 4, 6], "ad": [1, 2, 3, 4, 5, 6, 7, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 27, 28, 31, 35, 36, 37, 38, 39, 40], "6": [1, 2, 3, 4, 5, 6, 8, 11, 14, 16, 18, 21, 22, 23, 28, 29, 32, 33, 35, 36, 37], "phassphras": [1, 2, 3, 4, 5, 6], "decod": [1, 2, 3, 4, 5, 6, 21, 35, 38, 39, 40], "backend": [1, 2, 3, 4, 6, 14, 18, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "alias": [1, 2, 3, 4, 6, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36, 37, 40], "account_kei": [1, 2, 3, 4, 6], "path": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "contain": [1, 2, 3, 4, 5, 6, 7, 12, 14, 16, 17, 18, 22, 23, 24, 25, 26, 28, 29, 31, 36, 40], "creat": [1, 4, 5, 6, 11, 15, 16, 17, 18, 22, 23, 24, 25, 26, 28, 30, 31, 36, 37, 39, 40], "openssl_privatekei": [1, 2, 3, 6, 9, 10, 11, 15, 22, 23, 24, 25, 26, 27, 29, 30, 31, 33, 36, 37], "openssl_privatekey_pip": [1, 2, 3, 6, 15, 22, 23, 26, 27, 28, 31, 36, 37], "If": [1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "requisit": [1, 2, 3, 6], "avail": [1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 40], "directli": [1, 2, 3, 6, 10, 35, 36], "command": [1, 2, 3, 6, 16, 17], "line": [1, 2, 3, 6, 16], "tool": [1, 2, 3, 4, 6, 22, 23], "genrsa": [1, 2, 3, 6], "ecparam": [1, 2, 3, 4, 6], "genkei": [1, 2, 3, 4, 6], "ani": [1, 2, 3, 4, 6, 9, 10, 11, 17, 18, 22, 23, 24, 25, 26, 28, 29, 31, 36, 37], "other": [1, 2, 3, 4, 6, 11, 17, 18, 22, 23, 25, 28, 29, 35, 39, 40], "pem": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 14, 15, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "format": [1, 2, 3, 4, 5, 6, 7, 11, 15, 16, 17, 18, 21, 25, 26, 27, 28, 29, 31, 35, 36, 37, 39, 40], "well": [1, 2, 3, 4, 6, 12, 25, 26, 28, 29, 31, 36], "account_uri": [1, 2, 3, 4, 6], "assum": [1, 2, 3, 4, 6, 7, 9, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "uri": [1, 2, 3, 4, 6, 21, 22, 23, 35, 38, 39, 40], "given": [1, 2, 3, 4, 5, 6, 15, 16, 22, 23, 32], "doe": [1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "match": [1, 2, 3, 4, 6, 7, 12, 17, 18, 22, 23, 24, 28, 29, 36, 37, 40], "exist": [1, 2, 3, 4, 5, 6, 9, 11, 16, 17, 18, 22, 23, 24, 25, 26, 28, 29, 31, 36, 37, 40], "fail": [1, 2, 3, 4, 6, 11, 17, 18, 21, 22, 24, 25, 26, 27, 28, 29, 31, 35, 36, 38, 39, 40], "acme_directori": [1, 2, 3, 4, 6, 36], "directori": [1, 2, 3, 4, 6, 7, 36], "entri": [1, 2, 3, 4, 5, 6, 12, 21, 34, 35, 36, 38, 40], "point": [1, 2, 3, 4, 6, 7, 11, 17, 21, 22, 23, 27, 30, 35, 36, 37, 38, 39, 40], "url": [1, 2, 3, 4, 6], "access": [1, 2, 3, 4, 6, 12, 15, 22, 23, 26, 27, 28, 31, 36, 37], "server": [1, 2, 3, 4, 9, 11, 12, 14, 15, 17, 22, 23, 36, 37], "api": [1, 2, 3, 4, 6, 15, 36, 37], "For": [1, 2, 3, 4, 6, 10, 11, 12, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38], "safeti": [1, 2, 3, 4, 6], "reason": [1, 2, 3, 4, 6, 22, 23, 36, 37, 38, 39, 40], "default": [1, 2, 3, 4, 6, 7, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "set": [1, 2, 3, 4, 5, 6, 11, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "stage": [1, 2, 3, 4, 6, 36], "v1": [1, 2, 3, 4, 6], "technic": [1, 2, 3, 4, 6, 11], "correct": [1, 2, 3, 4, 6, 7, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "untrust": [1, 2, 3, 4, 6, 15], "all": [1, 2, 3, 4, 6, 7, 8, 9, 11, 17, 18, 21, 25, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40], "endpoint": [1, 2, 3, 4, 6], "found": [1, 2, 3, 4, 6, 8, 12], "here": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "http": [1, 2, 3, 4, 5, 6, 11, 12, 14, 17, 22, 23, 28, 36, 37], "letsencrypt": [1, 2, 3, 4, 6, 36], "org": [1, 2, 3, 4, 6, 11, 22, 23, 36, 38, 39, 40], "doc": [1, 2, 3, 4, 6, 9, 10, 28, 36], "environ": [1, 2, 3, 4, 5, 6, 36], "buypass": [1, 2, 3, 4, 6, 36], "com": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37, 38, 39, 40], "t": [1, 2, 3, 4, 6, 9, 17, 18, 21, 22, 24, 25, 26, 27, 28, 30, 31, 35, 36, 40], "63d4ai": [1, 2, 3, 4, 6], "go": [1, 2, 3, 4, 6], "ssl": [1, 2, 4, 5, 6, 7, 12, 15, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37, 39, 40], "product": [1, 2, 3, 4, 6, 11, 29], "v02": [1, 2, 3, 4, 6, 36], "zerossl": [1, 2, 3, 4, 6], "dv90": [1, 2, 3, 4, 6], "sectigo": [1, 2, 3, 4, 6], "qa": [1, 2, 3, 4, 6], "secur": [1, 2, 3, 4, 6, 11, 14, 25, 36, 37], "trust": [1, 2, 3, 4, 6, 38, 39, 40], "provid": [1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 14, 15, 16, 18, 22, 23, 28, 29, 31, 36, 37, 38, 39], "dv": [1, 2, 3, 4, 6], "list": [1, 2, 3, 4, 6, 7, 8, 11, 12, 14, 15, 17, 21, 22, 23, 25, 34, 35, 38], "servic": [1, 2, 3, 4, 6, 15, 36, 37], "test": [1, 2, 3, 4, 6, 11, 12, 18, 21, 35], "against": [1, 2, 3, 4, 6, 11, 14, 17], "acme_vers": [1, 2, 3, 4, 6], "integ": [1, 2, 3, 4, 6, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 27, 28, 29, 30, 35, 36, 37, 38, 39, 40], "must": [1, 2, 3, 4, 5, 6, 9, 11, 12, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "classic": [1, 2, 3, 4, 6], "standard": [1, 2, 3, 4, 6, 11], "deprec": [1, 2, 3, 4, 6, 18, 35, 36], "from": [1, 2, 3, 4, 6, 7, 9, 10, 11, 12, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 35, 36, 37, 39, 40], "3": [1, 2, 3, 4, 5, 6, 11, 12, 14, 16, 17, 18, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37], "choic": [1, 2, 3, 4, 5, 6, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "request_timeout": [1, 2, 3, 4, 6], "time": [1, 2, 3, 4, 6, 11, 12, 16, 17, 21, 25, 27, 30, 35, 36, 37, 38, 39, 40], "should": [1, 2, 3, 4, 5, 6, 8, 11, 12, 14, 17, 18, 21, 22, 23, 24, 25, 26, 28, 29, 31, 35, 36, 37, 39, 40], "wait": [1, 2, 3, 4, 6], "respons": [1, 2, 3, 4, 6, 11], "timeout": [1, 2, 3, 4, 6, 14], "appli": [1, 2, 3, 4, 6, 11, 14, 17, 18], "request": [1, 2, 3, 4, 5, 7, 8, 9, 10, 14, 15, 16, 17, 18, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "head": [1, 2, 3, 4, 6], "get": [1, 2, 3, 4, 6, 11, 15, 17, 18, 21, 22, 24, 25, 26, 27, 28, 30, 31, 35, 36, 39, 40], "post": [1, 2, 3, 4, 6, 11], "retrieve_ord": 1, "whether": [1, 2, 3, 4, 6, 8, 9, 11, 12, 14, 17, 18, 21, 22, 23, 24, 25, 27, 28, 31, 35, 36, 37, 38, 39, 40], "order": [1, 3, 6, 11, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 34, 35, 36, 38, 39, 40], "object": [1, 3, 6, 15, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "A": [1, 2, 5, 7, 8, 11, 14, 21, 22, 23, 27, 30, 32, 34, 35, 36, 37, 39, 40], "ignor": [1, 2, 3, 7, 11, 17, 18, 21, 22, 23, 25, 29, 34, 35, 36, 37, 38, 39, 40], "fetch": 1, "order_uri": [1, 3, 6], "alwai": [1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 14, 17, 18, 25, 27, 28, 29, 35, 36, 37, 40], "popul": 1, "option": [1, 2, 3, 4, 6, 11, 16, 17, 18, 22, 23, 24, 25, 26, 28, 29, 31, 35, 36, 37, 40], "object_list": 1, "current": [1, 3, 8, 11, 12, 14, 17, 18, 22, 23, 24, 25, 26, 28, 29, 31, 36, 37, 40], "so": [1, 2, 3, 4, 6, 11, 12, 16, 17, 18, 22, 24, 25, 26, 27, 28, 29, 31, 36, 38, 40], "result": [1, 4, 5, 9, 10, 11, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37, 38, 39, 40], "empti": [1, 3, 8], "url_list": 1, "select_crypto_backend": [1, 2, 3, 4, 6, 14, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37], "determin": [1, 2, 3, 4, 6, 14, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37], "auto": [1, 2, 3, 4, 6, 14, 18, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37], "tri": [1, 2, 3, 4, 6, 7, 14, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37], "fall": [1, 2, 3, 4, 6, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "back": [1, 2, 3, 4, 6, 9, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "try": [1, 2, 3, 4, 6, 7, 8, 14, 16, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37], "binari": [1, 2, 3, 4, 6, 8, 18, 24], "librari": [1, 2, 3, 4, 6, 8, 14, 17, 18, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "validate_cert": [1, 2, 3, 4, 6], "boolean": [1, 2, 3, 4, 6, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 35, 36, 37, 38, 39, 40], "call": [1, 2, 3, 4, 6, 11, 25, 35, 36], "valid": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 14, 15, 17, 21, 22, 23, 32, 33, 35, 36, 37, 40], "tl": [1, 2, 4, 6, 15, 22, 23, 25, 26, 28, 29, 31, 36, 37], "ever": [1, 2, 3, 4, 6], "fals": [1, 2, 3, 4, 6, 8, 9, 11, 12, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 35, 36, 37, 38, 39, 40], "purpos": [1, 2, 3, 4, 6, 11, 22, 23, 36, 37], "local": [1, 2, 3, 4, 6, 11, 12, 36, 37, 38], "pebbl": [1, 2, 3, 4, 6], "true": [1, 2, 3, 4, 6, 8, 9, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 35, 36, 37, 38, 39, 40], "descript": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "action_group": [1, 2, 3, 4, 6], "action": [1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 17, 18, 21, 22, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 39, 40], "group": [1, 2, 3, 4, 6, 17, 18, 21, 22, 24, 25, 26, 27, 28, 30, 31, 35, 36, 40], "module_default": [1, 2, 3, 4, 6], "check_mod": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "full": [1, 2, 3, 7, 8, 11, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "modifi": [1, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "state": [1, 2, 3, 5, 7, 8, 14, 16, 17, 18, 21, 22, 23, 24, 25, 27, 28, 30, 31, 32, 33, 35, 36, 39, 40], "run": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "statu": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "predict": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "target": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "diff_mod": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "n": [1, 5, 6, 7, 8, 14, 21, 27, 30, 32, 35, 39], "Will": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "what": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "possibli": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "diff": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "mode": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "acme_account": [1, 3, 15], "acme_account_fact": 1, "befor": [1, 3, 12, 34, 36, 37, 38], "8": [1, 3, 4, 16, 17, 18, 22, 24, 25, 26, 28, 31, 36], "usag": [1, 3, 7, 10, 11, 15, 16, 22, 36, 37], "did": [1, 3, 29], "new": [1, 2, 3, 4, 5, 6, 8, 9, 11, 12, 16, 17, 18, 22, 23, 24, 25, 26, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40], "enough": [1, 2, 3, 4, 6], "instead": [1, 2, 3, 4, 6, 10, 16, 17, 22, 23, 28, 29, 40], "explicitli": [1, 2, 3, 4, 6, 26, 27, 28], "disabl": [1, 2, 3, 4, 6, 11, 16, 17, 27], "enabl": [1, 2, 3, 4, 6, 11, 17, 22, 23], "slower": [1, 2, 3, 4, 6], "less": [1, 2, 3, 4, 6, 12, 17], "have": [1, 2, 3, 4, 6, 10, 11, 12, 13, 17, 18, 22, 24, 25, 26, 27, 28, 29, 31, 34, 36, 37, 38, 40], "store": [1, 2, 3, 4, 6, 10, 11, 12, 16, 23, 25, 26, 36, 37], "although": [1, 2, 3, 4, 6], "chosen": [1, 2, 3, 4, 6, 25], "principl": [1, 2, 3, 4, 6], "far": [1, 2, 3, 4, 6], "develop": [1, 2, 3, 4, 6, 36], "we": [1, 2, 3, 4, 5, 6, 9, 25, 28, 29], "got": [1, 2, 3, 4, 6], "feedback": [1, 2, 3, 4, 6], "thei": [1, 2, 3, 4, 6, 12, 16, 18, 24, 28, 29, 35, 39], "incommon": [1, 2, 3, 4, 6], "experi": [1, 2, 3, 4, 6], "problem": [1, 2, 3, 4, 6], "anoth": [1, 2, 3, 4, 6, 7, 9, 10, 11, 16, 21, 28, 29, 35, 37, 38, 39, 40], "pleas": [1, 2, 3, 4, 6, 7, 9, 18, 22, 23, 24, 26, 28, 29, 36, 37], "issu": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "help": [1, 2, 3, 4, 6, 11], "u": [1, 2, 3, 4, 6, 17, 18, 22, 24, 25, 26, 28, 31, 36, 37], "mention": [1, 2, 3, 4, 6, 25], "appreci": [1, 2, 3, 4, 6], "name": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "check": [1, 3, 7, 9, 11, 15, 17, 21, 22, 23, 24, 25, 27, 28, 29, 31, 32, 35, 38, 39, 40], "etc": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 37, 39, 40], "pki": [1, 2, 3, 4, 5, 6, 8, 12], "cert": [1, 2, 3, 4, 5, 6, 8, 11, 14, 17, 21, 22, 23, 25, 32, 33, 35, 38, 40], "regist": [1, 3, 5, 6, 7, 8, 9, 10, 14, 21, 23, 27, 29, 30, 32, 33, 35, 36, 37, 39], "account_data": 1, "verifi": [1, 7, 12, 15, 33, 36], "assert": [1, 32, 33, 35, 36], "print": [1, 34, 37, 39], "builtin": [1, 8, 23, 27, 30, 34, 35, 36, 37, 38, 39], "debug": [1, 2, 3, 4, 6, 8, 11, 14, 21, 23, 27, 29, 30, 34, 35, 37, 38, 39], "var": [1, 3, 6, 8, 14, 21, 23, 27, 30, 35, 37], "contact": [1, 2, 3, 6], "acme_account_kei": 1, "acme_account_uri": 1, "common": [1, 2, 3, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "document": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "follow": [1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "field": [1, 2, 3, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "uniqu": [1, 2, 3, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "dictionari": [1, 2, 3, 5, 6, 8, 11, 14, 16, 21, 22, 23, 27, 28, 29, 30, 31, 35, 38, 39, 40], "element": [1, 2, 3, 7, 8, 11, 12, 14, 17, 21, 22, 23, 25, 27, 30, 34, 35, 38, 39, 40], "challeng": [1, 3, 6, 15, 36], "resourc": [1, 3, 5, 12], "sampl": [1, 3, 4, 5, 6, 8, 11, 12, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 38, 39, 40], "mailto": [1, 2, 6], "me": [1, 2, 6], "tel": 1, "00123456789": 1, "queri": [1, 3, 21, 27, 30, 35], "public_account_kei": 1, "public": [1, 3, 11, 15, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 35, 36, 37], "json": [1, 6, 11, 38, 39], "web": [1, 12], "kty": [1, 6], "ec": [1, 3, 15, 36, 37], "crv": 1, "p": [1, 21, 27, 30, 35], "256": [1, 17, 18], "x": [1, 6, 14, 15, 21, 27, 30, 39], "mkbctnickusdii11yss3526idz8aito7tu6kpaqv7d4": 1, "y": [1, 14, 21, 27, 30, 35], "4etl6srw2yilurn5vfvvhuhp7x8pxltmwwlbbm4ifym": 1, "deactiv": [1, 2, 3, 11], "none": [1, 2, 3, 4, 5, 6, 11, 12, 14, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 33, 35], "success": [1, 3, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "error": [1, 3, 4, 6, 8, 11, 16, 36], "occur": [1, 40], "dure": [1, 2, 3, 11, 17, 25], "about": [1, 2, 11, 12, 14, 17, 22, 23, 27], "structur": 1, "rfc7807": 1, "expir": [1, 3, 6, 10, 11, 12, 14, 35, 36, 37, 40], "timestamp": [1, 17, 22, 24, 25, 26, 28, 31, 35, 36, 37, 39, 40], "describ": [1, 22, 23, 34, 38], "rfc3339": [1, 11], "includ": [1, 3, 7, 9, 11, 12, 17, 18, 22, 24, 25, 26, 28, 31, 35, 36, 38, 39, 40], "pend": [1, 11], "give": [1, 17, 18, 22, 24, 25, 26, 28, 31, 36], "expiri": [1, 11, 36, 37], "date": [1, 6, 7, 11, 14, 35, 36, 37, 38, 39, 40], "final": [1, 3], "identifi": [1, 2, 3, 5, 11, 16, 17, 21, 22, 23, 35, 36, 37], "type": [1, 3, 5, 6, 10, 11, 12, 16, 17, 18, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40], "dn": [1, 3, 5, 9, 10, 12, 21, 22, 23, 35, 36, 38, 39, 40], "ip": [1, 3, 5, 14, 21, 22, 23, 35], "hostnam": [1, 14], "address": [1, 2, 3, 5, 11, 12, 17, 21, 35, 38, 39, 40], "wildcard": [1, 3], "actual": [1, 5, 17, 18, 22, 24, 25, 26, 28, 31, 36], "prefix": [1, 2, 22, 23], "notaft": [1, 35], "notbefor": [1, 35], "readi": [1, 11], "invalid": [1, 11, 34, 38, 39, 40], "felix": [1, 2, 4, 5, 6, 7, 8, 21, 22, 23, 26, 27, 28, 29, 30, 31, 34, 35, 37, 38, 39, 40], "fontein": [1, 2, 4, 5, 6, 7, 8, 21, 22, 23, 26, 27, 28, 29, 30, 31, 34, 35, 37, 38, 39, 40], "felixfontein": [1, 2, 4, 5, 6, 7, 8, 21, 22, 23, 26, 27, 28, 29, 30, 31, 34, 35, 37, 38, 39, 40], "tracker": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "repositori": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "sourc": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "submit": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "bug": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "report": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "featur": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "allow_cr": 2, "creation": [2, 3, 6, 16], "present": [2, 3, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 28, 31, 35, 36, 40], "email": [2, 3, 11, 12, 21, 22, 23, 35, 36, 37, 38, 39, 40], "ietf": [2, 3, 6, 22, 23], "html": [2, 3, 6, 22, 23, 28], "rfc8555": [2, 3, 6], "section": [2, 3, 4, 6, 22, 23], "7": [2, 3, 6, 14, 17, 18, 21, 25, 30, 35, 38, 39], "absent": [2, 16, 17, 18, 22, 24, 25, 28, 31, 36, 40], "changed_kei": 2, "external_account_bind": 2, "extern": 2, "bind": 2, "data": [2, 3, 5, 11, 12, 15, 17, 18, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 40], "like": [2, 3, 10, 17, 18, 22, 24, 25, 26, 28, 31, 36, 37], "specif": [2, 3, 4, 5, 6, 10, 11, 12, 16, 22, 23, 25, 35, 36, 37], "properli": [2, 6], "custom": [2, 11, 18], "alg": 2, "mac": [2, 25], "algorithm": [2, 14, 16, 17, 18, 21, 27, 28, 29, 30, 31, 35, 36, 37, 38, 39, 40], "probabl": 2, "hs256": 2, "hs384": 2, "hs512": 2, "base64": [2, 3, 14, 21, 25, 28, 29, 32, 33, 35, 39, 40], "encod": [2, 3, 6, 11, 14, 21, 25, 28, 29, 32, 33, 35, 38, 39, 40], "pad": 2, "symbol": [2, 7, 17, 18, 22, 24, 25, 26, 28, 31, 36], "end": [2, 3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36], "omit": [2, 9, 16, 17, 18], "kid": 2, "new_account_key_cont": 2, "same": [2, 3, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 40], "restrict": [2, 3, 17, 22, 23], "new_account_key_src": 2, "new_account_key_passphras": 2, "inform": [2, 3, 4, 5, 6, 8, 10, 11, 12, 14, 15, 17, 22, 23, 28, 29, 36, 37], "touch": 2, "terms_agre": [2, 3], "indic": [2, 3, 11, 14, 22, 23, 27, 29], "agre": [2, 3], "term": [2, 3, 6], "acme_certif": [2, 5, 6, 7, 15], "do": [2, 3, 6, 9, 10, 11, 12, 16, 17, 18, 22, 24, 25, 26, 27, 28, 29, 31, 36], "basic": [2, 3, 21, 22, 23, 27, 30, 35], "manag": [2, 3, 4, 5, 6, 11, 15, 31], "both": [2, 3, 11, 18, 21, 22, 23, 27, 30, 31, 32, 33, 35, 37, 39, 40], "recommend": [2, 11, 12, 36, 37], "modify_account": [2, 3], "automat": [2, 3, 4, 5, 6, 16, 28, 29, 36], "rfc": [2, 3, 4, 5, 6, 22, 23], "8555": [2, 3, 4, 5, 6], "retriev": [2, 3, 6, 14, 15, 22, 23, 36, 37], "fact": 2, "write": [2, 3, 6, 7, 9, 16, 17, 18, 22, 24, 25, 26, 28, 29, 31, 36, 37, 40], "acme_inspect": [2, 3, 4, 15], "make": [2, 3, 6, 11, 14, 16, 18, 27, 28, 29, 32, 33, 35, 40], "sure": [2, 3, 16, 18, 27, 28, 29, 32, 33, 40], "TOS": 2, "myself": [2, 3], "one": [2, 3, 4, 7, 9, 11, 12, 14, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "variabl": [2, 3, 9, 21, 27, 34, 38], "new_account_kei": 2, "renew": [3, 11], "implement": [3, 29, 36, 37], "01": [3, 6, 11, 15, 17, 28, 29, 31], "alpn": [3, 6, 15], "twice": 3, "two": [3, 22, 23], "differ": [3, 4, 10, 12, 14, 17, 18, 22, 24, 28, 31, 36, 40], "task": [3, 11, 17, 18, 28, 29, 35], "output": [3, 6, 8, 11, 17, 25, 28, 29], "first": [3, 5, 6, 10, 11, 12, 16, 25, 35], "record": [3, 11, 12], "pass": [3, 9, 11], "second": [3, 12, 14, 16, 35, 36, 37, 40], "between": [3, 16, 18], "fulfil": 3, "step": [3, 11, 25], "whatev": 3, "mean": [3, 11, 32], "necessari": [3, 17], "destin": [3, 11, 17, 18, 22, 24, 25, 26, 28, 29, 31, 36], "webserv": 3, "serv": [3, 36], "perform": [3, 11, 12, 16, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36, 40], "how": [3, 5, 12, 14, 15, 21, 22, 23, 28, 35, 36, 38, 39, 40], "read": [3, 9, 16, 17, 18, 22, 24, 25, 26, 28, 29, 31, 32, 33, 36, 37, 40], "through": 3, "main": 3, "consid": [3, 17, 18, 22, 23, 24, 25, 28, 29, 36, 37], "experiment": 3, "accord": [3, 22, 23], "8738": 3, "account_email": 3, "associ": [3, 7, 11, 12], "account": [3, 4, 5, 6, 8, 11, 15], "more": [3, 7, 11, 14, 17, 22, 23, 25, 36, 37, 40], "than": [3, 4, 11, 12, 17, 18, 21, 22, 23, 25, 35, 36, 37, 38, 39, 40], "updat": [3, 6, 12, 17, 18, 22, 24, 25, 26, 28, 29, 31, 36, 40], "most": [3, 16], "agreement": [3, 11, 21, 35], "latest": [3, 28, 40], "gather": 3, "chain_dest": 3, "chain": [3, 11, 14, 15, 36], "intermedi": [3, 7, 11, 25, 29, 36], "csr": [3, 5, 6, 7, 9, 10, 11, 15, 24, 25, 28, 29, 31, 35, 36, 37], "src": [3, 9, 25, 37], "openssl_csr": [3, 10, 11, 15, 21, 23, 24, 25, 28, 29, 31, 36, 37], "req": 3, "mai": [3, 11, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36, 37], "multipl": [3, 9, 10, 11, 15, 21, 22, 23, 25, 27, 30, 35], "subject": [3, 7, 10, 11, 14, 17, 18, 21, 22, 23, 24, 25, 26, 28, 31, 35, 36, 37, 38, 40], "altern": [3, 10, 11, 22, 23, 36, 37], "each": [3, 9, 11, 28, 29, 31, 34, 38], "lead": [3, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "individu": [3, 17], "sign": [3, 5, 8, 11, 14, 15, 17, 24, 25, 28, 29, 31, 32, 35, 36, 37, 38, 39, 40], "bad": 3, "idea": 3, "view": 3, "precis": 3, "csr_content": [3, 9, 10, 36, 37], "openssl_csr_pip": [3, 9, 10, 15, 21, 22, 28, 29, 31, 36, 37], "ongo": 3, "previou": [3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "non": [3, 8, 11, 17], "activ": [3, 6, 11, 12], "taken": 3, "mark": [3, 22, 23], "no_log": [3, 28, 29], "up": [3, 5, 11, 16, 17, 18, 22, 24, 25, 26, 28, 31, 34, 35, 36, 38], "longer": [3, 16, 22, 23], "wai": [3, 5, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "caus": [3, 17, 18], "messag": 3, "come": 3, "unus": 3, "anywai": 3, "deactivate_authz": 3, "authent": [3, 6, 11, 12, 17, 22, 23, 36, 37], "authz": [3, 6], "after": [3, 16, 36, 37], "bound": 3, "remain": [3, 11, 12, 16, 17], "certain": [3, 17, 35], "amount": 3, "re": [3, 12, 14, 18, 21, 22, 23, 24, 25, 28, 29, 31, 35, 36, 37, 40], "domain": [3, 5, 11, 15, 21, 35, 38, 39, 40], "concern": [3, 22, 24, 28, 29, 36, 37], "dest": [3, 5, 7, 9, 23, 37], "fullchain_dest": [3, 6], "forc": [3, 11, 17, 18, 22, 24, 25, 26, 28, 29, 31, 36, 37, 40], "enforc": 3, "even": [3, 4, 11, 16, 17, 18, 24, 25, 28, 31, 36, 37], "remaining_dai": [3, 11], "especi": [3, 28], "addit": [3, 11, 16, 22, 23], "desir": [3, 16], "fullchain": [3, 6, 7], "want": [3, 9, 10, 11, 12, 16, 18, 22, 23, 27, 40], "avoid": [3, 11, 12, 17, 18, 22, 24, 25, 26, 27, 28, 31, 35, 36, 37, 40], "accident": [3, 27, 28, 29], "old": [3, 11, 22, 23, 35, 36], "number": [3, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 35, 36, 37, 38, 39, 40], "dai": [3, 11, 12, 14, 35, 36, 37], "left": [3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "being": [3, 11, 17, 28, 29, 35, 36, 37], "cert_dai": [3, 11], "challenge_data": [3, 5], "retrieve_all_altern": 3, "offer": [3, 9, 10], "These": [3, 15, 22, 23, 38], "togeth": [3, 16, 25], "all_chain": 3, "select_chain": 3, "criteria": 3, "select": [3, 5, 10, 18, 25, 28, 29], "until": [3, 7, 11, 14], "criterium": 3, "header": [3, 5, 6], "determinist": 3, "everi": [3, 11, 12, 18, 21, 22, 23, 26, 27, 28, 29, 30, 35, 36, 37, 40], "consist": [3, 27], "condit": [3, 14, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "issuer": [3, 7, 14, 21, 22, 23, 35, 36, 38, 39, 40], "authority_key_identifi": [3, 21, 22, 23, 35], "authoritykeyidentifi": [3, 21, 22, 23, 35], "extens": [3, 5, 6, 14, 18, 21, 22, 23, 35, 38, 39, 40], "base": [3, 11, 16, 17, 28, 29], "form": [3, 7, 11, 35], "c4": 3, "a7": 3, "b1": [3, 28, 29, 31], "a4": 3, "7b": 3, "2c": [3, 28, 29, 31], "71": [3, 28, 29, 31], "fa": 3, "db": 3, "e1": [3, 28, 29, 31], "4b": 3, "90": [3, 11, 12, 36, 37], "75": [3, 28, 29, 31], "ff": [3, 21, 22, 23, 27, 30, 35], "15": [3, 6, 11, 25, 36, 37], "60": [3, 11, 12, 28, 29, 31], "85": [3, 28, 29, 31], "89": 3, "would": [3, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "commonnam": [3, 21, 22, 23, 35, 36, 38, 39, 40], "my": [3, 28, 39, 40], "prefer": [3, 21, 35, 38, 39, 40], "root": [3, 11, 14, 15, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "cn": [3, 9, 11, 14, 22, 23, 40], "subject_key_identifi": [3, 21, 22, 23, 35], "subjectkeyidentifi": [3, 21, 35], "a8": 3, "4a": [3, 21, 27, 30, 35], "6a": [3, 28, 29, 31], "63": [3, 11, 21, 27, 30, 35], "04": [3, 21, 27, 28, 29, 30, 31, 35], "7d": [3, 40], "dd": [3, 17, 21, 22, 23, 28, 29, 31, 35], "ba": [3, 21, 27, 30, 35], "e6": [3, 21, 27, 30, 35], "d1": 3, "39": [3, 28, 29, 31], "b7": 3, "a6": [3, 28, 29, 31], "45": 3, "65": 3, "ef": [3, 28, 29, 31], "f3": 3, "a1": [3, 28, 29, 31], "test_certif": 3, "exclud": [3, 17, 21, 22, 23], "leaf": [3, 7], "ident": [3, 17], "last": [3, 16, 21, 35, 38, 39, 40], "furthest": 3, "awai": 3, "Its": 3, "safe_file_oper": [3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "strict": [3, 6, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "oper": [3, 11, 16, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "function": [3, 11, 16, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "ensur": [3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "proper": [3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "permiss": [3, 11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "corrupt": [3, 11, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36, 37, 40], "At": [3, 17], "least": [3, 11, 22, 23, 32, 33], "control": [3, 6, 12, 29, 38, 39], "over": 3, "rate": [3, 4], "limit": [3, 4, 16, 17], "8737": [3, 5, 6], "acme_challenge_cert_help": [3, 15], "prepar": [3, 15], "certificate_complete_chain": [3, 15], "find": [3, 7, 12], "acme_certificate_revok": [3, 15], "account_private_kei": 3, "httpd": [3, 4, 5, 6], "crt": [3, 4, 5, 6, 11, 12, 35, 36, 37, 40], "sample_com_challeng": [3, 5], "hashi": 3, "vault": [3, 16, 29], "lookup": [3, 7, 23, 29, 34, 37, 38], "hashi_vault": 3, "secret": [3, 28], "copi": [3, 7, 9, 11, 12, 23, 36, 37], "www": [3, 7, 9, 10, 11, 14, 17, 21, 22, 23, 35, 36, 37], "resource_valu": 3, "item": [3, 5, 22, 34], "loop": [3, 5, 34], "dict2item": 3, "v01": 3, "30": [3, 11, 28, 29, 31], "aw": 3, "route53": 3, "zone": 3, "txt": [3, 12, 17], "ttl": 3, "enclos": 3, "quot": [3, 17, 18, 22, 24, 25, 26, 28, 31, 36], "regex_replac": [3, 22], "map": [3, 11, 22, 35], "challenge_data_dn": 3, "dst": 3, "x3": 3, "cross": 3, "identrust": 3, "As": [3, 17, 18, 22, 24, 25, 26, 28, 31, 36], "long": [3, 12], "switch": 3, "own": [3, 9, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36, 37, 40], "isrg": 3, "x1": 3, "compat": [3, 11, 17, 25], "older": [3, 16, 25, 26, 28, 29, 31, 36], "client": [3, 11, 12, 14, 17, 22, 23, 36, 37, 38, 39, 40], "o": [3, 11, 14, 17, 18, 22, 23, 24, 25, 26, 28, 31, 36], "digit": 3, "signatur": [3, 7, 15, 17, 21, 22, 23, 33, 35, 36, 38, 39, 40], "co": 3, "4": [3, 4, 8, 14, 16, 21, 22, 23, 25, 31, 32, 33, 35, 36], "itself": [3, 40], "concaten": [3, 7], "full_chain": 3, "token": [3, 17], "a5b1c3d2e9f8g7h6": 3, "12345": [3, 6, 21, 35], "2022": [3, 25], "08": [3, 11, 28, 29, 31], "01t01": 3, "02": [3, 11], "34z": 3, "04t01": 3, "03": [3, 11, 22, 24, 25, 26, 28, 31, 36, 40], "45z": 3, "per": [3, 25], "yet": [3, 6], "_acm": 3, "known": [3, 11, 12, 17, 18, 21, 22, 24, 25, 26, 27, 28, 30, 31, 35, 36, 38, 39, 40], "evagxfads6psrb2lav9izf17dt3juxgj": 3, "pct92wr": 3, "oa": 3, "resource_origin": 3, "origin": [3, 11, 14, 21, 22, 24, 25, 26, 28, 31, 35, 36, 40], "produc": 3, "blob": 3, "put": 3, "acmevalid": 3, "x509": 3, "editor": 3, "rfc8737": 3, "b64decod": [3, 9, 37], "jinja": 3, "filter": [3, 39], "extract": [3, 14, 21, 35, 40], "ilirfxkkxa": 3, "17dt3juxgj": 3, "finalization_uri": 3, "michael": 3, "gruener": 3, "mgruener": 3, "exactli": [4, 14, 18, 21, 26, 35], "private_key_src": [4, 5], "private_key_cont": [4, 5, 22, 23, 25, 31], "valu": 4, "private_key_passphras": [4, 5, 26], "revoke_reason": 4, "One": [4, 17, 18, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 38, 39, 40], "revoc": [4, 11, 15, 22, 23, 38], "reasoncod": 4, "defin": [4, 10, 11, 12, 13, 16, 22, 23, 28, 29, 36, 37, 40], "rfc5280": [4, 22, 23], "possibl": [4, 11, 14, 21, 35], "unspecifi": [4, 17, 18, 22, 24, 25, 26, 28, 31, 36, 38, 39, 40], "keycompromis": 4, "cacompromis": 4, "affiliationchang": 4, "supersed": [4, 22, 23, 38, 39, 40], "cessationofoper": 4, "certificatehold": 4, "removefromcrl": 4, "9": [4, 14, 15, 18, 28, 29, 35, 36], "privilegewithdrawn": 4, "aacompromis": 4, "return": 4, "alreadi": [4, 11, 12, 16, 17, 18, 22, 23, 24, 25, 28, 31, 36, 37, 39, 40], "unchang": [4, 16], "depend": [4, 8, 11, 14, 21, 27, 28, 29, 30, 35], "some": [4, 14, 16, 29, 32, 33, 38, 39], "raw": [5, 6, 26, 28, 29], "convert": [5, 15, 18, 21, 28, 29, 35, 38, 39, 40], "simpl": [5, 9, 10], "gener": [5, 7, 11, 15, 16, 21, 26, 27, 30, 32, 33, 35, 39], "dictsort": 5, "sample_com_challenge_cert": 5, "regular_certif": 5, "deliv": 5, "regular": [5, 6], "connect": [5, 6, 14], "except": [5, 6, 14, 18, 21, 22, 23, 25, 28, 29, 35, 40], "challenge_certif": 5, "achiev": 5, "veri": [5, 10, 39], "nginx": [5, 6], "search": 5, "ssl_preread": 5, "ssl_preread_alpn_protocol": 5, "rout": 5, "private_kei": [5, 17, 29], "identifier_typ": 5, "self": [5, 9, 15, 22, 23, 35, 36, 37], "place": [5, 21, 27, 30, 35], "attempt": [6, 18], "encount": 6, "wish": 6, "investig": 6, "sent": [6, 12], "method": [6, 12, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "otherwis": [6, 11, 16, 17, 18, 21, 22, 24, 25, 26, 28, 31, 35, 36, 38, 39, 40], "fail_on_acme_error": 6, "id": [6, 11, 12], "localhost": [6, 14, 22, 37], "m": [6, 14, 17, 22, 23, 35, 36, 37, 40], "acct": 6, "newaccount": 6, "termsofserviceagre": 6, "account_cr": 6, "locat": [6, 11, 12, 36, 39, 40], "account_info": 6, "to_json": 6, "certificate_request": 6, "someth": [6, 25, 35], "went": 6, "wrong": 6, "output_json": 6, "selectattr": 6, "equalto": 6, "http01challeng": 6, "manual": [6, 12], "a85k3x9f91a4": 6, "random": [6, 12], "33417": 6, "keychang": 6, "meta": 6, "caaident": 6, "termsofservic": 6, "le": 6, "sa": 6, "novemb": 6, "2017": 6, "pdf": 6, "websit": 6, "newnonc": 6, "nonc": 6, "neword": 6, "revokecert": 6, "lowercas": 6, "boulder": 6, "cach": 6, "max": 6, "ag": 6, "close": [6, 16], "length": [6, 18, 36], "904": 6, "applic": [6, 11, 12, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "cooki": 6, "cookies_str": 6, "wed": 6, "07": [6, 21, 27, 30, 35], "nov": 6, "2018": [6, 11], "12": [6, 15, 22, 23, 24, 28, 29, 31, 36, 37], "34": [6, 21, 27, 30, 35], "56": [6, 28, 29, 31], "gmt": [6, 36, 37], "44": [6, 21, 22, 23, 35], "rel": [6, 17, 22, 23, 35, 36, 37, 40], "msg": [6, 14, 29, 34, 38, 39], "ok": 6, "byte": [6, 16, 21, 22, 23, 35], "pragma": 6, "replai": 6, "1234567890abcdefghijklmnopqrstuvwxyzabcdefgh": 6, "200": 6, "transport": [6, 27], "604800": 6, "46161": 6, "frame": 6, "deni": 6, "pars": [6, 7, 14, 21, 25, 27, 35], "output_text": 6, "text": [6, 11, 12], "see": [7, 9, 14, 16, 17, 18, 40], "note": [7, 9, 16, 17, 21, 24, 25, 26, 27, 28, 29, 38], "input_chain": 7, "intermediate_certif": 7, "filenam": [7, 11, 17, 18, 22, 24, 25, 28, 31, 36, 40], "subdirectori": 7, "scan": 7, "root_certif": 7, "www_ansible_com": 7, "completechain": 7, "join": 7, "complete_chain": 7, "rootchain": 7, "input": [7, 12, 25], "python": [8, 14, 21, 24, 25, 27, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "crypto_inform": 8, "show": [8, 9, 10, 29, 36, 38], "openssl_pres": 8, "usr": [8, 17, 18, 22, 24, 25, 26, 28, 31, 36], "bin": [8, 17, 18, 22, 24, 25, 26, 28, 31, 36], "1m": 8, "version_output": 8, "14": [8, 28, 29, 31], "dec": 8, "2021": 8, "python_cryptography_cap": 8, "python_cryptography_instal": 8, "theoret": 8, "higher": [8, 11, 34, 38], "libssl": 8, "has_dsa": 8, "dsa": [8, 10, 18, 21, 27, 28, 29, 30, 32, 33, 35], "has_dsa_sign": 8, "has_ec": 8, "has_ec_sign": 8, "has_ed25519": 8, "ed25519": [8, 18, 21, 27, 28, 29, 30, 32, 33, 35], "has_ed25519_sign": 8, "has_ed448": 8, "ed448": [8, 21, 27, 28, 29, 30, 32, 33, 35], "has_ed448_sign": 8, "has_rsa": 8, "has_rsa_sign": 8, "has_x25519": 8, "x25519": [8, 10, 21, 27, 28, 29, 30, 35], "has_x25519_seri": 8, "serial": [8, 11, 14, 17, 21, 22, 23, 35, 38, 39, 40], "has_x448": 8, "x448": [8, 21, 27, 28, 29, 30, 35], "python_cryptography_import_error": 8, "commun": [9, 10], "crypto": [9, 10], "guid": [9, 10], "exampl": [9, 10], "password": [9, 10, 11, 12, 16, 18, 22, 23, 25, 33, 36, 37, 40], "protect": [9, 10, 16, 18, 22, 23, 28, 29, 31, 33, 36, 37, 40], "secret_ca_passphras": 9, "instruct": [9, 12], "ask": 9, "pai": 9, "commerci": [9, 22, 23], "passphras": [9, 10, 16, 18, 22, 23, 25, 26, 27, 28, 29, 31, 33, 36, 37, 40], "privatekey_path": [9, 10, 21, 22, 23, 25, 30, 31, 32, 33, 35, 36, 37, 40], "privatekey_passphras": [9, 10, 22, 23, 25, 31, 33, 36, 37, 40], "common_nam": [9, 10, 21, 22, 23], "use_common_name_for_san": [9, 22, 23], "san": [9, 10, 11, 22, 23], "don": 9, "basic_constraint": [9, 21, 22, 23, 35], "basic_constraints_crit": [9, 21, 22, 23, 35], "key_usag": [9, 21, 22, 23, 35, 36], "keycertsign": 9, "key_usage_crit": [9, 21, 22, 23, 35], "ca_csr": 9, "x509_certif": [9, 10, 12, 15, 20, 22, 23, 24, 25, 28, 29, 31, 32, 35, 37], "selfsign": [9, 10, 35, 36, 37], "x509_certificate_pip": [9, 15, 22, 23, 28, 29, 31, 35, 36], "server_1": 9, "while": [9, 11, 12, 28, 29, 36, 37], "our": [9, 37], "server_2": 9, "materi": [9, 27, 29], "leav": [9, 27], "respect": [9, 16, 22, 23], "delegate_to": [9, 14, 37], "run_onc": [9, 14], "subject_alt_nam": [9, 10, 11, 21, 22, 23, 35, 36], "ownca": [9, 36, 37], "ownca_path": [9, 36, 37], "ownca_privatekey_path": [9, 36, 37], "ownca_privatekey_passphras": [9, 36, 37], "ownca_not_aft": [9, 36, 37], "365d": [9, 36, 37], "year": [9, 10, 11, 36, 37], "ownca_not_befor": [9, 36, 37], "1d": [9, 28, 29, 31, 35], "yesterdai": 9, "abov": 9, "procedur": 9, "idempot": [9, 16, 17, 25, 29, 36, 37, 40], "extend": [9, 11], "stat": 9, "certificate_exist": 9, "slurp": [9, 37], "els": [9, 25], "kind": 10, "start": [10, 21, 27, 30, 35, 36, 37], "paramet": [10, 15, 34], "4096": [10, 18, 24, 27, 28, 29, 30], "bit": [10, 18, 21, 24, 27, 28, 29, 30, 35], "size": [10, 12, 16, 18, 21, 24, 27, 28, 29, 30, 35], "changem": 10, "proce": 10, "selfsigned_not_aft": [10, 36, 37], "roughli": 10, "selfsigned_not_befor": [10, 36, 37], "now": [10, 11, 17, 36, 37], "properti": 10, "constraint": [10, 22, 23], "organization_nam": [10, 22, 23], "inc": [10, 11], "reissu": 11, "credenti": [11, 12, 36, 37], "organ": [11, 38], "system": [11, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "those": [11, 17, 18, 22, 24, 25, 26, 28, 31, 36], "pyyaml": [11, 12], "11": [11, 12, 17, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 35, 36, 40], "additional_email": 11, "receiv": [11, 12, 17, 18, 22, 24, 25, 26, 28, 31, 36], "deliveri": 11, "notic": 11, "notif": 11, "backup": [11, 18, 22, 24, 25, 26, 28, 29, 31, 36, 37, 40], "made": [11, 12, 17], "cert_expiri": 11, "compliant": 11, "2020": [11, 17, 18, 22, 24, 25, 26, 28, 31, 36], "23": 11, "23t15": 11, "00": [11, 17, 21, 22, 23, 28, 29, 31, 35, 36, 37], "05z": 11, "request_typ": 11, "issuanc": [11, 36, 37], "subsequ": 11, "initi": [11, 14], "month": [11, 36, 37], "choos": 11, "adjust": [11, 18, 36, 37], "eastern": 11, "est": [11, 36, 37], "could": [11, 22, 24, 27, 28, 29, 36, 37], "unintend": 11, "effect": 11, "pool": 11, "inventori": 11, "model": 11, "cert_lifetim": 11, "lifetim": [11, 36, 37], "cert_typ": 11, "cds_individu": 11, "cds_group": 11, "cds_ent_lit": [11, 36, 37], "cds_ent_pro": [11, 36, 37], "smime_": [11, 36, 37], "p1y": 11, "p2y": 11, "p3y": 11, "standard_ssl": [11, 36, 37], "advantage_ssl": [11, 36, 37], "uc_ssl": [11, 36, 37], "ev_ssl": [11, 36, 37], "wildcard_ssl": [11, 36, 37], "private_ssl": [11, 36, 37], "pd_ssl": [11, 36, 37], "code_sign": 11, "ev_code_sign": 11, "client_id": [11, 12], "under": [11, 12], "primari": [11, 12], "cannot": [11, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 40], "distinguish": 11, "repres": 11, "64": 11, "around": [11, 27], "overrid": [11, 34, 38], "eku": 11, "ou": [11, 14, 22, 23], "organiz": 11, "unit": 11, "replac": [11, 29], "ti": 11, "ct_log": 11, "complianc": 11, "browser": 11, "transpar": 11, "ct": 11, "log": [11, 17, 27, 28, 29], "best": [11, 17, 18, 22, 24, 25, 26, 28, 31, 36], "practic": 11, "techniqu": 11, "owner": [11, 12, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "monitor": 11, "elig": [11, 12], "custom_field": 11, "date1": 11, "date2": 11, "date3": 11, "date4": 11, "date5": 11, "dropdown1": 11, "dropdown": 11, "dropdown2": 11, "dropdown3": 11, "dropdown4": 11, "dropdown5": 11, "email1": 11, "email2": 11, "email3": 11, "email4": 11, "email5": 11, "number1": 11, "float": [11, 16], "number2": 11, "number3": 11, "number4": 11, "number5": 11, "text1": 11, "maximum": [11, 21, 27, 30, 35, 36, 37], "500": 11, "charact": 11, "text10": 11, "text11": 11, "text12": 11, "text13": 11, "text14": 11, "text15": 11, "text2": 11, "text3": 11, "text4": 11, "text5": 11, "text6": 11, "text7": 11, "text8": 11, "text9": 11, "server_auth": 11, "client_auth": 11, "server_and_client_auth": 11, "end_user_key_storage_agr": 11, "user": [11, 15, 16, 18, 22, 24, 25, 26, 28, 31, 36, 40], "code": 11, "cryptograph": [11, 15], "hardwar": 11, "csp": 11, "subscript": 11, "acknowledg": 11, "entrust_api_client_cert_key_path": [11, 12, 36, 37], "entrust_api_client_cert_path": [11, 12, 36, 37], "entrust_api_kei": [11, 12, 36, 37], "entrust_api_specification_path": [11, 12, 36, 37], "configur": [11, 12, 13, 16, 17, 18, 22, 24, 25, 26, 28, 29, 31, 34, 36, 37, 38, 40], "keep": [11, 12, 28, 36, 37], "download": [11, 12, 36, 37], "cloud": [11, 12, 36, 37], "net": [11, 12, 36, 37], "entrustcloud": [11, 12, 36, 37], "cm": [11, 12, 36, 37], "yaml": [11, 12, 17, 18, 22, 24, 25, 26, 28, 31, 36, 37], "entrust_api_us": [11, 12, 36, 37], "usernam": [11, 12, 22, 36, 37], "regardless": 11, "within": [11, 12], "past": [11, 35], "full_chain_path": 11, "unless": [11, 12, 16, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "behavior": [11, 18, 25, 28, 29, 36], "neither": 11, "nor": 11, "reus": 11, "unapprov": 11, "failur": 11, "reserv": 11, "futur": 11, "calcul": 11, "tracking_id": 11, "obtain": [11, 12], "act": [11, 17], "upon": [11, 21, 27, 30, 35], "exmapl": 11, "refer": 11, "validate_onli": 11, "cautiou": 11, "along": 11, "requester_email": 11, "track": [11, 36, 37], "requester_nam": 11, "requester_phon": 11, "phone": [11, 36, 37], "arrai": 11, "subjectaltnam": [11, 22, 23], "understand": [11, 16], "tld": 11, "save": [11, 24], "referenc": 11, "tracking_info": 11, "free": 11, "attach": [11, 22, 23], "partial": 11, "bare": 11, "minimum": [11, 18, 36, 37], "jo": [11, 36], "jdoe": [11, 22, 36], "555": [11, 36], "5555": [11, 36], "apiusernam": [11, 12, 36], "lv": [11, 12, 36], "32": [11, 12, 17, 21, 27, 28, 29, 30, 31, 35, 36], "cd9lnt": [11, 12, 36], "20": [11, 22], "79": [11, 28, 29, 31], "migrat": 11, "2378915": 11, "rather": 11, "overridden": [11, 24, 25], "testcertif": 11, "administr": [11, 12], "via": [11, 36], "itsupport": 11, "jsmith": 11, "admin": [11, 12], "invoic": 11, "25": [11, 28, 29, 31], "342": 11, "sale": 11, "red": 11, "backup_fil": [11, 22, 24, 25, 26, 28, 31, 36, 40], "2019": [11, 17, 22, 24, 25, 26, 28, 31, 36, 37, 40], "09": [11, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 40], "22": [11, 21, 22, 23, 24, 25, 26, 28, 29, 31, 35, 36, 40], "backup_full_chain_fil": 11, "253": 11, "cert_detail": 11, "guarante": 11, "forward": [11, 17], "releas": [11, 17], "take": [11, 17, 18, 21, 22, 24, 27, 28, 30, 31, 35, 36, 38, 39, 40], "howev": [11, 16, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "audit": 11, "cert_statu": 11, "expand": 11, "approv": [11, 12], "declin": [11, 12], "na": 11, "pending_quorum": 11, "suspend": 11, "serial_numb": [11, 14, 17, 35, 38, 39, 40], "1235262234164342": 11, "380079": 11, "chri": [11, 12], "trufan": [11, 12], "ctrufan": [11, 12], "verification_method": 12, "domain_statu": 12, "dns_content": 12, "dns_locat": 12, "dns_resource_typ": 12, "web_serv": 12, "file_cont": 12, "file_loc": 12, "e": [12, 22, 23], "were": 12, "pure": 12, "domain_nam": 12, "reverifi": 12, "verification_email": 12, "ownership": [12, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "whoi": 12, "construct": 12, "webmast": 12, "hostmast": 12, "postmast": 12, "subdomain": 12, "top": 12, "level": [12, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "example1": 12, "example2": 12, "preconstruct": 12, "namespac": 12, "exact": [12, 40], "verif": 12, "prove": 12, "verification_dns_record_typ": 12, "There": [12, 16], "small": [12, 15], "delai": 12, "typic": 12, "Be": 12, "awar": 12, "mani": [12, 14, 40], "ecs_certif": [12, 15], "revalid": 12, "fewer": [12, 36, 37], "ev": 12, "belong": [12, 22, 23], "expect": [12, 28, 29, 35, 36, 37, 40], "ab23cd41432522ff2526920393982fab": 12, "_pki": 12, "cancel": 12, "initial_verif": 12, "re_verif": 12, "ev_days_remain": 12, "submiss": 12, "never": [12, 17, 18, 28, 29, 36, 37, 40], "greater": [12, 17], "ov_days_remain": 12, "ev_elig": 12, "94": [12, 21, 27, 28, 29, 30, 31, 35], "ov_elig": 12, "abcd": 12, "ov": 12, "129": 12, "declar": 13, "core": [13, 15], "configu": 13, "No": 13, "sni": 14, "proxy_host": 14, "ca_cert": [14, 37], "fine": 14, "proxi": 14, "proxy_port": 14, "8080": 14, "server_nam": 14, "starttl": 14, "mysql": 14, "succe": 14, "rdp": 14, "3389": 14, "googl": 14, "443": 14, "expire_dai": 14, "not_aft": [14, 35, 36], "to_datetim": 14, "d": [14, 17, 35, 36, 37, 40], "h": [14, 17, 35, 36, 37, 40], "sz": 14, "ansible_date_tim": 14, "iso8601": 14, "dt": 14, "asn1_data": 14, "asn": [14, 21, 35, 36, 37, 38, 39, 40], "usual": [14, 17, 21, 35], "malform": [14, 21, 35], "critic": [14, 21, 22, 23, 35, 38, 39, 40], "not_befor": [14, 35, 36], "signature_algorithm": [14, 17, 35, 36], "john": 14, "westcott": 14, "iv": 14, "author": 15, "github": 15, "newer": [15, 17, 28, 29, 32, 33], "matrix": 15, "room": 15, "im": 15, "question": 15, "irc": 15, "channel": [15, 27], "libera": 15, "network": 15, "mail": 15, "project": 15, "subscrib": 15, "acm": [15, 36], "requir": [15, 34], "send": [15, 25, 38, 39], "direct": 15, "crypto_info": 15, "capabl": 15, "entrust": [15, 36, 37], "ecs_domain": 15, "get_certif": 15, "port": [15, 17], "luks_devic": 15, "luk": 15, "devic": 15, "openssh_cert": 15, "openssh": [15, 31], "openssh_keypair": [15, 31], "openssl_csr_info": [15, 22, 23, 36], "openssl_dhparam": [15, 22, 23, 25, 28, 29, 31, 36, 37], "diffi": [15, 22, 23, 25, 28, 29, 31, 36, 37], "hellman": [15, 22, 23, 25, 28, 29, 31, 36, 37], "openssl_pkcs12": [15, 22, 23, 24, 28, 29, 31, 36, 37], "pkc": [15, 17, 22, 23, 24, 28, 29, 31, 36, 37], "archiv": [15, 22, 23, 24, 28, 29, 31, 36, 37], "openssl_privatekey_convert": 15, "openssl_privatekey_info": [15, 28, 29, 30, 36], "openssl_publickei": [15, 22, 23, 24, 25, 26, 28, 29, 30, 36, 37], "openssl_publickey_info": 15, "openssl_signatur": [15, 32], "openssl_signature_info": [15, 33], "x509_certificate_info": [15, 19, 36], "509": [15, 39], "x509_crl": [15, 39], "crl": [15, 22, 23], "x509_crl_info": 15, "split_pem": 15, "split": 15, "destroi": 16, "open": 16, "cryptsetup": 16, "wipef": 16, "lsblk": 16, "blkid": 16, "label": [16, 21, 35, 38, 39, 40], "uuid": 16, "cipher": [16, 28, 29], "pre": [16, 25], "kernel": 16, "ae": [16, 28, 29, 31], "plain": 16, "spec": 16, "essiv": 16, "cbc": 16, "sha256": [16, 18, 21, 22, 23, 27, 28, 29, 30, 31, 35, 36, 37, 40], "dev": 16, "sda1": 16, "force_remove_last_kei": 16, "bewar": 16, "hash": [16, 21, 27, 30, 35], "setup": 16, "scheme": 16, "volum": 16, "digest": [16, 22, 23, 36, 37, 38, 39, 40], "keyfil": 16, "unlock": 16, "plaintext": 16, "danger": 16, "keysiz": [16, 28, 29], "luks2": 16, "later": 16, "luks1": 16, "new_keyfil": 16, "add": [16, 17, 18, 22, 24, 25, 26, 28, 31, 36], "keyslot": 16, "new_passphras": 16, "pbkdf": 16, "deriv": 16, "argon2i": 16, "argon2id": 16, "pbkdf2": 16, "iteration_count": 16, "iter": 16, "count": 16, "iteration_tim": 16, "millisecond": 16, "memori": 16, "cost": 16, "kilobyt": 16, "argon": 16, "parallel": 16, "thread": 16, "perf_no_read_workqueu": 16, "bypass": 16, "dm": 16, "crypt": 16, "intern": 16, "workqueu": 16, "synchron": 16, "perf_no_write_workqueu": 16, "perf_same_cpu_crypt": 16, "cpu": 16, "io": 16, "unbound": 16, "balanc": 16, "perf_submit_from_crypt_cpu": 16, "offload": 16, "separ": [16, 17, 21, 22, 23, 35], "situat": [16, 18, 28, 29], "block": [16, 29], "singl": 16, "degrad": 16, "significantli": 16, "persist": 16, "metadata": 16, "them": [16, 24, 31], "next": [16, 27], "remove_keyfil": 16, "filesystem": [16, 17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "remove_passphras": 16, "sector_s": 16, "sector": 16, "lock": 16, "suffic": 16, "explicit": 16, "With": 16, "loop0": 16, "foo": [16, 17], "mycrypt": 16, "keyfile2": 16, "personallabelnam": 16, "03ecd578": 16, "fad4": 16, "4e6c": 16, "9348": 16, "842e3e8fa340": 16, "suppli": 16, "c1da9a58": 16, "2fde": 16, "4256": 16, "9d9f": 16, "6ab008b4dd1b": 16, "jan": 16, "pokorni": 16, "japokorn": 16, "regener": [17, 18, 22, 23, 24, 25, 28, 29, 31, 36, 37, 40], "ssh": [17, 18], "keygen": [17, 18], "attr": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "flag": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "look": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "man": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "page": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "chattr": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "displai": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "lsattr": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "equival": [17, 18, 28, 29], "fed": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "chown": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "preserv": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "ignore_timestamp": [17, 36, 37, 40], "valid_from": 17, "valid_to": 17, "meet": 17, "chmod": [17, 18, 22, 24, 25, 26, 28, 31, 36], "rememb": [17, 18, 22, 24, 25, 26, 28, 31, 36], "octal": [17, 18, 22, 24, 25, 26, 28, 31, 36], "zero": [17, 18, 22, 24, 25, 26, 28, 31, 36], "parser": [17, 18, 22, 24, 25, 26, 28, 31, 36], "0644": [17, 18, 22, 24, 25, 26, 28, 31, 36], "01777": [17, 18, 22, 24, 25, 26, 28, 31, 36], "644": [17, 18, 22, 24, 25, 26, 28, 31, 36], "1777": [17, 18, 22, 24, 25, 26, 28, 31, 36], "convers": [17, 18, 22, 24, 25, 26, 28, 31, 36], "rule": [17, 18, 22, 24, 25, 26, 28, 31, 36], "decim": [17, 18, 22, 24, 25, 26, 28, 31, 36], "unexpect": [17, 18, 22, 24, 25, 26, 28, 31, 36], "rwx": [17, 18, 22, 24, 25, 26, 28, 31, 36], "rw": [17, 18, 22, 24, 25, 26, 28, 31, 36], "g": [17, 18, 21, 22, 24, 25, 26, 27, 28, 30, 31, 35, 36], "r": [17, 18, 21, 22, 24, 25, 26, 27, 28, 30, 31, 35, 36], "umask": [17, 18, 22, 24, 25, 26, 28, 31, 36], "newli": [17, 18, 22, 24, 25, 26, 28, 31, 36], "cve": [17, 18, 22, 24, 25, 26, 28, 31, 36], "1736": [17, 18, 22, 24, 25, 26, 28, 31, 36], "clear": 17, "shell": 17, "agent": 17, "permit": [17, 21, 22, 23], "pty": 17, "alloc": 17, "rc": 17, "sshd": 17, "x11": 17, "address_list": 17, "comma": 17, "netmask": 17, "pair": [17, 22, 23, 40], "cidr": 17, "pkcs11_provid": 17, "resid": 17, "share": 17, "libpkcs11": 17, "signing_kei": 17, "princip": 17, "By": [17, 18, 22, 24, 25, 26, 28, 29, 31, 36, 40], "public_kei": [17, 18, 21, 27, 35, 36], "unread": 17, "partial_idempot": [17, 18, 28, 29], "valid_at": [17, 35, 36], "full_idempot": [17, 18, 28, 29], "also": [17, 18, 40], "compar": 17, "selevel": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "selinux": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "context": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "ml": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "mc": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "sometim": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "rang": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "_default": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "portion": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "polici": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "keyrevocationlist": 17, "again": [17, 38, 39], "serol": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "role": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "setyp": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "seuser": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "sha": 17, "refus": 17, "sha2": 17, "512": 17, "correspond": [17, 18, 28, 29], "sshd_config": 17, "casignaturealgorithm": 17, "keyword": [17, 29, 35, 36], "prior": 17, "unsafe_writ": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "influenc": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "atom": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "prevent": [17, 18, 22, 24, 25, 26, 27, 28, 31, 36, 40], "inconsist": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "just": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "broken": [17, 18, 22, 24, 25, 26, 28, 29, 31, 36, 40], "docker": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "mount": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "insid": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "unsaf": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "manner": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "doesn": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "race": [17, 18, 22, 24, 25, 26, 28, 31, 36, 40], "use_ag": 17, "interpret": [17, 35, 36, 37, 40], "utc": [17, 35, 36, 37, 39, 40], "mainli": 17, "timespec": [17, 35, 36, 37, 40], "NOT": [17, 29, 36, 37, 40], "absolut": [17, 21, 27, 30, 35, 36, 37, 39, 40], "yyyi": 17, "mm": 17, "ddthh": 17, "ss": 17, "hh": 17, "w": [17, 21, 27, 30, 35, 36, 37, 40], "32w1d2h": [17, 35, 36, 37, 40], "1970": 17, "01t00": 17, "earlier": [17, 36, 37], "express": 17, "comparison": 17, "forev": 17, "pub": [17, 18, 30], "week": [17, 35], "32w": 17, "2w": 17, "examplehost": 17, "21": 17, "2001": 17, "tmp": [17, 18, 32, 33], "bla": 17, "ca_public_kei": 17, "info": [17, 21, 35], "l": [17, 22, 23], "f": 17, "david": [17, 18], "kainz": [17, 18], "lolcub": [17, 18], "rsa1": 18, "ecdsa": [18, 32, 33], "opensshbin": 18, "decrypt": [18, 25], "private_key_format": 18, "pkcs1": [18, 26, 28, 29], "keypair": 18, "pkcs8": [18, 26, 28, 29], "conform": [18, 28, 29], "unknown": [18, 21, 27, 28, 29, 30, 35], "therefor": 18, "1024": 18, "2048": [18, 24, 25, 28, 29], "suffici": 18, "fip": 18, "186": 18, "three": [18, 35, 36, 37, 40], "384": 18, "521": 18, "fix": 18, "id_ssh_rsa": 18, "super_secret_password": 18, "id_ssh_dsa": 18, "fingerprint": [18, 21, 27, 28, 29, 30, 31, 35], "r4yczxihvjedh2olfjvgi6y5xaytdcwk8vxkyzvyyfm": 18, "aaaab3nza": 18, "vel4e3xcw": 18, "interact": [21, 27, 30, 35, 36, 37], "name_encod": [21, 35, 38, 39, 40], "idna": [21, 35, 38, 39, 40], "idna2008": [21, 35, 38, 39, 40], "idna2003": [21, 35, 38, 39, 40], "unicod": [21, 35, 38, 39, 40], "remot": [21, 27, 30, 35, 36, 37, 39, 40], "load": [21, 26, 27, 30, 35], "dump": [21, 25, 27, 30, 35], "authority_cert_issu": [21, 22, 23, 35], "idn": [21, 35, 38, 39, 40], "handl": [21, 35, 38, 39, 40], "authority_cert_serial_numb": [21, 22, 23, 35], "hexadecim": [21, 35], "33": [21, 22, 23, 27, 28, 29, 30, 31, 35], "55": [21, 22, 23, 35], "66": [21, 22, 23, 28, 29, 31, 35], "77": [21, 22, 23, 28, 29, 31, 35], "88": [21, 22, 23, 28, 29, 31, 35], "99": [21, 22, 23, 28, 29, 31, 35], "aa": [21, 22, 23, 27, 30, 35], "bb": [21, 22, 23, 35], "cc": [21, 22, 23, 28, 29, 31, 35], "ee": [21, 22, 23, 28, 29, 31, 35], "pathlen": [21, 35], "extended_key_usag": [21, 22, 23, 35, 36], "biometr": [21, 35], "dvc": [21, 35, 36], "stamp": [21, 35], "extended_key_usage_crit": [21, 22, 23, 35], "extensions_by_oid": [21, 35, 36], "oid": [21, 35], "24": [21, 28, 29, 31, 35], "mamcaqu": [21, 35], "der": [21, 35, 38, 39, 40], "encipher": [21, 22, 23, 35, 36], "name_constraints_crit": [21, 22, 23], "name_constraint": 21, "name_constraints_exclud": [21, 22, 23], "subtre": [21, 22, 23], "name_constraints_permit": [21, 22, 23], "somedomain": [21, 22, 23], "ocsp_must_stapl": [21, 22, 23, 35], "ocsp": [21, 22, 23, 35], "stapl": [21, 22, 23, 35], "ocsp_must_staple_crit": [21, 22, 23, 35], "begin": [21, 27, 35], "nmiicijanbgkqhkig9w0baqefaaocag8a": [21, 27, 35], "public_key_data": [21, 35], "ecc": [21, 27, 28, 29, 30, 35], "public_key_typ": [21, 35], "expon": [21, 27, 30, 35], "exponent_s": [21, 27, 30, 35], "subgroup": [21, 27, 30, 35], "span": [21, 27, 30, 35], "prime": [21, 27, 30, 35], "modulu": [21, 27, 30, 35], "arithmet": [21, 27, 30, 35], "q": [21, 27, 30, 35], "divid": [21, 27, 30, 35], "coordin": [21, 27, 30, 35], "publicli": [21, 27, 30, 35], "whose": [21, 27, 30, 35, 37], "discret": [21, 27, 30, 35], "logarithm": [21, 27, 30, 35], "public_key_fingerprint": [21, 27, 35], "comput": [21, 27, 30, 35], "d4": [21, 27, 28, 29, 30, 31, 35], "b3": [21, 27, 28, 29, 30, 31, 35], "6d": [21, 27, 28, 29, 30, 31, 35], "c8": [21, 27, 30, 35], "ce": [21, 27, 30, 35], "4e": [21, 27, 28, 29, 30, 31, 35], "f6": [21, 27, 28, 29, 30, 31, 35], "29": [21, 27, 28, 29, 30, 31, 35], "4d": [21, 27, 28, 29, 30, 31, 35], "92": [21, 27, 30, 35], "a3": [21, 27, 30, 35], "b0": [21, 27, 30, 35], "c2": [21, 27, 30, 35], "bd": [21, 27, 30, 35], "bf": [21, 27, 30, 35], "43": [21, 27, 28, 29, 30, 31, 35], "0f": [21, 27, 28, 29, 30, 31, 35], "51": [21, 27, 28, 29, 30, 31, 35], "95": [21, 27, 30, 35], "2f": [21, 27, 28, 29, 30, 31, 35], "sha512": [21, 27, 28, 29, 30, 31, 35], "f7": [21, 27, 30, 35], "f0": [21, 27, 28, 29, 30, 31, 35], "8b": [21, 27, 30, 35], "5f": [21, 27, 28, 29, 30, 31, 35], "f9": [21, 27, 30, 35], "61": [21, 27, 30, 35], "0a": [21, 27, 30, 35], "68": [21, 27, 28, 29, 30, 31, 35], "f1": [21, 27, 28, 29, 30, 31, 35], "signature_valid": 21, "repeat": [21, 25, 35, 38, 39, 40], "emailaddress": [21, 22, 23, 35], "subject_alt_name_crit": [21, 22, 23, 35], "subject_ord": [21, 22, 23, 35, 36], "tupl": [21, 22, 23, 35, 38, 39, 40], "yani": [21, 22, 23, 27, 28, 29, 31, 35, 36, 37], "guenan": [21, 22, 23, 27, 28, 29, 31, 35, 36, 37], "spredzi": [21, 22, 23, 27, 28, 29, 31, 35, 36, 37], "seem": [22, 23, 36, 37], "overwrit": [22, 24, 28, 29, 36, 37], "keyusag": [22, 23], "extendedkeyusag": [22, 23], "basicconstraint": [22, 23], "rid": [22, 23], "dirnam": [22, 23], "othernam": [22, 23], "ones": [22, 23, 24], "mostli": [22, 23], "hex": [22, 23], "colon": [22, 23], "overwrot": [22, 24, 25, 26, 28, 31, 36, 40], "accid": [22, 24, 25, 26, 28, 31, 36, 40], "basicconstraints_crit": [22, 23], "country_nam": [22, 23], "c": [22, 23], "countrynam": [22, 23], "create_subject_key_identifi": [22, 23], "crl_distribution_point": [22, 23], "distribut": [22, 23], "crl_issuer": [22, 23], "full_nam": [22, 23], "relative_nam": [22, 23], "key_compromis": [22, 23, 38, 39, 40], "ca_compromis": [22, 23, 38, 39, 40], "affiliation_chang": [22, 23, 38, 39, 40], "cessation_of_oper": [22, 23, 38, 39, 40], "certificate_hold": [22, 23, 38, 39, 40], "privilege_withdrawn": [22, 23, 38, 39, 40], "aa_compromis": [22, 23, 38, 39, 40], "email_address": [22, 23], "extkeyusag": [22, 23], "extkeyusage_crit": [22, 23], "extendedkeyusage_crit": [22, 23], "keyusage_crit": [22, 23], "locality_nam": [22, 23], "localitynam": [22, 23], "ocspmuststapl": [22, 23], "rfc7633": [22, 23], "ocspmuststaple_crit": [22, 23], "reject": [22, 23], "organizationnam": [22, 23, 35, 38, 39, 40], "organizational_unit_nam": [22, 23], "organizationalunitnam": [22, 23], "privatekey_cont": [22, 23, 25, 31, 33, 36, 37, 40], "return_cont": [22, 24, 25, 28, 31, 36, 40], "state_or_province_nam": [22, 23], "st": [22, 23], "stateorprovincenam": [22, 23], "compon": [22, 23, 40], "usecommonnameforsan": [22, 23], "subjectaltname_crit": [22, 23], "row": [22, 23, 40], "fill": [22, 23], "2986": [22, 23], "unsupport": [22, 23], "inlin": [22, 23, 31, 37], "fr": 22, "dynam": 22, "with_dict": 22, "dns_server": 22, "special": 22, "digitalsignatur": [22, 23], "keyagr": [22, 23], "clientauth": [22, 23], "winrm": 22, "auth": 22, "311": 22, "utf8": 22, "pathlenconstraint": [22, 23], "privatekei": [22, 23, 25, 26, 28, 29, 31, 40], "dh": 24, "param": 24, "detect": [24, 25], "Or": 24, "dhparam": 24, "thom": 24, "wigger": 24, "thomwigg": 24, "pyopenssl": 25, "iter_s": 25, "maciter_s": 25, "export": [25, 26, 28, 29], "certificate_path": [25, 32, 33], "encryption_level": 25, "compatibility2022": 25, "softwar": 25, "38": [25, 28, 29, 31], "friendly_nam": 25, "friendli": 25, "50000": 25, "other_certif": 25, "ca_certif": 25, "other_certificates_parse_al": 25, "pkcs12": 25, "mechan": 25, "safe": 25, "addition": 25, "backward": 25, "opt": 25, "p12": 25, "raclett": 25, "ca_bundl": 25, "bundl": [25, 34], "0600": [25, 26, 28], "regen": 25, "guillaum": 25, "delpierr": 25, "gdelpierr": 25, "dest_passphras": 26, "dest_path": 26, "src_content": 26, "src_path": 26, "src_passphras": 26, "fake": 27, "key_is_consist": 27, "check_consist": 27, "potenti": 27, "side": 27, "attack": 27, "return_private_key_data": 27, "machin": [27, 36, 37], "can_load_kei": 27, "can_parse_kei": 27, "private_data": 27, "public_data": [27, 30], "eddsa": [28, 29], "particular": [28, 29], "maxim": [28, 29], "interoper": [28, 29], "secp384r1": [28, 29], "secp256r1": [28, 29], "iana": [28, 29], "registri": [28, 29], "secp224r1": [28, 29], "secp256k1": [28, 29], "secp521r1": [28, 29], "discourag": [28, 29], "secp192r1": [28, 29], "brainpoolp256r1": [28, 29], "brainpoolp384r1": [28, 29], "brainpoolp512r1": [28, 29], "sect163k1": [28, 29], "sect163r2": [28, 29], "sect233k1": [28, 29], "sect233r1": [28, 29], "sect283k1": [28, 29], "sect283r1": [28, 29], "sect409k1": [28, 29], "sect409r1": [28, 29], "sect571k1": [28, 29], "sect571r1": [28, 29], "tradit": [28, 29], "auto_ignor": [28, 29], "mismatch": [28, 29], "format_mismatch": [28, 29], "everyth": [28, 29, 40], "treat": [28, 35, 40], "appropri": 28, "care": 28, "shown": 28, "reference_appendic": 28, "faq": 28, "minim": [28, 29], "hashlib": [28, 29, 31], "md5": [28, 29, 31], "84": [28, 29, 31], "72": [28, 29, 31], "8d": [28, 29, 31], "b5": [28, 29, 31], "6c": [28, 29, 31], "37": [28, 29, 31], "83": [28, 29, 31], "f5": [28, 29, 31], "4c": [28, 29, 31], "sha1": [28, 29, 31], "7c": [28, 29, 31], "5d": [28, 29, 31], "eb": [28, 29, 31], "41": [28, 29, 31], "7e": [28, 29, 31], "1a": [28, 29, 31], "c7": [28, 29, 31], "f8": [28, 29, 31], "sha224": [28, 29, 31], "19": [28, 29, 31], "ac": [28, 29, 31], "ed": [28, 29, 31], "18": [28, 29, 31, 36, 37], "50": [28, 29, 31], "d3": [28, 29, 31], "06": [28, 29, 31, 36, 37], "5c": [28, 29, 31], "b2": [28, 29, 31], "91": [28, 29, 31], "52": [28, 29, 31], "8c": [28, 29, 31], "cb": [28, 29, 31], "d5": [28, 29, 31], "e9": [28, 29, 31], "9b": [28, 29, 31], "46": [28, 29, 31], "ab": [28, 29, 31], "70": [28, 29, 31], "cf": [28, 29, 31], "76": [28, 29, 31], "4f": [28, 29, 31], "57": [28, 29, 31], "6e": [28, 29, 31], "97": [28, 29, 31], "df": [28, 29, 31], "de": [28, 29, 31], "sha384": [28, 29, 31], "d9": [28, 29, 31], "40": [28, 29, 31], "59": [28, 29, 31], "c3": [28, 29, 31], "a2": [28, 29, 31], "e4": [28, 29, 31], "0b": [28, 29, 31], "1c": [28, 29, 31], "0c": [28, 29, 31], "9e": [28, 29, 31], "af": [28, 29, 31], "da": [28, 29, 31], "2e": [28, 29, 31], "c0": [28, 29, 31], "9a": [28, 29, 31], "3a": [28, 29, 31], "3d": [28, 29, 31], "fd": [28, 29, 31], "5e": [28, 29, 31], "48": [28, 29, 31], "9f": [28, 29, 31], "fe": [28, 29, 31], "7f": [28, 29, 31], "3f": [28, 29, 31], "cd": [28, 29, 31], "a5": [28, 29, 31], "e7": [28, 29, 31], "13": [28, 29, 31], "82": [28, 29, 31], "87": [28, 29, 31], "1f": [28, 29, 31], "28": [28, 29, 31], "53": [28, 29, 31], "86": [28, 29, 31], "69": [28, 29, 31], "35": [28, 29, 31], "1e": [28, 29, 31], "consol": 29, "relat": 29, "content_base64": 29, "return_current_kei": 29, "value_specified_in_no_log_paramet": 29, "async": 29, "reveal": 29, "TO": 29, "OR": 29, "IN": 29, "sop": 29, "sops_encrypt": 29, "content_text": 29, "overwritten": 29, "set_fact": 29, "publickei": 31, "certificate_cont": [32, 37], "example_fil": [32, 33], "sig": [32, 33], "patrick": [32, 33], "pichler": [32, 33], "aveexi": [32, 33], "marku": [32, 33, 35, 36, 37], "teufelberg": [32, 33, 35, 36, 37], "markusteufelberg": [32, 33, 35, 36, 37], "low": [34, 38], "high": [34, 38], "prioriti": [34, 38], "lower": [34, 38], "openssl_certificate_info": 35, "short": [35, 36], "redirect": [35, 36], "fqcn": [35, 36], "dict": 35, "word": [35, 39], "pattern": [35, 36, 37, 39, 40], "yyyymmddhhmmssz": [35, 36, 37, 39, 40], "csr_path": [35, 36, 37], "tomorrow": 35, "point_1": 35, "point_2": 35, "3w": 35, "whole": 35, "issuer_ord": [35, 38, 39, 40], "issuer_uri": 35, "20190413202428z": [35, 36, 38, 39, 40], "20190331202428z": [35, 36, 40], "ocsp_uri": 35, "respond": 35, "1234": [35, 38, 39, 40], "sha256withrsaencrypt": [35, 36, 38, 39, 40], "notion": [36, 37], "openssl_certif": 36, "intend": [36, 37], "tini": 36, "acme_accountkey_path": 36, "accountkei": 36, "acme_chain": 36, "acme_challenge_path": 36, "80": 36, "job": 36, "entrust_cert_typ": [36, 37], "entrust_not_aft": [36, 37], "stop": [36, 37], "365": [36, 37], "cover": [36, 37], "entrust_requester_email": [36, 37], "entrust_requester_nam": [36, 37], "entrust_requester_phon": [36, 37], "better": [36, 37], "ownca_cont": [36, 37], "ownca_create_authority_key_identifi": [36, 37], "ownca_create_subject_key_identifi": [36, 37], "ski": [36, 37], "create_if_not_provid": [36, 37], "always_cr": [36, 37], "never_cr": [36, 37], "ownca_digest": [36, 37], "On": [36, 37], "maco": [36, 37], "onward": [36, 37], "period": [36, 37], "825": [36, 37], "appl": [36, 37], "en": [36, 37], "ht210176": [36, 37], "3650d": [36, 37], "ownca_privatekey_cont": [36, 37], "resp": [36, 37], "ownca_vers": [36, 37], "nowadai": [36, 37], "almost": [36, 37], "emul": 36, "selfsigned_create_subject_key_identifi": [36, 37], "selfsigned_digest": [36, 37], "selfsigned_notaft": [36, 37], "selfsigned_notbefor": [36, 37], "selfsigned_vers": [36, 37], "minut": [36, 37, 40], "mandatori": [36, 37, 40], "dedic": [36, 37], "onc": [36, 37, 40], "ansible_ca": 36, "assertonli": 36, "invalid_at": 36, "valid_in": 36, "one_day_ten_hour": 36, "1d10h": 36, "fixed_timestamp": 36, "20200331202428z": 36, "ten_second": 36, "result_csr": 36, "result_privatekei": 36, "sha512withrsaencrypt": 36, "subject_strict": 36, "issuer_strict": 36, "has_expir": 36, "key_usage_strict": 36, "extended_key_usage_strict": 36, "subject_alt_name_strict": 36, "ie": 37, "ownca_cert": 37, "ownca_privatekei": 37, "hunter2": 37, "the_csr": 37, "key1": 38, "value1": 38, "key2": 38, "value2": 38, "list_revoked_certif": [38, 39], "larg": [38, 39], "enumer": [38, 39], "last_upd": [38, 39, 40], "next_upd": [38, 39, 40], "revoked_certif": [38, 39, 40], "invalidity_d": [38, 39, 40], "suspect": [38, 39, 40], "compromis": [38, 39, 40], "becam": [38, 39, 40], "invalidity_date_crit": [38, 39, 40], "issuer_crit": [38, 39, 40], "remove_from_crl": [38, 39, 40], "reason_crit": [38, 39, 40], "revocation_d": [38, 39, 40], "variant": 39, "combin": 40, "interest": 40, "2345": 40, "20191013152910z": 40, "20191001000000z": 40, "20191010010203z": 40}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"commun": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "crypto": [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "acme_account_fact": 0, "acme_account_info": 1, "modul": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "retriev": [1, 8, 38, 39], "inform": [1, 21, 27, 30, 35, 38, 39], "acm": [1, 2, 3, 4, 5, 6], "account": [1, 2], "synopsi": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "requir": [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "paramet": [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40], "attribut": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40], "note": [1, 2, 3, 4, 6, 11, 12, 14, 18, 22, 23, 32, 33, 35, 36, 37, 39, 40], "see": [1, 2, 3, 4, 5, 6, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39], "also": [1, 2, 3, 4, 5, 6, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39], "exampl": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "return": [1, 2, 3, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "valu": [1, 2, 3, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "author": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "collect": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "link": [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 14, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], "acme_account": 2, "creat": [2, 3, 9, 10], "modifi": 2, "delet": 2, "acme_certif": 3, "ssl": [3, 11], "tl": [3, 5, 11], "certif": [3, 4, 5, 7, 9, 10, 11, 12, 14, 17, 21, 22, 23, 35, 36, 37, 39, 40], "protocol": [3, 4], "acme_certificate_revok": 4, "revok": 4, "acme_challenge_cert_help": 5, "prepar": 5, "challeng": 5, "alpn": 5, "01": 5, "acme_inspect": 6, "send": 6, "direct": 6, "request": [6, 11, 12, 21, 22, 23], "an": [6, 31], "server": 6, "certificate_complete_chain": 7, "complet": 7, "chain": 7, "given": 7, "set": [7, 9], "untrust": 7, "root": 7, "crypto_info": 8, "cryptograph": 8, "capabl": 8, "how": [9, 10], "small": 9, "ca": 9, "up": 9, "us": 9, "sign": [9, 10, 21, 22, 23, 33], "self": 10, "ecs_certif": 11, "entrust": [11, 12], "servic": [11, 12], "ec": [11, 12], "api": [11, 12], "ecs_domain": 12, "valid": 12, "domain": 12, "index": [13, 15], "all": 13, "environ": 13, "variabl": 13, "get_certif": 14, "get": 14, "from": [14, 31, 38], "host": [14, 17], "port": 14, "descript": 15, "scenario": 15, "guid": 15, "plugin": 15, "filter": [15, 34, 38], "luks_devic": 16, "manag": 16, "encrypt": 16, "luk": 16, "devic": 16, "openssh_cert": 17, "gener": [17, 18, 22, 23, 24, 25, 28, 29, 31, 36, 37, 40], "openssh": [17, 18], "user": 17, "openssh_keypair": 18, "privat": [18, 26, 27, 28, 29, 31], "public": [18, 30, 31], "kei": [18, 26, 27, 28, 29, 30, 31], "openssl_certificate_info": 19, "openssl_certif": 20, "openssl_csr_info": 21, "provid": [21, 27, 30, 35], "openssl": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37], "csr": [21, 22, 23], "openssl_csr": 22, "openssl_csr_pip": 23, "openssl_dhparam": 24, "diffi": 24, "hellman": 24, "openssl_pkcs12": 25, "pkc": 25, "12": 25, "archiv": 25, "openssl_privatekey_convert": 26, "convert": 26, "openssl_privatekey_info": 27, "openssl_privatekei": 28, "openssl_privatekey_pip": 29, "without": 29, "disk": 29, "access": 29, "openssl_publickey_info": 30, "openssl_publickei": 31, "its": 31, "openssl_signature_info": 32, "verifi": 32, "signatur": 32, "openssl_signatur": 33, "data": 33, "split_pem": 34, "split": 34, "pem": [34, 38], "file": 34, "content": 34, "multipl": 34, "object": 34, "input": [34, 38], "x509_certificate_info": 35, "x": [35, 38], "509": [35, 38], "x509_certif": 36, "check": [36, 37], "x509_certificate_pip": 37, "x509_crl_info": [38, 39], "crl": [38, 39, 40], "format": 38, "keyword": 38, "revoc": [39, 40], "list": [39, 40], "x509_crl": 40}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"community.crypto.acme_account_facts": [[0, "community-crypto-acme-account-facts"]], "community.crypto.acme_account_info module \u2013 Retrieves information on ACME accounts": [[1, "community-crypto-acme-account-info-module-retrieves-information-on-acme-accounts"]], "Synopsis": [[1, "synopsis"], [2, "synopsis"], [3, "synopsis"], [4, "synopsis"], [5, "synopsis"], [6, "synopsis"], [7, "synopsis"], [8, "synopsis"], [11, "synopsis"], [12, "synopsis"], [14, "synopsis"], [16, "synopsis"], [17, "synopsis"], [18, "synopsis"], [21, "synopsis"], [22, "synopsis"], [23, "synopsis"], [24, "synopsis"], [25, "synopsis"], [26, "synopsis"], [27, "synopsis"], [28, "synopsis"], [29, "synopsis"], [30, "synopsis"], [31, "synopsis"], [32, "synopsis"], [33, "synopsis"], [34, "synopsis"], [35, "synopsis"], [36, "synopsis"], [37, "synopsis"], [38, "synopsis"], [39, "synopsis"], [40, "synopsis"]], "Requirements": [[1, "requirements"], [2, "requirements"], [3, "requirements"], [4, "requirements"], [5, "requirements"], [6, "requirements"], [7, "requirements"], [11, "requirements"], [12, "requirements"], [14, "requirements"], [16, "requirements"], [17, "requirements"], [18, "requirements"], [21, "requirements"], [22, "requirements"], [23, "requirements"], [24, "requirements"], [25, "requirements"], [26, "requirements"], [27, "requirements"], [28, "requirements"], [29, "requirements"], [30, "requirements"], [31, "requirements"], [32, "requirements"], [33, "requirements"], [35, "requirements"], [36, "requirements"], [37, "requirements"], [38, "requirements"], [39, "requirements"], [40, "requirements"]], "Parameters": [[1, "parameters"], [2, "parameters"], [3, "parameters"], [4, "parameters"], [5, "parameters"], [6, "parameters"], [7, "parameters"], [11, "parameters"], [12, "parameters"], [14, "parameters"], [16, "parameters"], [17, "parameters"], [18, "parameters"], [21, "parameters"], [22, "parameters"], [23, "parameters"], [24, "parameters"], [25, "parameters"], [26, "parameters"], [27, "parameters"], [28, "parameters"], [29, "parameters"], [30, "parameters"], [31, "parameters"], [32, "parameters"], [33, "parameters"], [35, "parameters"], [36, "parameters"], [37, "parameters"], [39, "parameters"], [40, "parameters"]], "Attributes": [[1, "attributes"], [2, "attributes"], [3, "attributes"], [4, "attributes"], [5, "attributes"], [6, "attributes"], [7, "attributes"], [8, "attributes"], [11, "attributes"], [12, "attributes"], [14, "attributes"], [16, "attributes"], [17, "attributes"], [18, "attributes"], [21, "attributes"], [22, "attributes"], [23, "attributes"], [24, "attributes"], [25, "attributes"], [26, "attributes"], [27, "attributes"], [28, "attributes"], [29, "attributes"], [30, "attributes"], [31, "attributes"], [32, "attributes"], [33, "attributes"], [35, "attributes"], [36, "attributes"], [37, "attributes"], [39, "attributes"], [40, "attributes"]], "Notes": [[1, "notes"], [2, "notes"], [3, "notes"], [4, "notes"], [6, "notes"], [11, "notes"], [12, "notes"], [14, "notes"], [18, "notes"], [22, "notes"], [23, "notes"], [32, "notes"], [33, "notes"], [35, "notes"], [36, "notes"], [37, "notes"], [39, "notes"], [40, "notes"]], "See Also": [[1, "see-also"], [2, "see-also"], [3, "see-also"], [4, "see-also"], [5, "see-also"], [6, "see-also"], [11, "see-also"], [12, "see-also"], [21, "see-also"], [22, "see-also"], [23, "see-also"], [24, "see-also"], [25, "see-also"], [26, "see-also"], [27, "see-also"], [28, "see-also"], [29, "see-also"], [30, "see-also"], [31, "see-also"], [32, "see-also"], [33, "see-also"], [35, "see-also"], [36, "see-also"], [37, "see-also"], [38, "see-also"], [39, "see-also"]], "Examples": [[1, "examples"], [2, "examples"], [3, "examples"], [4, "examples"], [5, "examples"], [6, "examples"], [7, "examples"], [8, "examples"], [11, "examples"], [12, "examples"], [14, "examples"], [16, "examples"], [17, "examples"], [18, "examples"], [21, "examples"], [22, "examples"], [23, "examples"], [24, "examples"], [25, "examples"], [26, "examples"], [27, "examples"], [28, "examples"], [29, "examples"], [30, "examples"], [31, "examples"], [32, "examples"], [33, "examples"], [34, "examples"], [35, "examples"], [36, "examples"], [37, "examples"], [38, "examples"], [39, "examples"], [40, "examples"]], "Return Values": [[1, "return-values"], [2, "return-values"], [3, "return-values"], [5, "return-values"], [6, "return-values"], [7, "return-values"], [8, "return-values"], [11, "return-values"], [12, "return-values"], [14, "return-values"], [16, "return-values"], [17, "return-values"], [18, "return-values"], [21, "return-values"], [22, "return-values"], [23, "return-values"], [24, "return-values"], [25, "return-values"], [26, "return-values"], [27, "return-values"], [28, "return-values"], [29, "return-values"], [30, "return-values"], [31, "return-values"], [32, "return-values"], [33, "return-values"], [35, "return-values"], [36, "return-values"], [37, "return-values"], [39, "return-values"], [40, "return-values"]], "Authors": [[1, "authors"], [2, "authors"], [3, "authors"], [4, "authors"], [5, "authors"], [6, "authors"], [7, "authors"], [8, "authors"], [11, "authors"], [12, "authors"], [14, "authors"], [16, "authors"], [17, "authors"], [18, "authors"], [21, "authors"], [22, "authors"], [23, "authors"], [24, "authors"], [25, "authors"], [26, "authors"], [27, "authors"], [28, "authors"], [29, "authors"], [30, "authors"], [31, "authors"], [32, "authors"], [33, "authors"], [34, "authors"], [35, "authors"], [36, "authors"], [37, "authors"], [38, "authors"], [39, "authors"], [40, "authors"]], "Collection links": [[1, "collection-links"], [2, "collection-links"], [3, "collection-links"], [4, "collection-links"], [5, "collection-links"], [6, "collection-links"], [7, "collection-links"], [8, "collection-links"], [11, "collection-links"], [12, "collection-links"], [14, "collection-links"], [16, "collection-links"], [17, "collection-links"], [18, "collection-links"], [21, "collection-links"], [22, "collection-links"], [23, "collection-links"], [24, "collection-links"], [25, "collection-links"], [26, "collection-links"], [27, "collection-links"], [28, "collection-links"], [29, "collection-links"], [30, "collection-links"], [31, "collection-links"], [32, "collection-links"], [33, "collection-links"], [34, "collection-links"], [35, "collection-links"], [36, "collection-links"], [37, "collection-links"], [38, "collection-links"], [39, "collection-links"], [40, "collection-links"]], "community.crypto.acme_account module \u2013 Create, modify or delete ACME accounts": [[2, "community-crypto-acme-account-module-create-modify-or-delete-acme-accounts"]], "community.crypto.acme_certificate module \u2013 Create SSL/TLS certificates with the ACME protocol": [[3, "community-crypto-acme-certificate-module-create-ssl-tls-certificates-with-the-acme-protocol"]], "community.crypto.acme_certificate_revoke module \u2013 Revoke certificates with the ACME protocol": [[4, "community-crypto-acme-certificate-revoke-module-revoke-certificates-with-the-acme-protocol"]], "community.crypto.acme_challenge_cert_helper module \u2013 Prepare certificates required for ACME challenges such as tls-alpn-01": [[5, "community-crypto-acme-challenge-cert-helper-module-prepare-certificates-required-for-acme-challenges-such-as-tls-alpn-01"]], "community.crypto.acme_inspect module \u2013 Send direct requests to an ACME server": [[6, "community-crypto-acme-inspect-module-send-direct-requests-to-an-acme-server"]], "community.crypto.certificate_complete_chain module \u2013 Complete certificate chain given a set of untrusted and root certificates": [[7, "community-crypto-certificate-complete-chain-module-complete-certificate-chain-given-a-set-of-untrusted-and-root-certificates"]], "community.crypto.crypto_info module \u2013 Retrieve cryptographic capabilities": [[8, "community-crypto-crypto-info-module-retrieve-cryptographic-capabilities"]], "How to create a small CA": [[9, "how-to-create-a-small-ca"]], "Set up the CA": [[9, "set-up-the-ca"]], "Use the CA to sign a certificate": [[9, "use-the-ca-to-sign-a-certificate"]], "How to create self-signed certificates": [[10, "how-to-create-self-signed-certificates"]], "community.crypto.ecs_certificate module \u2013 Request SSL/TLS certificates with the Entrust Certificate Services (ECS) API": [[11, "community-crypto-ecs-certificate-module-request-ssl-tls-certificates-with-the-entrust-certificate-services-ecs-api"]], "community.crypto.ecs_domain module \u2013 Request validation of a domain with the Entrust Certificate Services (ECS) API": [[12, "community-crypto-ecs-domain-module-request-validation-of-a-domain-with-the-entrust-certificate-services-ecs-api"]], "Index of all Collection Environment Variables": [[13, "index-of-all-collection-environment-variables"]], "community.crypto.get_certificate module \u2013 Get a certificate from a host:port": [[14, "community-crypto-get-certificate-module-get-a-certificate-from-a-host-port"]], "Community.Crypto": [[15, "community-crypto"]], "Description": [[15, "description"]], "Communication": [[15, "communication"]], "Scenario Guides": [[15, "scenario-guides"]], "Plugin Index": [[15, "plugin-index"]], "Modules": [[15, "modules"]], "Filter Plugins": [[15, "filter-plugins"]], "community.crypto.luks_device module \u2013 Manage encrypted (LUKS) devices": [[16, "community-crypto-luks-device-module-manage-encrypted-luks-devices"]], "community.crypto.openssh_cert module \u2013 Generate OpenSSH host or user certificates.": [[17, "community-crypto-openssh-cert-module-generate-openssh-host-or-user-certificates"]], "community.crypto.openssh_keypair module \u2013 Generate OpenSSH private and public keys": [[18, "community-crypto-openssh-keypair-module-generate-openssh-private-and-public-keys"]], "community.crypto.openssl_certificate_info": [[19, "community-crypto-openssl-certificate-info"]], "community.crypto.openssl_certificate": [[20, "community-crypto-openssl-certificate"]], "community.crypto.openssl_csr_info module \u2013 Provide information of OpenSSL Certificate Signing Requests (CSR)": [[21, "community-crypto-openssl-csr-info-module-provide-information-of-openssl-certificate-signing-requests-csr"]], "community.crypto.openssl_csr module \u2013 Generate OpenSSL Certificate Signing Request (CSR)": [[22, "community-crypto-openssl-csr-module-generate-openssl-certificate-signing-request-csr"]], "community.crypto.openssl_csr_pipe module \u2013 Generate OpenSSL Certificate Signing Request (CSR)": [[23, "community-crypto-openssl-csr-pipe-module-generate-openssl-certificate-signing-request-csr"]], "community.crypto.openssl_dhparam module \u2013 Generate OpenSSL Diffie-Hellman Parameters": [[24, "community-crypto-openssl-dhparam-module-generate-openssl-diffie-hellman-parameters"]], "community.crypto.openssl_pkcs12 module \u2013 Generate OpenSSL PKCS#12 archive": [[25, "community-crypto-openssl-pkcs12-module-generate-openssl-pkcs-12-archive"]], "community.crypto.openssl_privatekey_convert module \u2013 Convert OpenSSL private keys": [[26, "community-crypto-openssl-privatekey-convert-module-convert-openssl-private-keys"]], "community.crypto.openssl_privatekey_info module \u2013 Provide information for OpenSSL private keys": [[27, "community-crypto-openssl-privatekey-info-module-provide-information-for-openssl-private-keys"]], "community.crypto.openssl_privatekey module \u2013 Generate OpenSSL private keys": [[28, "community-crypto-openssl-privatekey-module-generate-openssl-private-keys"]], "community.crypto.openssl_privatekey_pipe module \u2013 Generate OpenSSL private keys without disk access": [[29, "community-crypto-openssl-privatekey-pipe-module-generate-openssl-private-keys-without-disk-access"]], "community.crypto.openssl_publickey_info module \u2013 Provide information for OpenSSL public keys": [[30, "community-crypto-openssl-publickey-info-module-provide-information-for-openssl-public-keys"]], "community.crypto.openssl_publickey module \u2013 Generate an OpenSSL public key from its private key.": [[31, "community-crypto-openssl-publickey-module-generate-an-openssl-public-key-from-its-private-key"]], "community.crypto.openssl_signature_info module \u2013 Verify signatures with openssl": [[32, "community-crypto-openssl-signature-info-module-verify-signatures-with-openssl"]], "community.crypto.openssl_signature module \u2013 Sign data with openssl": [[33, "community-crypto-openssl-signature-module-sign-data-with-openssl"]], "community.crypto.split_pem filter \u2013 Split PEM file contents into multiple objects": [[34, "community-crypto-split-pem-filter-split-pem-file-contents-into-multiple-objects"]], "Input": [[34, "input"], [38, "input"]], "Return Value": [[34, "return-value"], [38, "return-value"]], "community.crypto.x509_certificate_info module \u2013 Provide information of OpenSSL X.509 certificates": [[35, "community-crypto-x509-certificate-info-module-provide-information-of-openssl-x-509-certificates"]], "community.crypto.x509_certificate module \u2013 Generate and/or check OpenSSL certificates": [[36, "community-crypto-x509-certificate-module-generate-and-or-check-openssl-certificates"]], "community.crypto.x509_certificate_pipe module \u2013 Generate and/or check OpenSSL certificates": [[37, "community-crypto-x509-certificate-pipe-module-generate-and-or-check-openssl-certificates"]], "community.crypto.x509_crl_info filter \u2013 Retrieve information from X.509 CRLs in PEM format": [[38, "community-crypto-x509-crl-info-filter-retrieve-information-from-x-509-crls-in-pem-format"]], "Keyword parameters": [[38, "keyword-parameters"]], "community.crypto.x509_crl_info module \u2013 Retrieve information on Certificate Revocation Lists (CRLs)": [[39, "community-crypto-x509-crl-info-module-retrieve-information-on-certificate-revocation-lists-crls"]], "community.crypto.x509_crl module \u2013 Generate Certificate Revocation Lists (CRLs)": [[40, "community-crypto-x509-crl-module-generate-certificate-revocation-lists-crls"]]}, "indexentries": {}}) \ No newline at end of file diff --git a/pr/558/split_pem_filter.html b/pr/558/split_pem_filter.html new file mode 100644 index 00000000..8aea8b61 --- /dev/null +++ b/pr/558/split_pem_filter.html @@ -0,0 +1,280 @@ + + + + + + + community.crypto.split_pem filter – Split PEM file contents into multiple objects — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.split_pem filter – Split PEM file contents into multiple objects

+
+

Note

+

This filter plugin is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto.

+

To use it in a playbook, specify: community.crypto.split_pem.

+
+

New in community.crypto 2.10.0

+ +
+

Synopsis

+
    +
  • Split PEM file contents into multiple PEM objects. Comments or invalid parts are ignored.

  • +
+
+
+

Input

+

This describes the input of the filter, the value before | community.crypto.split_pem.

+ + + + + + + + + + + +

Parameter

Comments

+

Input

+

string / required

+

The PEM contents to split.

+
+
+
+

Examples

+
- name: Print all CA certificates
+  ansible.builtin.debug:
+    msg: '{{ item }}'
+  loop: >-
+    {{ lookup('ansible.builtin.file', '/path/to/ca-bundle.pem') | community.crypto.split_pem }}
+
+
+
+
+

Return Value

+ + + + + + + + + + + +

Key

Description

+

Return value

+

list / elements=string

+

A list of PEM file contents.

+

Returned: success

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+

Hint

+

Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

+
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/x509_certificate_info_module.html b/pr/558/x509_certificate_info_module.html new file mode 100644 index 00000000..106ec364 --- /dev/null +++ b/pr/558/x509_certificate_info_module.html @@ -0,0 +1,831 @@ + + + + + + + community.crypto.x509_certificate_info module – Provide information of OpenSSL X.509 certificates — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.x509_certificate_info module – Provide information of OpenSSL X.509 certificates

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.x509_certificate_info.

+
+ +
+

Synopsis

+
    +
  • This module allows one to query information on OpenSSL certificates.

  • +
  • It uses the cryptography python library to interact with OpenSSL.

  • +
  • Note that this module was called openssl_certificate_info when included directly in Ansible up to version 2.9. When moved to the collection community.crypto, it was renamed to community.crypto.x509_certificate_info. From Ansible 2.10 on, it can still be used by the old short name (or by ansible.builtin.openssl_certificate_info), which redirects to community.crypto.x509_certificate_info. When using FQCNs or when using the collections keyword, the new name community.crypto.x509_certificate_info should be used to avoid a deprecation warning.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • If name_encoding is set to another value than ignore, the idna Python library needs to be installed.

  • +
  • cryptography >= 1.6

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

content

+

string

+

added in community.crypto 1.0.0

+

Content of the X.509 certificate in PEM format.

+

Either path or content must be specified, but not both.

+
+

name_encoding

+

string

+

How to encode names (DNS names, URIs, email addresses) in return values.

+

ignore will use the encoding returned by the backend.

+

idna will convert all labels of domain names to IDNA encoding. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 encoding fails.

+

unicode will convert all labels of domain names to Unicode. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 decoding fails.

+

Note that idna and unicode require the idna Python library to be installed.

+

Choices:

+
    +
  • "ignore" ← (default)

  • +
  • "idna"

  • +
  • "unicode"

  • +
+
+

path

+

path

+

Remote absolute path where the certificate file is loaded from.

+

Either path or content must be specified, but not both.

+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

valid_at

+

dictionary

+

A dict of names mapping to time specifications. Every time specified here will be checked whether the certificate is valid at this point. See the valid_at return value for informations on the result.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h), and ASN.1 TIME (in other words, pattern YYYYMMDDHHMMSSZ). Note that all timestamps will be treated as being in UTC.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • All timestamp values are provided in ASN.1 TIME format, in other words, following the YYYYMMDDHHMMSSZ pattern. They are all in UTC.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
+
+
+
+

Examples

+
- name: Generate a Self Signed OpenSSL certificate
+  community.crypto.x509_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    csr_path: /etc/ssl/csr/ansible.com.csr
+    provider: selfsigned
+
+
+# Get information on the certificate
+
+- name: Get information on generated certificate
+  community.crypto.x509_certificate_info:
+    path: /etc/ssl/crt/ansible.com.crt
+  register: result
+
+- name: Dump information
+  ansible.builtin.debug:
+    var: result
+
+
+# Check whether the certificate is valid or not valid at certain times, fail
+# if this is not the case. The first task (x509_certificate_info) collects
+# the information, and the second task (assert) validates the result and
+# makes the playbook fail in case something is not as expected.
+
+- name: Test whether that certificate is valid tomorrow and/or in three weeks
+  community.crypto.x509_certificate_info:
+    path: /etc/ssl/crt/ansible.com.crt
+    valid_at:
+      point_1: "+1d"
+      point_2: "+3w"
+  register: result
+
+- name: Validate that certificate is valid tomorrow, but not in three weeks
+  assert:
+    that:
+      - result.valid_at.point_1      # valid in one day
+      - not result.valid_at.point_2  # not valid in three weeks
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

authority_cert_issuer

+

list / elements=string

+

The certificate’s authority cert issuer as a list of general names.

+

Is none if the AuthorityKeyIdentifier extension is not present.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]

+
+

authority_cert_serial_number

+

integer

+

The certificate’s authority cert serial number.

+

Is none if the AuthorityKeyIdentifier extension is not present.

+

Returned: success

+

Sample: 12345

+
+

authority_key_identifier

+

string

+

The certificate’s authority key identifier.

+

The identifier is returned in hexadecimal, with : used to separate bytes.

+

Is none if the AuthorityKeyIdentifier extension is not present.

+

Returned: success

+

Sample: "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33"

+
+

basic_constraints

+

list / elements=string

+

Entries in the basic_constraints extension, or none if extension is not present.

+

Returned: success

+

Sample: ["CA:TRUE", "pathlen:1"]

+
+

basic_constraints_critical

+

boolean

+

Whether the basic_constraints extension is critical.

+

Returned: success

+
+

expired

+

boolean

+

Whether the certificate is expired (in other words, notAfter is in the past).

+

Returned: success

+
+

extended_key_usage

+

list / elements=string

+

Entries in the extended_key_usage extension, or none if extension is not present.

+

Returned: success

+

Sample: ["Biometric Info", "DVCS", "Time Stamping"]

+
+

extended_key_usage_critical

+

boolean

+

Whether the extended_key_usage extension is critical.

+

Returned: success

+
+

extensions_by_oid

+

dictionary

+

Returns a dictionary for every extension OID.

+

Returned: success

+

Sample: {"1.3.6.1.5.5.7.1.24": {"critical": false, "value": "MAMCAQU="}}

+
+

critical

+

boolean

+

Whether the extension is critical.

+

Returned: success

+
+

value

+

string

+

The Base64 encoded value (in DER format) of the extension.

+

Note that depending on the cryptography version used, it is not possible to extract the ASN.1 content of the extension, but only to provide the re-encoded content of the extension in case it was parsed by cryptography. This should usually result in exactly the same value, except if the original extension value was malformed.

+

Returned: success

+

Sample: "MAMCAQU="

+
+

fingerprints

+

dictionary

+

added in community.crypto 1.2.0

+

Fingerprints of the DER-encoded form of the whole certificate.

+

For every hash algorithm available, the fingerprint is computed.

+

Returned: success

+

Sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63', 'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."

+
+

issuer

+

dictionary

+

The certificate’s issuer.

+

Note that for repeated values, only the last one will be returned.

+

Returned: success

+

Sample: {"commonName": "ca.example.com", "organizationName": "Ansible"}

+
+

issuer_ordered

+

list / elements=list

+

The certificate’s issuer as an ordered list of tuples.

+

Returned: success

+

Sample: [["organizationName", "Ansible"], [{"commonName": "ca.example.com"}]]

+
+

issuer_uri

+

string

+

added in community.crypto 2.9.0

+

The Issuer URI, if included in the certificate. Will be none if no issuer URI is included.

+

Returned: success

+
+

key_usage

+

string

+

Entries in the key_usage extension, or none if extension is not present.

+

Returned: success

+

Sample: "['Key Agreement', 'Data Encipherment']"

+
+

key_usage_critical

+

boolean

+

Whether the key_usage extension is critical.

+

Returned: success

+
+

not_after

+

string

+

notAfter date as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

not_before

+

string

+

notBefore date as ASN.1 TIME.

+

Returned: success

+

Sample: "20190331202428Z"

+
+

ocsp_must_staple

+

boolean

+

true if the OCSP Must Staple extension is present, none otherwise.

+

Returned: success

+
+

ocsp_must_staple_critical

+

boolean

+

Whether the ocsp_must_staple extension is critical.

+

Returned: success

+
+

ocsp_uri

+

string

+

The OCSP responder URI, if included in the certificate. Will be none if no OCSP responder URI is included.

+

Returned: success

+
+

public_key

+

string

+

Certificate’s public key in PEM format.

+

Returned: success

+

Sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."

+
+

public_key_data

+

dictionary

+

added in community.crypto 1.7.0

+

Public key data. Depends on the public key’s type.

+

Returned: success

+
+

curve

+

string

+

The curve’s name for ECC.

+

Returned: When public_key_type=ECC

+
+

exponent

+

integer

+

The RSA key’s public exponent.

+

Returned: When public_key_type=RSA

+
+

exponent_size

+

integer

+

The maximum number of bits of a private key. This is basically the bit size of the subgroup used.

+

Returned: When public_key_type=ECC

+
+

g

+

integer

+

The g value for DSA.

+

This is the element spanning the subgroup of the multiplicative group of the prime field used.

+

Returned: When public_key_type=DSA

+
+

modulus

+

integer

+

The RSA key’s modulus.

+

Returned: When public_key_type=RSA

+
+

p

+

integer

+

The p value for DSA.

+

This is the prime modulus upon which arithmetic takes place.

+

Returned: When public_key_type=DSA

+
+

q

+

integer

+

The q value for DSA.

+

This is a prime that divides p - 1, and at the same time the order of the subgroup of the multiplicative group of the prime field used.

+

Returned: When public_key_type=DSA

+
+

size

+

integer

+

Bit size of modulus (RSA) or prime number (DSA).

+

Returned: When public_key_type=RSA or public_key_type=DSA

+
+

x

+

integer

+

The x coordinate for the public point on the elliptic curve.

+

Returned: When public_key_type=ECC

+
+

y

+

integer

+

For public_key_type=ECC, this is the y coordinate for the public point on the elliptic curve.

+

For public_key_type=DSA, this is the publicly known group element whose discrete logarithm w.r.t. g is the private key.

+

Returned: When public_key_type=DSA or public_key_type=ECC

+
+

public_key_fingerprints

+

dictionary

+

Fingerprints of certificate’s public key.

+

For every hash algorithm available, the fingerprint is computed.

+

Returned: success

+

Sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63', 'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."

+
+

public_key_type

+

string

+

added in community.crypto 1.7.0

+

The certificate’s public key’s type.

+

One of RSA, DSA, ECC, Ed25519, X25519, Ed448, or X448.

+

Will start with unknown if the key type cannot be determined.

+

Returned: success

+

Sample: "RSA"

+
+

serial_number

+

integer

+

The certificate’s serial number.

+

Returned: success

+

Sample: 1234

+
+

signature_algorithm

+

string

+

The signature algorithm used to sign the certificate.

+

Returned: success

+

Sample: "sha256WithRSAEncryption"

+
+

subject

+

dictionary

+

The certificate’s subject as a dictionary.

+

Note that for repeated values, only the last one will be returned.

+

Returned: success

+

Sample: {"commonName": "www.example.com", "emailAddress": "test@example.com"}

+
+

subject_alt_name

+

list / elements=string

+

Entries in the subject_alt_name extension, or none if extension is not present.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]

+
+

subject_alt_name_critical

+

boolean

+

Whether the subject_alt_name extension is critical.

+

Returned: success

+
+

subject_key_identifier

+

string

+

The certificate’s subject key identifier.

+

The identifier is returned in hexadecimal, with : used to separate bytes.

+

Is none if the SubjectKeyIdentifier extension is not present.

+

Returned: success

+

Sample: "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33"

+
+

subject_ordered

+

list / elements=list

+

The certificate’s subject as an ordered list of tuples.

+

Returned: success

+

Sample: [["commonName", "www.example.com"], [{"emailAddress": "test@example.com"}]]

+
+

valid_at

+

dictionary

+

For every time stamp provided in the valid_at option, a boolean whether the certificate is valid at that point in time or not.

+

Returned: success

+
+

version

+

integer

+

The certificate version.

+

Returned: success

+

Sample: 3

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
  • Yanis Guenane (@Spredzy)

  • +
  • Markus Teufelberger (@MarkusTeufelberger)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/x509_certificate_module.html b/pr/558/x509_certificate_module.html new file mode 100644 index 00000000..6844d283 --- /dev/null +++ b/pr/558/x509_certificate_module.html @@ -0,0 +1,1068 @@ + + + + + + + community.crypto.x509_certificate module – Generate and/or check OpenSSL certificates — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.x509_certificate module – Generate and/or check OpenSSL certificates

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.x509_certificate.

+
+ +
+

Synopsis

+
    +
  • It implements a notion of provider (one of selfsigned, ownca, acme, and entrust) for your certificate.

  • +
  • It uses the cryptography python library to interact with OpenSSL.

  • +
  • Note that this module was called openssl_certificate when included directly in Ansible up to version 2.9. When moved to the collection community.crypto, it was renamed to community.crypto.x509_certificate. From Ansible 2.10 on, it can still be used by the old short name (or by ansible.builtin.openssl_certificate), which redirects to community.crypto.x509_certificate. When using FQCNs or when using the collections keyword, the new name community.crypto.x509_certificate should be used to avoid a deprecation warning.

  • +
  • Please note that the module regenerates existing certificate if it does not match the module’s options, or if it seems to be corrupt. If you are concerned that this could overwrite your existing certificate, consider using the backup option.

  • +
  • The ownca provider is intended for generating an OpenSSL certificate signed with your own CA (Certificate Authority) certificate (self-signed certificate).

  • +
  • This module allows one to (re)generate OpenSSL certificates.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • acme-tiny >= 4.0.0 (if using the acme provider)

  • +
  • cryptography >= 1.6 (if using selfsigned or ownca provider)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

acme_accountkey_path

+

path

+

The path to the accountkey for the acme provider.

+

This is only used by the acme provider.

+
+

acme_chain

+

boolean

+

Include the intermediate certificate to the generated certificate

+

This is only used by the acme provider.

+

Note that this is only available for older versions of acme-tiny. New versions include the chain automatically, and setting acme_chain to true results in an error.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

acme_challenge_path

+

path

+

The path to the ACME challenge directory that is served on http://<HOST>:80/.well-known/acme-challenge/

+

This is only used by the acme provider.

+
+

acme_directory

+

string

+

added in community.crypto 1.0.0

+

The ACME directory to use. You can use any directory that supports the ACME protocol, such as Buypass or Let’s Encrypt.

+

Let’s Encrypt recommends using their staging server while developing jobs. https://letsencrypt.org/docs/staging-environment/.

+

Default: "https://acme-v02.api.letsencrypt.org/directory"

+
+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original certificate back if you overwrote it with a new one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

csr_content

+

string

+

added in community.crypto 1.0.0

+

Content of the Certificate Signing Request (CSR) used to generate this certificate.

+

This is mutually exclusive with csr_path.

+
+

csr_path

+

path

+

Path to the Certificate Signing Request (CSR) used to generate this certificate.

+

This is mutually exclusive with csr_content.

+
+

entrust_api_client_cert_key_path

+

path

+

The path to the private key of the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_api_client_cert_path

+

path

+

The path to the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_api_key

+

string

+

The key (password) for authentication to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_api_specification_path

+

path

+

The path to the specification file defining the Entrust Certificate Services (ECS) API configuration.

+

You can use this to keep a local copy of the specification to avoid downloading it every time the module is used.

+

This is only used by the entrust provider.

+

Default: "https://cloud.entrust.net/EntrustCloud/documentation/cms-api-2.1.0.yaml"

+
+

entrust_api_user

+

string

+

The username for authentication to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_cert_type

+

string

+

Specify the type of certificate requested.

+

This is only used by the entrust provider.

+

Choices:

+
    +
  • "STANDARD_SSL" ← (default)

  • +
  • "ADVANTAGE_SSL"

  • +
  • "UC_SSL"

  • +
  • "EV_SSL"

  • +
  • "WILDCARD_SSL"

  • +
  • "PRIVATE_SSL"

  • +
  • "PD_SSL"

  • +
  • "CDS_ENT_LITE"

  • +
  • "CDS_ENT_PRO"

  • +
  • "SMIME_ENT"

  • +
+
+

entrust_not_after

+

string

+

The point in time at which the certificate stops being valid.

+

Time can be specified either as relative time or as an absolute timestamp.

+

A valid absolute time format is ASN.1 TIME such as 2019-06-18.

+

A valid relative time format is [+-]timespec where timespec can be an integer + [w | d | h | m | s], such as +365d or +32w1d2h).

+

Time will always be interpreted as UTC.

+

Note that only the date (day, month, year) is supported for specifying the expiry date of the issued certificate.

+

The full date-time is adjusted to EST (GMT -5:00) before issuance, which may result in a certificate with an expiration date one day earlier than expected if a relative time is used.

+

The minimum certificate lifetime is 90 days, and maximum is three years.

+

If this value is not specified, the certificate will stop being valid 365 days the date of issue.

+

This is only used by the entrust provider.

+

Please note that this value is not covered by the ignore_timestamps option.

+

Default: "+365d"

+
+

entrust_requester_email

+

string

+

The email of the requester of the certificate (for tracking purposes).

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_requester_name

+

string

+

The name of the requester of the certificate (for tracking purposes).

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_requester_phone

+

string

+

The phone number of the requester of the certificate (for tracking purposes).

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

force

+

boolean

+

Generate the certificate, even if it already exists.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

ignore_timestamps

+

boolean

+

added in community.crypto 2.0.0

+

Whether the “not before” and “not after” timestamps should be ignored for idempotency checks.

+

It is better to keep the default value true when using relative timestamps (like +0s for now).

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

mode

+

any

+

The permissions the resulting filesystem object should have.

+

For those used to /usr/bin/chmod remember that modes are actually octal numbers. You must either add a leading zero so that Ansible’s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like '644' or '1777') so Ansible receives a string and can do its own conversion from string into number.

+

Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results.

+

As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, u+rwx or u=rw,g=r,o=r).

+

If mode is not specified and the destination filesystem object does not exist, the default umask on the system will be used when setting the mode for the newly created filesystem object.

+

If mode is not specified and the destination filesystem object does exist, the mode of the existing filesystem object will be used.

+

Specifying mode is the best way to ensure filesystem objects are created with the correct permissions. See CVE-2020-1736 for further details.

+
+

ownca_content

+

string

+

added in community.crypto 1.0.0

+

Content of the CA (Certificate Authority) certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_path.

+
+

ownca_create_authority_key_identifier

+

boolean

+

Create a Authority Key Identifier from the CA’s certificate. If the CSR provided a authority key identifier, it is ignored.

+

The Authority Key Identifier is generated from the CA certificate’s Subject Key Identifier, if available. If it is not available, the CA certificate’s public key will be used.

+

This is only used by the ownca provider.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

ownca_create_subject_key_identifier

+

string

+

Whether to create the Subject Key Identifier (SKI) from the public key.

+

A value of create_if_not_provided (default) only creates a SKI when the CSR does not provide one.

+

A value of always_create always creates a SKI. If the CSR provides one, that one is ignored.

+

A value of never_create never creates a SKI. If the CSR provides one, that one is used.

+

This is only used by the ownca provider.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • "create_if_not_provided" ← (default)

  • +
  • "always_create"

  • +
  • "never_create"

  • +
+
+

ownca_digest

+

string

+

The digest algorithm to be used for the ownca certificate.

+

This is only used by the ownca provider.

+

Default: "sha256"

+
+

ownca_not_after

+

string

+

The point in time at which the certificate stops being valid.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will stop being valid 10 years from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the ownca provider.

+

On macOS 10.15 and onwards, TLS server certificates must have a validity period of 825 days or fewer. Please see https://support.apple.com/en-us/HT210176 for more details.

+

Default: "+3650d"

+
+

ownca_not_before

+

string

+

The point in time the certificate is valid from.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will start being valid from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the ownca provider.

+

Default: "+0s"

+
+

ownca_path

+

path

+

Remote absolute path of the CA (Certificate Authority) certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_content.

+
+

ownca_privatekey_content

+

string

+

added in community.crypto 1.0.0

+

Content of the CA (Certificate Authority) private key to use when signing the certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_privatekey_path.

+
+

ownca_privatekey_passphrase

+

string

+

The passphrase for the ownca_privatekey_path resp. ownca_privatekey_content.

+

This is only used by the ownca provider.

+
+

ownca_privatekey_path

+

path

+

Path to the CA (Certificate Authority) private key to use when signing the certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_privatekey_content.

+
+

ownca_version

+

integer

+

The version of the ownca certificate.

+

Nowadays it should almost always be 3.

+

This is only used by the ownca provider.

+

Default: 3

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

path

+

path / required

+

Remote absolute path where the generated certificate file should be created or is already located.

+
+

privatekey_content

+

string

+

added in community.crypto 1.0.0

+

Path to the private key to use when signing the certificate.

+

This is mutually exclusive with privatekey_path.

+
+

privatekey_passphrase

+

string

+

The passphrase for the privatekey_path resp. privatekey_content.

+

This is required if the private key is password protected.

+
+

privatekey_path

+

path

+

Path to the private key to use when signing the certificate.

+

This is mutually exclusive with privatekey_content.

+
+

provider

+

string

+

Name of the provider to use to generate/retrieve the OpenSSL certificate. Please see the examples on how to emulate it with community.crypto.x509_certificate_info, community.crypto.openssl_csr_info, community.crypto.openssl_privatekey_info and ansible.builtin.assert.

+

The entrust provider was added for Ansible 2.9 and requires credentials for the Entrust Certificate Services (ECS) API.

+

Required if state is present.

+

Choices:

+
    +
  • "acme"

  • +
  • "entrust"

  • +
  • "ownca"

  • +
  • "selfsigned"

  • +
+
+

return_content

+

boolean

+

added in community.crypto 1.0.0

+

If set to true, will return the (current or generated) certificate’s content as certificate.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

selfsigned_create_subject_key_identifier

+

string

+

Whether to create the Subject Key Identifier (SKI) from the public key.

+

A value of create_if_not_provided (default) only creates a SKI when the CSR does not provide one.

+

A value of always_create always creates a SKI. If the CSR provides one, that one is ignored.

+

A value of never_create never creates a SKI. If the CSR provides one, that one is used.

+

This is only used by the selfsigned provider.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • "create_if_not_provided" ← (default)

  • +
  • "always_create"

  • +
  • "never_create"

  • +
+
+

selfsigned_digest

+

string

+

Digest algorithm to be used when self-signing the certificate.

+

This is only used by the selfsigned provider.

+

Default: "sha256"

+
+
+

selfsigned_not_after

+

aliases: selfsigned_notAfter

+

string

+

The point in time at which the certificate stops being valid.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will stop being valid 10 years from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the selfsigned provider.

+

On macOS 10.15 and onwards, TLS server certificates must have a validity period of 825 days or fewer. Please see https://support.apple.com/en-us/HT210176 for more details.

+

Default: "+3650d"

+
+
+

selfsigned_not_before

+

aliases: selfsigned_notBefore

+

string

+

The point in time the certificate is valid from.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will start being valid from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the selfsigned provider.

+

Default: "+0s"

+
+

selfsigned_version

+

integer

+

Version of the selfsigned certificate.

+

Nowadays it should almost always be 3.

+

This is only used by the selfsigned provider.

+

Default: 3

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

state

+

string

+

Whether the certificate should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Notes

+
+

Note

+
    +
  • All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.

  • +
  • Date specified should be UTC. Minutes and seconds are mandatory.

  • +
  • For security reason, when you use ownca provider, you should NOT run community.crypto.x509_certificate on a target machine, but on a dedicated CA machine. It is recommended not to store the CA private key on the target machine. Once signed, the certificate can be moved to the target machine.

  • +
  • For the selfsigned provider, csr_path and csr_content are optional. If not provided, a certificate without any information (Subject, Subject Alternative Names, Key Usage, etc.) is created.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate_pipe

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Generate a Self Signed OpenSSL certificate
+  community.crypto.x509_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    csr_path: /etc/ssl/csr/ansible.com.csr
+    provider: selfsigned
+
+- name: Generate an OpenSSL certificate signed with your own CA certificate
+  community.crypto.x509_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr_path: /etc/ssl/csr/ansible.com.csr
+    ownca_path: /etc/ssl/crt/ansible_CA.crt
+    ownca_privatekey_path: /etc/ssl/private/ansible_CA.pem
+    provider: ownca
+
+- name: Generate a Let's Encrypt Certificate
+  community.crypto.x509_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr_path: /etc/ssl/csr/ansible.com.csr
+    provider: acme
+    acme_accountkey_path: /etc/ssl/private/ansible.com.pem
+    acme_challenge_path: /etc/ssl/challenges/ansible.com/
+
+- name: Force (re-)generate a new Let's Encrypt Certificate
+  community.crypto.x509_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr_path: /etc/ssl/csr/ansible.com.csr
+    provider: acme
+    acme_accountkey_path: /etc/ssl/private/ansible.com.pem
+    acme_challenge_path: /etc/ssl/challenges/ansible.com/
+    force: true
+
+- name: Generate an Entrust certificate via the Entrust Certificate Services (ECS) API
+  community.crypto.x509_certificate:
+    path: /etc/ssl/crt/ansible.com.crt
+    csr_path: /etc/ssl/csr/ansible.com.csr
+    provider: entrust
+    entrust_requester_name: Jo Doe
+    entrust_requester_email: jdoe@ansible.com
+    entrust_requester_phone: 555-555-5555
+    entrust_cert_type: STANDARD_SSL
+    entrust_api_user: apiusername
+    entrust_api_key: a^lv*32!cd9LnT
+    entrust_api_client_cert_path: /etc/ssl/entrust/ecs-client.crt
+    entrust_api_client_cert_key_path: /etc/ssl/entrust/ecs-key.crt
+    entrust_api_specification_path: /etc/ssl/entrust/api-docs/cms-api-2.1.0.yaml
+
+# The following example shows how to emulate the behavior of the removed
+# "assertonly" provider with the x509_certificate_info, openssl_csr_info,
+# openssl_privatekey_info and assert modules:
+
+- name: Get certificate information
+  community.crypto.x509_certificate_info:
+    path: /etc/ssl/crt/ansible.com.crt
+    # for valid_at, invalid_at and valid_in
+    valid_at:
+      one_day_ten_hours: "+1d10h"
+      fixed_timestamp: 20200331202428Z
+      ten_seconds: "+10"
+  register: result
+
+- name: Get CSR information
+  community.crypto.openssl_csr_info:
+    # Verifies that the CSR signature is valid; module will fail if not
+    path: /etc/ssl/csr/ansible.com.csr
+  register: result_csr
+
+- name: Get private key information
+  community.crypto.openssl_privatekey_info:
+    path: /etc/ssl/csr/ansible.com.key
+  register: result_privatekey
+
+- assert:
+    that:
+      # When private key was specified for assertonly, this was checked:
+      - result.public_key == result_privatekey.public_key
+      # When CSR was specified for assertonly, this was checked:
+      - result.public_key == result_csr.public_key
+      - result.subject_ordered == result_csr.subject_ordered
+      - result.extensions_by_oid == result_csr.extensions_by_oid
+      # signature_algorithms check
+      - "result.signature_algorithm == 'sha256WithRSAEncryption' or result.signature_algorithm == 'sha512WithRSAEncryption'"
+      # subject and subject_strict
+      - "result.subject.commonName == 'ansible.com'"
+      - "result.subject | length == 1"  # the number must be the number of entries you check for
+      # issuer and issuer_strict
+      - "result.issuer.commonName == 'ansible.com'"
+      - "result.issuer | length == 1"  # the number must be the number of entries you check for
+      # has_expired
+      - not result.expired
+      # version
+      - result.version == 3
+      # key_usage and key_usage_strict
+      - "'Data Encipherment' in result.key_usage"
+      - "result.key_usage | length == 1"  # the number must be the number of entries you check for
+      # extended_key_usage and extended_key_usage_strict
+      - "'DVCS' in result.extended_key_usage"
+      - "result.extended_key_usage | length == 1"  # the number must be the number of entries you check for
+      # subject_alt_name and subject_alt_name_strict
+      - "'dns:ansible.com' in result.subject_alt_name"
+      - "result.subject_alt_name | length == 1"  # the number must be the number of entries you check for
+      # not_before and not_after
+      - "result.not_before == '20190331202428Z'"
+      - "result.not_after == '20190413202428Z'"
+      # valid_at, invalid_at and valid_in
+      - "result.valid_at.one_day_ten_hours"  # for valid_at
+      - "not result.valid_at.fixed_timestamp"  # for invalid_at
+      - "result.valid_at.ten_seconds"  # for valid_in
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/www.ansible.com.crt.2019-03-09@11:22~"

+
+

certificate

+

string

+

added in community.crypto 1.0.0

+

The (current or generated) certificate’s content.

+

Returned: if state is present and return_content is true

+
+

filename

+

string

+

Path to the generated certificate.

+

Returned: changed or success

+

Sample: "/etc/ssl/crt/www.ansible.com.crt"

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Markus Teufelberger (@MarkusTeufelberger)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/x509_certificate_pipe_module.html b/pr/558/x509_certificate_pipe_module.html new file mode 100644 index 00000000..c2bf1e99 --- /dev/null +++ b/pr/558/x509_certificate_pipe_module.html @@ -0,0 +1,819 @@ + + + + + + + community.crypto.x509_certificate_pipe module – Generate and/or check OpenSSL certificates — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.x509_certificate_pipe module – Generate and/or check OpenSSL certificates

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.x509_certificate_pipe.

+
+

New in community.crypto 1.3.0

+ +
+

Synopsis

+
    +
  • It implements a notion of provider (ie. selfsigned, ownca, entrust) for your certificate.

  • +
  • It uses the cryptography python library to interact with OpenSSL.

  • +
  • Please note that the module regenerates an existing certificate if it does not match the module’s options, or if it seems to be corrupt. If you are concerned that this could overwrite your existing certificate, consider using the backup option.

  • +
  • The ownca provider is intended for generating an OpenSSL certificate signed with your own CA (Certificate Authority) certificate (self-signed certificate).

  • +
  • This module allows one to (re)generate OpenSSL certificates.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • cryptography >= 1.6 (if using selfsigned or ownca provider)

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

content

+

string

+

The existing certificate.

+
+

csr_content

+

string

+

Content of the Certificate Signing Request (CSR) used to generate this certificate.

+

This is mutually exclusive with csr_path.

+
+

csr_path

+

path

+

Path to the Certificate Signing Request (CSR) used to generate this certificate.

+

This is mutually exclusive with csr_content.

+
+

entrust_api_client_cert_key_path

+

path

+

The path to the private key of the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_api_client_cert_path

+

path

+

The path to the client certificate used to authenticate to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_api_key

+

string

+

The key (password) for authentication to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_api_specification_path

+

path

+

The path to the specification file defining the Entrust Certificate Services (ECS) API configuration.

+

You can use this to keep a local copy of the specification to avoid downloading it every time the module is used.

+

This is only used by the entrust provider.

+

Default: "https://cloud.entrust.net/EntrustCloud/documentation/cms-api-2.1.0.yaml"

+
+

entrust_api_user

+

string

+

The username for authentication to the Entrust Certificate Services (ECS) API.

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_cert_type

+

string

+

Specify the type of certificate requested.

+

This is only used by the entrust provider.

+

Choices:

+
    +
  • "STANDARD_SSL" ← (default)

  • +
  • "ADVANTAGE_SSL"

  • +
  • "UC_SSL"

  • +
  • "EV_SSL"

  • +
  • "WILDCARD_SSL"

  • +
  • "PRIVATE_SSL"

  • +
  • "PD_SSL"

  • +
  • "CDS_ENT_LITE"

  • +
  • "CDS_ENT_PRO"

  • +
  • "SMIME_ENT"

  • +
+
+

entrust_not_after

+

string

+

The point in time at which the certificate stops being valid.

+

Time can be specified either as relative time or as an absolute timestamp.

+

A valid absolute time format is ASN.1 TIME such as 2019-06-18.

+

A valid relative time format is [+-]timespec where timespec can be an integer + [w | d | h | m | s], such as +365d or +32w1d2h).

+

Time will always be interpreted as UTC.

+

Note that only the date (day, month, year) is supported for specifying the expiry date of the issued certificate.

+

The full date-time is adjusted to EST (GMT -5:00) before issuance, which may result in a certificate with an expiration date one day earlier than expected if a relative time is used.

+

The minimum certificate lifetime is 90 days, and maximum is three years.

+

If this value is not specified, the certificate will stop being valid 365 days the date of issue.

+

This is only used by the entrust provider.

+

Please note that this value is not covered by the ignore_timestamps option.

+

Default: "+365d"

+
+

entrust_requester_email

+

string

+

The email of the requester of the certificate (for tracking purposes).

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_requester_name

+

string

+

The name of the requester of the certificate (for tracking purposes).

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

entrust_requester_phone

+

string

+

The phone number of the requester of the certificate (for tracking purposes).

+

This is only used by the entrust provider.

+

This is required if the provider is entrust.

+
+

force

+

boolean

+

Generate the certificate, even if it already exists.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

ignore_timestamps

+

boolean

+

added in community.crypto 2.0.0

+

Whether the “not before” and “not after” timestamps should be ignored for idempotency checks.

+

It is better to keep the default value true when using relative timestamps (like +0s for now).

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

ownca_content

+

string

+

Content of the CA (Certificate Authority) certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_path.

+
+

ownca_create_authority_key_identifier

+

boolean

+

Create a Authority Key Identifier from the CA’s certificate. If the CSR provided a authority key identifier, it is ignored.

+

The Authority Key Identifier is generated from the CA certificate’s Subject Key Identifier, if available. If it is not available, the CA certificate’s public key will be used.

+

This is only used by the ownca provider.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

ownca_create_subject_key_identifier

+

string

+

Whether to create the Subject Key Identifier (SKI) from the public key.

+

A value of create_if_not_provided (default) only creates a SKI when the CSR does not provide one.

+

A value of always_create always creates a SKI. If the CSR provides one, that one is ignored.

+

A value of never_create never creates a SKI. If the CSR provides one, that one is used.

+

This is only used by the ownca provider.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • "create_if_not_provided" ← (default)

  • +
  • "always_create"

  • +
  • "never_create"

  • +
+
+

ownca_digest

+

string

+

The digest algorithm to be used for the ownca certificate.

+

This is only used by the ownca provider.

+

Default: "sha256"

+
+

ownca_not_after

+

string

+

The point in time at which the certificate stops being valid.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will stop being valid 10 years from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the ownca provider.

+

On macOS 10.15 and onwards, TLS server certificates must have a validity period of 825 days or fewer. Please see https://support.apple.com/en-us/HT210176 for more details.

+

Default: "+3650d"

+
+

ownca_not_before

+

string

+

The point in time the certificate is valid from.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will start being valid from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the ownca provider.

+

Default: "+0s"

+
+

ownca_path

+

path

+

Remote absolute path of the CA (Certificate Authority) certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_content.

+
+

ownca_privatekey_content

+

string

+

Content of the CA (Certificate Authority) private key to use when signing the certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_privatekey_path.

+
+

ownca_privatekey_passphrase

+

string

+

The passphrase for the ownca_privatekey_path resp. ownca_privatekey_content.

+

This is only used by the ownca provider.

+
+

ownca_privatekey_path

+

path

+

Path to the CA (Certificate Authority) private key to use when signing the certificate.

+

This is only used by the ownca provider.

+

This is mutually exclusive with ownca_privatekey_content.

+
+

ownca_version

+

integer

+

The version of the ownca certificate.

+

Nowadays it should almost always be 3.

+

This is only used by the ownca provider.

+

Default: 3

+
+

privatekey_content

+

string

+

Path to the private key to use when signing the certificate.

+

This is mutually exclusive with privatekey_path.

+
+

privatekey_passphrase

+

string

+

The passphrase for the privatekey_path resp. privatekey_content.

+

This is required if the private key is password protected.

+
+

privatekey_path

+

path

+

Path to the private key to use when signing the certificate.

+

This is mutually exclusive with privatekey_content.

+
+

provider

+

string / required

+

Name of the provider to use to generate/retrieve the OpenSSL certificate.

+

The entrust provider requires credentials for the Entrust Certificate Services (ECS) API.

+

Choices:

+
    +
  • "entrust"

  • +
  • "ownca"

  • +
  • "selfsigned"

  • +
+
+

select_crypto_backend

+

string

+

Determines which crypto backend to use.

+

The default choice is auto, which tries to use cryptography if available.

+

If set to cryptography, will try to use the cryptography library.

+

Choices:

+
    +
  • "auto" ← (default)

  • +
  • "cryptography"

  • +
+
+

selfsigned_create_subject_key_identifier

+

string

+

Whether to create the Subject Key Identifier (SKI) from the public key.

+

A value of create_if_not_provided (default) only creates a SKI when the CSR does not provide one.

+

A value of always_create always creates a SKI. If the CSR provides one, that one is ignored.

+

A value of never_create never creates a SKI. If the CSR provides one, that one is used.

+

This is only used by the selfsigned provider.

+

Note that this is only supported if the cryptography backend is used!

+

Choices:

+
    +
  • "create_if_not_provided" ← (default)

  • +
  • "always_create"

  • +
  • "never_create"

  • +
+
+

selfsigned_digest

+

string

+

Digest algorithm to be used when self-signing the certificate.

+

This is only used by the selfsigned provider.

+

Default: "sha256"

+
+
+

selfsigned_not_after

+

aliases: selfsigned_notAfter

+

string

+

The point in time at which the certificate stops being valid.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will stop being valid 10 years from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the selfsigned provider.

+

On macOS 10.15 and onwards, TLS server certificates must have a validity period of 825 days or fewer. Please see https://support.apple.com/en-us/HT210176 for more details.

+

Default: "+3650d"

+
+
+

selfsigned_not_before

+

aliases: selfsigned_notBefore

+

string

+

The point in time the certificate is valid from.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

If this value is not specified, the certificate will start being valid from now.

+

Note that this value is not used to determine whether an existing certificate should be regenerated. This can be changed by setting the ignore_timestamps option to false. Please note that you should avoid relative timestamps when setting ignore_timestamps=false.

+

This is only used by the selfsigned provider.

+

Default: "+0s"

+
+

selfsigned_version

+

integer

+

Version of the selfsigned certificate.

+

Nowadays it should almost always be 3.

+

This is only used by the selfsigned provider.

+

Default: 3

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.

  • +
  • Date specified should be UTC. Minutes and seconds are mandatory.

  • +
  • For security reason, when you use ownca provider, you should NOT run community.crypto.x509_certificate on a target machine, but on a dedicated CA machine. It is recommended not to store the CA private key on the target machine. Once signed, the certificate can be moved to the target machine.

  • +
  • For the selfsigned provider, csr_path and csr_content are optional. If not provided, a certificate without any information (Subject, Subject Alternative Names, Key Usage, etc.) is created.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_certificate

Generate and/or check OpenSSL certificates.

+
+
community.crypto.openssl_csr

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_csr_pipe

Generate OpenSSL Certificate Signing Request (CSR).

+
+
community.crypto.openssl_dhparam

Generate OpenSSL Diffie-Hellman Parameters.

+
+
community.crypto.openssl_pkcs12

Generate OpenSSL PKCS#12 archive.

+
+
community.crypto.openssl_privatekey

Generate OpenSSL private keys.

+
+
community.crypto.openssl_privatekey_pipe

Generate OpenSSL private keys without disk access.

+
+
community.crypto.openssl_publickey

Generate an OpenSSL public key from its private key.

+
+
+
+
+
+

Examples

+
- name: Generate a Self Signed OpenSSL certificate
+  community.crypto.x509_certificate_pipe:
+    provider: selfsigned
+    privatekey_path: /etc/ssl/private/ansible.com.pem
+    csr_path: /etc/ssl/csr/ansible.com.csr
+  register: result
+- name: Print the certificate
+  ansible.builtin.debug:
+    var: result.certificate
+
+# In the following example, both CSR and certificate file are stored on the
+# machine where ansible-playbook is executed, while the OwnCA data (certificate,
+# private key) are stored on the remote machine.
+
+- name: (1/2) Generate an OpenSSL Certificate with the CSR provided inline
+  community.crypto.x509_certificate_pipe:
+    provider: ownca
+    content: "{{ lookup('file', '/etc/ssl/csr/www.ansible.com.crt') }}"
+    csr_content: "{{ lookup('file', '/etc/ssl/csr/www.ansible.com.csr') }}"
+    ownca_cert: /path/to/ca_cert.crt
+    ownca_privatekey: /path/to/ca_cert.key
+    ownca_privatekey_passphrase: hunter2
+  register: result
+
+- name: (2/2) Store certificate
+  ansible.builtin.copy:
+    dest: /etc/ssl/csr/www.ansible.com.crt
+    content: "{{ result.certificate }}"
+  delegate_to: localhost
+  when: result is changed
+
+# In the following example, the certificate from another machine is signed by
+# our OwnCA whose private key and certificate are only available on this
+# machine (where ansible-playbook is executed), without having to write
+# the certificate file to disk on localhost. The CSR could have been
+# provided by community.crypto.openssl_csr_pipe earlier, or also have been
+# read from the remote machine.
+
+- name: (1/3) Read certificate's contents from remote machine
+  ansible.builtin.slurp:
+    src: /etc/ssl/csr/www.ansible.com.crt
+  register: certificate_content
+
+- name: (2/3) Generate an OpenSSL Certificate with the CSR provided inline
+  community.crypto.x509_certificate_pipe:
+    provider: ownca
+    content: "{{ certificate_content.content | b64decode }}"
+    csr_content: "{{ the_csr }}"
+    ownca_cert: /path/to/ca_cert.crt
+    ownca_privatekey: /path/to/ca_cert.key
+    ownca_privatekey_passphrase: hunter2
+  delegate_to: localhost
+  register: result
+
+- name: (3/3) Store certificate
+  ansible.builtin.copy:
+    dest: /etc/ssl/csr/www.ansible.com.crt
+    content: "{{ result.certificate }}"
+  when: result is changed
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + +

Key

Description

+

certificate

+

string

+

The (current or generated) certificate’s content.

+

Returned: changed or success

+
+
+

Authors

+
    +
  • Yanis Guenane (@Spredzy)

  • +
  • Markus Teufelberger (@MarkusTeufelberger)

  • +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/x509_crl_info_filter.html b/pr/558/x509_crl_info_filter.html new file mode 100644 index 00000000..8365acc8 --- /dev/null +++ b/pr/558/x509_crl_info_filter.html @@ -0,0 +1,491 @@ + + + + + + + community.crypto.x509_crl_info filter – Retrieve information from X.509 CRLs in PEM format — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.x509_crl_info filter – Retrieve information from X.509 CRLs in PEM format

+
+

Note

+

This filter plugin is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this filter plugin, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.x509_crl_info.

+
+

New in community.crypto 2.10.0

+ +
+

Synopsis

+ +
+
+

Requirements

+

The below requirements are needed on the local controller node that executes this filter.

+
    +
  • If name_encoding is set to another value than ignore, the idna Python library needs to be installed.

  • +
+
+
+

Input

+

This describes the input of the filter, the value before | community.crypto.x509_crl_info.

+ + + + + + + + + + + +

Parameter

Comments

+

Input

+

string / required

+

The content of the X.509 CRL in PEM format.

+
+
+
+

Keyword parameters

+

This describes keyword parameters of the filter. These are the values key1=value1, key2=value2 and so on in the following example: input | community.crypto.x509_crl_info(key1=value1, key2=value2, ...).

+ + + + + + + + + + + + + + +

Parameter

Comments

+

list_revoked_certificates

+

boolean

+

added in community.crypto 1.7.0

+

If set to false, the list of revoked certificates is not included in the result.

+

This is useful when retrieving information on large CRL files. Enumerating all revoked certificates can take some time, including serializing the result as JSON, sending it to the Ansible controller, and decoding it again.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

name_encoding

+

string

+

How to encode names (DNS names, URIs, email addresses) in return values.

+

ignore will use the encoding returned by the backend.

+

idna will convert all labels of domain names to IDNA encoding. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 encoding fails.

+

unicode will convert all labels of domain names to Unicode. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 decoding fails.

+

Note that idna and unicode require the idna Python library to be installed.

+

Choices:

+
    +
  • "ignore" ← (default)

  • +
  • "idna"

  • +
  • "unicode"

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_crl_info

Retrieve information on Certificate Revocation Lists (CRLs).

+
+
+
+
+
+

Examples

+
- name: Show the Organization Name of the CRL's subject
+  ansible.builtin.debug:
+    msg: >-
+      {{
+        (
+          lookup('ansible.builtin.file', '/path/to/cert.pem')
+          | community.crypto.x509_crl_info
+        ).issuer.organizationName
+      }}
+
+
+
+
+

Return Value

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

Return value

+

dictionary

+

Information on the CRL.

+

Returned: success

+
+

digest

+

string

+

The signature algorithm used to sign the CRL.

+

Returned: success

+

Sample: "sha256WithRSAEncryption"

+
+

format

+

string

+

Whether the CRL is in PEM format (pem) or in DER format (der).

+

Returned: success

+

Sample: "pem"

+
+

issuer

+

dictionary

+

The CRL’s issuer.

+

Note that for repeated values, only the last one will be returned.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: {"commonName": "ca.example.com", "organizationName": "Ansible"}

+
+

issuer_ordered

+

list / elements=list

+

The CRL’s issuer as an ordered list of tuples.

+

Returned: success

+

Sample: [["organizationName", "Ansible"], [{"commonName": "ca.example.com"}]]

+
+

last_update

+

string

+

The point in time from which this CRL can be trusted as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

next_update

+

string

+

The point in time from which a new CRL will be issued and the client has to check for it as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

revoked_certificates

+

list / elements=dictionary

+

List of certificates to be revoked.

+

Returned: success if list_revoked_certificates=true

+
+

invalidity_date

+

string

+

The point in time it was known/suspected that the private key was compromised +or that the certificate otherwise became invalid as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

invalidity_date_critical

+

boolean

+

Whether the invalidity date extension is critical.

+

Returned: success

+

Sample: false

+
+

issuer

+

list / elements=string

+

The certificate’s issuer.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:ca.example.org"]

+
+

issuer_critical

+

boolean

+

Whether the certificate issuer extension is critical.

+

Returned: success

+

Sample: false

+
+

reason

+

string

+

The value for the revocation reason extension.

+

One of unspecified, key_compromise, ca_compromise, affiliation_changed, superseded, cessation_of_operation, certificate_hold, privilege_withdrawn, aa_compromise, and remove_from_crl.

+

Returned: success

+

Sample: "key_compromise"

+
+

reason_critical

+

boolean

+

Whether the revocation reason extension is critical.

+

Returned: success

+

Sample: false

+
+

revocation_date

+

string

+

The point in time the certificate was revoked as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

serial_number

+

integer

+

Serial number of the certificate.

+

Returned: success

+

Sample: 1234

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+

Hint

+

Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

+
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/x509_crl_info_module.html b/pr/558/x509_crl_info_module.html new file mode 100644 index 00000000..16482f1b --- /dev/null +++ b/pr/558/x509_crl_info_module.html @@ -0,0 +1,526 @@ + + + + + + + community.crypto.x509_crl_info module – Retrieve information on Certificate Revocation Lists (CRLs) — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.x509_crl_info module – Retrieve information on Certificate Revocation Lists (CRLs)

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.x509_crl_info.

+
+

New in community.crypto 1.0.0

+ +
+

Synopsis

+
    +
  • This module allows one to retrieve information on Certificate Revocation Lists (CRLs).

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • If name_encoding is set to another value than ignore, the idna Python library needs to be installed.

  • +
  • cryptography >= 1.2

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+

content

+

string

+

Content of the X.509 CRL in PEM format, or Base64-encoded X.509 CRL.

+

Either path or content must be specified, but not both.

+
+

list_revoked_certificates

+

boolean

+

added in community.crypto 1.7.0

+

If set to false, the list of revoked certificates is not included in the result.

+

This is useful when retrieving information on large CRL files. Enumerating all revoked certificates can take some time, including serializing the result as JSON, sending it to the Ansible controller, and decoding it again.

+

Choices:

+
    +
  • false

  • +
  • true ← (default)

  • +
+
+

name_encoding

+

string

+

How to encode names (DNS names, URIs, email addresses) in return values.

+

ignore will use the encoding returned by the backend.

+

idna will convert all labels of domain names to IDNA encoding. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 encoding fails.

+

unicode will convert all labels of domain names to Unicode. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 decoding fails.

+

Note that idna and unicode require the idna Python library to be installed.

+

Choices:

+
    +
  • "ignore" ← (default)

  • +
  • "idna"

  • +
  • "unicode"

  • +
+
+

path

+

path

+

Remote absolute path where the generated CRL file should be created or is already located.

+

Either path or content must be specified, but not both.

+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

This action does not modify state.

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: N/A

+

This action does not modify state.

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+
+
+

Notes

+
+

Note

+
    +
  • All timestamp values are provided in ASN.1 TIME format, in other words, following the YYYYMMDDHHMMSSZ pattern. They are all in UTC.

  • +
+
+
+
+

See Also

+
+

See also

+
+
community.crypto.x509_crl

Generate Certificate Revocation Lists (CRLs).

+
+
community.crypto.x509_crl_info filter

A filter variant of this module.

+
+
+
+
+
+

Examples

+
- name: Get information on CRL
+  community.crypto.x509_crl_info:
+    path: /etc/ssl/my-ca.crl
+  register: result
+
+- name: Print the information
+  ansible.builtin.debug:
+    msg: "{{ result }}"
+
+- name: Get information on CRL without list of revoked certificates
+  community.crypto.x509_crl_info:
+    path: /etc/ssl/very-large.crl
+    list_revoked_certificates: false
+  register: result
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

digest

+

string

+

The signature algorithm used to sign the CRL.

+

Returned: success

+

Sample: "sha256WithRSAEncryption"

+
+

format

+

string

+

Whether the CRL is in PEM format (pem) or in DER format (der).

+

Returned: success

+

Sample: "pem"

+
+

issuer

+

dictionary

+

The CRL’s issuer.

+

Note that for repeated values, only the last one will be returned.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: {"commonName": "ca.example.com", "organizationName": "Ansible"}

+
+

issuer_ordered

+

list / elements=list

+

The CRL’s issuer as an ordered list of tuples.

+

Returned: success

+

Sample: [["organizationName", "Ansible"], [{"commonName": "ca.example.com"}]]

+
+

last_update

+

string

+

The point in time from which this CRL can be trusted as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

next_update

+

string

+

The point in time from which a new CRL will be issued and the client has to check for it as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

revoked_certificates

+

list / elements=dictionary

+

List of certificates to be revoked.

+

Returned: success if list_revoked_certificates=true

+
+

invalidity_date

+

string

+

The point in time it was known/suspected that the private key was compromised +or that the certificate otherwise became invalid as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

invalidity_date_critical

+

boolean

+

Whether the invalidity date extension is critical.

+

Returned: success

+

Sample: false

+
+

issuer

+

list / elements=string

+

The certificate’s issuer.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:ca.example.org"]

+
+

issuer_critical

+

boolean

+

Whether the certificate issuer extension is critical.

+

Returned: success

+

Sample: false

+
+

reason

+

string

+

The value for the revocation reason extension.

+

One of unspecified, key_compromise, ca_compromise, affiliation_changed, superseded, cessation_of_operation, certificate_hold, privilege_withdrawn, aa_compromise, and remove_from_crl.

+

Returned: success

+

Sample: "key_compromise"

+
+

reason_critical

+

boolean

+

Whether the revocation reason extension is critical.

+

Returned: success

+

Sample: false

+
+

revocation_date

+

string

+

The point in time the certificate was revoked as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

serial_number

+

integer

+

Serial number of the certificate.

+

Returned: success

+

Sample: 1234

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pr/558/x509_crl_module.html b/pr/558/x509_crl_module.html new file mode 100644 index 00000000..8628aebd --- /dev/null +++ b/pr/558/x509_crl_module.html @@ -0,0 +1,902 @@ + + + + + + + community.crypto.x509_crl module – Generate Certificate Revocation Lists (CRLs) — Community.Crypto Collection documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Community.Crypto Collection Docs
+
+
+ + +
+ +
+
+
+
    +
  • + +
  • + + Edit on GitHub +
  • +
+
+
+
+ + +
+ +
+

community.crypto.x509_crl module – Generate Certificate Revocation Lists (CRLs)

+
+

Note

+

This module is part of the community.crypto collection (version 2.10.0).

+

To install it, use: ansible-galaxy collection install community.crypto. +You need further requirements to be able to use this module, +see Requirements for details.

+

To use it in a playbook, specify: community.crypto.x509_crl.

+
+

New in community.crypto 1.0.0

+ +
+

Synopsis

+
    +
  • This module allows one to (re)generate or update Certificate Revocation Lists (CRLs).

  • +
  • Certificates on the revocation list can be either specified by serial number and (optionally) their issuer, or as a path to a certificate file in PEM format.

  • +
+
+
+

Requirements

+

The below requirements are needed on the host that executes this module.

+
    +
  • If name_encoding is set to another value than ignore, the idna Python library needs to be installed.

  • +
  • cryptography >= 1.2

  • +
+
+
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Parameter

Comments

+
+

attributes

+

aliases: attr

+

string

+

The attributes the resulting filesystem object should have.

+

To get supported flags look at the man page for chattr on the target system.

+

This string should contain the attributes in the same order as the one displayed by lsattr.

+

The = operator is assumed as default, otherwise + or - operators need to be included in the string.

+
+

backup

+

boolean

+

Create a backup file including a timestamp so you can get the original CRL back if you overwrote it with a new one by accident.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

digest

+

string

+

Digest algorithm to be used when signing the CRL.

+

Default: "sha256"

+
+

force

+

boolean

+

Should the CRL be forced to be regenerated.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

format

+

string

+

Whether the CRL file should be in PEM or DER format.

+

If an existing CRL file does match everything but format, it will be converted to the correct format instead of regenerated.

+

Choices:

+
    +
  • "pem" ← (default)

  • +
  • "der"

  • +
+
+

group

+

string

+

Name of the group that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current group of the current user unless you are root, in which case it can preserve the previous ownership.

+
+

ignore_timestamps

+

boolean

+

Whether the timestamps last_update, next_update and revocation_date (in revoked_certificates) should be ignored for idempotency checks. The timestamp invalidity_date in revoked_certificates will never be ignored.

+

Use this in combination with relative timestamps for these values to get idempotency.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

issuer

+

dictionary

+

Key/value pairs that will be present in the issuer name field of the CRL.

+

If you need to specify more than one value with the same key, use a list as value.

+

If the order of the components is important, use issuer_ordered.

+

One of issuer and issuer_ordered is required if state is present.

+

Mutually exclusive with issuer_ordered.

+
+

issuer_ordered

+

list / elements=dictionary

+

added in community.crypto 2.0.0

+

A list of dictionaries, where every dictionary must contain one key/value pair. This key/value pair will be present in the issuer name field of the CRL.

+

If you want to specify more than one value with the same key in a row, you can use a list as value.

+

One of issuer and issuer_ordered is required if state is present.

+

Mutually exclusive with issuer.

+
+

last_update

+

string

+

The point in time from which this CRL can be trusted.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

Note that if using relative time this module is NOT idempotent, except when ignore_timestamps is set to true.

+

Default: "+0s"

+
+

mode

+

string

+

Defines how to process entries of existing CRLs.

+

If set to generate, makes sure that the CRL has the exact set of revoked certificates as specified in revoked_certificates.

+

If set to update, makes sure that the CRL contains the revoked certificates from revoked_certificates, but can also contain other revoked certificates. If the CRL file already exists, all entries from the existing CRL will also be included in the new CRL. When using update, you might be interested in setting ignore_timestamps to true.

+

Choices:

+
    +
  • "generate" ← (default)

  • +
  • "update"

  • +
+
+

name_encoding

+

string

+

How to encode names (DNS names, URIs, email addresses) in return values.

+

ignore will use the encoding returned by the backend.

+

idna will convert all labels of domain names to IDNA encoding. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 encoding fails.

+

unicode will convert all labels of domain names to Unicode. IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 decoding fails.

+

Note that idna and unicode require the idna Python library to be installed.

+

Choices:

+
    +
  • "ignore" ← (default)

  • +
  • "idna"

  • +
  • "unicode"

  • +
+
+

next_update

+

string

+

The absolute latest point in time by which this issuer is expected to have issued another CRL. Many clients will treat a CRL as expired once next_update occurs.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

Note that if using relative time this module is NOT idempotent, except when ignore_timestamps is set to true.

+

Required if state is present.

+
+

owner

+

string

+

Name of the user that should own the filesystem object, as would be fed to chown.

+

When left unspecified, it uses the current user unless you are root, in which case it can preserve the previous ownership.

+
+

path

+

path / required

+

Remote absolute path where the generated CRL file should be created or is already located.

+
+

privatekey_content

+

string

+

The content of the CA’s private key to use when signing the CRL.

+

Either privatekey_path or privatekey_content must be specified if state is present, but not both.

+
+

privatekey_passphrase

+

string

+

The passphrase for the privatekey_path.

+

This is required if the private key is password protected.

+
+

privatekey_path

+

path

+

Path to the CA’s private key to use when signing the CRL.

+

Either privatekey_path or privatekey_content must be specified if state is present, but not both.

+
+

return_content

+

boolean

+

If set to true, will return the (current or generated) CRL’s content as crl.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

revoked_certificates

+

list / elements=dictionary

+

List of certificates to be revoked.

+

Required if state is present.

+
+

content

+

string

+

Content of a certificate in PEM format.

+

The serial number and issuer will be extracted from the certificate.

+

Mutually exclusive with path and serial_number. One of these three options must be specified.

+
+

invalidity_date

+

string

+

The point in time it was known/suspected that the private key was compromised or that the certificate otherwise became invalid.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

Note that if using relative time this module is NOT idempotent. This will NOT change when ignore_timestamps is set to true.

+
+

invalidity_date_critical

+

boolean

+

Whether the invalidity date extension should be critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

issuer

+

list / elements=string

+

The certificate’s issuer.

+

Example: DNS:ca.example.org

+
+

issuer_critical

+

boolean

+

Whether the certificate issuer extension should be critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

path

+

path

+

Path to a certificate in PEM format.

+

The serial number and issuer will be extracted from the certificate.

+

Mutually exclusive with content and serial_number. One of these three options must be specified.

+
+

reason

+

string

+

The value for the revocation reason extension.

+

Choices:

+
    +
  • "unspecified"

  • +
  • "key_compromise"

  • +
  • "ca_compromise"

  • +
  • "affiliation_changed"

  • +
  • "superseded"

  • +
  • "cessation_of_operation"

  • +
  • "certificate_hold"

  • +
  • "privilege_withdrawn"

  • +
  • "aa_compromise"

  • +
  • "remove_from_crl"

  • +
+
+

reason_critical

+

boolean

+

Whether the revocation reason extension should be critical.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+

revocation_date

+

string

+

The point in time the certificate was revoked.

+

Time can be specified either as relative time or as absolute timestamp.

+

Time will always be interpreted as UTC.

+

Valid format is [+-]timespec | ASN.1 TIME where timespec can be an integer + [w | d | h | m | s] (for example +32w1d2h).

+

Note that if using relative time this module is NOT idempotent, except when ignore_timestamps is set to true.

+

Default: "+0s"

+
+

serial_number

+

integer

+

Serial number of the certificate.

+

Mutually exclusive with path and content. One of these three options must be specified.

+
+

selevel

+

string

+

The level part of the SELinux filesystem object context.

+

This is the MLS/MCS attribute, sometimes known as the range.

+

When set to _default, it will use the level portion of the policy if available.

+
+

serole

+

string

+

The role part of the SELinux filesystem object context.

+

When set to _default, it will use the role portion of the policy if available.

+
+

setype

+

string

+

The type part of the SELinux filesystem object context.

+

When set to _default, it will use the type portion of the policy if available.

+
+

seuser

+

string

+

The user part of the SELinux filesystem object context.

+

By default it uses the system policy, where applicable.

+

When set to _default, it will use the user portion of the policy if available.

+
+

state

+

string

+

Whether the CRL file should exist or not, taking action if the state is different from what is stated.

+

Choices:

+
    +
  • "absent"

  • +
  • "present" ← (default)

  • +
+
+

unsafe_writes

+

boolean

+

Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object.

+

By default this module uses atomic operations to prevent data corruption or inconsistent reads from the target filesystem objects, but sometimes systems are configured or just broken in ways that prevent this. One example is docker mounted filesystem objects, which cannot be updated atomically from inside the container and can only be written in an unsafe manner.

+

This option allows Ansible to fall back to unsafe methods of updating filesystem objects when atomic operations fail (however, it doesn’t force Ansible to perform unsafe writes).

+

IMPORTANT! Unsafe writes are subject to race conditions and can lead to data corruption.

+

Choices:

+
    +
  • false ← (default)

  • +
  • true

  • +
+
+
+
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + +

Attribute

Support

Description

+

check_mode

+

Support: full

+

Can run in check_mode and return changed status prediction without modifying target.

+
+

diff_mode

+

Support: full

+

Will return details on what has changed (or possibly needs changing in check_mode), when in diff mode.

+
+

safe_file_operations

+

Support: full

+

Uses Ansible’s strict file operation functions to ensure proper permissions and avoid data corruption.

+
+
+
+

Notes

+
+

Note

+
    +
  • All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.

  • +
  • Date specified should be UTC. Minutes and seconds are mandatory.

  • +
+
+
+
+

Examples

+
- name: Generate a CRL
+  community.crypto.x509_crl:
+    path: /etc/ssl/my-ca.crl
+    privatekey_path: /etc/ssl/private/my-ca.pem
+    issuer:
+      CN: My CA
+    last_update: "+0s"
+    next_update: "+7d"
+    revoked_certificates:
+      - serial_number: 1234
+        revocation_date: 20190331202428Z
+        issuer:
+          CN: My CA
+      - serial_number: 2345
+        revocation_date: 20191013152910Z
+        reason: affiliation_changed
+        invalidity_date: 20191001000000Z
+      - path: /etc/ssl/crt/revoked-cert.pem
+        revocation_date: 20191010010203Z
+
+
+
+
+

Return Values

+

Common return values are documented here, the following are the fields unique to this module:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Key

Description

+

backup_file

+

string

+

Name of backup file created.

+

Returned: changed and if backup is true

+

Sample: "/path/to/my-ca.crl.2019-03-09@11:22~"

+
+

crl

+

string

+

The (current or generated) CRL’s content.

+

Will be the CRL itself if format is pem, and Base64 of the CRL if format is der.

+

Returned: if state is present and return_content is true

+
+

digest

+

string

+

The signature algorithm used to sign the CRL.

+

Returned: success

+

Sample: "sha256WithRSAEncryption"

+
+

filename

+

string

+

Path to the generated CRL.

+

Returned: changed or success

+

Sample: "/path/to/my-ca.crl"

+
+

format

+

string

+

Whether the CRL is in PEM format (pem) or in DER format (der).

+

Returned: success

+

Sample: "pem"

+
+

issuer

+

dictionary

+

The CRL’s issuer.

+

Note that for repeated values, only the last one will be returned.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: {"commonName": "ca.example.com", "organizationName": "Ansible"}

+
+

issuer_ordered

+

list / elements=list

+

The CRL’s issuer as an ordered list of tuples.

+

Returned: success

+

Sample: [["organizationName", "Ansible"], [{"commonName": "ca.example.com"}]]

+
+

last_update

+

string

+

The point in time from which this CRL can be trusted as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

next_update

+

string

+

The point in time from which a new CRL will be issued and the client has to check for it as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

privatekey

+

string

+

Path to the private CA key.

+

Returned: changed or success

+

Sample: "/path/to/my-ca.pem"

+
+

revoked_certificates

+

list / elements=dictionary

+

List of certificates to be revoked.

+

Returned: success

+
+

invalidity_date

+

string

+

The point in time it was known/suspected that the private key was compromised +or that the certificate otherwise became invalid as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

invalidity_date_critical

+

boolean

+

Whether the invalidity date extension is critical.

+

Returned: success

+

Sample: false

+
+

issuer

+

list / elements=string

+

The certificate’s issuer.

+

See name_encoding for how IDNs are handled.

+

Returned: success

+

Sample: ["DNS:ca.example.org"]

+
+

issuer_critical

+

boolean

+

Whether the certificate issuer extension is critical.

+

Returned: success

+

Sample: false

+
+

reason

+

string

+

The value for the revocation reason extension.

+

One of unspecified, key_compromise, ca_compromise, affiliation_changed, superseded, cessation_of_operation, certificate_hold, privilege_withdrawn, aa_compromise, and remove_from_crl.

+

Returned: success

+

Sample: "key_compromise"

+
+

reason_critical

+

boolean

+

Whether the revocation reason extension is critical.

+

Returned: success

+

Sample: false

+
+

revocation_date

+

string

+

The point in time the certificate was revoked as ASN.1 TIME.

+

Returned: success

+

Sample: "20190413202428Z"

+
+

serial_number

+

integer

+

Serial number of the certificate.

+

Returned: success

+

Sample: 1234

+
+
+

Authors

+
    +
  • Felix Fontein (@felixfontein)

  • +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+

© Copyright Community.Crypto Contributors.

+
+ + + + +
+
+
+
+
+ + + + \ No newline at end of file